def test_set_attributes(self): """Test attributes syncronization """ # upload a shapefile shp_file = os.path.join( gisdata.VECTOR_DATA, 'san_andres_y_providencia_poi.shp') layer = file_upload(shp_file) # set attributes for resource for attribute in layer.attribute_set.all(): attribute.attribute_label = '%s_label' % attribute.attribute attribute.description = '%s_description' % attribute.attribute attribute.save() # sync the attributes with GeoServer set_attributes(layer) # tests if everything is synced properly for attribute in layer.attribute_set.all(): self.assertEquals( attribute.attribute_label, '%s_label' % attribute.attribute ) self.assertEquals( attribute.description, '%s_description' % attribute.attribute )
def handle(self, *args, **options): ignore_errors = options.get('ignore_errors') filter = options.get('filter') if not options.get('username'): username = None else: username = options.get('username') all_layers = Layer.objects.all().order_by('name') if filter: all_layers = all_layers.filter(name__icontains=filter) if username: all_layers = all_layers.filter(owner__username=username) for index, layer in enumerate(all_layers): print "[%s / %s] Updating Layer [%s] ..." % ((index + 1), len(all_layers), layer.name) try: # recalculate the layer statistics set_attributes(layer, overwrite=True) # refresh metadata links set_resource_default_links(layer, layer, prune=True) # refresh catalogue metadata records catalogue_post_save(instance=layer, sender=layer.__class__) except BaseException as e: # import traceback # traceback.print_exc() if ignore_errors: print "[ERROR] Layer [%s] couldn't be updated" % (layer.name) else: raise e
def handle(self, *args, **options): ignore_errors = options.get('ignore_errors') remove_duplicates = options.get('remove_duplicates') filter = options.get('filter') if not options.get('username'): username = None else: username = options.get('username') all_layers = Layer.objects.all().order_by('name') if filter: all_layers = all_layers.filter(name__icontains=filter) if username: all_layers = all_layers.filter(owner__username=username) for index, layer in enumerate(all_layers): print "[%s / %s] Updating Layer [%s] ..." % ( (index + 1), len(all_layers), layer.name) try: # recalculate the layer statistics set_attributes(layer, overwrite=True) # refresh metadata links set_resource_default_links(layer, layer, prune=False) # refresh catalogue metadata records catalogue_post_save(instance=layer, sender=layer.__class__) if remove_duplicates: # remove duplicates for _n in _names: _links = Link.objects.filter(resource__id=layer.id, name=_n) while _links.count() > 1: _links.last().delete() print '.', # fixup Legend links legend_url_template = ogc_server_settings.PUBLIC_LOCATION + \ 'ows?service=WMS&request=GetLegendGraphic&format=image/png&WIDTH=20&HEIGHT=20&LAYER=' + \ '{alternate}&STYLE={style_name}' + \ '&legend_options=fontAntiAliasing:true;fontSize:12;forceLabels:on' if layer.default_style and not layer.get_legend_url( style_name=layer.default_style.name): Link.objects.update_or_create( resource=layer.resourcebase_ptr, name='Legend', extension='png', url=legend_url_template.format( alternate=layer.alternate, style_name=layer.default_style.name), mime='image/png', link_type='image') except BaseException as e: import traceback traceback.print_exc() if ignore_errors: print "[ERROR] Layer [%s] couldn't be updated" % ( layer.name) else: raise e
def handle(self, *args, **options): ignore_errors = options.get('ignore_errors') filter = options.get('filter') if not options.get('username'): username = None else: username = options.get('username') all_layers = Layer.objects.all().order_by('name') if filter: all_layers = all_layers.filter(name__icontains=filter) if username: all_layers = all_layers.filter(owner__username=username) for index, layer in enumerate(all_layers): print "[%s / %s] Updating Layer [%s] ..." % ( (index + 1), len(all_layers), layer.name) try: # recalculate the layer statistics set_attributes(layer, overwrite=True) # refresh metadata links set_resource_default_links(layer, layer, prune=False) # refresh catalogue metadata records catalogue_post_save(instance=layer, sender=layer.__class__) except BaseException as e: # import traceback # traceback.print_exc() if ignore_errors: print "[ERROR] Layer [%s] couldn't be updated" % ( layer.name) else: raise e
def handle(self, *args, **options): ignore_errors = options.get('ignore_errors') remove_duplicates = options.get('remove_duplicates') prune = options.get('prune') set_uuid = ast.literal_eval(options.get('set_uuid', 'False')) set_attrib = ast.literal_eval(options.get('set_attrib', 'True')) set_links = ast.literal_eval(options.get('set_links', 'True')) delete_orphaned_thumbnails = options.get('delete_orphaned_thumbnails') filter = options.get('filter') if not options.get('username'): username = None else: username = options.get('username') all_layers = Layer.objects.all().order_by('name') if filter: all_layers = all_layers.filter(name__icontains=filter) if username: all_layers = all_layers.filter(owner__username=username) for index, layer in enumerate(all_layers): print(f"[{(index + 1)} / {len(all_layers)}] Updating Layer [{layer.name}] ...") try: # recalculate the layer statistics if set_attrib: set_attributes(layer, overwrite=True) if set_uuid and hasattr(settings, 'LAYER_UUID_HANDLER') and settings.LAYER_UUID_HANDLER != '': from geonode.layers.utils import get_uuid_handler uuid = get_uuid_handler()(layer).create_uuid() la = Layer.objects.filter(resourcebase_ptr=layer.resourcebase_ptr) la.update(uuid=uuid) layer.refresh_from_db() # refresh metadata links if set_links: set_resource_default_links(layer, layer, prune=prune) # refresh catalogue metadata records catalogue_post_save(instance=layer, sender=layer.__class__) # remove duplicates if remove_duplicates: remove_duplicate_links(layer) except Exception as e: import traceback traceback.print_exc() if ignore_errors: logger.error(f"[ERROR] Layer [{layer.name}] couldn't be updated") else: raise e # delete orphaned thumbs if delete_orphaned_thumbnails: delete_orphaned_thumbs()
def handle(self, *args, **options): ignore_errors = options.get('ignore_errors') remove_duplicates = options.get('remove_duplicates') prune = options.get('prune') delete_orphaned_thumbnails = options.get('delete_orphaned_thumbnails') filter = options.get('filter') if not options.get('username'): username = None else: username = options.get('username') all_layers = Layer.objects.all().order_by('name') if filter: all_layers = all_layers.filter(name__icontains=filter) if username: all_layers = all_layers.filter(owner__username=username) for index, layer in enumerate(all_layers): print( f"[{(index + 1)} / {len(all_layers)}] Updating Layer [{layer.name}] ..." ) try: # recalculate the layer statistics set_attributes(layer, overwrite=True) # refresh metadata links set_resource_default_links(layer, layer, prune=prune) # refresh catalogue metadata records catalogue_post_save(instance=layer, sender=layer.__class__) # remove duplicates if remove_duplicates: remove_duplicate_links(layer) except Exception as e: import traceback traceback.print_exc() if ignore_errors: logger.error( f"[ERROR] Layer [{layer.name}] couldn't be updated") else: raise e # delete orphaned thumbs if delete_orphaned_thumbnails: delete_orphaned_thumbs()
def test_set_attributes_creates_attributes(self): """ Test utility function set_attributes() which creates Attribute instances attached to a Layer instance. """ # Creating a layer requires being logged in self.client.login(username='******', password='******') # Disconnect the geoserver-specific post_save signal attached to Layer creation. # The geoserver signal handler assumes things about the store where the Layer is placed. # this is a workaround. disconnected_post_save = signals.post_save.disconnect(geoserver_post_save, sender=Layer) # Create dummy layer to attach attributes to _l = Layer.objects.create( name='dummy_layer', bbox_x0=-180, bbox_x1=180, bbox_y0=-90, bbox_y1=90, srid='EPSG:4326') # Reconnect the signal if it was disconnected if disconnected_post_save: signals.post_save.connect(geoserver_post_save, sender=Layer) attribute_map = [ ['id', 'Integer'], ['date', 'IntegerList'], ['enddate', 'Real'], ['date_as_date', 'xsd:dateTime'], ] # attribute_map gets modified as a side-effect of the call to set_attributes() expected_results = copy.deepcopy(attribute_map) # set attributes for resource set_attributes(_l, attribute_map) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEqual(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results)
def test_set_attributes_creates_attributes(self): """ Test utility function set_attributes() which creates Attribute instances attached to a Layer instance. """ # Creating a layer requires being logged in self.client.login(username='******', password='******') # Disconnect the geoserver-specific post_save signal attached to Layer creation. # The geoserver signal handler assumes things about the store where the Layer is placed. # this is a workaround. disconnected_post_save = signals.post_save.disconnect(geoserver_post_save, sender=Layer) # Create dummy layer to attach attributes to _l = Layer.objects.create( name='dummy_layer', bbox_x0=-180, bbox_x1=180, bbox_y0=-90, bbox_y1=90, srid='EPSG:4326') # Reconnect the signal if it was disconnected if disconnected_post_save: signals.post_save.connect(geoserver_post_save, sender=Layer) attribute_map = [ ['id', 'Integer'], ['date', 'IntegerList'], ['enddate', 'Real'], ['date_as_date', 'xsd:dateTime'], ] # attribute_map gets modified as a side-effect of the call to set_attributes() expected_results = copy.deepcopy(attribute_map) # set attributes for resource set_attributes(_l, attribute_map) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEquals(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results)
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. """ if instance.storeType == "remoteStore": #Save layer attributes set_attributes(instance) return url = ogc_server_settings.internal_rest 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 if gs_resource is None: return 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', )) elif instance.storeType == 'coverageStore': #FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = instance.get_all_level_info() instance.set_permissions( {'users': { 'AnonymousUser': ['view_resourcebase'] }}) try: #Potentially 3 dimensions can be returned by the grid if there is a z #axis. Since we only want width/height, slice to the second dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] except GeoNodeException, e: msg = _('Could not create a download link for layer.') logger.warn(msg, e) else: links = wcs_links(ogc_server_settings.public_url + 'wcs?', instance.typename.encode('utf-8'), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth)) 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', )) instance.set_permissions(permissions)
extension='html', name=instance.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() #Save layer attributes set_attributes(instance) #Save layer styles set_styles(instance, gs_catalog) def geoserver_pre_save_maplayer(instance, sender, **kwargs): # If this object was saved via fixtures, # do not do post processing. if kwargs.get('raw', False): return try: instance.local = isinstance(gs_catalog.get_layer(instance.name), GsLayer) except EnvironmentError, e:
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. """ url = ogc_server_settings.internal_rest try: gs_resource = gs_catalog.get_resource(instance.name) except (FailedRequestError, EnvironmentError) as e: msg = ('Could not connect to geoserver at "%s"' 'to save information for layer "%s"' % (ogc_server_settings.LOCATION, instance.name.encode('utf-8'))) logger.warn(msg, e) # If geoserver is not online, there is no need to continue return # If there is no resource returned it could mean one of two things: # a) There is a synchronization problem in geoserver # b) The unit tests are running and another geoserver is running in the # background. # For both cases it is sensible to stop processing the layer if gs_resource is None: logger.warn('Could not get geoserver resource for %s' % instance) return gs_resource.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', )) elif instance.storeType == 'coverageStore': #FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = {} permissions['anonymous'] = instance.get_gen_level(ANONYMOUS_USERS) permissions['authenticated'] = instance.get_gen_level( AUTHENTICATED_USERS) instance.set_gen_level(ANONYMOUS_USERS, 'layer_readonly') #Potentially 3 dimensions can be returned by the grid if there is a z #axis. Since we only want width/height, slice to the second dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] links = wcs_links(ogc_server_settings.public_url + 'wcs?', instance.typename.encode('utf-8'), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth)) 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', )) instance.set_gen_level(ANONYMOUS_USERS, permissions['anonymous']) instance.set_gen_level(AUTHENTICATED_USERS, permissions['authenticated']) 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', )) 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.objects.get_or_create(resource=instance.resourcebase_ptr, url=tile_url, defaults=dict( extension='tiles', name=_("Tiles"), mime='image/png', link_type='image', )) wms_path = '%s/%s/wms' % (instance.workspace, instance.name) ows_url = urljoin(ogc_server_settings.public_url, wms_path) Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ows_url, defaults=dict( extension='html', name=_("OWS"), url=ows_url, mime='text/html', link_type='OGC:WMS', )) 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', )) params = { 'layers': instance.typename.encode('utf-8'), 'format': 'image/png8', 'width': 200, 'height': 150, } # 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_url = ogc_server_settings.LOCATION + "wms/reflect?" + p Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=thumbnail_url, defaults=dict( extension='png', name=_("Remote Thumbnail"), mime='image/png', link_type='image', )) # Download thumbnail and save it locally. resp, image = http_client.request(thumbnail_url) if 'ServiceException' in image or resp.status < 200 or resp.status > 299: msg = 'Unable to obtain thumbnail: %s' % image logger.debug(msg) # Replace error message with None. image = None if image is not None: #Clean any orphan Thumbnail before Thumbnail.objects.filter(resourcebase__id=None).delete() thumbnail, created = Thumbnail.objects.get_or_create( resourcebase__id=instance.id) thumbnail.thumb_spec = thumbnail_url thumbnail.save_thumb(image, instance._thumbnail_path()) Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=settings.SITEURL + instance._thumbnail_path(), defaults=dict( extension='png', name=_("Thumbnail"), mime='image/png', link_type='image', )) ogc_wms_url = ogc_server_settings.public_url + 'wms?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wms_url, defaults=dict( extension='html', name=instance.name, url=ogc_wms_url, mime='text/html', link_type='OGC:WMS', )) if instance.storeType == "dataStore": ogc_wfs_url = ogc_server_settings.public_url + 'wfs?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wfs_url, defaults=dict( extension='html', name=instance.name, url=ogc_wfs_url, mime='text/html', link_type='OGC:WFS', )) if instance.storeType == "coverageStore": ogc_wcs_url = ogc_server_settings.public_url + 'wcs?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wcs_url, defaults=dict( extension='html', name=instance.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() #Save layer attributes set_attributes(instance) #Save layer styles set_styles(instance, gs_catalog)
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. """ url = ogc_server_settings.internal_rest try: gs_resource= gs_catalog.get_resource(instance.name) 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 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', ) ) elif instance.storeType == 'coverageStore': #FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = {} permissions['anonymous'] = instance.get_gen_level(ANONYMOUS_USERS) permissions['authenticated'] = instance.get_gen_level(AUTHENTICATED_USERS) instance.set_gen_level(ANONYMOUS_USERS,'layer_readonly') #Potentially 3 dimensions can be returned by the grid if there is a z #axis. Since we only want width/height, slice to the second dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] links = wcs_links(ogc_server_settings.public_url + 'wcs?', instance.typename.encode('utf-8'), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth)) 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', ) ) instance.set_gen_level(ANONYMOUS_USERS,permissions['anonymous']) instance.set_gen_level(AUTHENTICATED_USERS,permissions['authenticated']) 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', ) ) 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.objects.get_or_create(resource= instance.resourcebase_ptr, url=tile_url, defaults=dict( extension='tiles', name=_("Tiles"), mime='image/png', link_type='image', ) ) wms_path = '%s/%s/wms' % (instance.workspace, instance.name) ows_url = urljoin(ogc_server_settings.public_url, wms_path) Link.objects.get_or_create(resource= instance.resourcebase_ptr, url=ows_url, defaults=dict( extension='html', name=_("OWS"), url=ows_url, mime='text/html', link_type='OGC:WMS', ) ) 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', ) ) params = { 'layers': instance.typename.encode('utf-8'), 'format': 'image/png8', 'width': 200, 'height': 150, } # 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 + "wms/reflect?" + p create_thumbnail(instance, thumbnail_remote_url) 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_url = ogc_server_settings.public_url + 'wms?' Link.objects.get_or_create(resource= instance.resourcebase_ptr, url=ogc_wms_url, defaults=dict( extension='html', name=instance.name, url=ogc_wms_url, mime='text/html', link_type='OGC:WMS', ) ) if instance.storeType == "dataStore": ogc_wfs_url = ogc_server_settings.public_url + 'wfs?' Link.objects.get_or_create(resource= instance.resourcebase_ptr, url=ogc_wfs_url, defaults=dict( extension='html', name=instance.name, url=ogc_wfs_url, mime='text/html', link_type='OGC:WFS', ) ) if instance.storeType == "coverageStore": ogc_wcs_url = ogc_server_settings.public_url + 'wcs?' Link.objects.get_or_create(resource= instance.resourcebase_ptr, url=ogc_wcs_url, defaults=dict( extension='html', name=instance.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() #Save layer attributes set_attributes(instance) #Save layer styles set_styles(instance, gs_catalog)
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. """ if type(instance) is ResourceBase: if hasattr(instance, 'layer'): instance = instance.layer else: return if instance.storeType == "remoteStore": # Save layer attributes set_attributes(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', ) ) if gs_resource.store.type and gs_resource.store.type.lower() == 'geogig' and \ gs_resource.store.connection_parameters.get('geogig_repository'): repo_url = '{url}geogig/{geogig_repository}'.format( url=ogc_server_settings.public_url, geogig_repository=gs_resource.store.connection_parameters.get('geogig_repository')) 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', ) ) 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.objects.get_or_create(resource=instance.resourcebase_ptr, url=tile_url, defaults=dict( extension='tiles', name="Tiles", mime='image/png', link_type='image', ) ) 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', ) ) 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 + \ "wms/reflect?" + p thumbnail_create_url = ogc_server_settings.LOCATION + \ "wms/reflect?" + p create_thumbnail(instance, thumbnail_remote_url, thumbnail_create_url, ogc_client=http_client) 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() # Save layer attributes set_attributes(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)
def test_set_attributes_creates_attributes(self): """ Test utility function set_attributes() which creates Attribute instances attached to a Dataset instance. """ # Creating a dataset requires being logged in self.client.login(username='******', password='******') # Create dummy dataset to attach attributes to _l = Dataset.objects.create(owner=self.user, name='dummy_dataset', bbox_polygon=Polygon.from_bbox( (-180, -90, 180, 90)), srid='EPSG:4326') attribute_map = [ ['id', 'Integer'], ['date', 'IntegerList'], ['enddate', 'Real'], ['date_as_date', 'xsd:dateTime'], ] # attribute_map gets modified as a side-effect of the call to set_attributes() expected_results = copy.deepcopy(attribute_map) # set attributes for resource set_attributes(_l, attribute_map.copy()) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEqual(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results) # GeoNode cleans up local duplicated attributes for attribute in attribute_map: field = attribute[0] ftype = attribute[1] if field: la = Attribute.objects.create(dataset=_l, attribute=field) la.visible = ftype.find("gml:") != 0 la.attribute_type = ftype la.description = None la.attribute_label = None la.display_order = 0 # set attributes for resource set_attributes(_l, attribute_map.copy()) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEqual(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results) # Test that deleted attributes from GeoServer gets deleted on GeoNode too attribute_map = [ ['id', 'Integer'], ['date_as_date', 'xsd:dateTime'], ] # attribute_map gets modified as a side-effect of the call to set_attributes() expected_results = copy.deepcopy(attribute_map) # set attributes for resource set_attributes(_l, attribute_map.copy()) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEqual(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results)
def test_set_attributes_creates_attributes(self): """ Test utility function set_attributes() which creates Attribute instances attached to a Layer instance. """ # Creating a layer requires being logged in self.client.login(username='******', password='******') # Disconnect the geoserver-specific post_save signal attached to Layer creation. # The geoserver signal handler assumes things about the store where the Layer is placed. # this is a workaround. disconnected_post_save = signals.post_save.disconnect( geoserver_post_save, sender=Layer) # Create dummy layer to attach attributes to _l = Layer.objects.create(name='dummy_layer', bbox_polygon=Polygon.from_bbox( (-180, -90, 180, 90)), srid='EPSG:4326') # Reconnect the signal if it was disconnected if disconnected_post_save: signals.post_save.connect(geoserver_post_save, sender=Layer) attribute_map = [ ['id', 'Integer'], ['date', 'IntegerList'], ['enddate', 'Real'], ['date_as_date', 'xsd:dateTime'], ] # attribute_map gets modified as a side-effect of the call to set_attributes() expected_results = copy.deepcopy(attribute_map) # set attributes for resource set_attributes(_l, attribute_map.copy()) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEqual(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results) # GeoNode cleans up local duplicated attributes for attribute in attribute_map: field = attribute[0] ftype = attribute[1] if field: la = Attribute.objects.create(layer=_l, attribute=field) la.visible = ftype.find("gml:") != 0 la.attribute_type = ftype la.description = None la.attribute_label = None la.display_order = 0 # set attributes for resource set_attributes(_l, attribute_map.copy()) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEqual(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results) # Test that deleted attributes from GeoServer gets deleted on GeoNode too attribute_map = [ ['id', 'Integer'], ['date_as_date', 'xsd:dateTime'], ] # attribute_map gets modified as a side-effect of the call to set_attributes() expected_results = copy.deepcopy(attribute_map) # set attributes for resource set_attributes(_l, attribute_map.copy()) # 2 items in attribute_map should translate into 2 Attribute instances self.assertEqual(_l.attributes.count(), len(expected_results)) # The name and type should be set as provided by attribute map for a in _l.attributes: self.assertIn([a.attribute, a.attribute_type], expected_results)
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. """ if type(instance) is ResourceBase: if hasattr(instance, "layer"): instance = instance.layer else: return if instance.storeType == "remoteStore": # Save layer attributes set_attributes(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"), ) if ( gs_resource.store.type and gs_resource.store.type.lower() == "geogig" and gs_resource.store.connection_parameters.get("geogig_repository") ): repo_url = "{url}geogig/{geogig_repository}".format( url=ogc_server_settings.public_url, geogig_repository=gs_resource.store.connection_parameters.get("geogig_repository"), ) 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": # FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = instance.get_all_level_info() instance.set_permissions({"users": {"AnonymousUser": ["view_resourcebase"]}}) try: # Potentially 3 dimensions can be returned by the grid if there is a z # axis. Since we only want width/height, slice to the second # dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] except GeoNodeException as e: msg = _("Could not create a download link for layer.") try: # HACK: The logger on signals throws an exception logger.warn(msg, e) except: pass else: links = wcs_links( ogc_server_settings.public_url + "wcs?", instance.typename.encode("utf-8"), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth), ) 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"), ) instance.set_permissions(permissions) 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"), ) 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.objects.get_or_create( resource=instance.resourcebase_ptr, url=tile_url, defaults=dict(extension="tiles", name="Tiles", mime="image/png", link_type="image"), ) 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"), ) params = {"layers": instance.typename.encode("utf-8"), "format": "image/png8", "width": 200, "height": 150} # 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 + "wms/reflect?" + p thumbnail_create_url = ogc_server_settings.LOCATION + "wms/reflect?" + p create_thumbnail(instance, thumbnail_remote_url, thumbnail_create_url, ogc_client=http_client) 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() # Save layer attributes set_attributes(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)
def _register_indexed_layers(service, wms=None, verbosity=False): """ Register layers for an indexed service (only WMS/OWS currently supported) """ logger.info("Registering layers for %s" % service.base_url) if re.match("WMS|OWS", service.type): wms = wms or WebMapService(service.base_url) count = 0 for layer in list(wms.contents): wms_layer = wms[layer] if wms_layer is None or wms_layer.name is None: continue logger.info("Registering layer %s" % wms_layer.name) if verbosity: print "Importing layer %s" % layer layer_uuid = str(uuid.uuid1()) try: keywords = map(lambda x: x[:100], wms_layer.keywords) except: keywords = [] if not wms_layer.abstract: abstract = "" else: abstract = wms_layer.abstract srid = None # Some ArcGIS WMSServers indicate they support 900913 but really # don't if 'EPSG:900913' in wms_layer.crsOptions and "MapServer/WmsServer" not in service.base_url: srid = 'EPSG:900913' elif len(wms_layer.crsOptions) > 0: matches = re.findall('EPSG\:(3857|102100|102113)', ' '.join(wms_layer.crsOptions)) if matches: srid = 'EPSG:%s' % matches[0] if srid is None: message = "%d Incompatible projection - try setting the service as cascaded" % count return_dict = {'status': 'ok', 'msg': message} return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200) bbox = list(wms_layer.boundingBoxWGS84 or (-179.0, -89.0, 179.0, 89.0)) # Need to check if layer already exists?? saved_layer, created = Layer.objects.get_or_create( typename=wms_layer.name, service=service, defaults=dict( name=wms_layer.name, store=service.name, # ?? storeType="remoteStore", workspace="remoteWorkspace", title=wms_layer.title or wms_layer.name, abstract=abstract or _("Not provided"), uuid=layer_uuid, owner=None, srid=srid, bbox_x0=bbox[0], bbox_x1=bbox[2], bbox_y0=bbox[1], bbox_y1=bbox[3])) if created: saved_layer.save() saved_layer.set_default_permissions() saved_layer.keywords.add(*keywords) set_attributes(saved_layer) service_layer, created = ServiceLayer.objects.get_or_create( typename=wms_layer.name, service=service) service_layer.layer = saved_layer service_layer.title = wms_layer.title service_layer.description = wms_layer.abstract service_layer.styles = wms_layer.styles service_layer.save() count += 1 message = "%d Layers Registered" % count return_dict = {'status': 'ok', 'msg': message} return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200) elif service.type == 'WFS': return HttpResponse('Not Implemented (Yet)', status=501) elif service.type == 'WCS': return HttpResponse('Not Implemented (Yet)', status=501) else: return HttpResponse('Invalid Service Type', status=400)
def _register_indexed_layers(service, wms=None, verbosity=False): """ Register layers for an indexed service (only WMS/OWS currently supported) """ logger.info("Registering layers for %s" % service.base_url) if re.match("WMS|OWS", service.type): wms = wms or WebMapService(service.base_url) count = 0 for layer in list(wms.contents): wms_layer = wms[layer] if wms_layer is None or wms_layer.name is None: continue logger.info("Registering layer %s" % wms_layer.name) if verbosity: print "Importing layer %s" % layer layer_uuid = str(uuid.uuid1()) try: keywords = map(lambda x: x[:100], wms_layer.keywords) except: keywords = [] if not wms_layer.abstract: abstract = "" else: abstract = wms_layer.abstract srid = None # Some ArcGIS WMSServers indicate they support 900913 but really # don't if "EPSG:900913" in wms_layer.crsOptions and "MapServer/WmsServer" not in service.base_url: srid = "EPSG:900913" elif len(wms_layer.crsOptions) > 0: matches = re.findall("EPSG\:(3857|102100|102113)", " ".join(wms_layer.crsOptions)) if matches: srid = "EPSG:%s" % matches[0] if srid is None: message = "%d Incompatible projection - try setting the service as cascaded" % count return_dict = {"status": "ok", "msg": message} return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200) bbox = list(wms_layer.boundingBoxWGS84 or (-179.0, -89.0, 179.0, 89.0)) # Need to check if layer already exists?? saved_layer, created = Layer.objects.get_or_create( typename=wms_layer.name, service=service, defaults=dict( name=wms_layer.name, store=service.name, # ?? storeType="remoteStore", workspace="remoteWorkspace", title=wms_layer.title or wms_layer.name, abstract=abstract or _("Not provided"), uuid=layer_uuid, owner=None, srid=srid, bbox_x0=bbox[0], bbox_x1=bbox[2], bbox_y0=bbox[1], bbox_y1=bbox[3], ), ) if created: saved_layer.save() saved_layer.set_default_permissions() saved_layer.keywords.add(*keywords) set_attributes(saved_layer) service_layer, created = ServiceLayer.objects.get_or_create(typename=wms_layer.name, service=service) service_layer.layer = saved_layer service_layer.title = wms_layer.title service_layer.description = wms_layer.abstract service_layer.styles = wms_layer.styles service_layer.save() count += 1 message = "%d Layers Registered" % count return_dict = {"status": "ok", "msg": message} return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200) elif service.type == "WFS": return HttpResponse("Not Implemented (Yet)", status=501) elif service.type == "WCS": return HttpResponse("Not Implemented (Yet)", status=501) else: return HttpResponse("Invalid Service Type", status=400)
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. """ url = ogc_server_settings.internal_rest try: gs_resource = gs_catalog.get_resource(instance.name) 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 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', )) elif instance.storeType == 'coverageStore': #FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = {} permissions['anonymous'] = instance.get_gen_level(ANONYMOUS_USERS) permissions['authenticated'] = instance.get_gen_level( AUTHENTICATED_USERS) instance.set_gen_level(ANONYMOUS_USERS, 'layer_readonly') #Potentially 3 dimensions can be returned by the grid if there is a z #axis. Since we only want width/height, slice to the second dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] links = wcs_links(ogc_server_settings.public_url + 'wcs?', instance.typename.encode('utf-8'), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth)) 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', )) instance.set_gen_level(ANONYMOUS_USERS, permissions['anonymous']) instance.set_gen_level(AUTHENTICATED_USERS, permissions['authenticated']) 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', )) 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.objects.get_or_create(resource=instance.resourcebase_ptr, url=tile_url, defaults=dict( extension='tiles', name=_("Tiles"), mime='image/png', link_type='image', )) wms_path = '%s/%s/wms' % (instance.workspace, instance.name) ows_url = urljoin(ogc_server_settings.public_url, wms_path) Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ows_url, defaults=dict( extension='html', name=_("OWS"), url=ows_url, mime='text/html', link_type='OGC:WMS', )) 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', )) params = { 'layers': instance.typename.encode('utf-8'), 'format': 'image/png8', 'width': 200, 'height': 150, } # 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 + "wms/reflect?" + p create_thumbnail(instance, thumbnail_remote_url) 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_url = ogc_server_settings.public_url + 'wms?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wms_url, defaults=dict( extension='html', name=instance.name, url=ogc_wms_url, mime='text/html', link_type='OGC:WMS', )) if instance.storeType == "dataStore": ogc_wfs_url = ogc_server_settings.public_url + 'wfs?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wfs_url, defaults=dict( extension='html', name=instance.name, url=ogc_wfs_url, mime='text/html', link_type='OGC:WFS', )) if instance.storeType == "coverageStore": ogc_wcs_url = ogc_server_settings.public_url + 'wcs?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wcs_url, defaults=dict( extension='html', name=instance.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() #Save layer attributes set_attributes(instance) #Save layer styles set_styles(instance, gs_catalog)
def process_wmts_service(url, name, type, username, password, wmts=None, owner=None, parent=None): """ Create a new WMTS service """ if wmts is None: wmts = WebMapTileService(url) try: base_url = _clean_url(wmts.getOperationByName("GetTile").methods["Get"]["url"]) if base_url and base_url != url: url = base_url wmts = WebMapTileService(base_url) except: logger.info("Could not retrieve GetMap url, using originally supplied URL %s" % url) pass try: service = Service.objects.get(base_url=url) return_dict = [ { "status": "ok", "msg": _("This is an existing service"), "service_id": service.pk, "service_name": service.name, "service_title": service.title, } ] return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200) except: pass title = wmts.identification.title if not name: if title: name = wmts.identification.title else: name = urlsplit(url).netloc for layer, layer_metadata in wmts.contents.items(): if layer is None or layer_metadata.name is None: continue logger.info("Registering layer %s" % layer_metadata.name) layer_uuid = str(uuid.uuid1()) try: keywords = map(lambda x: x[:100], layer_metadata.keywords) except: keywords = [] if not layer_metadata.abstract: abstract = "" else: abstract = layer_metadata.abstract bbox = list(layer_metadata.boundingBoxWGS84 or (-179.0, -89.0, 179.0, 89.0)) # Need to check if layer already exists?? saved_layer, created = Layer.objects.get_or_create( typename=layer_metadata.name, service=service, defaults=dict( name=layer_metadata.name, store=service.name, # ?? storeType="remoteStore", workspace="remoteWorkspace", title=layer_metadata.title or layer_metadata.name, abstract=layer_metadata.abstract or ("Not provided"), uuid=layer_uuid, owner=None, srid=layer_metadata.tilematrixsets, bbox_x0=bbox[0], bbox_x1=bbox[2], bbox_y0=bbox[1], bbox_y1=bbox[3], ), ) if created: saved_layer.save() saved_layer.set_default_permissions() saved_layer.keywords.add(*keywords) set_attributes(saved_layer) service_layer, created = ServiceLayer.objects.get_or_create(typename=layer_metadata.name, service=service) service_layer.layer = saved_layer service_layer.title = layer_metadata.title service_layer.description = layer_metadata.abstract service_layer.styles = layer_metadata.styles service_layer.save() message = "%d Layers Registered" % count return_dict = {"status": "ok", "msg": message} return HttpResponse(json.dumps(return_dict), mimetype="application/json", status=200)
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. """ if type(instance) is ResourceBase: if hasattr(instance, 'layer'): instance = instance.layer else: return if instance.storeType == "remoteStore": # Save layer attributes set_attributes(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', ) ) 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 + \ "wms/reflect?" + p thumbnail_create_url = ogc_server_settings.LOCATION + \ "wms/reflect?" + p create_thumbnail(instance, thumbnail_remote_url, thumbnail_create_url, ogc_client=http_client) 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(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)
def process_wmts_service(url, name, type, username, password, wmts=None, owner=None, parent=None): """ Create a new WMTS service """ if wmts is None: wmts = WebMapTileService(url) try: base_url = _clean_url( wmts.getOperationByName('GetTile').methods['Get']['url']) if base_url and base_url != url: url = base_url wmts = WebMapTileService(base_url) except: logger.info( "Could not retrieve GetMap url, using originally supplied URL %s" % url) pass try: service = Service.objects.get(base_url=url) return_dict = [{ 'status': 'ok', 'msg': _("This is an existing service"), 'service_id': service.pk, 'service_name': service.name, 'service_title': service.title }] return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200) except: pass title = wmts.identification.title if not name: if title: name = wmts.identification.title else: name = urlsplit(url).netloc for layer, layer_metadata in wmts.contents.items(): if layer is None or layer_metadata.name is None: continue logger.info("Registering layer %s" % layer_metadata.name) layer_uuid = str(uuid.uuid1()) try: keywords = map(lambda x: x[:100], layer_metadata.keywords) except: keywords = [] if not layer_metadata.abstract: abstract = "" else: abstract = layer_metadata.abstract bbox = list(layer_metadata.boundingBoxWGS84 or (-179.0, -89.0, 179.0, 89.0)) # Need to check if layer already exists?? saved_layer, created = Layer.objects.get_or_create( typename=layer_metadata.name, service=service, defaults=dict( name=layer_metadata.name, store=service.name, # ?? storeType="remoteStore", workspace="remoteWorkspace", title=layer_metadata.title or layer_metadata.name, abstract=layer_metadata.abstract or ("Not provided"), uuid=layer_uuid, owner=None, srid=layer_metadata.tilematrixsets, bbox_x0=bbox[0], bbox_x1=bbox[2], bbox_y0=bbox[1], bbox_y1=bbox[3])) if created: saved_layer.save() saved_layer.set_default_permissions() saved_layer.keywords.add(*keywords) set_attributes(saved_layer) service_layer, created = ServiceLayer.objects.get_or_create( typename=layer_metadata.name, service=service) service_layer.layer = saved_layer service_layer.title = layer_metadata.title service_layer.description = layer_metadata.abstract service_layer.styles = layer_metadata.styles service_layer.save() message = "%d Layers Registered" % count return_dict = {'status': 'ok', 'msg': message} return HttpResponse(json.dumps(return_dict), mimetype='application/json', status=200)
resource=instance.resourcebase_ptr, url=ogc_wcs_url, defaults=dict(extension="html", name=instance.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() # Save layer attributes set_attributes(instance) # Save layer styles set_styles(instance, gs_catalog) def geoserver_pre_save_maplayer(instance, sender, **kwargs): # If this object was saved via fixtures, # do not do post processing. if kwargs.get("raw", False): return try: instance.local = isinstance(gs_catalog.get_layer(instance.name), GsLayer) except EnvironmentError, e: if e.errno == errno.ECONNREFUSED:
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. """ if instance.storeType == "remoteStore": # Save layer attributes set_attributes(instance) return 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 if gs_resource is None: return 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', ) ) if gs_resource.store.type.lower() == 'geogit': repo_url = '{url}geogit/{workspace}:{store}'.format( url=ogc_server_settings.public_url, workspace=instance.workspace, store=instance.store) 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 GeoGit', mime='text/xml', link_type='html' ) ) command_url = lambda command: "{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='GeoGit 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='GeoGit statistics', mime='application/json', link_type='html' ) ) elif instance.storeType == 'coverageStore': # FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = instance.get_all_level_info() instance.set_permissions( {'users': {'AnonymousUser': ['view_resourcebase']}}) try: # Potentially 3 dimensions can be returned by the grid if there is a z # axis. Since we only want width/height, slice to the second # dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] except GeoNodeException as e: msg = _('Could not create a download link for layer.') logger.warn(msg, e) else: links = wcs_links(ogc_server_settings.public_url + 'wcs?', instance.typename.encode('utf-8'), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth)) 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', ) ) instance.set_permissions(permissions) 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', ) ) 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.objects.get_or_create(resource=instance.resourcebase_ptr, url=tile_url, defaults=dict( extension='tiles', name=_("Tiles"), mime='image/png', link_type='image', ) ) wms_path = '%s/%s/wms' % (instance.workspace, instance.name) ows_url = urljoin(ogc_server_settings.public_url, wms_path) Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ows_url, defaults=dict( extension='html', name=_("OWS"), url=ows_url, mime='text/html', link_type='OGC:WMS', ) ) 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', ) ) params = { 'layers': instance.typename.encode('utf-8'), 'format': 'image/png8', 'width': 200, 'height': 150, } # 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 + \ "wms/reflect?" + p thumbail_create_url = ogc_server_settings.LOCATION + \ "wms/reflect?" + p # This is a workaround for development mode where cookies are not shared and the layer is not public so # not visible through geoserver if settings.DEBUG: from geonode.security.views import _perms_info_json current_perms = _perms_info_json(instance.get_self_resource()) instance.set_default_permissions() create_thumbnail(instance, thumbnail_remote_url, thumbail_create_url) if settings.DEBUG: instance.set_permissions(json.loads(current_perms)) 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_url = ogc_server_settings.public_url + 'wms?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wms_url, defaults=dict( extension='html', name=instance.name, url=ogc_wms_url, mime='text/html', link_type='OGC:WMS', ) ) if instance.storeType == "dataStore": ogc_wfs_url = ogc_server_settings.public_url + 'wfs?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wfs_url, defaults=dict( extension='html', name=instance.name, url=ogc_wfs_url, mime='text/html', link_type='OGC:WFS', ) ) if instance.storeType == "coverageStore": ogc_wcs_url = ogc_server_settings.public_url + 'wcs?' Link.objects.get_or_create(resource=instance.resourcebase_ptr, url=ogc_wcs_url, defaults=dict( extension='html', name=instance.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() # Save layer attributes set_attributes(instance) # Save layer styles set_styles(instance, gs_catalog)
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. """ if type(instance) is ResourceBase: if hasattr(instance, 'layer'): instance = instance.layer else: return if instance.storeType == "remoteStore": # Save layer attributes set_attributes(instance) return 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 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', )) if gs_resource.store.type and gs_resource.store.type.lower() == 'geogig' and \ gs_resource.store.connection_parameters.get('geogig_repository'): repo_url = '{url}geogig/{geogig_repository}'.format( url=ogc_server_settings.public_url, geogig_repository=gs_resource.store.connection_parameters.get( 'geogig_repository')) 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')) command_url = lambda command: "{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': # FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = instance.get_all_level_info() instance.set_permissions( {'users': { 'AnonymousUser': ['view_resourcebase'] }}) try: # Potentially 3 dimensions can be returned by the grid if there is a z # axis. Since we only want width/height, slice to the second # dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] except GeoNodeException as e: msg = _('Could not create a download link for layer.') logger.warn(msg, e) else: links = wcs_links(ogc_server_settings.public_url + 'wcs?', instance.typename.encode('utf-8'), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth)) 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', )) instance.set_permissions(permissions) 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', )) 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.objects.get_or_create(resource=instance.resourcebase_ptr, url=tile_url, defaults=dict( extension='tiles', name=_("Tiles"), mime='image/png', link_type='image', )) 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', )) params = { 'layers': instance.typename.encode('utf-8'), 'format': 'image/png8', 'width': 200, 'height': 150, } # 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 + \ "wms/reflect?" + p thumbnail_create_url = ogc_server_settings.LOCATION + \ "wms/reflect?" + p create_thumbnail(instance, thumbnail_remote_url, thumbnail_create_url, ogc_client=http_client) 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() # Save layer attributes set_attributes(instance) # Save layer styles set_styles(instance, gs_catalog)
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. """ if instance.storeType == "remoteStore": #Save layer attributes set_attributes(instance) return url = ogc_server_settings.internal_rest 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 if gs_resource is None: return 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', ) ) elif instance.storeType == 'coverageStore': #FIXME(Ariel): This works for public layers, does it work for restricted too? # would those end up with no geotiff links, like, forever? permissions = instance.get_all_level_info() instance.set_permissions({'users':{'AnonymousUser': ['view_resourcebase']}}) try: #Potentially 3 dimensions can be returned by the grid if there is a z #axis. Since we only want width/height, slice to the second dimension covWidth, covHeight = get_coverage_grid_extent(instance)[:2] except GeoNodeException, e: msg = _('Could not create a download link for layer.') logger.warn(msg, e) else: links = wcs_links(ogc_server_settings.public_url + 'wcs?', instance.typename.encode('utf-8'), bbox=gs_resource.native_bbox[:-1], crs=gs_resource.native_bbox[-1], height=str(covHeight), width=str(covWidth)) 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', ) ) instance.set_permissions(permissions)