Example #1
0
def geoserver_pre_save_maplayer(instance, sender, **kwargs):
    # If this object was saved via fixtures,
    # do not do post processing.
    if kwargs.get('raw', False):
        return

    try:
        instance.local = isinstance(gs_catalog.get_layer(instance.name),
                                    GsLayer)
    except OSError as e:
        if e.errno == errno.ECONNREFUSED:
            msg = f'Could not connect to catalog to verify if layer {instance.name} was local'
            logger.warn(msg)
        else:
            raise e

    # Set dataset
    if instance.dataset is None:
        dataset_queryset = Dataset.objects.filter(
            Q(alternate=instance.name) | Q(name=instance.name))
        if instance.local and instance.store:
            dataset_queryset = dataset_queryset.filter(store=instance.store)
        elif instance.ows_url:
            dataset_queryset = dataset_queryset.filter(
                remote_service__base_url=instance.ows_url)
        try:
            instance.dataset = dataset_queryset.get()
        except Dataset.DoesNotExist:
            pass
Example #2
0
def gs_append_data_to_layer(layer, base_files, user):
    gs_layer = gs_catalog.get_layer(layer.name)
    if gs_layer and gs_layer.type == 'VECTOR':
        #  opening upload session for the selected layer
        upload_session, created = UploadSession.objects.get_or_create(
            resource=layer, user=user)
        upload_session.resource = layer
        upload_session.processed = False
        upload_session.save()

        #  opening Import session for the selected layer
        import_session = gs_uploader.start_import(
            import_id=upload_session.id,
            name=layer.name,
            target_store=gs_layer.resource.store.name)

        import_session.upload_task(base_files)
        task = import_session.tasks[0]
        #  Changing layer name, mode and target
        task.layer.set_target_layer_name(layer.name)
        task.set_update_mode("APPEND")
        task.set_target(store_name=gs_layer.resource.store.name,
                        workspace=gs_layer.resource.workspace.name)
        #  Starting import process
        import_session.commit()
        return upload_session
Example #3
0
def saveToGeonode(payload):
    admin = Profile.objects.filter(is_superuser=True).first()
    logger.debug('Uploading layer %s to geonode' % payload['zip_name'])

    # use overwrite to make sure if a layer exists it gets updated
    uploaded = upload(payload['zipfile_path'], admin, overwrite=True)[0]
    if uploaded['status'] == 'failed':
        raise Exception("Failed layer %s with error %s " %
                        (payload['zip_name'], uploaded['error']))
    else:
        uploaded_name = uploaded['name']

    if any(s in payload['zip_name'] for s in ['_a', '_p', '_l']):
        gs_layer = gs_catalog.get_layer(name=uploaded_name)
        gs_style = gs_catalog.get_style(name=payload['style_name'])

        if not gs_style:
            #let's make sure the style is there
            gs_catalog.create_style(payload['style_name'],
                                    payload['style_body'])
            gs_style = gs_catalog.get_style(name=payload['style_name'])

        gs_layer.default_style = gs_style
        gs_catalog.save(gs_layer)
        # gs_catalog.reload()

    saved_layer = Layer.objects.get(name=uploaded_name)
    mapSetLayer = createMapSetLayer(saved_layer, payload['zip_name'])
    payload['mapset'].layers.add(mapSetLayer)

    #create_gs_thumbnail(saved_layer, overwrite=True)
    return uploaded_name
Example #4
0
def layer_create(request, data=None, template='upload/layer_create.html'):
    print 'layer create'
    if request.method == 'POST':
        feature_type = json.loads(request.POST.get(u'featureType', None))
        datastore = feature_type['store']['name']
        store_create_geogig = json.loads(request.POST.get(u'storeCreateGeogig', 'false'))

        if store_create_geogig:
            if not feature_type['store']['name']:
                store_proposed = slugify(' '.join([request.user.username, feature_type['name']]))
            store_created = create_geoserver_db_featurestore(store_type='geogig', store_name=store_proposed)
            feature_type['store']['name'] = store_created.name

        # -- only allow creation of layers in the whitelisted datastores
        try:
            settings.ALLOWED_DATASTORE_LAYER_CREATE
        except AttributeError:
            return HttpResponse(status=FORBIDDEN, content='ALLOWED_DATASTORE_LAYER_CREATE whitelist is not defined.')

        if datastore not in settings.ALLOWED_DATASTORE_LAYER_CREATE:
            return HttpResponse(status=FORBIDDEN, content='datastore specified in featureType is not in the ALLOWED_DATASTORE_LAYER_CREATE whitelist.')

        post_request = requests.post(
            '{}/workspaces/{}/datastores/{}/featuretypes.json'.format(ogc_server_settings.rest, feature_type['namespace']['name'], datastore),
            data='{{"featureType":{}}}'.format(json.dumps(feature_type)),
            auth=ogc_server_settings.credentials,
            headers={'content-type': 'application/json'}
        )

        if post_request.status_code == 200 or post_request.status_code == 201:
            # import the layer from geoserver to geonode
            response = gs_slurp(filter=feature_type['name'], workspace=feature_type['namespace']['name'], store=feature_type['store']['name'])
            if 'layers' in response and len(response['layers']) == 1 and 'name' in response['layers'][0] and response['layers'][0]['name'] == feature_type['name']:
                # configruer layer with time dimension as a list for now. Since importer is being refactored,
                # we'll change how it is done.
                layer = gs_catalog.get_layer(feature_type['name'])
                resource = layer.resource
                if layer:
                    time_info = DimensionInfo(
                        name='time',
                        enabled=True,
                        presentation='LIST',
                        resolution=None,
                        units=None,
                        unitSymbol=None,
                        attribute='time',
                        end_attribute=None,
                        strategy=None)
                    resource.metadata = {'time': time_info}
                    resource.catalog.save(resource)
                    return HttpResponse(status=post_request.status_code, content=post_request.text)
                return HttpResponse(status=500, content='failed to configure layer')
            else:
                return HttpResponse(status=500, content='failed to add created layer from geoserver to geonode')
        else:
            return HttpResponse(status=post_request.status_code, content=post_request.text)
        print '---- create layer response: ', post_request.text
    return render_to_response(template, RequestContext(request, {}))
Example #5
0
    def tearDown(self):

        layer = gs_catalog.get_layer(self.layer_name)

        if layer:
            gs_catalog.delete(layer)

        if self.datastore:
            gs_catalog.delete(self.datastore, recurse=True)
Example #6
0
    def tearDown(self):

        layer = gs_catalog.get_layer(self.layer_name)

        if layer:
            gs_catalog.delete(layer)

        if self.datastore:
            gs_catalog.delete(self.datastore, recurse=True)
Example #7
0
 def set_default_style(self, layername, style):
     saved = False
     try:
         layer = gs_catalog.get_layer(layername)
         layer.default_style = style
         gs_catalog.save(layer)
         saved = True
     except Exception as e:
         logger.error(e.message)
     return saved
Example #8
0
    def handle(self, layer, layer_config, *args, **kwargs):
        """
        Configures time on the object.

        Handler specific params:
        "configureTime": Must be true for this handler to run.
        "start_date": Passed as the start time to Geoserver.
        "end_date" (optional): Passed as the end attribute to Geoserver.
        """

        lyr = gs_catalog.get_layer(layer)
        configure_time(lyr.resource, attribute=layer_config.get('start_date'),
                       end_attribute=layer_config.get('end_date'))
Example #9
0
    def handle(self, layer, layer_config, *args, **kwargs):
        """
        Configures time on the object.

        Handler specific params:
        "configureTime": Must be true for this handler to run.
        "start_date": Passed as the start time to Geoserver.
        "end_date" (optional): Passed as the end attribute to Geoserver.
        """

        lyr = gs_catalog.get_layer(layer)
        configure_time(lyr.resource,
                       attribute=layer_config.get('start_date'),
                       end_attribute=layer_config.get('end_date'))
Example #10
0
def geoserver_pre_save_maplayer(instance, sender, **kwargs):
    # If this object was saved via fixtures,
    # do not do post processing.
    if kwargs.get("raw", False):
        return

    try:
        instance.local = isinstance(gs_catalog.get_layer(instance.name), GsLayer)
    except EnvironmentError, e:
        if e.errno == errno.ECONNREFUSED:
            msg = "Could not connect to catalog to verify if layer %s was local" % instance.name
            logger.warn(msg, e)
        else:
            raise e
Example #11
0
def geoserver_pre_save_maplayer(instance, sender, **kwargs):
    # If this object was saved via fixtures,
    # do not do post processing.
    if kwargs.get('raw', False):
        return

    try:
        instance.local = isinstance(gs_catalog.get_layer(instance.name),
                                    GsLayer)
    except EnvironmentError as e:
        if e.errno == errno.ECONNREFUSED:
            msg = 'Could not connect to catalog to verify if layer %s was local' % instance.name
            logger.warn(msg, e)
        else:
            raise e
Example #12
0
def geoserver_pre_save_maplayer(instance, sender, **kwargs):
    # If this object was saved via fixtures,
    # do not do post processing.
    if kwargs.get('raw', False):
        return

    try:
        instance.local = isinstance(
            gs_catalog.get_layer(
                instance.name),
            GsLayer)
    except EnvironmentError as e:
        if e.errno == errno.ECONNREFUSED:
            msg = 'Could not connect to catalog to verify if layer %s was local' % instance.name
            try:
                # HACK: The logger on signals throws an exception
                logger.warn(msg, e)
            except:
                pass
        else:
            raise e
Example #13
0
def table_exist(name):
    data_db_name = settings.OGC_SERVER['default']['DATASTORE']
    connection = None
    for c in connections.all():
        if c.alias == data_db_name:
            connection = c
    table_names = connection.introspection.table_names()
    db_exist = name in table_names
    gs_exist = bool(gs_catalog.get_layer(name))
    try:
        Layer.objects.get(name=name)
        gn_exist = True
    except ObjectDoesNotExist:
        gn_exist = False
    layer_exist = db_exist or gs_exist or gn_exist
    if layer_exist:
        # TODO: using logger instead
        print('Table name \'{}\' is already exist in {}, {}, {}'.format(
            name,
            'database' if db_exist else '',
            'geoserver' if gs_exist else '',
            'geonode' if gn_exist else '',
        ))
    return layer_exist
Example #14
0
def file_upload(filename,
                name=None,
                user=None,
                title=None,
                abstract=None,
                style_name=None,
                skip=True,
                overwrite=False,
                keywords=[],
                charset='UTF-8',
                category=None,
                date=None):
    """Saves a layer in GeoNode asking as little information as possible.
       Only filename is required, user and title are optional.
    """
    # Get a valid user
    theuser = get_valid_user(user)

    # Create a new upload session
    upload_session = UploadSession.objects.create(user=theuser)

    # Get all the files uploaded with the layer
    files = get_files(filename)

    # Set a default title that looks nice ...
    if title is None:
        basename = os.path.splitext(os.path.basename(filename))[0]
        title = basename.title().replace('_', ' ')

    # Create a name from the title if it is not passed.
    if name is None:
        name = slugify(title).replace('-', '_')

    if category is not None:
        category = TopicCategory.objects.get(identifier=category)

    # Generate a name that is not taken if overwrite is False.
    valid_name = get_valid_layer_name(name, overwrite)

    # Add them to the upload session (new file fields are created).
    assigned_name = None
    for type_name, fn in files.items():
        with open(fn, 'rb') as f:
            upload_session.layerfile_set.create(
                name=type_name,
                file=File(f,
                          name='%s.%s' %
                          (assigned_name or valid_name, type_name)))
            # save the system assigned name for the remaining files
            if not assigned_name:
                the_file = upload_session.layerfile_set.all()[0].file.name
                assigned_name = os.path.splitext(os.path.basename(the_file))[0]

    # Get a bounding box
    bbox_x0, bbox_x1, bbox_y0, bbox_y1 = get_bbox(filename)

    # by default, if RESOURCE_PUBLISHING=True then layer.is_published
    # must be set to False
    is_published = True
    if settings.RESOURCE_PUBLISHING:
        is_published = False

    defaults = {
        'upload_session': upload_session,
        'title': title,
        'abstract': abstract,
        'owner': user,
        'charset': charset,
        'bbox_x0': bbox_x0,
        'bbox_x1': bbox_x1,
        'bbox_y0': bbox_y0,
        'bbox_y1': bbox_y1,
        'is_published': is_published,
        'category': category
    }

    # set metadata
    if 'xml' in files:
        xml_file = open(files['xml'])
        defaults['metadata_uploaded'] = True
        # get model properties from XML
        vals, keywords = set_metadata(xml_file.read())

        for key, value in vals.items():
            if key == 'spatial_representation_type':
                value = SpatialRepresentationType(identifier=value)
            elif key == 'topic_category':
                value, created = TopicCategory.objects.get_or_create(
                    identifier=value.lower(),
                    defaults={
                        'description': '',
                        'gn_description': value
                    })
                key = 'category'
                defaults[key] = value
            else:
                defaults[key] = value

    # If it is a vector file, create the layer in postgis.
    if is_vector(filename):
        defaults['storeType'] = 'dataStore'

    # If it is a raster file, get the resolution.
    if is_raster(filename):
        defaults['storeType'] = 'coverageStore'

    # Create a Django object.
    layer, created = Layer.objects.get_or_create(name=valid_name,
                                                 defaults=defaults)

    # set layer style in geoserver
    if style_name is not None:
        # import here because import at top of file fails for some reason
        from geonode.geoserver.helpers import gs_catalog
        try:
            gs_style = gs_catalog.get_style(style_name)
        except:
            gs_style = None
        if gs_style is not None:
            gs_layer = gs_catalog.get_layer(layer.name)
            gs_layer.default_style = gs_style
            gs_catalog.save(gs_layer)

    # set layer date
    if date is not None:
        layer.date = date

    # Delete the old layers if overwrite is true
    # and the layer was not just created
    # process the layer again after that by
    # doing a layer.save()
    if not created and overwrite:
        layer.upload_session.layerfile_set.all().delete()
        layer.upload_session = upload_session
        # Pass the parameter overwrite to tell whether the
        # geoserver_post_save_signal should upload the new file or not
        layer.overwrite = overwrite
    layer.save()

    # Assign the keywords (needs to be done after saving)
    if len(keywords) > 0:
        layer.keywords.add(*keywords)

    return layer
Example #15
0
def geoserver_pre_save(instance, sender, **kwargs):
    """Send information to geoserver.

       The attributes sent include:

        * Title
        * Abstract
        * Name
        * Keywords
        * Metadata Links,
        * Point of Contact name and url
    """

    # Don't run this signal if is a Layer from a remote service
    if instance.workspace == 'remoteWorkspace':
        return

    # If the store in None then it's a new instance from an upload,
    # only in this case run the geonode_uplaod method
    if not instance.store or getattr(instance, 'overwrite', False):
        base_file = instance.get_base_file()

        # There is no need to process it if there is not file.
        if base_file is None:
            return
        gs_name, workspace, values = geoserver_upload(
            instance,
            base_file.file.path,
            instance.owner,
            instance.name,
            overwrite=True,
            title=instance.title,
            abstract=instance.abstract,
            # keywords=instance.keywords,
            charset=instance.charset)
        # Set fields obtained via the geoserver upload.
        instance.name = gs_name
        instance.workspace = workspace
        # Iterate over values from geoserver.
        for key in ['typename', 'store', 'storeType']:
            setattr(instance, key, values[key])

    gs_resource = gs_catalog.get_resource(instance.name,
                                          store=instance.store,
                                          workspace=instance.workspace)

    gs_resource.title = instance.title
    gs_resource.abstract = instance.abstract
    gs_resource.name = instance.name

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.mime, link.name, link.url))

    gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if
    # ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
        gs_catalog.save(gs_resource)

    gs_layer = gs_catalog.get_layer(instance.name)

    if instance.poc and instance.poc:
        gs_layer.attribution = str(instance.poc)
        profile = Profile.objects.get(username=instance.poc.username)
        gs_layer.attribution_link = settings.SITEURL[:
                                                     -1] + profile.get_absolute_url(
                                                     )
        # gs_layer should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_layer)
    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """
    gs_resource = gs_catalog.get_resource(instance.name)

    bbox = gs_resource.latlon_bbox

    # FIXME(Ariel): Correct srid setting below
    # self.srid = gs_resource.src

    instance.srid_url = "http://www.spatialreference.org/ref/" + \
        instance.srid.replace(':', '/').lower() + "/"

    # Set bounding box values
    instance.bbox_x0 = bbox[0]
    instance.bbox_x1 = bbox[1]
    instance.bbox_y0 = bbox[2]
    instance.bbox_y1 = bbox[3]
Example #16
0
def geoserver_pre_save(instance, sender, **kwargs):
    """Send information to geoserver.

       The attributes sent include:

        * Title
        * Abstract
        * Name
        * Keywords
        * Metadata Links,
        * Point of Contact name and url
    """
    base_file = instance.get_base_file()

    # There is no need to process it if there is not file.
    if base_file is None:
        return

    gs_name, workspace, values = geoserver_upload(
        instance,
        base_file.file.path,
        instance.owner,
        instance.name,
        overwrite=True,
        title=instance.title,
        abstract=instance.abstract,
        #               keywords=instance.keywords,
        charset=instance.charset,
    )

    # Set fields obtained via the geoserver upload.
    instance.name = gs_name
    instance.workspace = workspace

    # Iterate over values from geoserver.
    for key in ["typename", "store", "storeType"]:
        setattr(instance, key, values[key])

    url = ogc_server_settings.internal_rest
    gs_resource = gs_catalog.get_resource(instance.name, store=instance.store, workspace=instance.workspace)

    gs_resource.title = instance.title
    gs_resource.abstract = instance.abstract
    gs_resource.name = instance.name

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.name, link.mime, link.url))

    gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
        gs_catalog.save(gs_resource)

    gs_layer = gs_catalog.get_layer(instance.name)

    if instance.poc and instance.poc.user:
        gs_layer.attribution = str(instance.poc.user)
        profile = Profile.objects.get(user=instance.poc.user)
        gs_layer.attribution_link = settings.SITEURL[:-1] + profile.get_absolute_url()
        # gs_layer should only be called if ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_layer)

    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """
    gs_resource = gs_catalog.get_resource(instance.name)

    bbox = gs_resource.latlon_bbox

    # FIXME(Ariel): Correct srid setting below
    # self.srid = gs_resource.src

    instance.srid_url = "http://www.spatialreference.org/ref/" + instance.srid.replace(":", "/").lower() + "/"

    # Set bounding box values
    instance.bbox_x0 = bbox[0]
    instance.bbox_x1 = bbox[1]
    instance.bbox_y0 = bbox[2]
    instance.bbox_y1 = bbox[3]
Example #17
0
def geoserver_post_save_local(layer_id, *args, **kwargs):
    """Send information to geoserver.

       The attributes sent include:

        * Title
        * Abstract
        * Name
        * Keywords
        * Metadata Links,
        * Point of Contact name and url
    """
    # If it is a layer object, post process it. If not, abort.
    try:
        instance = Layer.objects.get(id=layer_id)
    except Layer.DoesNotExist as e:
        logger.exception(e)
        return
        # raise e

    # Don't run this signal if is a Layer from a remote service
    if getattr(instance, "service", None) is not None:
        return

    # Don't run this signal handler if it is a tile layer or a remote store (Service)
    #    Currently only gpkg files containing tiles will have this type & will be served via MapProxy.
    if hasattr(instance, 'storeType') and getattr(instance, 'storeType') in ['tileStore', 'remoteStore']:
        return instance

    gs_resource = None
    values = None

    # If the store in None then it's a new instance from an upload,
    # only in this case run the geoserver_upload method
    if not instance.store or getattr(instance, 'overwrite', False):
        base_file, info = instance.get_base_file()

        # There is no need to process it if there is not file.
        if base_file is None:
            return
        gs_name, workspace, values, gs_resource = geoserver_upload(instance,
                                                                   base_file.file.path,
                                                                   instance.owner,
                                                                   instance.name,
                                                                   overwrite=True,
                                                                   title=instance.title,
                                                                   abstract=instance.abstract,
                                                                   # keywords=instance.keywords,
                                                                   charset=instance.charset)

    if not gs_resource:
        gs_resource = gs_catalog.get_resource(
            instance.name,
            store=instance.store,
            workspace=instance.workspace)
        if not gs_resource:
            gs_resource = gs_catalog.get_resource(instance.alternate)

    if gs_resource:
        gs_resource.title = instance.title or ""
        gs_resource.abstract = instance.abstract or ""
        gs_resource.name = instance.name or ""

        if not values:
            values = dict(store=gs_resource.store.name,
                          storeType=gs_resource.store.resource_type,
                          alternate=gs_resource.store.workspace.name + ':' + gs_resource.name,
                          title=gs_resource.title or gs_resource.store.name,
                          abstract=gs_resource.abstract or '',
                          owner=instance.owner)
    else:
        return

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.mime, link.name, link.url))

    gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if
    # ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
        try:
            gs_catalog.save(gs_resource)
        except geoserver.catalog.FailedRequestError as e:
            msg = ('Error while trying to save resource named %s in GeoServer, '
                   'try to use: "%s"' % (gs_resource, str(e)))
            e.args = (msg,)
            logger.exception(e)

    gs_layer = gs_catalog.get_layer(instance.name)

    if not gs_layer:
        gs_layer = gs_catalog.get_layer(instance.alternate)

    if gs_layer and instance.poc:
        # gsconfig now utilizes an attribution dictionary
        gs_layer.attribution = {'title': str(instance.poc),
                                'width': None,
                                'height': None,
                                'href': None,
                                'url': None,
                                'type': None}
        profile = Profile.objects.get(username=instance.poc.username)
        gs_layer.attribution_link = settings.SITEURL[
            :-1] + profile.get_absolute_url()
        # gs_layer should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            try:
                gs_catalog.save(gs_layer)
            except geoserver.catalog.FailedRequestError as e:
                msg = ('Error while trying to save layer named %s in GeoServer, '
                       'try to use: "%s"' % (gs_layer, str(e)))
                e.args = (msg,)
                logger.exception(e)

    if type(instance) is ResourceBase:
        if hasattr(instance, 'layer'):
            instance = instance.layer
        else:
            return

    if instance.storeType == "remoteStore":
        # Save layer attributes
        set_attributes_from_geoserver(instance)
        return

    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """
    # instance.name = instance.name or gs_layer.name
    # instance.title = instance.title or gs_resource.title
    instance.abstract = gs_resource.abstract or ''
    instance.workspace = gs_resource.store.workspace.name
    instance.store = gs_resource.store.name

    bbox = gs_resource.latlon_bbox

    # FIXME(Ariel): Correct srid setting below
    # self.srid = gs_resource.src

    instance.srid_url = "http://www.spatialreference.org/ref/" + \
        instance.srid.replace(':', '/').lower() + "/"

    # Set bounding box values
    instance.bbox_x0 = bbox[0]
    instance.bbox_x1 = bbox[1]
    instance.bbox_y0 = bbox[2]
    instance.bbox_y1 = bbox[3]

    # Iterate over values from geoserver.
    for key in ['alternate', 'store', 'storeType']:
        # attr_name = key if 'typename' not in key else 'alternate'
        # print attr_name
        setattr(instance, key, values[key])

    if settings.RESOURCE_PUBLISHING:
        if instance.is_published != gs_resource.advertised:
            if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
                gs_resource.advertised = 'true' if instance.is_published else 'false'
                gs_catalog.save(gs_resource)

    if not settings.FREETEXT_KEYWORDS_READONLY:
        if gs_resource.keywords:
            for keyword in gs_resource.keywords:
                instance.keywords.add(keyword)

    if any(instance.keyword_list()):
        keywords = instance.keyword_list()
        if settings.FREETEXT_KEYWORDS_READONLY:
            if gs_resource.keywords:
                keywords += gs_resource.keywords
        gs_resource.keywords = list(set(keywords))

        # gs_resource should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            try:
                gs_catalog.save(gs_resource)
            except geoserver.catalog.FailedRequestError as e:
                msg = ('Error while trying to save resource named %s in GeoServer, '
                       'try to use: "%s"' % (gs_resource, str(e)))
                e.args = (msg,)
                logger.exception(e)

    to_update = {
        'title': instance.title or instance.name,
        'abstract': instance.abstract or "",
        'alternate': instance.alternate,
        'bbox_x0': instance.bbox_x0,
        'bbox_x1': instance.bbox_x1,
        'bbox_y0': instance.bbox_y0,
        'bbox_y1': instance.bbox_y1
    }

    # Update ResourceBase
    resources = ResourceBase.objects.filter(id=instance.resourcebase_ptr.id)
    resources.update(**to_update)

    # to_update['name'] = instance.name,
    to_update['workspace'] = instance.workspace
    to_update['store'] = instance.store
    to_update['storeType'] = instance.storeType
    to_update['typename'] = instance.alternate

    # Save all the modified information in the instance without triggering signals.
    Layer.objects.filter(id=instance.id).update(**to_update)

    # Refresh from DB
    instance.refresh_from_db()

    # store the resource to avoid another geoserver call in the post_save
    instance.gs_resource = gs_resource

    bbox = gs_resource.latlon_bbox
    dx = float(bbox[1]) - float(bbox[0])
    dy = float(bbox[3]) - float(bbox[2])

    dataAspect = 1 if dy == 0 else dx / dy

    height = 550
    width = int(height * dataAspect)

    # Set download links for WMS, WCS or WFS and KML
    links = wms_links(ogc_server_settings.public_url + 'wms?',
                      instance.alternate.encode('utf-8'), instance.bbox_string,
                      instance.srid, height, width)

    for ext, name, mime, wms_url in links:
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   name=ugettext(name),
                                   defaults=dict(
                                       extension=ext,
                                       url=wms_url,
                                       mime=mime,
                                       link_type='image',
                                   )
                                   )

    if instance.storeType == "dataStore":
        links = wfs_links(
            ogc_server_settings.public_url +
            'wfs?',
            instance.alternate.encode('utf-8'))
        for ext, name, mime, wfs_url in links:
            if mime == 'SHAPE-ZIP':
                name = 'Zipped Shapefile'
            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=wfs_url,
                                       defaults=dict(
                                           extension=ext,
                                           name=name,
                                           mime=mime,
                                           url=wfs_url,
                                           link_type='data',
                                       )
                                       )

        gs_store_type = gs_resource.store.type.lower() if gs_resource.store.type else None
        geogig_repository = gs_resource.store.connection_parameters.get('geogig_repository', '')
        geogig_repo_name = geogig_repository.replace('geoserver://', '')
Example #18
0
def geoserver_post_save_local(instance, *args, **kwargs):
    """Send information to geoserver.

       The attributes sent include:

        * Title
        * Abstract
        * Name
        * Keywords
        * Metadata Links,
        * Point of Contact name and url
    """
    # Don't run this signal if is a Layer from a remote service
    if getattr(instance, "remote_service", None) is not None:
        return

    # Don't run this signal handler if it is a tile layer or a remote store (Service)
    #    Currently only gpkg files containing tiles will have this type & will be served via MapProxy.
    if hasattr(instance, 'storeType') and getattr(
            instance, 'storeType') in ['tileStore', 'remoteStore']:
        return instance

    gs_resource = None
    values = None

    # If the store in None then it's a new instance from an upload,
    # only in this case run the geoserver_upload method
    if not instance.store or getattr(instance, 'overwrite', False):
        base_file, info = instance.get_base_file()

        # There is no need to process it if there is not file.
        if base_file is None:
            return
        gs_name, workspace, values, gs_resource = geoserver_upload(
            instance,
            base_file.file.path,
            instance.owner,
            instance.name,
            overwrite=True,
            title=instance.title,
            abstract=instance.abstract,
            # keywords=instance.keywords,
            charset=instance.charset)

    if not gs_resource:
        gs_resource = gs_catalog.get_resource(instance.name,
                                              store=instance.store,
                                              workspace=instance.workspace)
        if not gs_resource:
            gs_resource = gs_catalog.get_resource(instance.alternate)

    if gs_resource:
        gs_resource.title = instance.title or ""
        gs_resource.abstract = instance.abstract or ""
        gs_resource.name = instance.name or ""

        if not values:
            values = dict(store=gs_resource.store.name,
                          storeType=gs_resource.store.resource_type,
                          alternate=gs_resource.store.workspace.name + ':' +
                          gs_resource.name,
                          title=gs_resource.title or gs_resource.store.name,
                          abstract=gs_resource.abstract or '',
                          owner=instance.owner)
    else:
        msg = "There isn't a geoserver resource for this layer: %s" % instance.name
        logger.exception(msg)
        raise Exception(msg)

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.mime, link.name, link.url))

    gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if
    # ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
        try:
            gs_catalog.save(gs_resource)
        except geoserver.catalog.FailedRequestError as e:
            msg = (
                'Error while trying to save resource named %s in GeoServer, '
                'try to use: "%s"' % (gs_resource, str(e)))
            e.args = (msg, )
            logger.exception(e)

    gs_layer = gs_catalog.get_layer(instance.name)

    if not gs_layer:
        gs_layer = gs_catalog.get_layer(instance.alternate)

    if gs_layer and instance.poc:
        # gsconfig now utilizes an attribution dictionary
        gs_layer.attribution = {
            'title': str(instance.poc),
            'width': None,
            'height': None,
            'href': None,
            'url': None,
            'type': None
        }
        profile = Profile.objects.get(username=instance.poc.username)
        gs_layer.attribution_link = settings.SITEURL[:
                                                     -1] + profile.get_absolute_url(
                                                     )
        # gs_layer should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            try:
                gs_catalog.save(gs_layer)
            except geoserver.catalog.FailedRequestError as e:
                msg = (
                    'Error while trying to save layer named %s in GeoServer, '
                    'try to use: "%s"' % (gs_layer, str(e)))
                e.args = (msg, )
                logger.exception(e)

    if type(instance) is ResourceBase:
        if hasattr(instance, 'layer'):
            instance = instance.layer
        else:
            return

    if instance.storeType == "remoteStore":
        # Save layer attributes
        set_attributes_from_geoserver(instance)
        return
    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """
    # instance.name = instance.name or gs_layer.name
    # instance.title = instance.title or gs_resource.title
    instance.abstract = gs_resource.abstract or ''
    instance.workspace = gs_resource.store.workspace.name
    instance.store = gs_resource.store.name

    bbox = gs_resource.native_bbox

    # Set bounding box values
    instance.bbox_x0 = bbox[0]
    instance.bbox_x1 = bbox[1]
    instance.bbox_y0 = bbox[2]
    instance.bbox_y1 = bbox[3]
    instance.srid = bbox[4]

    if instance.srid:
        instance.srid_url = "http://www.spatialreference.org/ref/" + \
            instance.srid.replace(':', '/').lower() + "/"
    else:
        raise GeoNodeException("Invalid Projection. Layer is missing CRS!")

    # Iterate over values from geoserver.
    for key in ['alternate', 'store', 'storeType']:
        # attr_name = key if 'typename' not in key else 'alternate'
        # print attr_name
        setattr(instance, key, values[key])

    if settings.RESOURCE_PUBLISHING:
        if instance.is_published != gs_resource.advertised:
            if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
                gs_resource.advertised = 'true' if instance.is_published else 'false'
                gs_catalog.save(gs_resource)

    if not settings.FREETEXT_KEYWORDS_READONLY:
        if gs_resource.keywords:
            for keyword in gs_resource.keywords:
                if keyword not in instance.keyword_list():
                    instance.keywords.add(keyword)

    if any(instance.keyword_list()):
        keywords = instance.keyword_list()
        gs_resource.keywords = list(set(keywords))

        # gs_resource should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            try:
                gs_catalog.save(gs_resource)
            except geoserver.catalog.FailedRequestError as e:
                msg = (
                    'Error while trying to save resource named %s in GeoServer, '
                    'try to use: "%s"' % (gs_resource, str(e)))
                e.args = (msg, )
                logger.exception(e)

    to_update = {
        'title': instance.title or instance.name,
        'abstract': instance.abstract or "",
        'alternate': instance.alternate,
        'bbox_x0': instance.bbox_x0,
        'bbox_x1': instance.bbox_x1,
        'bbox_y0': instance.bbox_y0,
        'bbox_y1': instance.bbox_y1,
        'srid': instance.srid
    }

    # Update ResourceBase
    resources = ResourceBase.objects.filter(id=instance.resourcebase_ptr.id)
    resources.update(**to_update)

    # to_update['name'] = instance.name,
    to_update['workspace'] = instance.workspace
    to_update['store'] = instance.store
    to_update['storeType'] = instance.storeType
    to_update['typename'] = instance.alternate

    # Save all the modified information in the instance without triggering signals.
    Layer.objects.filter(id=instance.id).update(**to_update)

    # Refresh from DB
    instance.refresh_from_db()

    # store the resource to avoid another geoserver call in the post_save
    instance.gs_resource = gs_resource

    bbox = gs_resource.native_bbox
    dx = float(bbox[1]) - float(bbox[0])
    dy = float(bbox[3]) - float(bbox[2])

    dataAspect = 1 if dy == 0 else dx / dy

    height = 550
    width = int(height * dataAspect)

    # Set download links for WMS, WCS or WFS and KML
    links = wms_links(ogc_server_settings.public_url + 'wms?',
                      instance.alternate.encode('utf-8'), instance.bbox_string,
                      instance.srid, height, width)

    for ext, name, mime, wms_url in links:
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   name=ugettext(name),
                                   defaults=dict(
                                       extension=ext,
                                       url=wms_url,
                                       mime=mime,
                                       link_type='image',
                                   ))

    if instance.storeType == "dataStore":
        links = wfs_links(ogc_server_settings.public_url + 'wfs?',
                          instance.alternate.encode('utf-8'))
        for ext, name, mime, wfs_url in links:
            if mime == 'SHAPE-ZIP':
                name = 'Zipped Shapefile'
            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=wfs_url,
                                       defaults=dict(
                                           extension=ext,
                                           name=name,
                                           mime=mime,
                                           url=wfs_url,
                                           link_type='data',
                                       ))

        gs_store_type = gs_resource.store.type.lower(
        ) if gs_resource.store.type else None
        geogig_repository = gs_resource.store.connection_parameters.get(
            'geogig_repository', '')
        geogig_repo_name = geogig_repository.replace('geoserver://', '')

        if gs_store_type == 'geogig' and geogig_repo_name:

            repo_url = '{url}geogig/repos/{repo_name}'.format(
                url=ogc_server_settings.public_url, repo_name=geogig_repo_name)

            path = gs_resource.dom.findall('nativeName')

            if path:
                path = 'path={path}'.format(path=path[0].text)

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=repo_url,
                                       defaults=dict(extension='html',
                                                     name='Clone in GeoGig',
                                                     mime='text/xml',
                                                     link_type='html'))

            def command_url(command):
                return "{repo_url}/{command}.json?{path}".format(
                    repo_url=repo_url, path=path, command=command)

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=command_url('log'),
                                       defaults=dict(extension='json',
                                                     name='GeoGig log',
                                                     mime='application/json',
                                                     link_type='html'))

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=command_url('statistics'),
                                       defaults=dict(extension='json',
                                                     name='GeoGig statistics',
                                                     mime='application/json',
                                                     link_type='html'))

    elif instance.storeType == 'coverageStore':
        links = wcs_links(ogc_server_settings.public_url + 'wcs?',
                          instance.alternate.encode('utf-8'),
                          ','.join(str(x) for x in instance.bbox[0:4]),
                          instance.srid)

    for ext, name, mime, wcs_url in links:
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=wcs_url,
                                   defaults=dict(
                                       extension=ext,
                                       name=name,
                                       mime=mime,
                                       link_type='data',
                                   ))

    kml_reflector_link_download = ogc_server_settings.public_url + "wms/kml?" + \
        urllib.urlencode({'layers': instance.alternate.encode('utf-8'), 'mode': "download"})

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=kml_reflector_link_download,
                               defaults=dict(
                                   extension='kml',
                                   name="KML",
                                   mime='text/xml',
                                   link_type='data',
                               ))

    kml_reflector_link_view = ogc_server_settings.public_url + "wms/kml?" + \
        urllib.urlencode({'layers': instance.alternate.encode('utf-8'), 'mode': "refresh"})

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=kml_reflector_link_view,
                               defaults=dict(
                                   extension='kml',
                                   name="View in Google Earth",
                                   mime='text/xml',
                                   link_type='data',
                               ))

    html_link_url = '%s%s' % (settings.SITEURL[:-1],
                              instance.get_absolute_url())

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=html_link_url,
                               defaults=dict(
                                   extension='html',
                                   name=instance.alternate,
                                   mime='text/html',
                                   link_type='html',
                               ))

    # some thumbnail generators will update thumbnail_url.  If so, don't
    # immediately re-generate the thumbnail here.  use layer#save(update_fields=['thumbnail_url'])
    if not ('update_fields' in kwargs and kwargs['update_fields'] is not None
            and 'thumbnail_url' in kwargs['update_fields']):
        logger.info("Creating Thumbnail for Layer [%s]" % (instance.alternate))
        create_gs_thumbnail(instance, overwrite=True)

    legend_url = ogc_server_settings.PUBLIC_LOCATION + \
        'wms?request=GetLegendGraphic&format=image/png&WIDTH=20&HEIGHT=20&LAYER=' + \
        instance.alternate + '&legend_options=fontAntiAliasing:true;fontSize:12;forceLabels:on'

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=legend_url,
                               defaults=dict(
                                   extension='png',
                                   name='Legend',
                                   url=legend_url,
                                   mime='image/png',
                                   link_type='image',
                               ))

    ogc_wms_path = '%s/ows' % instance.workspace
    ogc_wms_url = urljoin(ogc_server_settings.public_url, ogc_wms_path)
    ogc_wms_name = 'OGC WMS: %s Service' % instance.workspace
    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=ogc_wms_url,
                               defaults=dict(
                                   extension='html',
                                   name=ogc_wms_name,
                                   url=ogc_wms_url,
                                   mime='text/html',
                                   link_type='OGC:WMS',
                               ))

    if instance.storeType == "dataStore":
        ogc_wfs_path = '%s/wfs' % instance.workspace
        ogc_wfs_url = urljoin(ogc_server_settings.public_url, ogc_wfs_path)
        ogc_wfs_name = 'OGC WFS: %s Service' % instance.workspace
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=ogc_wfs_url,
                                   defaults=dict(
                                       extension='html',
                                       name=ogc_wfs_name,
                                       url=ogc_wfs_url,
                                       mime='text/html',
                                       link_type='OGC:WFS',
                                   ))

    if instance.storeType == "coverageStore":
        ogc_wcs_path = '%s/wcs' % instance.workspace
        ogc_wcs_url = urljoin(ogc_server_settings.public_url, ogc_wcs_path)
        ogc_wcs_name = 'OGC WCS: %s Service' % instance.workspace
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=ogc_wcs_url,
                                   defaults=dict(
                                       extension='html',
                                       name=ogc_wcs_name,
                                       url=ogc_wcs_url,
                                       mime='text/html',
                                       link_type='OGC:WCS',
                                   ))

    # remove links that belong to and old address
    for link in instance.link_set.all():
        if not urlparse(settings.SITEURL).hostname == urlparse(
                link.url).hostname and not urlparse(
                    ogc_server_settings.public_url).hostname == urlparse(
                        link.url).hostname:
            link.delete()

    # Define the link after the cleanup, we should use this more rather then remove
    # potential parasites
    tile_url = ('%sgwc/service/gmaps?' % ogc_server_settings.public_url +
                'layers=%s' % instance.alternate.encode('utf-8') +
                '&zoom={z}&x={x}&y={y}' + '&format=image/png8')

    link, created = Link.objects.get_or_create(
        resource=instance.resourcebase_ptr,
        extension='tiles',
        name="Tiles",
        mime='image/png',
        link_type='image',
    )
    if created:
        Link.objects.filter(pk=link.pk).update(url=tile_url)

    # Save layer attributes
    set_attributes_from_geoserver(instance)

    # Save layer styles
    set_styles(instance, gs_catalog)

    # NOTTODO by simod: we should not do this!
    # need to be removed when fixing #2015
    catalogue_post_save(instance, Layer)
Example #19
0
def layer_create(request, data=None, template='upload/layer_create.html'):
    print 'layer create'
    if request.method == 'POST':
        feature_type = json.loads(request.POST.get(u'featureType', None))
        datastore = feature_type['store']['name']
        store_create_geogig = json.loads(
            request.POST.get(u'storeCreateGeogig', 'false'))

        if store_create_geogig:
            if not feature_type['store']['name']:
                store_proposed = slugify(' '.join(
                    [request.user.username, feature_type['name']]))
            store_created = create_geoserver_db_featurestore(
                store_type='geogig', store_name=store_proposed)
            feature_type['store']['name'] = store_created.name

        # -- only allow creation of layers in the whitelisted datastores
        try:
            settings.ALLOWED_DATASTORE_LAYER_CREATE
        except AttributeError:
            return HttpResponse(
                status=FORBIDDEN,
                content=
                'ALLOWED_DATASTORE_LAYER_CREATE whitelist is not defined.')

        if datastore not in settings.ALLOWED_DATASTORE_LAYER_CREATE:
            return HttpResponse(
                status=FORBIDDEN,
                content=
                'datastore specified in featureType is not in the ALLOWED_DATASTORE_LAYER_CREATE whitelist.'
            )

        post_request = requests.post(
            '{}/workspaces/{}/datastores/{}/featuretypes.json'.format(
                ogc_server_settings.rest, feature_type['namespace']['name'],
                datastore),
            data='{{"featureType":{}}}'.format(json.dumps(feature_type)),
            auth=ogc_server_settings.credentials,
            headers={'content-type': 'application/json'})

        if post_request.status_code == 200 or post_request.status_code == 201:
            # import the layer from geoserver to geonode
            response = gs_slurp(filter=feature_type['name'],
                                workspace=feature_type['namespace']['name'],
                                store=feature_type['store']['name'])
            if 'layers' in response and len(
                    response['layers']
            ) == 1 and 'name' in response['layers'][0] and response['layers'][
                    0]['name'] == feature_type['name']:
                # configruer layer with time dimension as a list for now. Since importer is being refactored,
                # we'll change how it is done.
                layer = gs_catalog.get_layer(feature_type['name'])
                resource = layer.resource
                if layer:
                    time_info = DimensionInfo(name='time',
                                              enabled=True,
                                              presentation='LIST',
                                              resolution=None,
                                              units=None,
                                              unitSymbol=None,
                                              attribute='time',
                                              end_attribute=None,
                                              strategy=None)
                    resource.metadata = {'time': time_info}
                    resource.catalog.save(resource)
                    return HttpResponse(status=post_request.status_code,
                                        content=post_request.text)
                return HttpResponse(status=500,
                                    content='failed to configure layer')
            else:
                return HttpResponse(
                    status=500,
                    content=
                    'failed to add created layer from geoserver to geonode')
        else:
            return HttpResponse(status=post_request.status_code,
                                content=post_request.text)
        print '---- create layer response: ', post_request.text
    return render_to_response(template, RequestContext(request, {}))
Example #20
0
    def reload_data(self, geonode_layer):
        if self.task:
            self.task.status = "IN_PROGRESS"
            self.task.save()
        # To get layer name from alternate as it is the same as DB table name and geoserver layer name
        self.config_obj.name = geonode_layer.alternate.split(':')[-1]
        self.config_obj.overwrite = True
        feature_iter = iter(self)
        gtype = self.esri_serializer.get_geometry_type()
        store = get_store(gs_catalog, geonode_layer.store,
                          geonode_layer.workspace)
        # get database name and schema name from layer datastore
        # TODO: get all parameters for the datastore
        # TODO: find a way to pass the database password also , as it is encrypted in the datastore.
        db_connection = get_connection(
            database_name=store.connection_parameters['database'],
            schema=store.connection_parameters.get('schema', 'public'))
        with OSGEOManager.open_source(db_connection,
                                      update_enabled=1) as source:
            geoserver_layer = gs_catalog.get_layer(geonode_layer.alternate)
            # pass native_name to GetLayer as it represents the table name
            layer = source.GetLayer(geoserver_layer.resource.native_name)
            try:
                layer.StartTransaction()
                # remove all features
                # Note: remove features one by one allow to rollback if the error raised
                # TODO: check if truncating the table is possible to enhance the performance
                old_feature = layer.GetNextFeature()
                while old_feature:
                    layer.DeleteFeature(old_feature.GetFID())
                    old_feature = layer.GetNextFeature()
                # TODO: reset FID sequence otherwise new FIDs will be generated

                # build fields is mandatory for domain fields and subtypes
                self.esri_serializer.build_fields()

                # set outSR by destination layer wkid, to retrieve the features with matched projection
                self.set_out_sr(
                    int(layer.GetSpatialRef().GetAuthorityCode(None)))

                # importing the features again
                for next_feature in feature_iter:
                    self.create_feature(layer, next_feature, gtype)
                layer.CommitTransaction()

                geoserver_pub = GeoserverPublisher()
                # remove layer caching to update rendering.
                # otherwise changes will not be rendered until layer refreshed
                geoserver_pub.remove_cached(geonode_layer.typename)

                if self.task:
                    self.task.status = "FINISHED"
                    self.task.save()
            # TODO: check the which exceptions should be handled
            except (StopIteration, EsriFeatureLayerException, ConnectionError,
                    BaseException) as e:
                layer.RollbackTransaction()
                logger.error(e)
                return False
            else:
                return True
Example #21
0
def geoserver_post_save2(layer_id):
    """Save keywords to GeoServer

       The way keywords are implemented requires the layer
       to be saved to the database before accessing them.
    """
    """Send information to geoserver.

           The attributes sent include:

            * Title
            * Abstract
            * Name
            * Keywords
            * Metadata Links,
            * Point of Contact name and url
        """

    from geonode.layers.models import Layer
    instance = Layer.objects.get(id=layer_id)
    # Don't run this signal if is a Layer from a remote service
    if getattr(instance, "service", None) is not None:
        return instance

    # Don't run this signal handler if it is a tile layer
    #    Currently only gpkg files containing tiles will have this type & will be served via MapProxy.
    if hasattr(instance, 'storeType') and getattr(instance,
                                                  'storeType') == 'tileStore':
        return instance

    gs_resource = None

    # If the store in None then it's a new instance from an upload,
    # only in this case run the geonode_uplaod method
    if not instance.store or getattr(instance, 'overwrite', False):
        base_file, info = instance.get_base_file()

        # There is no need to process it if there is not file.
        if base_file is None:
            return instance

        gs_name, workspace, values, gs_resource = geoserver_upload(
            instance,
            base_file.file.path,
            instance.owner,
            instance.name,
            overwrite=True,
            title=instance.title,
            abstract=instance.abstract,
            # keywords=instance.keywords,
            charset=instance.charset)

        # Set fields obtained via the geoserver upload.
        instance.name = gs_name
        instance.workspace = workspace
        instance.store = values['store']
        # Iterate over values from geoserver.
        for key in ['typename', 'store', 'storeType']:
            setattr(instance, key, values[key])

        instance.save()

    if not gs_resource:
        gs_resource = gs_catalog.get_resource(instance.name,
                                              store=instance.store,
                                              workspace=instance.workspace)

    if gs_resource:
        gs_resource.title = instance.title if instance.title else ""
        gs_resource.abstract = instance.abstract if instance.abstract else ""
        gs_resource.name = instance.name if instance.name else ""

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.mime, link.name, link.url))

    if gs_resource:
        gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if
    # ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if gs_resource and getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED",
                               True):
        gs_catalog.save(gs_resource)

    gs_layer = gs_catalog.get_layer(instance.name)

    if instance.poc and instance.poc:
        # gsconfig now utilizes an attribution dictionary
        gs_layer.attribution = {
            'title': str(instance.poc),
            'width': None,
            'height': None,
            'href': None,
            'url': None,
            'type': None
        }
        profile = Profile.objects.get(username=instance.poc.username)
        gs_layer.attribution_link = settings.SITEURL[:
                                                     -1] + profile.get_absolute_url(
                                                     )
        # gs_layer should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_layer)
    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """

    if gs_resource:
        bbox = gs_resource.latlon_bbox

        # FIXME(Ariel): Correct srid setting below
        # self.srid = gs_resource.src

        instance.srid_url = "http://www.spatialreference.org/ref/" + \
                            instance.srid.replace(':', '/').lower() + "/"

        # Set bounding box values
        instance.bbox_x0 = bbox[0]
        instance.bbox_x1 = bbox[1]
        instance.bbox_y0 = bbox[2]
        instance.bbox_y1 = bbox[3]

        # store the resource to avoid another geoserver call in the post_save
        instance.gs_resource = gs_resource

    instance.save()

    if type(instance) is ResourceBase:
        if hasattr(instance, 'layer'):
            instance = instance.layer
        else:
            return instance

    if instance.storeType == "remoteStore":
        # Save layer attributes
        set_attributes_from_geoserver(instance)
        return instance

    if not getattr(instance, 'gs_resource', None):
        try:
            gs_resource = gs_catalog.get_resource(instance.name,
                                                  store=instance.store,
                                                  workspace=instance.workspace)
        except socket_error as serr:
            if serr.errno != errno.ECONNREFUSED:
                # Not the error we are looking for, re-raise
                raise serr
            # If the connection is refused, take it easy.
            return instance
    else:
        gs_resource = instance.gs_resource

    if gs_resource is None:
        return instance

    if settings.RESOURCE_PUBLISHING:
        if instance.is_published != gs_resource.advertised:
            if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
                gs_resource.advertised = instance.is_published
                gs_catalog.save(gs_resource)

    if any(instance.keyword_list()):
        gs_resource.keywords = instance.keyword_list()
        # gs_resource should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_resource)

    bbox = gs_resource.latlon_bbox
    dx = float(bbox[1]) - float(bbox[0])
    dy = float(bbox[3]) - float(bbox[2])

    dataAspect = 1 if dy == 0 else dx / dy

    height = 550
    width = int(height * dataAspect)

    # Set download links for WMS, WCS or WFS and KML
    links = wms_links(ogc_server_settings.public_url + 'wms?',
                      instance.typename.encode('utf-8'), instance.bbox_string,
                      instance.srid, height, width)

    for ext, name, mime, wms_url in links:
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   name=ugettext(name),
                                   defaults=dict(
                                       extension=ext,
                                       url=wms_url,
                                       mime=mime,
                                       link_type='image',
                                   ))

    if instance.storeType == "dataStore":
        links = wfs_links(ogc_server_settings.public_url + 'wfs?',
                          instance.typename.encode('utf-8'))
        for ext, name, mime, wfs_url in links:
            if mime == 'SHAPE-ZIP':
                name = 'Zipped Shapefile'
            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=wfs_url,
                                       defaults=dict(
                                           extension=ext,
                                           name=name,
                                           mime=mime,
                                           url=wfs_url,
                                           link_type='data',
                                       ))

        gs_store_type = gs_resource.store.type.lower(
        ) if gs_resource.store.type else None
        geogig_repository = gs_resource.store.connection_parameters.get(
            'geogig_repository', '')
        geogig_repo_name = geogig_repository.replace('geoserver://', '')

        if gs_store_type == 'geogig' and geogig_repo_name:

            repo_url = '{url}geogig/repos/{repo_name}'.format(
                url=ogc_server_settings.public_url, repo_name=geogig_repo_name)

            path = gs_resource.dom.findall('nativeName')

            if path:
                path = 'path={path}'.format(path=path[0].text)

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=repo_url,
                                       defaults=dict(extension='html',
                                                     name='Clone in GeoGig',
                                                     mime='text/xml',
                                                     link_type='html'))

            def command_url(command):
                return "{repo_url}/{command}.json?{path}".format(
                    repo_url=repo_url, path=path, command=command)

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=command_url('log'),
                                       defaults=dict(extension='json',
                                                     name='GeoGig log',
                                                     mime='application/json',
                                                     link_type='html'))

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=command_url('statistics'),
                                       defaults=dict(extension='json',
                                                     name='GeoGig statistics',
                                                     mime='application/json',
                                                     link_type='html'))

    elif instance.storeType == 'coverageStore':

        links = wcs_links(ogc_server_settings.public_url + 'wcs?',
                          instance.typename.encode('utf-8'))

    for ext, name, mime, wcs_url in links:
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=wcs_url,
                                   defaults=dict(
                                       extension=ext,
                                       name=name,
                                       mime=mime,
                                       link_type='data',
                                   ))

    kml_reflector_link_download = ogc_server_settings.public_url + "wms/kml?" + \
        urllib.urlencode({'layers': instance.typename.encode('utf-8'), 'mode': "download"})

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=kml_reflector_link_download,
                               defaults=dict(
                                   extension='kml',
                                   name="KML",
                                   mime='text/xml',
                                   link_type='data',
                               ))

    kml_reflector_link_view = ogc_server_settings.public_url + "wms/kml?" + \
        urllib.urlencode({'layers': instance.typename.encode('utf-8'), 'mode': "refresh"})

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=kml_reflector_link_view,
                               defaults=dict(
                                   extension='kml',
                                   name="View in Google Earth",
                                   mime='text/xml',
                                   link_type='data',
                               ))

    html_link_url = '%s%s' % (settings.SITEURL[:-1],
                              instance.get_absolute_url())

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=html_link_url,
                               defaults=dict(
                                   extension='html',
                                   name=instance.typename,
                                   mime='text/html',
                                   link_type='html',
                               ))

    create_gs_thumbnail(instance, overwrite=False)

    legend_url = ogc_server_settings.PUBLIC_LOCATION + \
        'wms?request=GetLegendGraphic&format=image/png&WIDTH=20&HEIGHT=20&LAYER=' + \
        instance.typename + '&legend_options=fontAntiAliasing:true;fontSize:12;forceLabels:on'

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=legend_url,
                               defaults=dict(
                                   extension='png',
                                   name='Legend',
                                   url=legend_url,
                                   mime='image/png',
                                   link_type='image',
                               ))

    ogc_wms_path = '%s/wms' % instance.workspace
    ogc_wms_url = urljoin(ogc_server_settings.public_url, ogc_wms_path)
    ogc_wms_name = 'OGC WMS: %s Service' % instance.workspace
    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=ogc_wms_url,
                               defaults=dict(
                                   extension='html',
                                   name=ogc_wms_name,
                                   url=ogc_wms_url,
                                   mime='text/html',
                                   link_type='OGC:WMS',
                               ))

    if instance.storeType == "dataStore":
        ogc_wfs_path = '%s/wfs' % instance.workspace
        ogc_wfs_url = urljoin(ogc_server_settings.public_url, ogc_wfs_path)
        ogc_wfs_name = 'OGC WFS: %s Service' % instance.workspace
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=ogc_wfs_url,
                                   defaults=dict(
                                       extension='html',
                                       name=ogc_wfs_name,
                                       url=ogc_wfs_url,
                                       mime='text/html',
                                       link_type='OGC:WFS',
                                   ))

    if instance.storeType == "coverageStore":
        ogc_wcs_path = '%s/wcs' % instance.workspace
        ogc_wcs_url = urljoin(ogc_server_settings.public_url, ogc_wcs_path)
        ogc_wcs_name = 'OGC WCS: %s Service' % instance.workspace
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=ogc_wcs_url,
                                   defaults=dict(
                                       extension='html',
                                       name=ogc_wcs_name,
                                       url=ogc_wcs_url,
                                       mime='text/html',
                                       link_type='OGC:WCS',
                                   ))

    # remove links that belong to and old address

    for link in instance.link_set.all():
        if not urlparse(settings.SITEURL).hostname == urlparse(
                link.url).hostname and not urlparse(
                    ogc_server_settings.public_url).hostname == urlparse(
                        link.url).hostname:
            link.delete()

    # Define the link after the cleanup, we should use this more rather then remove
    # potential parasites
    tile_url = ('%sgwc/service/gmaps?' % ogc_server_settings.public_url +
                'layers=%s' % instance.typename.encode('utf-8') +
                '&zoom={z}&x={x}&y={y}' + '&format=image/png8')

    link, created = Link.objects.get_or_create(
        resource=instance.resourcebase_ptr,
        extension='tiles',
        name="Tiles",
        mime='image/png',
        link_type='image',
    )
    if created:
        Link.objects.filter(pk=link.pk).update(url=tile_url)

    # Save layer attributes
    set_attributes_from_geoserver(instance)

    # Save layer styles
    set_styles(instance, gs_catalog)
    # NOTTODO by simod: we should not do this!
    # need to be removed when fixing #2015
    from geonode.catalogue.models import catalogue_post_save
    from geonode.layers.models import Layer
    catalogue_post_save(instance, Layer)
    return instance
Example #22
0
def geoserver_pre_save(instance, sender, **kwargs):
    """Send information to geoserver.

       The attributes sent include:

        * Title
        * Abstract
        * Name
        * Keywords
        * Metadata Links,
        * Point of Contact name and url
    """

    # Don't run this signal if is a Layer from a remote service
    if getattr(instance, "service", None) is not None:
        return

    gs_resource = None

    # If the store in None then it's a new instance from an upload,
    # only in this case run the geonode_uplaod method
    if not instance.store or getattr(instance, 'overwrite', False):
        base_file, info = instance.get_base_file()

        # There is no need to process it if there is not file.
        if base_file is None:
            return
        gs_name, workspace, values, gs_resource = geoserver_upload(instance,
                                                                   base_file.file.path,
                                                                   instance.owner,
                                                                   instance.name,
                                                                   overwrite=True,
                                                                   title=instance.title,
                                                                   abstract=instance.abstract,
                                                                   # keywords=instance.keywords,
                                                                   charset=instance.charset)
        # Set fields obtained via the geoserver upload.
        instance.name = gs_name
        instance.workspace = workspace
        # Iterate over values from geoserver.
        for key in ['typename', 'store', 'storeType']:
            setattr(instance, key, values[key])

    if not gs_resource:
        gs_resource = gs_catalog.get_resource(
            instance.name,
            store=instance.store,
            workspace=instance.workspace)

    gs_resource.title = instance.title
    gs_resource.abstract = instance.abstract
    gs_resource.name = instance.name

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.mime, link.name, link.url))

    gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if
    # ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
        gs_catalog.save(gs_resource)

    gs_layer = gs_catalog.get_layer(instance.name)

    if instance.poc and instance.poc:
        # gsconfig now utilizes an attribution dictionary
        gs_layer.attribution = {'title': str(instance.poc),
                                'width': None,
                                'height': None,
                                'href': None,
                                'url': None,
                                'type': None}
        profile = Profile.objects.get(username=instance.poc.username)
        gs_layer.attribution_link = settings.SITEURL[
            :-1] + profile.get_absolute_url()
        # gs_layer should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_layer)

    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """

    bbox = gs_resource.latlon_bbox

    # FIXME(Ariel): Correct srid setting below
    # self.srid = gs_resource.src

    instance.srid_url = "http://www.spatialreference.org/ref/" + \
        instance.srid.replace(':', '/').lower() + "/"

    # Set bounding box values
    instance.bbox_x0 = bbox[0]
    instance.bbox_x1 = bbox[1]
    instance.bbox_y0 = bbox[2]
    instance.bbox_y1 = bbox[3]

    # store the resource to avoid another geoserver call in the post_save
    instance.gs_resource = gs_resource
Example #23
0
def validate_input_source(layer,
                          filename,
                          files,
                          gtype=None,
                          action_type='replace'):
    if layer.is_vector() and is_raster(filename):
        raise Exception(
            _(f"You are attempting to {action_type} a vector layer with a raster."
              ))
    elif (not layer.is_vector()) and is_vector(filename):
        raise Exception(
            _(f"You are attempting to {action_type} a raster layer with a vector."
              ))

    if layer.is_vector():
        absolute_base_file = None
        try:
            if 'shp' in files and os.path.exists(files['shp']):
                absolute_base_file = _fixup_base_file(files['shp'])
            elif 'zip' in files and os.path.exists(files['zip']):
                absolute_base_file = _fixup_base_file(files['zip'])
        except Exception:
            absolute_base_file = None

        if not absolute_base_file or \
                os.path.splitext(absolute_base_file)[1].lower() != '.shp':
            raise Exception(
                _(f"You are attempting to {action_type} a vector layer with an unknown format."
                  ))
        else:
            try:
                gtype = layer.gtype if not gtype else gtype
                inDataSource = ogr.Open(absolute_base_file)
                lyr = inDataSource.GetLayer(str(layer.name))
                if not lyr:
                    raise Exception(
                        _(f"Please ensure the name is consistent with the file you are trying to {action_type}."
                          ))
                schema_is_compliant = False
                _ff = json.loads(lyr.GetFeature(0).ExportToJson())
                if gtype:
                    logger.warning(
                        _("Local GeoNode layer has no geometry type."))
                    if _ff["geometry"]["type"] in gtype or gtype in _ff[
                            "geometry"]["type"]:
                        schema_is_compliant = True
                elif "geometry" in _ff and _ff["geometry"]["type"]:
                    schema_is_compliant = True

                if not schema_is_compliant:
                    raise Exception(
                        _(f"Please ensure there is at least one geometry type \
                            that is consistent with the file you are trying to {action_type}."
                          ))

                new_schema_fields = [field.name for field in lyr.schema]
                gs_layer = gs_catalog.get_layer(layer.name)

                if not gs_layer:
                    raise Exception(
                        _("The selected Layer does not exists in the catalog.")
                    )

                gs_layer = gs_layer.resource.attributes
                schema_is_compliant = all(
                    [x in gs_layer for x in new_schema_fields])

                if not schema_is_compliant:
                    raise Exception(
                        _("Please ensure that the layer structure is consistent "
                          f"with the file you are trying to {action_type}."))
                return True
            except Exception as e:
                raise Exception(
                    _(f"Some error occurred while trying to access the uploaded schema: {str(e)}"
                      ))
Example #24
0
def geoserver_pre_save(instance, sender, **kwargs):
    """Send information to geoserver.

       The attributes sent include:

        * Title
        * Abstract
        * Name
        * Keywords
        * Metadata Links,
        * Point of Contact name and url
    """

    # Don't run this signal handler if it is a tile layer or a remote store (Service)
    #    Currently only gpkg files containing tiles will have this type & will be served via MapProxy.
    if hasattr(instance, 'storeType') and getattr(
            instance, 'storeType') in ['tileStore', 'remoteStore']:
        return

    gs_resource = None

    # If the store in None then it's a new instance from an upload,
    # only in this case run the geonode_uplaod method
    if not instance.store or getattr(instance, 'overwrite', False):
        base_file, info = instance.get_base_file()

        # There is no need to process it if there is not file.
        if base_file is None:
            return
        gs_name, workspace, values, gs_resource = geoserver_upload(
            instance,
            base_file.file.path,
            instance.owner,
            instance.name,
            overwrite=True,
            title=instance.title,
            abstract=instance.abstract,
            # keywords=instance.keywords,
            charset=instance.charset)
        # Set fields obtained via the geoserver upload.
        instance.name = gs_name
        instance.workspace = workspace
        # Iterate over values from geoserver.
        for key in ['typename', 'store', 'storeType']:
            setattr(instance, key, values[key])

    if not gs_resource:
        gs_resource = gs_catalog.get_resource(instance.name,
                                              store=instance.store,
                                              workspace=instance.workspace)

    if gs_resource:
        gs_resource.title = instance.title if instance.title else ""
        gs_resource.abstract = instance.abstract if instance.abstract else ""
        gs_resource.name = instance.name if instance.name else ""

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.mime, link.name, link.url))

    if gs_resource:
        gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if
    # ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if gs_resource and getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED",
                               True):
        gs_catalog.save(gs_resource)

    if instance.storeType and instance.storeType == 'layerGroup':
        gs_layer = gs_catalog.get_layergroup(name=instance.name,
                                             workspace=instance.workspace)
    else:
        gs_layer = gs_catalog.get_layer(instance.name)

    if instance.poc and instance.poc:
        # gsconfig now utilizes an attribution dictionary
        gs_layer.attribution = {
            'title': str(instance.poc),
            'width': None,
            'height': None,
            'href': None,
            'url': None,
            'type': None
        }
        profile = Profile.objects.get(username=instance.poc.username)
        gs_layer.attribution_link = settings.SITEURL[:
                                                     -1] + profile.get_absolute_url(
                                                     )
        # gs_layer should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            try:
                # Some geogig layers will return a 500 on save
                gs_catalog.save(gs_layer)
            except geoserver.catalog.FailedRequestError:
                pass
    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """

    if gs_resource:
        bbox = gs_resource.latlon_bbox

        # FIXME(Ariel): Correct srid setting below
        # self.srid = gs_resource.src

        instance.srid_url = "http://www.spatialreference.org/ref/" + \
            instance.srid.replace(':', '/').lower() + "/"

        # Set bounding box values
        instance.bbox_x0 = bbox[0]
        instance.bbox_x1 = bbox[1]
        instance.bbox_y0 = bbox[2]
        instance.bbox_y1 = bbox[3]

        # store the resource to avoid another geoserver call in the post_save
        instance.gs_resource = gs_resource
Example #25
0
 def set_default_layer_style(self, layername, stylename):
     gs_layer = gs_catalog.get_layer(layername)
     gs_layer.default_style = gs_catalog.get_style(
         stylename, workspace=settings.DEFAULT_WORKSPACE)
     gs_catalog.save(gs_layer)
Example #26
0
def geoserver_pre_save(instance, sender, **kwargs):
    """Send information to geoserver.

       The attributes sent include:

        * Title
        * Abstract
        * Name
        * Keywords
        * Metadata Links,
        * Point of Contact name and url
    """
    url = ogc_server_settings.internal_rest
    try:
        gs_resource = gs_catalog.get_resource(instance.name,
                                              store=instance.store,
                                              workspace=instance.workspace)
    except (EnvironmentError, FailedRequestError) as e:
        gs_resource = None
        msg = ('Could not connect to geoserver at "%s"'
               'to save information for layer "%s"' %
               (ogc_server_settings.LOCATION, instance.name.encode('utf-8')))
        logger.warn(msg, e)
        # If geoserver is not online, there is no need to continue
        return

    # If there is no resource returned it could mean one of two things:
    # a) There is a synchronization problem in geoserver
    # b) The unit tests are running and another geoserver is running in the
    # background.
    # For both cases it is sensible to stop processing the layer
    if gs_resource is None:
        logger.warn('Could not get geoserver resource for %s' % instance)
        return

    gs_resource.title = instance.title
    gs_resource.abstract = instance.abstract
    gs_resource.name = instance.name

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.name, link.mime, link.url))

    gs_resource.metadata_links = metadata_links
    #gs_resource should only be called if ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
        gs_catalog.save(gs_resource)

    gs_layer = gs_catalog.get_layer(instance.name)

    if instance.poc and instance.poc.user:
        gs_layer.attribution = str(instance.poc.user)
        profile = Profile.objects.get(user=instance.poc.user)
        gs_layer.attribution_link = settings.SITEURL[:
                                                     -1] + profile.get_absolute_url(
                                                     )
        #gs_layer should only be called if ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_layer)
    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """
    gs_resource = gs_catalog.get_resource(instance.name)

    bbox = gs_resource.latlon_bbox

    #FIXME(Ariel): Correct srid setting below
    #self.srid = gs_resource.src

    instance.srid_url = "http://www.spatialreference.org/ref/" + instance.srid.replace(
        ':', '/').lower() + "/"
    # Set bounding box values

    instance.bbox_x0 = bbox[0]
    instance.bbox_x1 = bbox[1]
    instance.bbox_y0 = bbox[2]
    instance.bbox_y1 = bbox[3]

    instance.thumbnail, created = Thumbnail.objects.get_or_create(
        resourcebase__id=instance.id)
Example #27
0
def geoserver_post_save2(layer_id):
    """Save keywords to GeoServer

       The way keywords are implemented requires the layer
       to be saved to the database before accessing them.
    """
    """Send information to geoserver.

           The attributes sent include:

            * Title
            * Abstract
            * Name
            * Keywords
            * Metadata Links,
            * Point of Contact name and url
        """

    from geonode.layers.models import Layer
    instance = Layer.objects.get(id=layer_id)
    # Don't run this signal if is a Layer from a remote service
    if getattr(instance, "service", None) is not None:
        return instance

    # Don't run this signal handler if it is a tile layer or a remote store (Service)
    #    Currently only gpkg files containing tiles will have this type & will be served via MapProxy.
    if hasattr(instance, 'storeType') and getattr(instance, 'storeType') in ['tileStore', 'remoteStore']:
        return instance

    gs_resource = None

    # If the store in None then it's a new instance from an upload,
    # only in this case run the geonode_uplaod method
    if not instance.store or getattr(instance, 'overwrite', False):
        base_file, info = instance.get_base_file()

        # There is no need to process it if there is not file.
        if base_file is None:
            return instance

        gs_name, workspace, values, gs_resource = geoserver_upload(instance,
                                                                   base_file.file.path,
                                                                   instance.owner,
                                                                   instance.name,
                                                                   overwrite=True,
                                                                   title=instance.title,
                                                                   abstract=instance.abstract,
                                                                   # keywords=instance.keywords,
                                                                   charset=instance.charset)

        # Set fields obtained via the geoserver upload.
        instance.name = gs_name
        instance.workspace = workspace
        instance.store = values['store']
        # Iterate over values from geoserver.
        for key in ['typename', 'store', 'storeType']:
            setattr(instance, key, values[key])

        instance.save()

    if not gs_resource:
        gs_resource = gs_catalog.get_resource(
            instance.name,
            store=instance.store,
            workspace=instance.workspace)

    if gs_resource:
        gs_resource.title = instance.title if instance.title else ""
        gs_resource.abstract = instance.abstract if instance.abstract else ""
        gs_resource.name = instance.name if instance.name else ""

    # Get metadata links
    metadata_links = []
    for link in instance.link_set.metadata():
        metadata_links.append((link.mime, link.name, link.url))

    if gs_resource:
        gs_resource.metadata_links = metadata_links
    # gs_resource should only be called if
    # ogc_server_settings.BACKEND_WRITE_ENABLED == True
    if gs_resource and getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED",
                               True):
        gs_catalog.save(gs_resource)

    gs_layer = gs_catalog.get_layer(instance.name)

    if instance.poc and instance.poc:
        # gsconfig now utilizes an attribution dictionary
        gs_layer.attribution = {'title': str(instance.poc),
                                'width': None,
                                'height': None,
                                'href': None,
                                'url': None,
                                'type': None}
        profile = Profile.objects.get(username=instance.poc.username)
        gs_layer.attribution_link = settings.SITEURL[
                                    :-1] + profile.get_absolute_url()
        # gs_layer should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_layer)

    """Get information from geoserver.

       The attributes retrieved include:

       * Bounding Box
       * SRID
       * Download links (WMS, WCS or WFS and KML)
       * Styles (SLD)
    """

    if gs_resource:
        bbox = gs_resource.latlon_bbox

        # FIXME(Ariel): Correct srid setting below
        # self.srid = gs_resource.src

        instance.srid_url = "http://www.spatialreference.org/ref/" + \
                            instance.srid.replace(':', '/').lower() + "/"

        # Set bounding box values
        instance.bbox_x0 = bbox[0]
        instance.bbox_x1 = bbox[1]
        instance.bbox_y0 = bbox[2]
        instance.bbox_y1 = bbox[3]

        # store the resource to avoid another geoserver call in the post_save
        instance.gs_resource = gs_resource

    instance.save()

    if type(instance) is ResourceBase:
        if hasattr(instance, 'layer'):
            instance = instance.layer
        else:
            return instance

    if instance.storeType == "remoteStore":
        # Save layer attributes
        set_attributes_from_geoserver(instance)
        return instance

    if not getattr(instance, 'gs_resource', None):
        try:
            gs_resource = gs_catalog.get_resource(
                instance.name,
                store=instance.store,
                workspace=instance.workspace)
        except socket_error as serr:
            if serr.errno != errno.ECONNREFUSED:
                # Not the error we are looking for, re-raise
                raise serr
            # If the connection is refused, take it easy.
            return instance
    else:
        gs_resource = instance.gs_resource

    if gs_resource is None:
        return instance

    if settings.RESOURCE_PUBLISHING:
        if instance.is_published != gs_resource.advertised:
            if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
                gs_resource.advertised = instance.is_published
                gs_catalog.save(gs_resource)

    if any(instance.keyword_list()):
        gs_resource.keywords = instance.keyword_list()
        # gs_resource should only be called if
        # ogc_server_settings.BACKEND_WRITE_ENABLED == True
        if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
            gs_catalog.save(gs_resource)

    bbox = gs_resource.latlon_bbox
    dx = float(bbox[1]) - float(bbox[0])
    dy = float(bbox[3]) - float(bbox[2])

    dataAspect = 1 if dy == 0 else dx / dy

    height = 550
    width = int(height * dataAspect)

    # Set download links for WMS, WCS or WFS and KML
    links = wms_links(ogc_server_settings.public_url + 'wms?',
                      instance.typename.encode('utf-8'), instance.bbox_string,
                      instance.srid, height, width)

    for ext, name, mime, wms_url in links:
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   name=ugettext(name),
                                   defaults=dict(
                                       extension=ext,
                                       url=wms_url,
                                       mime=mime,
                                       link_type='image',
                                   )
                                   )

    if instance.storeType == "dataStore":
        links = wfs_links(
            ogc_server_settings.public_url +
            'wfs?',
            instance.typename.encode('utf-8'))
        for ext, name, mime, wfs_url in links:
            if mime == 'SHAPE-ZIP':
                name = 'Zipped Shapefile'
            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=wfs_url,
                                       defaults=dict(
                                           extension=ext,
                                           name=name,
                                           mime=mime,
                                           url=wfs_url,
                                           link_type='data',
                                       )
                                       )

        gs_store_type = gs_resource.store.type.lower() if gs_resource.store.type else None
        geogig_repository = gs_resource.store.connection_parameters.get('geogig_repository', '')
        geogig_repo_name = geogig_repository.replace('geoserver://', '')

        if gs_store_type == 'geogig' and geogig_repo_name:

            repo_url = '{url}geogig/repos/{repo_name}'.format(
                url=ogc_server_settings.public_url,
                repo_name=geogig_repo_name)

            path = gs_resource.dom.findall('nativeName')

            if path:
                path = 'path={path}'.format(path=path[0].text)

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=repo_url,
                                       defaults=dict(extension='html',
                                                     name='Clone in GeoGig',
                                                     mime='text/xml',
                                                     link_type='html'
                                                     )
                                       )

            def command_url(command):
                return "{repo_url}/{command}.json?{path}".format(repo_url=repo_url,
                                                                 path=path,
                                                                 command=command)

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=command_url('log'),
                                       defaults=dict(extension='json',
                                                     name='GeoGig log',
                                                     mime='application/json',
                                                     link_type='html'
                                                     )
                                       )

            Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                       url=command_url('statistics'),
                                       defaults=dict(extension='json',
                                                     name='GeoGig statistics',
                                                     mime='application/json',
                                                     link_type='html'
                                                     )
                                       )

    elif instance.storeType == 'coverageStore':

        links = wcs_links(ogc_server_settings.public_url + 'wcs?',
                          instance.typename.encode('utf-8'))

    for ext, name, mime, wcs_url in links:
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=wcs_url,
                                   defaults=dict(
                                       extension=ext,
                                       name=name,
                                       mime=mime,
                                       link_type='data',
                                   )
                                   )

    kml_reflector_link_download = ogc_server_settings.public_url + "wms/kml?" + \
        urllib.urlencode({'layers': instance.typename.encode('utf-8'), 'mode': "download"})

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=kml_reflector_link_download,
                               defaults=dict(
                                   extension='kml',
                                   name="KML",
                                   mime='text/xml',
                                   link_type='data',
                               )
                               )

    kml_reflector_link_view = ogc_server_settings.public_url + "wms/kml?" + \
        urllib.urlencode({'layers': instance.typename.encode('utf-8'), 'mode': "refresh"})

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=kml_reflector_link_view,
                               defaults=dict(
                                   extension='kml',
                                   name="View in Google Earth",
                                   mime='text/xml',
                                   link_type='data',
                               )
                               )

    html_link_url = '%s%s' % (
        settings.SITEURL[:-1], instance.get_absolute_url())

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=html_link_url,
                               defaults=dict(
                                   extension='html',
                                   name=instance.typename,
                                   mime='text/html',
                                   link_type='html',
                               )
                               )

    create_gs_thumbnail(instance, overwrite=False)

    legend_url = ogc_server_settings.PUBLIC_LOCATION + \
        'wms?request=GetLegendGraphic&format=image/png&WIDTH=20&HEIGHT=20&LAYER=' + \
        instance.typename + '&legend_options=fontAntiAliasing:true;fontSize:12;forceLabels:on'

    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=legend_url,
                               defaults=dict(
                                   extension='png',
                                   name='Legend',
                                   url=legend_url,
                                   mime='image/png',
                                   link_type='image',
                               )
                               )

    ogc_wms_path = '%s/wms' % instance.workspace
    ogc_wms_url = urljoin(ogc_server_settings.public_url, ogc_wms_path)
    ogc_wms_name = 'OGC WMS: %s Service' % instance.workspace
    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=ogc_wms_url,
                               defaults=dict(
                                   extension='html',
                                   name=ogc_wms_name,
                                   url=ogc_wms_url,
                                   mime='text/html',
                                   link_type='OGC:WMS',
                               )
                               )

    if instance.storeType == "dataStore":
        ogc_wfs_path = '%s/wfs' % instance.workspace
        ogc_wfs_url = urljoin(ogc_server_settings.public_url, ogc_wfs_path)
        ogc_wfs_name = 'OGC WFS: %s Service' % instance.workspace
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=ogc_wfs_url,
                                   defaults=dict(
                                       extension='html',
                                       name=ogc_wfs_name,
                                       url=ogc_wfs_url,
                                       mime='text/html',
                                       link_type='OGC:WFS',
                                   )
                                   )

    if instance.storeType == "coverageStore":
        ogc_wcs_path = '%s/wcs' % instance.workspace
        ogc_wcs_url = urljoin(ogc_server_settings.public_url, ogc_wcs_path)
        ogc_wcs_name = 'OGC WCS: %s Service' % instance.workspace
        Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                   url=ogc_wcs_url,
                                   defaults=dict(
                                       extension='html',
                                       name=ogc_wcs_name,
                                       url=ogc_wcs_url,
                                       mime='text/html',
                                       link_type='OGC:WCS',
                                   )
                                   )

    # remove links that belong to and old address

    for link in instance.link_set.all():
        if not urlparse(
            settings.SITEURL).hostname == urlparse(
            link.url).hostname and not urlparse(
            ogc_server_settings.public_url).hostname == urlparse(
                link.url).hostname:
            link.delete()

    # Define the link after the cleanup, we should use this more rather then remove
    # potential parasites
    tile_url = ('%sgwc/service/gmaps?' % ogc_server_settings.public_url +
                'layers=%s' % instance.typename.encode('utf-8') +
                '&zoom={z}&x={x}&y={y}' +
                '&format=image/png8'
                )

    link, created = Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                                               extension='tiles',
                                               name="Tiles",
                                               mime='image/png',
                                               link_type='image',
                                               )
    if created:
        Link.objects.filter(pk=link.pk).update(url=tile_url)

    # Save layer attributes
    set_attributes_from_geoserver(instance)

    # Save layer styles
    set_styles(instance, gs_catalog)
    # NOTTODO by simod: we should not do this!
    # need to be removed when fixing #2015
    from geonode.catalogue.models import catalogue_post_save
    from geonode.layers.models import Layer
    catalogue_post_save(instance, Layer)
    return instance