Example #1
0
 def test_get_tools_config_internal_exception(self):
     """
     This test is designed to verify the behavior if internal exception
     is raised.
     """
     with mock.patch.object(subp, 'which', return_value='/dummy/path'):
         with mock.patch.object(subp, 'subp',
                                return_value=('key=value', b''),
                                side_effect=subp.ProcessExecutionError(
                                    "subp failed", exit_code=99)):
             # verify return value is 'defaultVal', not 'value'.
             self.assertEqual(
                 get_tools_config('section', 'key', 'defaultVal'),
                 'defaultVal')
 def test_get_tools_config_normal(self):
     """
     This test is designed to verify the value could be parsed from
     key = value of the given [section]
     """
     with mock.patch.object(util, 'which', return_value='/dummy/path'):
         # value is not blank
         with mock.patch.object(util,
                                'subp',
                                return_value=('key =   value  ', b'')):
             self.assertEqual(
                 get_tools_config('section', 'key', 'defaultVal'), 'value')
         # value is blank
         with mock.patch.object(util, 'subp', return_value=('key = ', b'')):
             self.assertEqual(
                 get_tools_config('section', 'key', 'defaultVal'), '')
         # value contains =
         with mock.patch.object(util,
                                'subp',
                                return_value=('key=Bar=Wark', b'')):
             self.assertEqual(
                 get_tools_config('section', 'key', 'defaultVal'),
                 'Bar=Wark')
    def test_get_tools_config_normal(self):
        """
        This test is designed to verify the value could be parsed from
        key = value of the given [section]
        """
        with mock.patch.object(subp, "which", return_value="/dummy/path"):
            # value is not blank
            with mock.patch.object(subp,
                                   "subp",
                                   return_value=SubpResult(
                                       "key =   value  ", b"")):
                self.assertEqual(
                    get_tools_config("section", "key", "defaultVal"), "value")
            # value is blank
            with mock.patch.object(subp,
                                   "subp",
                                   return_value=SubpResult("key = ", b"")):
                self.assertEqual(
                    get_tools_config("section", "key", "defaultVal"), "")
            # value contains =
            with mock.patch.object(subp,
                                   "subp",
                                   return_value=SubpResult(
                                       "key=Bar=Wark", b"")):
                self.assertEqual(
                    get_tools_config("section", "key", "defaultVal"),
                    "Bar=Wark",
                )

            # value contains specific characters
            with mock.patch.object(subp,
                                   "subp",
                                   return_value=SubpResult(
                                       "[a] b.c_d=e-f", b"")):
                self.assertEqual(
                    get_tools_config("section", "key", "defaultVal"), "e-f")
 def test_get_tools_config_internal_exception(self):
     """
     This test is designed to verify the behavior if internal exception
     is raised.
     """
     with mock.patch.object(subp, "which", return_value="/dummy/path"):
         with mock.patch.object(
                 subp,
                 "subp",
                 return_value=SubpResult("key=value", b""),
                 side_effect=subp.ProcessExecutionError("subp failed",
                                                        exit_code=99),
         ):
             # verify return value is 'defaultVal', not 'value'.
             self.assertEqual(
                 get_tools_config("section", "key", "defaultVal"),
                 "defaultVal",
             )
    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