Identify which map services are locking feature class

I actually just created something to do this recently, and plan on implementing it as part of my restapi package eventually once I add more utilities. I just added this serverAdminTools module to GitHub.

To access it, just clone the repo. For finding all services that contain a layer or SDE workspace, you can do the following:

import serverAdminTools   #make sure this is in your PYTHONPATH or use sys.path.append()

url = 'http://gisserver.yourdomain:6080/arcgis/admin/services'

# initialize helper class by loggin in to the ArcGIS Server instance
server = ServerAdministrator(url, 'username', 'password')

# find services that have the parcels layer from this sde database
ws = r'\\arcserver2\SDE_Connections\MN_GIS_LIS.sde'
feature_classes = ['MN_GIS_LIS.DBO.Parcels']
matching = server.find_services_containing(ws, feature_classes)

print matching

This printed the following:

{
  'feature_classes': {
    'MN_GIS_LIS.DBO.Parcels': [{
      'serviceObj': < Service: Duluth_Parcels.MapServer > ,
      'name': 'Duluth_Parcels'
    }]
  },
  'workspace': [{
    'serviceObj': < Service: Duluth_Parcels.MapServer > ,
    'name': 'Duluth_Parcels'
  }]
}

Where the workspace array lists all the services that reference that workspace, and then the feature classes array lists all the services that contain the feature classes that get passed in the list (2nd parameter). The serviceObj in each JSON structure is a reference to a Service in the restapi.admin module.

The find_services_containing() method also supports a third argument to automatically stop the services as they are found. So you can do stuff after you stop the services and restart when you're done. The ServerAdministrator will actually keep track of services that have been stopped within the instance, so you can do some stuff then call startStoppedServices() and they will all be started.

So you can do something like this:

matching = server.find_services_containing(ws, feature_classes, True) # third param is option to stop services, is False by default

# make schema changes to your feature classes
# do more stuff

# now restart the stopped services 
server.startStoppedServices()

# now all services should be up and running (this operation can take a while)

The only other utility I have so far is one to stop a service and compress all databases inside it. It will check for all the unique workspaces in a service, stop the service, run the compress on all relevant databases, and then restart the service. It takes two arguments where the first is a path to your SDE connection files then the service name:

# stop service and compress
sde_dir = r'\\arcserver2\SDE_Connections'
service.stopServiceAndCompressDatabase(sde_dir, 'Duluth_Parcels')

I hope this helps! This has been a huge time saver for my organization.

EDIT:

I changed the source code to use the service manifest.

UPDATE:

This has now been added to the version 1.0 branch of restapi, as as part of the admin sub-package and will soon be merged with the master branch. This is available through restapi like this:

from restapi.admin import utils 
server = utils.ServerAdministrator(server_url, 'username', 'password')
ws = r'\\arcserver2\SDE_Connections\MN_GIS_LIS.sde'
fcs = ['MN_GIS_LIS.DBO.Parcels']
matching = server.find_services_containing(ws, fcs)
print matching