Skip to content
This repository has been archived by the owner on Mar 31, 2020. It is now read-only.

3.2. Administering ArcGIS for Server site: manage services

AlexArcPy edited this page Apr 15, 2016 · 11 revisions

Now when we know how to access individual services published in ArcGIS Server site, let's see how we can manage services in batch.

###Stopping a single service What we would like to do now, is to get to the Administrator Directory page which represents the services:

http://localhost:6080/arcgis/admin/services/

This is the code we would need to get into there:

from arcrest import AGSTokenSecurityHandler
from arcrest.manageags._services import AGSService
from arcrest.manageags import AGSAdministration
ags_admin_url = r"http://localhost:6080/arcgis/admin"
ags_security_handler = AGSTokenSecurityHandler(username="psa",password="psa",org_url=ags_admin_url)
ags_obj = AGSAdministration(ags_admin_url, ags_security_handler)

This will let us perform certain administrative operations on the services, such as stop/start an individual service or do it in batch for multiple services.

Let's start with searching for a service we need.

ags_obj.services.services will return a list of AGSService objects for each service in the root, which means we can administer each service in the site individually. So, we can start administering a needed service just by getting a right AGSService object from the list. Assuming we want to access the CityStreets service (in the root):

ags_service_obj = [service for service in ags_obj.services.services if service.serviceName == 'CityStreets'][0]
ags_service_obj.serviceName
>>> 'CityStreets'

However, let's take a look at a useful method - find_services(). This will return a list of dictionaries with service names (including folders) and URL addresses.

Trying to find any MapServer services in the root:

root_services = ags_obj.services.find_services("MAPSERVER")

root_services
>>> [
{'URL': 'http://localhost:6080/arcgis/admin/services/SampleWorldCities.MAPSERVER',
  'description': 'The SampleWorldCities service is provided so you can quickly and easily preview the functionality of the GIS server. Click the thumbnail image to open in a web application. This sample service is optional and can be deleted.',
  'folderName': '/',
  'serviceName': 'SampleWorldCities',
  'type': 'MapServer'},
{'URL': 'http://localhost:6080/arcgis/admin/services/CityStreets.MAPSERVER',
  'description': 'City Streets Description',
  'folderName': '/',
  'serviceName': 'CityStreets',
  'type': 'MapServer'}
]

Note: You can get this dictionary with the services by browsing to the http://localhost:6080/arcgis/admin/services/?f=pjson page. The root folder is denoted most often as '/' in the REST API; so the "folderName": "/" means that the service is in the root. However, for some REST operations, one would supply '' for the root folder, so refer to the REST API Help when uncertain whether an empty string or '/' should be used.

Assuming we want to stop the CityStreets service (in the root), we could create a service admin object in this way:

root_services = ags_obj.services.find_services("MAPSERVER")
service_dict = [service for service in root_services if service['serviceName'] == 'CityStreets'][0]
service_dict
>>>
{'URL': 'http://localhost:6080/arcgis/admin/services/CityStreets.MAPSERVER',
  'description': 'City Streets Description',
  'folderName': '/',
  'serviceName': 'CityStreets',
  'type': 'MapServer'}

and then create an AGSService object for this service:

ags_service_obj = AGSService(url=service_dict['URL'],securityHandler=ags_security_handler)
ags_service_obj.serviceName
>>> CityStreets

Whichever way you came so far, you got the reference to the same service and can administer it now. Let's stop it:

ags_service_obj.stop_service()
>>> {'status': 'success'}

A handy way to check the state of the service is to use the property status (which contains the dictionary with the information on whether the service is started or stopped (STARTED or STOPPED):

ags_service_obj.status
>>> {u'configuredState': u'STOPPED', u'realTimeState': u'STOPPED'}

From the REST API Help page on Status:

The configured status configuredState represents the state of the resource as you have configured it to be. For example, starting a server machine or a GIS service would set its configured status to be STARTED. The status is persisted to the configuration store.

However, it is possible that the configured state may not match the actual state of the resource. The real-time status realTimeState represents the actual state of a resource. For instance, consider that you have configured the server machine to be STARTED but the machine was abruptly powered off. In this case, its real-time status would be STOPPED. The real-time status information is harvested when the request is made, and it is not persisted.

For most purposes, the real-time status should be used.

###Stopping multiple services Now when we know how to stop just one service, we could repeat this process by invoking .stopService() method for every AGService object in the list :

ags_services_obj = [service for service in ags_obj.services.services]
for service in ags_services_obj:
  service.stop_service()

Alternative way of performing a batch stop operation on multiple services is to invoke .stopServices() which you can access at http://localhost:6080/arcgis/admin/services/stopServices. However, for this method, you would need to supply a list of service dictionaries with the information about the folder it is located in, its name, and its type.

services = [{"folderName" : "",
  "serviceName" : "SampleWorldCities",
  "type" : "MapServer"
},
{"folderName" : "",
  "serviceName" : "CityStreets",
  "type" : "MapServer"
}
]
ags_obj.services.stopServices(services)
>>> {'status': 'success'}

But what if you need to stop all services not in the root, but in a certain folder? Well, this is where it would be handy to use the .findServices() method. Assuming we want to get a list of services within the Parks folder:

services_list = ags_obj.services.find_services("MAPSERVER")
services_in_folder = [service for service in services_list if service['folderName'] == 'Parks']
>>>
[{'URL': u'http://localhost:6080/arcgis/admin/services/Parks/Landmarks.MAPSERVER',
  u'description': u'',
  u'folderName': u'Parks',
  u'serviceName': u'Landmarks',
  u'type': u'MapServer'},
 {'URL': u'http://localhost:6080/arcgis/admin/services/Parks/WaterBodies.MAPSERVER',
  u'description': u'',
  u'folderName': u'Parks',
  u'serviceName': u'WaterBodies',
  u'type': u'MapServer'}]

The keys and values of the dictionaries in this list are in Unicode (the u before the name). Supplying this as JSON to the stopServices() would throw a JSON error. Basically we need to cast each of the Unicode strings into a string. A tiny function would be helpful here:

import collections
def convert(data):
  if isinstance(data, basestring):
    return str(data)
  elif isinstance(data, collections.Mapping):
    return dict(map(convert, data.iteritems()))
  elif isinstance(data, collections.Iterable):
    return type(data)(map(convert, data))
  else:
    return data

Running convert(services_in_folder) would return a list of dictionaries with the non-Unicode strings:

[{'URL': 'http://localhost:6080/arcgis/admin/services/Parks/Landmarks.MAPSERVER',
  'description': '',
  'folderName': 'Parks',
  'serviceName': 'Landmarks',
  'type': 'MapServer'},
 {'URL': 'http://localhost:6080/arcgis/admin/services/Parks/WaterBodies.MAPSERVER',
  'description': '',
  'folderName': 'Parks',
  'serviceName': 'WaterBodies',
  'type': 'MapServer'}]

We would need to iterate through each of them and stop:

services_urls = [service['URL'] for service in services_in_folder]
>>>
['http://localhost:6080/arcgis/admin/services/Parks/Landmarks.MAPSERVER',
 'http://localhost:6080/arcgis/admin/services/Parks/WaterBodies.MAPSERVER']
for url in services_urls:
	service_obj = AGSService(url, ags_security_handler)
	service_obj.stop_service()

Let's check that they are stopped:

for url in services_urls:
	service_obj = AGSService(url, ags_security_handler)
	print service_obj.status
>>>
{'configuredState': 'STOPPED', 'realTimeState': 'STOPPED'}
{'configuredState': 'STOPPED', 'realTimeState': 'STOPPED'}

An alternative approach would be to use the .stopServices() method supplying the list of dictionaries (with already converted strings) with the service details:

ags_obj.services.stopServices(convert(services_in_folder))
>>> {'status': 'success'}