6

When I create an image mosaic timeseries store through the geoserver web interface, a new table is created in my postgis database where the granule timeseries is indexed.

To accomplish this, the granules folder contains all the granules with names like:

nameYYYMMDD.tif

a database.properties file:

SPI=org.geotools.data.postgis.PostgisNGDataStoreFactory
host=localhost
port=5432
database=testing
schema=public
user=postgres
passwd=postgres
Loose\ bbox=true
Estimated\ extends=false
validate\ connections=true
Connection\ timeout=10
preparedStatements=true

an indexer.properties file:

TimeAttribute=ingestion
Schema=*the_geom:Polygon,location:String,ingestion:java.util.Date
PropertyCollectors=TimestampFileNameExtractorSPI[timeregex](ingestion)

and a timeregex.properties file:

regex=[0-9]{8}

If I zip up an exact copy of the granule folder used above and try to create the image mosaic layer through the rest api instead, the store and layer are created, but the granule indexing table isn't created in the postgis database. This makes it so that I can't edit the time dimension.

How do I get the rest api to create the postgis indexing table? Maybe there is some parameter I need to pass? I'm actually trying to do this through this gsconfig-py3 python wrapper. The call looks like this:

cat = Catalog("http://localhost:8080/geoserver/rest/",
              username="admin", password="geoserver")

st = cat.create_imagemosaic('store_name', 'D:\gridded\six_average_leaf_ncep.zip', workspace='workspace_name')
2

I believe the reason why it's not working is that you named the PostGIS config file database.properties instead of datastore.properties.

Below are 2 examples (1 using Python, 1 using cURL) on how to create an ImageMosaic using the Geoserver REST API and storing the index in a PostGIS table.

We will do it in 3 steps:

  1. Create the ImageMosaic with the necessary config files and an initial tif file
  2. Enable the time dimension (this is necessary as it's not done during step 1). We will set the presentation attribute to "LIST"
  3. Add a second granule (tif file)

Setup

In a zip file called "init.zip" we have the 3 required config files: datastore.properties, indexer.properties and timeregex.properties with the same content as yours and a tif file called "A20171130_calcite.tif".

For step 3, we have a zip file called "tiff.zip" which contains a tif file called "A20171201_calcite.tif".

We will add the ImageMosaic layer in the workspace "sf" and call it "test_immos".

I'm using Geoserver 2.11.2.

Examples

First, the Python example, using the requests module:

import requests
from requests.auth import HTTPBasicAuth


# Geoserver parameters
user = 'admin'
pwd = 'password'
gs_url = 'http://localhost:8080/geoserver/rest'
workspace = 'sf'

headers_zip = {'Content-Type': 'application/zip'}
headers_xml = {'Content-Type': 'application/xml; charset=UTF-8'}

# The name of the layer that we will create
layer = 'test_immos'

# 1) Create the layer
fileobj = open('init.zip', 'rb')

r = requests.put('{0}/workspaces/{1}/coveragestores/{2}/file.imagemosaic'\
     .format(gs_url, workspace, layer),
                 auth=HTTPBasicAuth(user, pwd),
                 files={"archive": ("init.zip", fileobj)},
                 headers=headers_zip
                 )

# 2) Enable the time dimension
data_xml = '<coverage>\
            <enabled>true</enabled>\
            <metadata><entry key="time">\
            <dimensionInfo>\
            <enabled>true</enabled>\
            <presentation>LIST</presentation>\
            <units>ISO8601</units><defaultValue/>\
            </dimensionInfo>\
            </entry></metadata>\
            </coverage>'

r = requests.put('{0}/workspaces/{1}/coveragestores/{2}/coverages/{2}'\
     .format(gs_url, workspace, layer),
                 auth=HTTPBasicAuth(user, pwd),
                 data=data_xml,
                 headers=headers_xml
                 )

# 3) Add a second granule

fileobj = open('tiff.zip', 'rb')

r = requests.post('{0}/workspaces/{1}/coveragestores/{2}/file.imagemosaic?recalculate= nativebbox,latlonbbox'\
     .format(gs_url, workspace, layer),
                 auth=HTTPBasicAuth(user, pwd),
                 files={"archive": ("tiff.zip", fileobj)},
                 headers=headers_zip
                 )

Now with cURL (commands and their output):

1) Create the layer:

$ curl -v -u 'admin:password' -XPUT -H "Content-type:application/zip" --data-binary @init.zip http://localhost:8080/geoserver/rest/workspaces/sf/coveragestores/test_immos/file.imagemosaic
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
* Server auth using Basic with user 'admin'
> PUT /geoserver/rest/workspaces/sf/coveragestores/test_immos/file.imagemosaic HTTP/1.1
> Host: localhost:8080
> Authorization: Basic YWRtaW46S20yM0A/OTk=
> User-Agent: curl/7.47.0
> Accept: */*
> Content-type:application/zip
> Content-Length: 852796
> Expect: 100-continue
> 
< HTTP/1.1 100 
* We are completely uploaded and fine
< HTTP/1.1 201 
< Date: Tue, 23 Jan 2018 20:07:35 GMT
< Server: Noelios-Restlet-Engine/1.0..8
< Content-Type: application/xml
< Transfer-Encoding: chunked
< 
<coverageStore>
  <name>test_immos</name>
  <type>ImageMosaic</type>
  <enabled>true</enabled>
  <workspace>
    <name>sf</name>
    <href>http://localhost:8080/geoserver/rest/workspaces/sf.xml</href>
  </workspace>
  <__default>false</__default>
  <url>file:data/sf/test_immos</url>
  <coverages>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/sf/coveragestores/test_immos/file/coverages.xml" type="application/xml"/>
  </coverages>
* Connection #0 to host localhost left intact

2) Enable the time dimension:

$ curl -v -u 'admin:password' -XPUT -H "Content-type:application/xml; charset=UTF-8" -d '<coverage><enabled>true</enabled><metadata><entry key="time"><dimensionInfo><enabled>true</enabled><presentation>LIST</presentation><units>ISO8601</units><defaultValue/></dimensionInfo></entry></metadata></coverage>' http://localhost:8080/geoserver/rest/workspaces/sf/coveragestores/test_immos/coverages/test_immos
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
* Server auth using Basic with user 'admin'
> PUT /geoserver/rest/workspaces/sf/coveragestores/test_immos/coverages/test_immos HTTP/1.1
> Host: localhost:8080
> Authorization: Basic YWRtaW46S20yM0A/OTk=
> User-Agent: curl/7.47.0
> Accept: */*
> Content-type:application/xml; charset=UTF-8
> Content-Length: 215
> e
* upload completely sent off: 215 out of 215 bytes
< HTTP/1.1 200 
< Date: Tue, 23 Jan 2018 20:14:39 GMT
< Server: Noelios-Restlet-Engine/1.0..8
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact

3) Add a second granule:

$ curl -v -u 'admin:password' -XPOST -H "Content-type: application/zip" --data-binary @tiff.zip http://localhost:8080/geoserver/rest/workspaces/sf/coveragestores/test_immos/file.imagemosaic?recalculate=nativebbox,latlonbbox
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
* Server auth using Basic with user 'admin'
> POST /geoserver/rest/workspaces/sf/coveragestores/test_immos/file.imagemosaic?recalculate=nativebbox,latlonbbox HTTP/1.1
> Host: localhost:8080
> Authorization: Basic YWRtaW46S20yM0A/OTk=
> User-Agent: curl/7.47.0
> Accept: */*
> Content-type: application/zip
> Content-Length: 853272
> Expect: 100-continue
> 
< HTTP/1.1 100 
* We are completely uploaded and fine
< HTTP/1.1 202 
< Date: Tue, 23 Jan 2018 20:20:17 GMT
< Server: Noelios-Restlet-Engine/1.0..8
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact

At the end of those 3 steps our index table "test_immos" in our PostGIS database looks like this:

postgis table

I have '04:00:00' in the timestamp as I'm at UTC+4.

A good way to check if everything is OK is to consult the GetCapabilities of our workspace. In our case:

http://localhost:8080/geoserver/sf/wms?service=wms&version=1.3.0&request=GetCapabilities

Looking for our layer "test_immos" we can see that the 2 granules (2017-11-30 and 2017-12-01) are indeed available:

GetCapabilities

It's important to note that in our case, as we have daily granules (so our time dimension only contains dates and not dates and times) we could have used a shapefile as the index instead of a PostGIS table. But in the case of hourly granules, we can't use a shapefile as the DBF format doesn't support timestamp (source).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.