From d064ab0bffd429382ea4fafeb144784d403848bd Mon Sep 17 00:00:00 2001 From: Ɓukasz 'sil2100' Zemczak Date: Mon, 16 Jan 2017 10:10:41 +0100 Subject: Import patches-unapplied version 2.2.2-0ubuntu1 to ubuntu/zesty-proposed Imported using git-ubuntu import. Changelog parent: 63d399807de30a64456e672063e7c20babf7aadc New changelog entries: * New upstream release (LP: #1651128) - d/patches/fix-auto-update.patch, d/patches/lp1623570-adjust-walinuxagent-service-after-and-wants.patch: - Dropped as changes have been applied upstream - Refreshed debian/patches/disable_import_test.patch --- azurelinuxagent/pa/deprovision/clearlinux.py | 31 ++++++++ azurelinuxagent/pa/deprovision/default.py | 17 ++++- azurelinuxagent/pa/deprovision/factory.py | 3 + azurelinuxagent/pa/deprovision/ubuntu.py | 33 ++++----- azurelinuxagent/pa/provision/default.py | 106 +++++++++++++-------------- azurelinuxagent/pa/provision/ubuntu.py | 14 ++-- azurelinuxagent/pa/rdma/centos.py | 45 +++++++++++- 7 files changed, 164 insertions(+), 85 deletions(-) create mode 100644 azurelinuxagent/pa/deprovision/clearlinux.py (limited to 'azurelinuxagent/pa') diff --git a/azurelinuxagent/pa/deprovision/clearlinux.py b/azurelinuxagent/pa/deprovision/clearlinux.py new file mode 100644 index 0000000..097891b --- /dev/null +++ b/azurelinuxagent/pa/deprovision/clearlinux.py @@ -0,0 +1,31 @@ +# Microsoft Azure Linux Agent +# +# Copyright 2014 Microsoft Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +import azurelinuxagent.common.utils.fileutil as fileutil +from azurelinuxagent.pa.deprovision.default import DeprovisionHandler, \ + DeprovisionAction + +class ClearLinuxDeprovisionHandler(DeprovisionHandler): + def __init__(self, distro): + self.distro = distro + + def setup(self, deluser): + warnings, actions = super(ClearLinuxDeprovisionHandler, self).setup(deluser) + # Probably should just wipe /etc and /var here + return warnings, actions diff --git a/azurelinuxagent/pa/deprovision/default.py b/azurelinuxagent/pa/deprovision/default.py index b570c31..a702d3f 100644 --- a/azurelinuxagent/pa/deprovision/default.py +++ b/azurelinuxagent/pa/deprovision/default.py @@ -17,6 +17,8 @@ # Requires Python 2.4+ and Openssl 1.0+ # +import signal +import sys import azurelinuxagent.common.conf as conf from azurelinuxagent.common.exception import ProtocolError from azurelinuxagent.common.future import read_input @@ -38,6 +40,7 @@ class DeprovisionHandler(object): def __init__(self): self.osutil = get_osutil() self.protocol_util = get_protocol_util() + signal.signal(signal.SIGINT, self.handle_interrupt_signal) def del_root_password(self, warnings, actions): warnings.append("WARNING! root password will be disabled. " @@ -63,8 +66,8 @@ class DeprovisionHandler(object): def regen_ssh_host_key(self, warnings, actions): warnings.append("WARNING! All SSH host key pairs will be deleted.") - actions.append(DeprovisionAction(shellutil.run, - ['rm -f /etc/ssh/ssh_host_*key*'])) + actions.append(DeprovisionAction(fileutil.rm_files, + ['/etc/ssh/ssh_host_*key*'])) def stop_agent_service(self, warnings, actions): warnings.append("WARNING! The waagent service will be stopped.") @@ -74,6 +77,11 @@ class DeprovisionHandler(object): files_to_del = ['/root/.bash_history', '/var/log/waagent.log'] actions.append(DeprovisionAction(fileutil.rm_files, files_to_del)) + def del_resolv(self, warnings, actions): + warnings.append("WARNING! /etc/resolv.conf will be deleted.") + files_to_del = ["/etc/resolv.conf"] + actions.append(DeprovisionAction(fileutil.rm_files, files_to_del)) + def del_dhcp_lease(self, warnings, actions): warnings.append("WARNING! Cached DHCP leases will be deleted.") dirs_to_del = ["/var/lib/dhclient", "/var/lib/dhcpcd", "/var/lib/dhcp"] @@ -109,6 +117,7 @@ class DeprovisionHandler(object): self.del_lib_dir(warnings, actions) self.del_files(warnings, actions) + self.del_resolv(warnings, actions) if deluser: self.del_user(warnings, actions) @@ -128,4 +137,8 @@ class DeprovisionHandler(object): for action in actions: action.invoke() + def handle_interrupt_signal(self, frame): + print("Deprovision is interrupted.") + sys.exit(0) + diff --git a/azurelinuxagent/pa/deprovision/factory.py b/azurelinuxagent/pa/deprovision/factory.py index dd01633..72a5be1 100644 --- a/azurelinuxagent/pa/deprovision/factory.py +++ b/azurelinuxagent/pa/deprovision/factory.py @@ -21,6 +21,7 @@ from azurelinuxagent.common.version import DISTRO_NAME, DISTRO_VERSION, \ DISTRO_FULL_NAME from .default import DeprovisionHandler +from .clearlinux import ClearLinuxDeprovisionHandler from .coreos import CoreOSDeprovisionHandler from .ubuntu import UbuntuDeprovisionHandler @@ -31,6 +32,8 @@ def get_deprovision_handler(distro_name=DISTRO_NAME, return UbuntuDeprovisionHandler() if distro_name == "coreos": return CoreOSDeprovisionHandler() + if distro_name == "clear linux": + return ClearLinuxDeprovisionHandler() return DeprovisionHandler() diff --git a/azurelinuxagent/pa/deprovision/ubuntu.py b/azurelinuxagent/pa/deprovision/ubuntu.py index 14f90de..b45d415 100644 --- a/azurelinuxagent/pa/deprovision/ubuntu.py +++ b/azurelinuxagent/pa/deprovision/ubuntu.py @@ -18,30 +18,25 @@ # import os -import azurelinuxagent.common.logger as logger import azurelinuxagent.common.utils.fileutil as fileutil from azurelinuxagent.pa.deprovision.default import DeprovisionHandler, \ - DeprovisionAction - -def del_resolv(): - if os.path.realpath('/etc/resolv.conf') != '/run/resolvconf/resolv.conf': - logger.info("resolvconf is not configured. Removing /etc/resolv.conf") - fileutil.rm_files('/etc/resolv.conf') - else: - logger.info("resolvconf is enabled; leaving /etc/resolv.conf intact") - fileutil.rm_files('/etc/resolvconf/resolv.conf.d/tail', - '/etc/resolvconf/resolv.conf.d/originial') + DeprovisionAction class UbuntuDeprovisionHandler(DeprovisionHandler): def __init__(self): super(UbuntuDeprovisionHandler, self).__init__() - def setup(self, deluser): - warnings, actions = super(UbuntuDeprovisionHandler, self).setup(deluser) - warnings.append("WARNING! Nameserver configuration in " - "/etc/resolvconf/resolv.conf.d/{tail,originial} " - "will be deleted.") - actions.append(DeprovisionAction(del_resolv)) - return warnings, actions - + def del_resolv(self, warnings, actions): + if os.path.realpath( + '/etc/resolv.conf') != '/run/resolvconf/resolv.conf': + warnings.append("WARNING! /etc/resolv.conf will be deleted.") + files_to_del = ["/etc/resolv.conf"] + actions.append(DeprovisionAction(fileutil.rm_files, files_to_del)) + else: + warnings.append("WARNING! /etc/resolvconf/resolv.conf.d/tail " + "and /etc/resolvconf/resolv.conf.d/original will " + "be deleted.") + files_to_del = ["/etc/resolvconf/resolv.conf.d/tail", + "/etc/resolvconf/resolv.conf.d/original"] + actions.append(DeprovisionAction(fileutil.rm_files, files_to_del)) diff --git a/azurelinuxagent/pa/provision/default.py b/azurelinuxagent/pa/provision/default.py index b07c147..e851036 100644 --- a/azurelinuxagent/pa/provision/default.py +++ b/azurelinuxagent/pa/provision/default.py @@ -25,69 +25,71 @@ from azurelinuxagent.common.future import ustr import azurelinuxagent.common.conf as conf from azurelinuxagent.common.event import add_event, WALAEventOperation from azurelinuxagent.common.exception import ProvisionError, ProtocolError, \ - OSUtilError + OSUtilError from azurelinuxagent.common.protocol.restapi import ProvisionStatus import azurelinuxagent.common.utils.shellutil as shellutil import azurelinuxagent.common.utils.fileutil as fileutil from azurelinuxagent.common.osutil import get_osutil from azurelinuxagent.common.protocol import get_protocol_util -CUSTOM_DATA_FILE="CustomData" +CUSTOM_DATA_FILE = "CustomData" -class ProvisionHandler(object): +class ProvisionHandler(object): def __init__(self): self.osutil = get_osutil() self.protocol_util = get_protocol_util() def run(self): - #If provision is not enabled, return - if not conf.get_provision_enabled(): - logger.info("Provisioning is disabled. Skip.") - return - + # if provisioning is already done, return provisioned = os.path.join(conf.get_lib_dir(), "provisioned") if os.path.isfile(provisioned): + logger.info("Provisioning already completed, skipping.") return - logger.info("Run provision handler.") - logger.info("Copy ovf-env.xml.") - try: - ovfenv = self.protocol_util.copy_ovf_env() - except ProtocolError as e: - self.report_event("Failed to copy ovf-env.xml: {0}".format(e)) - return - - self.protocol_util.get_protocol_by_file() - - self.report_not_ready("Provisioning", "Starting") - - try: - logger.info("Start provisioning") - self.provision(ovfenv) - fileutil.write_file(provisioned, "") - thumbprint = self.reg_ssh_host_key() - logger.info("Finished provisioning") - except ProvisionError as e: - logger.error("Provision failed: {0}", e) - self.report_not_ready("ProvisioningFailed", ustr(e)) - self.report_event(ustr(e)) - return - + thumbprint = None + # If provision is not enabled, report ready and then return + if not conf.get_provision_enabled(): + logger.info("Provisioning is disabled, skipping.") + else: + logger.info("Running provisioning handler") + try: + logger.info("Copying ovf-env.xml") + ovf_env = self.protocol_util.copy_ovf_env() + self.protocol_util.get_protocol_by_file() + self.report_not_ready("Provisioning", "Starting") + logger.info("Starting provisioning") + self.provision(ovf_env) + thumbprint = self.reg_ssh_host_key() + self.osutil.restart_ssh_service() + self.report_event("Provision succeed", is_success=True) + except ProtocolError as e: + logger.error("[ProtocolError] Provisioning failed: {0}", e) + self.report_not_ready("ProvisioningFailed", ustr(e)) + self.report_event("Failed to copy ovf-env.xml: {0}".format(e)) + return + except ProvisionError as e: + logger.error("[ProvisionError] Provisioning failed: {0}", e) + self.report_not_ready("ProvisioningFailed", ustr(e)) + self.report_event(ustr(e)) + return + # write out provisioned file and report Ready + fileutil.write_file(provisioned, "") self.report_ready(thumbprint) - self.report_event("Provision succeed", is_success=True) - + logger.info("Provisioning complete") + def reg_ssh_host_key(self): keypair_type = conf.get_ssh_host_keypair_type() if conf.get_regenerate_ssh_host_key(): - shellutil.run("rm -f /etc/ssh/ssh_host_*key*") - shellutil.run(("ssh-keygen -N '' -t {0} -f /etc/ssh/ssh_host_{1}_key" - "").format(keypair_type, keypair_type)) + fileutil.rm_files("/etc/ssh/ssh_host_*key*") + keygen_cmd = "ssh-keygen -N '' -t {0} -f /etc/ssh/ssh_host_{1}_key" + shellutil.run(keygen_cmd.format(keypair_type, keypair_type)) thumbprint = self.get_ssh_host_key_thumbprint(keypair_type) return thumbprint def get_ssh_host_key_thumbprint(self, keypair_type): - cmd = "ssh-keygen -lf /etc/ssh/ssh_host_{0}_key.pub".format(keypair_type) + cmd = "ssh-keygen -lf /etc/ssh/ssh_host_{0}_key.pub".format( + keypair_type) ret = shellutil.run_get_output(cmd) if ret[0] == 0: return ret[1].rstrip().split()[1].replace(':', '') @@ -107,13 +109,13 @@ class ProvisionHandler(object): self.config_user_account(ovfenv) self.save_customdata(ovfenv) - + if conf.get_delete_root_password(): self.osutil.del_root_password() except OSUtilError as e: raise ProvisionError("Failed to handle ovf-env.xml: {0}".format(e)) - + def config_user_account(self, ovfenv): logger.info("Create user account if not exists") self.osutil.useradd(ovfenv.username) @@ -123,27 +125,18 @@ class ProvisionHandler(object): crypt_id = conf.get_password_cryptid() salt_len = conf.get_password_crypt_salt_len() self.osutil.chpasswd(ovfenv.username, ovfenv.user_password, - crypt_id=crypt_id, salt_len=salt_len) - + crypt_id=crypt_id, salt_len=salt_len) + logger.info("Configure sudoer") - self.osutil.conf_sudoer(ovfenv.username, nopasswd=ovfenv.user_password is None) + self.osutil.conf_sudoer(ovfenv.username, + nopasswd=ovfenv.user_password is None) logger.info("Configure sshd") self.osutil.conf_sshd(ovfenv.disable_ssh_password_auth) - #Disable selinux temporary - sel = self.osutil.is_selinux_enforcing() - if sel: - self.osutil.set_selinux_enforce(0) - self.deploy_ssh_pubkeys(ovfenv) self.deploy_ssh_keypairs(ovfenv) - if sel: - self.osutil.set_selinux_enforce(1) - - self.osutil.restart_ssh_service() - def save_customdata(self, ovfenv): customdata = ovfenv.customdata if customdata is None: @@ -152,11 +145,11 @@ class ProvisionHandler(object): logger.info("Save custom data") lib_dir = conf.get_lib_dir() if conf.get_decode_customdata(): - customdata= self.osutil.decode_customdata(customdata) + customdata = self.osutil.decode_customdata(customdata) customdata_file = os.path.join(lib_dir, CUSTOM_DATA_FILE) fileutil.write_file(customdata_file, customdata) - + if conf.get_execute_customdata(): logger.info("Execute custom data") os.chmod(customdata_file, 0o700) @@ -183,6 +176,7 @@ class ProvisionHandler(object): protocol = self.protocol_util.get_protocol() protocol.report_provision_status(status) except ProtocolError as e: + logger.error("Reporting NotReady failed: {0}", e) self.report_event(ustr(e)) def report_ready(self, thumbprint=None): @@ -192,5 +186,5 @@ class ProvisionHandler(object): protocol = self.protocol_util.get_protocol() protocol.report_provision_status(status) except ProtocolError as e: + logger.error("Reporting Ready failed: {0}", e) self.report_event(ustr(e)) - diff --git a/azurelinuxagent/pa/provision/ubuntu.py b/azurelinuxagent/pa/provision/ubuntu.py index c334f23..7f2bce3 100644 --- a/azurelinuxagent/pa/provision/ubuntu.py +++ b/azurelinuxagent/pa/provision/ubuntu.py @@ -32,12 +32,14 @@ from azurelinuxagent.pa.provision.default import ProvisionHandler """ On ubuntu image, provision could be disabled. """ + + class UbuntuProvisionHandler(ProvisionHandler): def __init__(self): super(UbuntuProvisionHandler, self).__init__() def run(self): - #If provision is enabled, run default provision handler + # If provision is enabled, run default provision handler if conf.get_provision_enabled(): super(UbuntuProvisionHandler, self).run() return @@ -49,23 +51,21 @@ class UbuntuProvisionHandler(ProvisionHandler): logger.info("Waiting cloud-init to copy ovf-env.xml.") self.wait_for_ovfenv() - - protocol = self.protocol_util.get_protocol() + self.protocol_util.get_protocol() self.report_not_ready("Provisioning", "Starting") - logger.info("Sleep 15 seconds to prevent throttling") - time.sleep(15) #Sleep to prevent throttling + logger.info("Sleeping 1 second to avoid throttling.") + time.sleep(1) try: logger.info("Wait for ssh host key to be generated.") thumbprint = self.wait_for_ssh_host_key() fileutil.write_file(provisioned, "") logger.info("Finished provisioning") - except ProvisionError as e: logger.error("Provision failed: {0}", e) self.report_not_ready("ProvisioningFailed", ustr(e)) self.report_event(ustr(e)) return - + self.report_ready(thumbprint) self.report_event("Provision succeed", is_success=True) diff --git a/azurelinuxagent/pa/rdma/centos.py b/azurelinuxagent/pa/rdma/centos.py index c527e1b..8ad09c5 100644 --- a/azurelinuxagent/pa/rdma/centos.py +++ b/azurelinuxagent/pa/rdma/centos.py @@ -20,6 +20,7 @@ import glob import os import re +import time import azurelinuxagent.common.logger as logger import azurelinuxagent.common.utils.shellutil as shellutil from azurelinuxagent.common.rdma import RDMAHandler @@ -47,6 +48,17 @@ class CentOSRDMAHandler(RDMAHandler): Install the KVP daemon and the appropriate RDMA driver package for the RDMA firmware. """ + + # Check and install the KVP deamon if it not running + time.sleep(10) # give some time for the hv_hvp_daemon to start up. + kvpd_running = RDMAHandler.is_kvp_daemon_running() + logger.info('RDMA: kvp daemon running: %s' % kvpd_running) + if not kvpd_running: + self.check_or_install_kvp_daemon() + time.sleep(10) # wait for post-install reboot or kvp to come up + + # Find out RDMA firmware version and see if the existing package needs + # updating or if the package is missing altogether (and install it) fw_version = RDMAHandler.get_rdma_version() if not fw_version: raise Exception('Cannot determine RDMA firmware version') @@ -187,12 +199,20 @@ class CentOSRDMAHandler(RDMAHandler): raise Exception( "Failed to install RDMA {0} package".format(pkg_type)) + @staticmethod + def is_package_installed(pkg): + """Runs rpm -q and checks return code to find out if a package + is installed""" + return shellutil.run("rpm -q %s" % pkg, chk_err=False) == 0 + def uninstall_kvp_driver_package_if_exists(self): + logger.info('RDMA: deleting existing kvp driver packages') + kvp_pkgs = [self.hyper_v_package_name, self.hyper_v_package_name_new] for kvp_pkg in kvp_pkgs: - if shellutil.run("rpm -q %s" % kvp_pkg, chk_err=False) != 0: + if not self.is_package_installed(kvp_pkg): logger.info( "RDMA: kvp package %s does not exist, skipping" % kvp_pkg) else: @@ -201,3 +221,26 @@ class CentOSRDMAHandler(RDMAHandler): logger.info("RDMA: successfully erased package") else: logger.error("RDMA: failed to erase package") + + def check_or_install_kvp_daemon(self): + """Checks if kvp daemon package is installed, if not installs the + package and reboots the machine. + """ + logger.info("RDMA: Checking kvp daemon packages.") + kvp_pkgs = [self.hyper_v_package_name, + self.hyper_v_package_name_new] + + for pkg in kvp_pkgs: + logger.info("RDMA: Checking if package %s installed" % pkg) + installed = self.is_package_installed(pkg) + if installed: + raise Exception('RDMA: package %s is installed, but the kvp daemon is not running' % pkg) + + kvp_pkg_to_install=self.hyper_v_package_name + logger.info("RDMA: no kvp drivers installed, will install '%s'" % kvp_pkg_to_install) + logger.info("RDMA: trying to install kvp package '%s'" % kvp_pkg_to_install) + if self.install_package(kvp_pkg_to_install) != 0: + raise Exception("RDMA: failed to install kvp daemon package '%s'" % kvp_pkg_to_install) + logger.info("RDMA: package '%s' successfully installed" % kvp_pkg_to_install) + logger.info("RDMA: Machine will now be rebooted.") + self.reboot_system() \ No newline at end of file -- cgit v1.2.3