def test_custom_script(self): cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg") conf = Config(cf) self.assertIsNone(conf.custom_script_name) cf._insertKey("CUSTOM-SCRIPT|SCRIPT-NAME", "test-script") conf = Config(cf) self.assertEqual("test-script", conf.custom_script_name)
def test_config_password(self): cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg") cf._insertKey("PASSWORD|-PASS", "test-password") cf._insertKey("PASSWORD|RESET", "no") conf = Config(cf) self.assertEqual('test-password', conf.admin_password, "password") self.assertFalse(conf.reset_password, "do not reset password")
def test_config_reset_passwd(self): cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg") cf._insertKey("PASSWORD|-PASS", "test-password") cf._insertKey("PASSWORD|RESET", "random") conf = Config(cf) with self.assertRaises(ValueError): pw = conf.reset_password self.assertIsNone(pw) cf.clear() cf._insertKey("PASSWORD|RESET", "yes") self.assertEqual(1, len(cf), "insert size") conf = Config(cf) self.assertTrue(conf.reset_password, "reset password")
def _get_data(self): found = [] md = {} ud = "" vmwareImcConfigFilePath = None nicspath = None defaults = { "instance-id": "iid-dsovf", } (seedfile, contents) = get_ovf_env(self.paths.seed_dir) system_type = util.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") elif not util.get_cfg_option_bool( self.sys_cfg, "disable_vmware_customization", True): 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. 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.") if vmwareImcConfigFilePath: LOG.debug("Found VMware Customization Config File at %s", vmwareImcConfigFilePath) nicspath = wait_for_imc_cfg_file(filename="nics.txt", maxwait=10, naplen=5) else: LOG.debug("Did not find VMware Customization Config File") else: LOG.debug("Customization for VMware platform is disabled.") if vmwareImcConfigFilePath: self._vmware_nics_to_enable = "" try: cf = ConfigFile(vmwareImcConfigFilePath) self._vmware_cust_conf = Config(cf) (md, ud, cfg) = read_vmware_imc(self._vmware_cust_conf) self._vmware_nics_to_enable = get_nics_to_enable(nicspath) imcdirpath = os.path.dirname(vmwareImcConfigFilePath) 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 custScriptConfig = get_tools_config( CONFGROUPNAME_GUESTCUSTOMIZATION, GUESTCUSTOMIZATION_ENABLE_CUST_SCRIPTS, "false") if custScriptConfig.lower() != "true": # Update the customization status if there is a # custom script is disabled if special_customization and customscript: 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) 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) 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) 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) 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) 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_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) 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) = 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.cfg = cfg return True
def test_utility_methods(self): cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg") cf.clear() self.assertEqual(0, len(cf), "clear size") cf._insertKey(" PASSWORD|-PASS ", " foo ") cf._insertKey("BAR", " ") self.assertEqual(2, len(cf), "insert size") self.assertEqual('foo', cf["PASSWORD|-PASS"], "password") self.assertTrue("PASSWORD|-PASS" in cf, "hasPassword") self.assertFalse(cf.should_keep_current_value("PASSWORD|-PASS"), "keepPassword") self.assertFalse(cf.should_remove_current_value("PASSWORD|-PASS"), "removePassword") self.assertFalse("FOO" in cf, "hasFoo") self.assertTrue(cf.should_keep_current_value("FOO"), "keepFoo") self.assertFalse(cf.should_remove_current_value("FOO"), "removeFoo") self.assertTrue("BAR" in cf, "hasBar") self.assertFalse(cf.should_keep_current_value("BAR"), "keepBar") self.assertTrue(cf.should_remove_current_value("BAR"), "removeBar")
def get_data(self): found = [] md = {} ud = "" vmwarePlatformFound = False vmwareImcConfigFilePath = '' defaults = { "instance-id": "iid-dsovf", } (seedfile, contents) = get_ovf_env(self.paths.seed_dir) system_type = util.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") elif not util.get_cfg_option_bool( self.sys_cfg, "disable_vmware_customization", True): deployPkgPluginPath = search_file("/usr/lib/vmware-tools", "libdeployPkgPlugin.so") if not deployPkgPluginPath: deployPkgPluginPath = search_file("/usr/lib/open-vm-tools", "libdeployPkgPlugin.so") 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. 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=("/var/run/vmware-imc", "cust.cfg", max_wait)) if vmwareImcConfigFilePath: LOG.debug("Found VMware Customization Config File at %s", vmwareImcConfigFilePath) else: LOG.debug("Did not find VMware Customization Config File") else: LOG.debug("Customization for VMware platform is disabled.") if vmwareImcConfigFilePath: nics = "" try: cf = ConfigFile(vmwareImcConfigFilePath) conf = Config(cf) (md, ud, cfg) = read_vmware_imc(conf) dirpath = os.path.dirname(vmwareImcConfigFilePath) nics = get_nics_to_enable(dirpath) markerid = conf.marker_id markerexists = check_marker_exists(markerid) except Exception as e: LOG.debug("Error parsing the customization Config File") LOG.exception(e) set_customization_status( GuestCustStateEnum.GUESTCUST_STATE_RUNNING, GuestCustEventEnum.GUESTCUST_EVENT_CUSTOMIZE_FAILED) enable_nics(nics) return False finally: util.del_dir(os.path.dirname(vmwareImcConfigFilePath)) try: LOG.debug("Applying the Network customization") nicConfigurator = NicConfigurator(conf.nics) nicConfigurator.configure() except Exception as e: LOG.debug("Error applying the Network Configuration") LOG.exception(e) set_customization_status( GuestCustStateEnum.GUESTCUST_STATE_RUNNING, GuestCustEventEnum.GUESTCUST_EVENT_NETWORK_SETUP_FAILED) enable_nics(nics) return False if markerid and not markerexists: LOG.debug("Applying password customization") pwdConfigurator = PasswordConfigurator() adminpwd = conf.admin_password try: resetpwd = 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: LOG.debug("Error applying Password Configuration: %s", e) set_customization_status( GuestCustStateEnum.GUESTCUST_STATE_RUNNING, GuestCustEventEnum.GUESTCUST_EVENT_CUSTOMIZE_FAILED) enable_nics(nics) return False if markerid: LOG.debug("Handle marker creation") try: setup_marker_files(markerid) except Exception as e: LOG.debug("Error creating marker files: %s", e) set_customization_status( GuestCustStateEnum.GUESTCUST_STATE_RUNNING, GuestCustEventEnum.GUESTCUST_EVENT_CUSTOMIZE_FAILED) enable_nics(nics) return False vmwarePlatformFound = True set_customization_status( GuestCustStateEnum.GUESTCUST_STATE_DONE, GuestCustErrorEnum.GUESTCUST_ERROR_SUCCESS) enable_nics(nics) else: np = { 'iso': transport_iso9660, 'vmware-guestd': transport_vmware_guestd, } name = None for (name, transfunc) in np.items(): (contents, _dev, _fname) = 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 and not vmwarePlatformFound: 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) = 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.cfg = cfg return True
def test_get_nics_list_static(self): """Tests if NicConfigurator properly calculates network subnets for a configuration with 2 static NICs""" cf = ConfigFile("tests/data/vmware/cust-static-2nic.cfg") config = Config(cf) nicConfigurator = NicConfigurator(config.nics, False) nics_cfg_list = nicConfigurator.generate() self.assertEqual(5, len(nics_cfg_list), "number of elements") nic1 = {'name': 'NIC1'} nic2 = {'name': 'NIC2'} route_list = [] for cfg in nics_cfg_list: cfg_type = cfg.get('type') if cfg_type == 'physical': if cfg.get('name') == nic1.get('name'): nic1.update(cfg) elif cfg.get('name') == nic2.get('name'): nic2.update(cfg) elif cfg_type == 'route': route_list.append(cfg) self.assertEqual('physical', nic1.get('type'), 'type of NIC1') self.assertEqual('NIC1', nic1.get('name'), 'name of NIC1') self.assertEqual('00:50:56:a6:8c:08', nic1.get('mac_address'), 'mac address of NIC1') subnets = nic1.get('subnets') self.assertEqual(2, len(subnets), 'Number of subnets') static_subnet = [] static6_subnet = [] for subnet in subnets: subnet_type = subnet.get('type') if subnet_type == 'static': static_subnet.append(subnet) elif subnet_type == 'static6': static6_subnet.append(subnet) else: self.assertEqual(True, False, 'Unknown type') self.assertEqual(1, len(static_subnet), 'Number of static subnet') self.assertEqual(1, len(static6_subnet), 'Number of static6 subnet') subnet = static_subnet[0] self.assertEqual('10.20.87.154', subnet.get('address'), 'IPv4 address of static subnet') self.assertEqual('255.255.252.0', subnet.get('netmask'), 'NetMask of static subnet') self.assertEqual('auto', subnet.get('control'), 'control for static subnet') subnet = static6_subnet[0] self.assertEqual('fc00:10:20:87::154', subnet.get('address'), 'IPv6 address of static subnet') self.assertEqual('64', subnet.get('netmask'), 'NetMask of static6 subnet') route_set = set(['10.20.87.253', '10.20.87.105', '192.168.0.10']) for route in route_list: self.assertEqual(10000, route.get('metric'), 'metric of route') gateway = route.get('gateway') if gateway in route_set: route_set.discard(gateway) else: self.assertEqual(True, False, 'invalid gateway %s' % (gateway)) self.assertEqual('physical', nic2.get('type'), 'type of NIC2') self.assertEqual('NIC2', nic2.get('name'), 'name of NIC2') self.assertEqual('00:50:56:a6:ef:7d', nic2.get('mac_address'), 'mac address of NIC2') subnets = nic2.get('subnets') self.assertEqual(1, len(subnets), 'Number of subnets for NIC2') subnet = subnets[0] self.assertEqual('static', subnet.get('type'), 'Subnet type') self.assertEqual('192.168.6.102', subnet.get('address'), 'Subnet address') self.assertEqual('255.255.0.0', subnet.get('netmask'), 'Subnet netmask')