Publishing map service with WMS capability with arcpy

179
2
08-03-2021 02:33 PM
JoeRogan
New Contributor III

Hi, trying to use arcpy to publish and overwrite a service that has the WMS capability enabled.  Federated Server/Portal 10.8.1.  Code below isn't my full code, but I think I've reduced it down to what is relevant.  The problem is that when the final line runs that stages the service, it does an analyse and throws and error:

ERROR 001272: Analyzer errors were encountered ([{"code":"00297","message":"WMS layers must be shared with everyone","object":"MyServiceName"}]).

We used to have this working with 10.7 and with ArcMap's arcpy, but this is trying to use a Pro 2.7 map.  Not sure how to set sharing public before the arcpy.UploadServiceDefinition_server.  The service is already published and both the regular map service and WMS items are already shared public.

 

 

import arcpy
import os
import xml.dom.minidom as DOM

# Sign into Portal and publish
arcpy.SignInToPortal(portal_URL, portal_pub_user, portal_pub_pass)

# Create MapImageSharingDraft and set metadata, portal folder, and server folder properties
sharing_draft = MAP.getWebLayerSharingDraft("FEDERATED_SERVER""MAP_IMAGE", service_name)
sharing_draft.summary = "summary"
sharing_draft.tags = "tags"
sharing_draft.description = "description"
sharing_draft.credits = "credits"
sharing_draft.useLimitations = "useLimitations "
sharing_draft.serviceName = service_name
sharing_draft.federatedServerUrl = server_URL
sharing_draft.serverFolder = "serverFolder"
sharing_draft.portalFolder = "portalFolder"
sharing_draft.overwriteExistingService = True

# Create Service Definition Draft file
sharing_draft.exportToSDDraft(sddraft_output_filename)

# Edit SD Draft XML to enable WMS
doc = DOM.parse(sddraft_output_filename)
descriptions = doc.getElementsByTagName('Type')
for desc in descriptions:
  if desc.parentNode.tagName == 'SVCManifest':
    if desc.hasChildNodes():
      desc.firstChild.data = 'esriServiceDefinitionType_Replacement'
typeNames = doc.getElementsByTagName('TypeName')
for typeName in typeNames:
  # Get the TypeName we want to enable.
  if typeName.firstChild.data == 'WMSServer':
    extension = typeName.parentNode
    keys = doc.getElementsByTagName('Key')  
    for extElement in extension.childNodes:
      # Enabled WMS
      if extElement.tagName == 'Enabled':
        extElement.firstChild.data = 'true'
      
= open(sddraft_output_filename, 'w')
doc.writexml(f)
f.close()


# Stage Service
arcpy.StageService_server(sddraft_output_filename, sd_output_filename)
 
# Share to portal
arcpy.UploadServiceDefinition_server(in_sd_file=sd_output_filename, in_server=portal_URL, in_folder_type="EXISTING", in_override = "OVERRIDE_DEFINITION", in_public = "PUBLIC", in_organization = "SHARE_ORGANIZATION")
0 Kudos
2 Replies
TomThompson3
Esri Contributor

An enhancement was logged for this issue, noted below:

ENH-000142251: Include a sharing capability parameter in the StageService_server() function in Arcpy.

 

The workaround is to leverage the Python API or the REST API directly (via requests module) to update the service to enable WMS capabilities AFTER it has been published via ArcPy, using the edit() method on the Python API's service class, found here: https://developers.arcgis.com/python/api-reference/arcgis.gis.server.html#arcgis.gis.server.Service....

 

For this to be possible, the JSON dictionary of the edits must contain all properties for the service. The easiest way to do this initially is to make this change manually in the Server Manager on the server site, and capture the edit operation made to the service. The JSON will look something like this:

 

 

 

{
  "serviceName": "20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png",
  "type": "MapServer",
  "description": "",
  "capabilities": "Map,Query,Data",
  "provider": "DMaps",
  "clusterName": "default",
  "minInstancesPerNode": 0,
  "maxInstancesPerNode": 0,
  "instancesPerContainer": "1",
  "maxWaitTime": "60",
  "maxStartupTime": 300,
  "maxIdleTime": "1800",
  "maxUsageTime": "600",
  "loadBalancing": "ROUND_ROBIN",
  "isolationLevel": "HIGH",
  "configuredState": "STOPPED",
  "recycleInterval": "24",
  "recycleStartTime": "00:00",
  "keepAliveInterval": 1800,
  "private": false,
  "isDefault": false,
  "maxUploadFileSize": 0,
  "allowedUploadFileTypes": "",
  "properties": {
    "maxDomainCodeCount": "25000",
    "cacheDir": "C:\\arcgis\\arcgisserver\\directories\\arcgiscache",
    "maxImageWidth": "4096",
    "maxRecordCount": "2000",
    "antialiasingMode": "Fast",
    "enableDynamicLayers": true,
    "dynamicDataWorkspaces": [],
    "isCached": false,
    "virtualOutputDir": "/rest/directories/arcgisoutput",
    "exportTilesAllowed": "false",
    "maxImageHeight": "4096",
    "cacheOnDemand": false,
    "minScale": "9027.9774109999998",
    "schemaLockingEnabled": true,
    "useLocalCacheDir": true,
    "outputDir": "C:\\arcgis\\arcgisserver\\directories\\arcgisoutput",
    "maxScale": "4513.9887049999998",
    "filePath": "C:\\arcgis\\arcgisserver\\directories\\arcgissystem\\arcgisinput\\20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png.MapServer\\extracted\\p20\\Updated_20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png.msd",
    "supportedImageReturnTypes": "URL",
    "maxSampleSize": "100000",
    "clientCachingAllowed": true,
    "userName": "siteadmin",
    "textAntialiasingMode": "Force",
    "maxExportTilesCount": "100000",
    "ignoreCache": false,
    "maxBufferCount": "100",
    "disableIdentifyRelates": false,
    "portalURL": "https://site.int/portal/",
    "dateFieldsTimezoneID": "",
    "dateFieldsRespectsDayLightSavingTime": false,
    "tilingScheme": 3,
    "maxLOD": "",
    "minLOD": "",
    "resampling": false
  },
  "portalProperties": {
    "isHosted": false,
    "portalItems": [
      {
        "itemID": "2654fcc55e2442ff8dab2ac8be9b44be",
        "type": "MapServer"
      }
    ]
  },
  "extensions": [
    {
      "typeName": "ValidationServer",
      "capabilities": "",
      "enabled": false
    },
    {
      "typeName": "WCSServer",
      "capabilities": null,
      "properties": {
        "name": "20210520_Pembina_127_14302_Athabasca River Right _South_ Slope_B206_2cm_png",
        "role": "",
        "title": "20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png",
        "defaultVersion": "2.0.1",
        "abstract": "",
        "keywords": "",
        "fees": "",
        "accessConstraints": "None",
        "responsiblePerson": "",
        "responsiblePosition": "",
        "onlineResource": "https://site.int/server/services/20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png/MapServer/WCSServer",
        "providerName": "",
        "phone": "",
        "fax": "",
        "contactInstructions": "",
        "email": "",
        "address": "",
        "city": "",
        "province": "",
        "zipcode": "",
        "providerWebsite": "",
        "serviceHour": "",
        "country": "",
        "customGetCapabilities": false,
        "pathToCustomGetCapabilitiesFiles": "",
        "maxImageHeight": "",
        "maxImageWidth": "",
        "SupportEOProfile": false
      },
      "enabled": false
    },
    {
      "typeName": "WFSServer",
      "capabilities": null,
      "properties": {
        "name": "20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png",
        "appSchemaURI": "https://site.int/server/services/20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png/MapServer/WFSServer",
        "role": "",
        "appSchemaPrefix": "20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png",
        "pathToStoredQueryFile": "",
        "enableTransactions": false,
        "title": "",
        "abstract": "",
        "keyword": "",
        "fees": "",
        "serviceType": "",
        "serviceTypeVersion": "",
        "deliveryPoint": "",
        "accessConstraints": "",
        "individualName": "",
        "positionName": "",
        "providerName": "",
        "onlineResource": "https://site.int/server/services/20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png/MapServer/WFSServer",
        "facsimile": "",
        "phone": "",
        "electronicMailAddress": "",
        "contactInstructions": "",
        "hourOfService": "",
        "providerSite": "",
        "administrativeArea": "",
        "city": "",
        "postalCode": "",
        "country": "",
        "pathToCustomGetCapabilitiesFiles": "",
        "customGetCapabilities": false,
        "transactionsWithoutLocks": false,
        "enableDefMaxFeatures": false,
        "defMaxFeaturesValue": "",
        "axisOrderWFS10": "longlat",
        "axisOrderWFS11": "longlat",
        "axisOrderWFS20": "longlat"
      },
      "enabled": false
    },
    {
      "typeName": "NAServer",
      "capabilities": null,
      "properties": {
        "nALayerDir": "C:\\arcgis\\arcgisserver\\directories\\arcgisoutput",
        "defaultOutputGeometryPrecision": "",
        "defaultOutputGeometryPrecisionUnits": "esriMeters",
        "saveLayerOnServerWhenError": false,
        "saveLayerOnServerWhenDebugging": false,
        "allowSaveLayerOnServer": true,
        "ignoreNetworkLocationFields": false,
        "usePortalTravelModes": false,
        "licensedForAutomaticRerouting": false,
        "route_MaxBarriers": "",
        "route_MaxStops": "",
        "route_MaxFeaturesInLineBarriers": "",
        "route_MaxFeaturesInPolygonBarriers": "",
        "route_AllowTimeWindows": "true",
        "route_ForceHierarchyBeyondDistance": "",
        "route_ForceHierarchyBeyondDistanceUnits": "esriMeters",
        "oDCostMatrix_MaxBarriers": "",
        "oDCostMatrix_MaxOrigins": "",
        "oDCostMatrix_MaxDestinations": "",
        "oDCostMatrix_MaxDestinationsToFind": "",
        "oDCostMatrix_MaxFeaturesInLineBarriers": "",
        "oDCostMatrix_MaxFeaturesInPolygonBarriers": "",
        "oDCostMatrix_ForceHierarchyBeyondDistance": "",
        "oDCostMatrix_ForceHierarchyBeyondDistanceUnits": "esriMeters",
        "locationAllocation_MaxFacilities": "",
        "locationAllocation_MaxFeaturesInPolygonBarriers": "",
        "locationAllocation_MaxFeaturesInLineBarriers": "",
        "locationAllocation_MaxBarriers": "",
        "locationAllocation_MaxDemandPoints": "",
        "locationAllocation_ForceHierarchyBeyondDistance": "",
        "locationAllocation_ForceHierarchyBeyondDistanceUnits": "esriMeters",
        "serviceArea_MaxBarriers": "",
        "serviceArea_MaxBreakValue_Time": "",
        "serviceArea_MaxBreakValue_TimeUnits": "esriTimeUnitsMinutes",
        "serviceArea_MaxBreakValue_Length": "",
        "serviceArea_MaxBreakValue_LengthUnits": "esriMeters",
        "serviceArea_MaxBreakValue_Other": "",
        "serviceArea_MaxFacilities": "",
        "serviceArea_MaxFeaturesInPolygonBarriers": "",
        "serviceArea_MaxFeaturesInLineBarriers": "",
        "serviceArea_ForceHierarchyBeyondDistance": "",
        "serviceArea_ForceHierarchyBeyondDistanceUnits": "esriMeters",
        "serviceArea_ForceHierarchyBeyondTime": "",
        "serviceArea_ForceHierarchyBeyondTimeUnits": "esriTimeUnitsSeconds",
        "serviceArea_ForceHierarchyBeyondOther": "",
        "vRP_MaxFeaturesInPolygonBarriers": "",
        "vRP_MaxRoutes": "",
        "vRP_MaxFeaturesInLineBarriers": "",
        "vRP_MaxOrders": "",
        "vRP_MaxBarriers": "",
        "vRP_ForceHierarchyBeyondDistance": "",
        "vRP_ForceHierarchyBeyondDistanceUnits": "esriMeters",
        "closestFacility_MaxIncidents": "",
        "closestFacility_MaxBarriers": "",
        "closestFacility_MaxFacilities": "",
        "closestFacility_MaxFacilitiesToFind": "",
        "closestFacility_MaxFeaturesInLineBarriers": "",
        "closestFacility_MaxFeaturesInPolygonBarriers": "",
        "closestFacility_ForceHierarchyBeyondDistance": "",
        "closestFacility_ForceHierarchyBeyondDistanceUnits": "esriMeters"
      },
      "enabled": false
    },
    {
      "typeName": "VersionManagementServer",
      "capabilities": "Create,Delete,VersionInfos,LockInfos,PurgeLock,StartEditing,StopEditing,StartReading,StopReading,DeleteForwardEdits,Alter,Differences,Reconcile,Conflicts,InspectConflicts,Post,RestoreRows,Diagnostics",
      "enabled": false
    },
    {
      "typeName": "NetworkDiagramServer",
      "capabilities": "",
      "enabled": false
    },
    {
      "typeName": "KmlServer",
      "capabilities": "SingleImage,SeparateImages,Vectors",
      "properties": {
        "minRefreshPeriod": "30",
        "compatibilityMode": "GoogleEarth",
        "imageSize": "1024",
        "dpi": "96",
        "endPointURL": "",
        "featureLimit": "1000000",
        "useDefaultSnippets": false
      },
      "enabled": false
    },
    {
      "typeName": "LRServer",
      "capabilities": "",
      "enabled": false
    },
    {
      "typeName": "WMSServer",
      "capabilities": "GetCapabilities,GetMap,GetLegendGraphic,GetSchemaExtension,GetFeatureInfo,GetStyles",
      "properties": {
        "name": "WMS",
        "title": "20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png",
        "abstract": "",
        "keyword": "",
        "fees": "",
        "accessConstraints": "",
        "contactPerson": "",
        "contactPosition": "",
        "onlineResource": "https://site.int/server/services/20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png/MapServer/WMSServer",
        "contactOrganization": "",
        "contactVoiceTelephone": "",
        "contactFacsimileTelephone": "",
        "contactElectronicMailAddress": "",
        "address": "",
        "city": "",
        "stateOrProvince": "",
        "postCode": "",
        "country": "",
        "addressType": "",
        "pathToCustomGetCapabilitiesFiles": "",
        "pathToCustomSLDFile": "",
        "inheritLayerNames": false,
        "customGetCapabilities": false,
        "reaspect": false,
        "listSupportedCRS": "",
        "listCustomCRS": ""
      },
      "enabled": true
    },
    {
      "typeName": "UtilityNetworkServer",
      "capabilities": "Trace,ValidateNetworkTopology,DisableSubnetworkController,EnableSubnetworkController,UpdateSubnetwork,ExportSubnetwork,QueryNetworkMoments,UpdateIsConnected,EnableTopology,DisableTopology,SynthesizeAssociationGeometries",
      "enabled": false
    },
    {
      "typeName": "ParcelFabricServer",
      "capabilities": "Build,Merge,Clip,CopyLinesToParcelType,DeleteParcels,ChangeParcelType,DuplicateParcels,AssignFeaturesToRecord,UpdateParcelHistory,CreateSeeds,AnalyzeByLeastSquaresAdjustment,ApplyLeastSquaresAdjustment",
      "enabled": false
    },
    {
      "typeName": "FeatureServer",
      "capabilities": "Create,Query,Update,Delete,Uploads,Editing",
      "properties": {
        "zDefaultValue": "0",
        "allowOthersToDelete": false,
        "allowOthersToUpdate": false,
        "allowOthersToQuery": true,
        "enableZDefaults": false,
        "realm": "",
        "editorTrackingTimeInUTC": "true",
        "editorTrackingTimeZoneID": "UTC",
        "editorTrackingRespectsDayLightSavingTime": "false",
        "enableOwnershipBasedAccessControl": false,
        "allowGeometryUpdates": true,
        "allowUpdateWithoutMValues": false,
        "allowTrueCurvesUpdates": true,
        "xssPreventionEnabled": true,
        "includeTopologyLayer": false,
        "syncEnabled": false,
        "syncVersionCreationRule": "versionPerDownloadedMap",
        "onlyAllowTrueCurveUpdatesByTrueCurveClients": true,
        "syncBranchVersionCreationRule": "versionPerDownloadedMap"
      },
      "enabled": false
    },
    {
      "typeName": "MaritimeChartService",
      "capabilities": "",
      "properties": {
        "comments": "Not to be used for navigation.",
        "controlFilesDirectory": "C:\\arcgisserver\\directories\\maritimeserver\\maritimechartservice\\",
        "keywords": "S-57",
        "workingDirectory": "C:\\arcgisserver\\directories\\maritimeserver\\maritimechartservice\\",
        "author": "ArcGIS for Maritime Server",
        "subject": "S-57 Web Services",
        "datasetsDirectory": "C:\\arcgisserver\\directories\\maritimeserver\\maritimechartservice\\",
        "title": "Maritime Chart Service",
        "category": "S-57",
        "supportsREST": "true",
        "supportsSOAP": "false",
        "supportsInterceptor": "false"
      },
      "enabled": false
    }
  ],
  "frameworkProperties": {},
  "datasets": [],
  "_ssl": true,
  "enabled": true
}

 

 

 

This JSON dictionary is then passed to the edit() method, as in the Python script sample below, using the Python API:

 

 

 

from arcgis.gis import GIS
import json

# Login to the GIS
gis = GIS(url='https://site.int/portal/home/', username='login', password='pass', verify_cert = False)

# Access its servers
gis_servers = gis.admin.servers.list()

# Grab the first server (incase its a multi machine deployment)
server1 = gis_servers[0]
print(type(server1))
print(server1)
# Validate to confirm server is listening
gis.admin.servers.validate()

# Get folders on server
folders = server1.services.folders
print(folders)

# Confirm the service exists
serviceExists = server1.services.exists(folder_name='/', name='20210520_Pembina_127_14302_Athabasca_River_Right__South__Slope_B206_2cm_png', service_type='MapServer')
print(serviceExists)

# Get the service
service = server1.services.list(folder='/')
print(service[2])

# Edit the service
with open("serviceJSON.json") as json_file:

  data = json.load(json_file)

service[2].edit(data)


print("Complete")

 

 

 

This will update the newly published map service to enable the WMS capabilities on it.

NOTE: Minor alterations of the script will be necessary given your scenario. Most importantly is the service pulled from the List() method on line 26. My specific service I was updated was the 3rd in the list, yours will differ. 

 

Good luck :)

 

 

Tom

0 Kudos
JoeRogan
New Contributor III

In addition to Tom's solution below, I implemented a slightly different approach which basically simulates the REST requests in Server Manager.  Thanks Tom for  logging this issue and enhancement!

 

  # Turning on WMS capability starts here

  # Generate a token for accessing the REST admin
  token_response = requests.post(token_URL, data = {
    "f": "json",
    "client": "referer",
    "referer": portal_URL,
    "username": portal_pub_user,
    "password": portal_pub_pass,
    "expiration": 60
  })
  token = token_response.json()["token"]

  # Request the service data
  service_data_reponse = requests.post(service_admin_URL, data = {
    "f": "json",
    "token": token
  })
  service_data = service_data_reponse.json()

  # Enable the WMS extension and add metadata in the service description
  for extension in service_data["extensions"]:
    if (extension["typeName"] == "WMSServer"):
      extension["enabled"] = "true"
      extension["properties"]["keyword"] = ""

  # Edit the service with the new service data
  edit_response = requests.post(service_admin_URL + "/edit", data = {
    "f": "json",
    "token": token,
    "service": json.dumps(service_data),
    "runAsync": "true"
  })

  # Wait 30 seconds for the service to restart before sharing
  time.sleep(30)

  # Find and share the new WMS item in Portal
  egis = arcgis.GIS(url=portal_URL, username=portal_pub_user, password=portal_pub_pass, verify_cert=True)
  wms_items = egis.content.search(query=service_name, item_type="WMS")
  for wms_item in wms_items:
    if (wms_item.owner == portal_pub_user):
      wms_item.share(everyone=True, org=True)