Unable to Overwrite Existing Cached Map Service Using MapImageSharingDraft

113
0
3 weeks ago
旻翰莊
New Contributor

Hi, I'm trying to publish a map service using Python and ArcPy.
Even though I set sddraft.overwriteExistingService = True, the service is always published with a timestamp appended (e.g., Tainan_ZonePrice_202505151610) instead of overwriting the existing service.

I have already registered the target folder on the GIS Server, and the service name I'm using matches the one that already exists in that folder.

Here is a simplified version of my code:

import arcpy
import os
import xml.dom.minidom as DOM 
from dataclasses import dataclass
import requests
import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom

# Modify portal URL, username, and password
portal_url  = "https://test/portal"
server_username=""
server_password=""

arcpy.SignInToPortal(portal_url , server_username, server_password)
print("Signing in to portal...")

@dataclass
class Service:
    aprx_name: str         # Project file name
    aprx_path: str         # Path to the .aprx file
    serverFolder: str      # Folder on the server to publish to
    map: str               # Map name (only needed if named)
    service_name:  str     # Name of the service
    mapOperations: str     # Operations (Map, Data, Query)
    maxRecordCount: str    # Max record count (default is 2000)
    groups: str            # Shared groups, separated by commas (e.g., "Group A,Group B")
    sharingLevel: str      # Sharing level: OWNER, ORGANIZATION, or EVERYONE

MapImage = {
    1: Service("Tainan_ZonePrice", r"D:\MapData\Tainan_ZonePrice\Tainan_ZonePrice.aprx", "publish_test", "map", "Tainan_ZonePrice", "Map,Data,Query", 2000, "", "EVERYONE")
}

print(MapImage[1].aprx_name)

for key in [1]:
    try:
        # Output folders
        outdir_1 = r"D:\MapData\sddraft"
        outdir_2 = r"D:\MapData\sd"

        # Generate filenames for draft and service definition
        aprx_name = MapImage[key].aprx_name
        sddraft_filename = aprx_name + ".sddraft"
        sddraft_output_filename = os.path.join(outdir_1, sddraft_filename)
        sd_filename = aprx_name + ".sd"
        sd_output_filename = os.path.join(outdir_2, sd_filename)

        aprx_path = MapImage[key].aprx_path
        aprx = arcpy.mp.ArcGISProject(aprx_path)
        print(aprx.listMaps())
        m = aprx.listMaps(MapImage[key].map)[0]
        print(m)

        service_name = MapImage[key].service_name
        print(service_name)

        # Replace with your federated server URL
        federated_server_url = "https://test/server" 
        server_type = "FEDERATED_SERVER"
        sddraft = m.getWebLayerSharingDraft(server_type, "MAP_IMAGE", service_name)
        sddraft.federatedServerUrl = federated_server_url
        sddraft.enableCache = True
        sddraft.cache.configuration = r"D:\MapData\ArcGIS_Online_Bing_Maps_Google_Maps.xml"  # Tiling scheme
        sddraft.overwriteExistingService = True
        sddraft.copyDataToServer = False
        sddraft.portalFolder = MapImage[key].serverFolder
        sddraft.serverFolder = MapImage[key].serverFolder
        sddraft.maxRecordCount = MapImage[key].maxRecordCount
        sddraft.mapOperations = MapImage[key].mapOperations
        sddraft.sharing.sharingLevel = MapImage[key].sharingLevel
        sddraft.sharing.groups = MapImage[key].sharingLevel
        sddraft.exportToSDDraft(sddraft_output_filename)

        # Modify the XML
        doc = DOM.parse(sddraft_output_filename)

        # Preserve original XML declaration
        original_declaration = None
        with open(sddraft_output_filename, 'r', encoding='utf-8') as f:
            first_line = f.readline().strip()
            if first_line.startswith('<?xml'):
                original_declaration = first_line

        # Modify configuration properties
        try:
            config_props = doc.getElementsByTagName('ConfigurationProperties')[0]
            properties = config_props.getElementsByTagName('PropertyArray')[0]
            prop_sets = properties.getElementsByTagName('PropertySetProperty')

            for prop_set in prop_sets:
                keys = prop_set.getElementsByTagName('Key')
                if keys and keys[0].firstChild:
                    key_value = keys[0].firstChild.nodeValue
                    values = prop_set.getElementsByTagName('Value')

                    if key_value == "minScale" and values and values[0].firstChild:
                        values[0].firstChild.nodeValue = "295828763.795777"
                        print("minScale set")
                    elif key_value == "maxScale" and values and values[0].firstChild:
                        values[0].firstChild.nodeValue = "70.5310735"
                        print("maxScale set")
                    elif key_value == "isCached" and values and values[0].firstChild:
                        values[0].firstChild.nodeValue = "true"
                        print("isCached set")
        except Exception as e:
            print(f"Error modifying configuration properties: {str(e)}")

        # Save XML preserving original format
        with open(sddraft_output_filename, 'w', encoding='utf-8') as f:
            xml_declaration = original_declaration if original_declaration else '<?xml version="1.0" encoding="utf-8"?>'
            f.write(xml_declaration + '\n')
            f.write(doc.documentElement.toxml())

        print("Deleting existing .sd file")
        if os.path.exists(sd_output_filename):
            os.remove(sd_output_filename)

        print("Start staging")
        arcpy.server.StageService(sddraft_output_filename, sd_output_filename)
        warnings = arcpy.GetMessage(1)
        print(warnings)
        print("Publishing service...")

        print("Start uploading")
        federated_server_url1 = "https://test/server/rest/services/publish_test"
        results = arcpy.server.UploadServiceDefinition(sd_output_filename, federated_server_url1)
        print("Upload complete")

        print("Start managing cache tiles")
        service_url = f"https://test/server/rest/services/publish_test/{service_name}/MapServer"
        scales = "295828763.795777;147914381.897889;73957190.948944;36978595.474472;18489297.737236;9244648.868618;4622324.434309;2311162.217155;1155581.108577;577790.554289;288895.277144;144447.638572;72223.819286;36111.909643;18055.954822;9027.977411;4513.988705;2256.994353;1128.497176"
        arcpy.server.ManageMapServerCacheTiles(service_url, scales, "RECREATE_ALL_TILES")
        print("Cache management complete")

    except arcpy.ExecuteError:
        msgs = arcpy.GetMessages(2)
        print(f"Arcpy execution error: {msgs}")

    except Exception as e:
        print(f"Other error occurred: {e}")
 
 

No matter what I try, ArcGIS Server always appends a timestamp to the service name instead of overwriting the existing one.
I have confirmed that:

  • The service name matches an existing service.

  • The folder is correctly registered.

  • The overwriteExistingService flag is set to True.

Is there anything I am missing to ensure the existing service is truly overwritten, instead of creating a new one with a timestamp suffix?

Thanks in advance!

 
 
Tags (1)
0 Kudos
0 Replies