diff options
Diffstat (limited to 'azurelinuxagent/distro/default/extension.py')
-rw-r--r-- | azurelinuxagent/distro/default/extension.py | 611 |
1 files changed, 382 insertions, 229 deletions
diff --git a/azurelinuxagent/distro/default/extension.py b/azurelinuxagent/distro/default/extension.py index 58ba84e..f6c02aa 100644 --- a/azurelinuxagent/distro/default/extension.py +++ b/azurelinuxagent/distro/default/extension.py @@ -1,4 +1,4 @@ -# Windows Azure Linux Agent +# Microsoft Azure Linux Agent # # Copyright 2014 Microsoft Corporation # @@ -21,18 +21,35 @@ import zipfile import time import json import subprocess +import shutil import azurelinuxagent.logger as logger from azurelinuxagent.future import text from azurelinuxagent.utils.osutil import OSUTIL import azurelinuxagent.protocol as prot +from azurelinuxagent.metadata import AGENT_VERSION from azurelinuxagent.event import add_event, WALAEventOperation from azurelinuxagent.exception import ExtensionError import azurelinuxagent.utils.fileutil as fileutil import azurelinuxagent.utils.restutil as restutil import azurelinuxagent.utils.shellutil as shellutil +from azurelinuxagent.utils.textutil import Version + +#HandlerEnvironment.json schema version +HANDLER_ENVIRONMENT_VERSION = 1.0 VALID_EXTENSION_STATUS = ['transitioning', 'error', 'success', 'warning'] +VALID_HANDLER_STATUS = ['Ready', 'NotReady', "Installing", "Unresponsive"] + +def handler_state_to_status(handler_state): + if handler_state == "Enabled": + return "Ready" + elif handler_state in VALID_HANDLER_STATUS: + return handler_state + else: + return "NotReady" + + def validate_has_key(obj, key, fullname): if key not in obj: raise ExtensionError("Missing: {0}".format(fullname)) @@ -41,103 +58,52 @@ def validate_in_range(val, valid_range, name): if val not in valid_range: raise ExtensionError("Invalid {0}: {1}".format(name, val)) -def try_get(dictionary, key, default=None): - try: - return dictionary[key] - except KeyError: - return default +def parse_formatted_message(formatted_message): + if formatted_message is None: + return None + validate_has_key(formatted_message, 'lang', 'formattedMessage/lang') + validate_has_key(formatted_message, 'message', 'formattedMessage/message') + return formatted_message.get('message') + -def extension_sub_status_to_v2(substatus): +def parse_ext_substatus(substatus): #Check extension sub status format - validate_has_key(substatus, 'name', 'substatus/name') validate_has_key(substatus, 'status', 'substatus/status') - validate_has_key(substatus, 'code', 'substatus/code') - validate_has_key(substatus, 'formattedMessage', 'substatus/formattedMessage') - validate_has_key(substatus['formattedMessage'], 'lang', - 'substatus/formattedMessage/lang') - validate_has_key(substatus['formattedMessage'], 'message', - 'substatus/formattedMessage/message') - validate_in_range(substatus['status'], VALID_EXTENSION_STATUS, 'substatus/status') status = prot.ExtensionSubStatus() - status.name = try_get(substatus, 'name') - status.status = try_get(substatus, 'status') - status.code = try_get(substatus, 'code') - status.message = try_get(substatus['formattedMessage'], 'message') + status.name = substatus.get('name') + status.status = substatus.get('status') + status.code = substatus.get('code', 0) + formatted_message = substatus.get('formattedMessage') + status.message = parse_formatted_message(formatted_message) return status -def ext_status_to_v2(ext_status, seq_no): +def parse_ext_status(ext_status, data): + if data is None or len(data) is None: + return + #Currently, only the first status will be reported + data = data[0] #Check extension status format - validate_has_key(ext_status, 'status', 'status') - validate_has_key(ext_status['status'], 'status', 'status/status') - validate_has_key(ext_status['status'], 'operation', 'status/operation') - validate_has_key(ext_status['status'], 'code', 'status/code') - validate_has_key(ext_status['status'], 'name', 'status/name') - validate_has_key(ext_status['status'], 'formattedMessage', - 'status/formattedMessage') - validate_has_key(ext_status['status']['formattedMessage'], 'lang', - 'status/formattedMessage/lang') - validate_has_key(ext_status['status']['formattedMessage'], 'message', - 'status/formattedMessage/message') - - validate_in_range(ext_status['status']['status'], VALID_EXTENSION_STATUS, + validate_has_key(data, 'status', 'status') + status_data = data['status'] + validate_has_key(status_data, 'status', 'status/status') + + validate_in_range(status_data['status'], VALID_EXTENSION_STATUS, 'status/status') - status = prot.ExtensionStatus() - status.name = try_get(ext_status['status'], 'name') - status.configurationAppliedTime = try_get(ext_status['status'], - 'configurationAppliedTime') - status.operation = try_get(ext_status['status'], 'operation') - status.status = try_get(ext_status['status'], 'status') - status.code = try_get(ext_status['status'], 'code') - status.message = try_get(ext_status['status']['formattedMessage'], 'message') - status.sequenceNumber = seq_no - - substatus_list = try_get(ext_status['status'], 'substatus', []) + applied_time = status_data.get('configurationAppliedTime') + ext_status.configurationAppliedTime = applied_time + ext_status.operation = status_data.get('operation') + ext_status.status = status_data.get('status') + ext_status.code = status_data.get('code', 0) + formatted_message = status_data.get('formattedMessage') + ext_status.message = parse_formatted_message(formatted_message) + substatus_list = status_data.get('substatus') + if substatus_list is None: + return for substatus in substatus_list: - status.substatusList.extend(extension_sub_status_to_v2(substatus)) - return status - -class ExtensionsHandler(object): - - def process(self): - protocol = prot.FACTORY.get_default_protocol() - ext_list = protocol.get_extensions() - - h_status_list = [] - for extension in ext_list.extensions: - #TODO handle extension in parallel - pkg_list = protocol.get_extension_pkgs(extension) - h_status = self.process_extension(extension, pkg_list) - h_status_list.append(h_status) - - return h_status_list - - def process_extension(self, extension, pkg_list): - installed_version = get_installed_version(extension.name) - if installed_version is not None: - ext = ExtensionInstance(extension, pkg_list, - installed_version, installed=True) - else: - ext = ExtensionInstance(extension, pkg_list, - extension.properties.version) - try: - ext.init_logger() - ext.handle() - status = ext.collect_handler_status() - except ExtensionError as e: - logger.error("Failed to handle extension: {0}-{1}\n {2}", - ext.get_name(), ext.get_version(), e) - add_event(name=ext.get_name(), is_success=False, - op=ext.get_curr_op(), message = text(e)) - ext_status = prot.ExtensionStatus(status='error', code='-1', - operation = ext.get_curr_op(), - message = text(e), - seq_no = ext.get_seq_no()) - status = ext.create_handler_status(ext_status) - status.status = "Ready" - return status + ext_status.substatusList.append(parse_ext_substatus(substatus)) def parse_extension_dirname(dirname): """ @@ -160,67 +126,204 @@ def get_installed_version(target_name): name, version = parse_extension_dirname(dir_name) #Here we need to ensure names are exactly the same. if name == target_name: - if installed_version is None or installed_version < version: + if installed_version is None or \ + Version(installed_version) < Version(version): installed_version = version return installed_version -class ExtensionInstance(object): - def __init__(self, extension, pkg_list, curr_version, installed=False): - self.extension = extension +class ExtHandlerState(object): + Enabled = "Enabled" + Disabled = "Disabled" + Failed = "Failed" + + +class ExtHandlersHandler(object): + + def process(self): + try: + protocol = prot.FACTORY.get_default_protocol() + ext_handlers = protocol.get_ext_handlers() + except prot.ProtocolError as e: + add_event(name="WALA", is_success=False, message = text(e)) + return + + + vm_status = prot.VMStatus() + vm_status.vmAgent.version = AGENT_VERSION + vm_status.vmAgent.status = "Ready" + vm_status.vmAgent.message = "Guest Agent is running" + + if ext_handlers.extHandlers is None or \ + len(ext_handlers.extHandlers) == 0: + logger.verb("No extensions to handle") + else: + for ext_handler in ext_handlers.extHandlers: + #TODO handle extension in parallel + try: + pkg_list = protocol.get_ext_handler_pkgs(ext_handler) + except prot.ProtocolError as e: + add_event(name="WALA", is_success=False, message=text(e)) + continue + + handler_status = self.process_extension(ext_handler, pkg_list) + if handler_status is not None: + vm_status.vmAgent.extensionHandlers.append(handler_status) + + try: + logger.verb("Report vm agent status") + protocol.report_vm_status(vm_status) + except prot.ProtocolError as e: + add_event(name="WALA", is_success=False, message = text(e)) + + def process_extension(self, ext_handler, pkg_list): + installed_version = get_installed_version(ext_handler.name) + if installed_version is not None: + handler = ExtHandlerInstance(ext_handler, pkg_list, + installed_version, installed=True) + else: + handler = ExtHandlerInstance(ext_handler, pkg_list, + ext_handler.properties.version) + handler.handle() + + if handler.ext_status is not None: + try: + protocol = prot.FACTORY.get_default_protocol() + protocol.report_ext_status(handler.name, handler.ext.name, + handler.ext_status) + except prot.ProtocolError as e: + add_event(name="WALA", is_success=False, message=text(e)) + + return handler.handler_status + +class ExtHandlerInstance(object): + def __init__(self, ext_handler, pkg_list, curr_version, installed=False): + self.ext_handler = ext_handler + self.name = ext_handler.name + self.version = ext_handler.properties.version self.pkg_list = pkg_list + self.state = ext_handler.properties.state + self.update_policy = ext_handler.properties.upgradePolicy + self.curr_version = curr_version - self.lib_dir = OSUTIL.get_lib_dir() self.installed = installed - self.settings = None - - #Extension will have no more than 1 settings instance - if len(extension.properties.extensions) > 0: - self.settings = extension.properties.extensions[0] - self.enabled = False - self.curr_op = None + self.handler_state = None + self.lib_dir = OSUTIL.get_lib_dir() + + self.ext_status = prot.ExtensionStatus() + self.handler_status = prot.ExtHandlerStatus() + self.handler_status.name = self.name + self.handler_status.version = self.curr_version + + #Currently, extension settings will have no more than 1 instance + if len(ext_handler.properties.extensions) > 0: + self.ext = ext_handler.properties.extensions[0] + self.handler_status.extensions = [self.ext.name] + else: + #When no extension settings, set sequenceNumber to 0 + self.ext = prot.Extension(sequenceNumber=0) + self.ext_status.sequenceNumber = self.ext.sequenceNumber prefix = "[{0}]".format(self.get_full_name()) self.logger = logger.Logger(logger.DEFAULT_LOGGER, prefix) def init_logger(self): #Init logger appender for extension - fileutil.mkdir(self.get_log_dir(), mode=0o700) + fileutil.mkdir(self.get_log_dir(), mode=0o644) log_file = os.path.join(self.get_log_dir(), "CommandExecution.log") self.logger.add_appender(logger.AppenderType.FILE, - logger.LogLevel.INFO, log_file) + logger.LogLevel.INFO, log_file) def handle(self): - self.logger.info("Process extension settings:") - self.logger.info(" Name: {0}", self.get_name()) - self.logger.info(" Version: {0}", self.get_version()) + self.init_logger() + self.logger.verb("Start processing extension handler") + + try: + self.handle_state() + except ExtensionError as e: + self.set_state_err(text(e)) + self.report_event(is_success=False, message=text(e)) + self.logger.error("Failed to process extension handler") + return + try: + if self.installed: + self.collect_ext_status() + self.collect_handler_status() + except ExtensionError as e: + self.report_event(is_success=False, message=text(e)) + self.logger.error("Failed to get extension handler status") + return + + self.logger.verb("Finished processing extension handler") + + def handle_state(self): if self.installed: - self.logger.info("Installed version:{0}", self.curr_version) - h_status = self.get_handler_status() - self.enabled = (h_status == "Ready") - - state = self.get_state() - if state == 'enabled': - self.handle_enable() - elif state == 'disabled': - self.handle_disable() - elif state == 'uninstall': - self.handle_disable() - self.handle_uninstall() + self.handler_state = self.get_state() + + self.handler_status.status = handler_state_to_status(self.handler_state) + self.logger.verb("Handler state: {0}", self.handler_state) + self.logger.verb("Sequence number: {0}", self.ext.sequenceNumber) + + if self.state == 'enabled': + if self.handler_state == ExtHandlerState.Failed: + self.logger.verb("Found previous failure, quit handle_enable") + return + + if self.handler_state == ExtHandlerState.Enabled: + self.logger.verb("Already enabled with sequenceNumber: {0}", + self.ext.sequenceNumber) + self.logger.verb("Quit handle_enable") + return + + try: + new = self.handle_enable() + if new is not None: + #Upgrade happened + new.set_state(ExtHandlerState.Enabled) + else: + self.set_state(ExtHandlerState.Enabled) + + except ExtensionError as e: + self.set_state(ExtHandlerState.Failed) + raise e + elif self.state == 'disabled': + if self.handler_state == ExtHandlerState.Failed: + self.logger.verb("Found previous failure, quit handle_disable") + return + + if self.handler_state == ExtHandlerState.Disabled: + self.logger.verb("Already disabled with sequenceNumber: {0}", + self.ext.sequenceNumber) + self.logger.verb("Quit handle_disable") + return + + try: + self.handle_disable() + self.set_state(ExtHandlerState.Disabled) + except ExtensionError as e: + self.set_state(ExtHandlerState.Failed) + raise e + elif self.state == 'uninstall': + try: + self.handle_uninstall() + except ExtensionError as e: + self.set_state(ExtHandlerState.Failed) + raise e else: - raise ExtensionError("Unknown extension state:{0}".format(state)) + raise ExtensionError("Unknown state:{0}".format(self.state)) def handle_enable(self): target_version = self.get_target_version() + self.logger.info("Target version: {0}", target_version) if self.installed: - if target_version > self.curr_version: - self.upgrade(target_version) - elif target_version == self.curr_version: + if Version(target_version) > Version(self.curr_version): + return self.upgrade(target_version) + elif Version(target_version) == Version(self.curr_version): self.enable() else: - raise ExtensionError("A newer version has already been installed") + raise ExtensionError("A newer version is already installed") else: - if target_version > self.get_version(): + if Version(target_version) > Version(self.version): #This will happen when auto upgrade policy is enabled self.logger.info("Auto upgrade to new version:{0}", target_version) @@ -231,21 +334,45 @@ class ExtensionInstance(object): self.enable() def handle_disable(self): - if not self.installed or not self.enabled: + if not self.installed: + self.logger.verb("Not installed, quit disable") return + self.disable() def handle_uninstall(self): if not self.installed: + self.logger.verb("Not installed, quit unistall") + self.handler_status = None + self.ext_status = None return + self.disable() self.uninstall() + def report_event(self, is_success=True, message=""): + if self.ext_status is not None: + if not is_success: + self.ext_status.status = "error" + self.ext_status.code = -1 + if self.handler_status is not None: + self.handler_status.message = message + if not is_success: + self.handler_status.status = "NotReady" + add_event(name=self.name, op=self.ext_status.operation, + is_success=is_success, message=message) + + def set_operation(self, operation): + if self.ext_status.operation != WALAEventOperation.Upgrade: + self.ext_status.operation = operation + def upgrade(self, target_version): self.logger.info("Upgrade from: {0} to {1}", self.curr_version, target_version) - self.curr_op=WALAEventOperation.Upgrade + self.set_operation(WALAEventOperation.Upgrade) + old = self - new = ExtensionInstance(self.extension, self.pkg_list, target_version) + new = ExtHandlerInstance(self.ext_handler, self.pkg_list, + target_version) self.logger.info("Download new extension package") new.init_logger() new.download() @@ -262,19 +389,20 @@ class ExtensionInstance(object): new.install() self.logger.info("Enable new extension") new.enable() - add_event(name=self.get_name(), is_success=True, - op=self.curr_op, message="") + return new def download(self): self.logger.info("Download extension package") - self.curr_op=WALAEventOperation.Download + self.set_operation(WALAEventOperation.Download) + uris = self.get_package_uris() package = None for uri in uris: try: resp = restutil.http_get(uri.uri, chk_proxy=True) - package = resp.read() - break + if resp.status == restutil.httpclient.OK: + package = resp.read() + break except restutil.HttpError as e: self.logger.warn("Failed download extension from: {0}", uri.uri) @@ -287,14 +415,13 @@ class ExtensionInstance(object): zipfile.ZipFile(pkg_file).extractall(self.get_base_dir()) chmod = "find {0} -type f | xargs chmod u+x".format(self.get_base_dir()) shellutil.run(chmod) - add_event(name=self.get_name(), is_success=True, - op=self.curr_op, message="") + self.report_event(message="Download succeeded") def init_dir(self): self.logger.info("Initialize extension directory") #Save HandlerManifest.json man_file = fileutil.search_file(self.get_base_dir(), - 'HandlerManifest.json') + 'HandlerManifest.json') man = fileutil.read_file(man_file, remove_bom=True) fileutil.write_file(self.get_manifest_file(), man) @@ -303,106 +430,141 @@ class ExtensionInstance(object): fileutil.mkdir(status_dir, mode=0o700) conf_dir = self.get_conf_dir() fileutil.mkdir(conf_dir, mode=0o700) - - #Init handler state to uninstall - self.set_handler_status("NotReady") + + self.make_handler_state_dir() #Save HandlerEnvironment.json self.create_handler_env() def enable(self): self.logger.info("Enable extension.") - self.curr_op=WALAEventOperation.Enable + self.set_operation(WALAEventOperation.Enable) + man = self.load_manifest() self.launch_command(man.get_enable_command()) - self.set_handler_status("Ready") - add_event(name=self.get_name(), is_success=True, - op=self.curr_op, message="") def disable(self): self.logger.info("Disable extension.") - self.curr_op=WALAEventOperation.Disable + self.set_operation(WALAEventOperation.Disable) + man = self.load_manifest() self.launch_command(man.get_disable_command(), timeout=900) - self.set_handler_status("Ready") - add_event(name=self.get_name(), is_success=True, - op=self.curr_op, message="") def install(self): self.logger.info("Install extension.") - self.curr_op=WALAEventOperation.Install + self.set_operation(WALAEventOperation.Install) + man = self.load_manifest() - self.set_handler_status("Installing") self.launch_command(man.get_install_command(), timeout=900) - self.set_handler_status("Ready") - add_event(name=self.get_name(), is_success=True, - op=self.curr_op, message="") + self.installed = True def uninstall(self): self.logger.info("Uninstall extension.") - self.curr_op=WALAEventOperation.UnInstall + self.set_operation(WALAEventOperation.UnInstall) + man = self.load_manifest() self.launch_command(man.get_uninstall_command()) - self.set_handler_status("NotReady") - add_event(name=self.get_name(), is_success=True, - op=self.curr_op, message="") + + self.logger.info("Remove ext handler dir: {0}", self.get_base_dir()) + try: + shutil.rmtree(self.get_base_dir()) + except IOError as e: + raise ExtensionError("Failed to rm ext handler dir: {0}".format(e)) + + self.installed = False + self.handler_status = None + self.ext_status = None def update(self): self.logger.info("Update extension.") - self.curr_op=WALAEventOperation.Update + self.set_operation(WALAEventOperation.Update) + man = self.load_manifest() self.launch_command(man.get_update_command(), timeout=900) - add_event(name=self.get_name(), is_success=True, - op=self.curr_op, message="") - - def create_handler_status(self, ext_status, heartbeat=None): - status = prot.ExtensionHandlerStatus() - status.handlerName = self.get_name() - status.handlerVersion = self.get_version() - status.status = self.get_handler_status() - status.extensionStatusList.append(ext_status) - return status def collect_handler_status(self): + self.logger.verb("Collect extension handler status") + if self.handler_status is None: + return + + handler_state = self.get_state() + self.handler_status.status = handler_state_to_status(handler_state) + self.handler_status.message = self.get_state_err() man = self.load_manifest() - heartbeat=None if man.is_report_heartbeat(): heartbeat = self.collect_heartbeat() - ext_status = self.collect_extension_status() - status= self.create_handler_status(ext_status, heartbeat) - status.status = self.get_handler_status() - if heartbeat is not None: - status.status = heartbeat['status'] - status.extensionStatusList.append(ext_status) - return status - - def collect_extension_status(self): + if heartbeat is not None: + self.handler_status.status = heartbeat['status'] + + def collect_ext_status(self): + self.logger.verb("Collect extension status") + if self.handler_status is None: + return + + if self.ext is None: + return + ext_status_file = self.get_status_file() try: - ext_status_str = fileutil.read_file(ext_status_file) - ext_status = json.loads(ext_status_str) + data_str = fileutil.read_file(ext_status_file) + data = json.loads(data_str) + parse_ext_status(self.ext_status, data) except IOError as e: raise ExtensionError("Failed to get status file: {0}".format(e)) except ValueError as e: raise ExtensionError("Malformed status file: {0}".format(e)) - return ext_status_to_v2(ext_status[0], - self.settings.sequenceNumber) + + def make_handler_state_dir(self): + handler_state_dir = self.get_handler_state_dir() + fileutil.mkdir(handler_state_dir, 0o600) + if not os.path.exists(handler_state_dir): + os.makedirs(handler_state_dir) - def get_handler_status(self): - h_status = "uninstalled" - h_status_file = self.get_handler_state_file() + def get_state(self): + handler_state_file = self.get_handler_state_file() + if not os.path.isfile(handler_state_file): + return None try: - h_status = fileutil.read_file(h_status_file) - return h_status + handler_state = fileutil.read_file(handler_state_file) + if handler_state is not None: + handler_state = handler_state.rstrip() + return handler_state except IOError as e: - raise ExtensionError("Failed to get handler status: {0}".format(e)) + err = "Failed to get handler state: {0}".format(e) + add_event(name=self.name, is_success=False, message=err) - def set_handler_status(self, status): - h_status_file = self.get_handler_state_file() + def set_state(self, state): + handler_state_file = self.get_handler_state_file() + if not os.path.isfile(handler_state_file): + self.make_handler_state_dir() + try: + fileutil.write_file(handler_state_file, state) + except IOError as e: + err = "Failed to set handler state: {0}".format(e) + add_event(name=self.name, is_success=False, message=err) + + def get_state_err(self): + """Get handler error message""" + handler_state_err_file= self.get_handler_state_err_file() + if not os.path.isfile(handler_state_err_file): + return None try: - fileutil.write_file(h_status_file, status) + message = fileutil.read_file(handler_state_err_file) + return message except IOError as e: - raise ExtensionError("Failed to set handler status: {0}".format(e)) + err = "Failed to get handler state message: {0}".format(e) + add_event(name=self.name, is_success=False, message=err) + + def set_state_err(self, message): + """Set handler error message""" + handler_state_err_file = self.get_handler_state_err_file() + if not os.path.isfile(handler_state_err_file): + self.make_handler_state_dir() + try: + fileutil.write_file(handler_state_err_file, message) + except IOError as e: + err = "Failed to set handler state message: {0}".format(e) + add_event(name=self.name, is_success=False, message=err) def collect_heartbeat(self): self.logger.info("Collect heart beat") @@ -426,7 +588,7 @@ class ExtensionInstance(object): return heartbeat def is_responsive(self, heartbeat_file): - last_update=int(time.time()-os.stat(heartbeat_file).st_mtime) + last_update=int(time.time() - os.stat(heartbeat_file).st_mtime) return last_update > 600 # not updated for more than 10 min def launch_command(self, cmd, timeout=300): @@ -452,6 +614,7 @@ class ExtensionInstance(object): ret = child.wait() if ret == None or ret != 0: raise ExtensionError("Non-zero exit code: {0}, {1}".format(ret, cmd)) + self.report_event(message="Launch command succeeded: {0}".format(cmd)) def load_manifest(self): man_file = self.get_manifest_file() @@ -464,16 +627,15 @@ class ExtensionInstance(object): return HandlerManifest(data[0]) - def update_settings(self): - if self.settings is None: - self.logger.verbose("Extension has no settings") + if self.ext is None: + self.logger.verb("Extension has no settings") return settings = { - 'publicSettings': self.settings.publicSettings, - 'protectedSettings': self.settings.privateSettings, - 'protectedSettingsCertThumbprint': self.settings.certificateThumbprint + 'publicSettings': self.ext.publicSettings, + 'protectedSettings': self.ext.privateSettings, + 'protectedSettingsCertThumbprint': self.ext.certificateThumbprint } ext_settings = { "runtimeSettings":[{ @@ -482,13 +644,10 @@ class ExtensionInstance(object): } fileutil.write_file(self.get_settings_file(), json.dumps(ext_settings)) - latest = os.path.join(self.get_conf_dir(), "latest") - fileutil.write_file(latest, self.settings.sequenceNumber) - def create_handler_env(self): env = [{ - "name": self.get_name(), - "version" : self.get_version(), + "name": self.name, + "version" : HANDLER_ENVIRONMENT_VERSION, "handlerEnvironment" : { "logFolder" : self.get_log_dir(), "configFolder" : self.get_conf_dir(), @@ -500,8 +659,8 @@ class ExtensionInstance(object): json.dumps(env)) def get_target_version(self): - version = self.get_version() - update_policy = self.get_upgrade_policy() + version = self.version + update_policy = self.update_policy if update_policy is None or update_policy.lower() != 'auto': return version @@ -509,45 +668,29 @@ class ExtensionInstance(object): if major is None: raise ExtensionError("Wrong version format: {0}".format(version)) - packages = [x for x in self.pkg_list.versions if x.version.startswith(major + ".")] - packages = sorted(packages, key=lambda x: x.version, reverse=True) + packages = [x for x in self.pkg_list.versions \ + if x.version.startswith(major + ".")] + packages = sorted(packages, key=lambda x: Version(x.version), + reverse=True) if len(packages) <= 0: raise ExtensionError("Can't find version: {0}.*".format(major)) return packages[0].version def get_package_uris(self): - version = self.get_version() + version = self.curr_version packages = self.pkg_list.versions if packages is None: raise ExtensionError("Package uris is None.") for package in packages: - if package.version == version: + if Version(package.version) == Version(version): return package.uris raise ExtensionError("Can't get package uris for {0}.".format(version)) - - def get_curr_op(self): - return self.curr_op - - def get_name(self): - return self.extension.name - - def get_version(self): - return self.extension.properties.version - - def get_state(self): - return self.extension.properties.state - - def get_seq_no(self): - return self.settings.sequenceNumber - - def get_upgrade_policy(self): - return self.extension.properties.upgradePolicy - + def get_full_name(self): - return "{0}-{1}".format(self.get_name(), self.curr_version) + return "{0}-{1}".format(self.name, self.curr_version) def get_base_dir(self): return os.path.join(OSUTIL.get_lib_dir(), self.get_full_name()) @@ -557,17 +700,27 @@ class ExtensionInstance(object): def get_status_file(self): return os.path.join(self.get_status_dir(), - "{0}.status".format(self.settings.sequenceNumber)) + "{0}.status".format(self.ext.sequenceNumber)) def get_conf_dir(self): return os.path.join(self.get_base_dir(), 'config') def get_settings_file(self): return os.path.join(self.get_conf_dir(), - "{0}.settings".format(self.settings.sequenceNumber)) + "{0}.settings".format(self.ext.sequenceNumber)) + + def get_handler_state_dir(self): + return os.path.join(OSUTIL.get_lib_dir(), "handler_state", + self.get_full_name()) def get_handler_state_file(self): - return os.path.join(self.get_conf_dir(), 'HandlerState') + return os.path.join(self.get_handler_state_dir(), + '{0}.state'.format(self.ext.sequenceNumber)) + + def get_handler_state_err_file(self): + return os.path.join(self.get_handler_state_dir(), + '{0}.error'.format(self.ext.sequenceNumber)) + def get_heartbeat_file(self): return os.path.join(self.get_base_dir(), 'heartbeat.log') @@ -579,7 +732,7 @@ class ExtensionInstance(object): return os.path.join(self.get_base_dir(), 'HandlerEnvironment.json') def get_log_dir(self): - return os.path.join(OSUTIL.get_ext_log_dir(), self.get_name(), + return os.path.join(OSUTIL.get_ext_log_dir(), self.name, self.curr_version) class HandlerEnvironment(object): |