diff options
Diffstat (limited to 'azurelinuxagent/ga')
-rw-r--r-- | azurelinuxagent/ga/exthandlers.py | 77 | ||||
-rw-r--r-- | azurelinuxagent/ga/update.py | 69 |
2 files changed, 85 insertions, 61 deletions
diff --git a/azurelinuxagent/ga/exthandlers.py b/azurelinuxagent/ga/exthandlers.py index 9b99d04..e0125aa 100644 --- a/azurelinuxagent/ga/exthandlers.py +++ b/azurelinuxagent/ga/exthandlers.py @@ -149,14 +149,17 @@ def migrate_handler_state(): logger.warn("Exception occurred removing {0}: {1}", handler_state_path, str(e)) return + class ExtHandlerState(object): NotInstalled = "NotInstalled" Installed = "Installed" Enabled = "Enabled" + def get_exthandlers_handler(): return ExtHandlersHandler() + class ExtHandlersHandler(object): def __init__(self): self.protocol_util = get_protocol_util() @@ -222,8 +225,8 @@ class ExtHandlersHandler(object): self.log_etag = True state = ext_handler.properties.state - ext_handler_i.logger.info("Expected handler state: {0}", state) - if state == "enabled": + ext_handler_i.logger.info("Target handler state: {0}", state) + if state == u"enabled": self.handle_enable(ext_handler_i) elif state == u"disabled": self.handle_disable(ext_handler_i) @@ -237,21 +240,17 @@ class ExtHandlersHandler(object): ext_handler_i.report_event(message=ustr(e), is_success=False) def handle_enable(self, ext_handler_i): - old_ext_handler_i = ext_handler_i.get_installed_ext_handler() if old_ext_handler_i is not None and \ old_ext_handler_i.version_gt(ext_handler_i): raise ExtensionError(u"Downgrade not allowed") - handler_state = ext_handler_i.get_handler_state() - ext_handler_i.logger.info("Current handler state is: {0}", handler_state) + ext_handler_i.logger.info("[Enable] current handler state is: {0}", + handler_state.lower()) if handler_state == ExtHandlerState.NotInstalled: ext_handler_i.set_handler_state(ExtHandlerState.NotInstalled) - ext_handler_i.download() - ext_handler_i.update_settings() - if old_ext_handler_i is None: ext_handler_i.install() elif ext_handler_i.version_gt(old_ext_handler_i): @@ -268,13 +267,15 @@ class ExtHandlersHandler(object): def handle_disable(self, ext_handler_i): handler_state = ext_handler_i.get_handler_state() - ext_handler_i.logger.info("Current handler state is: {0}", handler_state) + ext_handler_i.logger.info("[Disable] current handler state is: {0}", + handler_state.lower()) if handler_state == ExtHandlerState.Enabled: ext_handler_i.disable() def handle_uninstall(self, ext_handler_i): handler_state = ext_handler_i.get_handler_state() - ext_handler_i.logger.info("Current handler state is: {0}", handler_state) + ext_handler_i.logger.info("[Uninstall] current handler state is: {0}", + handler_state.lower()) if handler_state != ExtHandlerState.NotInstalled: if handler_state == ExtHandlerState.Enabled: ext_handler_i.disable() @@ -299,7 +300,7 @@ class ExtHandlersHandler(object): try: self.protocol.report_vm_status(vm_status) if self.log_report: - logger.verbose("Successfully reported vm agent status") + logger.verbose("Completed vm agent status report") except ProtocolError as e: message = "Failed to report vm agent status: {0}".format(e) add_event(AGENT_NAME, version=CURRENT_VERSION, is_success=False, message=message) @@ -510,7 +511,7 @@ class ExtHandlerInstance(object): op=self.operation, is_success=is_success) def download(self): - self.logger.info("Download extension package") + self.logger.verbose("Download extension package") self.set_operation(WALAEventOperation.Download) if self.pkg is None: raise ExtensionError("No package uri found") @@ -527,7 +528,7 @@ class ExtHandlerInstance(object): if package is None: raise ExtensionError("Failed to download extension") - self.logger.info("Unpack extension package") + self.logger.verbose("Unpack extension package") pkg_file = os.path.join(conf.get_lib_dir(), os.path.basename(uri.uri) + ".zip") try: @@ -569,38 +570,38 @@ class ExtHandlerInstance(object): self.create_handler_env() def enable(self): - self.logger.info("Enable extension.") self.set_operation(WALAEventOperation.Enable) - man = self.load_manifest() - self.launch_command(man.get_enable_command(), timeout=300) + enable_cmd = man.get_enable_command() + self.logger.info("Enable extension [{0}]".format(enable_cmd)) + self.launch_command(enable_cmd, timeout=300) self.set_handler_state(ExtHandlerState.Enabled) self.set_handler_status(status="Ready", message="Plugin enabled") def disable(self): - self.logger.info("Disable extension.") self.set_operation(WALAEventOperation.Disable) - man = self.load_manifest() - self.launch_command(man.get_disable_command(), timeout=900) + disable_cmd = man.get_disable_command() + self.logger.info("Disable extension [{0}]".format(disable_cmd)) + self.launch_command(disable_cmd, timeout=900) self.set_handler_state(ExtHandlerState.Installed) self.set_handler_status(status="NotReady", message="Plugin disabled") def install(self): - self.logger.info("Install extension.") - self.set_operation(WALAEventOperation.Install) - man = self.load_manifest() - self.launch_command(man.get_install_command(), timeout=900) + install_cmd = man.get_install_command() + self.logger.info("Install extension [{0}]".format(install_cmd)) + self.set_operation(WALAEventOperation.Install) + self.launch_command(install_cmd, timeout=900) self.set_handler_state(ExtHandlerState.Installed) def uninstall(self): - self.logger.info("Uninstall extension.") - self.set_operation(WALAEventOperation.UnInstall) - try: + self.set_operation(WALAEventOperation.UnInstall) man = self.load_manifest() - self.launch_command(man.get_uninstall_command()) + uninstall_cmd = man.get_uninstall_command() + self.logger.info("Uninstall extension [{0}]".format(uninstall_cmd)) + self.launch_command(uninstall_cmd) except ExtensionError as e: self.report_event(message=ustr(e), is_success=False) @@ -608,18 +609,19 @@ class ExtHandlerInstance(object): try: base_dir = self.get_base_dir() if os.path.isdir(base_dir): - self.logger.info("Remove ext handler dir: {0}", base_dir) + self.logger.info("Remove extension handler directory: {0}", + base_dir) shutil.rmtree(base_dir) except IOError as e: - message = "Failed to rm ext handler dir: {0}".format(e) + message = "Failed to remove extension handler directory: {0}".format(e) self.report_event(message=message, is_success=False) def update(self): - self.logger.info("Update extension.") self.set_operation(WALAEventOperation.Update) - man = self.load_manifest() - self.launch_command(man.get_update_command(), timeout=900) + update_cmd = man.get_update_command() + self.logger.info("Update extension [{0}]".format(update_cmd)) + self.launch_command(update_cmd, timeout=900) def update_with_install(self): man = self.load_manifest() @@ -709,23 +711,24 @@ class ExtHandlerInstance(object): heartbeat = json.loads(heartbeat_json)[0]['heartbeat'] except IOError as e: raise ExtensionError("Failed to get heartbeat file:{0}".format(e)) - except ValueError as e: + except (ValueError, KeyError) as e: raise ExtensionError("Malformed heartbeat file: {0}".format(e)) return heartbeat def is_responsive(self, heartbeat_file): - last_update=int(time.time() - os.stat(heartbeat_file).st_mtime) - return last_update <= 600 # updated within the last 10 min + last_update = int(time.time() - os.stat(heartbeat_file).st_mtime) + return last_update <= 600 # updated within the last 10 min def launch_command(self, cmd, timeout=300): - self.logger.info("Launch command:{0}", cmd) + self.logger.verbose("Launch command: [{0}]", cmd) base_dir = self.get_base_dir() try: devnull = open(os.devnull, 'w') child = subprocess.Popen(base_dir + "/" + cmd, shell=True, cwd=base_dir, - stdout=devnull) + stdout=devnull, + env=os.environ) except Exception as e: #TODO do not catch all exception raise ExtensionError("Failed to launch: {0}, {1}".format(cmd, e)) diff --git a/azurelinuxagent/ga/update.py b/azurelinuxagent/ga/update.py index 59bc70c..203bb41 100644 --- a/azurelinuxagent/ga/update.py +++ b/azurelinuxagent/ga/update.py @@ -27,6 +27,7 @@ import signal import subprocess import sys import time +import traceback import zipfile import azurelinuxagent.common.conf as conf @@ -40,6 +41,7 @@ from azurelinuxagent.common.exception import UpdateError, ProtocolError from azurelinuxagent.common.future import ustr from azurelinuxagent.common.osutil import get_osutil from azurelinuxagent.common.protocol import get_protocol_util +from azurelinuxagent.common.protocol.hostplugin import HostPluginProtocol from azurelinuxagent.common.utils.flexible_version import FlexibleVersion from azurelinuxagent.common.version import AGENT_NAME, AGENT_VERSION, AGENT_LONG_VERSION, \ AGENT_DIR_GLOB, AGENT_PKG_GLOB, \ @@ -49,7 +51,6 @@ from azurelinuxagent.common.version import AGENT_NAME, AGENT_VERSION, AGENT_LONG from azurelinuxagent.ga.exthandlers import HandlerManifest - AGENT_ERROR_FILE = "error.json" # File name for agent error record AGENT_MANIFEST_FILE = "HandlerManifest.json" @@ -140,14 +141,24 @@ class UpdateHandler(object): cmds, cwd=agent_dir, stdout=sys.stdout, - stderr=sys.stderr) + stderr=sys.stderr, + env=os.environ) + + logger.verbose(u"Agent {0} launched with command '{1}'", agent_name, agent_cmd) - logger.info(u"Agent {0} launched with command '{1}'", agent_name, agent_cmd) + # If the most current agent is the installed agent and update is enabled, + # assume updates are likely available and poll every second. + # This reduces the start-up impact of finding / launching agent updates on + # fresh VMs. + if latest_agent is None and conf.get_autoupdate_enabled(): + poll_interval = 1 + else: + poll_interval = CHILD_POLL_INTERVAL ret = None start_time = time.time() while (time.time() - start_time) < CHILD_HEALTH_INTERVAL: - time.sleep(CHILD_POLL_INTERVAL) + time.sleep(poll_interval) ret = self.child_process.poll() if ret is not None: break @@ -249,6 +260,7 @@ class UpdateHandler(object): except Exception as e: logger.warn(u"Agent {0} failed with exception: {1}", CURRENT_AGENT, ustr(e)) + logger.warn(traceback.format_exc()) sys.exit(1) return @@ -328,7 +340,7 @@ class UpdateHandler(object): return False family = conf.get_autoupdate_gafamily() - logger.info("Checking for agent family {0} updates", family) + logger.verbose("Checking for agent family {0} updates", family) self.last_attempt_time = now try: @@ -348,7 +360,7 @@ class UpdateHandler(object): manifests = [m for m in manifest_list.vmAgentManifests \ if m.family == family and len(m.versionsManifestUris) > 0] if len(manifests) == 0: - logger.info(u"Incarnation {0} has no agent family {1} updates", etag, family) + logger.verbose(u"Incarnation {0} has no agent family {1} updates", etag, family) return False try: @@ -595,7 +607,7 @@ class GuestAgent(object): self.version = FlexibleVersion(version) location = u"disk" if path is not None else u"package" - logger.info(u"Instantiating Agent {0} from {1}", self.name, location) + logger.verbose(u"Instantiating Agent {0} from {1}", self.name, location) self.error = None self._load_error() @@ -651,14 +663,14 @@ class GuestAgent(object): def _ensure_downloaded(self): try: - logger.info(u"Ensuring Agent {0} is downloaded", self.name) + logger.verbose(u"Ensuring Agent {0} is downloaded", self.name) if self.is_blacklisted: - logger.info(u"Agent {0} is blacklisted - skipping download", self.name) + logger.warn(u"Agent {0} is blacklisted - skipping download", self.name) return if self.is_downloaded: - logger.info(u"Agent {0} was previously downloaded - skipping download", self.name) + logger.verbose(u"Agent {0} was previously downloaded - skipping download", self.name) self._load_manifest() return @@ -672,7 +684,7 @@ class GuestAgent(object): self._load_error() msg = u"Agent {0} downloaded successfully".format(self.name) - logger.info(msg) + logger.verbose(msg) add_event( AGENT_NAME, version=self.version, @@ -698,18 +710,24 @@ class GuestAgent(object): def _download(self): for uri in self.pkg.uris: - if self._fetch(uri.uri): + if not HostPluginProtocol.is_default_channel() and self._fetch(uri.uri): break - else: - if self.host is not None and self.host.ensure_initialized(): + elif self.host is not None and self.host.ensure_initialized(): + if not HostPluginProtocol.is_default_channel(): logger.warn("Download unsuccessful, falling back to host plugin") - uri, headers = self.host.get_artifact_request(uri.uri, self.host.manifest_uri) - if uri is not None \ - and headers is not None \ - and self._fetch(uri, headers=headers): - break else: - logger.warn("Download unsuccessful, host plugin not available") + logger.verbose("Using host plugin as default channel") + + uri, headers = self.host.get_artifact_request(uri.uri, self.host.manifest_uri) + if self._fetch(uri, headers=headers): + if not HostPluginProtocol.is_default_channel(): + logger.verbose("Setting host plugin as default channel") + HostPluginProtocol.set_default_channel(True) + break + else: + logger.warn("Host plugin download unsuccessful") + else: + logger.error("No download channels available") if not os.path.isfile(self.get_agent_pkg_path()): msg = u"Unable to download Agent {0} from any URI".format(self.name) @@ -731,7 +749,10 @@ class GuestAgent(object): fileutil.write_file(self.get_agent_pkg_path(), bytearray(package), asbin=True) - logger.info(u"Agent {0} downloaded from {1}", self.name, uri) + logger.verbose(u"Agent {0} downloaded from {1}", self.name, uri) + else: + logger.verbose("Fetch was unsuccessful [{0}]", + HostPluginProtocol.read_response_error(resp)) except restutil.HttpError as http_error: logger.verbose(u"Agent {0} download from {1} failed [{2}]", self.name, @@ -744,7 +765,7 @@ class GuestAgent(object): if self.error is None: self.error = GuestAgentError(self.get_agent_error_file()) self.error.load() - logger.info(u"Agent {0} error state: {1}", self.name, ustr(self.error)) + logger.verbose(u"Agent {0} error state: {1}", self.name, ustr(self.error)) except Exception as e: logger.warn(u"Agent {0} failed loading error state: {1}", self.name, ustr(e)) return @@ -780,7 +801,7 @@ class GuestAgent(object): ustr(e)) raise UpdateError(msg) - logger.info( + logger.verbose( u"Agent {0} loaded manifest from {1}", self.name, self.get_agent_manifest_path()) @@ -810,7 +831,7 @@ class GuestAgent(object): self.get_agent_dir()) raise UpdateError(msg) - logger.info( + logger.verbose( u"Agent {0} unpacked successfully to {1}", self.name, self.get_agent_dir()) |