Using a licence manager and concurrent licenses, users can switch licenses themselves, e.g. from Basic to Standard or Advanced. Or they can add an extension for a day.
Esri wants to phase out the concurrent license model and move to named user licenses.
However in ArcGIS Online only an Admin can do the job and help the user with switching a license or an extension. This cost time and is a serious drawback.
The alternative: buying the most expensive named user licenses for all users would be too costly.
Can Esri make user-based licence switching possible again?
I can imagine it's hard to do. But it would be appreceated very much.
Any other customers - reading this post who would like the same - feel welcome to support this.
Regards, Bert
Disappointed that your post hasn't generated a discussion. My group is concerned with the issues you've brought up. Signing out extensions, switching named user types temporarily so users can access everything in Professional Plus.
ESRI's success with concurrent licensing has resulting in the majority of our Pro users are part-time users which doesn't map over well to the "named user" model.
@BertvanRest @RandyKreuziger1 @DebSF We also ran into this issue early on, but we found some options with python toolboxes. We built a python (but could also be done with .atbx) toolbox to allow our users to manage their licenses and license extensions. It does mean that we need at least enough "Creator" level accounts to support the users we have, but from there, these toolboxes can be shared to allow users to manage their own licenses. We share these through our ArcGIS Enterprise environment and make them available to specific groups so that we can track who needs and has access to which license type. Here's a code snippet:
import arcpy
import arcgis_profile_service
import importlib
# coordinate_system is a dependency of arcpy_environment_initializer - it is CRITICAL
# that dependencies are only importlib.reload() reloaded at the level of the .pyt file
# attempting to reload a dependency within a dependency itself may cause publishing issues
# resulting in the unexplained 999999 error code.
importlib.reload(arcgis_profile_service)
class Toolbox:
def __init__(self):
"""
This defines the information for the entire toolbox.
"""
self.label = "License Manager"
self.alias = "LicenseManager"
self.description = "License manager for managing licenses and extensions"
# List of tool classes associated with this toolbox
self.tools = [Manage3DAnalystExtensionLicense, ManageDataReviewerExtensionLicense,
ManageNetworkAnalystExtensionLicense, ManageSpatialAnalystExtensionLicense,
ManageDataInteroperabilityExtensionLicense, ManageLocationReferencingExtensionLicense,
ManageProductionMappingExtensionLicense, ManageWorkflowManagerExtensionLicense,
ManageStandardArcProLicense, ManageAdvancedArcProLicense]
class BaseTool:
"""
The BaseTool class defined the basic functionality for managing licenses in a way that can be reused by other classes.
"""
def __init__(self):
"""Constructor defining the default information for each tool as well as properties to be used by deriving classes."""
self.label = "BaseTool"
self.alias = "Base Tool"
self.description = "Testing"
# The license_coded_name is the value Esri defined for the license or extension license. Ex. 3DAnalystN is coded name for 3D Analyst
self.license_coded_name = ""
# The license_readable_name is defined to for display purposes to help the end user understand the
# actual license name they would be familiar with. Ex. 3D Analyst is the readable name for 3DAnalystN
self.license_readable_name = ""
def getParameterInfo(self):
"""Configures the parameter(s) for the tool(s)."""
params = []
mode_parameter = arcpy.Parameter(
displayName="Mode",
name="Mode",
datatype="GPString",
parameterType="Required",
direction="Input"
)
mode_parameter.filter.type = "ValueList"
mode_parameter.filter.list = ["Assign", "Return"]
params.append(mode_parameter)
return params
def isLicensed(self):
"""Set whether the tool is licensed to execute."""
return True
def updateParameters(self, parameters):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
return
def updateMessages(self, parameters):
"""Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation."""
return
def execute(self, parameters, messages):
"""
Defines the code to run for each tool.
"""
# Gets the mode ('Assign' or 'Return') that the tool should use.
mode = parameters[0].valueAsText
try:
# Sets up the gis object for ArcGIS Online using the administrator account.
# Access for the administrator account is defined through a "profile" which must be set up in advance on the machine/server
# where this tool will be run. Once a profile is defined using the proper credentials, the profile can be used in place of credentials.
gis = arcgis_profile_service.get_arcgis_online_administrator_gis()
# Retrieve the portal description containing the current username information to be used for license administration.
portal_desc = arcpy.GetPortalDescription()
username = portal_desc['user']['username']
# Detect the chosen mode and print helpful messages to the user on what the tool is attempting to do.
if mode == 'Assign':
arcpy.AddMessage('Preparing to assign the ' + self.license_readable_name + ' license to ' + username)
else:
arcpy.AddMessage('Preparing to return the ' + self.license_readable_name + ' license from ' + username)
# Retrieve the ArcPro license information from ArcGIS Online and determine which users have the "license_coded_name" for the extension
# that is being assigned or returned. This will help users determine who has a license, especially on a failed attempt to assign the license.
pro_license = gis.admin.license.get("ArcGIS Pro")
extension_licenses = [self.license_coded_name]
for license_name in pro_license.all():
if "username" in license_name and "entitlements" in license_name:
license_username = license_name["username"]
license_entitlements = license_name["entitlements"]
if self.license_coded_name in license_entitlements:
arcpy.AddMessage(license_username + " has one of the available licenses for " + self.license_readable_name + ".")
# Get the user object for ArcGIS Online for the current user based on their username. A user must be a "Creator" for licenses to be
# assignable to their account - ArcPro licenses are not compatible with Viewer or Mobile Worker types.
user = gis.users.get(username)
if user is not None and user.user_types() is not None and user.user_types().get("name") == "Creator":
arcpy.AddMessage("Creator user type has been found - it is possible to assign or return licenses/extensions.")
existing_entitlements = pro_license.user_entitlement(username).get("entitlements", []) # default to an empty list [] if no existing entitlements
if mode == "Assign":
assignable_extensions = list(set(existing_entitlements + extension_licenses)) # removes duplicates
if "desktopBasicN" in assignable_extensions:
assignable_extensions.remove("desktopBasicN") # Esri changed licensing so that this is included by default
pro_license.assign(username=username, entitlements=assignable_extensions) # reassigning licenses
arcpy.AddMessage("Successfully assigned " + username + " " + self.license_readable_name + " licenses/extensions.")
else:
pro_license.revoke(username=username, entitlements=extension_licenses)
arcpy.AddMessage("Successfully returned " + username + " " + self.license_readable_name + " licenses/extensions.")
else:
arcpy.AddError("Specified user requires a Creator license before licenses/extensions can be assigned or revoked.")
except Exception as e:
arcpy.AddError("An error occurred: " + str(e) + " - Please contact the administrator if you are unable to proceed.")
return
def postExecute(self, parameters):
"""This method takes place after outputs are processed and
added to the display."""
return
class Manage3DAnalystExtensionLicense(BaseTool):
"""
This class sets up a tool for management of 3D Analyst license extensions.
"""
def __init__(self):
super().__init__()
"""Constructor that defines the information for the tool."""
self.label = "Manage 3D Analyst ArcGIS Pro Extension License"
self.alias = "Manage3DAnalystExtensionLicense"
self.description = "This tool allows users to manage their own 3D Analyst ArcGIS Pro Extension License"
def execute(self, parameters, messages):
self.license_coded_name = "3DAnalystN"
self.license_readable_name = "3D Analyst"
super().execute(parameters, messages)