Script fails to stop a service, but doesn't throw error ...?

1004
3
Jump to solution
01-25-2023 06:10 PM
Labels (1)
AllenDailey1
Occasional Contributor III

I am working on a standalone script that is supposed to stop a few geocoding services, then rebuild the address locators used in those services, then start the geocoding services. 

It is supposed to run on a standalone, non-federated ArcGIS Server (version 10.9.1) (the same server that the services were published to) in a DMZ server network.  The script is running on the server itself because machines on my internal network cannot connect with the DMZ server in the ways that are needed for this script. 

I am using the ArcGIS API for Python to stop and start the services, and I based those parts of the script on sample code from Esri.  The geocoding services were published on the ArcMap runtime, and today I created a Pro runtime geocoding service, and the script didn't stop that service either.  I am running the script in Command Prompt and sometimes in IDLE.

PROBLEM:  The script does not stop the geocoding services, yet it moves through that part of the script without throwing an error.  I can see in Server Manager online that the services are never stopped.  It only hits an error when it tries to rebuild an address locator but can't do it because the geocoding service was not actually stopped first.  

I have run out of ideas of how to troubleshoot or fix this.  I have double-checked everything I can think of to check - credentials, names and paths, etc.  The credentials being used can indeed stop the services manually in Server Manager.  Does anyone have any ideas?

Here is the core of the code:

 

 

import sys
import datetime
from arcgis.gis.server import Server  # ArcGIS API for Python
import arcpy
import keyring

if __name__ == "__main__":
    # Folder path where the locator is, not the service:
    arcpy.env.workspace = r'D:\RootFolder\OtherFolder'
    # Name of folder in the Server Manager where the locator lives:
    folder_folder_name = 'MyFolder' # File Explorer folder name
    ags_folder_name = 'MY_FOLDER' # ArcGIS Server Manager folder name
    # Base URL of the ArcGIS Server where the service lives:
    server_base_url = r'https://myserverbaseurl:port'
    # Names of the locators (not services):
    locator_name_list = ['LOCATOR_ROAD', 'LOCATOR_POINTS', 'LOCATOR_ADDR']
    # Names of the geocoding services published to the server:
    locservice1 = 'MY_FAV_SERVICE'  
    locservice2 = 'THE_OTHER_SERVICE'

    username = keyring.get_password('name', 'user')
    pw = keyring.get_password('other_name', 'password')

    # Create an instance of a Server object in ArcGIS API for Python.
    server = Server(url='{}/arcgis/admin'.format(server_base_url), username=username, password=pw)
    # Access server content (ArcGIS API for Python)
    cdir = server.content
    # Instantiate the services as service objects
    service1 = cdir.get(locservice1, folder=ags_folder_name)
    service2 = cdir.get(locservice2, folder=ags_folder_name)

    # TEST - this worked.
    #print(service1.service.iteminformation)
    #print(cdir) # This worked.
    
    # Stop the geocoding services in order to next rebuild the locators
    service1.service.stop()
    service2.service.stop()

    # Rebuild the locators. 
    for locator_name in locator_name_list:
        print(locator_name)
        arcpy.geocoding.RebuildAddressLocator(locator_name)
    
    # Start the services after rebuilding. (ArcGIS API for Python)
    service1.service.start()
    service2.service.start()

 

 

 

1 Solution

Accepted Solutions
AllenDailey1
Occasional Contributor III

Update - I figured it out.  I submitted a help request to Esri, and they tested my code and it worked in their environment.  So then I tried to drill deeper into possible issues other than the code itself.  I eventually discovered that on our DMZ servers, the account that is running the script (i.e. the account being used to run software like IDLE, Command Prompt, Pro, etc.) has to be the account that enters the credentials - used as an argument for the Server object - into Windows Credential Manager.  We are using Keyring to get the credentials from Windows Credential Manager in order to avoid hard-coding them in the script, which would be a security risk.  The account I need to use to run the script is different from the account whose credentials have to be passed into the Server object.  I ran Command Prompt as the account used to run the script, and in Command Prompt I used Python keyring to set_password for the credentials to be called in the Server object.  It seems that in our server environment, an account cannot access credentials that someone else (a different account) entered into Windows Credential Manager.  

Now the script is able to stop and start services!

This issue will probably only apply to a miniscule number of people out there, but it would be cool if this could help at least one other person!

View solution in original post

3 Replies
bbaker_tngeo
New Contributor III

I was working on a similar thing this week and found 2 different esri samples and combined them. I don't know if this is helpful, but the code below works with a locator published in ArcGIS Pro but the server is federated, if that makes a difference. The code is probably a bit clunky, I am planning to expand this to the entire folder of locators instead of just one, once I upgrade the rest to Pro and now know that it works.

How to start/stop a service: https://support.esri.com/en/technical-article/000019994

Rebuild address locator: https://pro.arcgis.com/en/pro-app/2.9/tool-reference/geocoding/rebuild-address-locator.htm

 

 

 

 

from arcgis.gis import GIS
import arcgis.gis.admin
import arcpy

portal = "portalurl"
userName = "user"
password = "password"


gis = GIS(portal, userName, password)

gis_servers = gis.admin.servers.list()

#To stop specific service(s)
for server in gis_servers:
    for service in server.services.list(folder="Locators"): #Specify folder
        if service.properties.serviceName == "Locator_Name": #Only specify a serviceName if one service is to be stopped; otherwise the entire folder will be stopped
            service.stop() 


arcpy.env.workspace = "C://folder/path"
 
locator1 = "Locator_Name"

arcpy.RebuildAddressLocator_geocoding(locator1)


for server in gis_servers:
    for service in server.services.list(folder="Locators"): #Specify folder
        if service.properties.serviceName == "Locator_Name": #Only specify a serviceName if one service is to be started; otherwise the entire folder will be stopped
            service.start()

 

0 Kudos
AllenDailey1
Occasional Contributor III

Thank you for your reply!  I believe that the GIS object cannot be used with standalone servers, only the Server object can. But I really appreciate your reply.

0 Kudos
AllenDailey1
Occasional Contributor III

Update - I figured it out.  I submitted a help request to Esri, and they tested my code and it worked in their environment.  So then I tried to drill deeper into possible issues other than the code itself.  I eventually discovered that on our DMZ servers, the account that is running the script (i.e. the account being used to run software like IDLE, Command Prompt, Pro, etc.) has to be the account that enters the credentials - used as an argument for the Server object - into Windows Credential Manager.  We are using Keyring to get the credentials from Windows Credential Manager in order to avoid hard-coding them in the script, which would be a security risk.  The account I need to use to run the script is different from the account whose credentials have to be passed into the Server object.  I ran Command Prompt as the account used to run the script, and in Command Prompt I used Python keyring to set_password for the credentials to be called in the Server object.  It seems that in our server environment, an account cannot access credentials that someone else (a different account) entered into Windows Credential Manager.  

Now the script is able to stop and start services!

This issue will probably only apply to a miniscule number of people out there, but it would be cool if this could help at least one other person!