azurelinuxagent/common/protocol/restapi.py (227 lines of code) (raw):

# Microsoft Azure Linux Agent # # Copyright 2018 Microsoft Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Requires Python 2.6+ and Openssl 1.0+ # import socket import time from azurelinuxagent.common.datacontract import DataContract, DataContractList from azurelinuxagent.common.future import ustr from azurelinuxagent.common.utils.textutil import getattrib from azurelinuxagent.common.version import DISTRO_VERSION, DISTRO_NAME, CURRENT_VERSION VERSION_0 = "0.0.0.0" class VMInfo(DataContract): def __init__(self, subscriptionId=None, vmName=None, roleName=None, roleInstanceName=None, tenantName=None): self.subscriptionId = subscriptionId self.vmName = vmName self.roleName = roleName self.roleInstanceName = roleInstanceName self.tenantName = tenantName class CertificateData(DataContract): def __init__(self, certificateData=None): self.certificateData = certificateData class Cert(DataContract): def __init__(self, name=None, thumbprint=None, certificateDataUri=None, storeName=None, storeLocation=None): self.name = name self.thumbprint = thumbprint self.certificateDataUri = certificateDataUri self.storeLocation = storeLocation self.storeName = storeName class CertList(DataContract): def __init__(self): self.certificates = DataContractList(Cert) class VMAgentFamily(object): def __init__(self, name): self.name = name # Two-state: None, string. Set to None if version not specified in the GS self.version = None # Tri-state: None, True, False. Set to None if this property not specified in the GS. self.is_version_from_rsm = None # Tri-state: None, True, False. Set to None if this property not specified in the GS. self.is_vm_enabled_for_rsm_upgrades = None self.uris = [] def __repr__(self): return self.__str__() def __str__(self): return "[name: '{0}' uris: {1}]".format(self.name, self.uris) class ExtensionState(object): Enabled = ustr("enabled") Disabled = ustr("disabled") class ExtensionRequestedState(object): """ This is the state of the Handler as requested by the Goal State. CRP only supports 2 states as of now - Enabled and Uninstall Disabled was used for older XML extensions and we keep it to support backward compatibility. """ Enabled = ustr("enabled") Disabled = ustr("disabled") Uninstall = ustr("uninstall") All = [Enabled, Disabled, Uninstall] class ExtensionSettings(object): """ The runtime settings associated with a Handler - Maps to Extension.PluginSettings.Plugin.RuntimeSettings for single config extensions in the ExtensionConfig.xml Eg: 1.settings, 2.settings - Maps to Extension.PluginSettings.Plugin.ExtensionRuntimeSettings for multi-config extensions in the ExtensionConfig.xml Eg: <extensionName>.1.settings, <extensionName>.2.settings """ def __init__(self, name=None, sequenceNumber=None, publicSettings=None, protectedSettings=None, certificateThumbprint=None, dependencyLevel=0, state=ExtensionState.Enabled): self.name = name self.sequenceNumber = sequenceNumber self.publicSettings = publicSettings self.protectedSettings = protectedSettings self.certificateThumbprint = certificateThumbprint self.dependencyLevel = dependencyLevel self.state = state def dependency_level_sort_key(self, handler_state): level = self.dependencyLevel # Process uninstall or disabled before enabled, in reverse order # Prioritize Handler state and Extension state both when sorting extensions # remap 0 to -1, 1 to -2, 2 to -3, etc if handler_state != ExtensionRequestedState.Enabled or self.state != ExtensionState.Enabled: level = (0 - level) - 1 return level def __repr__(self): return self.__str__() def __str__(self): return "{0}".format(self.name) class Extension(object): """ The main Plugin/handler specified by the publishers. Maps to Extension.PluginSettings.Plugins.Plugin in the ExtensionConfig.xml file Eg: Microsoft.OSTC.CustomScript """ def __init__(self, name=None): self.name = name self.version = None self.state = None self.settings = [] self.manifest_uris = [] self.supports_multi_config = False self.encoded_signature = None self.__invalid_handler_setting_reason = None @property def is_invalid_setting(self): return self.__invalid_handler_setting_reason is not None @property def invalid_setting_reason(self): return self.__invalid_handler_setting_reason @invalid_setting_reason.setter def invalid_setting_reason(self, value): self.__invalid_handler_setting_reason = value def dependency_level_sort_key(self): levels = [e.dependencyLevel for e in self.settings] if len(levels) == 0: level = 0 else: level = min(levels) # Process uninstall or disabled before enabled, in reverse order # remap 0 to -1, 1 to -2, 2 to -3, etc if self.state != u"enabled": level = (0 - level) - 1 return level def __repr__(self): return self.__str__() def __str__(self): return "{0}-{1}".format(self.name, self.version) class InVMGoalStateMetaData(DataContract): """ Object for parsing the GoalState MetaData received from CRP Eg: <InVMGoalStateMetaData inSvdSeqNo="2" createdOnTicks="637405409304121230" activityId="555e551c-600e-4fb4-90ba-8ab8ec28eccc" correlationId="400de90b-522e-491f-9d89-ec944661f531" /> """ def __init__(self, in_vm_metadata_node): self.correlation_id = getattrib(in_vm_metadata_node, "correlationId") self.activity_id = getattrib(in_vm_metadata_node, "activityId") self.created_on_ticks = getattrib(in_vm_metadata_node, "createdOnTicks") self.in_svd_seq_no = getattrib(in_vm_metadata_node, "inSvdSeqNo") class ExtHandlerPackage(DataContract): def __init__(self, version=None): self.version = version self.uris = [] # TODO update the naming to align with metadata protocol self.isinternal = False self.disallow_major_upgrade = False class ExtHandlerPackageList(DataContract): def __init__(self): self.versions = DataContractList(ExtHandlerPackage) class VMProperties(DataContract): def __init__(self, certificateThumbprint=None): # TODO need to confirm the property name self.certificateThumbprint = certificateThumbprint class ProvisionStatus(DataContract): def __init__(self, status=None, subStatus=None, description=None): self.status = status self.subStatus = subStatus self.description = description self.properties = VMProperties() class ExtensionSubStatus(DataContract): def __init__(self, name=None, status=None, code=None, message=None): self.name = name self.status = status self.code = code self.message = message class ExtensionStatus(DataContract): def __init__(self, name=None, configurationAppliedTime=None, operation=None, status=None, seq_no=None, code=None, message=None): self.name = name self.configurationAppliedTime = configurationAppliedTime self.operation = operation self.status = status self.sequenceNumber = seq_no self.code = code self.message = message self.substatusList = DataContractList(ExtensionSubStatus) class ExtHandlerStatus(DataContract): def __init__(self, name=None, version=None, status=None, code=0, message=None): self.name = name self.version = version self.status = status self.code = code self.message = message self.supports_multi_config = False self.extension_status = None class VMAgentStatus(DataContract): def __init__(self, status=None, message=None, gs_aggregate_status=None, update_status=None): self.status = status self.message = message self.hostname = socket.gethostname() self.version = str(CURRENT_VERSION) self.osname = DISTRO_NAME self.osversion = DISTRO_VERSION self.extensionHandlers = DataContractList(ExtHandlerStatus) self.vm_artifacts_aggregate_status = VMArtifactsAggregateStatus(gs_aggregate_status) self.update_status = update_status self._supports_fast_track = False @property def supports_fast_track(self): return self._supports_fast_track def set_supports_fast_track(self, value): self._supports_fast_track = value class VMStatus(DataContract): def __init__(self, status, message, gs_aggregate_status=None, vm_agent_update_status=None): self.vmAgent = VMAgentStatus(status=status, message=message, gs_aggregate_status=gs_aggregate_status, update_status=vm_agent_update_status) class GoalStateAggregateStatus(DataContract): def __init__(self, seq_no, status=None, message="", code=None): self.message = message self.in_svd_seq_no = seq_no self.status = status self.code = code self.__utc_timestamp = time.gmtime() @property def processed_time(self): return self.__utc_timestamp class VMArtifactsAggregateStatus(DataContract): def __init__(self, gs_aggregate_status=None): self.goal_state_aggregate_status = gs_aggregate_status class RemoteAccessUser(DataContract): def __init__(self, name, encrypted_password, expiration): self.name = name self.encrypted_password = encrypted_password self.expiration = expiration class RemoteAccessUsersList(DataContract): def __init__(self): self.users = DataContractList(RemoteAccessUser) class VMAgentUpdateStatuses(object): Success = ustr("Success") Transitioning = ustr("Transitioning") Error = ustr("Error") Unknown = ustr("Unknown") class VMAgentUpdateStatus(object): def __init__(self, expected_version, status=VMAgentUpdateStatuses.Success, message="", code=0): self.expected_version = expected_version self.status = status self.message = message self.code = code