Example #1
0
    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, '')
Example #2
0
    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
Example #6
0
    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
Example #7
0
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()
Example #10
0
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
Example #15
0
 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()
Example #16
0
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)
Example #17
0
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()))
Example #18
0
    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())
Example #19
0
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))
Example #23
0
    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)
Example #24
0
    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
Example #26
0
 def create_stop_flag(self):
     waagent.SetFileContents(self.stop_flag_path, '')
Example #27
0
    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()
Example #28
0
 def setHwInfo(self, timestamp, hwInfo):
     content = str(timestamp)
     content = content + "\n" + "\n".join(hwInfo)
     waagent.SetFileContents(HwInfoFile, content)