Exemple #1
0
def geoserver_post_save_map(instance, sender, created, **kwargs):
    instance.set_missing_info()
    if not created:
        if not instance.thumbnail_url or \
        instance.thumbnail_url == staticfiles.static(settings.MISSING_THUMBNAIL):
            logger.debug("... Creating Thumbnail for Map [%s]" % (instance.title))
            create_gs_thumbnail(instance, overwrite=False, check_bbox=True)
Exemple #2
0
def geoserver_post_save(instance, sender, created, **kwargs):
    from geonode.messaging import producer
    # this is attached to various models, (ResourceBase, Document)
    # so we should select what will be handled here
    if isinstance(instance, Layer):
        instance_dict = model_to_dict(instance)
        payload = json_serializer_producer(instance_dict)
        producer.geoserver_upload_layer(payload)

        if getattr(settings, 'DELAYED_SECURITY_SIGNALS', False):
            instance.set_dirty_state()

        if instance.storeType != 'remoteStore' and created:
            logger.info("... Creating Default Resource Links for Layer [%s]" %
                        (instance.alternate))
            try:
                set_resource_default_links(instance, sender, prune=True)
            except BaseException:
                from django.db import connection
                connection._rollback()
                logger.warn(
                    "Failure Creating Default Resource Links for Layer [%s]" %
                    (instance.alternate))
            logger.info("... Creating Thumbnail for Layer [%s]" %
                        (instance.alternate))
            try:
                create_gs_thumbnail(instance, overwrite=True, check_bbox=True)
            except BaseException:
                logger.warn("Failure Creating Thumbnail for Layer [%s]" %
                            (instance.alternate))
def sync_geonode_layers(ignore_errors,
                        filter,
                        username,
                        removeduplicates,
                        updatepermissions,
                        updatethumbnails,
                        updateattributes,
                        updatebbox):
    layers = Layer.objects.all().order_by('name')
    if filter:
        layers = layers.filter(name__icontains=filter)
    if username:
        layers = layers.filter(owner__username=username)
    layers_count = layers.count()
    count = 0
    layer_errors = []
    for layer in layers:
        try:
            count += 1
            print(f"Syncing layer {count}/{layers_count}: {layer.name}")
            if updatepermissions:
                print("Syncing permissions...")
                # sync permissions in GeoFence
                perm_spec = json.loads(_perms_info_json(layer))
                # re-sync GeoFence security rules
                layer.set_permissions(perm_spec)
            if updateattributes:
                # recalculate the layer statistics
                set_attributes_from_geoserver(layer, overwrite=True)
            if updatethumbnails:
                print("Regenerating thumbnails...")
                create_gs_thumbnail(layer, overwrite=True, check_bbox=False)
            if removeduplicates:
                # remove duplicates
                print("Removing duplicate links...")
                remove_duplicate_links(layer)
            if updatebbox:
                print("Regenerating BBOX...")
                sync_instance_with_geoserver(layer.id, updatemetadata=False, updatebbox=True)
        except (Exception, RuntimeError):
            layer_errors.append(layer.alternate)
            exception_type, error, traceback = sys.exc_info()
            print(exception_type, error, traceback)
            if ignore_errors:
                pass
            else:
                import traceback
                traceback.print_exc()
                print("Stopping process because --ignore-errors was not set and an error was found.")
                return
    print(f"There are {len(layer_errors)} layers which could not be updated because of errors")
    for layer_error in layer_errors:
        print(layer_error)
Exemple #4
0
def geoserver_rest_proxy(request, proxy_path, downstream_path):

    if not request.user.is_authenticated():
        return HttpResponse("You must be logged in to access GeoServer",
                            content_type="text/plain",
                            status=401)

    def strip_prefix(path, prefix):
        assert path.startswith(prefix)
        return path[len(prefix):]

    path = strip_prefix(request.get_full_path(), proxy_path)
    url = str("".join([ogc_server_settings.LOCATION, downstream_path, path]))

    headers = dict()

    affected_layers = None

    if request.method in ("POST", "GET",
                          "PUT") and "CONTENT_TYPE" in request.META:
        headers["Content-Type"] = request.META["CONTENT_TYPE"]
        # if user is not authorized, we must stop him
        # we need to sync django here and check if some object (styles) can
        # be edited by the user
        # we should remove this geonode dependency calling layers.views straight
        # from GXP, bypassing the proxy
        if downstream_path in ('rest/styles',
                               'rest/layers') and len(request.body) > 0:
            if not style_change_check(request, downstream_path):
                return HttpResponse(_(
                    "You don't have permissions to change style for this layer"
                ),
                                    content_type="text/plain",
                                    status=401)
            if downstream_path == 'rest/styles':
                affected_layers = style_update(request, url)

    response = http_request(url,
                            method=request.method,
                            headers=headers,
                            data=request.body or None)

    # update thumbnails
    if affected_layers:
        for layer in affected_layers:
            logger.debug('Updating thumbnail for layer with uuid %s' %
                         layer.uuid)
            create_gs_thumbnail(layer, True)

    return HttpResponse(content=response.content,
                        status=response.status_code,
                        content_type=response.headers.get(
                            "content-type", "text/plain"))
Exemple #5
0
def geoserver_post_save(instance, sender, **kwargs):
    from geonode.messaging import producer
    # this is attached to various models, (ResourceBase, Document)
    # so we should select what will be handled here
    if isinstance(instance, Layer):
        instance_dict = model_to_dict(instance)
        payload = json_serializer_producer(instance_dict)
        producer.geoserver_upload_layer(payload)
        logger.info("... Creating Thumbnail for Layer [%s]" % (instance.alternate))
        try:
            create_gs_thumbnail(instance, overwrite=True, check_bbox=True)
        except BaseException:
            logger.warn("!WARNING! - Failure while Creating Thumbnail for Layer [%s]" % (instance.alternate))
Exemple #6
0
def geoserver_rest_proxy(request, proxy_path, downstream_path):

    if not request.user.is_authenticated():
        return HttpResponse(
            "You must be logged in to access GeoServer",
            content_type="text/plain",
            status=401)

    def strip_prefix(path, prefix):
        assert path.startswith(prefix)
        return path[len(prefix):]

    path = strip_prefix(request.get_full_path(), proxy_path)
    url = str("".join([ogc_server_settings.LOCATION, downstream_path, path]))

    headers = dict()

    affected_layers = None

    if request.method in ("POST", "GET", "PUT") and "CONTENT_TYPE" in request.META:
        headers["Content-Type"] = request.META["CONTENT_TYPE"]
        # if user is not authorized, we must stop him
        # we need to sync django here and check if some object (styles) can
        # be edited by the user
        # we should remove this geonode dependency calling layers.views straight
        # from GXP, bypassing the proxy
        if downstream_path in ('rest/styles', 'rest/layers') and len(request.body) > 0:
            if not style_change_check(request, downstream_path):
                return HttpResponse(
                    _("You don't have permissions to change style for this layer"),
                    content_type="text/plain",
                    status=401)
            if downstream_path == 'rest/styles':
                affected_layers = style_update(request, url)

    response = http_request(url,
                            method=request.method,
                            headers=headers,
                            data=request.body or None)

    # update thumbnails
    if affected_layers:
        for layer in affected_layers:
            logger.debug(
                'Updating thumbnail for layer with uuid %s' % layer.uuid)
            create_gs_thumbnail(layer, True)

    return HttpResponse(
        content=response.content,
        status=response.status_code,
        content_type=response.headers.get("content-type", "text/plain"))
Exemple #7
0
def synch_guardian():
    from geonode.base.models import ResourceBase
    dirty_resources = ResourceBase.objects.filter(dirty_state=True)
    if dirty_resources and dirty_resources.count() > 0:
        _log(" --------------------------- synching with guardian!")
        for r in dirty_resources:
            if r.polymorphic_ctype.name == 'layer':
                layer = None
                try:
                    purge_geofence_layer_rules(r)
                    layer = Layer.objects.get(id=r.id)
                    perm_spec = layer.get_all_level_info()
                    _log(" %s --------------------------- %s " %
                         (layer, perm_spec))

                    # All the other users
                    if 'users' in perm_spec:
                        for user, perms in perm_spec['users'].items():
                            user = get_user_model().objects.get(username=user)
                            # Set the GeoFence User Rules
                            geofence_user = str(user)
                            if "AnonymousUser" in geofence_user:
                                geofence_user = None
                            sync_geofence_with_guardian(layer,
                                                        perms,
                                                        user=geofence_user)

                    # All the other groups
                    if 'groups' in perm_spec:
                        for group, perms in perm_spec['groups'].items():
                            group = Group.objects.get(name=group)
                            # Set the GeoFence Group Rules
                            sync_geofence_with_guardian(layer,
                                                        perms,
                                                        group=group)

                    try:
                        create_gs_thumbnail(layer,
                                            overwrite=True,
                                            check_bbox=True)
                    except BaseException:
                        logger.warn(
                            "!WARNING! - Failure while Creating Thumbnail for Layer [%s]"
                            % (layer.alternate))

                    r.clear_dirty_state()
                except BaseException:
                    logger.warn(
                        "!WARNING! - Failure Synching-up Security Rules for Resource [%s]"
                        % (r))
Exemple #8
0
def geoserver_post_save(instance, sender, created, **kwargs):
    from geonode.messaging import producer
    # this is attached to various models, (ResourceBase, Document)
    # so we should select what will be handled here
    if isinstance(instance, Layer):
        instance_dict = model_to_dict(instance)
        payload = json_serializer_producer(instance_dict)
        producer.geoserver_upload_layer(payload)

        if getattr(settings, 'DELAYED_SECURITY_SIGNALS', False):
            instance.set_dirty_state()

        if instance.storeType != 'remoteStore' and created:
            logger.info("... Creating Default Resource Linkks for Layer [%s]" % (instance.alternate))
            set_resource_default_links(instance, sender, prune=True)
            logger.info("... Creating Thumbnail for Layer [%s]" % (instance.alternate))
            try:
                create_gs_thumbnail(instance, overwrite=True, check_bbox=True)
            except BaseException:
                logger.warn("!WARNING! - Failure while Creating Thumbnail for Layer [%s]" % (instance.alternate))
def sync_geonode_maps(ignore_errors, filter, username, removeduplicates,
                      updatethumbnails):
    maps = Map.objects.all().order_by('title')
    if filter:
        maps = maps.filter(title__icontains=filter)
    if username:
        maps = maps.filter(owner__username=username)
    maps_count = maps.count()
    count = 0
    map_errors = []
    for map in maps:
        try:
            count += 1
            print(f"Syncing map {count}/{maps_count}: {map.title}")
            if updatethumbnails:
                print("Regenerating thumbnails...")
                create_gs_thumbnail(map, overwrite=True, check_bbox=False)
            if removeduplicates:
                # remove duplicates
                print("Removing duplicate links...")
                remove_duplicate_links(map)
        except Exception:
            map_errors.append(map.title)
            exception_type, error, traceback = sys.exc_info()
            print(exception_type, error, traceback)
            if ignore_errors:
                pass
            else:
                import traceback
                traceback.print_exc()
                print(
                    "Stopping process because --ignore-errors was not set and an error was found."
                )
                return
    print(
        f"There are {len(map_errors)} maps which could not be updated because of errors"
    )
    for map_error in map_errors:
        print(map_error)
Exemple #10
0
    def test_ogc_server_defaults(self):
        """
        Tests that OGC_SERVER_SETTINGS are built if they do not exist in the settings.
        """

        OGC_SERVER = {'default': dict()}

        defaults = self.OGC_DEFAULT_SETTINGS.get('default')
        ogc_settings = OGC_Servers_Handler(OGC_SERVER)['default']
        self.assertEqual(ogc_settings.server, defaults)
        self.assertEqual(ogc_settings.rest, defaults['LOCATION'] + 'rest')
        self.assertEqual(ogc_settings.ows, defaults['LOCATION'] + 'ows')

        # Make sure we get None vs a KeyError when the key does not exist
        self.assertIsNone(ogc_settings.SFDSDFDSF)

        # Testing OWS endpoints
        from django.urls import reverse
        from ..ows import _wcs_get_capabilities, _wfs_get_capabilities, _wms_get_capabilities
        wcs = _wcs_get_capabilities()
        logger.debug(wcs)
        self.assertIsNotNone(wcs)

        try:
            wcs_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except BaseException:
            wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')

        self.assertTrue(wcs.startswith(wcs_url))
        self.assertIn("service=WCS", wcs)
        self.assertIn("request=GetCapabilities", wcs)
        self.assertIn("version=2.0.1", wcs)

        wfs = _wfs_get_capabilities()
        logger.debug(wfs)
        self.assertIsNotNone(wfs)

        try:
            wfs_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except BaseException:
            wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertTrue(wfs.startswith(wfs_url))
        self.assertIn("service=WFS", wfs)
        self.assertIn("request=GetCapabilities", wfs)
        self.assertIn("version=1.1.0", wfs)

        wms = _wms_get_capabilities()
        logger.debug(wms)
        self.assertIsNotNone(wms)

        try:
            wms_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except BaseException:
            wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertTrue(wms.startswith(wms_url))
        self.assertIn("service=WMS", wms)
        self.assertIn("request=GetCapabilities", wms)
        self.assertIn("version=1.3.0", wms)

        # Test OWS Download Links
        from geonode.geoserver.ows import wcs_links, wfs_links, wms_links
        instance = Layer.objects.all()[0]
        bbox = instance.bbox
        srid = instance.srid
        height = 512
        width = 512

        # Default Style (expect exception since we are offline)
        style = None
        with self.assertRaises(GeoNodeException):
            style = get_sld_for(gs_catalog, instance)
        self.assertIsNone(style)
        style = gs_catalog.get_style("line")
        self.assertIsNotNone(style)
        instance.default_style, _ = Style.objects.get_or_create(
            name=style.name,
            defaults=dict(
                sld_title=style.sld_title,
                sld_body=style.sld_body
            )
        )
        self.assertIsNotNone(instance.default_style)
        self.assertIsNotNone(instance.default_style.name)

        # WMS Links
        wms_links = wms_links(ogc_settings.public_url + 'wms?',
                              instance.alternate,
                              bbox,
                              srid,
                              height,
                              width)
        self.assertIsNotNone(wms_links)
        self.assertEquals(len(wms_links), 3)
        wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wms')
        identifier = urlencode({'layers': instance.alternate})
        for _link in wms_links:
            logger.debug('%s --> %s' % (wms_url, _link[3]))
            self.assertTrue(wms_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # WFS Links
        wfs_links = wfs_links(ogc_settings.public_url + 'wfs?',
                              instance.alternate,
                              bbox,
                              srid)
        self.assertIsNotNone(wfs_links)
        self.assertEquals(len(wfs_links), 6)
        wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wfs')
        identifier = urlencode({'typename': instance.alternate})
        for _link in wfs_links:
            logger.debug('%s --> %s' % (wfs_url, _link[3]))
            self.assertTrue(wfs_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # WCS Links
        wcs_links = wcs_links(ogc_settings.public_url + 'wcs?',
                              instance.alternate,
                              bbox,
                              srid)
        self.assertIsNotNone(wcs_links)
        self.assertEquals(len(wcs_links), 2)
        wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wcs')
        identifier = urlencode({'coverageid': instance.alternate})
        for _link in wcs_links:
            logger.debug('%s --> %s' % (wcs_url, _link[3]))
            self.assertTrue(wcs_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # Thumbnails Generation Default
        create_gs_thumbnail(instance, overwrite=True)
        self.assertIsNotNone(instance.get_thumbnail_url())

        # Thumbnails Generation Through "remote url"
        create_gs_thumbnail_geonode(instance, overwrite=True, check_bbox=True)

        # Thumbnails Generation Through "image"
        request_body = {
            'width': width,
            'height': height,
            'layers': instance.alternate
        }
        if hasattr(instance, 'default_style'):
            if instance.default_style:
                request_body['styles'] = instance.default_style.name
        self.assertIsNotNone(request_body['styles'])

        try:
            image = _prepare_thumbnail_body_from_opts(request_body)
        except BaseException as e:
            logger.exception(e)
            image = None
        # We are offline here, the layer does not exists in GeoServer
        # - we expect the image is None
        self.assertIsNone(image)
Exemple #11
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)

    # 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 = Profile.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()
        # 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 layer named %s in GeoServer, '
                       'try to use: "%s"' % (gs_resource, str(e)))
                e.args = (msg,)
                logger.exception(e)

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

    # Save layer attributes
    set_attributes_from_geoserver(instance)

    # Save layer styles
    set_styles(instance, gs_catalog)

    # set SLD
    sld = instance.default_style.sld_body if instance.default_style else None
    if sld:
        set_layer_style(instance, instance.alternate, sld)

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

    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_resource.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

    try:
        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]
    except BaseException:
        pass

    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:
        try:
            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)
        except BaseException:
            pass

    if any(instance.keyword_list()):
        keywords = instance.keyword_list()
        gs_resource.keywords = [kw.decode("utf-8", "replace") 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):
            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

    try:
        bbox = gs_resource.native_bbox
    except BaseException:
        bbox = instance.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)

    # Parse Layer BBOX and SRID
    srid = instance.srid if instance.srid else getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:4326')
    if srid and instance.bbox_x0:
        bbox = ','.join(str(x) for x in [instance.bbox_x0, instance.bbox_y0,
                                         instance.bbox_x1, instance.bbox_y1])

    # Create Raw Data download link
    try:
        path = gs_resource.dom.findall('nativeName')
    except BaseException:
        path = instance.alternate
    download_url = urljoin(settings.SITEURL,
                           reverse('download', args=[instance.id]))
    Link.objects.get_or_create(resource=instance.resourcebase_ptr,
                               url=download_url,
                               defaults=dict(extension='zip',
                                             name='Original Dataset',
                                             mime='application/octet-stream',
                                             link_type='original',
                                             )
                               )

    # Set download links for WMS, WCS or WFS and KML
    links = wms_links(ogc_server_settings.public_url + 'wms?',
                      instance.alternate.encode('utf-8'),
                      bbox,
                      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'),
                          bbox=None,  # bbox filter should be set at runtime otherwise conflicting with CQL
                          srid=srid)
        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)

            try:
                path = gs_resource.dom.findall('nativeName')
            except BaseException:
                path = instance.alternate

            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'),
                          bbox,
                          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',
                               )
                               )

    site_url = settings.SITEURL.rstrip('/') if settings.SITEURL.startswith('http') else settings.SITEURL
    html_link_url = '%s%s' % (
        site_url, 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 '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)

    try:
        Link.objects.filter(resource=instance.resourcebase_ptr, name='Legend').delete()
    except BaseException:
        pass

    for style in instance.styles.all():
        legend_url = ogc_server_settings.PUBLIC_LOCATION + \
            'wms?request=GetLegendGraphic&format=image/png&WIDTH=20&HEIGHT=20&LAYER=' + \
            instance.alternate + '&STYLE=' + style.name + \
            '&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_path = 'ows'
    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_path = 'wfs'
        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_path = 'wcs'
        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)

    # NOTTODO by simod: we should not do this!
    # need to be removed when fixing #2015
    catalogue_post_save(instance, Layer)

    # Updating HAYSTACK Indexes if needed
    if settings.HAYSTACK_SEARCH:
        from django.core.management import call_command
        call_command('update_index')
Exemple #12
0
def geoserver_post_save_map(instance, sender, **kwargs):
    instance.set_missing_info()
    logger.info("... Creating Thumbnail for Map [%s]" % (instance.title))
    create_gs_thumbnail(instance, overwrite=False, check_bbox=True)
Exemple #13
0
def geoserver_post_save_map(instance, sender, created, **kwargs):
    instance.set_missing_info()
    if not created:
        logger.debug("... Creating Thumbnail for Map [%s]" % (instance.title))
        create_gs_thumbnail(instance, overwrite=False, check_bbox=True)
Exemple #14
0
def geoserver_post_save_map(instance, sender, **kwargs):
    instance.set_missing_info()
    create_gs_thumbnail(instance, overwrite=False)
Exemple #15
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
Exemple #16
0
def geoserver_post_save(instance, sender, **kwargs):
    """Save keywords to GeoServer

       The way keywords are implemented requires the layer
       to be saved to the database before accessing them.
    """
    # 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

    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

    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
    else:
        gs_resource = instance.gs_resource

    if gs_resource is None:
        return

    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=True)

    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)
Exemple #17
0
                               url=html_link_url,
                               defaults=dict(
                                   extension='html',
                                   name=instance.alternate,
                                   mime='text/html',
                                   link_type='html',
                               )
                               )

<<<<<<< HEAD
<<<<<<< HEAD
    logger.info("Creating Thumbnail for Layer [%s]" % (instance.typename))
=======
    logger.info("Creating Thumbnail for Layer [%s]" % (instance.alternate))
>>>>>>> e7605f5980062789a1dfe0321b74882a9af32ed6
    create_gs_thumbnail(instance, overwrite=False)
=======
    params = {
        'layers': instance.typename.encode('utf-8'),
        'format': 'image/png8',
        'width': 200,
        'height': 150,
        'TIME': '-99999999999-01-01T00:00:00.0Z/99999999999-01-01T00:00:00.0Z'
    }

    # Avoid using urllib.urlencode here because it breaks the url.
    # commas and slashes in values get encoded and then cause trouble
    # with the WMS parser.
    p = "&".join("%s=%s" % item for item in params.items())

    thumbnail_remote_url = ogc_server_settings.PUBLIC_LOCATION + \
Exemple #18
0
def geoserver_post_save(instance, sender, **kwargs):
    """Save keywords to GeoServer

       The way keywords are implemented requires the layer
       to be saved to the database before accessing them.
    """
    # 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

    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

    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
    else:
        gs_resource = instance.gs_resource

    if gs_resource is None:
        return

    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=True)

    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)
Exemple #19
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)

    # 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 = Profile.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()
        # 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 layer named %s in GeoServer, '
                       'try to use: "%s"' % (gs_resource, str(e)))
                e.args = (msg,)
                logger.exception(e)

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

    # Save layer attributes
    set_attributes_from_geoserver(instance)

    # Save layer styles
    set_styles(instance, gs_catalog)

    # set SLD
    sld = instance.default_style.sld_body if instance.default_style else None
    if sld:
        set_layer_style(instance, instance.alternate, sld)

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

    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_resource.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

    try:
        logger.debug(" -------------------------------------------------- ")
        bbox = gs_resource.native_bbox
        logger.debug(bbox)
        logger.debug(" -------------------------------------------------- ")
        # 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]
    except BaseException:
        pass

    if instance.srid:
        instance.srid_url = "http://www.spatialreference.org/ref/" + \
            instance.srid.replace(':', '/').lower() + "/"
    elif instance.bbox_x0 and instance.bbox_x1 and instance.bbox_y0 and instance.bbox_y1:
        # 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])

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

    if not settings.FREETEXT_KEYWORDS_READONLY:
        try:
            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)
        except BaseException:
            pass

    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):
            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

    # Refresh and create the instance default links
    layer = Layer.objects.get(id=instance.id)
    set_resource_default_links(instance, layer, prune=True)

    # 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 '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)

    # NOTTODO by simod: we should not do this!
    # need to be removed when fixing #2015
    catalogue_post_save(instance, Layer)

    # Updating HAYSTACK Indexes if needed
    if settings.HAYSTACK_SEARCH:
        from django.core.management import call_command
        call_command('update_index')
Exemple #20
0
    def test_save_and_delete_signals(self):
        """Test that GeoServer Signals methods work as espected"""

        layers = Layer.objects.all()[:2].values_list('id', flat=True)
        test_perm_layer = Layer.objects.get(id=layers[0])

        self.client.login(username='******', password='******')

        if check_ogc_backend(geoserver.BACKEND_PACKAGE):
            from geonode.geoserver.signals import (geoserver_pre_delete,
                                                   geoserver_post_save,
                                                   geoserver_post_save_local)
            # Handle Layer Save and Upload Signals
            geoserver_post_save(test_perm_layer, sender=Layer)
            geoserver_post_save_local(test_perm_layer)

            # Check instance bbox and links
            self.assertIsNotNone(test_perm_layer.bbox)
            self.assertIsNotNone(test_perm_layer.srid)
            self.assertIsNotNone(test_perm_layer.link_set)
            self.assertEquals(len(test_perm_layer.link_set.all()), 7)

            # Layer Manipulation
            from geonode.geoserver.upload import geoserver_upload
            from geonode.geoserver.signals import gs_catalog
            from geonode.geoserver.helpers import (
                check_geoserver_is_up, get_sld_for, fixup_style,
                set_layer_style, get_store, set_attributes_from_geoserver,
                set_styles, create_gs_thumbnail, cleanup)
            check_geoserver_is_up()

            admin_user = get_user_model().objects.get(username="******")
            saved_layer = geoserver_upload(
                test_perm_layer,
                os.path.join(gisdata.VECTOR_DATA,
                             "san_andres_y_providencia_poi.shp"),
                admin_user,
                test_perm_layer.name,
                overwrite=True)

            self.assertIsNotNone(saved_layer)
            _log(saved_layer)
            workspace, name = test_perm_layer.alternate.split(':')
            self.assertIsNotNone(workspace)
            self.assertIsNotNone(name)
            ws = gs_catalog.get_workspace(workspace)
            self.assertIsNotNone(ws)
            store = get_store(gs_catalog, name, workspace=ws)
            _log("1. ------------ %s " % store)
            self.assertIsNotNone(store)

            # Save layer attributes
            set_attributes_from_geoserver(test_perm_layer)

            # Save layer styles
            set_styles(test_perm_layer, gs_catalog)

            # set SLD
            sld = test_perm_layer.default_style.sld_body if test_perm_layer.default_style else None
            if sld:
                _log("2. ------------ %s " % sld)
                set_layer_style(test_perm_layer, test_perm_layer.alternate,
                                sld)

            fixup_style(gs_catalog, test_perm_layer.alternate, None)
            self.assertIsNone(get_sld_for(gs_catalog, test_perm_layer))
            _log("3. ------------ %s " %
                 get_sld_for(gs_catalog, test_perm_layer))

            create_gs_thumbnail(test_perm_layer, overwrite=True)
            self.assertIsNotNone(test_perm_layer.get_thumbnail_url())
            self.assertTrue(test_perm_layer.has_thumbnail())

            # Handle Layer Delete Signals
            geoserver_pre_delete(test_perm_layer, sender=Layer)

            # Check instance has been removed from GeoServer also
            from geonode.geoserver.views import get_layer_capabilities
            self.assertIsNone(get_layer_capabilities(test_perm_layer))

            # Cleaning Up
            test_perm_layer.delete()
            cleanup(test_perm_layer.name, test_perm_layer.uuid)
Exemple #21
0
def geoserver_post_save_map(instance, sender, **kwargs):
    instance.set_missing_info()
    create_gs_thumbnail(instance, overwrite=False)
Exemple #22
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)
Exemple #23
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
Exemple #24
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
    """
    instance.refresh_from_db()

    # 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
    _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 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)

    def fetch_gs_resource(values, tries):
        try:
            gs_resource = gs_catalog.get_resource(
                name=instance.name,
                store=instance.store,
                workspace=instance.workspace)
        except Exception:
            try:
                gs_resource = gs_catalog.get_resource(
                    name=instance.alternate,
                    store=instance.store,
                    workspace=instance.workspace)
            except Exception:
                try:
                    gs_resource = gs_catalog.get_resource(
                        name=instance.alternate or instance.typename)
                except Exception:
                    gs_resource = None

        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)
            if tries >= _max_tries:
                # raise GeoNodeException(msg)
                return (values, None)
            gs_resource = None
            sleep(3.00)

        return (values, gs_resource)

    while not gs_resource and _tries < _max_tries:
        values, gs_resource = fetch_gs_resource(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
        # 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)

        # 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()
            # 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 layer named %s in GeoServer, '
                           'try to use: "%s"' % (gs_resource, str(e)))
                    e.args = (msg,)
                    logger.exception(e)
    else:
        msg = "There isn't a geoserver resource for this layer: %s" % instance.name
        logger.warn(msg)

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

    # Save layer attributes
    set_attributes_from_geoserver(instance)

    # Save layer styles
    set_styles(instance, gs_catalog)

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

    if instance.storeType == "remoteStore":
        return

    if gs_resource:
        """Get information from geoserver.

           The attributes retrieved include:

           * Bounding Box
           * SRID
           * Download links (WMS, WCS or WFS and KML)
           * Styles (SLD)
        """
        try:
            instance.abstract = gs_resource.abstract or ''
        except Exception as e:
            logger.exception(e)
            instance.abstract = ''
        instance.workspace = gs_resource.store.workspace.name
        instance.store = gs_resource.store.name

        try:
            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]
        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_x0 and instance.bbox_x1 and instance.bbox_y0 and instance.bbox_y1:
        # Guessing 'EPSG:4326' by default
        instance.srid = 'EPSG:4326'
    else:
        raise GeoNodeException("Invalid Projection. Layer is missing CRS!")

    # Iterate over values from geoserver.
    if gs_resource:
        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 gs_resource:
        try:
            if settings.RESOURCE_PUBLISHING:
                if instance.is_published != gs_resource.advertised:
                    if getattr(ogc_server_settings, "BACKEND_WRITE_ENABLED", True):
                        gs_resource.advertised = 'true'
                        gs_catalog.save(gs_resource)

            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)

    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()

    # Updating the Catalogue
    catalogue_post_save(instance=instance, sender=instance.__class__)

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

    # 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 gs_resource:
        logger.debug("... Creating Default Resource Links for Layer [%s]" % (instance.alternate))
        set_resource_default_links(instance, instance, prune=True)

        if 'update_fields' in kwargs and kwargs['update_fields'] is not None and \
                'thumbnail_url' in kwargs['update_fields']:
            logger.debug("... Creating Thumbnail for Layer [%s]" % (instance.alternate))
            create_gs_thumbnail(instance, overwrite=True)

    # Updating HAYSTACK Indexes if needed
    if settings.HAYSTACK_SEARCH:
        from django.core.management import call_command
        call_command('update_index')
Exemple #25
0
    def test_save_and_delete_signals(self):
        """Test that GeoServer Signals methods work as espected"""

        layers = Layer.objects.all()[:2].values_list('id', flat=True)
        test_perm_layer = Layer.objects.get(id=layers[0])

        self.client.login(username='******', password='******')

        if check_ogc_backend(geoserver.BACKEND_PACKAGE):
            from geonode.geoserver.signals import (geoserver_pre_delete,
                                                   geoserver_post_save,
                                                   geoserver_post_save_local)
            # Handle Layer Save and Upload Signals
            geoserver_post_save(test_perm_layer, sender=Layer)
            geoserver_post_save_local(test_perm_layer)

            # Check instance bbox and links
            self.assertIsNotNone(test_perm_layer.bbox)
            self.assertIsNotNone(test_perm_layer.srid)
            self.assertIsNotNone(test_perm_layer.link_set)
            self.assertEquals(len(test_perm_layer.link_set.all()), 9)

            # Layer Manipulation
            from geonode.geoserver.upload import geoserver_upload
            from geonode.geoserver.signals import gs_catalog
            from geonode.geoserver.helpers import (check_geoserver_is_up,
                                                   get_sld_for,
                                                   fixup_style,
                                                   set_layer_style,
                                                   get_store,
                                                   set_attributes_from_geoserver,
                                                   set_styles,
                                                   create_gs_thumbnail,
                                                   cleanup)
            check_geoserver_is_up()

            admin_user = get_user_model().objects.get(username="******")
            saved_layer = geoserver_upload(
                test_perm_layer,
                os.path.join(
                    gisdata.VECTOR_DATA,
                    "san_andres_y_providencia_poi.shp"),
                admin_user,
                test_perm_layer.name,
                overwrite=True
            )

            self.assertIsNotNone(saved_layer)
            _log(saved_layer)
            workspace, name = test_perm_layer.alternate.split(':')
            self.assertIsNotNone(workspace)
            self.assertIsNotNone(name)
            ws = gs_catalog.get_workspace(workspace)
            self.assertIsNotNone(ws)
            store = get_store(gs_catalog, name, workspace=ws)
            _log("1. ------------ %s " % store)
            self.assertIsNotNone(store)

            # Save layer attributes
            set_attributes_from_geoserver(test_perm_layer)

            # Save layer styles
            set_styles(test_perm_layer, gs_catalog)

            # set SLD
            sld = test_perm_layer.default_style.sld_body if test_perm_layer.default_style else None
            if sld:
                _log("2. ------------ %s " % sld)
                set_layer_style(test_perm_layer, test_perm_layer.alternate, sld)

            fixup_style(gs_catalog, test_perm_layer.alternate, None)
            self.assertIsNone(get_sld_for(gs_catalog, test_perm_layer))
            _log("3. ------------ %s " % get_sld_for(gs_catalog, test_perm_layer))

            create_gs_thumbnail(test_perm_layer, overwrite=True)
            self.assertIsNotNone(test_perm_layer.get_thumbnail_url())
            self.assertTrue(test_perm_layer.has_thumbnail())

            # Handle Layer Delete Signals
            geoserver_pre_delete(test_perm_layer, sender=Layer)

            # Check instance has been removed from GeoServer also
            from geonode.geoserver.views import get_layer_capabilities
            self.assertIsNone(get_layer_capabilities(test_perm_layer))

            # Cleaning Up
            test_perm_layer.delete()
            cleanup(test_perm_layer.name, test_perm_layer.uuid)