示例#1
0
def _raise_error_status(prefix, error, event, config_file, conf):
    """
    Raise error and send customization status to the underlying VMware
    Virtualization Platform. Also, cleanup the imc directory.
    """
    LOG.debug('%s: %s', prefix, error)
    set_customization_status(GuestCustStateEnum.GUESTCUST_STATE_RUNNING, event)
    set_gc_status(conf, prefix)
    util.del_dir(os.path.dirname(config_file))
    raise error
    def test_set_gc_status(self):
        """
        This test is designed to verify the behavior of set_gc_status
        """
        # config is None, return None
        self.assertEqual(set_gc_status(None, 'Successful'), None)

        # post gc status is NO, return None
        cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg")
        conf = Config(cf)
        self.assertEqual(set_gc_status(conf, 'Successful'), None)

        # post gc status is YES, subp is called to execute command
        cf._insertKey("MISC|POST-GC-STATUS", "YES")
        conf = Config(cf)
        with mock.patch.object(util, 'subp',
                               return_value=('ok', b'')) as mockobj:
            self.assertEqual(set_gc_status(conf, 'Successful'), ('ok', b''))
            mockobj.assert_called_once_with(
                ['vmware-rpctool', 'info-set guestinfo.gc.status Successful'],
                rcs=[0])
    def test_set_gc_status(self):
        """
        This test is designed to verify the behavior of set_gc_status
        """
        # config is None, return None
        self.assertEqual(set_gc_status(None, "Successful"), None)

        # post gc status is NO, return None
        cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg")
        conf = Config(cf)
        self.assertEqual(set_gc_status(conf, "Successful"), None)

        # post gc status is YES, subp is called to execute command
        cf._insertKey("MISC|POST-GC-STATUS", "YES")
        conf = Config(cf)
        with mock.patch.object(subp,
                               "subp",
                               return_value=SubpResult("ok", b"")) as mockobj:
            self.assertEqual(set_gc_status(conf, "Successful"), ("ok", b""))
            mockobj.assert_called_once_with(
                ["vmware-rpctool", "info-set guestinfo.gc.status Successful"],
                rcs=[0],
            )
    def _get_data(self):
        found = []
        md = {}
        ud = ""
        vd = ""
        vmwareImcConfigFilePath = None
        nicspath = None

        defaults = {
            "instance-id": "iid-dsovf",
        }

        (seedfile, contents) = get_ovf_env(self.paths.seed_dir)

        system_type = dmi.read_dmi_data("system-product-name")
        if system_type is None:
            LOG.debug("No system-product-name found")

        if seedfile:
            # Found a seed dir
            seed = os.path.join(self.paths.seed_dir, seedfile)
            (md, ud, cfg) = read_ovf_environment(contents)
            self.environment = contents
            found.append(seed)
        elif system_type and 'vmware' in system_type.lower():
            LOG.debug("VMware Virtualization Platform found")
            if not self.vmware_customization_supported:
                LOG.debug("Skipping the check for "
                          "VMware Customization support")
            else:
                search_paths = (
                    "/usr/lib/vmware-tools", "/usr/lib64/vmware-tools",
                    "/usr/lib/open-vm-tools", "/usr/lib64/open-vm-tools")

                plugin = "libdeployPkgPlugin.so"
                deployPkgPluginPath = None
                for path in search_paths:
                    deployPkgPluginPath = search_file(path, plugin)
                    if deployPkgPluginPath:
                        LOG.debug("Found the customization plugin at %s",
                                  deployPkgPluginPath)
                        break

                if deployPkgPluginPath:
                    # When the VM is powered on, the "VMware Tools" daemon
                    # copies the customization specification file to
                    # /var/run/vmware-imc directory. cloud-init code needs
                    # to search for the file in that directory which indicates
                    # that required metadata and userdata files are now
                    # present.
                    max_wait = get_max_wait_from_cfg(self.ds_cfg)
                    vmwareImcConfigFilePath = util.log_time(
                        logfunc=LOG.debug,
                        msg="waiting for configuration file",
                        func=wait_for_imc_cfg_file,
                        args=("cust.cfg", max_wait))
                else:
                    LOG.debug("Did not find the customization plugin.")

                md_path = None
                if vmwareImcConfigFilePath:
                    imcdirpath = os.path.dirname(vmwareImcConfigFilePath)
                    cf = ConfigFile(vmwareImcConfigFilePath)
                    self._vmware_cust_conf = Config(cf)
                    LOG.debug("Found VMware Customization Config File at %s",
                              vmwareImcConfigFilePath)
                    try:
                        (md_path, ud_path, nicspath) = collect_imc_file_paths(
                            self._vmware_cust_conf)
                    except FileNotFoundError as e:
                        _raise_error_status(
                            "File(s) missing in directory",
                            e,
                            GuestCustEvent.GUESTCUST_EVENT_CUSTOMIZE_FAILED,
                            vmwareImcConfigFilePath,
                            self._vmware_cust_conf)
                else:
                    LOG.debug("Did not find VMware Customization Config File")

                # Honor disable_vmware_customization setting on metadata absent
                if not md_path:
                    if util.get_cfg_option_bool(self.sys_cfg,
                                                "disable_vmware_customization",
                                                True):
                        LOG.debug(
                            "Customization for VMware platform is disabled.")
                        # reset vmwareImcConfigFilePath to None to avoid
                        # customization for VMware platform
                        vmwareImcConfigFilePath = None

        use_raw_data = bool(vmwareImcConfigFilePath and md_path)
        if use_raw_data:
            set_gc_status(self._vmware_cust_conf, "Started")
            LOG.debug("Start to load cloud-init meta data and user data")
            try:
                (md, ud, cfg, network) = load_cloudinit_data(md_path, ud_path)

                if network:
                    self._network_config = network
                else:
                    self._network_config = (
                        self.distro.generate_fallback_config()
                    )

            except safeyaml.YAMLError as e:
                _raise_error_status(
                    "Error parsing the cloud-init meta data",
                    e,
                    GuestCustErrorEnum.GUESTCUST_ERROR_WRONG_META_FORMAT,
                    vmwareImcConfigFilePath,
                    self._vmware_cust_conf)
            except Exception as e:
                _raise_error_status(
                    "Error loading cloud-init configuration",
                    e,
                    GuestCustEvent.GUESTCUST_EVENT_CUSTOMIZE_FAILED,
                    vmwareImcConfigFilePath,
                    self._vmware_cust_conf)

            self._vmware_cust_found = True
            found.append('vmware-tools')

            util.del_dir(imcdirpath)
            set_customization_status(
                GuestCustStateEnum.GUESTCUST_STATE_DONE,
                GuestCustErrorEnum.GUESTCUST_ERROR_SUCCESS)
            set_gc_status(self._vmware_cust_conf, "Successful")

        elif vmwareImcConfigFilePath:
            # Load configuration from vmware_imc
            self._vmware_nics_to_enable = ""
            try:
                set_gc_status(self._vmware_cust_conf, "Started")

                (md, ud, cfg) = read_vmware_imc(self._vmware_cust_conf)
                self._vmware_nics_to_enable = get_nics_to_enable(nicspath)
                product_marker = self._vmware_cust_conf.marker_id
                hasmarkerfile = check_marker_exists(
                    product_marker, os.path.join(self.paths.cloud_dir, 'data'))
                special_customization = product_marker and not hasmarkerfile
                customscript = self._vmware_cust_conf.custom_script_name

                # In case there is a custom script, check whether VMware
                # Tools configuration allow the custom script to run.
                if special_customization and customscript:
                    defVal = "false"
                    if self._vmware_cust_conf.default_run_post_script:
                        LOG.debug(
                            "Set default value to true due to"
                            " customization configuration."
                        )
                        defVal = "true"

                    custScriptConfig = get_tools_config(
                        CONFGROUPNAME_GUESTCUSTOMIZATION,
                        GUESTCUSTOMIZATION_ENABLE_CUST_SCRIPTS,
                        defVal)
                    if custScriptConfig.lower() != "true":
                        # Update the customization status if custom script
                        # is disabled
                        msg = "Custom script is disabled by VM Administrator"
                        LOG.debug(msg)
                        set_customization_status(
                            GuestCustStateEnum.GUESTCUST_STATE_RUNNING,
                            GuestCustErrorEnum.GUESTCUST_ERROR_SCRIPT_DISABLED)
                        raise RuntimeError(msg)

                ccScriptsDir = os.path.join(
                    self.paths.get_cpath("scripts"),
                    "per-instance")
            except Exception as e:
                _raise_error_status(
                    "Error parsing the customization Config File",
                    e,
                    GuestCustEvent.GUESTCUST_EVENT_CUSTOMIZE_FAILED,
                    vmwareImcConfigFilePath,
                    self._vmware_cust_conf)

            if special_customization:
                if customscript:
                    try:
                        precust = PreCustomScript(customscript, imcdirpath)
                        precust.execute()
                    except Exception as e:
                        _raise_error_status(
                            "Error executing pre-customization script",
                            e,
                            GuestCustEvent.GUESTCUST_EVENT_CUSTOMIZE_FAILED,
                            vmwareImcConfigFilePath,
                            self._vmware_cust_conf)

            try:
                LOG.debug("Preparing the Network configuration")
                self._network_config = get_network_config_from_conf(
                    self._vmware_cust_conf,
                    True,
                    True,
                    self.distro.osfamily)
            except Exception as e:
                _raise_error_status(
                    "Error preparing Network Configuration",
                    e,
                    GuestCustEvent.GUESTCUST_EVENT_NETWORK_SETUP_FAILED,
                    vmwareImcConfigFilePath,
                    self._vmware_cust_conf)

            if special_customization:
                LOG.debug("Applying password customization")
                pwdConfigurator = PasswordConfigurator()
                adminpwd = self._vmware_cust_conf.admin_password
                try:
                    resetpwd = self._vmware_cust_conf.reset_password
                    if adminpwd or resetpwd:
                        pwdConfigurator.configure(adminpwd, resetpwd,
                                                  self.distro)
                    else:
                        LOG.debug("Changing password is not needed")
                except Exception as e:
                    _raise_error_status(
                        "Error applying Password Configuration",
                        e,
                        GuestCustEvent.GUESTCUST_EVENT_CUSTOMIZE_FAILED,
                        vmwareImcConfigFilePath,
                        self._vmware_cust_conf)

                if customscript:
                    try:
                        postcust = PostCustomScript(customscript,
                                                    imcdirpath,
                                                    ccScriptsDir)
                        postcust.execute()
                    except Exception as e:
                        _raise_error_status(
                            "Error executing post-customization script",
                            e,
                            GuestCustEvent.GUESTCUST_EVENT_CUSTOMIZE_FAILED,
                            vmwareImcConfigFilePath,
                            self._vmware_cust_conf)

            if product_marker:
                try:
                    setup_marker_files(
                        product_marker,
                        os.path.join(self.paths.cloud_dir, 'data'))
                except Exception as e:
                    _raise_error_status(
                        "Error creating marker files",
                        e,
                        GuestCustEvent.GUESTCUST_EVENT_CUSTOMIZE_FAILED,
                        vmwareImcConfigFilePath,
                        self._vmware_cust_conf)

            self._vmware_cust_found = True
            found.append('vmware-tools')

            # TODO: Need to set the status to DONE only when the
            # customization is done successfully.
            util.del_dir(os.path.dirname(vmwareImcConfigFilePath))
            enable_nics(self._vmware_nics_to_enable)
            set_customization_status(
                GuestCustStateEnum.GUESTCUST_STATE_DONE,
                GuestCustErrorEnum.GUESTCUST_ERROR_SUCCESS)
            set_gc_status(self._vmware_cust_conf, "Successful")

        else:
            np = [('com.vmware.guestInfo', transport_vmware_guestinfo),
                  ('iso', transport_iso9660)]
            name = None
            for name, transfunc in np:
                contents = transfunc()
                if contents:
                    break
            if contents:
                (md, ud, cfg) = read_ovf_environment(contents)
                self.environment = contents
                found.append(name)

        # There was no OVF transports found
        if len(found) == 0:
            return False

        if 'seedfrom' in md and md['seedfrom']:
            seedfrom = md['seedfrom']
            seedfound = False
            for proto in self.supported_seed_starts:
                if seedfrom.startswith(proto):
                    seedfound = proto
                    break
            if not seedfound:
                LOG.debug("Seed from %s not supported by %s",
                          seedfrom, self)
                return False

            (md_seed, ud, vd) = util.read_seeded(seedfrom, timeout=None)
            LOG.debug("Using seeded cache data from %s", seedfrom)

            md = util.mergemanydict([md, md_seed])
            found.append(seedfrom)

        # Now that we have exhausted any other places merge in the defaults
        md = util.mergemanydict([md, defaults])

        self.seed = ",".join(found)
        self.metadata = md
        self.userdata_raw = ud
        self.vendordata_raw = vd
        self.cfg = cfg
        return True