def setUp(self): print( '\n\n============================================================================================' ) waagent.LoggerInit('/var/log/waagent.log', '/dev/stdout') waagent.Log("%s started to handle." % (ExtensionShortName)) global hutil hutil = Util.HandlerUtility(waagent.Log, waagent.Error) hutil.do_parse_context('TEST') global MyPatching MyPatching = FakePatching(hutil) if MyPatching is None: sys.exit(1) distro = DistInfo()[0] if 'centos' in distro or 'Oracle' in distro or 'redhat' in distro: MyPatching.cron_restart_cmd = 'service crond restart' try: os.remove('mrseq') except: pass waagent.SetFileContents(MyPatching.package_downloaded_path, '') waagent.SetFileContents(MyPatching.package_patched_path, '')
def download(self): # Read the latest configuration for scheduled task settings = json.loads( waagent.GetFileContents(self.scheduled_configs_file)) self.parse_settings(settings) self.provide_vm_status_test(StatusTest["Scheduled"]) if not self.check_vm_idle(StatusTest["Scheduled"]): return if self.exists_stop_flag(): self.hutil.log_and_syslog( logging.INFO, "Downloading patches is stopped/canceled") return waagent.SetFileContents(self.package_downloaded_path, '') waagent.SetFileContents(self.package_patched_path, '') start_download_time = time.time() # Installing security patches is mandatory self._download(self.category_required) if self.category == self.category_all: self._download(self.category_all) end_download_time = time.time() waagent.AddExtensionEvent( name=self.hutil.get_name(), op=waagent.WALAEventOperation.Download, isSuccess=True, version=Version, message=" ".join([ "Real downloading time is", str(round(end_download_time - start_download_time, 3)), "s" ]))
def download(self): if self.exists_stop_flag(): self.hutil.log("Downloading patches is stopped/canceled") return waagent.SetFileContents(self.package_downloaded_path, '') waagent.SetFileContents(self.package_patched_path, '') # Installing security patches is mandatory self._download(self.category_required) if self.category == self.category_all: self._download(self.category_all)
def _parse_config(self, ctxt): config = None try: config = json.loads(ctxt) except: self.error('JSON exception decoding ' + ctxt) if config == None: self.error("JSON error processing settings file:" + ctxt) else: handlerSettings = config['runtimeSettings'][0]['handlerSettings'] if handlerSettings.has_key('protectedSettings') and \ handlerSettings.has_key("protectedSettingsCertThumbprint") and \ handlerSettings['protectedSettings'] is not None and \ handlerSettings["protectedSettingsCertThumbprint"] is not None: protectedSettings = handlerSettings['protectedSettings'] thumb = handlerSettings['protectedSettingsCertThumbprint'] cert = waagent.LibDir + '/' + thumb + '.crt' pkey = waagent.LibDir + '/' + thumb + '.prv' waagent.SetFileContents('/tmp/kk', protectedSettings) cleartxt = None cleartxt = waagent.RunGetOutput("base64 -d /tmp/kk | openssl smime -inform DER -decrypt -recip " + cert + " -inkey " + pkey)[1] os.remove("/tmp/kk") if cleartxt == None: self.error("OpenSSh decode error using thumbprint " + thumb) do_exit(1,operation,'error','1', operation + ' Failed') jctxt = '' try: jctxt = json.loads(cleartxt) except: self.error('JSON exception decoding ' + cleartxt) handlerSettings['protectedSettings'] = jctxt self.log('Config decoded correctly.') return config
def _parse_config(self, ctxt): config = None try: config = json.loads(ctxt) except: self.error('JSON exception decoding ' + ctxt) if config == None: self.error("JSON error processing settings file:" + ctxt) else: handlerSettings = config['runtimeSettings'][0]['handlerSettings'] if 'protectedSettings' in handlerSettings and \ "protectedSettingsCertThumbprint" in handlerSettings and \ handlerSettings['protectedSettings'] is not None and \ handlerSettings["protectedSettingsCertThumbprint"] is not None: protectedSettings = handlerSettings['protectedSettings'] thumb = handlerSettings['protectedSettingsCertThumbprint'] cert = waagent.LibDir + '/' + thumb + '.crt' pkey = waagent.LibDir + '/' + thumb + '.prv' f = tempfile.NamedTemporaryFile(delete=False) f.close() waagent.SetFileContents(f.name,config['runtimeSettings'][0]['handlerSettings']['protectedSettings']) cleartxt = None if 'NS-BSD' in platform.system(): # base64 tool is not available with NSBSD, use openssl cleartxt = waagent.RunGetOutput(self.patching.openssl_path + " base64 -d -A -in " + f.name + " | " + self.patching.openssl_path + " smime -inform DER -decrypt -recip " + cert + " -inkey " + pkey)[1] else: cleartxt = waagent.RunGetOutput(self.patching.base64_path + " -d " + f.name + " | " + self.patching.openssl_path + " smime -inform DER -decrypt -recip " + cert + " -inkey " + pkey)[1] jctxt = {} try: jctxt = json.loads(cleartxt) except: self.error('JSON exception decoding ' + cleartxt) handlerSettings['protectedSettings'] = jctxt self.log('Config decoded correctly.') return config
def _parse_config(self, ctxt): config = None try: config = json.loads(ctxt) except: self.error('JSON exception decoding ' + ctxt) if config == None: self.error("JSON error processing settings file:" + ctxt) else: handlerSettings = config['runtimeSettings'][0]['handlerSettings'] if handlerSettings.has_key('protectedSettings') and \ handlerSettings.has_key("protectedSettingsCertThumbprint") and \ handlerSettings['protectedSettings'] is not None and \ handlerSettings["protectedSettingsCertThumbprint"] is not None: protectedSettings = handlerSettings['protectedSettings'] thumb = handlerSettings['protectedSettingsCertThumbprint'] cert = waagent.LibDir + '/' + thumb + '.crt' pkey = waagent.LibDir + '/' + thumb + '.prv' f = tempfile.NamedTemporaryFile(delete=False) f.close() waagent.SetFileContents(f.name, config['runtimeSettings'][0]['handlerSettings']['protectedSettings']) cleartxt = None cleartxt = waagent.RunGetOutput(self.patching.base64_path + " -d " + f.name + " | " + self.patching.openssl_path + " smime -inform DER -decrypt -recip " + cert + " -inkey " + pkey)[1] if cleartxt == None: self.error("OpenSSh decode error using thumbprint " + thumb) do_exit(1, self.operation,'error','1', self.operation + ' Failed') jctxt = '' try: jctxt = json.loads(cleartxt) except: self.error('JSON exception decoding ' + cleartxt) handlerSettings['protectedSettings'] = jctxt self.log('Config decoded correctly.') return config
def enable(hutil): pidFile = os.path.join(aem.LibDir, "pid"); #Check whether monitor process is running. #If it does, return. Otherwise clear pid file if os.path.isfile(pidFile): pid = waagent.GetFileContents(pidFile) if os.path.isdir(os.path.join("/proc", pid)): if hutil.is_seq_smaller(): hutil.do_exit(0, 'Enable', 'success', '0', 'Azure Enhanced Monitor is already running') else: waagent.Log("Stop old daemon: {0}".format(pid)) os.kill(int(pid), 9) os.remove(pidFile) args = [os.path.join(os.getcwd(), __file__), "daemon"] devnull = open(os.devnull, 'w') child = subprocess.Popen(args, stdout=devnull, stderr=devnull) if child.pid == None or child.pid < 1: hutil.do_exit(1, 'Enable', 'error', '1', 'Failed to launch Azure Enhanced Monitor') else: hutil.save_seq() waagent.SetFileContents(pidFile, str(child.pid)) waagent.Log(("Daemon pid: {0}").format(child.pid)) hutil.do_exit(0, 'Enable', 'success', '0', 'Azure Enhanced Monitor is enabled')
def update_settings_file(self): if (self._context._config['runtimeSettings'][0]['handlerSettings'].get( 'protectedSettings') != None): del self._context._config['runtimeSettings'][0]['handlerSettings'][ 'protectedSettings'] self.log("removing the protected settings") waagent.SetFileContents(self._context._settings_file, json.dumps(self._context._config))
def patch_one_off(self): """ Called when startTime is empty string, which means a on-demand patch. """ global start_patch_time start_patch_time = time.time() self.hutil.log("Going to patch one-off") waagent.SetFileContents(self.package_downloaded_path, '') waagent.SetFileContents(self.package_patched_path, '') retcode, patchlist_required = self.check(self.category_required) if retcode > 0: self.hutil.error("Failed to check valid upgrades") sys.exit(1) if not patchlist_required: self.hutil.log("No packages are available for update.") else: self._patch(self.category_required, patchlist_required) if self.category == self.category_all: if not self.exists_stop_flag(): self.hutil.log("Going to sleep for " + str(self.gap_between_stage) + "s") time.sleep(self.gap_between_stage) retcode, patchlist_other = self.check(self.category_all) if retcode > 0: self.hutil.error("Failed to check valid upgrades") sys.exit(1) patchlist_other = [ pkg for pkg in patchlist_other if pkg not in patchlist_required ] if not patchlist_other: self.hutil.log("No packages are available for update.") else: self._patch(self.category_all, patchlist_other) else: self.hutil.log("Installing patches (Category:" + self.category_all + ") is stopped/canceled") shutil.copy2(self.package_patched_path, self.package_downloaded_path) self.delete_stop_flag() #self.report() self.reboot_if_required()
def save_local_file(src, dst, hutil): seqNo = hutil.get_seq_no() download_dir = prepare_download_dir(seqNo) file_path = os.path.join(download_dir, dst) try: waagent.SetFileContents(file_path, src) except Exception, e: hutil.log_and_syslog(logging.ERROR, ("Failed to save file from user's configuration " "with error {0}").format(e)) raise
def _parse_config(self, config_txt): # pre : config_txt is a text string containing JSON configuration settings # post: handlerSettings is initialized with these settings and the config # object is returned. If an error occurs, None is returned. if not config_txt: self.error('empty config, nothing to parse') return None config = None try: config = json.loads(config_txt) except: self.error('invalid config, could not parse: ' + str(config_txt)) if config: handlerSettings = config['runtimeSettings'][0]['handlerSettings'] # skip unnecessary decryption of protected settings for query status # operations, to avoid timeouts in case of multiple settings files if handlerSettings.has_key('publicSettings'): ps = handlerSettings.get('publicSettings') op = ps.get(CommonVariables.EncryptionEncryptionOperationKey) if op == CommonVariables.QueryEncryptionStatus: return config if handlerSettings.has_key('protectedSettings') and \ handlerSettings.has_key("protectedSettingsCertThumbprint") and \ handlerSettings['protectedSettings'] is not None and \ handlerSettings["protectedSettingsCertThumbprint"] is not None: thumb = handlerSettings['protectedSettingsCertThumbprint'] cert = waagent.LibDir + '/' + thumb + '.crt' pkey = waagent.LibDir + '/' + thumb + '.prv' f = tempfile.NamedTemporaryFile(delete=False) f.close() waagent.SetFileContents( f.name, config['runtimeSettings'][0]['handlerSettings'] ['protectedSettings']) cleartxt = None cleartxt = waagent.RunGetOutput( self.patching.base64_path + " -d " + f.name + " | " + self.patching.openssl_path + " smime -inform DER -decrypt -recip " + cert + " -inkey " + pkey)[1] if cleartxt == None: self.error("OpenSSh decode error using thumbprint " + thumb) self.do_exit(1, self.operation, 'error', '1', self.operation + ' Failed') jctxt = '' try: jctxt = json.loads(cleartxt) except: self.error('JSON exception loading protected settings') handlerSettings['protectedSettings'] = jctxt return config
def _save_cert_str_as_file(cert_txt, file_name): cert_start = cert_txt.find(BeginCertificateTag) if (cert_start >= 0): cert_txt = cert_txt[cert_start + len(BeginCertificateTag):] cert_end = cert_txt.find(EndCertificateTag) if (cert_end >= 0): cert_txt = cert_txt[:cert_end] cert_txt = cert_txt.strip() cert_txt = "{0}\n{1}\n{2}\n".format(BeginCertificateTag, cert_txt, EndCertificateTag) waagent.SetFileContents(file_name, cert_txt)
def setUp(self): print '\n\n============================================================================================' waagent.LoggerInit('/var/log/waagent.log', '/dev/stdout') waagent.Log("%s started to handle." % (ExtensionShortName)) global protect_settings protect_settings = json.loads(contents) global hutil hutil = Util.HandlerUtility(waagent.Log, waagent.Error, ExtensionShortName) global MyPatching MyPatching = FakePatching(hutil) if MyPatching == None: sys.exit(1) try: os.remove('mrseq') except: pass waagent.SetFileContents(MyPatching.package_downloaded_path, '') waagent.SetFileContents(MyPatching.package_patched_path, '')
def _parse_config(self, config_txt): config = None try: config = json.loads(config_txt) except: self.error('JSON exception decoding ' + config_txt) if config == None: self.error("JSON error processing settings file:" + config_txt) else: handlerSettings = config['runtimeSettings'][0]['handlerSettings'] # skip unnecessary decryption of protected settings for query status # operations, to avoid timeouts in case of multiple settings files if handlerSettings.has_key('publicSettings'): ps = handlerSettings.get('publicSettings') op = ps.get(CommonVariables.EncryptionEncryptionOperationKey) if op == CommonVariables.QueryEncryptionStatus: return config if handlerSettings.has_key('protectedSettings') and \ handlerSettings.has_key("protectedSettingsCertThumbprint") and \ handlerSettings['protectedSettings'] is not None and \ handlerSettings["protectedSettingsCertThumbprint"] is not None: thumb = handlerSettings['protectedSettingsCertThumbprint'] cert = waagent.LibDir + '/' + thumb + '.crt' pkey = waagent.LibDir + '/' + thumb + '.prv' f = tempfile.NamedTemporaryFile(delete=False) f.close() waagent.SetFileContents( f.name, config['runtimeSettings'][0]['handlerSettings'] ['protectedSettings']) cleartxt = None cleartxt = waagent.RunGetOutput( self.patching.base64_path + " -d " + f.name + " | " + self.patching.openssl_path + " smime -inform DER -decrypt -recip " + cert + " -inkey " + pkey)[1] if cleartxt == None: self.error("OpenSSh decode error using thumbprint " + thumb) self.do_exit(1, self.operation, 'error', '1', self.operation + ' Failed') jctxt = '' try: jctxt = json.loads(cleartxt) except: self.error('JSON exception loading protected settings') handlerSettings['protectedSettings'] = jctxt return config
def enable(self): if self.stop: self.stop_download() self.create_stop_flag() return self.delete_stop_flag() if not self.disabled and self.oneoff: script_file_path = os.path.realpath(sys.argv[0]) os.system(' '.join( ['python', script_file_path, '-oneoff', '>/dev/null 2>&1 &'])) else: waagent.SetFileContents(self.history_scheduled, '') self.set_download_cron() self.set_patch_cron() self.restart_cron()
def _add_dns_search(domain_fqdn): need_update = False new_content = '' for line in (open('/etc/resolv.conf','r')).readlines(): if re.match('^search.* {0}'.format(domain_fqdn), line): waagent.Log('{0} was already added in /etc/resolv.conf'.format(domain_fqdn)) return if re.match('^search', line): need_update = True new_content += line.replace('search', 'search {0}'.format(domain_fqdn)) else: new_content += line if need_update: waagent.Log('Adding {0} to /etc/resolv.conf'.format(domain_fqdn)) waagent.SetFileContents('/etc/resolv.conf', new_content)
def enable(): hutil = parse_context('Enable') try: #Check whether monitor process is running. #If it does, return. Otherwise clear pid file hutil.log("enable() called.") if os.path.isfile(DaemonPidFilePath): pid = waagent.GetFileContents(DaemonPidFilePath) hutil.log("Discovered daemon pid: {0}".format(pid)) if os.path.isdir(os.path.join("/proc", pid)) and _is_nodemanager_daemon(pid): if hutil.is_seq_smaller(): hutil.log("Sequence is smaller skip killing") hutil.do_exit(0, 'Enable', 'success', '0', 'HPC Linux node manager daemon is already running') else: hutil.log("Stop old daemon: {0}".format(pid)) os.killpg(int(pid), 9) hutil.log("Remove the daemon pid file: {0}".format(DaemonPidFilePath)) os.remove(DaemonPidFilePath) args = [os.path.join(os.getcwd(), __file__), "daemon"] devnull = open(os.devnull, 'w') hutil.log("Starting daemon process") child = subprocess.Popen(args, stdout=devnull, stderr=devnull, preexec_fn=os.setsid) if child.pid is None or child.pid < 1: hutil.log("failed to start the daemon process") hutil.do_exit(1, 'Enable', 'error', '1', 'Failed to launch HPC Linux node manager daemon') else: hutil.log("started the daemon process, save seq") hutil.save_seq() hutil.log("started the daemon process, save pid {0}".format(child.pid)) waagent.SetFileContents(DaemonPidFilePath, str(child.pid)) #Sleep 3 seconds to check if the process is still running time.sleep(3) if child.poll() is None: hutil.log("3 seconds later, success, Daemon pid: {0}".format(child.pid)) hutil.do_exit(0, 'Enable', 'success', '0', 'HPC Linux node manager daemon is enabled') else: hutil.log("3 seconds later, failed, Daemon pid: None") hutil.do_exit(3, 'Enable', 'error', '3', 'Failed to launch HPC Linux node manager daemon') except Exception as e: hutil.log("Failed to enable the extension with error: %s, stack trace: %s" %(str(e), traceback.format_exc())) hutil.do_exit(2, 'Enable','error','2', "Enable failed. {0} {1}".format(str(e), traceback.format_exc()))
def test_hwchangeinfo(self): netinfo = aem.NetworkInfo() testHwInfoFile = "/tmp/HwInfo" aem.HwInfoFile = testHwInfoFile if os.path.isfile(testHwInfoFile): os.remove(testHwInfoFile) hwChangeInfo = aem.HardwareChangeInfo(netinfo) self.assertNotEquals(None, hwChangeInfo.getLastHardwareChange()) self.assertTrue(os.path.isfile, aem.HwInfoFile) #No hardware change lastChange = hwChangeInfo.getLastHardwareChange() hwChangeInfo = aem.HardwareChangeInfo(netinfo) self.assertEquals(lastChange, hwChangeInfo.getLastHardwareChange()) #Create mock hardware waagent.SetFileContents(testHwInfoFile, ("0\nma-ca-sa-ds-02")) hwChangeInfo = aem.HardwareChangeInfo(netinfo) self.assertNotEquals(None, hwChangeInfo.getLastHardwareChange())
def _save_cert_str_as_file(cert_txt, file_name): cert_txt = cert_txt.replace(BeginCertificateTag, '').replace(EndCertificateTag, '').replace(' ', '\n') cert_txt = BeginCertificateTag + cert_txt + EndCertificateTag + '\n' waagent.SetFileContents(file_name, cert_txt)
def set_last_seq(self, seq): waagent.SetFileContents('mrseq', str(seq))
def do_heartbeat_report(self, heartbeat_file, status, code, message): # heartbeat health_report = '[{"version":"1.0","heartbeat":{"status":"' + status + '","code":"' + code + '","Message":"' + message + '"}}]' if waagent.SetFileContents(heartbeat_file, health_report) == None: self.error('Unable to wite heartbeat info to ' + heartbeat_file)
def _set_most_recent_seq(self, seq): waagent.SetFileContents('mrseq', str(seq))
def scrub_settings_file(self): content = waagent.GetFileContents(self._context._settings_file) redacted = HandlerUtility.redact_protected_settings(content) waagent.SetFileContents(self._context._settings_file, redacted)
def parse_settings(self, settings): disabled = settings.get("disabled") if disabled is None or str( disabled).lower() not in ConfigOptions.disabled: msg = "The value of parameter \"disabled\" is empty or invalid. Set it False by default." self.hutil.log_and_syslog(logging.WARNING, msg) self.disabled = False else: if str(disabled).lower() == "true": self.disabled = True else: self.disabled = False self.current_configs["disabled"] = str(self.disabled) if self.disabled: msg = "The extension is disabled." self.hutil.log_and_syslog(logging.WARNING, msg) return stop = settings.get("stop") if stop is None or str(stop).lower() not in ConfigOptions.stop: msg = "The value of parameter \"stop\" is empty or invalid. Set it False by default." self.hutil.log_and_syslog(logging.WARNING, msg) self.stop = False else: if str(stop).lower() == 'true': self.stop = True else: self.stop = False self.current_configs["stop"] = str(self.stop) reboot_after_patch = settings.get("rebootAfterPatch") if reboot_after_patch is None or reboot_after_patch.lower( ) not in ConfigOptions.reboot_after_patch: msg = "The value of parameter \"rebootAfterPatch\" is empty or invalid. Set it \"rebootifneed\" by default." self.hutil.log_and_syslog(logging.WARNING, msg) self.reboot_after_patch = ConfigOptions.reboot_after_patch[0] else: self.reboot_after_patch = reboot_after_patch.lower() waagent.AddExtensionEvent(name=self.hutil.get_name(), op=waagent.WALAEventOperation.Enable, isSuccess=True, version=Version, message="rebootAfterPatch=" + self.reboot_after_patch) self.current_configs["rebootAfterPatch"] = self.reboot_after_patch category = settings.get('category') if category is None or category.lower( ) not in ConfigOptions.category.values(): msg = "The value of parameter \"category\" is empty or invalid. Set it " + self.category_required + " by default." self.hutil.log_and_syslog(logging.WARNING, msg) self.category = self.category_required else: self.category = category.lower() waagent.AddExtensionEvent(name=self.hutil.get_name(), op=waagent.WALAEventOperation.Enable, isSuccess=True, version=Version, message="category=" + self.category) self.current_configs["category"] = self.category check_hrmin = re.compile(r'^[0-9]{1,2}:[0-9]{1,2}$') install_duration = settings.get('installDuration') if install_duration is None or not re.match(check_hrmin, install_duration): msg = "The value of parameter \"installDuration\" is empty or invalid. Set it 1 hour by default." self.hutil.log_and_syslog(logging.WARNING, msg) self.install_duration = 3600 self.current_configs["installDuration"] = "01:00" else: hr_min = install_duration.split(':') self.install_duration = int(hr_min[0]) * 3600 + int(hr_min[1]) * 60 self.current_configs["installDuration"] = install_duration if self.install_duration <= 300: msg = "The value of parameter \"installDuration\" is smaller than 5 minutes. The extension will not reserve 5 minutes for reboot. It is recommended to set \"installDuration\" more than 30 minutes." self.hutil.log_and_syslog(logging.WARNING, msg) else: msg = "The extension will reserve 5 minutes for reboot." # 5 min for reboot self.install_duration -= 300 self.hutil.log_and_syslog(logging.INFO, msg) # The parameter "downloadDuration" is not exposed to users. So there's no log. download_duration = settings.get('downloadDuration') if download_duration is not None and re.match(check_hrmin, download_duration): hr_min = download_duration.split(':') self.download_duration = int(hr_min[0]) * 3600 + int( hr_min[1]) * 60 oneoff = settings.get('oneoff') if oneoff is None or str(oneoff).lower() not in ConfigOptions.oneoff: msg = "The value of parameter \"oneoff\" is empty or invalid. Set it False by default." self.hutil.log_and_syslog(logging.WARNING, msg) self.oneoff = False else: if str(oneoff).lower() == "true": self.oneoff = True msg = "The extension will run in one-off mode." else: self.oneoff = False msg = "The extension will run in scheduled task mode." self.hutil.log_and_syslog(logging.INFO, msg) self.current_configs["oneoff"] = str(self.oneoff) if not self.oneoff: start_time = settings.get('startTime') if start_time is None or not re.match(check_hrmin, start_time): msg = "The parameter \"startTime\" is empty or invalid. It defaults to 03:00." self.hutil.log_and_syslog(logging.WARNING, msg) start_time = "03:00" self.start_time = datetime.datetime.strptime(start_time, '%H:%M') self.download_time = self.start_time - datetime.timedelta( seconds=self.download_duration) self.current_configs["startTime"] = start_time day_of_week = settings.get("dayOfWeek") if day_of_week is None or day_of_week == "": msg = "The parameter \"dayOfWeek\" is empty. dayOfWeek defaults to Everyday." self.hutil.log_and_syslog(logging.WARNING, msg) day_of_week = "everyday" self.day_of_week = ConfigOptions.day_of_week["everyday"] else: for day in day_of_week.split('|'): day = day.strip().lower() if day not in ConfigOptions.day_of_week: msg = "The parameter \"dayOfWeek\" is invalid. dayOfWeek defaults to Everyday." self.hutil.log_and_syslog(logging.WARNING, msg) day_of_week = "everyday" break if "everyday" in day_of_week: self.day_of_week = ConfigOptions.day_of_week["everyday"] else: self.day_of_week = [ ConfigOptions.day_of_week[day.strip().lower()] for day in day_of_week.split('|') ] waagent.AddExtensionEvent(name=self.hutil.get_name(), op=waagent.WALAEventOperation.Enable, isSuccess=True, version=Version, message="dayOfWeek=" + day_of_week) self.current_configs["dayOfWeek"] = day_of_week interval_of_weeks = settings.get('intervalOfWeeks') if interval_of_weeks is None or interval_of_weeks not in ConfigOptions.interval_of_weeks: msg = "The parameter \"intervalOfWeeks\" is empty or invalid. intervalOfWeeks defaults to 1." self.hutil.log_and_syslog(logging.WARNING, msg) self.interval_of_weeks = '1' else: self.interval_of_weeks = interval_of_weeks waagent.AddExtensionEvent(name=self.hutil.get_name(), op=waagent.WALAEventOperation.Enable, isSuccess=True, version=Version, message="intervalOfWeeks=" + self.interval_of_weeks) self.current_configs["intervalOfWeeks"] = self.interval_of_weeks # Save the latest configuration for scheduled task to avoid one-off mode's affection waagent.SetFileContents(self.scheduled_configs_file, json.dumps(self.current_configs)) msg = "Current Configuration: " + self.get_current_config() self.hutil.log_and_syslog(logging.INFO, msg)
def do_parse_context(self,operation): self._context = HandlerContext(self._short_name) handler_env=None config=None ctxt=None code=0 # get the HandlerEnvironment.json. According to the extension handler spec, it is always in the ./ directory self.log('cwd is ' + os.path.realpath(os.path.curdir)) handler_env_file='./HandlerEnvironment.json' if not os.path.isfile(handler_env_file): self.error("Unable to locate " + handler_env_file) sys.exit(1) ctxt=waagent.GetFileContents(handler_env_file) if ctxt == None : self.error("Unable to read " + handler_env_file) try: handler_env=json.loads(ctxt) except: pass if handler_env == None : self.log("JSON error processing " + handler_env_file) sys.exit(1) if type(handler_env) == list: handler_env = handler_env[0] self._context._name = handler_env['name'] self._context._version = str(handler_env['version']) self._context._config_dir=handler_env['handlerEnvironment']['configFolder'] self._context._log_file= os.path.join(handler_env['handlerEnvironment']['logFolder'],'extension.log') self._change_log_file() self._context._status_dir=handler_env['handlerEnvironment']['statusFolder'] self._context._heartbeat_file=handler_env['handlerEnvironment']['heartbeatFile'] self._context._seq_no = self._get_current_seq_no(self._context._config_dir) if self._context._seq_no < 0: self.error("Unable to locate a .settings file!") sys.exit(1) self._context._seq_no = str(self._context._seq_no) self.log('sequence number is ' + self._context._seq_no) self._context._status_file= os.path.join(self._context._status_dir, self._context._seq_no +'.status') self._context._settings_file = os.path.join(self._context._config_dir, self._context._seq_no + '.settings') self.log("setting file path is" + self._context._settings_file) ctxt=None ctxt=waagent.GetFileContents(self._context._settings_file) if ctxt == None : self.error('Unable to read ' + self._context._settings_file + '. ') self.do_exit( 1, operation, 'error', '1', 'Failed') self.log("JSON config: " + ctxt) config = None try: config=json.loads(ctxt) except: self.error('JSON exception decoding ' + ctxt) if config == None: self.error("JSON error processing " + settings_file) else: if config['runtimeSettings'][0]['handlerSettings'].has_key('protectedSettings'): thumb=config['runtimeSettings'][0]['handlerSettings']['protectedSettingsCertThumbprint'] cert=waagent.LibDir+'/'+thumb+'.crt' pkey=waagent.LibDir+'/'+thumb+'.prv' waagent.SetFileContents('/tmp/kk',config['runtimeSettings'][0]['handlerSettings']['protectedSettings']) cleartxt=None cleartxt=waagent.RunGetOutput("base64 -d /tmp/kk | openssl smime -inform DER -decrypt -recip " + cert + " -inkey " + pkey )[1] if cleartxt == None: self.error("OpenSSh decode error using thumbprint " + thumb ) do_exit(1,operation,'error','1', operation + ' Failed') jctxt='' try: jctxt=json.loads(cleartxt) except: self.error('JSON exception decoding ' + cleartxt) config['runtimeSettings'][0]['handlerSettings']['protectedSettings']=jctxt self.log('Config decoded correctly.') self._context._config = config return self._context
def create_stop_flag(self): waagent.SetFileContents(self.stop_flag_path, '')
def patch_one_off(self): """ Called when startTime is empty string, which means a on-demand patch. """ self.provide_vm_status_test(StatusTest["Oneoff"]) if not self.check_vm_idle(StatusTest["Oneoff"]): return global start_patch_time start_patch_time = time.time() self.hutil.log_and_syslog(logging.INFO, "Going to patch one-off") waagent.SetFileContents(self.package_downloaded_path, '') waagent.SetFileContents(self.package_patched_path, '') # Record the open deleted files before patching self.open_deleted_files_before = self.check_open_deleted_files() pkg_failed = [] is_time_out = [False, False] retcode, patchlist_required = self.check(self.category_required) if retcode > 0: msg = "Failed to check valid upgrades" self.hutil.log_and_syslog(logging.ERROR, msg) self.hutil.do_exit(1, 'Enable', 'error', '0', msg) if not patchlist_required: self.hutil.log_and_syslog( logging.INFO, "No packages are available for update. (Category:" + self.category_required + ")") else: is_time_out[0], failed = self._patch(self.category_required, patchlist_required) pkg_failed.extend(failed) if self.category == self.category_all: if not self.exists_stop_flag(): if not is_time_out[0]: retcode, patchlist_other = self.check(self.category_all) if retcode > 0: msg = "Failed to check valid upgrades" self.hutil.log_and_syslog(logging.ERROR, msg) self.hutil.do_exit(1, 'Enable', 'error', '0', msg) patchlist_other = [ pkg for pkg in patchlist_other if pkg not in patchlist_required ] if len(patchlist_other) == 0: self.hutil.log_and_syslog( logging.INFO, "No packages are available for update. (Category:" + self.category_all + ")") else: self.hutil.log_and_syslog( logging.INFO, "Going to sleep for " + str(self.gap_between_stage) + "s") time.sleep(self.gap_between_stage) self.hutil.log_and_syslog( logging.INFO, "Going to patch one-off (Category:" + self.category_all + ")") is_time_out[1], failed = self._patch( self.category_all, patchlist_other) pkg_failed.extend(failed) else: self.hutil.log_and_syslog( logging.INFO, "Installing patches (Category:" + self.category_all + ") is stopped/canceled") if is_time_out[0] or is_time_out[1]: waagent.AddExtensionEvent(name=self.hutil.get_name(), op="Oneoff Patch", isSuccess=False, version=Version, message="Patching time out") shutil.copy2(self.package_patched_path, self.package_downloaded_path) for pkg in pkg_failed: waagent.AppendFileContents(self.package_downloaded_path, pkg + '\n') self.open_deleted_files_after = self.check_open_deleted_files() self.delete_stop_flag() #self.report() if StatusTest["Oneoff"]["Healthy"]: is_healthy = StatusTest["Oneoff"]["Healthy"]() msg = "Checking the VM is healthy after patching: " + str( is_healthy) self.hutil.log_and_syslog(logging.INFO, msg) waagent.AddExtensionEvent(name=self.hutil.get_name(), op="Check healthy", isSuccess=is_healthy, version=Version, message=msg) if self.patched is not None and len(self.patched) > 0: self.reboot_if_required()
def setHwInfo(self, timestamp, hwInfo): content = str(timestamp) content = content + "\n" + "\n".join(hwInfo) waagent.SetFileContents(HwInfoFile, content)