No JSON object could be decoded - StartStopServices.py

5769
12
10-11-2016 03:31 AM
DilsonKitoko
New Contributor III

I'm trying to run a python scrtipt to stop services, but I'm getting the following error message : "No JSON object could be decoded" . My server uses https protocol thru port 6443. I'm using the file "StartStopServices.py" available at following path: https://github.com/WestonSF/ArcGISAdminToolkit/commit/a183df77441956e515105b2b166b11eb4e525873

#-------------------------------------------------------------
# Name:       Start or Stop Services
# Purpose:    Starts or stops GIS services. Can start/stop all GIS services for an ArcGIS server site or just the ones
#             that are specified.
# Author:     Shaun Weston (shaun_weston@eagle.co.nz)
# Date Created:    07/10/2014
# Last Updated:    06/11/2014
# Copyright:   (c) Eagle Technology
# ArcGIS Version:   10.1+
# Python Version:   2.7
#--------------------------------

# Import modules
import os
import sys
import logging
import smtplib
import arcpy
import httplib
import json
import urllib
import urllib2
import urlparse


# Enable data to be overwritten
arcpy.env.overwriteOutput = True

# Set global variables
enableLogging = "false" # Use logger.info("Example..."), logger.warning("Example..."), logger.error("Example...")
logFile = "" # os.path.join(os.path.dirname(__file__), "Example.log")
sendErrorEmail = "false"
emailTo = ""
emailUser = ""
emailPassword = ""
emailSubject = ""
emailMessage = ""
output = None

# Start of main function
def mainFunction(agsServerSite,username,password,startStop,allServices,userServices): # Get parameters from ArcGIS Desktop tool by seperating by comma e.g. (var1 is 1st parameter,var2 is 2nd parameter,var3 is 3rd parameter)  
    try:
        # Logging
        if (enableLogging == "true"):
            # Setup logging
            logger, logMessage = setLogging(logFile)
            # Log start of process
            logger.info("Process started.")
            
        # --------------------------------------- Start of code --------------------------------------- #


        # Get the server site details
        protocol, serverName, serverPort, context = splitSiteURL(agsServerSite)



        # If any of the variables are blank
        if (serverName == None or serverPort == None or protocol == None or context == None):
            return -1


        # Add on slash to context if necessary
        if not context.endswith('/'):
            context += '/'


        # Add on admin to context if necessary   
        if not context.endswith('admin/'):
            context += 'admin/'
            
        # Get token
        token = getToken(username, password, serverName, serverPort)


        # If token received
        if (token != -1):
            services = []    
            folder = ''



            # If task is for all services
            if (allServices == "true"):                
                # Query the root level for services            
                url = "http://{}:{}/arcgis/admin/services{}?f=pjson&token={}".format(serverName, serverPort, folder, token)   


                # Make the request 
                try:
                    serviceList = json.loads(urllib2.urlopen(url).read())
                except urllib2.URLError, error:
                    arcpy.AddError(error)
                    # Logging
                    if (enableLogging == "true"):
                        logger.error(error)                    
                    sys.exit()


                # Add the services at the root level
                for single in serviceList["services"]:
                    services.append(single['serviceName'] + '.' + single['type'])
                    
                # Build up list of folders and remove the System and Utilities folder
                folderList = serviceList["folders"]
                folderList.remove("Utilities")             
                folderList.remove("System")


                # If there is any folders
                if len(folderList) > 0:
                    # For each folder in the list
                    for folder in folderList:
                        # Query the folder for map services
                        URL = "http://{}:{}/arcgis/admin/services/{}?f=pjson&token={}".format(serverName, serverPort, folder, token)    
                        fList = json.loads(urllib2.urlopen(URL).read())
                        
                        for single in fList["services"]:
                            # Add the services found to the list
                            services.append(folder + "/" + single['serviceName'] + '.' + single['type'])
            # Just for the user defined list of services
            else:
                services = userServices.split(",")
                
            # For each of the services
            for service in services:
                # Start or stop the map service
                op_service_url = "http://{}:{}/arcgis/admin/services/{}/{}?token={}&f=json".format(serverName, serverPort, service, startStop, token)
                status = urllib2.urlopen(op_service_url, ' ').read()


                # If successfully started/stopped                    
                if 'success' in status:
                    arcpy.AddMessage(startStop + " successfully performed on " + service)
                    # Logging
                    if (enableLogging == "true"):
                        logger.error(startStop + " successfully performed on " + service)
                # If there is an error
                else: 
                    arcpy.AddError("Failed to perform operation. Returned message from the server:")
                    arcpy.AddError(status)
                    # Logging
                    if (enableLogging == "true"):
                        logger.error("Failed to perform operation. Returned message from the server:")
                        logger.error(status)

        
        # --------------------------------------- End of code --------------------------------------- #  
            
        # If called from gp tool return the arcpy parameter   
        if __name__ == '__main__':
            # Return the output if there is any
            if output:
                arcpy.SetParameterAsText(1, output)
        # Otherwise return the result          
        else:
            # Return the output if there is any
            if output:
                return output      
        # Logging
        if (enableLogging == "true"):
            # Log end of process
            logger.info("Process ended.")
            # Remove file handler and close log file            
            logging.FileHandler.close(logMessage)
            logger.removeHandler(logMessage)
        pass
    # If arcpy error
    except arcpy.ExecuteError:           
        # Build and show the error message
        errorMessage = arcpy.GetMessages(2)   
        arcpy.AddError(errorMessage)           
        # Logging
        if (enableLogging == "true"):
            # Log error          
            logger.error(errorMessage)                 
            # Remove file handler and close log file
            logging.FileHandler.close(logMessage)
            logger.removeHandler(logMessage)
        if (sendErrorEmail == "true"):
            # Send email
            sendEmail(errorMessage)
    # If python error
    except Exception as e:
        errorMessage = ""
        # Build and show the error message
        for i in range(len(e.args)):
            if (i == 0):
                errorMessage = unicode(e.args[i]).encode('utf-8')
            else:
                errorMessage = errorMessage + " " + unicode(e.args[i]).encode('utf-8')
        arcpy.AddError(errorMessage)              
        # Logging
        if (enableLogging == "true"):
            # Log error            
            logger.error(errorMessage)               
            # Remove file handler and close log file
            logging.FileHandler.close(logMessage)
            logger.removeHandler(logMessage)
        if (sendErrorEmail == "true"):
            # Send email
            sendEmail(errorMessage)            
# End of main function


# Start of get token function
def getToken(username, password, serverName, serverPort):
    
    query_dict = {'username':   username,
                  'password':   password,
                  'expiration': "60",
                  'client':     'requestip'}
    
    query_string = urllib.urlencode(query_dict)
    url = "http://{}:{}/arcgis/admin/generateToken?f=json".format(serverName, serverPort)
   
    try:
        token = json.loads(urllib2.urlopen(url, query_string).read())
        if "token" not in token or token == None:
            arcpy.AddError("Failed to get token, return message from server:")
            arcpy.AddError(token['messages'])            
            # Logging
            if (enableLogging == "true"):   
                logger.error("Failed to get token, return message from server:")
                logger.error(token['messages'])                
            sys.exit()
        else:
            # Return the token to the function which called for it
            return token['token']
    
    except urllib2.URLError, error:
        arcpy.AddError("Could not connect to machine {} on port {}".format(serverName, serverPort))
        arcpy.AddError(error)
        # Logging
        if (enableLogging == "true"):   
            logger.error("Could not connect to machine {} on port {}".format(serverName, serverPort))
            logger.error(error)         
        sys.exit()
# End of get token function


# Start of HTTP POST request to the server function
def postToServer(serverName, serverPort, protocol, url, params):
    # If on standard port
        if (serverPort == -1 and protocol == 'http'):
            serverPort = 80
            
    # If on secure port
        if (serverPort == -1 and protocol == 'https'):
            serverPort = 6443
            
        if (protocol == 'http'):
            httpConn = httplib.HTTPConnection(serverName, int(serverPort))




        if (protocol == 'https'):
            httpConn = httplib.HTTPSConnection(serverName, int(serverPort))




        headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain",'referer':'backuputility','referrer':'backuputility'}



    # URL encode the resource URL
        url = urllib.quote(url.encode('utf-8'))




    # Build the connection to add the roles to the server
        httpConn.request("POST", url, params, headers)




        response = httpConn.getresponse()
        data = response.read()




        httpConn.close()





        # Return response
        return (response, data)
# End of HTTP POST request to the server function 
        
            
# Start of split URL function 
def splitSiteURL(siteURL):
    try:
        serverName = ''
        serverPort = -1
        protocol = 'http'
        context = '/arcgis'
        # Split up the URL provided
        urllist = urlparse.urlsplit(siteURL)
        # Put the URL list into a dictionary
        d = urllist._asdict()




        # Get the server name and port
        serverNameAndPort = d['netloc'].split(":")




        # User did not enter the port number, so we return -1
        if (len(serverNameAndPort) == 1):
            serverName = serverNameAndPort[0]
        else:
            if (len(serverNameAndPort) == 2):
                serverName = serverNameAndPort[0]
                serverPort = serverNameAndPort[1]




        # Get protocol
        if (d['scheme'] is not ''):
            protocol = d['scheme']




        # Get path
        if (d['path'] is not '/' and d['path'] is not ''):
            context = d['path']




        # Return variables
        return protocol, serverName, serverPort, context  
    except:
        arcpy.AddError("The ArcGIS Server site URL should be in the format http(s)://<host>:<port>/arcgis")
        # Logging
        if (enableLogging == "true"):      
            logger.error("The ArcGIS Server site URL should be in the format http(s)://<host>:<port>/arcgis")
            sys.exit()
        return None, None, None, None
# End of split URL function


# Start of status check JSON object function


def assertJsonSuccess(data):
    obj = json.loads(data)
    if 'status' in obj and obj['status'] == "error":
        if ('messages' in obj):
            errMsgs = obj['messages']
            for errMsg in errMsgs:


                arcpy.AddError(errMsg)



                # Logging
                        
                if (enableLogging == "true"):


                    logger.error(errMsg)
                    
            sys.exit()
            
        return False
        
    else:
            
        return True
                 
# End of status check JSON object function



# Start of set logging function
def setLogging(logFile):
    # Create a logger
    logger = logging.getLogger(os.path.basename(__file__))
    logger.setLevel(logging.DEBUG)
    # Setup log message handler
    logMessage = logging.FileHandler(logFile)
    # Setup the log formatting
    logFormat = logging.Formatter("%(asctime)s: %(levelname)s - %(message)s", "%d/%m/%Y - %H:%M:%S")
    # Add formatter to log message handler
    logMessage.setFormatter(logFormat)
    # Add log message handler to logger
    logger.addHandler(logMessage)


    return logger, logMessage               
# End of set logging function


# Start of send email function
def sendEmail(message):
    # Send an email
    arcpy.AddMessage("Sending email...")
    # Server and port information
    smtpServer = smtplib.SMTP("smtp.gmail.com",587) 
    smtpServer.ehlo()
    smtpServer.starttls() 
    smtpServer.ehlo
    # Login with sender email address and password
    smtpServer.login(emailUser, emailPassword)
    # Email content
    header = 'To:' + emailTo + '\n' + 'From: ' + emailUser + '\n' + 'Subject:' + emailSubject + '\n'
    body = header + '\n' + emailMessage + '\n' + '\n' + message
    # Send the email and close the connection
    smtpServer.sendmail(emailUser, emailTo, body)    
# End of send email function


# This test allows the script to be used from the operating
# system command prompt (stand-alone), in a Python IDE, 
# as a geoprocessing script tool, or as a module imported in
# another script
if __name__ == '__main__':
    # Arguments are optional - If running from ArcGIS Desktop tool, parameters will be loaded into *argv
    argv = tuple(arcpy.GetParameterAsText(i)
        for i in range(arcpy.GetArgumentCount()))
    mainFunction(*argv)
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


   

Tags (1)
0 Kudos
12 Replies
JonathanQuinn
Esri Notable Contributor

That's definitely JSON, so I'm not sure why the error is being thrown.  The thing I haven't seen before is how you're constructing the parameters for the getToken request.

url = "https://{}:{}/arcgis/admin/generateToken?f=json".format(server, port)
query_dict = {
        'username': adminUser,
        'password': adminPass,
        'expiration': str(expiration),
        'client': 'requestip'
    }

f=json is a parameter sent along with the request, so it should be included in the query_dict:

url = "https://{}:{}/arcgis/admin/generateToken".format(server, port)
query_dict = {
        'username': adminUser,
        'password': adminPass,
        'expiration': str(expiration),
        'client': 'requestip',
        'f':'json'
    }

What if you give that a try?

0 Kudos
CraigPrisland2
New Contributor III

Jonathan,

Thanks for the suggestion.  When I tested this out, I was still getting the same error.  However,  I was able to successfully run this script by updating lines 56-57 a little:

    try:
        # Request the token
        with contextlib.closing(urllib2.urlopen(url, query_string)) as jsonResponse:
            response = jsonResponse.read()
            print response
            getTokenResult = json.loads(response)

Craig

0 Kudos
JonathanQuinn
Esri Notable Contributor

Hm, not sure why turning the string to a JSON object couldn't be done in one line, but glad it's working now!

0 Kudos