Операции по автоматическому согласованию и закреплению данных сервис-ориентированных версий с поддержкой синхронизации.

Администраторы портала и администраторы версий могут использовать скрипты Python для автоматизации планового согласования версий реплик после того, как полевые работники согласуют изменения в данные, включенные в сервис-ориентированные версии.

Этот рабочий процесс применяется для управления версиями реплик, созданных с помощью сервиса объектов с поддержкой синхронизации, с данными сервис-ориентированных версий.

Дополнительные сведения об автономных картах с данными сервис-ориентированных версий

Применимый сценарий

Пример Python в следующем разделе использует сервис объектов ArcGIS REST API и инструменты геообработки ArcPy для согласования и публикации версий реплик с установленными правилами атрибутов проверки. Ниже описывается, когда вы будете использовать этот образец кода, и что делает скрипт.

Примечание:

Этот скрипт - пример рабочего процесса с установкой конкретных данных. Ваши рабочие процессы не обязательно должны в точности соответствовать модели данных, но основные концепции и логику скрипта все равно можно использовать для автоматизации процессов для вашей организации. Например, вы можете не использовать правила проверки, и, соответственно изменить скрипт и удалить из него проверку с помощью правил. Также, в ряде случаев при использовании правил проверки вы можете захотеть согласовать, запустить проверку и закрепить изменения в каждой версии отдельно, перед запуском операции проверки, чтобы быть уверенным, что изменения, сделанные другими пользователями, будут включены в проверку.

Предварительное условие:

В этом примере настройка данных следующая:

  • В сервисе объектов должна быть включена функция синхронизации с данными сервис-ориентированных версий, выбрана опция Создать версию для каждой загруженной карты, для чего требуется ArcGIS Enterprise 10.8.1 или более поздняя версия.
  • Реплики были созданы в сервисе путем перевода карты в автономный режим.
  • В сервисе включена функция сервера управления версиями.
  • У пользователя портала должны быть учетные данные участника либо с ролью администратора портала по умолчанию, либо с пользовательской ролью, которой предоставлены права доступа для управления версиями.
  • В этом примере к данным также применены правила атрибутов проверки и включена функция сервера проверки. Это - не обязательное требование для работы с версиями реплик, но позволяет обеспечить целостность данных.

  1. Список версий реплик для этого сервиса объектов можно получить с помощью ресурса replicas в ArcGIS REST API.
  2. Используйте ресурс versionsInfos в ArcGIS REST API для получения свойств этой версии. Используя эти свойства, создайте фильтр, чтобы получить только те версии, в которых дата оценки равна нулю или измененная дата больше последней даты оценки (то есть с момента последней оценки были сделаны изменения). Добавьте имена версий, удовлетворяющие фильтру, в список listOfVersionsToValidate, который будет оцениваться.
  3. Для каждой версии в списке оценки используйте операцию evaluate в ArcGIS REST API, чтобы выполнить оценку правил атрибутов проверки в этом сервисе. Если оценка прошла успешно без возвращенных ошибок, то версия готова к согласованию и публикации. Если оценка прошла успешно, но ошибки возвращаются, не публикуйте изменения и создайте сообщение, чтобы ошибки можно было проверить и исправить вручную.
  4. Для версий, которые были успешно оценены без ошибок, запустите инструмент Согласовать версии с возможностью публикации изменений.
  5. Запустите инструмент Согласовать версии с возможностью только согласования (без публикации) на всех версиях реплик.

Образец кода

Приведенный ниже полный образец кода Python завершает перечисленные выше операции. Этот скрипт включает в себя возможность создания файла журнала, который захватывает выходные данные каждой завершенной операции, и который можно просмотреть после завершения этого скрипта.

# 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.')