Start Stop Map Service arcpy

15796
24
Jump to solution
11-17-2016 10:56 AM
jaykapalczynski
Frequent Contributor

Is there a way to stop and start a map/feature service in ArcGIS Server via python?

24 Replies
jaykapalczynski
Frequent Contributor

Im trying to below....BUT I only want to hit a single service....

In ArcGIS Server Manager  Site:Folder X  Individual Service: D

Not sure if I can configure that in the ServiceList parameter which is supported to follow format: 

 serviceList = List of services. A service must be in the <name>.<type> notation

Dont know my port number or where to find it

'''
This script will stop or start all selected services

==Inputs==
ServerName
Port
AdminUser
AdminPassword (sent in clear text)
Stop or Start 
Service(s) (multivalue list)
'''

import urllib, urllib2, json
import arcpy


def gentoken(server, port, adminUser, adminPass, expiration=60):
    #Re-usable function to get a token required for Admin changes
    
    query_dict = {'username':   adminUser,
                  'password':   adminPass,
                  'expiration': str(expiration),
                  'client':     'requestip'}
    
    query_string = urllib.urlencode(query_dict)
    url = "http://{}:{}/arcgis/admin/generateToken".format(server, port)
    
     #https://vafwisdev.dgif.virginia.gov/arcgis/admin
     
    token = json.loads(urllib.urlopen(url + "?f=json", query_string).read())
        
    if "token" not in token:
        arcpy.AddError(token['messages'])
        quit()
    else:
        return token['token']


def stopStartServices(server, port, adminUser, adminPass, stopStart, serviceList, token=None):  
    ''' Function to stop, start or delete a service.
    Requires Admin user/password, as well as server and port (necessary to construct token if one does not exist).
    stopStart = Stop|Start|Delete
    serviceList = List of services. A service must be in the <name>.<type> notation
    If a token exists, you can pass one in for use.  
    '''    
    
    # Get and set the token
    if token is None:       
        token = gentoken(server, port, adminUser, adminPass)
    
    # Getting services from tool validation creates a semicolon delimited list that needs to be broken up
    services = serviceList.split(';')
    
    #modify the services(s)    
    for service in services:        
        service = urllib.quote(service.encode('utf8'))
        op_service_url = "http://{}:{}/arcgis/admin/services/{}/{}?token={}&f=json".format(server, port, service, stopStart, token)        
        status = urllib2.urlopen(op_service_url, ' ').read()
        
        if 'success' in status:
            arcpy.AddMessage(str(service) + " === " + str(stopStart))
        else:
            arcpy.AddWarning(status)
    
    return 


if __name__ == "__main__": 
    
    # Gather inputs    
    server = arcpy.GetParameterAsText(0) 
    port = arcpy.GetParameterAsText(1) 
    adminUser = arcpy.GetParameterAsText(2) 
    adminPass = arcpy.GetParameterAsText(3) 
    stopStart = arcpy.GetParameter(4) 
    serviceList = arcpy.GetParameterAsText(5) 
    
    stopStartServices(server, port, adminUser, adminPass, stopStart, serviceList)
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
CallumSmith2
Occasional Contributor

Jay have a look at the following code. This is something I have just cobbled together quickly. There are obviously "more that one way to skin a cat" so please dont take this as gospel.

All you should have to do is:

1. install the request module.

2. Enter a username and password for you server environment. i.e. what you use to log into arcgis server manager.

3. Enter a token url. This will be either a server a portal token depending if your environment is federated or not.

4. A admin url for your service you want to stop.

# Stop Service

import sys
import os
import logging
import json

sys.path.append(r'\\works.co.nz\app\GISProjects\scripts\Dev\Framework\Modules')
import requests
requests.packages.urllib3.disable_warnings()
logging.getLogger('requests.packages.urllib3').setLevel(logging.CRITICAL)

# Parameters
username = ''   # Username for your Server
password = '' # PAssword for your Server

tokenURL = ''   # URL to generate token (Portal or server depending if federated or not)
serviceURL = ''   # URL for service to stop

try:
    # Generate a Token
    payload = { 'username': username, 'password': password, 'expiration': '60', 'referer': 'https://www.google.com', 'request': 'gettoken', 'f': 'json' }
    r = json.loads(requests.post(tokenURL, data=payload).content)

    # If valid token
    if 'token' in r:
        token = r.get('token', None)

        # Now Stop the Service
        url = serviceURL + '/' + 'stop'
        payload = {'f':'json',
                  'token':token}

        r = json.loads(requests.post(url, data=payload).content)

        if r.get('status', False):
            print 'Service Stopped Sucessfully.'
        else:
            print 'Error encountered Stopping Service'
    else:
        print 'Unable to generate Token'

except Exception, e:
    print e

cheers

Callum

jaykapalczynski
Frequent Contributor

Error:
Traceback (most recent call last):
File "C:\Users\adminjk\Desktop\PythonSync\ServerAdminToolkit\StopService.py", line 9, in <module>
import requests
ImportError: No module named requests
>>>

sys.path.append(r'\\works.co.nz\app\GISProjects\scripts\Dev\Framework\Modules')
import requests
requests.packages.urllib3.disable_warnings()
logging.getLogger('requests.packages.urllib3').setLevel(logging.CRITICAL)

0 Kudos
CallumSmith2
Occasional Contributor

Have you installed the requests module? requests 2.11.1 : Python Package Index 

Once you have it installed it should work. NOTE: you can probably remove the (sys.path.append) line as that is because we have the requests module installed in a location where python would not normally look. It also helps for running scripts from multiple machines and not having to install the module locally on each machine.

cheers

Callum

jaykapalczynski
Frequent Contributor

download "requests-2.11.1-py-none-any.whl" ?

huh

Installation

To install Requests, simply:

$ pip install requests ✨  ✨

Satisfaction, guaranteed.

I am so very confused...install this.  install where? install how?  ugggg

CallumSmith2
Occasional Contributor

OK you need to install pip.

1. On the web search for get-pip.py, download it and place it in your python installation folder e.g. "C:\python27\arcGIs10.4"

2. On a command shell navigate to the python install folder and type "python get-pip.py" NOTE: if you have a proxy server add the flag --proxy {proxy details}

3. pip will be installed in the scripts folder e.g. "C:\python27\arcGIs10.4\scripts"

4. Download the "requests-2.11.1.tar.gz (md5)" from the requests site https://pypi.python.org/pypi/requests/2.11.1#downloads 

5. in a command shell navigate to "C:\python27\arcGIs10.4\scripts" (Where pip is installed) and type the following command to install the requests module "pip install {path to requests-2.11.1.tar.gz (md5)}. If you have a proxy server use the proxy flag as you did above.

Requests will now be installed and you van now use pip to install other modules.

cheers

Callum

jaykapalczynski
Frequent Contributor

I have to install a software -  to install aother software - just to stop a service...ok trying...

BlakeTerhune
MVP Regular Contributor

Lots of useful info has already been posted, it can just be a chore to sort through it to get exactly what you need. This is compounded by the fact that there are always many different ways to do the same thing and makes it extra confusing. Here is the Python code I use to start/stop a single service. It uses all built-in modules so there's no need to install anything extra.

"""Based on these 2014 resources by Kevin Hibma (Product Engineer at Esri):
ArcGIS Server Administration Toolkit - 10.1+
    http://www.arcgis.com/home/item.html?id=12dde73e0e784e47818162b4d41ee340
AdministeringArcGISServerwithPython_DS2014
    https://github.com/arcpy/AdministeringArcGISServerwithPython_DS2014

Other related information can be found in the ArcGIS Help Resources
  Scripting with the ArcGIS REST API
      http://resources.arcgis.com/en/help/main/10.2/0154/0154000005r1000000.htm
"""

# Required imports
import urllib
import urllib2
import json
import contextlib  ## context manager to clean up resources when exiting a 'with' block

def main():  ## Entry point into the script
    # Local variables
    ## Authentication
    adminUser = r"someuser"
    adminPass = r"passw0rd"
    ## ArcGIS Server Machine
    server = "SERVERNAME"
    port = "6080"
    ## Services ("FolderName/ServiceName.ServiceType")
    svc = "SampleWorldCities.MapServer"

    try:
        # Get ArcGIS Server token
        expiration = 60  ## Token timeout in minutes; default is 60 minutes.
        token = getToken(adminUser, adminPass, server, port, expiration)

        # Perform action on service
        action = "start"  ## "start" or "stop"
        jsonOuput = serviceStartStop(server, port, svc, action, token)
        ## Validate JSON object result
        if jsonOuput['status'] == "success":
            print "{} {} successful".format(action.title(), str(svc))
        else:
            print "Failed to {} {}".format(action, str(svc))
            raise Exception(jsonOuput)

    except Exception, err:
        print err


# Function to generate a token from ArcGIS Server; returns token.
## http://resources.arcgis.com/en/help/arcgis-rest-api/02r3/02r3000000m5000000.htm
def getToken(adminUser, adminPass, server, port, expiration):
    # Build URL
    url = "http://{}:{}/arcgis/admin/generateToken?f=json".format(server, port)

    # Encode the query string
    query_dict = {
        'username': adminUser,
        'password': adminPass,
        'expiration': str(expiration),  ## Token timeout in minutes; default is 60 minutes.
        'client': 'requestip'
    }
    query_string = urllib.urlencode(query_dict)

    try:
        # Request the token
        with contextlib.closing(urllib2.urlopen(url, query_string)) as jsonResponse:
            getTokenResult = json.loads(jsonResponse.read())
            ## Validate result
            if "token" not in getTokenResult or getTokenResult == None:
                raise Exception("Failed to get token: {}".format(getTokenResult['messages']))
            else:
                return getTokenResult['token']

    except urllib2.URLError, e:
        raise Exception("Could not connect to machine {} on port {}\n{}".format(server, port, e))


# Function to start or stop a service on ArcGIS Server; returns JSON response.
## http://resources.arcgis.com/en/help/arcgis-rest-api/02r3/02r3000001s6000000.htm
def serviceStartStop(server, port, svc, action, token):
    # Build URL
    url = "http://{}:{}/arcgis/admin".format(server, port)
    requestURL = url + "/services/{}/{}".format(svc, action)

    # Encode the query string
    query_dict = {
        "token": token,
        "f": "json"
    }
    query_string = urllib.urlencode(query_dict)

    # Send the server request and return the JSON response
    with contextlib.closing(urllib.urlopen(requestURL, query_string)) as jsonResponse:
        return json.loads(jsonResponse.read())


if __name__ == '__main__':
    main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
CallumSmith2
Occasional Contributor

Agreed. Everything you need should be on this posting. Basically as Blake has eluded to there are many different ways to achieve what you want. Its just a matter of working through the options and using the one you are most comfortable with.

cheers

Callum

jaykapalczynski
Frequent Contributor

Golden.....got it to work....THANK YOU ALL...went with Blakes solution...

"""Based on these 2014 resources by Kevin Hibma (Product Engineer at Esri):
ArcGIS Server Administration Toolkit - 10.1+
http://www.arcgis.com/home/item.html?id=12dde73e0e784e47818162b4d41ee340
AdministeringArcGISServerwithPython_DS2014
https://github.com/arcpy/AdministeringArcGISServerwithPython_DS2014
Other related information can be found in the ArcGIS Help Resources
Scripting with the ArcGIS REST API
http://resources.arcgis.com/en/help/main/10.2/0154/0154000005r1000000.htm
"""
# Required imports
import urllib
import urllib2
import json
import contextlib ## context manager to clean up resources when exiting a 'with' block
def main(): ## Entry point into the script
# Local variables
## Authentication
adminUser = r"xxxx"
adminPass = r"xxxx"
## ArcGIS Server Machine
server = "xxxxdev.xxxx.xxxx.gov"
port = "443"
## Services ("FolderName/ServiceName.ServiceType")
svc = "Test/xInspection.MapServer"

try:
# Get ArcGIS Server token
expiration = 60 ## Token timeout in minutes; default is 60 minutes.
token = getToken(adminUser, adminPass, server, port, expiration)
# Perform action on service
action = "stop" ## "start" or "stop"
jsonOuput = serviceStartStop(server, port, svc, action, token)
## Validate JSON object result
if jsonOuput['status'] == "success":
print "{} {} successful".format(action.title(), str(svc))
else:
print "Failed to {} {}".format(action, str(svc))
raise Exception(jsonOuput)
except Exception, err:
print err

# Function to generate a token from ArcGIS Server; returns token.
## http://resources.arcgis.com/en/help/arcgis-rest-api/02r3/02r3000000m5000000.htm
def getToken(adminUser, adminPass, server, port, expiration):
# Build URL
url = "https://{}:{}/arcgis/admin/generateToken?f=json".format(server, port)
print (url)

# Encode the query string
query_dict = {
'username': adminUser,
'password': adminPass,
'expiration': str(expiration), ## Token timeout in minutes; default is 60 minutes.
'client': 'requestip'
}
query_string = urllib.urlencode(query_dict)
try:
# Request the token
with contextlib.closing(urllib2.urlopen(url, query_string)) as jsonResponse:
getTokenResult = json.loads(jsonResponse.read())
## Validate result
if "token" not in getTokenResult or getTokenResult == None:
raise Exception("Failed to get token: {}".format(getTokenResult['messages']))
else:
return getTokenResult['token']
except urllib2.URLError, e:
raise Exception("Could not connect to machine {} on port {}\n{}".format(server, port, e))

# Function to start or stop a service on ArcGIS Server; returns JSON response.
## http://resources.arcgis.com/en/help/arcgis-rest-api/02r3/02r3000001s6000000.htm
def serviceStartStop(server, port, svc, action, token):
# Build URL
url = "https://{}:{}/arcgis/admin".format(server, port)
requestURL = url + "/services/{}/{}".format(svc, action)
# Encode the query string
query_dict = {
"token": token,
"f": "json"
}
query_string = urllib.urlencode(query_dict)

# Send the server request and return the JSON response
with contextlib.closing(urllib.urlopen(requestURL, query_string)) as jsonResponse:
return json.loads(jsonResponse.read())

if __name__ == '__main__':
main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos