def _patch(self, category, patchlist):
     if self.exists_stop_flag():
         self.log_and_syslog(
             logging.INFO, "Installing patches (Category:" + category +
             ") is stopped/canceled")
         return False, list()
     if not patchlist:
         self.log_and_syslog(logging.INFO,
                             "No packages are available for update.")
         return False, list()
     self.log_and_syslog(
         logging.INFO, "Start to install " + str(len(patchlist)) +
         " patches (Category:" + category + ")")
     self.log_and_syslog(logging.INFO, "Patch list: " + ' '.join(patchlist))
     pkg_failed = []
     for pkg_name in patchlist:
         if pkg_name == 'walinuxagent':
             continue
         current_patch_time = time.time()
         if current_patch_time - start_patch_time > self.install_duration:
             msg = "Patching time exceeded. The pending package will be patched in the next cycle"
             self.log_and_syslog(logging.WARNING, msg)
             return True, pkg_failed
         retcode = self.patch_package(pkg_name)
         if retcode != 0:
             self.log_and_syslog(logging.ERROR,
                                 "Failed to patch the package:" + pkg_name)
             pkg_failed.append(' '.join([pkg_name, category]))
             continue
         self.patched.append(pkg_name)
         self.log_and_syslog(logging.INFO,
                             "Package " + pkg_name + " is patched.")
         waagent.AppendFileContents(self.package_patched_path,
                                    pkg_name + ' ' + category + '\n')
     return False, pkg_failed
Beispiel #2
0
 def _download(self, category):
     self.hutil.log_and_syslog(
         logging.INFO,
         "Start to check&download patches (Category:" + category + ")")
     retcode, downloadlist = self.check(category)
     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 'walinuxagent' in downloadlist:
         downloadlist.remove('walinuxagent')
     if not downloadlist:
         self.hutil.log_and_syslog(logging.INFO,
                                   "No packages are available for update.")
         return
     self.hutil.log_and_syslog(
         logging.INFO,
         "There are " + str(len(downloadlist)) + " packages to upgrade.")
     self.hutil.log_and_syslog(logging.INFO,
                               "Download list: " + ' '.join(downloadlist))
     for pkg_name in downloadlist:
         if pkg_name in self.downloaded:
             continue
         retcode = self.download_package(pkg_name)
         if retcode != 0:
             self.hutil.log_and_syslog(
                 logging.ERROR,
                 "Failed to download the package: " + pkg_name)
             continue
         self.downloaded.append(pkg_name)
         self.hutil.log_and_syslog(
             logging.INFO, "Package " + pkg_name + " is downloaded.")
         waagent.AppendFileContents(self.package_downloaded_path,
                                    pkg_name + ' ' + category + '\n')
 def _patch(self, category, patchlist):
     if self.exists_stop_flag():
         self.hutil.log("Installing patches (Category:" + category +
                        ") is stopped/canceled")
         return
     if not patchlist:
         self.hutil.log("No packages are available for update.")
         return
     self.hutil.log("Start to install " + str(len(patchlist)) +
                    " patches (Category:" + category + ")")
     self.hutil.log("Patch list: " + ' '.join(patchlist))
     for pkg_name in patchlist:
         current_patch_time = time.time()
         if current_patch_time - start_patch_time > self.install_duration:
             self.hutil.log(
                 "Patching time exceeded. The pending package will be \
                             patched in the next cycle")
             break
         retcode = self.patch_package(pkg_name)
         if retcode != 0:
             self.hutil.error("Failed to patch the package:" + pkg_name)
             continue
         self.patched.append(pkg_name)
         self.hutil.log("Package " + pkg_name + " is patched.")
         waagent.AppendFileContents(self.package_patched_path,
                                    pkg_name + ' ' + category + '\n')
 def retry_download(self):
     retry_count = 0
     max_retry_count = 12
     self.log_and_syslog(
         logging.INFO, "Retry queue: {0}".format(" ".join([
             pkg_name for pkg_name, category in self.download_retry_queue
         ])))
     while self.download_retry_queue:
         pkg_name, category = self.download_retry_queue[0]
         self.download_retry_queue = self.download_retry_queue[1:]
         retcode = self.download_package(pkg_name)
         if retcode == 0:
             self.downloaded.append(pkg_name)
             self.log_and_syslog(logging.INFO,
                                 "Package " + pkg_name + " is downloaded.")
             waagent.AppendFileContents(self.package_downloaded_path,
                                        pkg_name + ' ' + category + '\n')
         else:
             self.log_and_syslog(
                 logging.ERROR,
                 "Failed to download the package: " + pkg_name)
             self.log_and_syslog(
                 logging.INFO,
                 "Put {0} back into a retry queue".format(pkg_name))
             self.download_retry_queue.append((pkg_name, category))
             retry_count = retry_count + 1
             if retry_count > max_retry_count:
                 err_msg = ("Failed to download after {0} retries, "
                            "retry queue: {1}").format(
                                max_retry_count, " ".join([
                                    pkg_name for pkg_name, category in
                                    self.download_retry_queue
                                ]))
                 self.log_and_syslog(logging.ERROR, err_msg)
                 waagent.AddExtensionEvent(
                     name=self.hutil.get_name(),
                     op=waagent.WALAEventOperation.Download,
                     isSuccess=False,
                     version=Version,
                     message=err_msg)
                 break
             k = retry_count if (retry_count < 10) else 10
             interval = int(random.uniform(0, 2**k))
             self.log_and_syslog(
                 logging.INFO,
                 ("Sleep {0}s before "
                  "the next retry, current retry_count = {1}").format(
                      interval, retry_count))
             time.sleep(interval)
 def _download(self, category):
     self.hutil.log("Start to check&download patches (Category:" +
                    category + ")")
     retcode, downloadlist = self.check(category)
     if retcode > 0:
         self.hutil.error("Failed to check valid upgrades")
         sys.exit(1)
     if not downloadlist:
         self.hutil.log("No packages are available for update.")
         return
     self.hutil.log("There are " + str(len(downloadlist)) +
                    " packages to upgrade.")
     self.hutil.log("Download list: " + ' '.join(downloadlist))
     for pkg_name in downloadlist:
         if pkg_name in self.downloaded:
             continue
         retcode = self.download_package(pkg_name)
         if retcode != 0:
             self.hutil.error("Failed to download the package: " + pkg_name)
             continue
         self.downloaded.append(pkg_name)
         self.hutil.log("Package " + pkg_name + " is downloaded.")
         waagent.AppendFileContents(self.package_downloaded_path,
                                    pkg_name + ' ' + category + '\n')
Beispiel #6
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()
Beispiel #7
0
    def patch(self):
        # Read the latest configuration for scheduled task
        settings = json.loads(
            waagent.GetFileContents(self.scheduled_configs_file))
        self.parse_settings(settings)

        if not self.check_vm_idle(StatusTest["Scheduled"]):
            return

        if self.exists_stop_flag():
            self.hutil.log_and_syslog(
                logging.INFO, "Installing patches is stopped/canceled")
            self.delete_stop_flag()
            return

        # Record the scheduled time
        waagent.AppendFileContents(
            self.history_scheduled,
            time.strftime("%Y-%m-%d %a", time.localtime()) + '\n')
        # Record the open deleted files before patching
        self.open_deleted_files_before = self.check_open_deleted_files()

        retcode = self.stop_download()
        if retcode == 0:
            self.hutil.log_and_syslog(
                logging.WARNING,
                "Download time exceeded. The pending package will be downloaded in the next cycle"
            )
            waagent.AddExtensionEvent(name=self.hutil.get_name(),
                                      op=waagent.WALAEventOperation.Download,
                                      isSuccess=False,
                                      version=Version,
                                      message="Downloading time out")

        global start_patch_time
        start_patch_time = time.time()

        pkg_failed = []
        is_time_out = [False, False]
        patchlist = self.get_pkg_to_patch(self.category_required)
        is_time_out[0], failed = self._patch(self.category_required, patchlist)
        pkg_failed.extend(failed)
        if not self.exists_stop_flag():
            if not is_time_out[0]:
                patchlist = self.get_pkg_to_patch(self.category_all)
                if len(patchlist) == 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)
                    is_time_out[1], failed = self._patch(
                        self.category_all, patchlist)
                    pkg_failed.extend(failed)
        else:
            msg = "Installing patches (Category:" + self.category_all + ") is stopped/canceled"
            self.hutil.log_and_syslog(logging.INFO, msg)
        if is_time_out[0] or is_time_out[1]:
            msg = "Patching time out"
            self.hutil.log_and_syslog(logging.WARNING, msg)
            waagent.AddExtensionEvent(name=self.hutil.get_name(),
                                      op="Patch",
                                      isSuccess=False,
                                      version=Version,
                                      message=msg)

        self.open_deleted_files_after = self.check_open_deleted_files()
        self.delete_stop_flag()
        #self.report()
        if StatusTest["Scheduled"]["Healthy"]:
            is_healthy = StatusTest["Scheduled"]["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 _save_other_sudoers(sudoers):
    sudoersFile = '/etc/sudoers.d/waagent'
    if sudoers is None:
        return
    waagent.AppendFileContents(sudoersFile, "\n".join(sudoers))
    os.chmod("/etc/sudoers.d/waagent", 0440)
def _set_user_account_pub_key(protect_settings, hutil):
    ovf_xml = waagent.GetFileContents('/var/lib/waagent/ovf-env.xml')
    ovf_env = waagent.OvfEnv().Parse(ovf_xml)

    # user name must be provided if set ssh key or password
    if not protect_settings or not protect_settings.has_key('username'):
        return

    user_name = protect_settings['username']
    user_pass = protect_settings.get('password')
    cert_txt = protect_settings.get('ssh_key')
    no_convert = False
    if (not (user_pass) and not (cert_txt) and not (ovf_env.SshPublicKeys)):
        raise Exception("No password or ssh_key is specified.")

    #Reset user account and password, password could be empty
    sudoers = _get_other_sudoers(user_name)
    error_string = waagent.MyDistro.CreateAccount(user_name, user_pass, None,
                                                  None)
    _save_other_sudoers(sudoers)

    if error_string != None:
        waagent.AddExtensionEvent(
            name=hutil.get_name(),
            op=waagent.WALAEventOperation.Enable,
            isSuccess=False,
            message="(02101)Failed to create the account or set the password.")
        raise Exception("Failed to create the account or set the password: "******"Succeeded in create the account or set the password.")

    #Allow password authentication if user_pass is provided
    if user_pass is not None:
        _allow_password_auth()

    #Reset ssh key with the new public key passed in or reuse old public key.
    if cert_txt or len(ovf_env.SshPublicKeys) > 0:
        if cert_txt and cert_txt.strip().lower().startswith("ssh-rsa"):
            no_convert = True
        try:
            pub_path = os.path.join('/home/', user_name, '.ssh',
                                    'authorized_keys')
            ovf_env.UserName = user_name
            if (no_convert):
                if (cert_txt):
                    pub_path = ovf_env.PrepareDir(pub_path)
                    final_cert_txt = cert_txt
                    if (not cert_txt.endswith("\n")):
                        final_cert_txt = final_cert_txt + "\n"
                    waagent.AppendFileContents(pub_path, final_cert_txt)
                    waagent.MyDistro.setSelinuxContext(
                        pub_path, 'unconfined_u:object_r:ssh_home_t:s0')
                    waagent.ChangeOwner(pub_path, user_name)
                    hutil.log("Succeeded in resetting ssh_key.")
                else:
                    waagent.AddExtensionEvent(
                        name=hutil.get_name(),
                        op=waagent.WALAEventOperation.Enable,
                        isSuccess=False,
                        message=
                        "(02100)Failed to reset ssh key because the cert content is empty."
                    )
            else:
                if cert_txt:
                    _save_cert_str_as_file(cert_txt, 'temp.crt')
                else:
                    for pkey in ovf_env.SshPublicKeys:
                        if pkey[1]:
                            shutil.copy(
                                os.path.join(waagent.LibDir, pkey[0] + '.crt'),
                                os.path.join(os.getcwd(), 'temp.crt'))
                            break
                pub_path = ovf_env.PrepareDir(pub_path)
                retcode = waagent.Run(
                    waagent.Openssl +
                    " x509 -in temp.crt -noout -pubkey > temp.pub")
                if retcode > 0:
                    raise Exception("Failed to generate public key file.")
                waagent.MyDistro.sshDeployPublicKey('temp.pub', pub_path)
                waagent.MyDistro.setSelinuxContext(
                    pub_path, 'unconfined_u:object_r:ssh_home_t:s0')
                waagent.ChangeOwner(pub_path, user_name)
                os.remove('temp.pub')
                os.remove('temp.crt')
                hutil.log("Succeeded in resetting ssh_key.")
        except Exception as e:
            hutil.log(str(e))
            waagent.AddExtensionEvent(
                name=hutil.get_name(),
                op=waagent.WALAEventOperation.Enable,
                isSuccess=False,
                message="(02100)Failed to reset ssh key.")