Finding Sasquatch with Pro and Python

777
1
08-28-2019 06:45 AM
ThomasColson
MVP Frequent Contributor
4 1 777

In order to support a very large number of map consumers, that don't ever edit anything or create data, I rely on AGOL to host Map (Hosted Feature Services), hook those back to Portal as "Items", and keep my ArcGIS Server Farm service instances low, only spawning what is needed to support editors. Through security controls, the map service that automatically comes with a feature services is un-discoverable. I don't want people hitting the map services and spawning more service instances. This is in effect a "Collaboration"for people that can't enable Collaboration on their Portal. 

https://www.esri.com/arcgis-blog/products/api-python/analytics/updating-your-hosted-feature-services... has been pretty handy for the past few years, via a scheduled task, it updates (nightly) several hundred feature services by pulling data from SDE into a Pro Project and overwriting what's on AGOL. Unfortunately, it doesn't allow you to preserve "Allow Export to other formats" setting on AGOL. 

Enter https://pro.arcgis.com/en/pro-app/arcpy/sharing/introduction-to-arcpy-sharing.htm, which I've finally rolled my sleeves up on and have converted all my python doo-hickeys to use https://pro.arcgis.com/en/pro-app/arcpy/sharing/featuresharingdraft-class.htmhttps://pro.arcgis.com/en/pro-app/tool-reference/server/stage-service.htm, and https://pro.arcgis.com/en/pro-app/tool-reference/server/upload-service-definition.htm. Coincidentally there's a lot more options to control service parameters. 

Disclaimer: I know nothing about python, so I'm sure there's all sorts of inefficiencies in here, but it works. 

import arcpy
import sys, string, os, calendar, datetime, traceback,smtplib
from arcpy import env
from subprocess import call

# Mail Server Settings
service = "GRSM_SASQUATCH"
sd_filename = service + ".sd"
try:
    d = datetime.datetime.now()
    log = open("C:\\PYTHON_LOGS\LOG."+service+".txt","a")
    log.write("----------------------------" + "\n")
    log.write("----------------------------" + "\n")
    log.write("Log: " + str(d) + "\n")
    log.write("\n")
# Start process...
    starttime = datetime.datetime.now()
    log.write("Begin process:\n")
    log.write("     Process started at " + str(starttime) + "\n")
    log.write("\n")
    
    # Mail Server Settings
    SERVER = "1.2.34"
    PORT = "25"
    FROM = "sasquatch@big.foot.com"
    MAILDOMAIN = '@big.foot.com'
    # Data Steward getting the email. Needs to be their email address...without @big.foot.comat the end
    userList=["yeti"]
    # get a list of usernames from the list of named tuples returned from ListUsers
    userNames = [u for u in userList]
    # take the userNames list and make email addresses by appending the appropriate suffix.
    emailList = [name +  MAILDOMAIN for name in userNames]
    TO = emailList
    # Grab date for the email
    DATE = d

    # Sign in to portal
    arcpy.SignInToPortal('https://www.arcgis.com', 'userid', 'password')

    # Set output file names
    outdir = r"C:\PRODUCTION\GRSM_SASQUATCH"
    sddraft_filename = service + ".sddraft"
    sddraft_output_filename = os.path.join(outdir, sddraft_filename)
    #Delete any left over SD files from failed previous run
    try:
        os.remove(sd_filename)
        print("Successfully deleted ", sd_filename)
    except:
        print("Error while deleting file ", sd_filename, ", perhaps it doesn't exist")
    try:
        os.remove(sddraft_output_filename)
        print("Successfully deleted ", sddraft_output_filename)
    except:
        print("Error while deleting file ", sddraft_output_filename, ", perhaps it doesn't exist")        

    # Reference map to publish
    aprx = arcpy.mp.ArcGISProject(r"C:\PRODUCTION\GRSM_SASQUATCH\GRSM_SASQUATCH.aprx")
    m = aprx.listMaps("GRSM_SASQUATCH_LOCATIONS")[0]

    # Create FeatureSharingDraft and set service properties
    # https://pro.arcgis.com/en/pro-app/arcpy/sharing/featuresharingdraft-class.htm
    sharing_draft = m.getWebLayerSharingDraft("HOSTING_SERVER", "FEATURE", service)
    sharing_draft.summary = "Sasquatch Locations"
    sharing_draft.tags = "Sasquatch, Fur, Hairy, Big Foot"
    sharing_draft.description = "Hide and Seek Champion"
    sharing_draft.credits = "Yeti"
    sharing_draft.useLimitations = "This is not real"
    #sharing_draft.portalFolder = "Front Country"
    sharing_draft.overwriteExistingService = "true"
    sharing_draft.allowExporting = "true"

    # Create Service Definition Draft file
    sharing_draft.exportToSDDraft(sddraft_output_filename)

    # Stage Service
    # https://pro.arcgis.com/en/pro-app/tool-reference/server/stage-service.htm
    sd_output_filename = os.path.join(outdir, sd_filename)
    arcpy.StageService_server(sddraft_output_filename, sd_output_filename)

    # Share to portal
    # https://pro.arcgis.com/en/pro-app/tool-reference/server/upload-service-definition.htm
    print("Uploading Service Definition...")
    arcpy.UploadServiceDefinition_server(sd_output_filename,
                                         "My Hosted Services",
                                         "",
                                         "",
                                         "EXISTING",
                                         "existingFolder",
                                         "",
                                         "OVERRIDE_DEFINITION",
                                         "SHARE_ONLINE",
                                         "PUBLIC",
                                         "SHARE_ORGANIZATION",
                                         ["GRSM","Great Smoky Mountains National Park Open Data"] )

    # Clean up SD files
    try:
        os.remove(sd_filename)
        print("Successfully deleted ", sd_filename)
    except:
        print("Error while deleting file ", sd_filename, ", perhaps it doesn't exist")
    try:
        os.remove(sddraft_output_filename)
        print("Successfully deleted ", sddraft_output_filename)
    except:
        print("Error while deleting file ", sddraft_output_filename, ", perhaps it doesn't exist")        

    # Write nothing to log if success.
    endtime = datetime.datetime.now()
    log.write("     Completed successfully in " 
           + str(endtime - starttime) + "\n")
    log.write("\n")
    log.close()
    print('done')

except:
    
 # Get the traceback object
    tb = sys.exc_info()[2]
    tbinfo = traceback.format_tb(tb)[0]
 # Concatenate information together concerning 
 # the error into a message string
    pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
    msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
# Return python error messages for use in 
# script tool or Python Window
    arcpy.AddError(pymsg)
    arcpy.AddError(msgs)
# Print Python error messages for use in 
# Python / Python Window
    log.write("" + pymsg + "\n")
    log.write("" + msgs + "")
    log.close()
    # Define email message if something went wrong
    SUBJECT = "Notification of Un-Successful AGOL Update of "+service 
    MSG = "Did Not Update: {} - ID: {} at "+ str(DATE)+ "; " +pymsg + "; " + msgs
    print (MSG)
    print (emailList)
 
    # Send an email notifying steward of successful archive
    #MESSAGE = "\ From: %s To: %s Subject: %s %s" % (FROM, ", ".join(TO), SUBJECT, MSG)
    MESSAGE = "Subject: %s\n\n%s" % (SUBJECT, MSG)
    try:
            try:
                print("Connecting to Server...")
                server = smtplib.SMTP(SERVER,PORT)
                try:
                    print("Login...")
                    try:
                        print("Sending mail...")
                        server.sendmail(FROM, TO, MESSAGE)
                    except Exception as e:
                        print("Send Error Mail\n" + e.message)
                except Exception as e:
                    print("Error Authentication Server: check the credentials \n" + e.message)
            except Exception as e:
                print("Error Connecting to Server : check the URL of the server and communications port ( 25 and ' the default ) \n" + e.message)
     
            print("Quit.")
            server.quit()
     
    except Exception as e:
            print (e.message)    
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
1 Comment
About the Author
This is a personal account and does not reflect the view or policies of my org.