Beispiel #1
0
 def geoserver_upload(self, input_file):
     print "upload", input_file
     path, file_ext = os.path.split(input_file)
     f = os.path.splitext(file_ext)[0]
     cat = Catalog(self.GEOSERVER_HOST, self.GEOSERVER_USER, self.GEOSERVER_PASSWORD)
     try:
         cat.create_coveragestore(name=f, data=input_file, workspace=cat.get_workspace(self.GEOSERVER_WORKSPACE),
                                  overwrite=True)
     except UploadError:
         print "map already exist"
         cat.delete(cat.get_layer(f))
         cat.delete(cat.get_resources(f, self.GEOSERVER_WORKSPACE)[0])
         cat.create_coveragestore(name=f, data=input_file, workspace=cat.get_workspace(self.GEOSERVER_WORKSPACE),
                                  overwrite=True)
            def wrapper(self, *args, **kwargs):
                workspace_name = 'geonode'
                django_datastore = db.connections['datastore']

                catalog = Catalog(
                    ogc_server_settings.internal_rest,
                    *ogc_server_settings.credentials
                )
                # Set up workspace/datastore as appropriate
                ws = catalog.get_workspace(workspace_name)
                delete_ws = False
                if ws is None:
                    ws = catalog.create_workspace(workspace_name, 'http://www.geonode.org/')
                    delete_ws = True

                datastore = create_datastore(workspace_name, django_datastore, catalog)

                # test method called here
                try:
                    ret = wrapped_func(self, *args, **kwargs)
                finally:
                    # Tear down workspace/datastore as appropriate
                    if delete_ws:
                        catalog.delete(ws, recurse=True)
                    else:
                        catalog.delete(datastore, recurse=True)

                return ret
Beispiel #3
0
def upload_impact_vector(impact_file_path):
    data = dict()
    try:
        cat = Catalog(GEOSERVER_REST_URL, GS_USERNAME, GS_PASSWORD)
        ws = cat.get_workspace(GS_IMPACT_WS)

        base = str(os.path.splitext(impact_file_path)[0])
        name = str(os.path.splitext(os.path.basename(base))[0])

        shx = base + '.shx'
        dbf = base + '.dbf'
        prj = base + '.prj'
        data = { 
                 'shp' : impact_file_path,
                 'shx' : shx,
                 'dbf' : dbf,
                 'prj' : prj
               }

        cat.create_featurestore(name, data, ws, True)

        data = {'return': 'success', 'resource' : name }
    except:
        return {'return': 'fail'}
    else:
        return data
Beispiel #4
0
def remove_service(request, service_id):
    """
    Delete a service, and its constituent layers.
    """
    service_obj = get_object_or_404(Service, pk=service_id)

    if not request.user.has_perm("maps.delete_service", obj=service_obj):
        return HttpResponse(
            loader.render_to_string(
                "401.html",
                RequestContext(request, {"error_message": _("You are not permitted to remove this service.")}),
            ),
            status=401,
        )

    if request.method == "GET":
        return render_to_response("services/service_remove.html", RequestContext(request, {"service": service_obj}))
    elif request.method == "POST":
        # Retrieve this service's workspace from the GeoServer catalog.
        cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password)
        workspace = cat.get_workspace(service_obj.name)

        # Delete nested workspace structure from GeoServer for this service.
        if workspace:
            for store in cat.get_stores(workspace):
                for resource in cat.get_resources(store):
                    for layer in cat.get_layers(resource):
                        cat.delete(layer)
                    cat.delete(resource)
                cat.delete(store)
            cat.delete(workspace)

        # Delete service from GeoNode.
        service_obj.delete()
        return HttpResponseRedirect(reverse("services"))
class UploaderTests(MapStoryTestMixin):

    """
    Basic checks to make sure pages load, etc.
    """

    def create_datastore(self, connection, catalog):
        settings = connection.settings_dict
        params = {'database': settings['NAME'],
                  'passwd': settings['PASSWORD'],
                  'namespace': 'http://www.geonode.org/',
                  'type': 'PostGIS',
                  'dbtype': 'postgis',
                  'host': settings['HOST'],
                  'user': settings['USER'],
                  'port': settings['PORT'],
                  'enabled': "True"}

        store = catalog.create_datastore(
            settings['NAME'],
            workspace=self.workspace)
        store.connection_parameters.update(params)

        try:
            catalog.save(store)
        except FailedRequestError:
            # assuming this is because it already exists
            pass

        return catalog.get_store(settings['NAME'])

    def setUp(self):

        if not os.path.exists(os.path.join(os.path.split(__file__)[0], '..', 'importer-test-files')):
            self.skipTest('Skipping test due to missing test data.')

        # These tests require geonode to be running on :80!
        self.postgis = db.connections['datastore']
        self.postgis_settings = self.postgis.settings_dict

        self.username, self.password = self.create_user(
            'admin', 'admin', is_superuser=True)
        self.non_admin_username, self.non_admin_password = self.create_user(
            'non_admin', 'non_admin')
        self.cat = Catalog(
            ogc_server_settings.internal_rest,
            *ogc_server_settings.credentials)
        if self.cat.get_workspace('geonode') is None:
            self.cat.create_workspace('geonode', 'http://geonode.org')
        self.workspace = 'geonode'
        self.datastore = self.create_datastore(self.postgis, self.cat)

    def tearDown(self):
        """
        Clean up geoserver.
        """
        self.cat.delete(self.datastore, recurse=True)
Beispiel #6
0
def add_layer(shp):
  global ds_name, ws_name, appserver
  global instance
  cat = Catalog(appserver + '/rest')
  ws = cat.get_workspace(ws_name)
  ds = cat.get_store(ds_name, ws_name)
  print 'starting {0}...'.format(shp)
  components =  dict((ext, shp + '.' + ext) for ext in ['shp', 'prj', 'shx', 'dbf'])
  cat.add_data_to_store(ds, shp, components, ws, True)
  print '{0} finished ...'.format(shp)
def raster_to_geoserver(geoserver_url, raster, workspace):
    cat = Catalog(geoserver_url, username, password)
    create_workspace(geoserver_url, username, password, workspace)
    file_name = os.path.splitext(os.path.basename(raster))[0]
    workspace = cat.get_workspace(workspace)
    if not file_name in [l.name for l in cat.get_layers()]:
        print 'Creating new layer: %s' %file_name
        cat.create_coveragestore(file_name, raster, workspace)
    else:
        print 'Layer %s already exists' %file_name
Beispiel #8
0
    def geoserver_upload_shape(self, input_file):
        print "upload", input_file

        path, file_ext = os.path.split(input_file)

        cat = Catalog(self.GEOSERVER_HOST, self.GEOSERVER_USER, self.GEOSERVER_PASSWORD)
        shapeFile = shapefile_and_friends(input_file)
        print shapeFile
        cat.create_featurestore(name=file_ext, data=shapeFile, workspace=cat.get_workspace(self.GEOSERVER_WORKSPACE),
                                overwrite=True, charset=None)
def shp_to_geoserver(geoserver_url, shapefile, workspace):
    cat = Catalog(geoserver_url, username, password)
    create_workspace(geoserver_url, username, password, workspace)
    shapefile_plus_sidecars = geoserver.util.shapefile_and_friends(shapefile)
    file_name = os.path.splitext(os.path.basename(shapefile))[0]
    workspace = cat.get_workspace(workspace)
    if not file_name in [l.name for l in cat.get_layers()]:
        print 'Creating new layer: %s' %file_name
        cat.create_featurestore(file_name, shapefile_plus_sidecars, workspace)
    else:
        print 'Layer %s already exists' %file_name
Beispiel #10
0
def upload_raster(impact_file_path):
    data = dict()
    try:
        cat = Catalog(GEOSERVER_REST_URL, GS_USERNAME, GS_PASSWORD)
        ws = cat.get_workspace(GS_IMPACT_WS)

        base = str(os.path.splitext(impact_file_path)[0])
        name = str(os.path.splitext(os.path.basename(base))[0])

        cat.create_coveragestore(name, impact_file_path, ws, True)
    except:
        raise
Beispiel #11
0
def get_geoserver_cascading_workspace(create=True):
    """Return the geoserver workspace used for cascaded services

    The workspace can be created it if needed.

    """

    catalog = Catalog(
        service_url=settings.OGC_SERVER["default"]["LOCATION"] + "rest",
        username=settings.OGC_SERVER["default"]["USER"],
        password=settings.OGC_SERVER["default"]["PASSWORD"]
    )
    name = getattr(settings, "CASCADE_WORKSPACE", "cascaded-services")
    workspace = catalog.get_workspace(name)
    if workspace is None and create:
        uri = "http://www.geonode.org/{}".format(name)
        workspace = catalog.create_workspace(name, uri)
    return workspace
    def uploadGS(self):
        shpFile = os.path.join(self.tempFolder, 'diff_simplify')

        cat = Catalog("http://localhost:8080/geoserver/rest", username="******", password="******")
        gsWorkspace = cat.get_workspace("SJ")
        shapefileData = geoserver.util.shapefile_and_friends(shpFile)

        # TODO: 레이어명 구분이 필요
        layerName = self.resId
        # layerName = time.strftime("%Y%m%d_%H%M%S")
        cat.create_featurestore(layerName, shapefileData, gsWorkspace)

        cat.reload()

        layer = cat.get_layer(layerName)
        diffStyle = cat.get_style('SJ:diff_style')

        if diffStyle is not None:
            layer._set_default_style('SJ:diff_style')
            cat.save(layer)
Beispiel #13
0
    def updateGs(self):
        gs = settings.GEOSERVER
        cat = Catalog(gs['host'], gs['user'], gs['password'])
        ws = cat.get_workspace(gs['workspace'])
        epsg = 'EPSG:404000'

        for kuva in self.all():
            image = kuva.jpgImage
            path = os.path.join(settings.MEDIA_ROOT, image.name)

            layerName = kuva.gsName()

            kuva.createWld()
            cs = cat.create_coveragestore2(layerName, workspace=ws)
            cs.url = 'file://' + path
            cs.type = 'WorldImage'
            cat.save(cs)

            coverage = cat.publish_coverage(layerName, cs, epsg)
            cat.addToGwc(coverage, 'kuva404000')
Beispiel #14
0
def main(args):

    # print args
    data_path = args.path or DATA_PATH
    geo_server = args.geoserver or GEOSERVER
    mosaic_name = args.mosaic or MOSAIC_NAME
    new_layer = args.layer  # eg. '20091201.tif' or '20091201.zip'
    store_name = args.store or STORE
    workspace_name = args.workspace or WORKSPACE
    username = args.user or USERNAME
    password = args.password or PASSWORD

    # access geoserver
    # TODO - in production usage, find another way to access username & password
    try:
        gs_catalog = Catalog("%s/geoserver/rest" % geo_server,
                             username=username, password=password) 
        ws = gs_catalog.get_workspace(workspace_name)
        if not ws:
            logger.error('Unable to access workspace: "%s"' % workspace_name)
            return
    except FailedRequestError, e:
        logger.error('Unable to access GeoServer.', exc_info=True)
        return
Beispiel #15
0
        ts.save()
        logger.info("[x] File:--%r-- has been successfully imported", src)
    except Exception, e:
        logger.error("[x] File:--%r-- failed to be imported", src)
        data_move(src, ERROR_file)
        raise Exception(
            "[x] %r _FAILED to be imported" % src + ' reason--%r' % e)

    try:
        logger.debug("[x] Publishing %r to GeoServer", src)
        cat = Catalog(
            gs_setting['geoserver_url'] + '/rest',
            gs_setting['geoserver_username'],
            gs_setting['geoserver_password'], True)

        workspace = cat.get_workspace(gs_setting['geoserver_workspace'])
        if workspace is None:
            cat.create_workspace(
                gs_setting['geoserver_workspace'],
                gs_setting['geoserver_workspace'])

        str_time = "{:02d}:{:02d}:{:02d}".format(
            timestamp.hour[0].item(),
            timestamp.minute[0].item(),
            timestamp.second[0].item()
        )

        store_name = "{uuid}_{date}T{time}Z".format(
            uuid=ts.uuid,
            date=str_date,
            time=str_time,
Beispiel #16
0
class CatalogTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD'])
        self.gs_version = self.cat.get_short_version()

    def testGSVersion(self):
        version = self.cat.get_version()
        pat = re.compile('\d\.\d+')
        self.assertTrue(pat.match('2.2.x'))
        self.assertTrue(pat.match('2.3.2'))
        self.assertTrue(pat.match('2.3-SNAPSHOT'))
        self.assertTrue(pat.match(version))

    def testWorkspaces(self):
        self.assertEqual(7, len(self.cat.get_workspaces()))
        # marking out test since geoserver default workspace is not consistent
        # self.assertEqual("cite", self.cat.get_default_workspace().name)
        self.assertEqual("topp", self.cat.get_workspaces(names="topp")[-1].name)
        self.assertEqual(2, len(self.cat.get_workspaces(names=['topp', 'sde'])))
        self.assertEqual(2, len(self.cat.get_workspaces(names='topp, sde')))
        self.assertEqual("topp", self.cat.get_workspace("topp").name)
        self.assertIsNone(self.cat.get_workspace("blahblah-"))

    def testStores(self):
        self.assertEqual(0, len(self.cat.get_stores(names="nonexistentstore")))
        topp = self.cat.get_workspaces("topp")[0]
        sf = self.cat.get_workspaces("sf")[0]
        self.assertEqual(9, len(self.cat.get_stores()))
        self.assertEqual(2, len(self.cat.get_stores(workspaces=topp)))
        self.assertEqual(2, len(self.cat.get_stores(workspaces=sf)))
        self.assertEqual(2, len(self.cat.get_stores(workspaces='sf')))
        self.assertEqual(2, len(self.cat.get_stores(names='states_shapefile, sfdem')))
        self.assertEqual(2, len(self.cat.get_stores(names=['states_shapefile', 'sfdem'])))
        self.assertEqual("states_shapefile", self.cat.get_stores(names="states_shapefile", workspaces=topp.name)[0].name)
        self.assertEqual("states_shapefile", self.cat.get_stores(names="states_shapefile")[0].name)
        self.assertEqual("sfdem", self.cat.get_stores(names="sfdem", workspaces=sf.name)[0].name)
        self.assertEqual("sfdem", self.cat.get_stores(names="sfdem")[0].name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem").name)
        self.assertIsNone(self.cat.get_store("blah+blah-"))

    def testResources(self):
        topp = self.cat.get_workspaces("topp")[0]
        sf = self.cat.get_workspaces("sf")[0]
        states = self.cat.get_stores(names="states_shapefile", workspaces=topp.name)[0]
        sfdem = self.cat.get_stores(names="sfdem", workspaces=sf.name)[0]
        self.assertEqual(19, len(self.cat.get_resources()))
        self.assertEqual(2, len(self.cat.get_resources(stores=[states.name, sfdem.name])))
        self.assertEqual(11, len(self.cat.get_resources(workspaces=[topp.name, sf.name])))

        self.assertEqual("states", self.cat.get_resources(names="states", stores=states.name)[0].name)
        self.assertEqual("states", self.cat.get_resources(names="states", workspaces=topp.name)[0].name)
        self.assertEqual("states", self.cat.get_resources(names="states")[0].name)
        self.assertEqual("states", self.cat.get_resource("states").name)
        self.assertIsNone(self.cat.get_resource("blah+1blah-2"))

        states = self.cat.get_resources(names="states")[0]

        fields = [
            states.title,
            states.abstract,
            states.native_bbox,
            states.latlon_bbox,
            states.projection,
            states.projection_policy
        ]

        self.assertFalse(None in fields, str(fields))
        self.assertFalse(len(states.keywords) == 0)
        self.assertFalse(len(states.attributes) == 0)
        self.assertTrue(states.enabled)

        self.assertEqual("sfdem", self.cat.get_resources(names="sfdem", stores=sfdem.name)[0].name)
        self.assertEqual("sfdem", self.cat.get_resources(names="sfdem", workspaces=sf.name)[0].name)
        self.assertEqual("sfdem", self.cat.get_resources(names="sfdem")[0].name)

    def testResourcesUpdate(self):
        res_dest = self.cat.get_resources()
        count = 0

        for rd in res_dest:
            # only wms layers
            if rd.resource_type != "wmsLayer":
                continue
            # looking for same name
            ro = self.cat.get_resources(names=rd.name)

            if ro is not None:
                rd.title = ro.title
                rd.abstract = ro.abstract
                rd.keywords = ro.keywords
                rd.projection = ro.projection
                rd.native_bbox = ro.native_bbox
                rd.latlon_bbox = ro.latlon_bbox
                rd.projection_policy = ro.projection_policy
                rd.enabled = ro.enabled
                rd.advertised = ro.advertised
                rd.metadata_links = ro.metadata_links or None

                self.cat.save(rd)
                self.cat.reload()
                count += 1

    def testLayers(self):
        if self.gs_version >= "2.13":
            expected = set([
                'sf:roads',
                'sf:sfdem',
                'nurc:mosaic',
                'tiger:giant_polygon',
                'sf:bugsites',
                'topp:states',
                'sf:streams',
                'tiger:poly_landmarks',
                'tiger:poi',
                'topp:tasmania_water_bodies',
                'tiger:tiger_roads',
                'topp:tasmania_roads',
                'nurc:Pk50095',
                'topp:tasmania_cities',
                'nurc:Img_Sample',
                'sf:restricted',
                'nurc:Arc_Sample',
                'sf:archsites',
                'topp:tasmania_state_boundaries'
            ])
        else:
            expected = set([
                "Arc_Sample",
                "Pk50095",
                "Img_Sample",
                "mosaic",
                "sfdem",
                "bugsites",
                "restricted",
                "streams",
                "archsites",
                "roads",
                "tasmania_roads",
                "tasmania_water_bodies",
                "tasmania_state_boundaries",
                "tasmania_cities",
                "states",
                "poly_landmarks",
                "tiger_roads",
                "poi",
                "giant_polygon"
            ])

        actual = set(l.name for l in self.cat.get_layers())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        states = self.cat.get_layer("states")

        self.assert_("states", states.name)
        self.assert_(isinstance(states.resource, ResourceInfo))
        self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon']))
        self.assertEqual(states.default_style.name, "population")

    def testLayerGroups(self):
        expected = set(["tasmania", "tiger-ny", "spearfish"])
        actual = set(l.name for l in self.cat.get_layergroups(names=["tasmania", "tiger-ny", "spearfish"]))
        missing = expected - actual
        extras = actual - expected
        message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        tas = self.cat.get_layergroups(names="tasmania")[0]

        self.assert_("tasmania", tas.name)
        self.assert_(isinstance(tas, LayerGroup))
        if self.gs_version >= "2.13":
            self.assertEqual(tas.layers, [
                'topp:tasmania_state_boundaries',
                'topp:tasmania_water_bodies',
                'topp:tasmania_roads',
                'topp:tasmania_cities'
            ], tas.layers)
        else:
            self.assertEqual(tas.layers, [
                'tasmania_state_boundaries',
                'tasmania_water_bodies',
                'tasmania_roads',
                'tasmania_cities'
            ], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        # Try to create a new Layer Group into the "topp" workspace
        self.assert_(self.cat.get_workspaces("topp")[0] is not None)
        tas2 = self.cat.create_layergroup("tasmania_reloaded", tas.layers, workspace = "topp")
        self.cat.save(tas2)
        self.assertEqual(1, len(self.cat.get_layergroups(names='tasmania_reloaded', workspaces="topp")))
        tas2 = self.cat.get_layergroups(names='tasmania_reloaded', workspaces="topp")[0]
        self.assert_("tasmania_reloaded", tas2.name)
        self.assert_(isinstance(tas2, LayerGroup))
        self.assertEqual(tas2.workspace, "topp", tas2.workspace)
        if self.gs_version >= "2.13":
            self.assertEqual(tas2.layers, [
                'topp:tasmania_state_boundaries',
                'topp:tasmania_water_bodies',
                'topp:tasmania_roads',
                'topp:tasmania_cities'
            ], tas2.layers)
        else:
            self.assertEqual(tas2.layers, [
                'tasmania_state_boundaries',
                'tasmania_water_bodies',
                'tasmania_roads',
                'tasmania_cities'
            ], tas2.layers)
        self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles)

    def testStyles(self):
        self.assertEqual("population", self.cat.get_styles("population")[0].name)
        self.assertEqual("popshade.sld", self.cat.get_styles("population")[0].filename)
        self.assertEqual("population", self.cat.get_styles("population")[0].sld_name)
        self.assertEqual("population", self.cat.get_style("population").sld_name)
        self.assertIsNone(self.cat.get_style("blah+#5blah-"))
        self.assertEqual(0, len(self.cat.get_styles('non-existing-style')))

    def testEscaping(self):
        # GSConfig is inconsistent about using exceptions vs. returning None
        # when a resource isn't found.
        # But the basic idea is that none of them should throw HTTP errors from
        # misconstructed URLS
        self.cat.get_styles("best style ever")
        self.cat.get_workspaces("best workspace ever")
        self.assertEqual(0, len(self.cat.get_stores(workspaces="best workspace ever", names="best store ever")))
        self.cat.get_layer("best layer ever")
        self.cat.get_layergroups("best layergroup ever")

    def testUnicodeUrl(self):
        """
        Tests that the geoserver.support.url function support unicode strings.
        """

        # Test the url function with unicode
        seg = ['workspaces', 'test', 'datastores', u'operaci\xf3n_repo', 'featuretypes.xml']
        u = build_url(base=self.cat.service_url, seg=seg)
        self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/operaci%C3%B3n_repo/featuretypes.xml")

        # Test the url function with normal string
        seg = ['workspaces', 'test', 'datastores', 'test-repo', 'featuretypes.xml']
        u = build_url(base=self.cat.service_url, seg=seg)
        self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/test-repo/featuretypes.xml")
class GeoserverHelper:
    def __init__(self,
                 geoserverUrl="",
                 geoserverUserName="",
                 geoserverPW="",
                 geoserverWorkSpace="",
                 postgreIP="",
                 postgreUserName="",
                 postgrePW=""):
        """use the constructor given arguments if used"""
        self.geoserverUrl = geoserverUrl if geoserverUrl != "" else GEOSERVERURL
        self.geoserverUserName = geoserverUserName if geoserverUserName != "" else GEOSERVERUSERNAME
        self.geoserverPW = geoserverPW if geoserverPW != "" else GEOSERVERPW
        self.geoserverWorkSpace = geoserverWorkSpace if geoserverWorkSpace != "" else "crc"
        self.postgreIP = postgreIP if postgreIP != "" else POSTGREIP
        self.postgreUserName = postgreUserName if postgreUserName != "" else POSTGREUSERNAME
        self.postgrePW = postgrePW if postgrePW != "" else POSTGREPW

        if self.geoserverUrl[-1] != '/':
            raise Exception("GeoserverUrl must end with a slash ('/')")

        self.catalog = Catalog(self.geoserverUrl + "rest/")
        self.catalog.http.add_credentials(self.geoserverUserName,
                                          self.geoserverPW)
        try:
            workspaces = self.catalog.get_workspaces()
        except:
            e = sys.exc_info()[0]
            print e
        self.cWorkSpace = self.catalog.get_workspace(self.geoserverWorkSpace)

    def getLayers(self):
        return self.cWorkSpace.catalog.get_layers()

    def insertShapeIntoPostGis(self,
                               shapeFile,
                               databaseName,
                               tableName,
                               encoding=3857):
        '''returns the returnCode of the execution of the insert script, e.g:
        helper.insertShapeIntoPostGis('/home/c815/gsTest/test.shp','crc','testingHelper2')'''

        if not os.path.isfile(shapeFile):
            print "Shape file not found"
            return -1
            cmds = "PGPASSWORD={pgPW} ./createWSFTFromSHP.sh -s {shapeFileF} -d {databaseNameF} -t {tableNameF} -u {postgreUsername} -i {postgreIP}".format(
                pgPW=self.postgrePW,
                shapeFileF=shapeFile,
                databaseNameF=databaseName,
                tableNameF=tableName,
                postgreUsername=self.postgreUserName,
                postgreIP=self.postgreIP)
            return subprocess.call(cmds, shell=True)

    def uploadShapeFile(self, shapeFile, storeName):
        shpPlusSidcars = geoserver.util.shapefile_and_friends(shapeFile[:-3])
        shpPlusSidcars
        self.ft = self.catalog.create_featurestore(storeName, shpPlusSidcars,
                                                   self.cWorkSpace)

    def getStyles(self):
        return self.catalog.get_styles()

    def uploadStyleFile(self, sldFile, styleName, overWrite, workSpace=None):
        f = open(sldFile, 'r')
        styleSrc = f.read()
        uploadStyle(styleSrc, styleName, overWrite, workSpace)
        f.close()

    def uploadStyle(self, sldSrc, styleName, overWrite, workSpace=None):
        self.catalog.create_style(styleName, sldSrc, overWrite, workSpace)

    def publishPostGISLayer(self,
                            postGISLayerName,
                            storeName,
                            crs='EPSG:3857'):
        '''cat.publish_featuretype('testingstuff',crcStore,native_crs='EPSG:3857')'''

        store = self.catalog.get_store(storeName)
        if store != None:
            self.catalog.publish_featuretype(postGISLayerName, store, crs)

    def setDefaultStyleForLayer(self, layerName, styleName):
        l = self.catalog.get_layer(layerName)

        sNames = [i.name for i in self.getStyles()]
        if styleName not in sNames:
            split = styleName.split(':')
            if len(split) == 2:
                workSpace = styleName.split(':')[0]
                newStyleName = styleName.split(':')[1]
            else:
                return -1
            style = self.catalog.get_style(newStyleName, workSpace)
            if style is None:
                return -1
            if l != None:
                l._set_default_style(styleName)
                self.catalog.save(l)
                return 0

    def createPostGISDataStore(self,
                               storeName,
                               postGisPassword,
                               postGisUser,
                               postGisHost,
                               postGisDatabase,
                               workSpace=None):

        #check if connection parameter are valid
        try:
            conn = psycopg2.connect(
                "dbname='{dbName}' user='******' host='{Host}' password='******'"
                .format(dbName=postGisDatabase,
                        dbUser=postGisUser,
                        Host=postGisHost,
                        password=postGisPassword))
        except:
            return False

        w = self.catalog.create_datastore(storeName, workSpace)
        template = Template(
            """{'validate connections': 'true', 'port': '5432', 
        'Support on the fly geometry simplification': 'true', 
        'create database': 'false', 'dbtype': 'postgis', 
        'Connection timeout': '20', 'namespace': 'http://www.crcproject.com', 
        'Max connection idle time': '300', 'Expose primary keys': 'false', 
        'min connections': '1', 'Max open prepared statements':'50', 
        'passwd': '$passwd', 
        'encode functions': 'false', 
        'max connections': '10', 'Evictor tests per run': '3', 'Loose bbox': 'true', 
        'Evictor run periodicity': '300', 'Estimated extends': 'true', 
        'database': '$database', 
        'fetch size': '1000', 'Test while idle': 'true', 
        'host': '$host', 
        'preparedStatements': 'false', 'schema': 'public', 
        'user': '******'}""")
        dic = ast.literal_eval(
            template.substitute(passwd=postGisPassword,
                                user=postGisUser,
                                host=postGisHost,
                                database=postGisDatabase))
        #'passwd': 'crypt1:Bsaz2AUI8T+6Pj43krA7kg==',
        #'user': '******'}
        #'database': 'crc',
        #'host': 'localhost',
        w.connection_parameters = dic
        self.catalog.save(w)
        return True
Beispiel #18
0
def _register_cascaded_layers(service, owner=None):
    """
    Register layers for a cascading WMS
    """
    if service.type == 'WMS' or service.type == "OWS":
        cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest",
                      _user, _password)
        # Can we always assume that it is geonode?
        # Should cascading layers have a separate workspace?
        cascade_ws = cat.get_workspace(service.name)
        if cascade_ws is None:
            cascade_ws = cat.create_workspace(service.name, 'cascade')
        try:
            store = cat.get_store(service.name, cascade_ws)
        except Exception:
            store = cat.create_wmsstore(service.name, cascade_ws)
            cat.save(store)
        wms = WebMapService(service.base_url)
        layers = list(wms.contents)

        count = 0
        for layer in layers:
            lyr = cat.get_resource(layer, store, cascade_ws)
            if lyr is None:
                if service.type in ["WMS", "OWS"]:
                    resource = cat.create_wmslayer(cascade_ws, store, layer)
                elif service.type == "WFS":
                    resource = cat.create_wfslayer(cascade_ws, store, layer)

                if resource:
                    bbox = resource.latlon_bbox
                    cascaded_layer, created = Layer.objects.get_or_create(
                        typename="%s:%s" % (cascade_ws.name, resource.name),
                        service=service,
                        defaults={
                            "name": resource.name,
                            "workspace": cascade_ws.name,
                            "store": store.name,
                            "storeType": store.resource_type,
                            "title": resource.title or 'No title provided',
                            "abstract": resource.abstract or 'No abstract provided',
                            "owner": None,
                            "uuid": str(uuid.uuid4()),
                            "bbox_x0": bbox[0],
                            "bbox_x1": bbox[1],
                            "bbox_y0": bbox[2],
                            "bbox_y1": bbox[3],
                        })

                    if created:
                        cascaded_layer.save()
                        if cascaded_layer is not None and cascaded_layer.bbox is None:
                            cascaded_layer._populate_from_gs(
                                gs_resource=resource)
                        cascaded_layer.set_default_permissions()

                        service_layer, created = ServiceLayer.objects.get_or_create(
                            service=service,
                            typename=cascaded_layer.name
                        )
                        service_layer.layer = cascaded_layer
                        service_layer.title = cascaded_layer.title,
                        service_layer.description = cascaded_layer.abstract,
                        service_layer.styles = cascaded_layer.styles
                        service_layer.save()

                        count += 1
                    else:
                        logger.error(
                            "Resource %s from store %s could not be saved as layer" % (layer, store.name))
        message = "%d Layers Registered" % count
        return_dict = {'status': 'ok', 'msg': message}
        return HttpResponse(json.dumps(return_dict),
                            mimetype='application/json',
                            status=200)
    elif service.type == 'WCS':
        return HttpResponse('Not Implemented (Yet)', status=501)
    else:
        return HttpResponse('Invalid Service Type', status=400)
Beispiel #19
0
def gs_slurp(ignore_errors=True,
             verbosity=1,
             console=None,
             owner=None,
             workspace=None,
             store=None,
             filter=None,
             skip_unadvertised=False,
             remove_deleted=False):
    """Configure the layers available in GeoServer in GeoNode.

       It returns a list of dictionaries with the name of the layer,
       the result of the operation and the errors and traceback if it failed.
    """

    # avoid circular import problem
    from geonode.layers.models import set_attributes

    if console is None:
        console = open(os.devnull, 'w')

    if verbosity > 1:
        print >> console, "Inspecting the available layers in GeoServer ..."
    cat = Catalog(ogc_server_settings.internal_rest, _user, _password)
    if workspace is not None:
        workspace = cat.get_workspace(workspace)
        if workspace is None:
            resources = []
        else:
            resources = cat.get_resources(workspace=workspace)
    elif store is not None:
        store = cat.get_store(store)
        resources = cat.get_resources(store=store)
    else:
        resources = cat.get_resources(workspace=workspace)
    if remove_deleted:
        resources_for_delete_compare = resources[:]
        workspace_for_delete_compare = workspace
        # filter out layers for delete comparison with GeoNode layers by following criteria:
        # enabled = true, if --skip-unadvertised: advertised = true, but disregard the filter parameter in the case of deleting layers
        resources_for_delete_compare = [
            k for k in resources_for_delete_compare if k.enabled == "true"
        ]
        if skip_unadvertised:
            resources_for_delete_compare = [
                k for k in resources_for_delete_compare
                if k.advertised == "true" or k.advertised == True
                or k.advertised is None
            ]
    if filter:
        resources = [k for k in resources if filter in k.name]

    # filter out layers depending on enabled, advertised status:
    resources = [k for k in resources if k.enabled == "true"]
    if skip_unadvertised:
        resources = [
            k for k in resources if k.advertised == "true"
            or k.advertised == True or k.advertised is None
        ]

    # TODO: Should we do something with these?
    # i.e. look for matching layers in GeoNode and also disable?
    disabled_resources = [k for k in resources if k.enabled == "false"]

    number = len(resources)
    if verbosity > 1:
        msg = "Found %d layers, starting processing" % number
        print >> console, msg
    output = {
        'stats': {
            'failed': 0,
            'updated': 0,
            'created': 0,
            'deleted': 0,
        },
        'layers': [],
        'deleted_layers': []
    }
    start = datetime.datetime.now()
    for i, resource in enumerate(resources):
        name = resource.name
        store = resource.store
        workspace = store.workspace
        try:
            # Avoid circular import problem
            from geonode.layers.models import Layer
            layer, created = Layer.objects.get_or_create(
                name=name,
                defaults={
                    "workspace":
                    workspace.name,
                    "store":
                    store.name,
                    "storeType":
                    store.resource_type,
                    "typename":
                    "%s:%s" % (workspace.name.encode('utf-8'),
                               resource.name.encode('utf-8')),
                    "title":
                    resource.title or 'No title provided',
                    "abstract":
                    resource.abstract or 'No abstract provided',
                    "owner":
                    owner,
                    "uuid":
                    str(uuid.uuid4())
                })
            layer.save()
            # recalculate the layer statistics
            set_attributes(layer, overwrite=True)

        except Exception, e:
            if ignore_errors:
                status = 'failed'
                exception_type, error, traceback = sys.exc_info()
            else:
                if verbosity > 0:
                    msg = "Stopping process because --ignore-errors was not set and an error was found."
                    print >> sys.stderr, msg
                raise Exception(
                    'Failed to process %s' % resource.name.encode('utf-8'),
                    e), None, sys.exc_info()[2]
        else:
            if created:
                layer.set_default_permissions()
                status = 'created'
                output['stats']['created'] += 1
            else:
                status = 'updated'
                output['stats']['updated'] += 1

        msg = "[%s] Layer %s (%d/%d)" % (status, name, i + 1, number)
        info = {'name': name, 'status': status}
        if status == 'failed':
            output['stats']['failed'] += 1
            info['traceback'] = traceback
            info['exception_type'] = exception_type
            info['error'] = error
        output['layers'].append(info)
        if verbosity > 0:
            print >> console, msg
Beispiel #20
0
        elif (passedTime > uploadTimeOut):
            logging.error('TIMEOUT: Failed to upload NetCDF File')
            exit(1)
        else:
            time.sleep(1)
            cat.reload()
            passedTime += 1


# ensure AdvancedProjectionSetting is turned off (if not -> layers wont display layers correctly)???
r_set_wms_options = session.put(geoserver_url + '/services/wms/settings',
                                data='<wms><metadata><entry key="advancedProjectionHandling">false</entry></metadata></wms>',
                                headers=headers_xml)

# Delete old workspace and create new one
if cat.get_workspace(workspace):
    if cat.get_store(projectName, workspace):
        test=cat.get_store(projectName, workspace)
        cat.delete(cat.get_store(projectName, workspace=workspace), purge="all", recurse=True)
    cat.delete(cat.get_workspace(workspace), purge="all", recurse=True)
    for layer in cat.get_layers():
        if layer.name.startswith(workspace):
            cat.delete(layer, recurse=True)
    for style in cat.get_styles(workspaces=[workspace]):
        cat.delete(style, recurse=True)
cat.create_workspace(workspace, geoserver_url + '/' + workspace)

# zip the ncFile
zfile = cfg['general']['workdir'] + '/outputFiles/data.zip'
logging.info('Writing Zipfile ' + zfile)
output = zipfile.ZipFile(zfile, 'w')
Beispiel #21
0
def main():
    # 主要使用 gsconfig 实现
    # 1- 创建指定的命名空间
    #
    cat = Catalog(url, username=USER_NAME, password=PWD)
    ws = cat.create_workspace(WORK_SPACE, WORK_SPACE)
    # 2- TODO:[*] 创建store——暂时放弃使用 catalog create的方式,还是直接rest的方式
    # ds=cat.create_datastore('testStore',WORK_SPACE)
    # ds.connection_parameters.update()
    # 2- 提交store存储
    coveragestore = 'st_3'
    headers_xml = {'content-type': 'text/xml'}
    # TODO:[*] 20-03-04 注意此处存在的问题: 若提交非geoserver 服务所在的路径下的data,会提示错误
    file_path = r'file:nmefc/waterwind/nmefc_2016072112_opdr.nc'
    # 注意 f-string 多行也适用
    store_xml=f'''
                <coverageStore>
                    <name>{coveragestore}</name>
                    <description>风场处理后的数据</description>
                    <type>NetCDF</type>
                    <enabled>true</enabled>
                    <workspace>
                        <name>{WORK_SPACE}</name>                        
                    </workspace>
                    <__default>false</__default>
                    <url>file:{file_path}</url>
                    <coverages>                        
                    </coverages>
                </coverageStore>
              '''
    r_create_coveragestore = requests.post(
        f'http://*****:*****@key": "COVERAGE_VIEW",
				"coverageView": {
					"coverageBands": {
						"coverageBand": [{
							"inputCoverageBands": {
								"@class": "singleton-list",
								"inputCoverageBand": [{
									"coverageName": "x_wind_10m"
								}]
							},
							"definition": "x_wind_10m",
							"index": 0,
							"compositionType": "BAND_SELECT"
						},
						 {
							"inputCoverageBands": {
								"@class": "singleton-list",
								"inputCoverageBand": [{
									"coverageName": "y_wind_10m"
								}]
							},
							"definition": "y_wind_10m",
							"index": 1,
							"compositionType": "BAND_SELECT"
						}]
					},
					"name": "ceshi_0305_03",
					"envelopeCompositionType": "INTERSECTION",
					"selectedResolution": "BEST",
					"selectedResolutionIndex": -1
				}
			}, {
				"@key": "cachingEnabled",
				"$": "false"
			}, {
				"@key": "dirName",
				"$": "nmefc_wind_dir_xy_ceshi_0305_03
			}]
		},
		"store": {
			"@class": "coverageStore",
			"name": "{WORK_SPACE}:{store_name}",
			"href": "http:\/\/localhost:8082\/geoserver\/rest\/workspaces\/{WORK_SPACE}\/coveragestores\/{store_name}.json"
		},
		"nativeFormat": "NetCDF",
		
		"supportedFormats": {
			"string": ["GEOTIFF", "GIF", "PNG", "JPEG", "TIFF"]
		},
		"interpolationMethods": {
			"string": ["nearest neighbor", "bilinear", "bicubic"]
		},
		"defaultInterpolationMethod": "nearest neighbor",
		"dimensions": {
			"coverageDimension": [{
				"name": "x_wind_10m",
				"description": "GridSampleDimension[-Infinity,Infinity]",
				"range": {
					"min": "-inf",
					"max": "inf"
				},
				"dimensionType": {
					"name": "REAL_32BITS"
				}
			}, {
				"name": "y_wind_10m",
				"description": "GridSampleDimension[-Infinity,Infinity]",
				"range": {
					"min": "-inf",
					"max": "inf"
				},
				"dimensionType": {
					"name": "REAL_32BITS"
				}
			}]
		},
		"requestSRS": {
			"string": ["EPSG:4326"]
		},
		"responseSRS": {
			"string": ["EPSG:4326"]
		},
		"parameters": {
			"entry": [{
				"string": "Bands",
				"null": ""
			}, {
				"string": "Filter",
				"null": ""
			}]
		},
		"nativeCoverageName": "ceshi_0305_03"
	}
}
    '''

    # TODO:[-] 20-03-05 此种方式可以提交,但只有一路band
    json_str='''
                <coverage>
                <title>st_4</title>
                <name>st_4</name>
                <metadata>
                    <entry key="time">
                         <coverageView>
                            <coverageBands>
                                <coverageBand>
                                        <inputCoverageBands>
                                            <inputCoverageBand>
                                                <coverageName>x_wind_10m</coverageName>
                                            </inputCoverageBand>
                                        </inputCoverageBands>
                                    <definition>x_wind_10m</definition>
                                    <index>0</index>
                                    <compositionType>BAND_SELECT</compositionType>
                                </coverageBand>
                            </coverageBands>
                        </coverageView>
                    </entry>
                </metadata>
                <grid dimension="2">
                    <range>
                        <low>0 0</low>
                        <high>251 251</high>
                    </range>
                    <transform>
                        <scaleX>0.2</scaleX>
                        <scaleY>-0.2</scaleY>
                        <shearX>0.0</shearX>
                        <shearY>0.0</shearY>
                        <translateX>100.0</translateX>
                        <translateY>50.0</translateY>
                    </transform>
                    <crs>EPSG:4326</crs>
                </grid>
                <supportedFormats>
                    <string>GEOTIFF</string>
                    <string>GIF</string>
                    <string>PNG</string>
                    <string>JPEG</string>
                    <string>TIFF</string>
                </supportedFormats>
                <enabled>true</enabled>
                <dimensions>
                    <coverageDimension>
                        <name>x_wind_10m</name>          
                        <dimensionType>
                            <name>REAL_32BITS</name>
                        </dimensionType>              
                    </coverageDimension>
                    <coverageDimension>
                        <name>y_wind_10m</name>      
                        <dimensionType>
                            <name>REAL_32BITS</name>
                        </dimensionType>                       
                    </coverageDimension>
                </dimensions>
                <nativeFormat>NetCDF</nativeFormat>
                <defaultInterpolationMethod>nearest neighbor</defaultInterpolationMethod>
                <srs>EPSG:4326</srs>
                <requestSRS>
                    <string>EPSG:4326</string>
                </requestSRS>
                <responseSRS>
                    <string>EPSG:4326</string>
                </responseSRS>
                <nativeCoverageName>x_wind_10m</nativeCoverageName>
            </coverage>
            '''
    # json_str = '''<coverage>
    #                 <title>{coveragestore}</title>
    #                 <metadata>
    #                     <entry key="time">
    #                         <dimensionInfo>
    #                         <enabled>true</enabled>
    #                         <attribute>time_attribute</attribute>
    #                         <presentation>LIST</presentation>
    #                         <units>ISO8601</units>
    #                         <defaultValue>NONE</defaultValue>
    #                         </dimensionInfo>
    #                         <coverageView>
    #                             <coverageBands>
    #                                 <inputCoverageBands>
    #                                     <inputCoverageBand>
    #                                         <coverageName>wind</coverageName>
    #                                     </inputCoverageBand>
    #                                 </inputCoverageBands>
    #                                 <definition>x_wind_10m</definition>
    #                                 <index>0</index>
    #                             </coverageBands>
    #                         </coverageView>
    #                     </entry>
    #                 </metadata>
    #                 <enabled>true</enabled>
    #             </coverage>
    #             '''
    #
    #
    # data = {
    #     'a': 123,
    #     'b': 123
    # }
    # import json
    # json_temp = json.dumps(data)


    coverage_title='ceshi_coverage_01'
    store_name='nmefc_wind'
    # TODO:此种方式提交的有多路band
    json_coverage_new=f'''
    <coverage>
  <name>{coverage_title}</name>
  <nativeName>{coverage_title}</nativeName>
  <namespace>
    <name>{WORK_SPACE}</name>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8082/geoserver/rest/namespaces/{WORK_SPACE}.xml" type="application/xml"/>
  </namespace>
  <title>{coverage_title}</title>
  <description>Generated from NetCDF</description>
  <keywords>
    <string>{coverage_title}</string>
    <string>WCS</string>
    <string>NetCDF</string>
  </keywords>
  <nativeCRS>GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4326"]]</nativeCRS>
  <srs>EPSG:4326</srs>
  <nativeBoundingBox>
    <minx>99.9</minx>
    <maxx>150.10000000000002</maxx>
    <miny>-0.1</miny>
    <maxy>50.1</maxy>
    <crs>EPSG:4326</crs>
  </nativeBoundingBox>
  <latLonBoundingBox>
    <minx>99.9</minx>
    <maxx>150.10000000000002</maxx>
    <miny>-0.1</miny>
    <maxy>50.1</maxy>
    <crs>EPSG:4326</crs>
  </latLonBoundingBox>
  <projectionPolicy>REPROJECT_TO_DECLARED</projectionPolicy>
  <enabled>true</enabled>
  <metadata>
    <entry key="COVERAGE_VIEW">
      <coverageView>
        <coverageBands>
          <coverageBand>
            <inputCoverageBands class="singleton-list">
              <inputCoverageBand>
                <coverageName>x_wind_10m</coverageName>
              </inputCoverageBand>
            </inputCoverageBands>
            <definition>x_wind_10m</definition>
            <index>0</index>
            <compositionType>BAND_SELECT</compositionType>
          </coverageBand>
          <coverageBand>
            <inputCoverageBands class="singleton-list">
              <inputCoverageBand>
                <coverageName>y_wind_10m</coverageName>
              </inputCoverageBand>
            </inputCoverageBands>
            <definition>y_wind_10m</definition>
            <index>1</index>
            <compositionType>BAND_SELECT</compositionType>
          </coverageBand>
        </coverageBands>
        <name>{coverage_title}</name>
        <envelopeCompositionType>INTERSECTION</envelopeCompositionType>
        <selectedResolution>BEST</selectedResolution>
        <selectedResolutionIndex>-1</selectedResolutionIndex>
      </coverageView>
    </entry>
    <entry key="cachingEnabled">false</entry>
    <entry key="dirName">nmefc_wind_dir_xy_view_nmefc_wind</entry>
  </metadata>
  <store class="coverageStore">
    <name>{WORK_SPACE}:{store_name}</name>
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8082/geoserver/rest/workspaces/{WORK_SPACE}/coveragestores/{store_name}.xml" type="application/xml"/>
  </store>
  <nativeFormat>NetCDF</nativeFormat>
  <grid dimension="2">
    <range>
      <low>0 0</low>
      <high>251 251</high>
    </range>
    <transform>
      <scaleX>0.2</scaleX>
      <scaleY>-0.2</scaleY>
      <shearX>0.0</shearX>
      <shearY>0.0</shearY>
      <translateX>100.0</translateX>
      <translateY>50.0</translateY>
    </transform>
    <crs>EPSG:4326</crs>
  </grid>
  <supportedFormats>
    <string>GEOTIFF</string>
    <string>GIF</string>
    <string>PNG</string>
    <string>JPEG</string>
    <string>TIFF</string>
  </supportedFormats>
  <interpolationMethods>
    <string>nearest neighbor</string>
    <string>bilinear</string>
    <string>bicubic</string>
  </interpolationMethods>
  <defaultInterpolationMethod>nearest neighbor</defaultInterpolationMethod>
  <dimensions>
    <coverageDimension>
      <name>x_wind_10m</name>
      <description>GridSampleDimension[-Infinity,Infinity]</description>
      <range>
        <min>-inf</min>
        <max>inf</max>
      </range>
      <dimensionType>
        <name>REAL_32BITS</name>
      </dimensionType>
    </coverageDimension>
    <coverageDimension>
      <name>y_wind_10m</name>
      <description>GridSampleDimension[-Infinity,Infinity]</description>
      <range>
        <min>-inf</min>
        <max>inf</max>
      </range>
      <dimensionType>
        <name>REAL_32BITS</name>
      </dimensionType>
    </coverageDimension>
  </dimensions>
  <requestSRS>
    <string>EPSG:4326</string>
  </requestSRS>
  <responseSRS>
    <string>EPSG:4326</string>
  </responseSRS>
  <parameters>
    <entry>
      <string>Bands</string>
      <null/>
    </entry>
    <entry>
      <string>Filter</string>
      <null/>
    </entry>
  </parameters>
  <nativeCoverageName>{coverage_title}</nativeCoverageName>
</coverage>
                        '''

    json_coverage_merage='''
                        <coverage><name>ceshi_coverage_01</name><nativeName>ceshi_coverage_01</nativeName><namespace><name>ceshi</name><atom>ceshi</atom></namespace><title>ceshi_coverage_01</title><nativeCoverageName>ceshi_coverage_01</nativeCoverageName><enabled>true</enabled><nativeFormat>NetCDF</nativeFormat><requestSRS><string>EPSG:4326</string></requestSRS><responseSRS><string>EPSG:4326</string></responseSRS><defaultInterpolationMethod>nearest neighbor</defaultInterpolationMethod><metadata><entry key="COVERAGE_VIEW"><coverageView><name>ceshi_coverage_01</name><envelopeCompositionType>INTERSECTION</envelopeCompositionType><selectedResolution /><selectedResolutionIndex>-1</selectedResolutionIndex><coverageBands><coverageBand><definition>x_wind_10m</definition><index>0</index><inputcoveragebands><inputcoverageband><coverageName>x_wind_10m</coverageName></inputcoverageband></inputcoveragebands></coverageBand><coverageBand><definition>ceshi</definition><index>1</index><inputcoveragebands><inputcoverageband><coverageName>y_wind_10m</coverageName></inputcoverageband></inputcoveragebands></coverageBand></coverageBands></coverageView></entry><entry key="cachingEnabled">false</entry><entry key="dirName">nmefc_wind_dir_xy_view_nmefc_wind</entry></metadata><store class="coverageStore"><name>my_test_2:nmefc_2016072112_opdr</name></store><dimensions><coverageDimension><name>x_wind_10m</name><description>GridSampleDimension[-Infinity,Infinity]</description><dimensionType><name>REAL_32BITS</name></dimensionType><range><min>-inf</min><max>inf</max></range></coverageDimension><coverageDimension><name>y_wind_10m</name><description>GridSampleDimension[-Infinity,Infinity]</description><dimensionType><name>REAL_32BITS</name></dimensionType><range><min>-inf</min><max>inf</max></range></coverageDimension></dimensions></coverage>
                        '''
    headers_xml_json = {'Content-Type': 'application/json'}
    response = requests.post(
        f'http://localhost:8082/geoserver/rest/workspaces/{WORK_SPACE}/coveragestores/{coveragestore}/coverages',
        auth=('admin', 'geoserver'),
        # TODO:[*] 20-03-05 此处的问题是对于一个栅格数据有多个特征时,如何添加 对应的name
        # data='<coverage><nativeCoverageName>x_wind_10m</nativeCoverageName><name>x_wind_10m</name></coverage><coverage><nativeCoverageName>y_wind_10m</nativeCoverageName><name>x_wind_10m</name></coverage>',
        # TODO:[*] 20-03-19 使用自动拼接的xml,此部分暂时注释掉
        # data=json_coverage_new,
        data=json_coverage_merage,
        headers=headers_xml)
    pass

    # 5 绑定样式
    # TODO:[-] 20-03-08 绑定样式的api要参考:大体思路是 -> 工作区->layer->修改默认style(注意不能创建)
    # PUT /workspaces/{workspaceName}/layers/{layerName}   Modify a layer.
    # https://docs.geoserver.org/latest/en/api/#/latest/en/api/1.0.0/layers.yaml
    # curl -v -u admin:geoserver -XPUT -H "Content-type: text/xml" -d "<layer><defaultStyle><name>RH2Style</name></defaultStyle></layer>" http://localhost:8090/geoserver/rest/layers/RH2
    style_name='wind_dir_style'
    json_style=f'''
                    <defaultStyle>
                        <name>{WORK_SPACE}:{style_name}</name>
                        <workspace>{WORK_SPACE}</workspace>
                        <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8082/geoserver/rest/workspaces/{WORK_SPACE}/styles/{style_name}.xml" type="application/xml"/>
                    </defaultStyle>
                '''

    json_style_2 = f'''
                        <layer>
                            <defaultStyle>
                                <name>{style_name}</name>
                            </defaultStyle>
                        </layer>
                    '''
    url_style=f'http://localhost:8082/geoserver/rest//workspaces/{WORK_SPACE}/layers/{coverage_title}'
    response=requests.put(
        url_style,
        auth=('admin', 'geoserver'),
        data=json_style_2,
        headers=headers_xml)
    pass
Beispiel #22
0
class GeoServerDatasetEngineEnd2EndTests(unittest.TestCase):

    def setUp(self):
        # Files
        self.tests_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        self.files_root = os.path.join(self.tests_root, 'files')

        # GeoServer
        self.gs_endpoint = TEST_GEOSERVER_DATASET_SERVICE['ENDPOINT']
        self.gs_username = TEST_GEOSERVER_DATASET_SERVICE['USERNAME']
        self.gs_password = TEST_GEOSERVER_DATASET_SERVICE['PASSWORD']
        self.catalog = GeoServerCatalog(self.gs_endpoint, username=self.gs_username, password=self.gs_password)

        # Postgis
        self.pg_username = TEST_POSTGIS_SERVICE['USERNAME']
        self.pg_password = TEST_POSTGIS_SERVICE['PASSWORD']
        self.pg_database = TEST_POSTGIS_SERVICE['DATABASE']
        self.pg_table_name = 'points'
        self.pg_host = TEST_POSTGIS_SERVICE['HOST']
        self.pg_port = TEST_POSTGIS_SERVICE['PORT']
        self.pg_url = TEST_POSTGIS_SERVICE['URL']
        self.pg_public_url = TEST_POSTGIS_SERVICE['PUBLIC_URL']

        # Setup a testing workspace
        self.workspace_name = random_string_generator(10)
        self.workspace_uri = 'http://www.tethysplatform.org/{}'.format(self.workspace_name)

        retries = 5
        while retries > 0:
            try:
                self.catalog.create_workspace(self.workspace_name, self.workspace_uri)
                break
            except AssertionError as e:
                if 'Error persisting' in str(e) and retries > 0:
                    print("WARNING: FAILED TO PERSIST WORKSPACE.")
                    retries -= 1
                else:
                    raise

        # Setup Postgis database connection
        self.public_engine = create_engine(self.pg_public_url)
        self.connection = self.public_engine.connect()
        self.transaction = self.connection.begin()

        # Create GeoServer Engine
        self.endpoint = TEST_GEOSERVER_DATASET_SERVICE['ENDPOINT']
        self.geoserver_engine = GeoServerSpatialDatasetEngine(endpoint=self.endpoint,
                                                              username=TEST_GEOSERVER_DATASET_SERVICE['USERNAME'],
                                                              password=TEST_GEOSERVER_DATASET_SERVICE['PASSWORD'])

        self.geometry_column = 'geometry'
        self.geometry_type = 'Point'
        self.srid = 4326

    def assert_valid_response_object(self, response_object):
        # Response object should be a dictionary with the keys 'success' and either 'result' if success is True
        # or 'error' if success is False
        self.assertIsInstance(response_object, dict)
        self.assertIn('success', response_object)

        if isinstance(response_object, dict) and 'success' in response_object:
            if response_object['success'] is True:
                self.assertIn('result', response_object)
            elif response_object['success'] is False:
                self.assertIn('error', response_object)

    def tearDown(self):
        # Clean up GeoServer
        workspace = self.catalog.get_workspace(self.workspace_name)
        self.catalog.delete(workspace, recurse=True, purge=True)

        # Clean up Postgis database
        self.transaction.rollback()
        self.connection.close()
        self.public_engine.dispose()

    def setup_postgis_table(self):
        """
        Creates table in the database named "points" with two entries. The table has three columns:
        "id", "name", and "geometry." Use this table for the tests that require a database.
        """
        # Clean up
        delete_sql = "DROP TABLE IF EXISTS {table}".\
            format(table=self.pg_table_name)
        self.connection.execute(delete_sql)

        # Create table
        geom_table_sql = "CREATE TABLE IF NOT EXISTS {table} (" \
                         "id integer CONSTRAINT points_primary_key PRIMARY KEY, " \
                         "name varchar(20)" \
                         "); " \
                         "SELECT AddGeometryColumn('public', '{table}', 'geometry', 4326, 'POINT', 2);". \
            format(table=self.pg_table_name)

        self.connection.execute(geom_table_sql)

        insert_sql = "INSERT INTO {table} VALUES ({id}, '{name}', ST_GeomFromText('POINT({lon} {lat})', 4326));"
        rows = [
            {"id": 1, "name": "Aquaveo", "lat": 40.276039, "lon": -111.651120},
            {"id": 2, "name": "BYU", "lat": 40.252335, "lon": -111.649326},
        ]

        for r in rows:
            sql = insert_sql.format(
                table=self.pg_table_name,
                id=r['id'],
                name=r['name'],
                lat=r['lat'],
                lon=r['lon']
            )
            self.connection.execute(sql)
        self.transaction.commit()

    def test_create_shapefile_resource_base(self):
        # call methods: create_shapefile_resource, list_resources, get_resource, delete_resource

        # TEST create shapefile

        # Setup
        filename = 'test'
        shapefile_name = os.path.join(self.files_root, 'shapefile', filename)
        workspace = self.workspace_name
        store_id = random_string_generator(10)
        store_id_name = '{}:{}'.format(workspace, store_id)
        # store_id_name = store_id

        # Execute
        response = self.geoserver_engine.create_shapefile_resource(store_id=store_id_name,
                                                                   shapefile_base=shapefile_name,
                                                                   overwrite=True)
        # Validate response object
        self.assert_valid_response_object(response)

        # Should succeed
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)
        self.assertIn(store_id, r['name'])
        self.assertIn(store_id, r['store'])

        # TEST list_resources

        # Execute
        response = self.geoserver_engine.list_resources()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # layer listed
        self.assertIn(store_id, result)

        # TEST get_resources

        # Execute
        # Geoserver uses the store_id as the layer/resource name (not the filename)
        resource_id_name = '{}:{}'.format(workspace, store_id)
        response = self.geoserver_engine.get_resource(resource_id=resource_id_name)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertEquals(store_id, r['name'])
        self.assertIn(store_id, r['wfs']['shapefile'])

        # TEST delete_resource
        # Execute
        # This case the resource id is the same as the store id.
        response = self.geoserver_engine.delete_resource(resource_id=resource_id_name,
                                                         store_id=store_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        # TODO: delete_resource is returning a 403 error: not authorized.
        # self.assertTrue(response['success'])

    def test_create_shapefile_resource_zip(self):
        # call methods: create_shapefile_resource, list_layers, get_layer, delete_layer

        # TEST create_shapefile_resource
        # Test1.zip

        # Setup
        shapefile_zip = os.path.join(self.files_root, 'shapefile', "test1.zip")
        shapefile = "test1"
        workspace = self.workspace_name
        store_id = random_string_generator(10)
        store_id_name = '{}:{}'.format(workspace, store_id)

        # Execute
        response = self.geoserver_engine.create_shapefile_resource(store_id=store_id_name,
                                                                   shapefile_zip=shapefile_zip,
                                                                   overwrite=True)
        # Validate response object
        self.assert_valid_response_object(response)

        # Should succeed
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        filename = os.path.splitext(os.path.basename(shapefile_zip))[0]
        self.assertIsInstance(r, dict)
        self.assertIn(filename, r['name'])
        self.assertIn(store_id, r['store'])

        # TEST list_layers test
        # Execute
        response = self.geoserver_engine.list_layers()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # Get the last item from result
        layer_id = '{}:{}'.format(workspace, shapefile)

        # TEST get layers test
        # Execute
        response = self.geoserver_engine.get_layer(layer_id=layer_id,
                                                   store_id=store_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        self.assertIn(filename, r['name'])
        self.assertIn(self.workspace_name, r['name'])

        # TEST delete_layer
        self.geoserver_engine.delete_layer(layer_id=layer_id,
                                           store_id=store_id)

        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

    def test_create_shapefile_resource_upload(self):
        # call methods: create_shapefile_resource, list_stores, get_store, delete_store

        # TEST create_shapefile_resource

        # Use in memory file list: test.shp and friends
        # Setup
        shapefile_cst = os.path.join(self.files_root, 'shapefile', 'test.cst')
        shapefile_dbf = os.path.join(self.files_root, 'shapefile', 'test.dbf')
        shapefile_prj = os.path.join(self.files_root, 'shapefile', 'test.prj')
        shapefile_shp = os.path.join(self.files_root, 'shapefile', 'test.shp')
        shapefile_shx = os.path.join(self.files_root, 'shapefile', 'test.shx')

        # Workspace is given
        store_rand = random_string_generator(10)
        store_id = '{}:{}'.format(self.workspace_name, store_rand)

        with open(shapefile_cst, 'rb') as cst_upload,\
                open(shapefile_dbf, 'rb') as dbf_upload,\
                open(shapefile_prj, 'rb') as prj_upload,\
                open(shapefile_shp, 'rb') as shp_upload,\
                open(shapefile_shx, 'rb') as shx_upload:
            upload_list = [cst_upload, dbf_upload, prj_upload, shp_upload, shx_upload]
            response = self.geoserver_engine.create_shapefile_resource(store_id=store_id,
                                                                       shapefile_upload=upload_list,
                                                                       overwrite=True)
        # Should succeed
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)
        self.assertIn(store_rand, r['name'])
        self.assertIn(store_rand, r['store'])

        # TEST list_stores

        # Execute

        response = self.geoserver_engine.list_stores()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # layer group listed
        self.assertIn(store_rand, result)

        # TEST get store

        # Execute
        response = self.geoserver_engine.get_store(store_id=store_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertIn(r['name'], store_rand)
        self.assertIn('workspace', r)
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST delete_store
        response = self.geoserver_engine.delete_store(store_id=store_id, purge=True, recurse=True)

        # Failure Check
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

    def test_create_coverage_resource_arcgrid(self):
        # call methods: create_coverage_resource, list_resources, get_resource, delete_resource

        # TEST create_coverage_resource
        # precip30min.zip
        store_name = random_string_generator(10)
        expected_store_id = '{}:{}'.format(self.workspace_name, store_name)
        expected_coverage_type = 'arcgrid'
        coverage_file_name = 'precip30min.zip'
        coverage_name = coverage_file_name.split('.')[0]
        coverage_file = os.path.join(self.files_root, "arc_sample", coverage_file_name)

        with open(coverage_file, 'rb') as coverage_upload:
            # Execute
            response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id,
                                                                      coverage_type=expected_coverage_type,
                                                                      coverage_upload=coverage_upload,
                                                                      overwrite=True)
        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Values
        self.assertEqual(coverage_name, r['name'])
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST list_resources

        # Execute
        response = self.geoserver_engine.list_resources()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # layer listed
        self.assertIn(coverage_name, result)

        # TEST get_resource

        # Execute
        resource_id = '{}:{}'.format(self.workspace_name, coverage_name)

        response = self.geoserver_engine.get_resource(resource_id=resource_id,
                                                      store_id=store_name)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        self.assertIn('ArcGrid', r['keywords'])
        self.assertEqual(coverage_name, r['title'])
        self.assertEqual('coverage', r['resource_type'])

        # delete_resource
        # TODO: delete_resource is returning a 403 error: not authorized.
        # Execute
        resource_id = '{}:{}'.format(self.workspace_name, coverage_name)
        response = self.geoserver_engine.delete_resource(resource_id=resource_id,
                                                         store_id=store_name)

        # # Validate response object
        self.assert_valid_response_object(response)

        # # Success
        # self.assertTrue(response['success'])

    def test_create_coverage_resource_grassgrid(self):
        # call methods: create_coverage_resource, list_layers, get_layer, delete_layer

        # TEST create_coverage resource
        # my_grass.zip
        store_name = random_string_generator(10)
        expected_store_id = '{}:{}'.format(self.workspace_name, store_name)
        expected_coverage_type = 'grassgrid'
        coverage_file_name = 'my_grass.zip'
        coverage_name = coverage_file_name.split('.')[0]
        coverage_file = os.path.join(self.files_root, "grass_ascii", coverage_file_name)

        # Execute
        response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id,
                                                                  coverage_type=expected_coverage_type,
                                                                  coverage_file=coverage_file,
                                                                  overwrite=True)
        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Tests
        self.assertIn(coverage_name, r['name'])
        self.assertEqual(self.workspace_name, r['workspace'])

        #  TEST list_layers

        #  Execute
        response = self.geoserver_engine.list_layers()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # Check if layer is in list
        self.assertIn(coverage_name, result)

        # TEST get_layer

        # Execute
        layer_id = '{}:{}'.format(self.workspace_name, coverage_name)
        response = self.geoserver_engine.get_layer(layer_id=layer_id,
                                                   store_id=store_name)
        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)
        self.assertIn(store_name, r['store'])
        self.assertIn(self.workspace_name, r['name'])

        # TEST delete_layer
        self.geoserver_engine.delete_layer(layer_id=layer_id,
                                           store_id=store_name)

        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

    def test_create_coverage_resource_geotiff(self):
        # adem.tif
        # call methods: create_coverage_resource, list_stores, get_store, delete_store

        # TEST create_coverage_resource

        store_name = random_string_generator(10)
        expected_store_id = '{}:{}'.format(self.workspace_name, store_name)
        expected_coverage_type = 'geotiff'
        coverage_file_name = 'adem.tif'
        coverage_name = coverage_file_name.split('.')[0]
        coverage_file = os.path.join(self.files_root, coverage_file_name)

        with open(coverage_file, 'rb') as coverage_upload:
            # Execute
            response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id,
                                                                      coverage_type=expected_coverage_type,
                                                                      coverage_upload=coverage_upload,
                                                                      overwrite=True)
        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Values
        self.assertEqual(coverage_name, r['name'])
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST list_stores

        # Execute

        response = self.geoserver_engine.list_stores()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # TEST layer group listed
        self.assertIn(store_name, result)

        # TEST get store

        # Execute
        response = self.geoserver_engine.get_store(store_id=expected_store_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertIn(r['name'], store_name)
        self.assertIn('workspace', r)
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST delete_store
        response = self.geoserver_engine.delete_store(store_id=expected_store_id, purge=True, recurse=True)

        # Failure Check
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

    def test_create_coverage_resource_world_file_tif(self):
        # pk50095.zip
        # call methods: create_coverage_resource, list_layers, get_layer, delete_layer
        # TEST create_coverage resource
        store_name = random_string_generator(10)
        expected_store_id = '{}:{}'.format(self.workspace_name, store_name)
        expected_coverage_type = 'worldimage'
        coverage_file_name = 'Pk50095.zip'
        coverage_name = coverage_file_name.split('.')[0]
        coverage_file = os.path.join(self.files_root, "img_sample", coverage_file_name)

        # Execute
        response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id,
                                                                  coverage_type=expected_coverage_type,
                                                                  coverage_file=coverage_file,
                                                                  overwrite=True)
        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Tests
        self.assertIn(coverage_name, r['name'])
        self.assertEqual(self.workspace_name, r['workspace'])

        #  TEST list_layers

        #  Execute
        response = self.geoserver_engine.list_layers()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # Check if layer is in list
        self.assertIn(coverage_name, result)

        # TEST get_layer

        # Execute
        layer_id = '{}:{}'.format(self.workspace_name, coverage_name)
        response = self.geoserver_engine.get_layer(layer_id=layer_id,
                                                   store_id=store_name)
        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)
        self.assertIn(store_name, r['store'])
        self.assertIn(self.workspace_name, self.workspace_name)

        # TEST delete_layer
        self.geoserver_engine.delete_layer(layer_id=coverage_name,
                                           store_id=store_name)

        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

    def test_create_coverage_resource_upload(self):
        # DO NOT MOCK
        # Use in memory file list: precip30min.prj & precip30min.asc
        # call methods: create_coverage_resource, list_resources, get_resource, delete_resource
        store_id_name = random_string_generator(10)
        expected_store_id = '{}:{}'.format(self.workspace_name, store_id_name)
        expected_coverage_type = 'arcgrid'
        coverage_file_name = 'precip30min.asc'
        prj_file_name = 'precip30min.prj'
        coverage_name = coverage_file_name.split('.')[0]
        arc_sample = os.path.join(self.files_root, "arc_sample")
        coverage_file = os.path.join(arc_sample, coverage_file_name)
        prj_file = os.path.join(arc_sample, prj_file_name)

        with open(coverage_file, 'rb') as coverage_upload:
            with open(prj_file, 'rb') as prj_upload:
                upload_list = [coverage_upload, prj_upload]

                # Execute
                response = self.geoserver_engine.create_coverage_resource(store_id=expected_store_id,
                                                                          coverage_type=expected_coverage_type,
                                                                          coverage_upload=upload_list,
                                                                          overwrite=True)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Values
        self.assertEqual(coverage_name, r['name'])
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST list_resources

        # Execute
        response = self.geoserver_engine.list_resources()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # layer listed
        self.assertIn(coverage_name, result)

        # TEST get_resources

        # Execute
        resource_id = "{}:{}".format(self.workspace_name, coverage_name)
        response = self.geoserver_engine.get_resource(resource_id=resource_id,
                                                      store_id=store_id_name)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertEquals(coverage_name, r['name'])
        self.assertIn(coverage_name, r['wcs']['arcgrid'])

        # TEST delete_resource
        # TODO: delete_resource is returning a 403 error: not authorized.
        # Execute
        # This case the resource id is the same as the filename.
        resource_id = '{}:{}'.format(self.workspace_name, coverage_name)
        response = self.geoserver_engine.delete_resource(resource_id=resource_id,
                                                         store_id=store_id_name)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        # self.assertTrue(response['success'])

    def test_create_layer_group(self):

        # call methods: create_layer_group, list_layer_groups, get_layer_group, delete_layer_group

        # create_layer_group
        # Use existing layers and styles in geoserver:
        # layers: sf:roads, sf:bugsites, sf:streams;
        # styles: simple_roads, capitals, simple_streams

        # TEST create_layer_group

        # Do create
        # expected_layer_group_id = '{}:{}'.format(self.workspace_name, random_string_generator(10))

        expected_layer_group_id = random_string_generator(10)
        expected_layers = ['roads', 'bugsites', 'streams']
        expected_styles = ['simple_roads', 'capitals', 'simple_streams']

        # TODO: create_layer_group: fails on catalog.save() when workspace is given.
        response = self.geoserver_engine.create_layer_group(layer_group_id=expected_layer_group_id,
                                                            layers=expected_layers,
                                                            styles=expected_styles)
        # Should succeed
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

        # Validate
        result = response['result']

        self.assertEquals(result['name'], expected_layer_group_id)
        self.assertEquals(result['layers'], expected_layers)
        self.assertEquals(result['styles'], expected_styles)

        # TEST list_layer_groups

        # Execute
        response = self.geoserver_engine.list_layer_groups()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # layer group listed
        self.assertIn(expected_layer_group_id, result)

        # TEST get layer_group

        # Execute
        response = self.geoserver_engine.get_layer_group(layer_group_id=expected_layer_group_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # List of dictionaries
        self.assertIn('workspace', r)
        self.assertEqual(None, r['workspace'])
        self.assertIn('layers', r)
        self.assertEqual(expected_layers, r['layers'])
        self.assertIn('styles', r)
        self.assertEqual(expected_styles, r['styles'])
        self.assertNotIn('dom', r)

        # TEST delete layer group
        # Clean up
        self.geoserver_engine.delete_layer_group(layer_group_id=expected_layer_group_id)
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])
        # self.assertIsNone(response['result'])

    def test_create_workspace(self):
        # call methods: create_workspace, list_workspaces, get_workspace, delete_workspace

        # TEST create workspace
        expected_workspace_id = random_string_generator(10)

        expected_uri = 'http://www.tethysplatform.org/{}'.format(expected_workspace_id)

        # create workspace test
        response = self.geoserver_engine.create_workspace(workspace_id=expected_workspace_id, uri=expected_uri)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        self.assertIn('name', r)

        self.assertEqual(expected_workspace_id, r['name'])

        # TEST list workspace

        # Execute
        response = self.geoserver_engine.list_workspaces()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # TEST layer group listed
        self.assertIn(expected_workspace_id, result)

        # TEST get_workspace

        # Execute
        response = self.geoserver_engine.get_workspace(workspace_id=expected_workspace_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertIn(r['name'], expected_workspace_id)

        # TEST delete work_space

        # Do delete
        response = self.geoserver_engine.delete_workspace(workspace_id=expected_workspace_id)

        # Should succeed
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])
        self.assertIsNone(response['result'])

    def test_create_style(self):
        # call methods: create_style, list_styles, get_style, delete_style

        # TEST create_style
        expected_style_id_name = random_string_generator(10)
        expected_style_id = '{}:{}'.format(self.workspace_name, expected_style_id_name)
        style_file_name = 'point.sld'
        expected_sld = os.path.join(self.files_root, style_file_name)

        # Execute
        with open(expected_sld, 'r') as sld_file:
            sld_string = sld_file.read()
            # TODO: create_style: Fails on when overwrite is False.
            response = self.geoserver_engine.create_style(style_id=expected_style_id, sld=sld_string, overwrite=True)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # TEST list_styles

        # Execute
        response = self.geoserver_engine.list_styles(workspace=self.workspace_name)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # TEST layer listed
        self.assertIn(expected_style_id_name, result)

        # TEST get_style

        # Execute
        response = self.geoserver_engine.get_style(style_id=expected_style_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertIn(r['name'], expected_style_id)
        self.assertIn('workspace', r)
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST delete_style

        # Do delete
        response = self.geoserver_engine.delete_style(style_id=expected_style_id)

        # Should succeed
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])
        self.assertIsNone(response['result'])

    def test_link_and_add_table(self):
        # call methods: link_sqlalchemy_db_to_geoserver, add_table_to_postgis_store, list_stores, get_store,
        # delete_store
        self.setup_postgis_table()

        # TEST link_sqlalchemy_db_to_geoserver
        store_id_name = random_string_generator(10)
        store_id = '{}:{}'.format(self.workspace_name, store_id_name)
        sqlalchemy_engine = create_engine(self.pg_url)

        response = self.geoserver_engine.link_sqlalchemy_db_to_geoserver(store_id=store_id,
                                                                         sqlalchemy_engine=sqlalchemy_engine,
                                                                         docker=True)

        # Check for success response
        self.assertTrue(response['success'])
        sqlalchemy_engine.dispose()

        # TEST add_table_to_postgis_store

        # Execute
        response = self.geoserver_engine.add_table_to_postgis_store(store_id=store_id,
                                                                    table=self.pg_table_name)

        # Check for success response
        self.assertTrue(response['success'])

        # TEST list_stores

        # Execute

        response = self.geoserver_engine.list_stores()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # layer group listed
        self.assertIn(store_id_name, result)

        # TEST get store

        # Execute
        response = self.geoserver_engine.get_store(store_id=store_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertIn(store_id_name, r['name'])
        self.assertIn('workspace', r)
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST delete_store
        response = self.geoserver_engine.delete_store(store_id=store_id, purge=True, recurse=True)

        # Failure Check
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

    def test_create_postgis_feature_resource(self):
        # call methods: create_postgis_feature_resource (with table), list_stores, get_store, delete_store
        self.setup_postgis_table()

        # TEST create_postgis_feature_resource (with table)
        store_id_name = random_string_generator(10)
        store_id = '{}:{}'.format(self.workspace_name, store_id_name)

        response = self.geoserver_engine.create_postgis_feature_resource(store_id=store_id,
                                                                         host=self.pg_host,
                                                                         port=self.pg_port,
                                                                         database=self.pg_database,
                                                                         user=self.pg_username,
                                                                         password=self.pg_password,
                                                                         table=self.pg_table_name)

        self.assertTrue(response['success'])

        # TEST list_stores

        # Execute

        response = self.geoserver_engine.list_stores()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # layer group listed
        self.assertIn(store_id_name, result)

        # TEST get store

        # Execute
        response = self.geoserver_engine.get_store(store_id=store_id)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertIn(store_id_name, r['name'])
        self.assertIn('workspace', r)
        self.assertEqual(self.workspace_name, r['workspace'])

        # TEST delete_store
        response = self.geoserver_engine.delete_store(store_id=store_id, purge=True, recurse=True)

        # Failure Check
        self.assert_valid_response_object(response)
        self.assertTrue(response['success'])

    def test_create_sql_view(self):
        # call methods: create_sql_view, list_resources, list_stores, list_layers
        self.setup_postgis_table()

        # TEST create_postgis_feature_resource (with table)
        store_id_name = random_string_generator(10)
        store_id = '{}:{}'.format(self.workspace_name, store_id_name)

        response = self.geoserver_engine.create_postgis_feature_resource(store_id=store_id,
                                                                         host=self.pg_host,
                                                                         port=self.pg_port,
                                                                         database=self.pg_database,
                                                                         user=self.pg_username,
                                                                         password=self.pg_password,
                                                                         table=self.pg_table_name)
        self.assertTrue(response['success'])

        feature_type_name = random_string_generator(10)
        postgis_store_id = '{}:{}'.format(self.workspace_name, store_id_name)
        sql = "SELECT * FROM {}".format(self.pg_table_name)
        geometry_column = self.geometry_column
        geometry_type = self.geometry_type

        response = self.geoserver_engine.create_sql_view(feature_type_name=feature_type_name,
                                                         postgis_store_id=postgis_store_id,
                                                         sql=sql,
                                                         geometry_column=geometry_column,
                                                         geometry_type=geometry_type)

        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        self.assertIn('name', r)
        self.assertIn(feature_type_name, r['name'])

        # TEST list_resources

        # Execute
        response = self.geoserver_engine.list_resources()

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        result = response['result']

        # Returns list
        self.assertIsInstance(result, list)

        # layer listed
        self.assertIn(feature_type_name, result)

        # TEST get_resources

        # Execute
        # Geoserver uses the store_id as the layer/resource name (not the filename)
        resource_id_name = '{}:{}'.format(self.workspace_name, feature_type_name)
        response = self.geoserver_engine.get_resource(resource_id=resource_id_name)

        # Validate response object
        self.assert_valid_response_object(response)

        # Success
        self.assertTrue(response['success'])

        # Extract Result
        r = response['result']

        # Type
        self.assertIsInstance(r, dict)

        # Properties
        self.assertIn('name', r)
        self.assertEquals(feature_type_name, r['name'])
        self.assertIn(feature_type_name, r['wfs']['shapefile'])

        # TEST delete_resource
        # Execute
        # This case the resource id is the same as the store id.
        response = self.geoserver_engine.delete_resource(resource_id=resource_id_name,
                                                         store_id=store_id_name)

        # Validate response object
        self.assert_valid_response_object(response)
Beispiel #23
0
def setup_join(new_table_owner, table_name, layer_typename,
               table_attribute_name, layer_attribute_name):
    LOGGER.info('setup_join')
    """
    Setup the Table Join in GeoNode
    """

    assert isinstance(new_table_owner,
                      User), "new_table_owner must be a User object"
    assert table_name is not None, "table_name cannot be None"
    assert layer_typename is not None, "layer_typename cannot be None"
    assert table_attribute_name is not None, "table_attribute_name cannot be None"
    assert layer_attribute_name is not None, "layer_attribute_name cannot be None"

    LOGGER.info('setup_join. Step (1): Retrieve the DataTable object')
    try:
        dt = DataTable.objects.get(table_name=table_name)
    except DataTable.DoesNotExist:
        err_msg = 'No DataTable object found for table_name "%s"' % table_name
        LOGGER.error(err_msg)
        return None, err_msg

    LOGGER.info('setup_join. Step (2): Retrieve the Layer object')

    try:
        layer = Layer.objects.get(typename=layer_typename)
    except Layer.DoesNotExist:
        err_msg = 'No Layer object found for layer_typename "%s"' % layer_typename
        LOGGER.error(err_msg)
        return None, err_msg

    LOGGER.info('setup_join. Step (3): Retrieve the DataTableAttribute object')
    try:
        table_attribute = DataTableAttribute.objects.get(\
                                        datatable=dt,
                                        attribute=table_attribute_name)
    except DataTableAttribute.DoesNotExist:
        err_msg = 'No DataTableAttribute object found for table/attribute (%s/%s)' \
                  % (dt,
                     table_attribute_name)
        LOGGER.error(err_msg)
        return None, err_msg

    LOGGER.info('setup_join. Step (4): Retrieve the LayerAttribute object')
    try:
        layer_attribute = LayerAttribute.objects.get(\
                                layer=layer,
                                attribute=layer_attribute_name)
    except LayerAttribute.DoesNotExist:
        err_msg = 'No LayerAttribute object found for layer/attribute (%s/%s)'\
                  % (layer, layer_attribute_name)
        LOGGER.error(err_msg)
        return None, err_msg

    LOGGER.info('setup_join. Step (5): Build SQL statement to create view')

    layer_name = layer.typename.split(':')[1]

    # ------------------------------------------------------------------
    # (5) Check if the layer and the table are in the same store (database)
    # ------------------------------------------------------------------
    if layer.store != dt.tablespace:
        err_msg = 'layer (%s) and tablespace (%s) must be in the same database.'\
            % (layer.store, dt.tablespace)
        LOGGER.error(err_msg)
        return None, err_msg

    # ------------------------------------------------------------------
    # (5a) Check if the join columns compatible
    # ------------------------------------------------------------------
    column_checker = ColumnChecker(\
                                layer_name,
                                layer_attribute.attribute,
                                dt.table_name,
                                table_attribute.attribute)
    (are_cols_compatible,
     err_msg) = column_checker.are_join_columns_compatible()
    if not are_cols_compatible:  # Doesn't look good, return an error message
        return None, err_msg

    # ------------------------------------------------------------------
    # (5b) Create SQL statement for the tablejoin
    # ------------------------------------------------------------------
    view_name = get_unique_viewname(dt.table_name, layer_name)

    # SQL to create the view
    view_sql = ('CREATE VIEW {0}'
                ' AS SELECT {1}.{2}, {3}.*'
                ' FROM {1} INNER JOIN {3}'
                ' ON {1}."{4}" = {3}."{5}";'.format(\
                    view_name,  # 0
                    layer_name, # 1
                    THE_GEOM_LAYER_COLUMN, # 2
                    dt.table_name,  # 3
                    layer_attribute.attribute, # 4
                    table_attribute.attribute)) # 5

    # Materialized view for next version of Postgres
    """view_sql = ('create materialized view {0} as'
                   ' select {1}.the_geom, {2}.*'
                   ' from {1} inner join {2}'
                   ' on {1}."{3}" = {2}."{4}";').format(\
                       view_name,
                       layer_name,
                       dt.table_name,
                       layer_attribute.attribute,
                       table_attribute.attribute)
    """
    LOGGER.info('setup_join. Step (6): Retrieve stats')

    # ------------------------------------------------------------------
    # Retrieve stats
    # ------------------------------------------------------------------
    matched_count_sql = ('select count({0}) from {1} where {1}.{0}'
                         ' in (select "{2}" from {3});').format(\
                            table_attribute.attribute,
                            dt.table_name,
                            layer_attribute.attribute,
                            layer_name)

    unmatched_count_sql = ('select count({0}) from {1} where {1}.{0}'
                           ' not in (select "{2}" from {3});').format(\
                            table_attribute.attribute,
                            dt.table_name,
                            layer_attribute.attribute,
                            layer_name)

    unmatched_list_sql = ('select {0} from {1} where {1}.{0}'
                          ' not in (select "{2}" from {3}) limit 500;').format(\
                            table_attribute.attribute,
                            dt.table_name,
                            layer_attribute.attribute,
                            layer_name)

    # ------------------------------------------------------------------
    # Create a TableJoin object
    # ------------------------------------------------------------------
    LOGGER.info('setup_join. Step (7): Create a TableJoin object')
    tj, created = TableJoin.objects.get_or_create(\
                                source_layer=layer,
                                datatable=dt,
                                table_attribute=table_attribute,
                                layer_attribute=layer_attribute,
                                view_name=view_name,
                                view_sql=view_sql)
    tj.save()
    msgt('table join created! :) %s' % tj.id)

    # ------------------------------------------------------------------
    # Create the View (and double view)
    # ------------------------------------------------------------------
    LOGGER.info('setup_join. Step (8): Create the View (and double view)')

    # Convenience method to drop a view
    #
    drop_view_by_name(view_name)

    try:
        conn = psycopg2.connect(get_datastore_connection_string())
        cur = conn.cursor()

        # Create the new view
        #
        msg('view_sql: %s' % view_sql)
        cur.execute(view_sql)
        #cur.execute(double_view_sql)   # For later version of postgres

        # Record the counts for matched records and
        # add unmatched records to the TableJoin object

        # Unmatched count
        cur.execute(matched_count_sql)
        tj.matched_records_count = cur.fetchone()[0]

        # Matched count
        cur.execute(unmatched_count_sql)
        tj.unmatched_records_count = int(cur.fetchone()[0])

        # Unmatched records list
        if tj.unmatched_records_count > 0:
            cur.execute(unmatched_list_sql)
            tj.unmatched_records_list = ",".join(
                ['%s' % r[0] for r in cur.fetchall()])

        conn.commit()
        cur.close()

        # If no records match, then delete the TableJoin
        #
        if tj.matched_records_count == 0:
            # Delete the table join
            tj.delete()

            # Create an error message, log it, and send it back
            err_msg = ('No records matched.  Make sure that you chose'
                       ' the correct column and that the chosen layer'
                       ' is in the same geographic area.')
            LOGGER.error(err_msg)
            return None, err_msg

    except Exception as ex_obj:
        tj.delete()  # If needed for debugging, don't delete the table join

        traceback.print_exc(sys.exc_info())
        err_msg = "Error Joining table %s to layer %s: %s" % (\
                        table_name,
                        layer_typename,
                        str(ex_obj[0]))
        LOGGER.error(err_msg)

        if err_msg.find('You might need to add explicit type casts.') > -1:
            user_msg = "The chosen column is a different data type than the one expected."
        else:
            user_msg = err_msg

        return None, user_msg

    finally:
        conn.close()

    #--------------------------------------------------
    # Create the Layer in GeoServer from the view
    #--------------------------------------------------
    LOGGER.info(
        'setup_join. Step (9): Create the Layer in GeoServer from the view')
    try:
        LOGGER.info('setup_join. Step (9a): Find the datastore')
        #----------------------------
        # Find the datastore
        #----------------------------
        cat = Catalog(
            settings.GEOSERVER_BASE_URL + "rest",
            settings.GEOSERVER_CREDENTIALS[0],
            settings.GEOSERVER_CREDENTIALS[1])  # "admin", "geoserver")

        workspace = cat.get_workspace('geonode')
        ds_list = cat.get_xml(workspace.datastore_url)
        datastores = [
            datastore_from_index(cat, workspace, n)
            for n in ds_list.findall("dataStore")
        ]
        ds = None

        # Iterate through datastores
        #
        for datastore in datastores:
            #msg ('datastore name:', datastore.name)
            if datastore.name == layer.store:
                ds = datastore

        if ds is None:
            tj.delete()
            err_msg = "Datastore name not found: '%s' (join)" % settings.DB_DATASTORE_NAME
            LOGGER.error(str(ds))
            return None, err_msg

        # Publish the feature
        #
        LOGGER.info('setup_join. Step (9b): Publish the feature type')
        ft = cat.publish_featuretype(view_name, ds, layer.srs, srs=layer.srs)
        #ft = cat.publish_featuretype(double_view_name, ds, layer.srs, srs=layer.srs)

        LOGGER.info('setup_join. Step (9c): Save the feature type')
        cat.save(ft)

    except Exception as e:
        tj.delete()
        traceback.print_exc(sys.exc_info())
        err_msg = "Error creating GeoServer layer for %s: %s" % (view_name,
                                                                 str(e))
        LOGGER.error(err_msg)
        return None, err_msg

    # ------------------------------------------------------
    # Set the Layer's default Style
    # ------------------------------------------------------
    sld_success, err_msg = set_style_for_new_join_layer(cat, ft, layer)
    if not sld_success:
        return None, err_msg

    # ------------------------------------------------------------------
    # Create the Layer in GeoNode from the GeoServer Layer
    # ------------------------------------------------------------------
    LOGGER.info(
        'setup_join. Step (10): Create the Layer in GeoNode from the GeoServer Layer'
    )
    try:
        layer_params = {
            "workspace":
            workspace.name,
            "store":
            ds.name,
            "storeType":
            ds.resource_type,
            "typename":
            "%s:%s" %
            (workspace.name.encode('utf-8'), ft.name.encode('utf-8')),
            "title":
            dt.title or 'No title provided',
            "abstract":
            dt.abstract or 'No abstract provided',
            "uuid":
            str(uuid.uuid4()),
            "owner":
            new_table_owner,
            #"bbox_x0": Decimal(ft.latlon_bbox[0]),
            #"bbox_x1": Decimal(ft.latlon_bbox[1]),
            #"bbox_y0": Decimal(ft.latlon_bbox[2]),
            #"bbox_y1": Decimal(ft.latlon_bbox[3])
        }

        layer, created = Layer.objects.get_or_create(name=view_name,
                                                     defaults=layer_params)

        # Set default permissions (public)
        layer.set_default_permissions()
        #set_attributes(layer, overwrite=True)

        tj.join_layer = layer
        tj.save()
    except Exception as e:
        tj.delete()
        traceback.print_exc(sys.exc_info())
        err_msg = "Error creating GeoNode layer for %s: %s" % (view_name,
                                                               str(e))
        LOGGER.error(err_msg)
        return None, err_msg

    # ------------------------------------------------------------------
    # Create LayerAttributes for the new Layer (not done in GeoNode 2.x)
    # ------------------------------------------------------------------
    LOGGER.info(
        'setup_join. Step (11): Create Layer Attributes from the Datatable')
    (attributes_created,
     err_msg) = create_layer_attributes_from_datatable(dt, layer)
    if not attributes_created:
        LOGGER.error(err_msg)
        tj.delete()  # Delete the table join object
        return None, "Sorry there was an error creating the Datatable (s11)"

    return tj, ""
                 gn_to_gs_fix(layer, res, args.dry_run, creds, args.disable_ssl_verification)
             except Inconsistency as e:
                 logger.debug("Inconsistency found : %s" % e)
                 errors.append(e)
     # Layer groups TODO: not managed yet by gsconfig
     # lgroups = gscatalog.get_layergroups()
     # for lg in lgroups:
     #     gn_to_gs_fix(lg, args.dry_run, creds)
 # Workspace
 elif args.mode == "workspace":
     if args.item is None:
         print("Missing item option")
         parser.print_help()
         sys.exit()
     print_banner(args)
     workspace = gscatalog.get_workspace(name=args.item)
     if workspace is None:
         logger.error("workspace \"%s\" not found" % args.item)
         sys.exit()
     else:
         resources = gscatalog.get_resources(workspace=workspace)
         for res in resources:
             try:
                 layer = gscatalog.get_layer(res.workspace.name + ":" + res.name)
                 gn_to_gs_fix(layer, res, args.dry_run, creds, args.disable_ssl_verification)
             except Inconsistency as e:
                 errors.append(e)
 # Single layer
 else:
     # TODO: weird ... gsconfig.get_layer(name="...") returns always a layer, even if it does not exist ...
     # better off parsing every resources available ? What if the GS has a huge catalog ?
Beispiel #25
0
from geoserver.catalog import Catalog
import geoserver.util

cat = Catalog("http://localhost:9090/geoserver/rest/")
cat.username = "******"
cat.password = "******"

workspace = cat.get_workspace("fenix")
cat.create_coveragestore(
    "test_gsconfig2",
    "/home/vortex/Desktop/LAYERS/MOROCCO_MICHELA/to_publish/original/wheat_mask.tif",
    workspace)
layer = cat.get_layer("test_gsconfig2")
layer._set_default_style("mask")
cat.save(layer)
# print cat
# print "here"
# layer = cat.get_style("burg")
class CatalogTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog(GSPARAMS['GSURL'],
                           username=GSPARAMS['GSUSER'],
                           password=GSPARAMS['GSPASSWORD'])
        self.gs_version = self.cat.get_short_version()

    def testGSVersion(self):
        version = self.cat.get_version()
        pat = re.compile('\d\.\d+')
        self.assertTrue(pat.match('2.2.x'))
        self.assertTrue(pat.match('2.3.2'))
        self.assertTrue(pat.match('2.3-SNAPSHOT'))
        self.assertTrue(pat.match(version))

    def testWorkspaces(self):
        self.assertEqual(7, len(self.cat.get_workspaces()))
        # marking out test since geoserver default workspace is not consistent
        # self.assertEqual("cite", self.cat.get_default_workspace().name)
        self.assertEqual("topp",
                         self.cat.get_workspaces(names="topp")[-1].name)
        self.assertEqual(2,
                         len(self.cat.get_workspaces(names=['topp', 'sde'])))
        self.assertEqual(2, len(self.cat.get_workspaces(names='topp, sde')))
        self.assertEqual("topp", self.cat.get_workspace("topp").name)
        self.assertIsNone(self.cat.get_workspace("blahblah-"))

    def testStores(self):
        self.assertEqual(0, len(self.cat.get_stores(names="nonexistentstore")))
        topp = self.cat.get_workspaces("topp")[0]
        sf = self.cat.get_workspaces("sf")[0]
        self.assertEqual(9, len(self.cat.get_stores()))
        self.assertEqual(2, len(self.cat.get_stores(workspaces=topp)))
        self.assertEqual(2, len(self.cat.get_stores(workspaces=sf)))
        self.assertEqual(2, len(self.cat.get_stores(workspaces='sf')))
        self.assertEqual(
            2, len(self.cat.get_stores(names='states_shapefile, sfdem')))
        self.assertEqual(
            2, len(self.cat.get_stores(names=['states_shapefile', 'sfdem'])))
        self.assertEqual(
            "states_shapefile",
            self.cat.get_stores(names="states_shapefile",
                                workspaces=topp.name)[0].name)
        self.assertEqual("states_shapefile",
                         self.cat.get_stores(names="states_shapefile")[0].name)
        self.assertEqual(
            "sfdem",
            self.cat.get_stores(names="sfdem", workspaces=sf.name)[0].name)
        self.assertEqual("sfdem",
                         self.cat.get_store("sfdem", workspace="sf").name)
        self.assertIsNone(self.cat.get_store("blah+blah-"))

    def testResources(self):
        topp = self.cat.get_workspaces("topp")[0]
        sf = self.cat.get_workspaces("sf")[0]
        states = self.cat.get_stores(names="states_shapefile",
                                     workspaces=topp.name)[0]
        sfdem = self.cat.get_stores(names="sfdem", workspaces=sf.name)[0]
        self.assertEqual(19, len(self.cat.get_resources()))
        self.assertEqual(
            2,
            len(
                self.cat.get_resources(stores=[states.name, sfdem.name],
                                       workspaces=[topp.name, sf.name])))
        self.assertEqual(
            11, len(self.cat.get_resources(workspaces=[topp.name, sf.name])))

        self.assertEqual(
            "states",
            self.cat.get_resources(names="states",
                                   stores=states.name,
                                   workspaces=topp.name)[0].name)
        self.assertEqual(
            "states",
            self.cat.get_resources(names="states",
                                   workspaces=topp.name)[0].name)
        self.assertEqual(
            "states",
            self.cat.get_resource("states", workspace=topp.name).name)
        self.assertIsNone(self.cat.get_resource("blah+1blah-2"))

        states = self.cat.get_resources(names="states",
                                        workspaces=topp.name)[0]

        fields = [
            states.title, states.abstract, states.native_bbox,
            states.latlon_bbox, states.projection, states.projection_policy
        ]

        self.assertFalse(None in fields, str(fields))
        self.assertFalse(len(states.keywords) == 0)
        self.assertFalse(len(states.attributes) == 0)
        self.assertTrue(states.enabled)

        self.assertEqual(
            "sfdem",
            self.cat.get_resources(names="sfdem",
                                   stores=sfdem.name,
                                   workspaces=sf.name)[0].name)
        self.assertEqual(
            "sfdem",
            self.cat.get_resources(names="sfdem", workspaces=sf.name)[0].name)

    def testResourcesUpdate(self):
        res_dest = self.cat.get_resources()
        count = 0

        for rd in res_dest:
            # only wms layers
            if rd.resource_type != "wmsLayer":
                continue
            # looking for same name
            ro = self.cat.get_resources(names=rd.name)

            if ro is not None:
                rd.title = ro.title
                rd.abstract = ro.abstract
                rd.keywords = ro.keywords
                rd.projection = ro.projection
                rd.native_bbox = ro.native_bbox
                rd.latlon_bbox = ro.latlon_bbox
                rd.projection_policy = ro.projection_policy
                rd.enabled = ro.enabled
                rd.advertised = ro.advertised
                rd.metadata_links = ro.metadata_links or None

                self.cat.save(rd)
                self.cat.reload()
                count += 1

    def testLayers(self):
        if self.gs_version >= "2.13":
            expected = set([
                'sf:roads', 'sf:sfdem', 'nurc:mosaic', 'tiger:giant_polygon',
                'sf:bugsites', 'topp:states', 'sf:streams',
                'tiger:poly_landmarks', 'tiger:poi',
                'topp:tasmania_water_bodies', 'tiger:tiger_roads',
                'topp:tasmania_roads', 'nurc:Pk50095', 'topp:tasmania_cities',
                'nurc:Img_Sample', 'sf:restricted', 'nurc:Arc_Sample',
                'sf:archsites', 'topp:tasmania_state_boundaries'
            ])
        else:
            expected = set([
                "Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem",
                "bugsites", "restricted", "streams", "archsites", "roads",
                "tasmania_roads", "tasmania_water_bodies",
                "tasmania_state_boundaries", "tasmania_cities", "states",
                "poly_landmarks", "tiger_roads", "poi", "giant_polygon"
            ])

        actual = set(l.name for l in self.cat.get_layers())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (
            extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        states = self.cat.get_layer("states")

        self.assert_("states", states.name)
        self.assert_(isinstance(states.resource, ResourceInfo))
        self.assertEqual(set(s.name for s in states.styles),
                         set(['pophatch', 'polygon']))
        self.assertEqual(states.default_style.name, "population")

    def testLayerGroups(self):
        expected = set(["tasmania", "tiger-ny", "spearfish"])
        actual = set(l.name for l in self.cat.get_layergroups(
            names=["tasmania", "tiger-ny", "spearfish"]))
        missing = expected - actual
        extras = actual - expected
        message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (
            extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        tas = self.cat.get_layergroups(names="tasmania")[0]

        self.assert_("tasmania", tas.name)
        self.assert_(isinstance(tas, LayerGroup))
        if self.gs_version >= "2.13":
            self.assertEqual(tas.layers, [
                'topp:tasmania_state_boundaries', 'topp:tasmania_water_bodies',
                'topp:tasmania_roads', 'topp:tasmania_cities'
            ], tas.layers)
        else:
            self.assertEqual(tas.layers, [
                'tasmania_state_boundaries', 'tasmania_water_bodies',
                'tasmania_roads', 'tasmania_cities'
            ], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        # Try to create a new Layer Group into the "topp" workspace
        self.assert_(self.cat.get_workspaces("topp")[0] is not None)
        tas2 = self.cat.create_layergroup("tasmania_reloaded",
                                          tas.layers,
                                          workspace="topp")
        self.cat.save(tas2)
        self.assertEqual(
            1,
            len(
                self.cat.get_layergroups(names='tasmania_reloaded',
                                         workspaces="topp")))
        tas2 = self.cat.get_layergroups(names='tasmania_reloaded',
                                        workspaces="topp")[0]
        self.assert_("tasmania_reloaded", tas2.name)
        self.assert_(isinstance(tas2, LayerGroup))
        self.assertEqual(tas2.workspace, "topp", tas2.workspace)
        if self.gs_version >= "2.13":
            self.assertEqual(tas2.layers, [
                'topp:tasmania_state_boundaries', 'topp:tasmania_water_bodies',
                'topp:tasmania_roads', 'topp:tasmania_cities'
            ], tas2.layers)
        else:
            self.assertEqual(tas2.layers, [
                'tasmania_state_boundaries', 'tasmania_water_bodies',
                'tasmania_roads', 'tasmania_cities'
            ], tas2.layers)
        self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles)

    def testStyles(self):
        self.assertEqual("population",
                         self.cat.get_styles("population")[0].name)
        self.assertEqual("popshade.sld",
                         self.cat.get_styles("population")[0].filename)
        self.assertEqual("population",
                         self.cat.get_styles("population")[0].sld_name)
        self.assertEqual("population",
                         self.cat.get_style("population").sld_name)
        self.assertIsNone(self.cat.get_style("blah+#5blah-"))
        self.assertEqual(0, len(self.cat.get_styles('non-existing-style')))

    def testEscaping(self):
        # GSConfig is inconsistent about using exceptions vs. returning None
        # when a resource isn't found.
        # But the basic idea is that none of them should throw HTTP errors from
        # misconstructed URLS
        self.cat.get_styles("best style ever")
        self.cat.get_workspaces("best workspace ever")
        self.assertEqual(
            0,
            len(
                self.cat.get_stores(workspaces="best workspace ever",
                                    names="best store ever")))
        self.cat.get_layer("best layer ever")
        self.cat.get_layergroups("best layergroup ever")

    def testUnicodeUrl(self):
        """
        Tests that the geoserver.support.url function support unicode strings.
        """

        # Test the url function with unicode
        seg = [
            'workspaces', 'test', 'datastores', u'operaci\xf3n_repo',
            'featuretypes.xml'
        ]
        u = build_url(base=self.cat.service_url, seg=seg)
        self.assertEqual(
            u, self.cat.service_url +
            "/workspaces/test/datastores/operaci%C3%B3n_repo/featuretypes.xml")

        # Test the url function with normal string
        seg = [
            'workspaces', 'test', 'datastores', 'test-repo', 'featuretypes.xml'
        ]
        u = build_url(base=self.cat.service_url, seg=seg)
        self.assertEqual(
            u, self.cat.service_url +
            "/workspaces/test/datastores/test-repo/featuretypes.xml")
Beispiel #27
0
#!/usr/bin/env python

from geoserver.catalog import Catalog

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

native_bbox = \
    ['589434.856', '4914006.338', '609527.21', '4928063.398', 'EPSG:26713']
latlon_bbox = ['-103.877', '44.371', '-103.622', '44.5', 'EPSG:4326']

sf = cat.get_workspace('sf')
for rs in cat.get_resources(workspace=sf):
    rs.native_bbox = native_bbox
    rs.latlon_bbox = latlon_bbox
    cat.save(rs)
Beispiel #28
0
def gs_slurp(self, ignore_errors=True, verbosity=1, console=None, owner=None, workspace=None):
    """Configure the layers available in GeoServer in GeoNode.

       It returns a list of dictionaries with the name of the layer,
       the result of the operation and the errors and traceback if it failed.
    """
    if console is None:
        console = open(os.devnull, 'w')

    if verbosity > 1:
        print >> console, "Inspecting the available layers in GeoServer ..."
    url = "%srest" % settings.GEOSERVER_BASE_URL
    cat = Catalog(url, _user, _password)
    if workspace is not None:
        workspace = cat.get_workspace(workspace)
    resources = cat.get_resources(workspace=workspace)
    number = len(resources)
    if verbosity > 1:
        msg =  "Found %d layers, starting processing" % number
        print >> console, msg
    output = []
    for i, resource in enumerate(resources):
        name = resource.name
        store = resource.store
        workspace = store.workspace
        try:
            # Avoid circular import problem
            from geonode.layers.models import Layer
            layer, created = Layer.objects.get_or_create(name=name, defaults = {
                "workspace": workspace.name,
                "store": store.name,
                "storeType": store.resource_type,
                "typename": "%s:%s" % (workspace.name, resource.name),
                "title": resource.title or 'No title provided',
                "abstract": resource.abstract or 'No abstract provided',
                "owner": owner,
                "uuid": str(uuid.uuid4())
            })

            layer.save()
        except Exception, e:
            if ignore_errors:
                status = 'failed'
                exception_type, error, traceback = sys.exc_info()
            else:
                if verbosity > 0:
                    msg = "Stopping process because --ignore-errors was not set and an error was found."
                    print >> sys.stderr, msg
                raise Exception('Failed to process %s' % resource.name, e), None, sys.exc_info()[2]
        else:
            if created:
                layer.set_default_permissions()
                status = 'created'
            else:
                status = 'updated'

        msg = "[%s] Layer %s (%d/%d)" % (status, name, i+1, number)
        info = {'name': name, 'status': status}
        if status == 'failed':
            info['traceback'] = traceback
            info['exception_type'] = exception_type
            info['error'] = error
        output.append(info)
        if verbosity > 0:
            print >> console, msg
Beispiel #29
0
class GsConn:
    def __init__(self, host, login, password, debug=False):
        """
        Geoserver connection
        """
        self.host = host
        self.login = login
        self.password = password
        self.debug = debug

        # Connect to server
        self.cat = Catalog("http://%s/geoserver/rest" % host, login, password)
        if self.debug is True:
            print "Connected to geoserver"

    def crate_workspace(self, name, overwrite=False):
        """
        Creates a workspace
        :param name: Workspace name.
        :param overwrite: If True, delete existing workspace.
        :return: None
        """
        workspaces = [workspace.name for workspace in self.cat.get_workspaces()]

        if name in workspaces and overwrite is True:
            # ws2del = self.cat.get_workspace(name)
            # self.cat.delete(ws2del, purge=True, recurse=True)
            return None  # NOTE: If we delete the workspace then all associated layers are lost.
        elif name in workspaces and overwrite is False:
            print "ERROR: Workspace %s already exists (use overwrite=True)." % name

        self.cat.create_workspace(name, "http://%s/%s" % (self.host, name))
        if self.debug is True:
            print "Workspace %s available." % name

        ws = self.cat.get_workspace(name)
        ws.enabled = True

    def create_pg_store(self, name, workspace, host, port, login, password, dbname, schema, overwrite=False):
        """
        Creates datastore.
        :param name: Name of the datastore.
        :param workspace: Name of the workspace to use.
        :param overwrite: If True replace datastore.
        :return: None
        """
        stores = [store.name for store in self.cat.get_stores()]

        if name in stores and overwrite is True:
            # st2del = self.cat.get_store(name)
            # self.cat.delete(st2del, purge=True, recurse=True)
            # self.cat.reload()
            return None  # NOTE: If we delete store, every layers associated with are lost.
        elif name in stores and overwrite is False:
            print "ERROR: Store %s already exists (use overwrite=True)." % name

        ds = self.cat.create_datastore(name, workspace)
        ds.connection_parameters.update(
            host=host, port=port, user=login, passwd=password, dbtype="postgis", database=dbname, schema=schema
        )
        self.cat.save(ds)

        ds = self.cat.get_store(name)
        if ds.enabled is False:
            print "ERROR: Geoserver store %s not enabled" % name

        if self.debug is True:
            print "Datastore %s created." % name

    def publish_pg_layer(self, layer_table, layer_name, store, srid, overwrite=True):
        """
        """
        existing_lyr = self.cat.get_layer("ma_carte:%s" % layer_table)
        if existing_lyr is not None:
            print "Layer ma_carte:%s already exists, deleting it." % layer_table
            self.cat.delete(existing_lyr)
            self.cat.reload()

        ds = self.cat.get_store(store)
        ft = self.cat.publish_featuretype(layer_table, ds, "EPSG:%s" % srid, srs="EPSG:4326")
        ft.projection_policy = "REPROJECT_TO_DECLARED"
        ft.title = layer_name
        self.cat.save(ft)

        if ft.enabled is False:
            print "ERROR: Layer %s %s %s is not enabled."(ft.workspace.name, ft.store.name, ft.title)

        if self.debug is True:
            print "Layer %s>%s>%s published." % (ft.workspace.name, ft.store.name, ft.title)

    def create_style_from_sld(self, style_name, sld_file, workspace, overwrite=True):
        """
        """
        if self.cat.get_style(style_name) is not None:
            print "Style %s already exists, deleting it." % style_name
            style2del = self.cat.get_style(style_name)
            self.cat.delete(style2del)

        self.cat.create_style(
            style_name, open(sld_file).read(), overwrite=overwrite
        )  # FIXME: if ", workspace=workspace" specified can't delete style

        if self.debug is True:
            print "Style %s created in Geoserver" % style_name

    def apply_style_to_layer(self, layer_name, style_name):
        """
        Apply a geoserver styler to a layer
        """
        gs_layer = self.cat.get_layer(layer_name)
        gs_style = self.cat.get_style(style_name)

        # FIXME: Which works better?
        # gs_layer.default_style = gs_style / gs_layer._set_default_style(gs_style)
        # FIXME: Maybe indicate workspace when saving style then name the style as "workspace:style"
        gs_layer._set_default_style(gs_style)
        self.cat.save(gs_layer)

        if self.debug is True:
            print "Style applied to %s" % layer_name
Beispiel #30
0
#!/usr/bin/env python
"""
gsconfig is a python library for manipulating a GeoServer instance via the GeoServer RESTConfig API.

The project is distributed under a MIT License .
"""

__author__ = "David Winslow"
__copyright__ = "Copyright 2012-2015 Boundless, Copyright 2010-2012 OpenPlans"
__license__ = "MIT"

from geoserver.catalog import Catalog

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

ws = cat.get_workspace("sf")
resources = cat.get_resources(workspace=ws)
if len(resources) != 0:
    assert all(r.projection == "EPSG:27613" for r in resources), ws.name
Beispiel #31
0
class CatalogTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog("http://localhost:8080/geoserver/rest")

    def testAbout(self):
        about_html = self.cat.about()
        self.assertTrue('<html xmlns="http://www.w3.org/1999/xhtml"' in about_html)

    def testGSVersion(self):
        version = self.cat.gsversion()
        pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)')
        self.assertTrue(pat.match('2.2.x'))
        self.assertTrue(pat.match('2.3.2'))
        self.assertTrue(pat.match('2.3-SNAPSHOT'))
        self.assertFalse(pat.match('2.3.y'))
        self.assertFalse(pat.match('233'))
        self.assertTrue(pat.match(version))

    def testWorkspaces(self):
        self.assertEqual(7, len(self.cat.get_workspaces()))
        # marking out test since geoserver default workspace is not consistent 
        # self.assertEqual("cite", self.cat.get_default_workspace().name)
        self.assertEqual("topp", self.cat.get_workspace("topp").name)


    def testStores(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        self.assertEqual(9, len(self.cat.get_stores()))
        self.assertEqual(2, len(self.cat.get_stores(topp)))
        self.assertEqual(2, len(self.cat.get_stores(sf)))
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name)
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem").name)

  
    def testResources(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        states = self.cat.get_store("states_shapefile", topp)
        sfdem = self.cat.get_store("sfdem", sf)
        self.assertEqual(19, len(self.cat.get_resources()))
        self.assertEqual(1, len(self.cat.get_resources(states)))
        self.assertEqual(5, len(self.cat.get_resources(workspace=topp)))
        self.assertEqual(1, len(self.cat.get_resources(sfdem)))
        self.assertEqual(6, len(self.cat.get_resources(workspace=sf)))

        self.assertEqual("states", self.cat.get_resource("states", states).name)
        self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name)
        self.assertEqual("states", self.cat.get_resource("states").name)
        states = self.cat.get_resource("states")

        fields = [
            states.title,
            states.abstract,
            states.native_bbox,
            states.latlon_bbox,
            states.projection,
            states.projection_policy
        ]

        self.assertFalse(None in fields, str(fields))
        self.assertFalse(len(states.keywords) == 0)
        self.assertFalse(len(states.attributes) == 0)
        self.assertTrue(states.enabled)

        self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name)
        self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name)
        self.assertEqual("sfdem", self.cat.get_resource("sfdem").name)


    def testLayers(self):
        expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem",
            "bugsites", "restricted", "streams", "archsites", "roads",
            "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries",
            "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi",
            "giant_polygon"
        ])
        actual = set(l.name for l in self.cat.get_layers())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        states = self.cat.get_layer("states")

        self.assert_("states", states.name)
        self.assert_(isinstance(states.resource, ResourceInfo))
        self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon']))
        self.assertEqual(states.default_style.name, "population")

    def testLayerGroups(self):
        expected = set(["tasmania", "tiger-ny", "spearfish"])
        actual = set(l.name for l in self.cat.get_layergroups())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        tas = self.cat.get_layergroup("tasmania")

        self.assert_("tasmania", tas.name)
        self.assert_(isinstance(tas, LayerGroup))
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

    def testStyles(self):
        self.assertEqual(20, len(self.cat.get_styles()))
        self.assertEqual("population", self.cat.get_style("population").name)
        self.assertEqual("popshade.sld", self.cat.get_style("population").filename)
        self.assertEqual("population", self.cat.get_style("population").sld_name)

    def testEscaping(self):
        # GSConfig is inconsistent about using exceptions vs. returning None
        # when a resource isn't found.
        # But the basic idea is that none of them should throw HTTP errors from
        # misconstructed URLS
        self.cat.get_style("best style ever")
        self.cat.get_workspace("best workspace ever")
        self.cat.get_store(workspace="best workspace ever",
                name="best store ever")
        self.assertRaises(FailedRequestError,
            lambda: self.cat.get_resource(
                workspace="best workspace ever", store="best store ever",
                name="best resource ever"))
        self.cat.get_layer("best layer ever")
        self.cat.get_layergroup("best layergroup ever")

    def testUnicodeUrl(self):
        """
        Tests that the geoserver.support.url function support unicode strings.
        """

        # Test the url function with unicode
        seg = ['workspaces', 'test', 'datastores', u'operaci\xf3n_repo', 'featuretypes.xml']
        u = url(base=self.cat.service_url, seg=seg)
        self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/operaci%C3%B3n_repo/featuretypes.xml")

        # Test the url function with normal string
        seg = ['workspaces', 'test', 'datastores', 'test-repo', 'featuretypes.xml']
        u = url(base=self.cat.service_url, seg=seg)
        self.assertEqual(u, self.cat.service_url + "/workspaces/test/datastores/test-repo/featuretypes.xml")
class UploaderTests(TestCase):
    """Basic checks to make sure pages load, etc.
    """
    def create_datastore(self, connection, catalog):
        """Convenience method for creating a datastore.
        """
        settings = connection.settings_dict
        ds_name = settings['NAME']
        params = {
            'database': ds_name,
            'passwd': settings['PASSWORD'],
            'namespace': 'http://www.geonode.org/',
            'type': 'PostGIS',
            'dbtype': 'postgis',
            'host': settings['HOST'],
            'user': settings['USER'],
            'port': settings['PORT'],
            'enabled': 'True'
        }

        store = catalog.create_datastore(ds_name, workspace=self.workspace)
        store.connection_parameters.update(params)

        try:
            catalog.save(store)
        except FailedRequestError:
            # assuming this is because it already exists
            pass

        return catalog.get_store(ds_name)

    def create_user(self, username, password, **kwargs):
        """Convenience method for creating users.
        """
        user, created = User.objects.get_or_create(username=username, **kwargs)

        if created:
            user.set_password(password)
            user.save()

        return user

    def setUp(self):

        self.assertTrue(
            os.path.exists(_TEST_FILES_DIR),
            'Test could not run due to missing test data at {0!r}'.format(
                _TEST_FILES_DIR))

        # These tests require geonode to be running on :80!
        self.postgis = db.connections['datastore']
        self.postgis_settings = self.postgis.settings_dict

        self.admin_user = self.create_user('admin', 'admin', is_superuser=True)
        self.non_admin_user = self.create_user('non_admin', 'non_admin')
        self.catalog = Catalog(ogc_server_settings.internal_rest,
                               *ogc_server_settings.credentials)
        if self.catalog.get_workspace('geonode') is None:
            self.catalog.create_workspace('geonode', 'http://www.geonode.org/')
        self.workspace = 'geonode'
        self.datastore = self.create_datastore(self.postgis, self.catalog)

    def tearDown(self):
        """Clean up geoserver.
        """
        self.catalog.delete(self.datastore, recurse=True)

    def import_file(self, path, configs=None):
        """Imports the file.
        """
        if configs is None:
            configs = []
        self.assertTrue(os.path.exists(path))

        # run ogr2ogr
        ogr = OGRImport(path)
        layers = ogr.handle(configuration_options=configs)

        return layers

    def generic_import(self, filename, configs=None):
        if configs is None:
            configs = [{'index': 0}]

        path = test_file(filename)
        results = self.import_file(path, configs=configs)
        layer_results = []
        for result in results:
            if result[1].get('raster'):
                layer_path = result[0]
                layer_name = os.path.splitext(os.path.basename(layer_path))[0]
                layer = Layer.objects.get(name=layer_name)
                self.assertTrue(layer_path.endswith('.tif'))
                self.assertTrue(os.path.exists(layer_path))
                gdal_layer = gdal.OpenEx(layer_path)
                self.assertTrue(gdal_layer.GetDriver().ShortName, 'GTiff')
                layer_results.append(layer)
            else:
                layer = Layer.objects.get(name=result[0])
                self.assertEqual(layer.srid, 'EPSG:4326')
                self.assertEqual(layer.store, self.datastore.name)
                self.assertEqual(layer.storeType, 'dataStore')

                if not path.endswith('zip'):
                    self.assertGreaterEqual(layer.attributes.count(),
                                            DataSource(path)[0].num_fields)

                layer_results.append(layer)

        return layer_results[0]

    def generic_api_upload(self, filenames, configs=None):
        """Tests the import api.
        """
        client = AdminClient()
        client.login_as_non_admin()

        # Don't accidentally iterate over given 'foo' as ['f', 'o', 'o'].
        self.assertNotIsInstance(filenames, str)

        # Upload Files
        outfiles = []
        for filename in filenames:
            path = test_file(filename)
            with open(path) as stream:
                data = stream.read()
            upload = SimpleUploadedFile(filename, data)
            outfiles.append(upload)
        response = client.post(reverse('uploads-new-json'), {
            'file': outfiles,
            'json': json.dumps(configs)
        },
                               follow=True)
        content = json.loads(response.content)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(content['id'], 1)

        # Configure Uploaded Files
        upload_id = content['id']
        upload_layers = UploadLayer.objects.filter(upload_id=upload_id)

        for upload_layer in upload_layers:
            for config in configs:
                if config['upload_file_name'] == os.path.basename(
                        upload_layer.name):
                    payload = config['config']
                    url = '/importer-api/data-layers/{0}/configure/'.format(
                        upload_layer.id)
                    response = client.post(url,
                                           data=json.dumps(payload),
                                           content_type='application/json')
                    self.assertEqual(response.status_code, 200)
                    url = '/importer-api/data-layers/{0}/'.format(
                        upload_layer.id)
                    response = client.get(url, content_type='application/json')
                    self.assertEqual(response.status_code, 200)

        return content

    def generic_raster_import(self, filename, configs=None):
        if configs is None:
            configs = [{'index': 0}]

        path = test_file(filename)
        results = self.import_file(path, configs=configs)
        layer_path = results[0][0]
        layer_name = os.path.splitext(os.path.basename(layer_path))[0]
        layer = Layer.objects.get(name=layer_name)
        self.assertTrue(layer_path.endswith('.tif'))
        self.assertTrue(os.path.exists(layer_path))
        gdal_layer = gdal.OpenEx(layer_path)
        self.assertTrue(gdal_layer.GetDriver().ShortName, 'GTiff')
        return layer

    def test_multi_upload(self):
        """Tests Uploading Multiple Files
        """
        # Number of layers in each file
        upload_layer_counts = [1, 1, 1]
        upload = self.generic_api_upload(filenames=[
            'boxes_with_year_field.zip', 'boxes_with_date.zip',
            'point_with_date.geojson'
        ],
                                         configs=[{
                                             'upload_file_name':
                                             'boxes_with_year_field.shp',
                                             'config': [{
                                                 'index': 0
                                             }]
                                         }, {
                                             'upload_file_name':
                                             'boxes_with_date.shp',
                                             'config': [{
                                                 'index': 0
                                             }]
                                         }, {
                                             'upload_file_name':
                                             'point_with_date.geojson',
                                             'config': [{
                                                 'index': 0
                                             }]
                                         }])

        self.assertEqual(Layer.objects.count(), sum(upload_layer_counts))
        self.assertEqual(9, upload['count'])

    def test_upload_with_slds(self):
        """Tests Uploading sld
        """
        upload = self.generic_api_upload(
            filenames=['boxes_with_date.zip', 'boxes.sld', 'boxes1.sld'],
            configs=[{
                'upload_file_name':
                'boxes_with_date.shp',
                'config': [{
                    'index': 0,
                    'default_style': 'boxes.sld',
                    'styles': ['boxes.sld', 'boxes1.sld']
                }]
            }])
        self.assertEqual(6, upload['count'])
        upload_id = upload['id']
        uplayers = UploadLayer.objects.filter(upload=upload_id)
        layer_id = uplayers[0].pk

        upfiles_count = UploadFile.objects.filter(upload=upload_id).count()
        self.assertEqual(6, upfiles_count)

        # Warning: this assumes that Layer pks equal UploadLayer pks
        layer = Layer.objects.get(pk=layer_id)
        gslayer = self.catalog.get_layer(layer.name)
        default_style = gslayer.default_style
        # TODO: can we use public API or omit this?
        self.catalog._cache.clear()
        self.assertEqual('boxes.sld', default_style.filename)

    def test_upload_with_metadata(self):
        """Tests Uploading metadata
        """
        upload = self.generic_api_upload(filenames=[
            'boxes_with_date.zip',
            'samplemetadata.xml',
        ],
                                         configs=[{
                                             'upload_file_name':
                                             'boxes_with_date.shp',
                                             'config': [{
                                                 'index':
                                                 0,
                                                 'metadata':
                                                 'samplemetadata.xml'
                                             }]
                                         }])
        self.assertEqual(5, upload['count'])
        upload_id = upload['id']
        uplayers = UploadLayer.objects.filter(upload=upload_id)
        layer_id = uplayers[0].pk

        upfiles_count = UploadFile.objects.filter(upload=upload_id).count()
        self.assertEqual(5, upfiles_count)

        layer = Layer.objects.get(pk=layer_id)
        self.assertEqual(layer.language, 'eng')
        self.assertEqual(layer.title,
                         'Old_Americas_LSIB_Polygons_Detailed_2013Mar')

    def test_geotiff_raster(self):
        """Exercise GeoTIFF raster import.
        """
        layer = self.generic_raster_import('test_grid.tif',
                                           configs=[{
                                               'index': 0
                                           }])
        self.assertTrue(layer.name.startswith('test_grid'))

    def test_nitf_raster(self):
        """Tests NITF raster import
        """
        layer = self.generic_raster_import('test_nitf.nitf')
        self.assertTrue(layer.name.startswith('test_nitf'))

    def test_box_with_year_field(self):
        """Tests the import of test_box_with_year_field.
        """

        layer = self.generic_import('boxes_with_year_field.shp',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date']
                                    }])
        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_boxes_with_date(self):
        """Tests the import of test_boxes_with_date.
        """

        layer = self.generic_import('boxes_with_date.shp',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date'],
                                        'start_date': 'date',
                                        'configureTime': True
                                    }])

        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_boxes_with_date_gpkg(self):
        """Tests the import of test_boxes_with_date.gpkg.
        """

        layer = self.generic_import('boxes_with_date.gpkg',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date'],
                                        'start_date': 'date',
                                        'configureTime': True
                                    }])

        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_boxes_plus_raster_gpkg_by_index(self):
        """ Tests the import of multilayer vector + tile geopackage using index, treating tile layers
            as rasters.
            Tile layers are now treated by default as a distinct layer type.
            This test forces them to still be treated as rasters and should be
            removed once tests for vector/tile geopackage files are in place.
        """

        layer = self.generic_import('boxes_plus_raster.gpkg',
                                    configs=[
                                        {
                                            'index': 0,
                                            'convert_to_date': ['date'],
                                            'start_date': 'date',
                                            'configureTime': True
                                        },
                                        {
                                            'index': 1
                                        },
                                        {
                                            'index': 2
                                        },
                                        {
                                            'index': 3
                                        },
                                        {
                                            'index': 4
                                        },
                                        {
                                            'index': 5
                                        },
                                        {
                                            'index': 6,
                                            'layer_type': 'raster'
                                        },
                                        {
                                            'index': 7,
                                            'layer_type': 'raster'
                                        },
                                    ])

        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_boxes_with_date_csv(self):
        """Tests a CSV with WKT polygon.
        """

        layer = self.generic_import('boxes_with_date.csv',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date']
                                    }])
        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_csv_missing_features(self):
        """Test csv that has some rows without geoms and uses ISO-8859 (Latin 4) encoding.
        """

        self.generic_import('missing-features.csv', configs=[{'index': 0}])

    def test_boxes_with_iso_date(self):
        """Tests the import of test_boxes_with_iso_date.
        """

        layer = self.generic_import('boxes_with_date_iso_date.shp',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date']
                                    }])
        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_duplicate_imports(self):
        """Import the same layer twice to ensure file names increment properly.
        """
        path = test_file('boxes_with_date_iso_date.zip')
        ogr = OGRImport(path)
        layers1 = ogr.handle({'index': 0, 'name': 'test'})
        layers2 = ogr.handle({'index': 0, 'name': 'test'})

        self.assertEqual(layers1[0][0], 'test')
        self.assertEqual(layers2[0][0], 'test0')

    def test_launder(self):
        """Ensure the launder function works as expected.
        """
        self.assertEqual(launder('tm_world_borders_simpl_0.3'),
                         'tm_world_borders_simpl_0_3')
        self.assertEqual(launder('Testing#'), 'testing_')
        self.assertEqual(launder('   '), '_')

    def test_boxes_with_date_iso_date_zip(self):
        """Tests the import of test_boxes_with_iso_date.
        """

        layer = self.generic_import('boxes_with_date_iso_date.zip',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date']
                                    }])
        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_boxes_with_dates_bc(self):
        """Tests the import of test_boxes_with_dates_bc.
        """

        layer = self.generic_import('boxes_with_dates_bc.shp',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date']
                                    }])

        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_point_with_date(self):
        """Tests the import of point_with_date.geojson
        """

        layer = self.generic_import('point_with_date.geojson',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date']
                                    }])

        # OGR will name geojson layers 'ogrgeojson' we rename to the path basename
        self.assertTrue(layer.name.startswith('point_with_date'))
        date_attr = get_layer_attr(layer, 'date_as_date')
        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')

        configure_time(
            self.catalog.get_layer(layer.name).resource,
            attribute=date_attr.attribute,
        )
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def test_boxes_with_end_date(self):
        """Tests the import of test_boxes_with_end_date.

        This layer has a date and an end date field that are typed correctly.
        """

        layer = self.generic_import('boxes_with_end_date.shp',
                                    configs=[{
                                        'index':
                                        0,
                                        'convert_to_date': ['date', 'enddate'],
                                        'start_date':
                                        'date',
                                        'end_date':
                                        'enddate',
                                        'configureTime':
                                        True
                                    }])

        date_attr = get_layer_attr(layer, 'date_as_date')
        end_date_attr = get_layer_attr(layer, 'enddate_as_date')

        self.assertEqual(date_attr.attribute_type, 'xsd:dateTime')
        self.assertEqual(end_date_attr.attribute_type, 'xsd:dateTime')

        configure_time(self.catalog.get_layer(layer.name).resource,
                       attribute=date_attr.attribute,
                       end_attribute=end_date_attr.attribute)
        self.generic_time_check(layer,
                                attribute=date_attr.attribute,
                                end_attribute=end_date_attr.attribute)

    def test_us_states_kml(self):
        """Tests the import of us_states_kml.

        This layer has a date and an end date field that are typed correctly.
        """
        # TODO: Support time in kmls.
        layer = self.generic_import('us_states.kml', configs=[{'index': 0}])
        self.assertEqual(layer.name.lower(), "us_states")

    def test_mojstrovka_gpx(self):
        """Tests the import of mojstrovka.gpx.

        This layer has a date and an end date field that are typed correctly.
        """
        layer = self.generic_import('mojstrovka.gpx',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['time'],
                                        'configureTime': True
                                    }])
        date_attr = get_layer_attr(layer, 'time_as_date')
        self.assertEqual(date_attr.attribute_type, u'xsd:dateTime')

        configure_time(self.catalog.get_layer(layer.name).resource,
                       attribute=date_attr.attribute)
        self.generic_time_check(layer, attribute=date_attr.attribute)

    def generic_time_check(self, layer, attribute=None, end_attribute=None):
        """Convenience method to run generic tests on time layers.
        """
        # TODO: can we use public API or omit this?
        self.catalog._cache.clear()
        resource = self.catalog.get_resource(layer.name,
                                             store=layer.store,
                                             workspace=self.workspace)

        time_info = resource.metadata['time']
        self.assertEqual('LIST', time_info.presentation)
        self.assertEqual(True, time_info.enabled)
        self.assertEqual(attribute, time_info.attribute)
        self.assertEqual(end_attribute, time_info.end_attribute)

    def test_us_shootings_csv(self):
        """Tests the import of US_Shootings.csv.
        """
        if osgeo.gdal.__version__ < '2.0.0':
            self.skipTest('GDAL Version does not support open options')

        path = test_file('US_Shootings.csv')
        layer = self.generic_import(path,
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['Date']
                                    }])
        self.assertTrue(layer.name.startswith('us_shootings'))

        date_field = 'date'
        configure_time(self.catalog.get_layer(layer.name).resource,
                       attribute=date_field)
        self.generic_time_check(layer, attribute=date_field)

    def test_sitins(self):
        """Tests the import of US_Civil_Rights_Sitins0.csv
        """
        if osgeo.gdal.__version__ < '2.0.0':
            self.skipTest('GDAL Version does not support open options')
        layer = self.generic_import('US_Civil_Rights_Sitins0.csv',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['Date']
                                    }])
        self.assertEqual(layer.name.lower(), 'us_civil_rights_sitins0')

    def get_layer_names(self, path):
        """Gets layer names from a data source.
        """
        data_source = DataSource(path)
        return [layer.name for layer in data_source]

    def test_gdal_import(self):
        path = test_file('point_with_date.geojson')
        self.generic_import(path,
                            configs=[{
                                'index': 0,
                                'convert_to_date': ['date']
                            }])

    def test_wfs(self):
        """Tests the import from a WFS Endpoint
        """
        wfs = 'WFS:http://demo.geo-solutions.it/geoserver/tiger/wfs'
        ogr = OGRImport(wfs)
        configs = [
            {
                'layer_name': 'tiger:giant_polygon'
            },
            {
                'layer_name': 'tiger:poi'
            },
        ]
        layers = ogr.handle(configuration_options=configs)
        for result in layers:
            layer = Layer.objects.get(name=result[0])
            self.assertEqual(layer.srid, 'EPSG:4326')
            self.assertEqual(layer.store, self.datastore.name)
            self.assertEqual(layer.storeType, 'dataStore')

    def test_arcgisjson(self):
        """Tests the import from a WFS Endpoint
        """
        endpoint = 'http://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/FeatureServer/16/query'\
            '?where=objectid=326&outfields=*&f=json'
        ogr = OGRImport(endpoint)
        configs = [{'index': 0}]
        layers = ogr.handle(configuration_options=configs)
        for result in layers:
            layer = Layer.objects.get(name=result[0])
            self.assertEqual(layer.srid, 'EPSG:4326')
            self.assertEqual(layer.store, self.datastore.name)
            self.assertEqual(layer.storeType, 'dataStore')

    def test_file_add_view(self):
        """Tests the file_add_view.
        """
        client = AdminClient()

        # test login required for this view
        request = client.get(reverse('uploads-new'))
        self.assertEqual(request.status_code, 302)

        client.login_as_non_admin()

        with open(test_file('point_with_date.geojson')) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context['request'].path,
                         reverse('uploads-list'))
        self.assertEqual(len(response.context['object_list']), 1)
        upload = response.context['object_list'][0]
        self.assertEqual(upload.user.username, 'non_admin')
        self.assertEqual(upload.file_type, 'GeoJSON')
        self.assertTrue(upload.uploadlayer_set.all())
        self.assertEqual(upload.state, 'UPLOADED')
        self.assertIsNotNone(upload.name)

        uploaded_file = upload.uploadfile_set.first()
        self.assertTrue(os.path.exists(uploaded_file.file.path))

        with open(test_file('empty_file.geojson')) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        self.assertEqual(response.status_code, 200)
        self.assertIn('file', response.context_data['form'].errors)

    def test_file_add_view_as_json(self):
        """Tests the file_add_view.
        """
        client = AdminClient()
        client.login_as_non_admin()

        with open(test_file('point_with_date.geojson')) as stream:
            response = client.post(reverse('uploads-new-json'),
                                   {'file': stream},
                                   follow=True)

        self.assertEqual(response.status_code, 200)
        self.assertIn('application/json', response.get('Content-Type', ''))
        content = json.loads(response.content)
        self.assertIn('state', content)
        self.assertIn('id', content)

    def test_describe_fields(self):
        """Tests the describe fields functionality.
        """
        path = test_file('US_Shootings.csv')
        with GDALInspector(path) as inspector:
            layers = inspector.describe_fields()

        self.assertTrue(layers[0]['layer_name'], 'us_shootings')
        self.assertEqual([n['name'] for n in layers[0]['fields']], [
            'Date', 'Shooter', 'Killed', 'Wounded', 'Location', 'City',
            'Longitude', 'Latitude'
        ])
        self.assertEqual(layers[0]['feature_count'], 203)

    def test_gdal_file_type(self):
        """Tests the describe fields functionality.
        """
        filenames = {
            'US_Shootings.csv': {'CSV'},
            'point_with_date.geojson': {'GeoJSON'},
            'mojstrovka.gpx': {'GPX'},
            'us_states.kml': {'LIBKML', 'KML'},
            'boxes_with_year_field.shp': {'ESRI Shapefile'},
            'boxes_with_date_iso_date.zip': {'ESRI Shapefile'}
        }
        from osgeo_importer.models import NoDataSourceFound
        try:
            for filename, file_type in sorted(filenames.items()):
                path = test_file(filename)
                with GDALInspector(path) as inspector:
                    self.assertIn(inspector.file_type(), file_type)
        except NoDataSourceFound:
            logging.exception('No data source found in: {0}'.format(path))
            raise

    def test_configure_view(self):
        """Tests the configuration view.
        """
        path = test_file('point_with_date.geojson')
        new_user = User.objects.create(username='******')
        new_user_perms = ['change_resourcebase_permissions']
        client = AdminClient()
        client.login_as_non_admin()

        with open(path) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        upload = response.context['object_list'][0]

        payload = [{
            'index': 0,
            'convert_to_date': ['date'],
            'start_date': 'date',
            'configureTime': True,
            'editable': True,
            'permissions': {
                'users': {
                    'test':
                    new_user_perms,
                    'AnonymousUser': [
                        'change_layer_data', 'download_resourcebase',
                        'view_resourcebase'
                    ]
                }
            }
        }]
        response = client.post(
            '/importer-api/data-layers/{0}/configure/'.format(upload.id),
            data=json.dumps(payload),
            content_type='application/json')

        self.assertTrue(response.status_code, 200)

        first_layer = Layer.objects.all()[0]
        self.assertEqual(first_layer.srid, 'EPSG:4326')
        self.assertEqual(first_layer.store, self.datastore.name)
        self.assertEqual(first_layer.storeType, 'dataStore')
        self.assertTrue(first_layer.attributes[1].attribute_type,
                        'xsd:dateTime')
        self.assertEqual(Layer.objects.all()[0].owner.username,
                         self.non_admin_user.username)

        perms = first_layer.get_all_level_info()
        user = User.objects.get(username=self.non_admin_user.username)

        # check user permissions
        expected_perms = [
            u'publish_resourcebase', u'change_resourcebase_permissions',
            u'delete_resourcebase', u'change_resourcebase',
            u'change_resourcebase_metadata', u'download_resourcebase',
            u'view_resourcebase', u'change_layer_style', u'change_layer_data'
        ]
        for perm in expected_perms:
            self.assertIn(perm, perms['users'][user])

        self.assertTrue(perms['users'][new_user])
        self.assertIn('change_resourcebase_permissions',
                      perms['users'][new_user])
        self.assertIn(
            'change_layer_data',
            perms['users'][User.objects.get(username='******')])

        catalog_layer = self.catalog.get_layer(first_layer.name)
        self.assertIn('time', catalog_layer.resource.metadata)
        self.assertEqual(UploadLayer.objects.first().layer, first_layer)

    def test_configure_view_convert_date(self):
        """Tests the configure view with a dataset that needs to be converted to a date.
        """
        client = AdminClient()
        client.login_as_non_admin()

        with open(test_file('US_Shootings.csv')) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        upload = response.context['object_list'][0]

        payload = [{
            'index': 0,
            'convert_to_date': ['Date'],
            'start_date': 'Date',
            'configureTime': True,
            'editable': True
        }]

        response = client.get(
            '/importer-api/data-layers/{0}/configure/'.format(upload.id))
        self.assertEqual(response.status_code, 405)

        response = client.post(
            '/importer-api/data-layers/{0}/configure/'.format(upload.id))
        self.assertEqual(response.status_code, 400)

        response = client.post(
            '/importer-api/data-layers/{0}/configure/'.format(upload.id),
            data=json.dumps(payload),
            content_type='application/json')
        self.assertTrue(response.status_code, 200)

        first_layer = Layer.objects.all()[0]
        self.assertEqual(first_layer.srid, 'EPSG:4326')
        self.assertEqual(first_layer.store, self.datastore.name)
        self.assertEqual(first_layer.storeType, 'dataStore')
        self.assertTrue(first_layer.attributes[1].attribute_type,
                        'xsd:dateTime')
        self.assertTrue(first_layer.attributes.filter(attribute='date'),
                        'xsd:dateTime')

        catalog_layer = self.catalog.get_layer(first_layer.name)
        self.assertIn('time', catalog_layer.resource.metadata)

        # ensure a user who does not own the upload cannot configure an import from it.
        client.logout()
        client.login_as_admin()
        response = client.post(
            '/importer-api/data-layers/{0}/configure/'.format(upload.id))
        self.assertEqual(response.status_code, 404)

    def test_list_api(self):
        client = AdminClient()

        response = client.get('/importer-api/data/')
        self.assertEqual(response.status_code, 401)

        client.login_as_non_admin()

        response = client.get('/importer-api/data/')
        self.assertEqual(response.status_code, 200)

        admin = User.objects.get(username=self.admin_user.username)
        non_admin = User.objects.get(username=self.non_admin_user.username)

        path = test_file('US_Shootings.csv')
        with open(path, 'rb') as stream:
            uploaded_file = SimpleUploadedFile('test_data', stream.read())
            admin_upload = UploadedData.objects.create(state='Admin test',
                                                       user=admin)
            admin_upload.uploadfile_set.add(
                UploadFile.objects.create(file=uploaded_file))

            non_admin_upload = UploadedData.objects.create(
                state='Non admin test', user=non_admin)
            non_admin_upload.uploadfile_set.add(
                UploadFile.objects.create(file=uploaded_file))

        client.login_as_admin()
        response = client.get('/importer-api/data/')
        self.assertEqual(response.status_code, 200)
        body = json.loads(response.content)
        self.assertEqual(len(body['objects']), 2)

        response = client.get('/importer-api/data/?user__username=admin')
        self.assertEqual(response.status_code, 200)
        body = json.loads(response.content)
        self.assertEqual(len(body['objects']), 1)

    def test_layer_list_api(self):
        client = AdminClient()
        response = client.get('/importer-api/data-layers/')
        self.assertEqual(response.status_code, 401)

        client.login_as_non_admin()

        response = client.get('/importer-api/data-layers/')
        self.assertEqual(response.status_code, 200)

    def test_delete_from_non_admin_api(self):
        """Ensure users can delete their data.
        """
        client = AdminClient()

        client = AdminClient()
        client.login_as_non_admin()

        with open(test_file('point_with_date.geojson')) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        self.assertEqual(UploadedData.objects.all().count(), 1)
        upload_id = UploadedData.objects.first().id
        response = client.delete('/importer-api/data/{0}/'.format(upload_id))
        self.assertEqual(response.status_code, 204)

        self.assertEqual(UploadedData.objects.all().count(), 0)

    def test_delete_from_admin_api(self):
        """Ensure that administrators can delete data that isn't theirs.
        """
        client = AdminClient()
        client.login_as_non_admin()

        with open(test_file('point_with_date.geojson')) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        self.assertEqual(UploadedData.objects.all().count(), 1)

        client.logout()
        client.login_as_admin()

        upload_id = UploadedData.objects.first().id
        response = client.delete('/importer-api/data/{0}/'.format(upload_id))

        self.assertEqual(response.status_code, 204)

        self.assertEqual(UploadedData.objects.all().count(), 0)

    def naming_an_import(self):
        """Tests providing a name in the configuration options.
        """
        client = AdminClient()
        client.login_as_non_admin()
        name = 'point-with-a-date'
        with open(test_file('point_with_date.geojson')) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        payload = {
            'index': 0,
            'convert_to_date': ['date'],
            'start_date': 'date',
            'configureTime': True,
            'name': name,
            'editable': True
        }
        response = client.post('/importer-api/data-layers/1/configure/',
                               data=json.dumps(payload),
                               content_type='application/json')
        self.assertEqual(response.status_code, 200)

        first_layer = Layer.objects.all()[0]
        self.assertEqual(first_layer.title, name.replace('-', '_'))

    def test_api_import(self):
        """Tests the import api.
        """
        client = AdminClient()
        client.login_as_non_admin()

        with open(test_file('point_with_date.geojson')) as stream:
            response = client.post(reverse('uploads-new'), {'file': stream},
                                   follow=True)

        payload = {
            'index': 0,
            'convert_to_date': ['date'],
            'start_date': 'date',
            'configureTime': True,
            'editable': True
        }

        self.assertIsInstance(
            UploadLayer.objects.first().configuration_options, dict)

        response = client.get('/importer-api/data-layers/1/')
        self.assertEqual(response.status_code, 200)

        response = client.post('/importer-api/data-layers/1/configure/',
                               data=json.dumps([payload]),
                               content_type='application/json')
        self.assertEqual(response.status_code, 200)
        self.assertIn('task', response.content)

        first_layer = Layer.objects.all()[0]
        self.assertEqual(first_layer.srid, 'EPSG:4326')
        self.assertEqual(first_layer.store, self.datastore.name)
        self.assertEqual(first_layer.storeType, 'dataStore')
        self.assertTrue(first_layer.attributes[1].attribute_type,
                        'xsd:dateTime')

        catalog_layer = self.catalog.get_layer(first_layer.name)
        self.assertIn('time', catalog_layer.resource.metadata)
        self.assertEqual(UploadLayer.objects.first().layer, first_layer)
        self.assertTrue(UploadLayer.objects.first().task_id)

    def test_valid_file_extensions(self):
        """Test the file extension validator.
        """

        for extension in load_handler(OSGEO_IMPORTER,
                                      'test.txt').valid_extensions:
            filename = 'test.{0}'.format(extension)
            upload = SimpleUploadedFile(filename, '')
            self.assertIsNone(validate_file_extension(upload))

        with self.assertRaises(ValidationError):
            validate_file_extension(SimpleUploadedFile('test.txt', ''))

    def test_no_geom(self):
        """Test the file extension validator.
        """

        with self.assertRaises(ValidationError):
            validate_inspector_can_read(
                SimpleUploadedFile('test.csv', 'test,loc\nyes,POINT(0,0)'))

        # This should pass (geom type is unknown)
        validate_inspector_can_read(
            SimpleUploadedFile('test.csv', 'test,WKT\nyes,POINT(0,0)'))

    def test_numeric_overflow(self):
        """Regression test for numeric field overflows in shapefiles.

        # https://trac.osgeo.org/gdal/ticket/5241
        """
        self.generic_import('Walmart.zip',
                            configs=[{
                                'configureTime': False,
                                'convert_to_date': ['W1_OPENDAT'],
                                'editable': True,
                                'index': 0,
                                'name': 'Walmart',
                                'start_date': 'W1_OPENDAT'
                            }])

    def test_multipolygon_shapefile(self):
        """Tests shapefile with multipart polygons.
        """

        self.generic_import('PhoenixFirstDues.zip', configs=[{'index': 0}])

    def test_istanbul(self):
        """Tests shapefile with multipart polygons and non-WGS84 SR.
        """
        result = self.generic_import('Istanbul.zip', configs=[{'index': 0}])
        feature_type = self.catalog.get_resource(result.name)
        self.assertEqual(feature_type.projection, 'EPSG:32635')

    def test_houston_tx_annexations(self):
        """Tests Shapefile with originally unsupported EPSG Code.
        """
        result = self.generic_import('HoustonTXAnnexations.zip',
                                     configs=[{
                                         'index': 0
                                     }])
        feature_type = self.catalog.get_resource(result.name)
        self.assertEqual(feature_type.projection, 'EPSG:2278')

    def test_gwc_handler(self):
        """Tests the GeoWebCache handler
        """
        layer = self.generic_import('boxes_with_date.shp',
                                    configs=[{
                                        'index': 0,
                                        'convert_to_date': ['date'],
                                        'start_date': 'date',
                                        'configureTime': True
                                    }])

        gwc = GeoWebCacheHandler(None)
        gs_layer = self.catalog.get_layer(layer.name)

        self.assertTrue(gwc.time_enabled(gs_layer))
        gs_layer.fetch()

        payload = self.catalog.http.request(gwc.gwc_url(gs_layer))
        self.assertIn('regexParameterFilter', payload[1])
        self.assertEqual(int(payload[0]['status']), 200)

        # Don't configure time, ensure everything still works
        layer = self.generic_import('boxes_with_date_iso_date.shp',
                                    configs=[{
                                        'index': 0
                                    }])
        gs_layer = self.catalog.get_layer(layer.name)
        self.catalog._cache.clear()
        gs_layer.fetch()

        payload = self.catalog.http.request(gwc.gwc_url(gs_layer))
        self.assertNotIn('regexParameterFilter', payload[1])
        self.assertEqual(int(payload[0]['status']), 200)

    def test_utf8(self):
        """Tests utf8 characters in attributes
        """
        path = test_file('china_provinces.shp')
        layer = self.generic_import(path)
        ogr = OGRImport(path)
        datastore, _ = ogr.open_target_datastore(ogr.target_store)
        sql = ("select NAME_CH from {0} where NAME_PY = 'An Zhou'".format(
            layer.name))
        result = datastore.ExecuteSQL(sql)
        feature = result.GetFeature(0)
        self.assertEqual(feature.GetField('name_ch'), '安州')

    def test_non_converted_date(self):
        """Test converting a field as date.
        """
        results = self.generic_import('TM_WORLD_BORDERS_2005.zip',
                                      configs=[{
                                          'index': 0,
                                          'start_date': 'Year',
                                          'configureTime': True
                                      }])
        layer = self.catalog.get_layer(results.typename)
        self.assertIn('time', layer.resource.metadata)
        self.assertEqual('year', layer.resource.metadata['time'].attribute)

    def test_fid_field(self):
        """
        Regression test for preserving an FID field when target layer supports
        it but source does not.
        """
        self.generic_import('noaa_paleoclimate.zip', configs=[{'index': 0}])

    def test_csv_with_wkb_geometry(self):
        """Exercise import of CSV files with multiple geometries.
        """
        filenames = [
            'police_csv.csv', 'police_csv_nOGC.csv', 'police_csv_noLatLon.csv',
            'police_csv_WKR.csv', 'police_csv_nFID.csv',
            'police_csv_nOGFID.csv', 'police_csv_noWKB.csv'
        ]

        for filename in filenames:
            self.generic_import(
                filename, {
                    'configureTime': True,
                    'convert_to_date': ['date_time'],
                    'editable': True,
                    'index': 0,
                    'name': filename.lower(),
                    'permissions': {
                        'users': {
                            'AnonymousUser': [
                                'change_layer_data', 'download_resourcebase',
                                'view_resourcebase'
                            ]
                        }
                    },
                    'start_date': 'date_time',
                })
Beispiel #33
0
class wrap_geoserver:
    """ Geoserver (gsconfig) wrapper """
    def __init__(self,
                 geoserver_name,
                 username=None,
                 password=None,
                 easy=False):
        if geoserver_name in list(REST.keys()):
            self.path = REST[geoserver_name]
        else:
            self.path = geoserver_name
        self.wms = self.path.replace("rest/", "wms")

        self.name = geoserver_name
        self.catalog = Catalog(self.path, username, password)

        if not easy:
            self.layers = []
            self.layer_names = []

            for layer in self.catalog.get_layers():
                self.layers.append(layer)
                self.layer_names.append(layer.name)

            self.stores = [store for store in self.catalog.get_stores()]
            self.store_names = [store.name for store in self.stores]

            styles = []
            self.workspaces = []
            self.workspace_names = []

            for workspace in self.catalog.get_workspaces():
                styles = styles + self.catalog.get_styles(workspace)
                self.workspace_names.append(workspace._name)
                self.workspaces.append(workspace)

            self.styles = styles + [
                style for style in self.catalog.get_styles()
            ]
            self.style_names = [style.name for style in self.styles]

    def unpack(self, workspace_name, store_type="datastore"):
        layers_and_styles = {}
        features = []
        workspace = self.get_workspace(workspace_name)

        if store_type == "datastore":
            store_url = workspace.datastore_url
        elif store_type == "coveragestore":
            store_url = workspace.coveragestore_url
        else:
            print("No correct store given")

        for datastore in tqdm(get(store_url, "name")):
            url = "{}workspaces/{}/datastores/{}".format(
                self.path, workspace.name, datastore)
            features = features + get(url, between_quotes=True)

        for feature in features:
            layer_name = os.path.basename(feature).split(".")[0]
            self.get_layer(self.get_slug(workspace.name, layer_name))
            layers_and_styles[layer_name] = self.layer.default_style

        setattr(self, workspace_name + "_data", layers_and_styles)
        return layers_and_styles

    def get_layer(self, layer, easy=False):
        self.layer = self.catalog.get_layer(layer)

        if not easy:
            self.resource = self.layer.resource
            self.layer_name = self.layer.resource.name
            self.sld_name = self.layer.default_style.name
            self.sld_body = self.layer.default_style.sld_body
            self.layer_latlon_bbox = self.layer.resource.latlon_bbox
            self.layer_title = self.layer.resource.title
            self.layer_abstract = self.layer.resource.abstract

    def get_store(self, layer):
        self.store = self.layer.resource._store

    def get_resource(self):
        self.resource = self.catalog.get_resource(self.layer.name, self.store)

    def get_workspace(self, workspace_name):
        self.workspace = self.catalog.get_workspace(workspace_name)
        self.workspace_name = self.workspace._name
        return self.workspace

    def write_abstract(self, data, load_resource=True):
        if load_resource:
            self.get_resource()
        self.resource.abstract = data
        self.catalog.save(self.resource)

    def write_title(self, title):
        self.resource.title = title
        self.catalog.save(self.resource)

    def get_connection_parameters(self):
        self.get_resource()
        return self.resource.store.connection_parameters

    def create_workspace(self, workspace_name):
        workspace_exists = workspace_name in self.workspace_names

        if not workspace_exists:
            self.workspace = self.catalog.create_workspace(workspace_name)

        else:
            print("workspace already exists, using existing workspace")

        self.workspace = self.catalog.get_workspace(workspace_name)
        self.workspace_name = workspace_name

    def create_postgis_datastore(self, store_name, workspace_name, pg_data):

        try:
            self.store = self.catalog.get_store(store_name,
                                                self.workspace_name)
            print("store within workspace exists, using existing store")

        except Exception as e:
            print(e)

            ds = self.catalog.create_datastore(store_name, workspace_name)
            ds.connection_parameters.update(
                host=pg_data["host"],
                port=pg_data["port"],
                database=pg_data["database"],
                user=pg_data["username"],
                passwd=pg_data["password"],
                dbtype="postgis",
                schema="public",
            )

            self.save(ds)
            self.store = self.catalog.get_store(store_name,
                                                self.workspace_name)
            self.store_name = store_name

    def publish_layer(self,
                      layer_name,
                      workspace_name,
                      overwrite=False,
                      epsg="3857",
                      reload=False):

        layer_exists = layer_name in self.layer_names
        # if layer_name in self.workspace_layers[workspace_name]:
        slug = self.get_slug(workspace_name, layer_name)
        if overwrite and layer_exists:
            print("Layer exists, deleting layer")
            try:

                self.layer = self.catalog.get_layer(slug)
                self.delete(self.layer)
                self.reload()

                layer_exists = False

            except Exception as e:
                print(e)
                print("Layer does not exist in workspace")
                layer_exists = False

        if not layer_exists:

            feature_type = self.catalog.publish_featuretype(
                layer_name,
                self.store,
                "EPSG:{}".format(str(epsg)),
                srs="EPSG:{}".format(str(epsg)),
            )
            self.save(feature_type)
            self.feature_type = feature_type

        else:
            print("layer already exists, using existing layer")

        if reload:
            self.get_layer(slug)

        self.layer_name = layer_name

    def publish_layergroup(self,
                           name,
                           layers,
                           styles=(),
                           bounds=None,
                           workspace=None):
        layer_group = self.catalog.create_layergroup(name, layers, styles,
                                                     bounds, workspace)
        self.save(layer_group)

    def save(self, save_object):
        return self.catalog.save(save_object)

    def close(self):
        self.catalog = None

    def delete(self, delete_object):
        self.catalog.delete(delete_object)

    def reload(self):
        self.catalog.reload()

    def upload_shapefile(self, layer_name, shapefile_path):
        path = shapefile_path.split(".shp")[0]
        shapefile = shapefile_and_friends(path)
        ft = self.catalog.create_featurestore(layer_name, shapefile,
                                              self.workspace)
        self.save(ft)

    def upload_sld(self, sld_name, workspace_name, sld, overwrite=True):
        style_exists = sld_name in self.style_names

        if overwrite and style_exists:
            print("Overwriting style")
            style = self.catalog.get_style(sld_name, workspace_name)
            self.delete(style)
            self.reload()
            style_exists = False

        if not style_exists:
            try:
                self.catalog.create_style(sld_name, sld, False, workspace_name,
                                          "sld11")
            except Exception as e:
                print(e)

                style = self.catalog.get_style(sld_name, workspace_name)
                self.delete(style)
                self.reload()
                self.catalog.create_style(sld_name, sld, False, workspace_name,
                                          "sld10")
            self.style_name = sld_name

        else:
            if style_exists:
                print("Style already exists, using current style")
                self.style_name = sld_name

    def set_sld_for_layer(self,
                          workspace_name=None,
                          style_name=None,
                          use_custom=False):
        if not use_custom:
            workspace_name = self.workspace_name
            style_name = self.style_name
            self.style_slug = self.get_slug(workspace_name, style_name)

        else:
            if workspace_name is None:
                self.style_slug = style_name
            else:
                self.style_slug = self.get_slug(workspace_name, style_name)

        self.style = self.catalog.get_style(self.style_slug)

        print("Setting {} for {}".format(self.style.name, self.layer.name))
        self.layer.default_style = self.style
        self.save(self.layer)

    def get_slug(self, workspace, name):
        return "{}:{}".format(workspace, name)

    def get_slug_data(self, slug):
        workspace_name = slug.split(":")[0]
        layer_name = slug.split(":")[1]
        return workspace_name, layer_name

    def get_sld(self, layer_slug=None):
        if layer_slug is None:
            self.style = self.catalog.get_style(self.layer_slug)
        else:
            self.style = self.catalog.get_style(layer_slug)

        self.sld_body = self.style.sld_body
        return self.sld_body

    def get_layer_workspace(self, layer_name):
        return self.catalog.get_layer(layer_name).resource.workspace.name
Beispiel #34
0
def createDataStore(name, filename, format="shapefile"):
    cat = Catalog("{0}/rest/".format(geoserver_connection), geoserver_username,
                  geoserver_password)
    ws = cat.get_workspace(workspace)
    msg = ""
    if format == "shapefile":
        shapefile = shapefile_and_friends(filename)
        try:
            cat.create_featurestore(name, shapefile, workspace)
        except ConflictingDataError as inst:
            msg = str(inst)
        except:
            raise
        resource = cat.get_resource(name, workspace=ws)
        resource.projection = 'EPSG:4326'
        cat.save(resource)
        resource.projection_policy = 'REPROJECT_TO_DECLARED'
        cat.save(resource)
        resource.refresh()
        bbox = resource.latlon_bbox[:4]
        solr_geom = 'ENVELOPE({0},{1},{2},{3})'.format(bbox[0], bbox[1],
                                                       bbox[3], bbox[2])
        return {
            "solr_geom": solr_geom,
            "msg": msg,
            "resource_type": resource.resource_type
        }
    elif format == "image":
        if cat.get_store(name):
            newcs = cat.get_store(name, workspace=ws)
            msg = "Geoserver datastore already existed. Update existing datastore."
        else:
            newcs = cat.create_coveragestore2(name, ws)
        newcs.type = "GeoTIFF"
        newcs.url = filename
        cat.save(newcs)
        # add coverage
        url = "{0}/rest/workspaces/{1}/coveragestores/{2}/coverages.json"
        url = url.format(geoserver_connection, ws.name, name)
        headers = {"Content-Type": "application/json"}
        coverageName = os.path.splitext(os.path.basename(filename))[0]
        postdata = {
            "coverage": {
                "nativeCoverageName": coverageName,
                "name": coverageName,
                'projectionPolicy': 'REPROJECT_TO_DECLARED',
                'srs': 'EPSG:4326'
            }
        }
        requests.post(url,
                      json.dumps(postdata),
                      headers=headers,
                      auth=(geoserver_username, geoserver_password))
        # Reproject
        resource = cat.get_resource(name, workspace=ws)
        url = "{0}/rest/workspaces/{1}/coveragestores/{2}/coverages/{2}?{3}"
        parameters = "recalculate=nativebbox,latlonbbox"
        url = url.format(geoserver_connection, ws.name, name, parameters)
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        requests.post(url,
                      headers=headers,
                      auth=(geoserver_username, geoserver_password))
        # resource.refresh()
        bbox = resource.latlon_bbox[:4]
        solr_geom = 'ENVELOPE({0},{1},{2},{3})'.format(bbox[0], bbox[1],
                                                       bbox[3], bbox[2])
        return {
            "solr_geom": solr_geom,
            "msg": msg,
            "resource_type": resource.resource_type
        }
    return True
Beispiel #35
0
def _register_cascaded_service(url, type, name, username, password, wms=None, owner=None, parent=None):
    """
    Register a service as cascading WMS
    """

    try:
        service = Service.objects.get(base_url=url)
        return_dict = {}
        return_dict['service_id'] = service.pk
        return_dict['msg'] = "This is an existing Service"
        return HttpResponse(json.dumps(return_dict),
                            mimetype='application/json',
                            status=200)
    except:
        # TODO: Handle this error properly
        pass

    if wms is None:
        wms = WebMapService(url)
    # TODO: Make sure we are parsing all service level metadata
    # TODO: Handle for setting ServiceProfiletRole
    service = Service.objects.create(base_url=url,
                                     type=type,
                                     method='C',
                                     name=name,
                                     version=wms.identification.version,
                                     title=wms.identification.title,
                                     abstract=wms.identification.abstract,
                                     online_resource=wms.provider.url,
                                     owner=owner,
                                     parent=parent)

    service.keywords = ','.join(wms.identification.keywords)
    service.save()
    service.set_default_permissions()

    if type in ['WMS', 'OWS']:
        # Register the Service with GeoServer to be cascaded
        cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest",
                      _user, _password)
        cascade_ws = cat.get_workspace(name)
        if cascade_ws is None:
            cascade_ws = cat.create_workspace(
                name, "http://geonode.org/" + name)

        # TODO: Make sure there isn't an existing store with that name, and
        # deal with it if there is

        try:
            cascade_store = cat.get_store(name, cascade_ws)
        except:
            cascade_store = cat.create_wmsstore(
                name, cascade_ws, username, password)
            cascade_store.capabilitiesURL = url
            cascade_store.type = "WMS"
            cat.save(cascade_store)
        available_resources = cascade_store.get_resources(available=True)

    elif type == 'WFS':
        # Register the Service with GeoServer to be cascaded
        cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest",
                      _user, _password)
        # Can we always assume that it is geonode?
        cascade_ws = cat.get_workspace(settings.CASCADE_WORKSPACE)
        if cascade_ws is None:
            cascade_ws = cat.create_workspace(
                settings.CASCADE_WORKSPACE, "http://geonode.org/cascade")

        try:
            wfs_ds = cat.get_store(name, cascade_ws)
        except:
            wfs_ds = cat.create_datastore(name, cascade_ws)
            connection_params = {
                "WFSDataStoreFactory:MAXFEATURES": "0",
                "WFSDataStoreFactory:TRY_GZIP": "true",
                "WFSDataStoreFactory:PROTOCOL": "false",
                "WFSDataStoreFactory:LENIENT": "true",
                "WFSDataStoreFactory:TIMEOUT": "3000",
                "WFSDataStoreFactory:BUFFER_SIZE": "10",
                "WFSDataStoreFactory:ENCODING": "UTF-8",
                "WFSDataStoreFactory:WFS_STRATEGY": "nonstrict",
                "WFSDataStoreFactory:GET_CAPABILITIES_URL": url,
            }
            if username and password:
                connection_params["WFSDataStoreFactory:USERNAME"] = username
                connection_params["WFSDataStoreFactory:PASSWORD"] = password

            wfs_ds.connection_parameters = connection_params
            cat.save(wfs_ds)
        available_resources = wfs_ds.get_resources(available=True)

        # Save the Service record
        service, created = Service.objects.get_or_create(type=type,
                                                         method='C',
                                                         base_url=url,
                                                         name=name,
                                                         owner=owner)
        service.save()
        service.set_default_permissions()
    elif type == 'WCS':
        return HttpResponse('Not Implemented (Yet)', status=501)
    else:
        return HttpResponse(
            'Invalid Method / Type combo: ' +
            'Only Cascaded WMS, WFS and WCS supported',
            mimetype="text/plain",
            status=400)

    message = "Service %s registered" % service.name
    return_dict = [{'status': 'ok',
                    'msg': message,
                    'service_id': service.pk,
                    'service_name': service.name,
                    'service_title': service.title,
                    'available_layers': available_resources
                    }]

    if settings.USE_QUEUE:
        # Create a layer import job
        WebServiceHarvestLayersJob.objects.get_or_create(service=service)
    else:
        _register_cascaded_layers(service)
    return HttpResponse(json.dumps(return_dict),
                        mimetype='application/json',
                        status=200)
Beispiel #36
0
class ModifyingTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog(GSPARAMS['GSURL'],
                           username=GSPARAMS['GSUSER'],
                           password=GSPARAMS['GSPASSWORD'])

    def testFeatureTypeSave(self):
        # test saving round trip
        rs = self.cat.get_resource("bugsites")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"
        enabled = rs.enabled

        # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(new_abstract, rs.abstract)
        self.assertEqual(enabled, rs.enabled)

        # Change keywords on server
        rs.keywords = ["bugsites", "gsconfig"]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(["bugsites", "gsconfig"], rs.keywords)
        self.assertEqual(enabled, rs.enabled)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211",
                              "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual([
            ("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")
        ], rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)

        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(old_abstract, rs.abstract)

    def testDataStoreCreate(self):
        ds = self.cat.create_datastore("vector_gsconfig")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)

    def testPublishFeatureType(self):
        # Use the other test and store creation to load vector data into a database
        # @todo maybe load directly to database?
        try:
            self.testDataStoreCreateAndThenAlsoImportData()
        except FailedRequestError:
            pass
        try:
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            self.cat.delete(lyr)
            self.cat.delete(lyr.resource)
            ds = self.cat.get_store("gsconfig_import_test")
            # make sure it's gone
            self.assert_(self.cat.get_layer('import') is None)
            self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326")
            # and now it's not
            self.assert_(self.cat.get_layer('import') is not None)
        finally:
            # tear stuff down to allow the other test to pass if we run first
            ds = self.cat.get_store("gsconfig_import_test")
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            try:
                if lyr:
                    self.cat.delete(lyr)
                    self.cat.delete(lyr.resource)
                if ds:
                    self.cat.delete(ds)
            except:
                pass

    def testDataStoreModify(self):
        ds = self.cat.get_store("sf")
        self.assertFalse("foo" in ds.connection_parameters)
        ds.connection_parameters = ds.connection_parameters
        ds.connection_parameters["foo"] = "bar"
        orig_ws = ds.workspace.name
        self.cat.save(ds)
        ds = self.cat.get_store("sf")
        self.assertTrue("foo" in ds.connection_parameters)
        self.assertEqual("bar", ds.connection_parameters["foo"])
        self.assertEqual(orig_ws, ds.workspace.name)

    @drop_table('import')
    def testDataStoreCreateAndThenAlsoImportData(self):
        ds = self.cat.create_datastore("gsconfig_import_test")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test")
        self.cat.add_data_to_store(
            ds, "import", {
                'shp': 'test/data/states.shp',
                'shx': 'test/data/states.shx',
                'dbf': 'test/data/states.dbf',
                'prj': 'test/data/states.prj'
            })

    @drop_table('import2')
    def testVirtualTables(self):
        ds = self.cat.create_datastore("gsconfig_import_test2")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test2")
        self.cat.add_data_to_store(
            ds, "import2", {
                'shp': 'test/data/states.shp',
                'shx': 'test/data/states.shx',
                'dbf': 'test/data/states.dbf',
                'prj': 'test/data/states.prj'
            })
        store = self.cat.get_store("gsconfig_import_test2")
        geom = JDBCVirtualTableGeometry('the_geom', 'MultiPolygon', '4326')
        ft_name = 'my_jdbc_vt_test'
        epsg_code = 'EPSG:4326'
        sql = "select * from import2 where 'STATE_NAME' = 'Illinois'"
        keyColumn = None
        parameters = None

        jdbc_vt = JDBCVirtualTable(ft_name, sql, 'false', geom, keyColumn,
                                   parameters)
        ft = self.cat.publish_featuretype(ft_name,
                                          store,
                                          epsg_code,
                                          jdbc_virtual_table=jdbc_vt)

    # DISABLED; this test works only in the very particular case
    # "mytiff.tiff" is already present into the GEOSERVER_DATA_DIR
    # def testCoverageStoreCreate(self):
    #     ds = self.cat.create_coveragestore2("coverage_gsconfig")
    #     ds.data_url = "file:test/data/mytiff.tiff"
    #     self.cat.save(ds)

    def testCoverageStoreModify(self):
        cs = self.cat.get_store("sfdem")
        self.assertEqual("GeoTIFF", cs.type)
        cs.type = "WorldImage"
        self.cat.save(cs)
        cs = self.cat.get_store("sfdem")
        self.assertEqual("WorldImage", cs.type)

        # not sure about order of test runs here, but it might cause problems
        # for other tests if this layer is misconfigured
        cs.type = "GeoTIFF"
        self.cat.save(cs)

    def testCoverageSave(self):
        # test saving round trip
        rs = self.cat.get_resource("Arc_Sample")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"

        # # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(new_abstract, rs.abstract)

        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(old_abstract, rs.abstract)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211",
                              "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual([
            ("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")
        ], rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)

        srs_before = set(['EPSG:4326'])
        srs_after = set(['EPSG:4326', 'EPSG:3785'])
        formats = set(
            ['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF'])
        formats_after = set(["PNG", "GIF", "TIFF"])

        # set and save request_srs_list
        self.assertEquals(set(rs.request_srs_list), srs_before,
                          str(rs.request_srs_list))
        rs.request_srs_list = rs.request_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.request_srs_list), srs_after,
                          str(rs.request_srs_list))

        # set and save response_srs_list
        self.assertEquals(set(rs.response_srs_list), srs_before,
                          str(rs.response_srs_list))
        rs.response_srs_list = rs.response_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.response_srs_list), srs_after,
                          str(rs.response_srs_list))

        # set and save supported_formats
        self.assertEquals(set(rs.supported_formats), formats,
                          str(rs.supported_formats))
        rs.supported_formats = ["PNG", "GIF", "TIFF"]
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.supported_formats), formats_after,
                          str(rs.supported_formats))

    def testWmsStoreCreate(self):
        ws = self.cat.create_wmsstore("wmsstore_gsconfig")
        ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        ws.type = "WMS"
        self.cat.save(ws)

    def testWmsLayer(self):
        self.cat.create_workspace("wmstest", "http://example.com/wmstest")
        wmstest = self.cat.get_workspace("wmstest")
        wmsstore = self.cat.create_wmsstore("wmsstore", wmstest)
        wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        wmsstore.type = "WMS"
        self.cat.save(wmsstore)
        wmsstore = self.cat.get_store("wmsstore")
        self.assertEqual(1, len(self.cat.get_stores(wmstest)))
        available_layers = wmsstore.get_resources(available=True)
        for layer in available_layers:
            # sanitize the layer name - validation will fail on newer geoservers
            name = layer.replace(':', '_')
            new_layer = self.cat.create_wmslayer(wmstest,
                                                 wmsstore,
                                                 name,
                                                 nativeName=layer)
        added_layers = wmsstore.get_resources()
        self.assertEqual(len(available_layers), len(added_layers))

        changed_layer = added_layers[0]
        self.assertEqual(True, changed_layer.advertised)
        self.assertEqual(True, changed_layer.enabled)
        changed_layer.advertised = False
        changed_layer.enabled = False
        self.cat.save(changed_layer)
        self.cat._cache.clear()
        changed_layer = wmsstore.get_resources()[0]
        changed_layer.fetch()
        self.assertEqual(False, changed_layer.advertised)
        self.assertEqual(False, changed_layer.enabled)

        # Testing projection and projection policy changes
        changed_layer.projection = "EPSG:900913"
        changed_layer.projection_policy = "REPROJECT_TO_DECLARED"
        self.cat.save(changed_layer)
        self.cat._cache.clear()
        layer = self.cat.get_layer(changed_layer.name)
        self.assertEqual(layer.resource.projection_policy,
                         changed_layer.projection_policy)
        self.assertEqual(layer.resource.projection, changed_layer.projection)

    def testFeatureTypeCreate(self):
        shapefile_plus_sidecars = shapefile_and_friends("test/data/states")
        expected = {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        }

        self.assertEqual(len(expected), len(shapefile_plus_sidecars))
        for k, v in expected.iteritems():
            self.assertEqual(v, shapefile_plus_sidecars[k])

        sf = self.cat.get_workspace("sf")
        self.cat.create_featurestore("states_test", shapefile_plus_sidecars,
                                     sf)

        self.assert_(
            self.cat.get_resource("states_test", workspace=sf) is not None)

        self.assertRaises(
            ConflictingDataError, lambda: self.cat.create_featurestore(
                "states_test", shapefile_plus_sidecars, sf))

        self.assertRaises(
            UploadError, lambda: self.cat.create_coveragestore(
                "states_raster_test", shapefile_plus_sidecars, sf))

        bogus_shp = {
            'shp': 'test/data/Pk50095.tif',
            'shx': 'test/data/Pk50095.tif',
            'dbf': 'test/data/Pk50095.tfw',
            'prj': 'test/data/Pk50095.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf))

        lyr = self.cat.get_layer("states_test")
        self.cat.delete(lyr)
        self.assert_(self.cat.get_layer("states_test") is None)

    def testCoverageCreate(self):
        tiffdata = {
            'tiff': 'test/data/Pk50095.tif',
            'tfw': 'test/data/Pk50095.tfw',
            'prj': 'test/data/Pk50095.prj'
        }

        sf = self.cat.get_workspace("sf")
        ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf)

        self.assert_(
            self.cat.get_resource("Pk50095", workspace=sf) is not None)

        self.assertRaises(
            ConflictingDataError,
            lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf))

        self.assertRaises(
            UploadError, lambda: self.cat.create_featurestore(
                "Pk50095_vector", tiffdata, sf))

        bogus_tiff = {
            'tiff': 'test/data/states.shp',
            'tfw': 'test/data/states.shx',
            'prj': 'test/data/states.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster", bogus_tiff))

        ft_ext = self.cat.create_coveragestore_external_geotiff(
            "Pk50095_ext", 'file:test/data/Pk50095.tif', sf)

    def testLayerSave(self):
        # test saving round trip
        lyr = self.cat.get_layer("states")
        old_attribution = lyr.attribution
        new_attribution = {
            'title': 'Not the original attribution',
            'width': '123',
            'height': '321',
            'href': 'http://www.georchestra.org',
            'url':
            'https://www.cigalsace.org/portail/cigal/documents/page/mentions-legales/Logo_geOrchestra.jpg',
            'type': 'image/jpeg'
        }

        # change attribution on server
        lyr.attribution = new_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(new_attribution, lyr.attribution)

        # Restore attribution
        lyr.attribution = old_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(old_attribution, lyr.attribution)

        self.assertEqual(lyr.default_style.name, "population")

        old_default_style = lyr.default_style
        lyr.default_style = (s for s in lyr.styles
                             if s.name == "pophatch").next()
        lyr.styles = [old_default_style]
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(lyr.default_style.name, "pophatch")
        self.assertEqual([s.name for s in lyr.styles], ["population"])

    def testStyles(self):
        # check count before tests (upload)
        count = len(self.cat.get_styles())

        # upload new style, verify existence
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Fred", fred.sld_title)

        # replace style, verify changes
        self.cat.create_style("fred",
                              open("test/ted.sld").read(),
                              overwrite=True)
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Ted", fred.sld_title)

        # delete style, verify non-existence
        self.cat.delete(fred, purge=True)
        self.assert_(self.cat.get_style("fred") is None)

        # attempt creating new style
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assertEqual("Fred", fred.sld_title)

        # verify it can be found via URL and check the name
        f = self.cat.get_style_by_url(fred.href)
        self.assert_(f is not None)
        self.assertEqual(f.name, fred.name)

        # compare count after upload
        self.assertEqual(count + 1, len(self.cat.get_styles()))

        # attempt creating a new style without "title"
        self.cat.create_style("notitle", open("test/notitle.sld").read())
        notitle = self.cat.get_style("notitle")
        self.assertEqual(None, notitle.sld_title)

    def testWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("jed",
                              open("test/fred.sld").read(),
                              workspace="topp")

        jed = self.cat.get_style("jed", workspace="blarny")
        self.assert_(jed is None)
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)
        jed = self.cat.get_style("topp:jed")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)

        # replace style, verify changes
        self.cat.create_style("jed",
                              open("test/ted.sld").read(),
                              overwrite=True,
                              workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Ted", jed.sld_title)

        # delete style, verify non-existence
        self.cat.delete(jed, purge=True)
        self.assert_(self.cat.get_style("jed", workspace="topp") is None)

        # attempt creating new style
        self.cat.create_style("jed",
                              open("test/fred.sld").read(),
                              workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assertEqual("Fred", jed.sld_title)

        # verify it can be found via URL and check the full name
        f = self.cat.get_style_by_url(jed.href)
        self.assert_(f is not None)
        self.assertEqual(f.fqn, jed.fqn)

    def testLayerWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("ned",
                              open("test/fred.sld").read(),
                              overwrite=True,
                              workspace="topp")
        self.cat.create_style("zed",
                              open("test/ted.sld").read(),
                              overwrite=True,
                              workspace="topp")
        ned = self.cat.get_style("ned", workspace="topp")
        zed = self.cat.get_style("zed", workspace="topp")
        self.assert_(ned is not None)
        self.assert_(zed is not None)

        lyr = self.cat.get_layer("states")
        lyr.default_style = ned
        lyr.styles = [zed]
        self.cat.save(lyr)
        self.assertEqual("topp:ned", lyr.default_style)
        self.assertEqual([zed], lyr.styles)

        lyr.refresh()
        self.assertEqual("topp:ned", lyr.default_style.fqn)
        self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles])

    def testWorkspaceCreate(self):
        ws = self.cat.get_workspace("acme")
        self.assertEqual(None, ws)
        self.cat.create_workspace("acme", "http://example.com/acme")
        ws = self.cat.get_workspace("acme")
        self.assertEqual("acme", ws.name)

    def testWorkspaceDelete(self):
        self.cat.create_workspace("foo", "http://example.com/foo")
        ws = self.cat.get_workspace("foo")
        self.cat.delete(ws)
        ws = self.cat.get_workspace("foo")
        self.assert_(ws is None)

    def testWorkspaceDefault(self):
        # save orig
        orig = self.cat.get_default_workspace()
        neu = self.cat.create_workspace("neu", "http://example.com/neu")
        try:
            # make sure setting it works
            self.cat.set_default_workspace("neu")
            ws = self.cat.get_default_workspace()
            self.assertEqual('neu', ws.name)
        finally:
            # cleanup and reset to the way things were
            self.cat.delete(neu)
            self.cat.set_default_workspace(orig.name)
            ws = self.cat.get_default_workspace()
            self.assertEqual(orig.name, ws.name)

    def testFeatureTypeDelete(self):
        pass

    def testCoverageDelete(self):
        pass

    def testDataStoreDelete(self):
        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)
        states.enabled = False
        self.assert_(states.enabled == False)
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == False)

        states.enabled = True
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)

    def testLayerGroupSave(self):
        tas = self.cat.get_layergroup("tasmania")

        self.assertEqual(tas.layers, [
            'tasmania_state_boundaries', 'tasmania_water_bodies',
            'tasmania_roads', 'tasmania_cities'
        ], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        tas.layers = tas.layers[:-1]
        tas.styles = tas.styles[:-1]

        self.cat.save(tas)

        # this verifies the local state
        self.assertEqual(tas.layers, [
            'tasmania_state_boundaries', 'tasmania_water_bodies',
            'tasmania_roads'
        ], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)

        # force a refresh to check the remote state
        tas.refresh()
        self.assertEqual(tas.layers, [
            'tasmania_state_boundaries', 'tasmania_water_bodies',
            'tasmania_roads'
        ], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)

    def testImageMosaic(self):
        """
            Test case for Issue #110
        """
        # testing the mosaic creation
        name = 'cea_mosaic'
        data = open('test/data/mosaic/cea.zip', 'rb')
        self.cat.create_imagemosaic(name, data)

        # get the layer resource back
        self.cat._cache.clear()
        resource = self.cat.get_layer(name).resource

        self.assert_(resource is not None)

        # delete granule from mosaic
        coverage = name
        store = self.cat.get_store(name)
        granule_id = name + '.1'
        self.cat.mosaic_delete_granule(coverage, store, granule_id)

    def testTimeDimension(self):
        sf = self.cat.get_workspace("sf")
        files = shapefile_and_friends(
            os.path.join(gisdata.GOOD_DATA, "time", "boxes_with_end_date"))
        self.cat.create_featurestore("boxes_with_end_date", files, sf)

        get_resource = lambda: self.cat._cache.clear() or self.cat.get_layer(
            'boxes_with_end_date').resource

        # configure time as LIST
        resource = get_resource()
        timeInfo = DimensionInfo("time",
                                 "true",
                                 "LIST",
                                 None,
                                 "ISO8601",
                                 None,
                                 attribute="date")
        resource.metadata = {'time': timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual("LIST", timeInfo.presentation)
        self.assertEqual(True, timeInfo.enabled)
        self.assertEqual("date", timeInfo.attribute)
        self.assertEqual("ISO8601", timeInfo.units)

        # disable time dimension
        timeInfo = resource.metadata['time']
        timeInfo.enabled = False
        # since this is an xml property, it won't get written unless we modify it
        resource.metadata = {'time': timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual(False, timeInfo.enabled)

        # configure with interval, end_attribute and enable again
        timeInfo.enabled = True
        timeInfo.presentation = 'DISCRETE_INTERVAL'
        timeInfo.resolution = '3 days'
        timeInfo.end_attribute = 'enddate'
        resource.metadata = {'time': timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual(True, timeInfo.enabled)
        self.assertEqual('DISCRETE_INTERVAL', timeInfo.presentation)
        self.assertEqual('3 days', timeInfo.resolution_str())
        self.assertEqual('enddate', timeInfo.end_attribute)
Beispiel #37
0
import requests
from geoserver.catalog import Catalog

# Set cat variable
cat = Catalog('http://url/geoserver/rest/',
              username="******",
              password="******")

# Create Workspace
#ws = cat.create_workspace('ws_name','http://uri/ws_name')
ws = cat.get_workspace('ws_name')

# Create Store from PostGIS
ds = cat.create_datastore('db_name', 'ws_name')

ds.connection_parameters.update(host='host',
                                port='5432',
                                database='db_name',
                                user='******',
                                passwd='password',
                                dbtype='postgis',
                                schema='public')

cat.save(ds)

# Add Layers from Postgres
ft = cat.publish_featuretype('table_name', ds, 'EPSG:3857', srs='EPSG:3857')

cat.save(ft)
Beispiel #38
0
class CatalogTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog(GSPARAMS['GSURL'],
                           username=GSPARAMS['GSUSER'],
                           password=GSPARAMS['GSPASSWORD'])

    def testAbout(self):
        about_html = self.cat.about()
        self.assertTrue(
            '<html xmlns="http://www.w3.org/1999/xhtml"' in about_html)

    def testGSVersion(self):
        version = self.cat.gsversion()
        pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)')
        self.assertTrue(pat.match('2.2.x'))
        self.assertTrue(pat.match('2.3.2'))
        self.assertTrue(pat.match('2.3-SNAPSHOT'))
        self.assertFalse(pat.match('2.3.y'))
        self.assertFalse(pat.match('233'))
        self.assertTrue(pat.match(version))

    def testWorkspaces(self):
        self.assertEqual(7, len(self.cat.get_workspaces()))
        # marking out test since geoserver default workspace is not consistent
        # self.assertEqual("cite", self.cat.get_default_workspace().name)
        self.assertEqual("topp", self.cat.get_workspace("topp").name)

    def testStores(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        self.assertEqual(9, len(self.cat.get_stores()))
        self.assertEqual(2, len(self.cat.get_stores(topp)))
        self.assertEqual(2, len(self.cat.get_stores(sf)))
        self.assertEqual("states_shapefile",
                         self.cat.get_store("states_shapefile", topp).name)
        self.assertEqual("states_shapefile",
                         self.cat.get_store("states_shapefile").name)
        self.assertEqual("states_shapefile",
                         self.cat.get_store("states_shapefile").name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem").name)

    def testResources(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        states = self.cat.get_store("states_shapefile", topp)
        sfdem = self.cat.get_store("sfdem", sf)
        self.assertEqual(19, len(self.cat.get_resources()))
        self.assertEqual(1, len(self.cat.get_resources(states)))
        self.assertEqual(5, len(self.cat.get_resources(workspace=topp)))
        self.assertEqual(1, len(self.cat.get_resources(sfdem)))
        self.assertEqual(6, len(self.cat.get_resources(workspace=sf)))

        self.assertEqual("states",
                         self.cat.get_resource("states", states).name)
        self.assertEqual("states",
                         self.cat.get_resource("states", workspace=topp).name)
        self.assertEqual("states", self.cat.get_resource("states").name)
        states = self.cat.get_resource("states")

        fields = [
            states.title, states.abstract, states.native_bbox,
            states.latlon_bbox, states.projection, states.projection_policy
        ]

        self.assertFalse(None in fields, str(fields))
        self.assertFalse(len(states.keywords) == 0)
        self.assertFalse(len(states.attributes) == 0)
        self.assertTrue(states.enabled)

        self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name)
        self.assertEqual("sfdem",
                         self.cat.get_resource("sfdem", workspace=sf).name)
        self.assertEqual("sfdem", self.cat.get_resource("sfdem").name)

    def testResourcesUpdate(self):
        res_dest = self.cat.get_resources()
        count = 0

        for rd in res_dest:
            # only wms layers
            if rd.resource_type != "wmsLayer": continue
            # looking for same name
            ro = self.cat.get_resource(rd.name)

            if ro is not None:
                rd.title = ro.title
                rd.abstract = ro.abstract
                rd.keywords = ro.keywords
                rd.projection = ro.projection
                rd.native_bbox = ro.native_bbox
                rd.latlon_bbox = ro.latlon_bbox
                rd.projection_policy = ro.projection_policy
                rd.enabled = ro.enabled
                rd.advertised = ro.advertised
                rd.metadata_links = ro.metadata_links or None

                self.cat.save(rd)
                self.cat.reload()

                # print "Updated layer: " + rd.name
                count += 1

        # print "Total updated layers: " + str(count)

    def testLayers(self):
        expected = set([
            "Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem",
            "bugsites", "restricted", "streams", "archsites", "roads",
            "tasmania_roads", "tasmania_water_bodies",
            "tasmania_state_boundaries", "tasmania_cities", "states",
            "poly_landmarks", "tiger_roads", "poi", "giant_polygon"
        ])
        actual = set(l.name for l in self.cat.get_layers())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (
            extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        states = self.cat.get_layer("states")

        self.assert_("states", states.name)
        self.assert_(isinstance(states.resource, ResourceInfo))
        self.assertEqual(set(s.name for s in states.styles),
                         set(['pophatch', 'polygon']))
        self.assertEqual(states.default_style.name, "population")

    def testLayerGroups(self):
        expected = set(["tasmania", "tiger-ny", "spearfish"])
        actual = set(l.name for l in self.cat.get_layergroups())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (
            extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        tas = self.cat.get_layergroup("tasmania")

        self.assert_("tasmania", tas.name)
        self.assert_(isinstance(tas, LayerGroup))
        self.assertEqual(tas.layers, [
            'tasmania_state_boundaries', 'tasmania_water_bodies',
            'tasmania_roads', 'tasmania_cities'
        ], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        # Try to create a new Layer Group into the "topp" workspace
        self.assert_(self.cat.get_workspace("topp") is not None)
        tas2 = self.cat.create_layergroup("tasmania_reloaded",
                                          tas.layers,
                                          workspace="topp")
        self.cat.save(tas2)
        self.assert_(self.cat.get_layergroup("tasmania_reloaded") is None)
        self.assert_(
            self.cat.get_layergroup("tasmania_reloaded", "topp") is not None)
        tas2 = self.cat.get_layergroup("tasmania_reloaded", "topp")
        self.assert_("tasmania_reloaded", tas2.name)
        self.assert_(isinstance(tas2, LayerGroup))
        self.assertEqual(tas2.workspace, "topp", tas2.workspace)
        self.assertEqual(tas2.layers, [
            'tasmania_state_boundaries', 'tasmania_water_bodies',
            'tasmania_roads', 'tasmania_cities'
        ], tas2.layers)
        self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles)

    def testStyles(self):
        self.assertEqual("population", self.cat.get_style("population").name)
        self.assertEqual("popshade.sld",
                         self.cat.get_style("population").filename)
        self.assertEqual("population",
                         self.cat.get_style("population").sld_name)
        self.assert_(self.cat.get_style('non-existing-style') is None)

    def testEscaping(self):
        # GSConfig is inconsistent about using exceptions vs. returning None
        # when a resource isn't found.
        # But the basic idea is that none of them should throw HTTP errors from
        # misconstructed URLS
        self.cat.get_style("best style ever")
        self.cat.get_workspace("best workspace ever")
        try:
            self.cat.get_store(workspace="best workspace ever",
                               name="best store ever")
            self.fail('expected exception')
        except FailedRequestError, fre:
            self.assertEqual('No store found named: best store ever',
                             fre.message)
        try:
            self.cat.get_resource(workspace="best workspace ever",
                                  store="best store ever",
                                  name="best resource ever")
        except FailedRequestError, fre:
            self.assertEqual('No store found named: best store ever',
                             fre.message)
Beispiel #39
0
class ModifyingTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog("http://localhost:8080/geoserver/rest")

    def testFeatureTypeSave(self):
        # test saving round trip
        rs = self.cat.get_resource("bugsites")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"
        enabled = rs.enabled

        # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(new_abstract, rs.abstract)
        self.assertEqual(enabled, rs.enabled)

        # Change keywords on server
        rs.keywords = ["bugsites", "gsconfig"]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(["bugsites", "gsconfig"], rs.keywords)
        self.assertEqual(enabled, rs.enabled)
        
        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(
                        [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
                        rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)


        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(old_abstract, rs.abstract)

    def testDataStoreCreate(self):
        ds = self.cat.create_datastore("vector_gsconfig")
        ds.connection_parameters.update(
            host="localhost", port="5432", database="db", user="******",
            passwd="password", dbtype="postgis")
        self.cat.save(ds)

    def testDataStoreModify(self):
        ds = self.cat.get_store("sf")
        self.assertFalse("foo" in ds.connection_parameters)
        ds.connection_parameters = ds.connection_parameters
        ds.connection_parameters["foo"] = "bar"
        orig_ws = ds.workspace.name
        self.cat.save(ds)
        ds = self.cat.get_store("sf")
        self.assertTrue("foo" in ds.connection_parameters)
        self.assertEqual("bar", ds.connection_parameters["foo"])
        self.assertEqual(orig_ws, ds.workspace.name)

    def testDataStoreCreateAndThenAlsoImportData(self):
        ds = self.cat.create_datastore("gsconfig_import_test")
        ds.connection_parameters.update(
            host="localhost", port="5432", database="db", user="******",
            passwd="password", dbtype="postgis")
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test")
        self.cat.add_data_to_store(ds, "import", {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        })

    def testCoverageStoreCreate(self):
        ds = self.cat.create_coveragestore2("coverage_gsconfig")
        ds.data_url = "file:data/mytiff.tiff"
        self.cat.save(ds)

    def testCoverageStoreModify(self):
        cs = self.cat.get_store("sfdem")
        self.assertEqual("GeoTIFF", cs.type)
        cs.type = "WorldImage"
        self.cat.save(cs)
        cs = self.cat.get_store("sfdem")
        self.assertEqual("WorldImage", cs.type)

        # not sure about order of test runs here, but it might cause problems
        # for other tests if this layer is misconfigured
        cs.type = "GeoTIFF"
        self.cat.save(cs) 

    def testCoverageSave(self):
        # test saving round trip
        rs = self.cat.get_resource("Arc_Sample")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"

        # # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(new_abstract, rs.abstract)

        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(old_abstract, rs.abstract)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(
            [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
            rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)

        srs_before = set(['EPSG:4326'])
        srs_after = set(['EPSG:4326', 'EPSG:3785'])
        formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF'])
        formats_after = set(["PNG", "GIF", "TIFF"])

        # set and save request_srs_list
        self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list))
        rs.request_srs_list = rs.request_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list))

        # set and save response_srs_list
        self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list))
        rs.response_srs_list = rs.response_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list))

        # set and save supported_formats
        self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats))
        rs.supported_formats = ["PNG", "GIF", "TIFF"]
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats))


    def testFeatureTypeCreate(self):
        shapefile_plus_sidecars = shapefile_and_friends("test/data/states")
        expected = {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        }

        self.assertEqual(len(expected), len(shapefile_plus_sidecars))
        for k, v in expected.iteritems():
            self.assertEqual(v, shapefile_plus_sidecars[k])
 
        sf = self.cat.get_workspace("sf")
        self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)

        self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None)

        self.assertRaises(
            ConflictingDataError, 
            lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)
        )

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf)
        )

        bogus_shp = {
            'shp': 'test/data/Pk50095.tif',
            'shx': 'test/data/Pk50095.tif',
            'dbf':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf)
        )

        lyr = self.cat.get_layer("states_test")
        self.cat.delete(lyr)
        self.assert_(self.cat.get_layer("states_test") is None)


    def testCoverageCreate(self):
        tiffdata = {
            'tiff': 'test/data/Pk50095.tif',
            'tfw':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        sf = self.cat.get_workspace("sf")
        # TODO: Uploading WorldImage file no longer works???
        # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf)

        # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None)

        # self.assertRaises(
        #         ConflictingDataError, 
        #         lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf)
        # )

        self.assertRaises(
            UploadError, 
            lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf)
        )

        bogus_tiff = {
            'tiff': 'test/data/states.shp',
            'tfw': 'test/data/states.shx',
            'prj': 'test/data/states.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster", bogus_tiff)
        )

    def testLayerSave(self):
        # test saving round trip
        lyr = self.cat.get_layer("states")
        old_attribution = lyr.attribution
        new_attribution = "Not the original attribution"

        # change attribution on server
        lyr.attribution = new_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(new_attribution, lyr.attribution)

        # Restore attribution
        lyr.attribution = old_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(old_attribution, lyr.attribution)

        self.assertEqual(lyr.default_style.name, "population")
     
        old_default_style = lyr.default_style
        lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next()
        lyr.styles = [old_default_style]
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(lyr.default_style.name, "pophatch")
        self.assertEqual([s.name for s in lyr.styles], ["population"])


    def testStyles(self):
        # upload new style, verify existence
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Fred", fred.sld_title)

        # replace style, verify changes
        self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True)
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Ted", fred.sld_title)

        # delete style, verify non-existence
        self.cat.delete(fred, purge=True)
        self.assert_(self.cat.get_style("fred") is None)

        # attempt creating new style
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assertEqual("Fred", fred.sld_title)

    def testWorkspaceCreate(self):
        ws = self.cat.get_workspace("acme")
        self.assertEqual(None, ws)
        self.cat.create_workspace("acme", "http://example.com/acme")
        ws = self.cat.get_workspace("acme")
        self.assertEqual("acme", ws.name)

    def testWorkspaceDelete(self): 
        self.cat.create_workspace("foo", "http://example.com/foo")
        ws = self.cat.get_workspace("foo")
        self.cat.delete(ws)
        ws = self.cat.get_workspace("foo")
        self.assert_(ws is None)

    def testFeatureTypeDelete(self):
        pass

    def testCoverageDelete(self):
        pass

    def testDataStoreDelete(self):
        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)
        states.enabled = False
        self.assert_(states.enabled == False)
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == False)

        states.enabled = True
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)

    def testLayerGroupSave(self):
        tas = self.cat.get_layergroup("tasmania")

        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        tas.layers = tas.layers[:-1]
        tas.styles = tas.styles[:-1]

        self.cat.save(tas)

        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)
Beispiel #40
0
class CatalogTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD'])

    def testAbout(self):
        about_html = self.cat.about()
        self.assertTrue('<html xmlns="http://www.w3.org/1999/xhtml"' in about_html)

    def testGSVersion(self):
        version = self.cat.gsversion()
        pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)')
        self.assertTrue(pat.match('2.2.x'))
        self.assertTrue(pat.match('2.3.2'))
        self.assertTrue(pat.match('2.3-SNAPSHOT'))
        self.assertFalse(pat.match('2.3.y'))
        self.assertFalse(pat.match('233'))
        self.assertTrue(pat.match(version))

    def testWorkspaces(self):
        self.assertEqual(7, len(self.cat.get_workspaces()))
        # marking out test since geoserver default workspace is not consistent
        # self.assertEqual("cite", self.cat.get_default_workspace().name)
        self.assertEqual("topp", self.cat.get_workspace("topp").name)


    def testStores(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        self.assertEqual(9, len(self.cat.get_stores()))
        self.assertEqual(2, len(self.cat.get_stores(topp)))
        self.assertEqual(2, len(self.cat.get_stores(sf)))
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name)
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem").name)


    def testResources(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        states = self.cat.get_store("states_shapefile", topp)
        sfdem = self.cat.get_store("sfdem", sf)
        self.assertEqual(19, len(self.cat.get_resources()))
        self.assertEqual(1, len(self.cat.get_resources(states)))
        self.assertEqual(5, len(self.cat.get_resources(workspace=topp)))
        self.assertEqual(1, len(self.cat.get_resources(sfdem)))
        self.assertEqual(6, len(self.cat.get_resources(workspace=sf)))

        self.assertEqual("states", self.cat.get_resource("states", states).name)
        self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name)
        self.assertEqual("states", self.cat.get_resource("states").name)
        states = self.cat.get_resource("states")

        fields = [
            states.title,
            states.abstract,
            states.native_bbox,
            states.latlon_bbox,
            states.projection,
            states.projection_policy
        ]

        self.assertFalse(None in fields, str(fields))
        self.assertFalse(len(states.keywords) == 0)
        self.assertFalse(len(states.attributes) == 0)
        self.assertTrue(states.enabled)

        self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name)
        self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name)
        self.assertEqual("sfdem", self.cat.get_resource("sfdem").name)

    def testResourcesUpdate(self):
        res_dest = self.cat.get_resources()
        count = 0

        for rd in res_dest:
            # only wms layers
            if rd.resource_type != "wmsLayer": continue
            # looking for same name
            ro = self.cat.get_resource(rd.name)

            if ro is not None:
                rd.title  = ro.title
                rd.abstract  = ro.abstract
                rd.keywords  = ro.keywords
                rd.projection  = ro.projection
                rd.native_bbox  = ro.native_bbox
                rd.latlon_bbox  = ro.latlon_bbox
                rd.projection_policy  = ro.projection_policy
                rd.enabled  = ro.enabled
                rd.advertised  = ro.advertised
                rd.metadata_links = ro.metadata_links or None

                self.cat.save(rd)
                self.cat.reload()

                # print "Updated layer: " + rd.name
                count += 1

        # print "Total updated layers: " + str(count)

    def testLayers(self):
        expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem",
            "bugsites", "restricted", "streams", "archsites", "roads",
            "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries",
            "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi",
            "giant_polygon"
        ])
        actual = set(l.name for l in self.cat.get_layers())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        states = self.cat.get_layer("states")

        self.assert_("states", states.name)
        self.assert_(isinstance(states.resource, ResourceInfo))
        self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon']))
        self.assertEqual(states.default_style.name, "population")

    def testLayerGroups(self):
        expected = set(["tasmania", "tiger-ny", "spearfish"])
        actual = set(l.name for l in self.cat.get_layergroups())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        tas = self.cat.get_layergroup("tasmania")

        self.assert_("tasmania", tas.name)
        self.assert_(isinstance(tas, LayerGroup))
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        # Try to create a new Layer Group into the "topp" workspace
        self.assert_(self.cat.get_workspace("topp") is not None)
        tas2 = self.cat.create_layergroup("tasmania_reloaded", tas.layers, workspace = "topp")
        self.cat.save(tas2)
        self.assert_(self.cat.get_layergroup("tasmania_reloaded") is None)
        self.assert_(self.cat.get_layergroup("tasmania_reloaded", "topp") is not None)
        tas2 = self.cat.get_layergroup("tasmania_reloaded", "topp")
        self.assert_("tasmania_reloaded", tas2.name)
        self.assert_(isinstance(tas2, LayerGroup))
        self.assertEqual(tas2.workspace, "topp", tas2.workspace)
        self.assertEqual(tas2.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas2.layers)
        self.assertEqual(tas2.styles, [None, None, None, None], tas2.styles)

    def testStyles(self):
        self.assertEqual("population", self.cat.get_style("population").name)
        self.assertEqual("popshade.sld", self.cat.get_style("population").filename)
        self.assertEqual("population", self.cat.get_style("population").sld_name)
        self.assert_(self.cat.get_style('non-existing-style') is None)

    def testEscaping(self):
        # GSConfig is inconsistent about using exceptions vs. returning None
        # when a resource isn't found.
        # But the basic idea is that none of them should throw HTTP errors from
        # misconstructed URLS
        self.cat.get_style("best style ever")
        self.cat.get_workspace("best workspace ever")
        try:
            self.cat.get_store(workspace="best workspace ever",
                name="best store ever")
            self.fail('expected exception')
        except FailedRequestError, fre:
            self.assertEqual('No store found named: best store ever', fre.message)
        try:
            self.cat.get_resource(workspace="best workspace ever",
                store="best store ever",
                name="best resource ever")
        except FailedRequestError, fre:
            self.assertEqual('No store found named: best store ever', fre.message)
Beispiel #41
0
class CatalogTests(unittest.TestCase):
  def setUp(self):
    self.cat = Catalog("http://localhost:8080/geoserver/rest")


  def testWorkspaces(self):
    self.assertEqual(7, len(self.cat.get_workspaces()))
    # marking out test since geoserver default workspace is not consistent 
    # self.assertEqual("cite", self.cat.get_default_workspace().name)
    self.assertEqual("topp", self.cat.get_workspace("topp").name)


  def testStores(self):
    topp = self.cat.get_workspace("topp")
    sf = self.cat.get_workspace("sf")
    self.assertEqual(9, len(self.cat.get_stores()))
    self.assertEqual(2, len(self.cat.get_stores(topp)))
    self.assertEqual(2, len(self.cat.get_stores(sf)))
    self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name)
    self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
    self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
    self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name)
    self.assertEqual("sfdem", self.cat.get_store("sfdem").name)

  
  def testResources(self):
    topp = self.cat.get_workspace("topp")
    sf = self.cat.get_workspace("sf")
    states = self.cat.get_store("states_shapefile", topp)
    sfdem = self.cat.get_store("sfdem", sf)
    self.assertEqual(19, len(self.cat.get_resources()))
    self.assertEqual(1, len(self.cat.get_resources(states)))
    self.assertEqual(5, len(self.cat.get_resources(workspace=topp)))
    self.assertEqual(1, len(self.cat.get_resources(sfdem)))
    self.assertEqual(6, len(self.cat.get_resources(workspace=sf)))

    self.assertEqual("states", self.cat.get_resource("states", states).name)
    self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name)
    self.assertEqual("states", self.cat.get_resource("states").name)
    states = self.cat.get_resource("states")

    fields = [
        states.title,
        states.abstract,
        states.native_bbox,
        states.latlon_bbox,
        states.projection,
        states.projection_policy
    ]

    self.assertFalse(None in fields, str(fields))
    self.assertFalse(len(states.keywords) == 0)
    self.assertFalse(len(states.attributes) == 0)
    self.assertTrue(states.enabled)

    self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name)
    self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name)
    self.assertEqual("sfdem", self.cat.get_resource("sfdem").name)


  def testLayers(self):
    expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem",
      "bugsites", "restricted", "streams", "archsites", "roads",
      "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries",
      "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi",
      "giant_polygon"
    ])
    actual = set(l.name for l in self.cat.get_layers())
    missing = expected - actual
    extras = actual - expected
    message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
    self.assert_(len(expected ^ actual) == 0, message)

    states = self.cat.get_layer("states")

    self.assert_("states", states.name)
    self.assert_(isinstance(states.resource, ResourceInfo))
    self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon']))
    self.assertEqual(states.default_style.name, "population")

  def testLayerGroups(self):
    expected = set(["tasmania", "tiger-ny", "spearfish"])
    actual = set(l.name for l in self.cat.get_layergroups())
    missing = expected - actual
    extras = actual - expected
    message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
    self.assert_(len(expected ^ actual) == 0, message)

    tas = self.cat.get_layergroup("tasmania")

    self.assert_("tasmania", tas.name)
    self.assert_(isinstance(tas, LayerGroup))
    self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
    self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

  def testStyles(self):
    self.assertEqual(20, len(self.cat.get_styles()))
    self.assertEqual("population", self.cat.get_style("population").name)
Beispiel #42
0
def export_geoserver(request):
    project = request.POST.get('project', False)
    workspace_name = request.POST.get('workspace',
                                      'geoglows_hydroviewer_creator')
    store_name = request.POST.get('store_name', 'shapefilestore')
    store_name = str(store_name).replace(' ', '_')
    store_name = str.lower(store_name)
    if not project:
        return JsonResponse({'error': 'unable to find the project'})
    proj_dir = get_project_directory(project)

    # tailor the geoserver url
    url = request.POST.get('gs_url')
    if not url[-1] == '/':
        url += '/'

    # add keys to the export_configs.json
    with open(os.path.join(proj_dir, 'export_configs.json'),
              'r') as configfile:
        geoserver_configs = json.loads(configfile.read())
        geoserver_configs['url'] = url.replace('/rest/',
                                               f'/{workspace_name}/wms')
        geoserver_configs['workspace'] = workspace_name
        geoserver_configs['drainage_layer_name'] = str.lower(
            project) + '_drainagelines'
        geoserver_configs['catchment_layer_name'] = str.lower(
            project) + '_catchments'

    if geoserver_configs['exported_drainage'] and geoserver_configs[
            'exported_catchment']:
        geoserver_configs['exported_drainage'] = False
        geoserver_configs['exported_catchment'] = False

    try:
        cat = Catalog(url,
                      username=request.POST.get('gs_username', 'admin'),
                      password=request.POST.get('gs_password', 'geoserver'))
        # identify the geoserver stores
        workspace = cat.get_workspace(workspace_name)
    except Exception as e:
        print(e)
        return JsonResponse({'status': 'failed'})

    if not geoserver_configs['exported_drainage']:
        try:
            # create geoserver store and upload the drainagelines
            zip_path = os.path.join(proj_dir, 'drainageline_shapefile.zip')
            cat.create_featurestore(store_name,
                                    workspace=workspace,
                                    data=zip_path,
                                    overwrite=True)
            geoserver_configs['exported_drainage'] = True
            with open(os.path.join(proj_dir, 'export_configs.json'),
                      'w') as configfile:
                configfile.write(json.dumps(geoserver_configs))
        except Exception as e:
            print('failed to upload drainagelines')
            print(e)

    elif not geoserver_configs['exported_catchment']:
        try:
            # create geoserver store and upload the catchments
            zip_path = os.path.join(proj_dir, 'catchment_shapefile.zip')
            cat.add_data_to_store(store_name,
                                  store_name,
                                  data=zip_path,
                                  workspace=workspace,
                                  overwrite=False)
            geoserver_configs['exported_catchment'] = True
            with open(os.path.join(proj_dir, 'export_configs.json'),
                      'w') as configfile:
                configfile.write(json.dumps(geoserver_configs))
        except Exception as e:
            print('failed to upload catchments')
            print(e)

    return JsonResponse({'status': 'success'})
Beispiel #43
0
class ModifyingTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog("http://localhost:8080/geoserver/rest")

    def testFeatureTypeSave(self):
        # test saving round trip
        rs = self.cat.get_resource("bugsites")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"
        enabled = rs.enabled

        # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(new_abstract, rs.abstract)
        self.assertEqual(enabled, rs.enabled)

        # Change keywords on server
        rs.keywords = ["bugsites", "gsconfig"]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(["bugsites", "gsconfig"], rs.keywords)
        self.assertEqual(enabled, rs.enabled)
        
        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(
                        [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
                        rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)


        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(old_abstract, rs.abstract)

    def testDataStoreCreate(self):
        ds = self.cat.create_datastore("vector_gsconfig")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)

    def testPublishFeatureType(self):
        # Use the other test and store creation to load vector data into a database
        # @todo maybe load directly to database?
        try:
            self.testDataStoreCreateAndThenAlsoImportData()
        except FailedRequestError:
            pass
        try:
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            self.cat.delete(lyr)
            self.cat.delete(lyr.resource)
            ds = self.cat.get_store("gsconfig_import_test")
            # make sure it's gone
            self.assert_(self.cat.get_layer('import') is None)
            self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326")
            # and now it's not
            self.assert_(self.cat.get_layer('import') is not None)
        finally:
            # tear stuff down to allow the other test to pass if we run first
            ds = self.cat.get_store("gsconfig_import_test")
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            self.cat.delete(lyr)
            self.cat.delete(lyr.resource)
            self.cat.delete(ds)

    def testDataStoreModify(self):
        ds = self.cat.get_store("sf")
        self.assertFalse("foo" in ds.connection_parameters)
        ds.connection_parameters = ds.connection_parameters
        ds.connection_parameters["foo"] = "bar"
        orig_ws = ds.workspace.name
        self.cat.save(ds)
        ds = self.cat.get_store("sf")
        self.assertTrue("foo" in ds.connection_parameters)
        self.assertEqual("bar", ds.connection_parameters["foo"])
        self.assertEqual(orig_ws, ds.workspace.name)

    @drop_table('import')
    def testDataStoreCreateAndThenAlsoImportData(self):
        ds = self.cat.create_datastore("gsconfig_import_test")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test")
        self.cat.add_data_to_store(ds, "import", {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        })

    def testCoverageStoreCreate(self):
        ds = self.cat.create_coveragestore2("coverage_gsconfig")
        ds.data_url = "file:data/mytiff.tiff"
        self.cat.save(ds)

    def testCoverageStoreModify(self):
        cs = self.cat.get_store("sfdem")
        self.assertEqual("GeoTIFF", cs.type)
        cs.type = "WorldImage"
        self.cat.save(cs)
        cs = self.cat.get_store("sfdem")
        self.assertEqual("WorldImage", cs.type)

        # not sure about order of test runs here, but it might cause problems
        # for other tests if this layer is misconfigured
        cs.type = "GeoTIFF"
        self.cat.save(cs) 

    def testCoverageSave(self):
        # test saving round trip
        rs = self.cat.get_resource("Arc_Sample")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"

        # # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(new_abstract, rs.abstract)

        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(old_abstract, rs.abstract)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(
            [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
            rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)

        srs_before = set(['EPSG:4326'])
        srs_after = set(['EPSG:4326', 'EPSG:3785'])
        formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF'])
        formats_after = set(["PNG", "GIF", "TIFF"])

        # set and save request_srs_list
        self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list))
        rs.request_srs_list = rs.request_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list))

        # set and save response_srs_list
        self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list))
        rs.response_srs_list = rs.response_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list))

        # set and save supported_formats
        self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats))
        rs.supported_formats = ["PNG", "GIF", "TIFF"]
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats))

    def testWmsStoreCreate(self):
        ws = self.cat.create_wmsstore("wmsstore_gsconfig")
        ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        ws.type = "WMS"
        self.cat.save(ws)
     
    def testWmsLayer(self):
        self.cat.create_workspace("wmstest", "http://example.com/wmstest")
        wmstest = self.cat.get_workspace("wmstest")
        wmsstore = self.cat.create_wmsstore("wmsstore", wmstest)
        wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        wmsstore.type = "WMS"
        self.cat.save(wmsstore)
        wmsstore = self.cat.get_store("wmsstore")
        self.assertEqual(1, len(self.cat.get_stores(wmstest)))
        available_layers = wmsstore.get_resources(available=True)
        for layer in available_layers:
            new_layer = self.cat.create_wmslayer(wmstest, wmsstore, layer)
        added_layers = wmsstore.get_resources()
        self.assertEqual(len(available_layers), len(added_layers))

    def testFeatureTypeCreate(self):
        shapefile_plus_sidecars = shapefile_and_friends("test/data/states")
        expected = {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        }

        self.assertEqual(len(expected), len(shapefile_plus_sidecars))
        for k, v in expected.iteritems():
            self.assertEqual(v, shapefile_plus_sidecars[k])
 
        sf = self.cat.get_workspace("sf")
        self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)

        self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None)

        self.assertRaises(
            ConflictingDataError, 
            lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)
        )

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf)
        )

        bogus_shp = {
            'shp': 'test/data/Pk50095.tif',
            'shx': 'test/data/Pk50095.tif',
            'dbf':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf)
        )

        lyr = self.cat.get_layer("states_test")
        self.cat.delete(lyr)
        self.assert_(self.cat.get_layer("states_test") is None)


    def testCoverageCreate(self):
        tiffdata = {
            'tiff': 'test/data/Pk50095.tif',
            'tfw':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        sf = self.cat.get_workspace("sf")
        # TODO: Uploading WorldImage file no longer works???
        # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf)

        # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None)

        # self.assertRaises(
        #         ConflictingDataError, 
        #         lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf)
        # )

        self.assertRaises(
            UploadError, 
            lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf)
        )

        bogus_tiff = {
            'tiff': 'test/data/states.shp',
            'tfw': 'test/data/states.shx',
            'prj': 'test/data/states.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster", bogus_tiff)
        )

    def testLayerSave(self):
        # test saving round trip
        lyr = self.cat.get_layer("states")
        old_attribution = lyr.attribution
        new_attribution = "Not the original attribution"

        # change attribution on server
        lyr.attribution = new_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(new_attribution, lyr.attribution)

        # Restore attribution
        lyr.attribution = old_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(old_attribution, lyr.attribution)

        self.assertEqual(lyr.default_style.name, "population")
     
        old_default_style = lyr.default_style
        lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next()
        lyr.styles = [old_default_style]
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(lyr.default_style.name, "pophatch")
        self.assertEqual([s.name for s in lyr.styles], ["population"])


    def testStyles(self):
        # upload new style, verify existence
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Fred", fred.sld_title)

        # replace style, verify changes
        self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True)
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Ted", fred.sld_title)

        # delete style, verify non-existence
        self.cat.delete(fred, purge=True)
        self.assert_(self.cat.get_style("fred") is None)

        # attempt creating new style
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assertEqual("Fred", fred.sld_title)

        # verify it can be found via URL and check the name
        f = self.cat.get_style_by_url(fred.href)
        self.assert_(f is not None)
        self.assertEqual(f.name, fred.name)

    def testWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp")

        jed = self.cat.get_style("jed", workspace="blarny")
        self.assert_(jed is None)
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)
        jed = self.cat.get_style("topp:jed")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)

        # replace style, verify changes
        self.cat.create_style("jed", open("test/ted.sld").read(), overwrite=True, workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Ted", jed.sld_title)

        # delete style, verify non-existence
        self.cat.delete(jed, purge=True)
        self.assert_(self.cat.get_style("jed", workspace="topp") is None)

        # attempt creating new style
        self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assertEqual("Fred", jed.sld_title)

        # verify it can be found via URL and check the full name
        f = self.cat.get_style_by_url(jed.href)
        self.assert_(f is not None)
        self.assertEqual(f.fqn, jed.fqn)

    def testLayerWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("ned", open("test/fred.sld").read(), overwrite=True, workspace="topp")
        self.cat.create_style("zed", open("test/ted.sld").read(), overwrite=True, workspace="topp")
        ned = self.cat.get_style("ned", workspace="topp")
        zed = self.cat.get_style("zed", workspace="topp")
        self.assert_(ned is not None)
        self.assert_(zed is not None)

        lyr = self.cat.get_layer("states")
        lyr.default_style = ned
        lyr.styles = [zed]
        self.cat.save(lyr)
        self.assertEqual("topp:ned", lyr.default_style)
        self.assertEqual([zed], lyr.styles)

        lyr.refresh()
        self.assertEqual("topp:ned", lyr.default_style.fqn)
        self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles])

    def testWorkspaceCreate(self):
        ws = self.cat.get_workspace("acme")
        self.assertEqual(None, ws)
        self.cat.create_workspace("acme", "http://example.com/acme")
        ws = self.cat.get_workspace("acme")
        self.assertEqual("acme", ws.name)

    def testWorkspaceDelete(self): 
        self.cat.create_workspace("foo", "http://example.com/foo")
        ws = self.cat.get_workspace("foo")
        self.cat.delete(ws)
        ws = self.cat.get_workspace("foo")
        self.assert_(ws is None)

    def testWorkspaceDefault(self):
        # save orig
        orig = self.cat.get_default_workspace()
        neu = self.cat.create_workspace("neu", "http://example.com/neu")
        try:
            # make sure setting it works
            self.cat.set_default_workspace("neu")
            ws = self.cat.get_default_workspace()
            self.assertEqual('neu', ws.name)
        finally:
            # cleanup and reset to the way things were
            self.cat.delete(neu)
            self.cat.set_default_workspace(orig.name)
            ws = self.cat.get_default_workspace()
            self.assertEqual(orig.name, ws.name)

    def testFeatureTypeDelete(self):
        pass

    def testCoverageDelete(self):
        pass

    def testDataStoreDelete(self):
        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)
        states.enabled = False
        self.assert_(states.enabled == False)
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == False)

        states.enabled = True
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)

    def testLayerGroupSave(self):
        tas = self.cat.get_layergroup("tasmania")

        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        tas.layers = tas.layers[:-1]
        tas.styles = tas.styles[:-1]

        self.cat.save(tas)

        # this verifies the local state
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)

        # force a refresh to check the remote state
        tas.refresh()
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)
Beispiel #44
0
def _register_cascaded_layers(service, owner=None):
    """
    Register layers for a cascading WMS
    """
    if service.type == "WMS" or service.type == "OWS":
        cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password)
        # Can we always assume that it is geonode?
        # Should cascading layers have a separate workspace?
        cascade_ws = cat.get_workspace(service.name)
        if cascade_ws is None:
            cascade_ws = cat.create_workspace(service.name, "cascade")
        try:
            store = cat.get_store(service.name, cascade_ws)
        except Exception:
            store = cat.create_wmsstore(service.name, cascade_ws)
            cat.save(store)
        wms = WebMapService(service.base_url)
        layers = list(wms.contents)
        count = 0
        for layer in layers:
            lyr = cat.get_resource(layer, store, cascade_ws)
            if lyr is None:
                if service.type in ["WMS", "OWS"]:
                    resource = cat.create_wmslayer(cascade_ws, store, layer)
                elif service.type == "WFS":
                    resource = cat.create_wfslayer(cascade_ws, store, layer)

                if resource:
                    bbox = resource.latlon_bbox
                    cascaded_layer, created = Layer.objects.get_or_create(
                        typename="%s:%s" % (cascade_ws.name, resource.name),
                        service=service,
                        defaults={
                            "name": resource.name,
                            "workspace": cascade_ws.name,
                            "store": store.name,
                            "storeType": store.resource_type,
                            "title": resource.title or "No title provided",
                            "abstract": resource.abstract or "No abstract provided",
                            "owner": None,
                            "uuid": str(uuid.uuid4()),
                            "bbox_x0": bbox[0],
                            "bbox_x1": bbox[1],
                            "bbox_y0": bbox[2],
                            "bbox_y1": bbox[3],
                        },
                    )

                    if created:
                        cascaded_layer.save()
                        if cascaded_layer is not None and cascaded_layer.bbox is None:
                            cascaded_layer._populate_from_gs(gs_resource=resource)
                        cascaded_layer.set_default_permissions()

                        service_layer, created = ServiceLayer.objects.get_or_create(
                            service=service, typename=cascaded_layer.name
                        )
                        service_layer.layer = cascaded_layer
                        service_layer.title = (cascaded_layer.title,)
                        service_layer.description = (cascaded_layer.abstract,)
                        service_layer.styles = cascaded_layer.styles
                        service_layer.save()

                        count += 1
                    else:
                        logger.error("Resource %s from store %s could not be saved as layer" % (layer, store.name))
        message = "%d Layers Registered" % count
        return_dict = {"status": "ok", "msg": message}
        return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200)
    elif service.type == "WCS":
        return HttpResponse("Not Implemented (Yet)", status=501)
    else:
        return HttpResponse("Invalid Service Type", status=400)
Beispiel #45
0
def _register_cascaded_layers(service, owner=None):
    """
    Register layers for a cascading WMS
    """
    if service.type == 'WMS' or service.type == "OWS":
        cat = Catalog(settings.OGC_SERVER['default']['LOCATION'] + "rest", 
                        _user , _password)
        # Can we always assume that it is geonode?
        # Should cascading layers have a separate workspace?
        cascade_ws = cat.get_workspace(settings.CASCADE_WORKSPACE)
        if cascade_ws is None:
            cascade_ws = cat.create_workspace(settings.CASCADE_WORKSPACE, 'cascade')
        try:
            store = cat.get_store(service.name,cascade_ws)
        except Exception:
            store = cat.create_wmsstore(service.name, cascade_ws)
        wms = WebMapService(service.base_url)
        layers = list(wms.contents)

        count = 0
        for layer in layers:
            lyr = cat.get_resource(layer, store, cascade_ws)
            if lyr is None:
                if service.type in ["WMS","OWS"]:
                    resource = cat.create_wmslayer(cascade_ws, store, layer)
                elif service.type == "WFS":
                    resource = cat.create_wfslayer(cascade_ws, store, layer)

                if resource:
                    cascaded_layer, created = Layer.objects.get_or_create(
                        typename = "%s:%s" % (cascade_ws.name, resource.name),
                        defaults = {
                            "name": resource.name,
                            "workspace": cascade_ws.name,
                            "store": store.name,
                            "storeType": store.resource_type,
                            "title": resource.title or 'No title provided',
                            "abstract": resource.abstract or 'No abstract provided',
                            "owner": None,
                            "uuid": str(uuid.uuid4())
                        })


                    if created:
                        cascaded_layer.save()
                        if cascaded_layer is not None and cascaded_layer.bbox is None:
                            cascaded_layer._populate_from_gs(gs_resource=resource)
                        cascaded_layer.set_default_permissions()

                        service_layer, created = ServiceLayer.objects.get_or_create(
                            service=service,
                            typename=cascaded_layer.name
                        )
                        service_layer.layer = cascaded_layer
                        service_layer.title=cascaded_layer.title,
                        service_layer.description=cascaded_layer.abstract,
                        service_layer.styles=cascaded_layer.styles
                        service_layer.save()

                        count += 1
                    else:
                        logger.error("Resource %s from store %s could not be saved as layer" % (layer, store.name))
        message = "%d Layers Registered" % count
        return_dict = {'status': 'ok', 'msg': message }
        return HttpResponse(json.dumps(return_dict),
                            mimetype='application/json',
                            status=200)
    elif service.type == 'WCS':
        return HttpResponse('Not Implemented (Yet)', status=501)
    else:
        return HttpResponse('Invalid Service Type', status=400)
Beispiel #46
0
class CatalogUtils:
    cat = None

    def __init__(self, url=None, user=None, pw=None):
        """
        :param url: example: http://localhost:8080/geoserver/rest/
        :param user:
        :param pw:
        """
        self.cat = Catalog(url, username=user, password=pw)

    def ws(self, ws_name):
        return self.cat.get_workspace(ws_name)

    def get_shapefile(self, path):
        """
        Creates a dictionary of all the files in a shapefile (.shp, .dbf, .xml, etc.)
        :param path: path to unarchived shapefile, without extension
        :return:
        """
        return geoserver.util.shapefile_and_friends(path)

    def store_exists(self, name):
        for i in self.cat.get_stores():
            if i.name == name:
                return True
        return False

    def add_shapefile(self, data, name=None, ws=None):
        """
        Adds a shapefile to a GeoServer instance as a Feature Store
        :param data: the path to the shapefile  (.shp) or the zipped shapefile (.zip)
        :param name: the name of the feature store. if None, the file name will be used
        :param ws: the name of the workspace. if None, the default workspace will be used
        :return: the created feature store
        """

        if name is None:
            name = os.path.split(data)[-1]
            if name.endswith('.zip') or name.endswith('.shp'):
                name = name[:name.rindex('.')].upper()
                # name = name[:name.rindex('.')]
                print name

        if self.store_exists(name):
            print "Store exists", name
            raise Exception(
                "A store with this name already exists... please change the name."
            )

        if data.endswith('.shp'):
            data = self.get_shapefile(data[:data.rindex('.')])
        elif data.endswith('.zip'):
            pass
        else:
            raise Exception(
                "'data' must be the path to a shapefile (.shp) or zipped shapefile."
            )

        if ws is not None:
            ws = self.ws(ws)
            if ws is None:
                raise Exception("The requested workspace does not exist.")
        else:
            ws = self.cat.get_default_workspace()
            if ws is None:
                raise Exception("No default workspace found!")
        print('adding: ' + name)
        self.cat.create_featurestore(name="GMU" + name,
                                     data=data,
                                     workspace=ws)
        return self.cat.get_store("GMU" + name)
Beispiel #47
0
from config import get_config
from geoserver.catalog import Catalog

geoserver = Catalog(
    get_config('geoserver.restUrl'),
    get_config('geoserver.user'),
    get_config('geoserver.password'),
)

# create workspace if not exists, a workspace is mandatory to work with geoserver
workspace_name = get_config('geoserver.workspace')
workspace = geoserver.get_workspace(workspace_name)
if workspace is None:
    geoserver.create_workspace(
        workspace_name,
        get_config('geoserver.hostUrl') + workspace_name)
    geoserver.reload()

geoserver_connection = geoserver
workspace_obj = workspace
class GeoGigUploaderBase(ImportHelper):
    def __init__(self, *args, **kwargs):
        super(GeoGigUploaderBase, self).__init__(*args, **kwargs)
        setUpModule()  # this isn't available when being used in other module

    def setUp(self):
        self.admin_user = self.create_user('admin', 'admin', is_superuser=True)
        self.non_admin_user = self.create_user('non_admin', 'non_admin')
        self.catalog = Catalog(ogc_server_settings.internal_rest,
                               *ogc_server_settings.credentials)
        if self.catalog.get_workspace('geonode') is None:
            self.catalog.create_workspace('geonode', 'http://www.geonode.org/')
        self.workspace = 'geonode'
        self.datastoreNames = []

    def tearDown(self):
        """Clean up geoserver/geogig catalog.
        """
        # delete stores (will cascade to delete layers)
        for store_name in self.datastoreNames:
            self.catalog.delete(self.catalog.get_store(store_name),
                                recurse=True)

        # delete repository reference in geoserver
        for store_name in self.datastoreNames:
            self.remove_geogig_repo(store_name)

        # geoserver can leave connections open - HACK HACK HACK
        self.free_geogig_connections()

    # HACK HACK HACK -- sometimes connections from geoserver to geogig are left open.  This kills the postgresql backend!
    #  this is a major hammer.  Once geoserver/geogig are better at cleaning up, remove this.
    def free_geogig_connections(self):
        with db.connections["geogig"].cursor() as c:
            c.execute(
                "select pg_terminate_backend(pid) from pg_stat_activity where application_name = 'PostgreSQL JDBC Driver' or application_name='geogig'"
            )

    # aggressive delete of the repo (mostly cleans up after itself)
    #  call the geogig rest API DELETE
    def remove_geogig_repo(self, ref_name):
        username = ogc_server_settings.credentials.username
        password = ogc_server_settings.credentials.password
        url = ogc_server_settings.rest
        http = httplib2.Http(disable_ssl_certificate_validation=False)
        http.add_credentials(username, password)
        netloc = urlparse(url).netloc
        http.authorizations.append(
            httplib2.BasicAuthentication((username, password), netloc, url, {},
                                         None, None, http))
        rest_url = ogc_server_settings.LOCATION + \
            "geogig/repos/" + ref_name + "/delete.json"
        resp, content = http.request(rest_url, 'GET')
        response = json.loads(content)
        token = response["response"]["token"]
        rest_url = ogc_server_settings.LOCATION + \
            "geogig/repos/" + ref_name + "?token=" + token
        resp, content = http.request(rest_url, 'DELETE')

    # convenience method to load in the test dataset
    # return a (geonode) layer
    # the layer will be in Geoserver and Geonode
    # self.catalog.get_layer(layer.name) -- to get the Geoserver Layer
    def fully_import_file(self,
                          path,
                          fname,
                          start_time_column,
                          end_time_column=None):
        # setup time
        if end_time_column is None:
            time_config = {
                'convert_to_date': [start_time_column],
                'start_date': start_time_column,
                'configureTime': True
            }
        else:
            time_config = {
                'convert_to_date': [start_time_column, end_time_column],
                'start_date': start_time_column,
                'end_date': end_time_column,
                'configureTime': True
            }

        name = os.path.splitext(fname)[0] + "_" + str(uuid.uuid1())[:8]
        self.datastoreNames.append(name)  # remember for future deletion

        full_fname = os.path.join(path, fname)
        configs = self.prepare_file_for_import(full_fname)
        configs[0].update({'name': name})
        configs[0].update({'layer_name': name})
        configs[0].update(time_config)

        # configure the datastore/repo
        configs[0]['geoserver_store'] = {}
        configs[0]['geoserver_store']['type'] = 'geogig'
        configs[0]['geoserver_store']['name'] = name
        configs[0]['geoserver_store']['create'] = 'true'
        configs[0]['geoserver_store']['branch'] = 'master'
        configs[0]['geoserver_store'][
            'geogig_repository'] = "geoserver://" + name

        result = self.generic_import(fname, path=path, configs=configs)
        return result

    def import_file(self, path, configs=None):
        """Imports the file.
        """
        if configs is None:
            configs = []
        self.assertTrue(os.path.exists(path), path)

        # run ogr2ogr
        ogr = OGRImport(path)
        layers = ogr.handle(configuration_options=configs)

        return layers

    def generic_import(self, filename, path, configs=None):
        if configs is None:
            configs = [{'index': 0}]

        path = os.path.join(path, filename)
        results = self.import_file(path, configs=configs)
        layer_results = []
        for result in results:
            layer = Layer.objects.get(name=result[0])
            self.assertEqual(layer.srid, 'EPSG:4326')
            self.assertTrue(layer.store in self.datastoreNames)
            self.assertEqual(layer.storeType, 'dataStore')

            if not path.endswith('zip'):
                self.assertGreaterEqual(layer.attributes.count(),
                                        DataSource(path)[0].num_fields)

            layer_results.append(layer)

        return layer_results[0]

    def prepare_file_for_import(self, filepath):
        """ Prepares the file path provided for import; performs some housekeeping, uploads & configures the file.
            Returns a list of dicts of the form {'index': <layer_index>, 'upload_layer_id': <upload_layer_id>}
                these may be used as configuration options for importing all of the layers in the file.
        """
        # Make a copy of the test file, as it's removed in configure_upload()
        filename = os.path.basename(filepath)
        tmppath = os.path.join('/tmp', filename)
        shutil.copy(filepath, tmppath)

        # upload & configure_upload expect closed file objects
        #    This is heritage from originally being closely tied to a view passing request.Files
        of = open(tmppath, 'rb')
        of.close()
        files = [of]
        uploaded_data = self.upload(files, self.admin_user)
        self.configure_upload(uploaded_data, files)
        configs = [{
            'index': l.index,
            'upload_layer_id': l.id
        } for l in uploaded_data.uploadlayer_set.all()]
        return configs

    def create_user(self, username, password, **kwargs):
        """Convenience method for creating users.
        """
        user, created = User.objects.get_or_create(username=username, **kwargs)

        if created:
            user.set_password(password)
            user.save()

        return user
Beispiel #49
0
class ModifyingTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog("http://localhost:8080/geoserver/rest")

    def testFeatureTypeSave(self):
        # test saving round trip
        rs = self.cat.get_resource("bugsites")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"
        enabled = rs.enabled

        # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(new_abstract, rs.abstract)
        self.assertEqual(enabled, rs.enabled)

        # Change keywords on server
        rs.keywords = ["bugsites", "gsconfig"]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(["bugsites", "gsconfig"], rs.keywords)
        self.assertEqual(enabled, rs.enabled)
        
        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(
                        [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
                        rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)


        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(old_abstract, rs.abstract)

    def testDataStoreCreate(self):
        ds = self.cat.create_datastore("vector_gsconfig")
        ds.connection_parameters.update(
            host="localhost", port="5432", database="db", user="******",
            passwd="password", dbtype="postgis")
        self.cat.save(ds)

    def testDataStoreModify(self):
        ds = self.cat.get_store("sf")
        self.assertFalse("foo" in ds.connection_parameters)
        ds.connection_parameters = ds.connection_parameters
        ds.connection_parameters["foo"] = "bar"
        orig_ws = ds.workspace.name
        self.cat.save(ds)
        ds = self.cat.get_store("sf")
        self.assertTrue("foo" in ds.connection_parameters)
        self.assertEqual("bar", ds.connection_parameters["foo"])
        self.assertEqual(orig_ws, ds.workspace.name)

    def testDataStoreCreateAndThenAlsoImportData(self):
        ds = self.cat.create_datastore("gsconfig_import_test")
        ds.connection_parameters.update(
            host="localhost", port="5432", database="db", user="******",
            passwd="password", dbtype="postgis")
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test")
        self.cat.add_data_to_store(ds, "import", {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        })

    def testCoverageStoreCreate(self):
        ds = self.cat.create_coveragestore2("coverage_gsconfig")
        ds.data_url = "file:data/mytiff.tiff"
        self.cat.save(ds)

    def testCoverageStoreModify(self):
        cs = self.cat.get_store("sfdem")
        self.assertEqual("GeoTIFF", cs.type)
        cs.type = "WorldImage"
        self.cat.save(cs)
        cs = self.cat.get_store("sfdem")
        self.assertEqual("WorldImage", cs.type)

        # not sure about order of test runs here, but it might cause problems
        # for other tests if this layer is misconfigured
        cs.type = "GeoTIFF"
        self.cat.save(cs) 

    def testCoverageSave(self):
        # test saving round trip
        rs = self.cat.get_resource("Arc_Sample")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"

        # # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(new_abstract, rs.abstract)

        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(old_abstract, rs.abstract)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(
            [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
            rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)

        srs_before = set(['EPSG:4326'])
        srs_after = set(['EPSG:4326', 'EPSG:3785'])
        formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF'])
        formats_after = set(["PNG", "GIF", "TIFF"])

        # set and save request_srs_list
        self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list))
        rs.request_srs_list = rs.request_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list))

        # set and save response_srs_list
        self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list))
        rs.response_srs_list = rs.response_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list))

        # set and save supported_formats
        self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats))
        rs.supported_formats = ["PNG", "GIF", "TIFF"]
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats))


    def testFeatureTypeCreate(self):
        shapefile_plus_sidecars = shapefile_and_friends("test/data/states")
        expected = {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        }

        self.assertEqual(len(expected), len(shapefile_plus_sidecars))
        for k, v in expected.iteritems():
            self.assertEqual(v, shapefile_plus_sidecars[k])
 
        sf = self.cat.get_workspace("sf")
        self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)

        self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None)

        self.assertRaises(
            ConflictingDataError, 
            lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)
        )

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf)
        )

        bogus_shp = {
            'shp': 'test/data/Pk50095.tif',
            'shx': 'test/data/Pk50095.tif',
            'dbf':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf)
        )

        lyr = self.cat.get_layer("states_test")
        self.cat.delete(lyr)
        self.assert_(self.cat.get_layer("states_test") is None)


    def testCoverageCreate(self):
        tiffdata = {
            'tiff': 'test/data/Pk50095.tif',
            'tfw':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        sf = self.cat.get_workspace("sf")
        # TODO: Uploading WorldImage file no longer works???
        # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf)

        # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None)

        # self.assertRaises(
        #         ConflictingDataError, 
        #         lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf)
        # )

        self.assertRaises(
            UploadError, 
            lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf)
        )

        bogus_tiff = {
            'tiff': 'test/data/states.shp',
            'tfw': 'test/data/states.shx',
            'prj': 'test/data/states.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster", bogus_tiff)
        )

    def testLayerSave(self):
        # test saving round trip
        lyr = self.cat.get_layer("states")
        old_attribution = lyr.attribution
        new_attribution = "Not the original attribution"

        # change attribution on server
        lyr.attribution = new_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(new_attribution, lyr.attribution)

        # Restore attribution
        lyr.attribution = old_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(old_attribution, lyr.attribution)

        self.assertEqual(lyr.default_style.name, "population")
     
        old_default_style = lyr.default_style
        lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next()
        lyr.styles = [old_default_style]
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(lyr.default_style.name, "pophatch")
        self.assertEqual([s.name for s in lyr.styles], ["population"])


    def testStyles(self):
        # upload new style, verify existence
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Fred", fred.sld_title)

        # replace style, verify changes
        self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True)
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Ted", fred.sld_title)

        # delete style, verify non-existence
        self.cat.delete(fred, purge=True)
        self.assert_(self.cat.get_style("fred") is None)

        # attempt creating new style
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assertEqual("Fred", fred.sld_title)

    def testWorkspaceCreate(self):
        ws = self.cat.get_workspace("acme")
        self.assertEqual(None, ws)
        self.cat.create_workspace("acme", "http://example.com/acme")
        ws = self.cat.get_workspace("acme")
        self.assertEqual("acme", ws.name)

    def testWorkspaceDelete(self): 
        self.cat.create_workspace("foo", "http://example.com/foo")
        ws = self.cat.get_workspace("foo")
        self.cat.delete(ws)
        ws = self.cat.get_workspace("foo")
        self.assert_(ws is None)

    def testFeatureTypeDelete(self):
        pass

    def testCoverageDelete(self):
        pass

    def testDataStoreDelete(self):
        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)
        states.enabled = False
        self.assert_(states.enabled == False)
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == False)

        states.enabled = True
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)

    def testLayerGroupSave(self):
        tas = self.cat.get_layergroup("tasmania")

        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        tas.layers = tas.layers[:-1]
        tas.styles = tas.styles[:-1]

        self.cat.save(tas)

        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)
Beispiel #50
0
#sendToCatalog(catalog,sys.argv[1])

if __name__ == "__main__":
    if (len(sys.argv) != 4):
        print "Error with arguments. Must enter almost three"
        sys.exit(-1)
    print sys.argv[1]
    name_file = sys.argv[1].split("/")[-1]
    scenario = sys.argv[2]
    nameStore = sys.argv[3]
    cat = Catalog(geoserver_path)
    #pdb.set_trace()

    try:
        print name_file, sys.argv[1]
        vk = cat.get_workspace(scenario)
        if vk == None:
            vk = cat.create_workspace(scenario, scenario)
        vk.enabled = True
        try:
            cv = cat.create_coveragestore(nameStore, sys.argv[1], vk)
            inf = CoverageStore(cat, vk, scenario)
            inf.fetch()
            cat.save(inf)
            f.write("Processed %s" % (name_file))
        except Exception:
            print "Catalogued %s!" % (name_file)
        print nameStore, name_file, scenario
        comman = 'curl -i --data "layerName=%s&coverageStore=%s&imageurl=ftp://131.254.204.143:21/../../usr/share/tomcat7/apache-tomcat-7.0.53/webapps/geoserver/data/data/%s/%s/%s.geotiff" http://172.18.242.41:8043/IDV' % (
            name_file, nameStore, scenario, nameStore, nameStore)
        print comman
Beispiel #51
0
  print 'USAGE: populate [GEOSERVER] [DBSERVER]'
  sys.exit(1)

appserver = sys.argv[1]
dbserver = sys.argv[2]

ws_name = 'naturalearth'
ds_name = 'ne_pg'
lg_name = "ne_pg"

cat = Catalog(appserver + '/rest')

# check if workspace exists, bail if it does (safter than deleting it)
if any(ws.name == ws_name for ws in cat.get_workspaces()):
  print 'workspace already exists...'
  ws = cat.get_workspace(ws_name)
else:
  print 'creating workspace...'
  ws = cat.create_workspace(ws_name, 'http://www.naturalearth.org')

if any(ds.workspace.name == ws.name and ds.name == ds_name for ds in cat.get_stores()):
  print 'datastore already exists...'
  ds = cat.get_store(ds_name, ws_name)
else:
  print 'creating datastore'
  ds = cat.create_datastore(ds_name, ws.name)
  ds.connection_parameters.update(
    host=dbserver,
    port='5432',
    database='ne_tmp',
    user='******',
def publishGeoserver(appdef, progress):
    viewCrs = appdef["Settings"]["App view CRS"]
    usesGeoServer = False
    for applayer in appdef["Layers"]:
        if applayer.method != METHOD_FILE:
            if applayer.layer.type(
            ) == applayer.layer.VectorLayer and applayer.layer.providerType(
            ).lower() != "wfs":
                usesGeoServer = True
    if not usesGeoServer:
        return
    progress.setText("Publishing to GeoServer")
    progress.setProgress(0)
    geoserverUrl = appdef["Deploy"]["GeoServer url"] + "/rest"
    geoserverPassword = appdef["Deploy"]["GeoServer password"]
    geoserverUsername = appdef["Deploy"]["GeoServer username"]
    workspaceName = appdef["Deploy"]["GeoServer workspace"]
    dsName = "ds_" + workspaceName
    host = appdef["Deploy"]["PostGIS host"]
    port = appdef["Deploy"]["PostGIS port"]
    postgisUsername = appdef["Deploy"]["PostGIS username"]
    postgisPassword = appdef["Deploy"]["PostGIS password"]
    database = appdef["Deploy"]["PostGIS database"]
    schema = appdef["Deploy"]["PostGIS schema"]
    catalog = Catalog(geoserverUrl, geoserverUsername, geoserverPassword)
    workspace = catalog.get_workspace(workspaceName)
    if workspace is None:
        workspace = catalog.create_workspace(workspaceName, workspaceName)
    try:
        store = catalog.get_store(dsName, workspace)
        resources = store.get_resources()
        for resource in resources:
            layers = catalog.get_layers(resource)
            for layer in layers:
                catalog.delete(layer)
            catalog.delete(resource)
        catalog.delete(store)
    except Exception:
        pass
    try:
        store = catalog.get_store(dsName, workspace)
    except FailedRequestError:
        store = None
    for i, applayer in enumerate(appdef["Layers"]):
        layer = applayer.layer
        if applayer.method != METHOD_FILE and applayer.method != METHOD_DIRECT:
            name = safeName(layer.name())
            sld, icons = getGsCompatibleSld(layer)
            if sld is not None:
                catalog.create_style(name, sld, True)
                uploadIcons(icons, geoserverUsername, geoserverPassword,
                            catalog.gs_base_url)
            if layer.type() == layer.VectorLayer:
                if applayer.method == METHOD_WFS_POSTGIS or applayer.method == METHOD_WMS_POSTGIS:
                    if store is None:
                        store = catalog.create_datastore(dsName, workspace)
                        store.connection_parameters.update(
                            host=host,
                            port=str(port),
                            database=database,
                            user=postgisUsername,
                            schema=schema,
                            passwd=postgisPassword,
                            dbtype="postgis")
                        catalog.save(store)
                    catalog.publish_featuretype(name, store,
                                                layer.crs().authid())
                else:
                    path = getDataFromLayer(layer, viewCrs)
                    catalog.create_featurestore(name,
                                                path,
                                                workspace=workspace,
                                                overwrite=True)
                gslayer = catalog.get_layer(name)
                r = gslayer.resource
                r.dirty['srs'] = viewCrs
                catalog.save(r)
            elif layer.type() == layer.RasterLayer:
                path = getDataFromLayer(layer, viewCrs)
                catalog.create_coveragestore(name,
                                             path,
                                             workspace=workspace,
                                             overwrite=True)
            if sld is not None:
                publishing = catalog.get_layer(name)
                publishing.default_style = catalog.get_style(name)
                catalog.save(publishing)
        progress.setProgress(int((i + 1) * 100.0 / len(appdef["Layers"])))
def publishGeoserver(appdef, progress):
	viewCrs = appdef["Settings"]["App view CRS"]
	usesGeoServer = False
	for applayer in appdef["Layers"]:
		if applayer.method != METHOD_FILE:
			if applayer.layer.type() == applayer.layer.VectorLayer and applayer.layer.providerType().lower() != "wfs":
				usesGeoServer = True
	if not usesGeoServer:
		return
	progress.setText("Publishing to GeoServer")
	progress.setProgress(0)
	geoserverUrl = appdef["Deploy"]["GeoServer url"] + "/rest"
	geoserverPassword = appdef["Deploy"]["GeoServer password"]
	geoserverUsername = appdef["Deploy"]["GeoServer username"]
	workspaceName = appdef["Deploy"]["GeoServer workspace"]
	dsName = "ds_" + workspaceName
	host = appdef["Deploy"]["PostGIS host"]
	port = appdef["Deploy"]["PostGIS port"]
	postgisUsername = appdef["Deploy"]["PostGIS username"]
	postgisPassword = appdef["Deploy"]["PostGIS password"]
	database = appdef["Deploy"]["PostGIS database"]
	schema = appdef["Deploy"]["PostGIS schema"]
	catalog = Catalog(geoserverUrl, geoserverUsername, geoserverPassword)
	workspace = catalog.get_workspace(workspaceName)
	if workspace is None:
		workspace = catalog.create_workspace(workspaceName, workspaceName)
	try:
		store = catalog.get_store(dsName, workspace)
		resources = store.get_resources()
		for resource in resources:
			layers = catalog.get_layers(resource)
			for layer in layers:
				catalog.delete(layer)
			catalog.delete(resource)
		catalog.delete(store)
	except Exception:
		pass
	try:
		store = catalog.get_store(dsName, workspace)
	except FailedRequestError:
		store = None
	for i, applayer in enumerate(appdef["Layers"]):
		layer = applayer.layer
		if applayer.method != METHOD_FILE and applayer.method != METHOD_DIRECT:
			name = safeName(layer.name())
			sld, icons = getGsCompatibleSld(layer)
			if sld is not None:
				catalog.create_style(name, sld, True)
				uploadIcons(icons, geoserverUsername, geoserverPassword, catalog.gs_base_url)
			if layer.type() == layer.VectorLayer:
				if applayer.method == METHOD_WFS_POSTGIS or applayer.method == METHOD_WMS_POSTGIS:
					if store is None:
						store = catalog.create_datastore(dsName, workspace)
						store.connection_parameters.update(
							host=host, port=str(port), database=database, user=postgisUsername, schema=schema,
							passwd=postgisPassword, dbtype="postgis")
						catalog.save(store)
					catalog.publish_featuretype(name, store, layer.crs().authid())
				else:
					path = getDataFromLayer(layer, viewCrs)
					catalog.create_featurestore(name,
													path,
													workspace=workspace,
													overwrite=True)
				gslayer = catalog.get_layer(name)
				r = gslayer.resource
				r.dirty['srs'] = viewCrs
				catalog.save(r)
			elif layer.type() == layer.RasterLayer:
				path = getDataFromLayer(layer, viewCrs)
				catalog.create_coveragestore(name,
				                          path,
				                          workspace=workspace,
				                          overwrite=True)
			if sld is not None:
				publishing = catalog.get_layer(name)
				publishing.default_style = catalog.get_style(name)
				catalog.save(publishing)
		progress.setProgress(int((i+1)*100.0/len(appdef["Layers"])))
Beispiel #54
0
from logging.handlers import RotatingFileHandler
from os import path

# Python 3 backported
from collections import OrderedDict

# 3rd party libraries
from geoserver.catalog import Catalog
from geoserver.resource import Coverage, FeatureType
from geoserver.util import shapefile_and_friends

# ############################################################################
# ########## MAIN #############
# ##################################

# connection
cat = Catalog("http://localhost:8080/geoserver/rest", "admin", "geoserver")

# READ
all_layers = cat.get_layers()

print(len(all_layers))

# WRITE
wks_esipe = cat.get_workspace("ESIPE_IG3")
shapefile_plus_sidecars = shapefile_and_friends(
    r"data_samples\idf_RGP_emploi_exh")
feat = cat.create_featurestore("test_gsoncif_write",
                               workspace=wks_esipe,
                               data=shapefile_plus_sidecars)
Beispiel #55
0
class ModifyingTests(unittest.TestCase):

    def setUp(self):
        self.cat = Catalog(GSPARAMS['GSURL'], username=GSPARAMS['GSUSER'], password=GSPARAMS['GSPASSWORD'])

    def testFeatureTypeSave(self):
        # test saving round trip
        rs = self.cat.get_resource("bugsites")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"
        enabled = rs.enabled

        # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(new_abstract, rs.abstract)
        self.assertEqual(enabled, rs.enabled)

        # Change keywords on server
        rs.keywords = ["bugsites", "gsconfig"]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(["bugsites", "gsconfig"], rs.keywords)
        self.assertEqual(enabled, rs.enabled)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(
                        [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
                        rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)


        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(old_abstract, rs.abstract)

    def testDataStoreCreate(self):
        ds = self.cat.create_datastore("vector_gsconfig")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)

    def testPublishFeatureType(self):
        # Use the other test and store creation to load vector data into a database
        # @todo maybe load directly to database?
        try:
            self.testDataStoreCreateAndThenAlsoImportData()
        except FailedRequestError:
            pass
        try:
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            self.cat.delete(lyr)
            self.cat.delete(lyr.resource)
            ds = self.cat.get_store("gsconfig_import_test")
            # make sure it's gone
            self.assert_(self.cat.get_layer('import') is None)
            self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326")
            # and now it's not
            self.assert_(self.cat.get_layer('import') is not None)
        finally:
            # tear stuff down to allow the other test to pass if we run first
            ds = self.cat.get_store("gsconfig_import_test")
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            try:
                if lyr:
                    self.cat.delete(lyr)
                    self.cat.delete(lyr.resource)
                if ds:
                    self.cat.delete(ds)
            except:
                pass

    def testDataStoreModify(self):
        ds = self.cat.get_store("sf")
        self.assertFalse("foo" in ds.connection_parameters)
        ds.connection_parameters = ds.connection_parameters
        ds.connection_parameters["foo"] = "bar"
        orig_ws = ds.workspace.name
        self.cat.save(ds)
        ds = self.cat.get_store("sf")
        self.assertTrue("foo" in ds.connection_parameters)
        self.assertEqual("bar", ds.connection_parameters["foo"])
        self.assertEqual(orig_ws, ds.workspace.name)

    @drop_table('import')
    def testDataStoreCreateAndThenAlsoImportData(self):
        ds = self.cat.create_datastore("gsconfig_import_test")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test")
        self.cat.add_data_to_store(ds, "import", {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        })

    @drop_table('import2')
    def testVirtualTables(self):
        ds = self.cat.create_datastore("gsconfig_import_test2")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test2")
        self.cat.add_data_to_store(ds, "import2", {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        })
        store = self.cat.get_store("gsconfig_import_test2")
        geom = JDBCVirtualTableGeometry('the_geom','MultiPolygon','4326')
        ft_name = 'my_jdbc_vt_test'
        epsg_code = 'EPSG:4326'
        sql = "select * from import2 where 'STATE_NAME' = 'Illinois'"
        keyColumn = None
        parameters = None

        jdbc_vt = JDBCVirtualTable(ft_name, sql, 'false', geom, keyColumn, parameters)
        ft = self.cat.publish_featuretype(ft_name, store, epsg_code, jdbc_virtual_table=jdbc_vt)

    # DISABLED; this test works only in the very particular case
    # "mytiff.tiff" is already present into the GEOSERVER_DATA_DIR
    # def testCoverageStoreCreate(self):
    #     ds = self.cat.create_coveragestore2("coverage_gsconfig")
    #     ds.data_url = "file:test/data/mytiff.tiff"
    #     self.cat.save(ds)

    def testCoverageStoreModify(self):
        cs = self.cat.get_store("sfdem")
        self.assertEqual("GeoTIFF", cs.type)
        cs.type = "WorldImage"
        self.cat.save(cs)
        cs = self.cat.get_store("sfdem")
        self.assertEqual("WorldImage", cs.type)

        # not sure about order of test runs here, but it might cause problems
        # for other tests if this layer is misconfigured
        cs.type = "GeoTIFF"
        self.cat.save(cs)

    def testCoverageSave(self):
        # test saving round trip
        rs = self.cat.get_resource("Arc_Sample")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"

        # # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(new_abstract, rs.abstract)

        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(old_abstract, rs.abstract)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(
            [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
            rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)

        srs_before = set(['EPSG:4326'])
        srs_after = set(['EPSG:4326', 'EPSG:3785'])
        formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF'])
        formats_after = set(["PNG", "GIF", "TIFF"])

        # set and save request_srs_list
        self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list))
        rs.request_srs_list = rs.request_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list))

        # set and save response_srs_list
        self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list))
        rs.response_srs_list = rs.response_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list))

        # set and save supported_formats
        self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats))
        rs.supported_formats = ["PNG", "GIF", "TIFF"]
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats))

    def testWmsStoreCreate(self):
        ws = self.cat.create_wmsstore("wmsstore_gsconfig")
        ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        ws.type = "WMS"
        self.cat.save(ws)

    def testWmsLayer(self):
        self.cat.create_workspace("wmstest", "http://example.com/wmstest")
        wmstest = self.cat.get_workspace("wmstest")
        wmsstore = self.cat.create_wmsstore("wmsstore", wmstest)
        wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        wmsstore.type = "WMS"
        self.cat.save(wmsstore)
        wmsstore = self.cat.get_store("wmsstore")
        self.assertEqual(1, len(self.cat.get_stores(wmstest)))
        available_layers = wmsstore.get_resources(available=True)
        for layer in available_layers:
            # sanitize the layer name - validation will fail on newer geoservers
            name = layer.replace(':', '_')
            new_layer = self.cat.create_wmslayer(wmstest, wmsstore, name, nativeName=layer)
        added_layers = wmsstore.get_resources()
        self.assertEqual(len(available_layers), len(added_layers))

        changed_layer = added_layers[0]
        self.assertEqual(True, changed_layer.advertised)
        self.assertEqual(True, changed_layer.enabled)
        changed_layer.advertised = False
        changed_layer.enabled = False
        self.cat.save(changed_layer)
        self.cat._cache.clear()
        changed_layer = wmsstore.get_resources()[0]
        changed_layer.fetch()
        self.assertEqual(False, changed_layer.advertised)
        self.assertEqual(False, changed_layer.enabled)

        # Testing projection and projection policy changes
        changed_layer.projection = "EPSG:900913"
        changed_layer.projection_policy = "REPROJECT_TO_DECLARED"
        self.cat.save(changed_layer)
        self.cat._cache.clear()
        layer = self.cat.get_layer(changed_layer.name)
        self.assertEqual(layer.resource.projection_policy, changed_layer.projection_policy)
        self.assertEqual(layer.resource.projection, changed_layer.projection)

    def testFeatureTypeCreate(self):
        shapefile_plus_sidecars = shapefile_and_friends("test/data/states")
        expected = {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        }

        self.assertEqual(len(expected), len(shapefile_plus_sidecars))
        for k, v in expected.iteritems():
            self.assertEqual(v, shapefile_plus_sidecars[k])

        sf = self.cat.get_workspace("sf")
        self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)

        self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None)

        self.assertRaises(
            ConflictingDataError,
            lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)
        )

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf)
        )

        bogus_shp = {
            'shp': 'test/data/Pk50095.tif',
            'shx': 'test/data/Pk50095.tif',
            'dbf': 'test/data/Pk50095.tfw',
            'prj': 'test/data/Pk50095.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf)
        )

        lyr = self.cat.get_layer("states_test")
        self.cat.delete(lyr)
        self.assert_(self.cat.get_layer("states_test") is None)


    def testCoverageCreate(self):
        tiffdata = {
            'tiff': 'test/data/Pk50095.tif',
            'tfw':  'test/data/Pk50095.tfw',
            'prj':  'test/data/Pk50095.prj'
        }

        sf = self.cat.get_workspace("sf")
        ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf)

        self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None)

        self.assertRaises(
                ConflictingDataError,
                lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf)
        )

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf)
        )

        bogus_tiff = {
            'tiff': 'test/data/states.shp',
            'tfw':  'test/data/states.shx',
            'prj':  'test/data/states.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster", bogus_tiff)
        )

        ft_ext = self.cat.create_coveragestore_external_geotiff("Pk50095_ext", 'file:test/data/Pk50095.tif', sf)

    def testLayerSave(self):
        # test saving round trip
        lyr = self.cat.get_layer("states")
        old_attribution = lyr.attribution
        new_attribution = { 'title': 'Not the original attribution',
                            'width': '123',
                            'height': '321',
                            'href': 'http://www.georchestra.org',
                            'url': 'https://www.cigalsace.org/portail/cigal/documents/page/mentions-legales/Logo_geOrchestra.jpg',
                            'type': 'image/jpeg' }

        # change attribution on server
        lyr.attribution = new_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(new_attribution, lyr.attribution)

        # Restore attribution
        lyr.attribution = old_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(old_attribution, lyr.attribution)

        self.assertEqual(lyr.default_style.name, "population")

        old_default_style = lyr.default_style
        lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next()
        lyr.styles = [old_default_style]
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(lyr.default_style.name, "pophatch")
        self.assertEqual([s.name for s in lyr.styles], ["population"])


    def testStyles(self):
        # check count before tests (upload)
        count = len(self.cat.get_styles())

        # upload new style, verify existence
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Fred", fred.sld_title)

        # replace style, verify changes
        self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True)
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Ted", fred.sld_title)

        # delete style, verify non-existence
        self.cat.delete(fred, purge=True)
        self.assert_(self.cat.get_style("fred") is None)

        # attempt creating new style
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assertEqual("Fred", fred.sld_title)

        # verify it can be found via URL and check the name
        f = self.cat.get_style_by_url(fred.href)
        self.assert_(f is not None)
        self.assertEqual(f.name, fred.name)

        # compare count after upload
        self.assertEqual(count +1, len(self.cat.get_styles()))

        # attempt creating a new style without "title"
        self.cat.create_style("notitle", open("test/notitle.sld").read())
        notitle = self.cat.get_style("notitle")
        self.assertEqual(None, notitle.sld_title)

    def testWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp")

        jed = self.cat.get_style("jed", workspace="blarny")
        self.assert_(jed is None)
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)
        jed = self.cat.get_style("topp:jed")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)

        # replace style, verify changes
        self.cat.create_style("jed", open("test/ted.sld").read(), overwrite=True, workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Ted", jed.sld_title)

        # delete style, verify non-existence
        self.cat.delete(jed, purge=True)
        self.assert_(self.cat.get_style("jed", workspace="topp") is None)

        # attempt creating new style
        self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assertEqual("Fred", jed.sld_title)

        # verify it can be found via URL and check the full name
        f = self.cat.get_style_by_url(jed.href)
        self.assert_(f is not None)
        self.assertEqual(f.fqn, jed.fqn)

    def testLayerWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("ned", open("test/fred.sld").read(), overwrite=True, workspace="topp")
        self.cat.create_style("zed", open("test/ted.sld").read(), overwrite=True, workspace="topp")
        ned = self.cat.get_style("ned", workspace="topp")
        zed = self.cat.get_style("zed", workspace="topp")
        self.assert_(ned is not None)
        self.assert_(zed is not None)

        lyr = self.cat.get_layer("states")
        lyr.default_style = ned
        lyr.styles = [zed]
        self.cat.save(lyr)
        self.assertEqual("topp:ned", lyr.default_style)
        self.assertEqual([zed], lyr.styles)

        lyr.refresh()
        self.assertEqual("topp:ned", lyr.default_style.fqn)
        self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles])

    def testWorkspaceCreate(self):
        ws = self.cat.get_workspace("acme")
        self.assertEqual(None, ws)
        self.cat.create_workspace("acme", "http://example.com/acme")
        ws = self.cat.get_workspace("acme")
        self.assertEqual("acme", ws.name)

    def testWorkspaceDelete(self):
        self.cat.create_workspace("foo", "http://example.com/foo")
        ws = self.cat.get_workspace("foo")
        self.cat.delete(ws)
        ws = self.cat.get_workspace("foo")
        self.assert_(ws is None)

    def testWorkspaceDefault(self):
        # save orig
        orig = self.cat.get_default_workspace()
        neu = self.cat.create_workspace("neu", "http://example.com/neu")
        try:
            # make sure setting it works
            self.cat.set_default_workspace("neu")
            ws = self.cat.get_default_workspace()
            self.assertEqual('neu', ws.name)
        finally:
            # cleanup and reset to the way things were
            self.cat.delete(neu)
            self.cat.set_default_workspace(orig.name)
            ws = self.cat.get_default_workspace()
            self.assertEqual(orig.name, ws.name)

    def testFeatureTypeDelete(self):
        pass

    def testCoverageDelete(self):
        pass

    def testDataStoreDelete(self):
        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)
        states.enabled = False
        self.assert_(states.enabled == False)
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == False)

        states.enabled = True
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)

    def testLayerGroupSave(self):
        tas = self.cat.get_layergroup("tasmania")

        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        tas.layers = tas.layers[:-1]
        tas.styles = tas.styles[:-1]

        self.cat.save(tas)

        # this verifies the local state
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)

        # force a refresh to check the remote state
        tas.refresh()
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)

    def testImageMosaic(self):
        """
            Test case for Issue #110
        """
        # testing the mosaic creation
        name = 'cea_mosaic'
        data = open('test/data/mosaic/cea.zip', 'rb')
        self.cat.create_imagemosaic(name, data)

        # get the layer resource back
        self.cat._cache.clear()
        resource = self.cat.get_layer(name).resource

        self.assert_(resource is not None)

        # delete granule from mosaic
        coverage = name
        store = self.cat.get_store(name)
        granule_id = name + '.1'
        self.cat.mosaic_delete_granule(coverage, store, granule_id)


    def testTimeDimension(self):
        sf = self.cat.get_workspace("sf")
        files = shapefile_and_friends(os.path.join(gisdata.GOOD_DATA, "time", "boxes_with_end_date"))
        self.cat.create_featurestore("boxes_with_end_date", files, sf)

        get_resource = lambda: self.cat._cache.clear() or self.cat.get_layer('boxes_with_end_date').resource

        # configure time as LIST
        resource = get_resource()
        timeInfo = DimensionInfo("time", "true", "LIST", None, "ISO8601", None, attribute="date")
        resource.metadata = {'time':timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual("LIST", timeInfo.presentation)
        self.assertEqual(True, timeInfo.enabled)
        self.assertEqual("date", timeInfo.attribute)
        self.assertEqual("ISO8601", timeInfo.units)

        # disable time dimension
        timeInfo = resource.metadata['time']
        timeInfo.enabled = False
        # since this is an xml property, it won't get written unless we modify it
        resource.metadata = {'time' : timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual(False, timeInfo.enabled)

        # configure with interval, end_attribute and enable again
        timeInfo.enabled = True
        timeInfo.presentation = 'DISCRETE_INTERVAL'
        timeInfo.resolution = '3 days'
        timeInfo.end_attribute = 'enddate'
        resource.metadata = {'time' : timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual(True, timeInfo.enabled)
        self.assertEqual('DISCRETE_INTERVAL', timeInfo.presentation)
        self.assertEqual('3 days', timeInfo.resolution_str())
        self.assertEqual('enddate', timeInfo.end_attribute)
                             auth=('admin', 'geoserver1'),
                             data=payload,
                             headers=headers)

        layerurl = '%s/geoserver/rest/layers/%s' % (geoserverurl, layername)
        layerheaders = {'Content-type': 'application/json'}
        jsonstr = {'layer': {'defaultStyle': {'name': layername}}}
        layerpayload = json.dumps(jsonstr)
        layerresp = requests.put(layerurl,
                                 auth=(user, pw),
                                 data=layerpayload,
                                 headers=layerheaders)
        # pubilsh grouplayers
    geourl = "%s/geoserver/rest/" % (geoserverurl)  # the url of geoserver
    geocat = Catalog(geourl, user, pw)  # create a Catalog object
    workspace = geocat.get_workspace(targeworkspace)  # workspace name
    layers = geocat.get_layers()
    lys = []
    for layer in layersconfig:
        size = len(targeworkspace) + 1
        isingeoserver = False
        if (layernames.__contains__(layer)):
            for geoserverlyr in layers:
                if geoserverlyr.name[size:] == layer:
                    isingeoserver = True
                    lys.append(targeworkspace + ":" + layer)
                    break
        else:
            print(layer + " not in slds!!")
        if not isingeoserver:
            print(layer + " not in geoserver!!")
Beispiel #57
0
def _register_cascaded_service(url, type, name, username, password, wms=None, owner=None, parent=None):
    """
    Register a service as cascading WMS
    """

    try:
        service = Service.objects.get(base_url=url)
        return_dict = {}
        return_dict["service_id"] = service.pk
        return_dict["msg"] = "This is an existing Service"
        return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200)
    except:
        # TODO: Handle this error properly
        pass

    if wms is None:
        wms = WebMapService(url)
    # TODO: Make sure we are parsing all service level metadata
    # TODO: Handle for setting ServiceProfiletRole
    service = Service.objects.create(
        base_url=url,
        type=type,
        method="C",
        name=name,
        version=wms.identification.version,
        title=wms.identification.title,
        abstract=wms.identification.abstract,
        online_resource=wms.provider.url,
        owner=owner,
        parent=parent,
    )
    service.keywords = ",".join(wms.identification.keywords)
    service.save()
    service.set_default_permissions()
    if type in ["WMS", "OWS"]:
        # Register the Service with GeoServer to be cascaded
        cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password)
        cascade_ws = cat.get_workspace(name)
        if cascade_ws is None:
            cascade_ws = cat.create_workspace(name, "http://geonode.org/" + name)

        # TODO: Make sure there isn't an existing store with that name, and
        # deal with it if there is

        try:
            cascade_store = cat.get_store(name, cascade_ws)
        except:
            cascade_store = cat.create_wmsstore(name, cascade_ws, username, password)
            cascade_store.capabilitiesURL = url
            cascade_store.type = "WMS"
            cat.save(cascade_store)
        available_resources = cascade_store.get_resources(available=True)

    elif type == "WFS":
        # Register the Service with GeoServer to be cascaded
        cat = Catalog(settings.OGC_SERVER["default"]["LOCATION"] + "rest", _user, _password)
        # Can we always assume that it is geonode?
        cascade_ws = cat.get_workspace(settings.CASCADE_WORKSPACE)
        if cascade_ws is None:
            cascade_ws = cat.create_workspace(settings.CASCADE_WORKSPACE, "http://geonode.org/cascade")

        try:
            wfs_ds = cat.get_store(name, cascade_ws)
        except:
            wfs_ds = cat.create_datastore(name, cascade_ws)
            connection_params = {
                "WFSDataStoreFactory:MAXFEATURES": "0",
                "WFSDataStoreFactory:TRY_GZIP": "true",
                "WFSDataStoreFactory:PROTOCOL": "false",
                "WFSDataStoreFactory:LENIENT": "true",
                "WFSDataStoreFactory:TIMEOUT": "3000",
                "WFSDataStoreFactory:BUFFER_SIZE": "10",
                "WFSDataStoreFactory:ENCODING": "UTF-8",
                "WFSDataStoreFactory:WFS_STRATEGY": "nonstrict",
                "WFSDataStoreFactory:GET_CAPABILITIES_URL": url,
            }
            if username and password:
                connection_params["WFSDataStoreFactory:USERNAME"] = username
                connection_params["WFSDataStoreFactory:PASSWORD"] = password

            wfs_ds.connection_parameters = connection_params
            cat.save(wfs_ds)
        available_resources = wfs_ds.get_resources(available=True)

        # Save the Service record
        service, created = Service.objects.get_or_create(type=type, method="C", base_url=url, name=name, owner=owner)
        service.save()
        service.set_default_permissions()
    elif type == "WCS":
        return HttpResponse("Not Implemented (Yet)", status=501)
    else:
        return HttpResponse(
            "Invalid Method / Type combo: " + "Only Cascaded WMS, WFS and WCS supported",
            mimetype="text/plain",
            status=400,
        )

    message = "Service %s registered" % service.name
    return_dict = [
        {
            "status": "ok",
            "msg": message,
            "service_id": service.pk,
            "service_name": service.name,
            "service_title": service.title,
            "available_layers": available_resources,
        }
    ]

    if settings.USE_QUEUE:
        # Create a layer import job
        WebServiceHarvestLayersJob.objects.get_or_create(service=service)
    else:
        _register_cascaded_layers(service)
    return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200)
Beispiel #58
0
class ModifyingTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog("http://localhost:8080/geoserver/rest")

    def testFeatureTypeSave(self):
        # test saving round trip
        rs = self.cat.get_resource("bugsites")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"
        enabled = rs.enabled

        # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(new_abstract, rs.abstract)
        self.assertEqual(enabled, rs.enabled)

        # Change keywords on server
        rs.keywords = ["bugsites", "gsconfig"]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(["bugsites", "gsconfig"], rs.keywords)
        self.assertEqual(enabled, rs.enabled)
        
        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(
                        [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
                        rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)


        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("bugsites")
        self.assertEqual(old_abstract, rs.abstract)

    def testDataStoreCreate(self):
        ds = self.cat.create_datastore("vector_gsconfig")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)

    def testPublishFeatureType(self):
        # Use the other test and store creation to load vector data into a database
        # @todo maybe load directly to database?
        try:
            self.testDataStoreCreateAndThenAlsoImportData()
        except FailedRequestError:
            pass
        try:
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            self.cat.delete(lyr)
            self.cat.delete(lyr.resource)
            ds = self.cat.get_store("gsconfig_import_test")
            # make sure it's gone
            self.assert_(self.cat.get_layer('import') is None)
            self.cat.publish_featuretype("import", ds, native_crs="EPSG:4326")
            # and now it's not
            self.assert_(self.cat.get_layer('import') is not None)
        finally:
            # tear stuff down to allow the other test to pass if we run first
            ds = self.cat.get_store("gsconfig_import_test")
            lyr = self.cat.get_layer('import')
            # Delete the existing layer and resource to allow republishing.
            self.cat.delete(lyr)
            self.cat.delete(lyr.resource)
            self.cat.delete(ds)

    def testDataStoreModify(self):
        ds = self.cat.get_store("sf")
        self.assertFalse("foo" in ds.connection_parameters)
        ds.connection_parameters = ds.connection_parameters
        ds.connection_parameters["foo"] = "bar"
        orig_ws = ds.workspace.name
        self.cat.save(ds)
        ds = self.cat.get_store("sf")
        self.assertTrue("foo" in ds.connection_parameters)
        self.assertEqual("bar", ds.connection_parameters["foo"])
        self.assertEqual(orig_ws, ds.workspace.name)

    @drop_table('import')
    def testDataStoreCreateAndThenAlsoImportData(self):
        ds = self.cat.create_datastore("gsconfig_import_test")
        ds.connection_parameters.update(**DBPARAMS)
        self.cat.save(ds)
        ds = self.cat.get_store("gsconfig_import_test")
        self.cat.add_data_to_store(ds, "import", {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        })

    def testCoverageStoreCreate(self):
        ds = self.cat.create_coveragestore2("coverage_gsconfig")
        ds.data_url = "file:data/mytiff.tiff"
        self.cat.save(ds)

    def testCoverageStoreModify(self):
        cs = self.cat.get_store("sfdem")
        self.assertEqual("GeoTIFF", cs.type)
        cs.type = "WorldImage"
        self.cat.save(cs)
        cs = self.cat.get_store("sfdem")
        self.assertEqual("WorldImage", cs.type)

        # not sure about order of test runs here, but it might cause problems
        # for other tests if this layer is misconfigured
        cs.type = "GeoTIFF"
        self.cat.save(cs) 

    def testCoverageSave(self):
        # test saving round trip
        rs = self.cat.get_resource("Arc_Sample")
        old_abstract = rs.abstract
        new_abstract = "Not the original abstract"

        # # Change abstract on server
        rs.abstract = new_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(new_abstract, rs.abstract)

        # Restore abstract
        rs.abstract = old_abstract
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(old_abstract, rs.abstract)

        # Change metadata links on server
        rs.metadata_links = [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")]
        enabled = rs.enabled
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEqual(
            [("text/xml", "TC211", "http://example.com/gsconfig.test.metadata")],
            rs.metadata_links)
        self.assertEqual(enabled, rs.enabled)

        srs_before = set(['EPSG:4326'])
        srs_after = set(['EPSG:4326', 'EPSG:3785'])
        formats = set(['ARCGRID', 'ARCGRID-GZIP', 'GEOTIFF', 'PNG', 'GIF', 'TIFF'])
        formats_after = set(["PNG", "GIF", "TIFF"])

        # set and save request_srs_list
        self.assertEquals(set(rs.request_srs_list), srs_before, str(rs.request_srs_list))
        rs.request_srs_list = rs.request_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.request_srs_list), srs_after, str(rs.request_srs_list))

        # set and save response_srs_list
        self.assertEquals(set(rs.response_srs_list), srs_before, str(rs.response_srs_list))
        rs.response_srs_list = rs.response_srs_list + ['EPSG:3785']
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.response_srs_list), srs_after, str(rs.response_srs_list))

        # set and save supported_formats
        self.assertEquals(set(rs.supported_formats), formats, str(rs.supported_formats))
        rs.supported_formats = ["PNG", "GIF", "TIFF"]
        self.cat.save(rs)
        rs = self.cat.get_resource("Arc_Sample")
        self.assertEquals(set(rs.supported_formats), formats_after, str(rs.supported_formats))

    def testWmsStoreCreate(self):
        ws = self.cat.create_wmsstore("wmsstore_gsconfig")
        ws.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        ws.type = "WMS"
        self.cat.save(ws)
     
    def testWmsLayer(self):
        self.cat.create_workspace("wmstest", "http://example.com/wmstest")
        wmstest = self.cat.get_workspace("wmstest")
        wmsstore = self.cat.create_wmsstore("wmsstore", wmstest)
        wmsstore.capabilitiesURL = "http://suite.opengeo.org/geoserver/ows?service=wms&version=1.1.1&request=GetCapabilities"
        wmsstore.type = "WMS"
        self.cat.save(wmsstore)
        wmsstore = self.cat.get_store("wmsstore")
        self.assertEqual(1, len(self.cat.get_stores(wmstest)))
        available_layers = wmsstore.get_resources(available=True)
        for layer in available_layers:
            # sanitize the layer name - validation will fail on newer geoservers
            name = layer.replace(':', '_')
            new_layer = self.cat.create_wmslayer(wmstest, wmsstore, name, nativeName=layer)
        added_layers = wmsstore.get_resources()
        self.assertEqual(len(available_layers), len(added_layers))

        changed_layer = added_layers[0]
        self.assertEqual(True, changed_layer.advertised)
        self.assertEqual(True, changed_layer.enabled)
        changed_layer.advertised = False
        changed_layer.enabled = False
        self.cat.save(changed_layer)
        self.cat._cache.clear()
        changed_layer = wmsstore.get_resources()[0]
        changed_layer.fetch()
        self.assertEqual(False, changed_layer.advertised)
        self.assertEqual(False, changed_layer.enabled)

    def testFeatureTypeCreate(self):
        shapefile_plus_sidecars = shapefile_and_friends("test/data/states")
        expected = {
            'shp': 'test/data/states.shp',
            'shx': 'test/data/states.shx',
            'dbf': 'test/data/states.dbf',
            'prj': 'test/data/states.prj'
        }

        self.assertEqual(len(expected), len(shapefile_plus_sidecars))
        for k, v in expected.iteritems():
            self.assertEqual(v, shapefile_plus_sidecars[k])
 
        sf = self.cat.get_workspace("sf")
        self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)

        self.assert_(self.cat.get_resource("states_test", workspace=sf) is not None)

        self.assertRaises(
            ConflictingDataError, 
            lambda: self.cat.create_featurestore("states_test", shapefile_plus_sidecars, sf)
        )

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster_test", shapefile_plus_sidecars, sf)
        )

        bogus_shp = {
            'shp': 'test/data/Pk50095.tif',
            'shx': 'test/data/Pk50095.tif',
            'dbf':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_featurestore("bogus_shp", bogus_shp, sf)
        )

        lyr = self.cat.get_layer("states_test")
        self.cat.delete(lyr)
        self.assert_(self.cat.get_layer("states_test") is None)


    def testCoverageCreate(self):
        tiffdata = {
            'tiff': 'test/data/Pk50095.tif',
            'tfw':    'test/data/Pk50095.tfw',
            'prj':    'test/data/Pk50095.prj'
        }

        sf = self.cat.get_workspace("sf")
        # TODO: Uploading WorldImage file no longer works???
        # ft = self.cat.create_coveragestore("Pk50095", tiffdata, sf)

        # self.assert_(self.cat.get_resource("Pk50095", workspace=sf) is not None)

        # self.assertRaises(
        #         ConflictingDataError, 
        #         lambda: self.cat.create_coveragestore("Pk50095", tiffdata, sf)
        # )

        self.assertRaises(
            UploadError, 
            lambda: self.cat.create_featurestore("Pk50095_vector", tiffdata, sf)
        )

        bogus_tiff = {
            'tiff': 'test/data/states.shp',
            'tfw': 'test/data/states.shx',
            'prj': 'test/data/states.prj'
        }

        self.assertRaises(
            UploadError,
            lambda: self.cat.create_coveragestore("states_raster", bogus_tiff)
        )

    def testLayerSave(self):
        # test saving round trip
        lyr = self.cat.get_layer("states")
        old_attribution = lyr.attribution
        new_attribution = "Not the original attribution"

        # change attribution on server
        lyr.attribution = new_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(new_attribution, lyr.attribution)

        # Restore attribution
        lyr.attribution = old_attribution
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(old_attribution, lyr.attribution)

        self.assertEqual(lyr.default_style.name, "population")
     
        old_default_style = lyr.default_style
        lyr.default_style = (s for s in lyr.styles if s.name == "pophatch").next()
        lyr.styles = [old_default_style]
        self.cat.save(lyr)
        lyr = self.cat.get_layer("states")
        self.assertEqual(lyr.default_style.name, "pophatch")
        self.assertEqual([s.name for s in lyr.styles], ["population"])


    def testStyles(self):
        # upload new style, verify existence
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Fred", fred.sld_title)

        # replace style, verify changes
        self.cat.create_style("fred", open("test/ted.sld").read(), overwrite=True)
        fred = self.cat.get_style("fred")
        self.assert_(fred is not None)
        self.assertEqual("Ted", fred.sld_title)

        # delete style, verify non-existence
        self.cat.delete(fred, purge=True)
        self.assert_(self.cat.get_style("fred") is None)

        # attempt creating new style
        self.cat.create_style("fred", open("test/fred.sld").read())
        fred = self.cat.get_style("fred")
        self.assertEqual("Fred", fred.sld_title)

        # verify it can be found via URL and check the name
        f = self.cat.get_style_by_url(fred.href)
        self.assert_(f is not None)
        self.assertEqual(f.name, fred.name)

    def testWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp")

        jed = self.cat.get_style("jed", workspace="blarny")
        self.assert_(jed is None)
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)
        jed = self.cat.get_style("topp:jed")
        self.assert_(jed is not None)
        self.assertEqual("Fred", jed.sld_title)

        # replace style, verify changes
        self.cat.create_style("jed", open("test/ted.sld").read(), overwrite=True, workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assert_(jed is not None)
        self.assertEqual("Ted", jed.sld_title)

        # delete style, verify non-existence
        self.cat.delete(jed, purge=True)
        self.assert_(self.cat.get_style("jed", workspace="topp") is None)

        # attempt creating new style
        self.cat.create_style("jed", open("test/fred.sld").read(), workspace="topp")
        jed = self.cat.get_style("jed", workspace="topp")
        self.assertEqual("Fred", jed.sld_title)

        # verify it can be found via URL and check the full name
        f = self.cat.get_style_by_url(jed.href)
        self.assert_(f is not None)
        self.assertEqual(f.fqn, jed.fqn)

    def testLayerWorkspaceStyles(self):
        # upload new style, verify existence
        self.cat.create_style("ned", open("test/fred.sld").read(), overwrite=True, workspace="topp")
        self.cat.create_style("zed", open("test/ted.sld").read(), overwrite=True, workspace="topp")
        ned = self.cat.get_style("ned", workspace="topp")
        zed = self.cat.get_style("zed", workspace="topp")
        self.assert_(ned is not None)
        self.assert_(zed is not None)

        lyr = self.cat.get_layer("states")
        lyr.default_style = ned
        lyr.styles = [zed]
        self.cat.save(lyr)
        self.assertEqual("topp:ned", lyr.default_style)
        self.assertEqual([zed], lyr.styles)

        lyr.refresh()
        self.assertEqual("topp:ned", lyr.default_style.fqn)
        self.assertEqual([zed.fqn], [s.fqn for s in lyr.styles])

    def testWorkspaceCreate(self):
        ws = self.cat.get_workspace("acme")
        self.assertEqual(None, ws)
        self.cat.create_workspace("acme", "http://example.com/acme")
        ws = self.cat.get_workspace("acme")
        self.assertEqual("acme", ws.name)

    def testWorkspaceDelete(self): 
        self.cat.create_workspace("foo", "http://example.com/foo")
        ws = self.cat.get_workspace("foo")
        self.cat.delete(ws)
        ws = self.cat.get_workspace("foo")
        self.assert_(ws is None)

    def testWorkspaceDefault(self):
        # save orig
        orig = self.cat.get_default_workspace()
        neu = self.cat.create_workspace("neu", "http://example.com/neu")
        try:
            # make sure setting it works
            self.cat.set_default_workspace("neu")
            ws = self.cat.get_default_workspace()
            self.assertEqual('neu', ws.name)
        finally:
            # cleanup and reset to the way things were
            self.cat.delete(neu)
            self.cat.set_default_workspace(orig.name)
            ws = self.cat.get_default_workspace()
            self.assertEqual(orig.name, ws.name)

    def testFeatureTypeDelete(self):
        pass

    def testCoverageDelete(self):
        pass

    def testDataStoreDelete(self):
        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)
        states.enabled = False
        self.assert_(states.enabled == False)
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == False)

        states.enabled = True
        self.cat.save(states)

        states = self.cat.get_store('states_shapefile')
        self.assert_(states.enabled == True)

    def testLayerGroupSave(self):
        tas = self.cat.get_layergroup("tasmania")

        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

        tas.layers = tas.layers[:-1]
        tas.styles = tas.styles[:-1]

        self.cat.save(tas)

        # this verifies the local state
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)

        # force a refresh to check the remote state
        tas.refresh()
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None], tas.styles)

    def testTimeDimension(self):
        sf = self.cat.get_workspace("sf")
        files = shapefile_and_friends(os.path.join(gisdata.GOOD_DATA, "time", "boxes_with_end_date"))
        self.cat.create_featurestore("boxes_with_end_date", files, sf)

        get_resource = lambda: self.cat._cache.clear() or self.cat.get_layer('boxes_with_end_date').resource

        # configure time as LIST
        resource = get_resource()
        timeInfo = DimensionInfo("time", "true", "LIST", None, "ISO8601", None, attribute="date")
        resource.metadata = {'time':timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual("LIST", timeInfo.presentation)
        self.assertEqual(True, timeInfo.enabled)
        self.assertEqual("date", timeInfo.attribute)
        self.assertEqual("ISO8601", timeInfo.units)

        # disable time dimension
        timeInfo = resource.metadata['time']
        timeInfo.enabled = False
        # since this is an xml property, it won't get written unless we modify it
        resource.metadata = {'time' : timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual(False, timeInfo.enabled)

        # configure with interval, end_attribute and enable again
        timeInfo.enabled = True
        timeInfo.presentation = 'DISCRETE_INTERVAL'
        timeInfo.resolution = '3 days'
        timeInfo.end_attribute = 'enddate'
        resource.metadata = {'time' : timeInfo}
        self.cat.save(resource)
        # and verify
        resource = get_resource()
        timeInfo = resource.metadata['time']
        self.assertEqual(True, timeInfo.enabled)
        self.assertEqual('DISCRETE_INTERVAL', timeInfo.presentation)
        self.assertEqual('3 days', timeInfo.resolution_str())
        self.assertEqual('enddate', timeInfo.end_attribute)
Beispiel #59
0
def gs_slurp(ignore_errors=True, verbosity=1, console=None, owner=None, workspace=None, store=None, filter=None):
    """Configure the layers available in GeoServer in GeoNode.

       It returns a list of dictionaries with the name of the layer,
       the result of the operation and the errors and traceback if it failed.
    """
    if console is None:
        console = open(os.devnull, 'w')

    if verbosity > 1:
        print >> console, "Inspecting the available layers in GeoServer ..."
    url = "%srest" % settings.GEOSERVER_BASE_URL
    cat = Catalog(url, _user, _password)
    if workspace is not None:
        workspace = cat.get_workspace(workspace)
        resources = cat.get_resources(workspace=workspace)
    elif store is not None:
        store = cat.get_store(store)
        resources = cat.get_resources(store=store)
    else:
        resources = cat.get_resources(workspace=workspace)
    if filter:
        resources = [k for k in resources if filter in k.name]

    # filter out layers explicitly disabled by geoserver
    resources = [k for k in resources if k.enabled == "true"]
   
    # TODO: Should we do something with these?
    # i.e. look for matching layers in GeoNode and also disable? 
    disabled_resources = [k for k in resources if k.enabled == "false"]
    
    number = len(resources)
    if verbosity > 1:
        msg =  "Found %d layers, starting processing" % number
        print >> console, msg
    output = []
    for i, resource in enumerate(resources):
        name = resource.name
        store = resource.store
        workspace = store.workspace
        try:
            # Avoid circular import problem
            from geonode.layers.models import Layer
            layer, created = Layer.objects.get_or_create(name=name, defaults = {
                "workspace": workspace.name,
                "store": store.name,
                "storeType": store.resource_type,
                "typename": "%s:%s" % (workspace.name, resource.name),
                "title": resource.title or 'No title provided',
                "abstract": resource.abstract or 'No abstract provided',
                "owner": owner,
                "uuid": str(uuid.uuid4())
            })
            layer.save()

        except Exception, e:
            if ignore_errors:
                status = 'failed'
                exception_type, error, traceback = sys.exc_info()
            else:
                if verbosity > 0:
                    msg = "Stopping process because --ignore-errors was not set and an error was found."
                    print >> sys.stderr, msg
                raise Exception('Failed to process %s' % resource.name, e), None, sys.exc_info()[2]
        else:
            if created:
                layer.set_default_permissions()
                status = 'created'
            else:
                status = 'updated'

        msg = "[%s] Layer %s (%d/%d)" % (status, name, i+1, number)
        info = {'name': name, 'status': status}
        if status == 'failed':
            info['traceback'] = traceback
            info['exception_type'] = exception_type
            info['error'] = error
        output.append(info)
        if verbosity > 0:
            print >> console, msg
Beispiel #60
0
class CatalogTests(unittest.TestCase):
    def setUp(self):
        self.cat = Catalog("http://localhost:8080/geoserver/rest")

    def testAbout(self):
        about_html = self.cat.about()
        self.assertTrue('<html xmlns="http://www.w3.org/1999/xhtml"' in about_html)

    def testGSVersion(self):
        version = self.cat.gsversion()
        pat = re.compile('\d\.\d(\.[\dx]|-SNAPSHOT)')
        self.assertTrue(pat.match('2.2.x'))
        self.assertTrue(pat.match('2.3.2'))
        self.assertTrue(pat.match('2.3-SNAPSHOT'))
        self.assertFalse(pat.match('2.3.y'))
        self.assertFalse(pat.match('233'))
        self.assertTrue(pat.match(version))

    def testWorkspaces(self):
        self.assertEqual(7, len(self.cat.get_workspaces()))
        # marking out test since geoserver default workspace is not consistent 
        # self.assertEqual("cite", self.cat.get_default_workspace().name)
        self.assertEqual("topp", self.cat.get_workspace("topp").name)


    def testStores(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        self.assertEqual(9, len(self.cat.get_stores()))
        self.assertEqual(2, len(self.cat.get_stores(topp)))
        self.assertEqual(2, len(self.cat.get_stores(sf)))
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile", topp).name)
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
        self.assertEqual("states_shapefile", self.cat.get_store("states_shapefile").name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem", sf).name)
        self.assertEqual("sfdem", self.cat.get_store("sfdem").name)

  
    def testResources(self):
        topp = self.cat.get_workspace("topp")
        sf = self.cat.get_workspace("sf")
        states = self.cat.get_store("states_shapefile", topp)
        sfdem = self.cat.get_store("sfdem", sf)
        self.assertEqual(19, len(self.cat.get_resources()))
        self.assertEqual(1, len(self.cat.get_resources(states)))
        self.assertEqual(5, len(self.cat.get_resources(workspace=topp)))
        self.assertEqual(1, len(self.cat.get_resources(sfdem)))
        self.assertEqual(6, len(self.cat.get_resources(workspace=sf)))

        self.assertEqual("states", self.cat.get_resource("states", states).name)
        self.assertEqual("states", self.cat.get_resource("states", workspace=topp).name)
        self.assertEqual("states", self.cat.get_resource("states").name)
        states = self.cat.get_resource("states")

        fields = [
            states.title,
            states.abstract,
            states.native_bbox,
            states.latlon_bbox,
            states.projection,
            states.projection_policy
        ]

        self.assertFalse(None in fields, str(fields))
        self.assertFalse(len(states.keywords) == 0)
        self.assertFalse(len(states.attributes) == 0)
        self.assertTrue(states.enabled)

        self.assertEqual("sfdem", self.cat.get_resource("sfdem", sfdem).name)
        self.assertEqual("sfdem", self.cat.get_resource("sfdem", workspace=sf).name)
        self.assertEqual("sfdem", self.cat.get_resource("sfdem").name)


    def testLayers(self):
        expected = set(["Arc_Sample", "Pk50095", "Img_Sample", "mosaic", "sfdem",
            "bugsites", "restricted", "streams", "archsites", "roads",
            "tasmania_roads", "tasmania_water_bodies", "tasmania_state_boundaries",
            "tasmania_cities", "states", "poly_landmarks", "tiger_roads", "poi",
            "giant_polygon"
        ])
        actual = set(l.name for l in self.cat.get_layers())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layer list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        states = self.cat.get_layer("states")

        self.assert_("states", states.name)
        self.assert_(isinstance(states.resource, ResourceInfo))
        self.assertEqual(set(s.name for s in states.styles), set(['pophatch', 'polygon']))
        self.assertEqual(states.default_style.name, "population")

    def testLayerGroups(self):
        expected = set(["tasmania", "tiger-ny", "spearfish"])
        actual = set(l.name for l in self.cat.get_layergroups())
        missing = expected - actual
        extras = actual - expected
        message = "Actual layergroup list did not match expected! (Extras: %s) (Missing: %s)" % (extras, missing)
        self.assert_(len(expected ^ actual) == 0, message)

        tas = self.cat.get_layergroup("tasmania")

        self.assert_("tasmania", tas.name)
        self.assert_(isinstance(tas, LayerGroup))
        self.assertEqual(tas.layers, ['tasmania_state_boundaries', 'tasmania_water_bodies', 'tasmania_roads', 'tasmania_cities'], tas.layers)
        self.assertEqual(tas.styles, [None, None, None, None], tas.styles)

    def testStyles(self):
        self.assertEqual(20, len(self.cat.get_styles()))
        self.assertEqual("population", self.cat.get_style("population").name)
        self.assertEqual("popshade.sld", self.cat.get_style("population").filename)
        self.assertEqual("population", self.cat.get_style("population").sld_name)
        self.assert_(self.cat.get_style('non-existing-style') is None)

    def testEscaping(self):
        # GSConfig is inconsistent about using exceptions vs. returning None
        # when a resource isn't found.
        # But the basic idea is that none of them should throw HTTP errors from
        # misconstructed URLS
        self.cat.get_style("best style ever")
        self.cat.get_workspace("best workspace ever")
        try:
            self.cat.get_store(workspace="best workspace ever",
                name="best store ever")
            self.fail('expected exception')
        except FailedRequestError, fre:
            self.assertEqual('No store found named: best store ever', fre.message)
        try:
            self.cat.get_resource(workspace="best workspace ever",
                store="best store ever",
                name="best resource ever")
        except FailedRequestError, fre:
            self.assertEqual('No store found named: best store ever', fre.message)