Portal-Administratoren und Versionsadministratoren können Python-Skripte verwenden, um einen geplanten Abgleich von Replikatversionen zu automatisieren, nachdem Außendienstmitarbeiter ihre Änderungen an Daten in Verzweigungsversionierung synchronisiert haben.
Dieser Workflow kann für das Verwalten von Replikatversionen verwendet werden, die mit einem Feature-Service mit aktivierter Synchronisierung mit nach Verzweigung versionierten Daten erstellt wurden.
Weitere Informationen zum Arbeiten mit Offline-Karten mit nach Verzweigung versionierten Daten
Anwendbares Szenario
Im Python-Beispiel im nächsten Abschnitt werden die ArcGIS REST API des Feature-Service und ArcPy-Geoverarbeitungswerkzeuge verwendet, um Replikatversionen mit vorhandenen Validierungsattributregeln abzugleichen und zurückzuschreiben. Nachfolgend wird beschrieben, wann das Codebeispiel verwendet werden sollte und welche Operationen das Beispielskript ausführt.
Hinweis:
Dieses Skript ist ein Beispiel für einen Workflow mit einem bestimmten Daten-Setup. Ihre Workflows entsprechen möglicherweise nicht genau diesem Datenmodell, die Konzepte und die Logik des Skripts können aber dennoch verwendet werden, um ein angepasstes automatisiertes Skript für Ihre Organisation zu erstellen. Wenn Sie beispielsweise keine Validierungsregeln verwenden, können Sie das Skript ändern, um die Auswertung von Validierungsregeln zu entfernen. Es kann auch vorkommen, dass Sie bei Verwendung von Validierungsregeln alle Versionen abgleichen, validieren und einzeln zurückschreiben möchten, bevor Sie die Auswertungsoperation durchführen, um sicherzustellen, dass die Validierung die von den anderen Editoren vorgenommenen Änderungen umfasst.
In diesem Beispiel wird die folgende Konstellation verwendet:
- Im Feature-Service muss mit ausgewählter Option Für jede heruntergeladene Karte eine Version erstellen die Synchronisierung mit nach Verzweigung versionierten Daten aktiviert sein. Dazu ist ArcGIS Enterprise 10.8.1 oder höher erforderlich.
- Im Service wurden Replikate erstellt, indem eine Karte offline genommen wurde.
- Im Service wurde die Funktionalität des Servers für die Versionsverwaltung aktiviert.
- Die Anmeldeinformationen, die für den Portal-Benutzer im Skript angegeben sind, müssen für ein Mitglied der Standardadministratorrolle des Portals oder einer benutzerdefinierten Rolle mit der Berechtigung zur Versionsverwaltung gelten.
- In diesem Beispiel wurden in den Daten auch Validierungsattributregeln angewendet und die Funktionalität des Validierungsservers aktiviert. Dies ist zwar keine Voraussetzung für die Arbeit mit Replikatversionen, bietet aber eine Möglichkeit, die Datenintegrität zu gewährleisten.
- Verwenden der Ressource replicas in ArcGIS REST API zum Abrufen einer Liste der Replikatversionen für den Feature-Service.
- Verwenden der Ressource versionsInfos in ArcGIS REST API zum Abrufen der Eigenschaften der Version. Verwenden dieser Eigenschaften zum Erstellen eines Filter, damit nur die Versionen abgerufen werden, in denen das Auswertungsdatum NULL ist oder das Datum der letzten Änderung größer als das Datum der letzten Auswertung ist (was bedeutet, dass seit der letzten Auswertung Änderungen vorgenommen wurden). Anhängen der Namen der Versionen, die den Filter erfüllen, an die Liste listOfVersionsToValidate mit den Versionen, die ausgewertet werden sollen.
- Verwenden der Operation evaluate in ArcGIS REST API für jede Version in der Auswertungsliste zum Auswerten der Validierungsattributregeln im Service. Wenn die Auswertung erfolgreich war und keine Fehler zurückgegeben wurden, kann die Version abgeglichen und zurückgeschrieben werden. Wenn die Auswertung erfolgreich war, aber Fehler zurückgegeben wurden, dürfen die Änderungen nicht zurückgeschrieben werden. Stattdessen wird eine entsprechende Meldung generiert, damit die Fehler manuell untersucht und korrigiert werden können.
- Ausführen des Werkzeugs Versionen abgleichen mit der Option zum Zurückschreiben der Änderungen für Versionen, die erfolgreich und ohne Fehler ausgewertet wurden.
- Ausführen des Werkzeugs Versionen abgleichen mit der Option zum ausschließlichen Abgleichen (ohne Zurückschreiben) für alle Replikatversionen.
Codebeispiel
Das folgende Python-Codebeispiel führt die oben angegebenen Operationen aus. Dieses Skript enthält eine Option zum Generieren einer Protokolldatei, in der die Ausgabe jeder ausgeführten Operation erfasst wird und die nach der Ausführung des Skripts angezeigt werden kann.
# Import modules
import arcpy, traceback, urllib, json, urllib.request, urllib.parse, os, urllib.error, datetime
# Overwrite the reconcile log output each time the script is run
arcpy.env.overwriteOutput = True
# Script parameters
serviceName = "MyServiceName"
baseURL = "https://MyServer.MyDomain.com"
portalAdmin = "MyAdminUser"
portalAdminPwd = "MyAdmin.Password"
logFileScript = "C:/Logs/validateRecPostScriptLog.txt"
logfileOutputRecPost = 'C:/Logs/reconcile_log.txt'
# Choose to output a log file for the script
outputScriptReport = True
# Define functions
def openURL(url, params=None):
"""This function used to open a URL and returns the json response"""
try:
request_params = {'f':'pjson'}
if params:
request_params.update(params)
encodedParams = urllib.parse.urlencode(request_params)
request = urllib.request.urlopen(url, encodedParams.encode('UTF-8'))
response = request.read()
json_response = json.loads(response)
return json_response
except:
print (traceback.format_exc())
def versionInfo(versionOwner=""):
"""This function queries the versions owned by the versionOwner.
It returns a list of dictionaries."""
vmsUrlinfo = "{}/server/rest/services/{}/VersionManagementServer/versionInfos?&ownerFilter={}&includeHidden=&f=json&token={}".format(baseURL, serviceName, versionOwner, token)
response = openURL(vmsUrlinfo)
if response['success'] == True:
versionsDict = response['versions']
return versionsDict
else:
return("Unable to get version info")
def evaluateUrl(validationUrl, validate_params):
"""This function runs evaluate on the validation server
It returns the json response."""
evalJsonResp = openURL(validationUrl, validate_params)
if evalJsonResp['success'] == False:
return [False, evalJsonResp]
else:
return [True, evalJsonResp]
def generateMessage(msg, print_statement=True):
"""This function generates messages as the script runs. If print_statement
is set to True, print to the screen. If outputScriptReport is set to true,
write the message to the logfile"""
if outputScriptReport == True:
with open(logFileScript, 'a') as log_file:
log_file.write(msg + "\n")
if print_statement == True:
print(msg)
def recPostVersions(versionList, post):
"""This function runs the Reconcile Versions GP tool to reconcile
and optionally post to the feature service"""
if post == True:
postVersion = "POST"
elif post == False:
postVersion = "NO_POST"
# Reconcile and post the replica versions
# This tool is set to abort if there are conflicts and detects conflicts by object
arcpy.ReconcileVersions_management(featureService,
'ALL_VERSIONS',
'sde.DEFAULT',
versionList,
'NO_LOCK_ACQUIRED',
'ABORT_CONFLICTS',
'BY_OBJECT',
'FAVOR_EDIT_VERSION',
postVersion,
'KEEP_VERSION',
logfileOutputRecPost)
generateMessage(arcpy.GetMessages()+"\n")
# Start execution
generateMessage('Starting Validation/Reconcile/Post Automation Script... {:%Y-%b-%d %H:%M:%S}\n'.format(datetime.datetime.now()))
# Sign in to ArcGIS Enterprise
signIntoPortal = arcpy.SignInToPortal(baseURL+"/portal", portalAdmin, portalAdminPwd)
generateMessage("Signed into ArcGIS Enterprise {} as user {}".format(baseURL+"/portal", portalAdmin))
# Get the token returned by the SignIntoPortal arcpy function to use for making REST requests
token = signIntoPortal['token']
# Build the feature service URL
featureService = "{}/server/rest/services/{}/FeatureServer".format(baseURL, serviceName)
# Get a list of the replica versions from the REST endpoint
listOfRepVersions = []
replicaVersionsURL = featureService + "/replicas?returnVersion=true&f=pjson"
repVersionsJson = openURL(replicaVersionsURL, signIntoPortal)
for repVersion in repVersionsJson:
versionName = repVersion['replicaVersion']
listOfRepVersions.append(versionName)
# Create an empty list to append version names to validate
listOfVersionsToValidate = []
# Iterate through each version returned by the versionInfo() function to find
# the versions that need to be validated that are also in the listOfRepVersions list
for version in versionInfo():
print("")
# Parse the version info response, which is a python dictionary/json
# If the version name is sde.DEFAULT, pass since we do not want to evaluate the default version
if version['versionName'] == "sde.DEFAULT":
pass
# If the modifiedDate property is null, pass
elif version['modifiedDate'] == "None":
pass
# If the evaluation date is null, append the version name to the list to listOfVersions to be evaluated
elif version['evaluationDate'] == None:
if version['versionName'] in listOfRepVersions:
listOfVersionsToValidate.append(version['versionName'])
# If the evaluation date is not null, but it has been modifed since the last evaluation, add it to the list to be validated
elif version['evaluationDate'] != None and version['modifiedDate'] > version['evaluationDate']:
if version['versionName'] in listOfRepVersions:
listOfVersionsToValidate.append(version['versionName'])
# If none of these conditions are met
else:
generateMessage("Version {} will not be validated.".format(version['versionName']))
# Validate versions
generateMessage('The following versions will be validated: {}\n'.format(listOfVersionsToValidate))
# Create lists to contain versions where the validation passed or failed
failEval = []
passEval = []
# For each version in the list of versions, build the json request needed to validate
for i in listOfVersionsToValidate:
validate_params = { "gdbVersion": i,
"sessionId": "",
"evaluationArea": "",
"changesInVersion": "true",
"selection": "",
"evaluationType": '["validationRules"]',
"returnEdits": "true",
"async": "false",
"f": "pjson",
"token": token
}
# Build the REST URL used to validate the service
validationUrl = baseURL + "/server/rest/services/"+ serviceName +"/ValidationServer/evaluate"
# Call the evalVersion() function to validate the version
evalVersion = evaluateUrl(validationUrl, validate_params)
# If the evaluate failed, append to the failEval list
if evalVersion[0] == False:
generateMessage("Evalution of version {} failed".format(i))
generateMessage(str(evalVersion[1]))
failEval.append(i)
# If the evaluate passed, check to see if errors were returned
elif evalVersion[0] == True:
# If errors are returned, only reconcile this version
if evalVersion[1]['errorsIdentified'] != 0:
generateMessage("{} Errors were identified in version {}.\nThe version will be reconciled but will not be posted.\n".format((str(evalVersion[1]['errorsIdentified'])),i))
generateMessage(str(evalVersion[1]), False)
# If errors were not found this version can be posted
else:
generateMessage("Evaluation of version {} passed with no errors identified.\nThis version will be reconciled and posted.\n".format(i))
generateMessage(str(evalVersion[1]))
passEval.append(i)
# The versions that passed validation should be reconciled/posted
generateMessage('\nThe following versions passed validation and will be reconciled and posted: {}\n'.format(passEval))
# Run recPostVersions on the list of versions that passed evaluation with the option to post
recPostVersions(passEval, True)
# Open the reconcile log file and append the results to our report
with open(logfileOutputRecPost, 'r') as openRecLog:
generateMessage(openRecLog.read(), False)
# Run recPostVersions with the option to reconcile all replica versions, no post
recPostVersions(listOfRepVersions, False)
# Open the reconcile log file and append the results to our report
with open(logfileOutputRecPost, 'r') as openRecLog:
generateMessage(openRecLog.read(), False)
# Script execution complete
generateMessage('Validate, Reconcile, & Post Script Complete.')