Exemplo n.º 1
0
def geoserver_post_save_thumbnail(sender, instance, **kwargs):
    # Creating Layer Thumbnail
    # some thumbnail generators will update thumbnail_url.  If so, don't
    # immediately re-generate the thumbnail here.  use layer#save(update_fields=['thumbnail_url'])
    try:
        instance.refresh_from_db()
        logger.debug(f"... Creating Thumbnail for Layer {instance.title}")
        _recreate_thumbnail = False
        if 'update_fields' in kwargs and kwargs['update_fields'] is not None and \
        'thumbnail_url' in kwargs['update_fields']:
            _recreate_thumbnail = True
        if not instance.thumbnail_url or \
        instance.thumbnail_url == staticfiles.static(settings.MISSING_THUMBNAIL) or \
        is_monochromatic_image(instance.thumbnail_url):
            _recreate_thumbnail = True
        if _recreate_thumbnail:
            geoserver_create_thumbnail.apply_async(((
                instance.id,
                False,
                True,
            )))
        else:
            logger.debug(
                f"... Thumbnail for Layer {instance.title} already exists: {instance.thumbnail_url}"
            )
    except Exception as e:
        logger.exception(e)
Exemplo n.º 2
0
def geoserver_post_save_layers(self, instance_id, *args, **kwargs):
    """
    Runs update layers.
    """
    instance = None
    try:
        instance = Layer.objects.get(id=instance_id)
    except Layer.DoesNotExist:
        logger.debug(f"Layer id {instance_id} does not exist yet!")
        raise

    lock_id = f'{self.request.id}'
    with AcquireLock(lock_id) as lock:
        if lock.acquire() is True:
            # Don't run this signal if is a Layer from a remote service
            if getattr(instance, "remote_service", None) is not None:
                return

            if instance.storeType == "remoteStore":
                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

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

            geonode_upload_sessions = UploadSession.objects.filter(
                resource=instance)
            geonode_upload_sessions.update(processed=False)

            gs_resource = None
            values = None
            _tries = 0
            _max_tries = getattr(ogc_server_settings, "MAX_RETRIES", 2)

            # 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 no 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,
                    charset=instance.charset)

            values, gs_resource = fetch_gs_resource(instance, values, _tries)
            while not gs_resource and _tries < _max_tries:
                values, gs_resource = fetch_gs_resource(
                    instance, values, _tries)
                _tries += 1

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

            if gs_resource:
                logger.debug("Found geoserver resource for this layer: %s" %
                             instance.name)
                gs_resource.metadata_links = metadata_links
                instance.gs_resource = gs_resource

                # Update Attribution link
                if instance.poc:
                    # gsconfig now utilizes an attribution dictionary
                    gs_resource.attribution = {
                        'title': str(instance.poc),
                        'width': None,
                        'height': None,
                        'href': None,
                        'url': None,
                        'type': None
                    }
                    profile = get_user_model().objects.get(
                        username=instance.poc.username)
                    site_url = settings.SITEURL.rstrip(
                        '/') if settings.SITEURL.startswith(
                            'http') else settings.SITEURL
                    gs_resource.attribution_link = site_url + profile.get_absolute_url(
                    )
                """Get information from geoserver.

                The attributes retrieved include:

                * Bounding Box
                * SRID
                * Download links (WMS, WCS or WFS and KML)
                * Styles (SLD)
                """
                try:
                    # This is usually done in Layer.pre_save, however if the hooks
                    # are bypassed by custom create/updates we need to ensure the
                    # bbox is calculated properly.
                    bbox = gs_resource.native_bbox
                    instance.set_bbox_polygon(
                        [bbox[0], bbox[2], bbox[1], bbox[3]],
                        gs_resource.projection)
                except Exception as e:
                    logger.exception(e)

                if instance.srid:
                    instance.srid_url = "http://www.spatialreference.org/ref/" + \
                        instance.srid.replace(':', '/').lower() + "/"
                elif instance.bbox_polygon is not None:
                    # Guessing 'EPSG:4326' by default
                    instance.srid = 'EPSG:4326'
                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])

                try:
                    if settings.RESOURCE_PUBLISHING:
                        if instance.is_published != gs_resource.advertised:
                            gs_resource.advertised = 'true'

                    if not settings.FREETEXT_KEYWORDS_READONLY:
                        # AF: Warning - this won't allow people to have empty keywords on GeoNode
                        if len(instance.keyword_list()
                               ) == 0 and 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 = [
                            kw for kw in 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):
                        gs_catalog.save(gs_resource)
                except Exception 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)

                # store the resource to avoid another geoserver call in the post_save
                to_update = {
                    'title': instance.title or instance.name,
                    'abstract': instance.abstract or "",
                    'alternate': instance.alternate,
                    'bbox_polygon': instance.bbox_polygon,
                    'srid': 'EPSG:4326'
                }

                if is_monochromatic_image(instance.thumbnail_url):
                    to_update['thumbnail_url'] = staticfiles.static(
                        settings.MISSING_THUMBNAIL)

                # Save all the modified information in the instance without triggering signals.
                try:
                    with transaction.atomic():
                        ResourceBase.objects.filter(
                            id=instance.resourcebase_ptr.id).update(
                                **to_update)

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

                        Layer.objects.filter(id=instance.id).update(
                            **to_update)

                        # Refresh from DB
                        instance.refresh_from_db()
                except Exception as e:
                    logger.exception(e)

                # Refreshing CSW records
                logger.debug(
                    f"... Updating the Catalogue entries for Layer {instance.title}"
                )
                try:
                    catalogue_post_save(instance=instance,
                                        sender=instance.__class__)
                except Exception as e:
                    logger.exception(e)

                # Refreshing layer links
                logger.debug(
                    f"... Creating Default Resource Links for Layer {instance.title}"
                )
                try:
                    set_resource_default_links(instance, instance, prune=True)
                except Exception as e:
                    logger.exception(e)

                # Save layer attributes
                logger.debug(
                    f"... Refresh GeoServer attributes list for Layer {instance.title}"
                )
                try:
                    set_attributes_from_geoserver(instance)
                except Exception as e:
                    logger.exception(e)

                # Save layer styles
                logger.debug(
                    f"... Refresh Legend links for Layer {instance.title}")
                try:
                    set_styles(instance, gs_catalog)
                except Exception as e:
                    logger.exception(e)

                # Invalidate GeoWebCache for the updated resource
                try:
                    _stylefilterparams_geowebcache_layer(instance.alternate)
                    _invalidate_geowebcache_layer(instance.alternate)
                except Exception:
                    pass

                # Creating Layer Thumbnail by sending a signal
                from geonode.geoserver.signals import geoserver_post_save_complete
                geoserver_post_save_complete.send(sender=instance.__class__,
                                                  instance=instance)
            try:
                geonode_upload_sessions = UploadSession.objects.filter(
                    resource=instance)
                geonode_upload_sessions.update(processed=True)
            except Exception as e:
                logger.exception(e)

            # Updating HAYSTACK Indexes if needed
            if settings.HAYSTACK_SEARCH:
                call_command('update_index')