def test_is_connected_when_wireless_and_carrier_active(self): """is_connected is True if wireless /sys/net/devname/carrier is 1.""" self.assertFalse(net.is_connected('eth0')) ensure_file(os.path.join(self.sysdir, 'eth0', 'wireless')) self.assertFalse(net.is_connected('eth0')) write_file(os.path.join(self.sysdir, 'eth0', 'carrier'), "1") self.assertTrue(net.is_connected('eth0'))
def test_defaults(self, m_write_file, kwarg, expected): """Test that ensure_file defaults appropriately.""" util.ensure_file(mock.sentinel.path) assert 1 == m_write_file.call_count _args, kwargs = m_write_file.call_args assert expected == kwargs[kwarg]
def test_is_vlan(self): """is_vlan is True when /sys/net/devname/uevent has DEVTYPE=vlan.""" ensure_file(os.path.join(self.sysdir, 'eth0', 'uevent')) self.assertFalse(net.is_vlan('eth0')) content = 'junk\nDEVTYPE=vlan\njunk\n' write_file(os.path.join(self.sysdir, 'eth0', 'uevent'), content) self.assertTrue(net.is_vlan('eth0'))
def _initialize_filesystem(self): util.ensure_dirs(self._initial_subdirs()) log_file = util.get_cfg_option_str(self.cfg, "def_log_file") if log_file: util.ensure_file(log_file, mode=0o640, preserve_mode=True) perms = self.cfg.get("syslog_fix_perms") if not perms: perms = {} if not isinstance(perms, list): perms = [perms] error = None for perm in perms: u, g = util.extract_usergroup(perm) try: util.chownbyname(log_file, u, g) return except OSError as e: error = e LOG.warning( "Failed changing perms on '%s'. tried: %s. %s", log_file, ",".join(perms), error, )
def execute(self): """ This method executes post-customization script before or after reboot based on the presence of rc local. """ self.prepare_script() self.install_agent() if not self.postreboot: LOG.warning("Executing post-customization script inline") util.subp(["/bin/sh", self.scriptpath, "postcustomization"]) else: LOG.debug("Scheduling custom script to run post reboot") if not os.path.isdir(CustomScriptConstant.POST_CUST_TMP_DIR): os.mkdir(CustomScriptConstant.POST_CUST_TMP_DIR) # Script "post-customize-guest.sh" and user uploaded script are # are present in the same directory and needs to copied to a temp # directory to be executed post reboot. User uploaded script is # saved as customize.sh in the temp directory. # post-customize-guest.sh excutes customize.sh after reboot. LOG.debug("Copying post-customization script") util.copy(self.scriptpath, CustomScriptConstant.POST_CUST_TMP_DIR + "/customize.sh") LOG.debug("Copying script to run post-customization script") util.copy( os.path.join(self.directory, CustomScriptConstant.POST_CUST_RUN_SCRIPT_NAME), CustomScriptConstant.POST_CUST_RUN_SCRIPT) LOG.info("Creating post-reboot pending marker") util.ensure_file(CustomScriptConstant.POST_REBOOT_PENDING_MARKER)
def test__is_cloudinit_disabled( self, ensured_file: Optional[Callable], uses_systemd: bool, get_cmdline: str, expected_is_disabled: bool, is_disabled_msg: str, expected_reason: Union[str, Callable], config: Config, ): if ensured_file is not None: ensure_file(ensured_file(config)) (is_disabled, reason) = wrap_and_call( M_NAME, { "uses_systemd": uses_systemd, "get_cmdline": get_cmdline, }, status._is_cloudinit_disabled, config.disable_file, config.paths, ) assert is_disabled == expected_is_disabled, is_disabled_msg if isinstance(expected_reason, str): assert reason == expected_reason else: assert reason == expected_reason(config)
def test_status_output( self, m_read_cfg_paths, ensured_file: Optional[Callable], status_content: Dict, assert_file, cmdargs: MyArgs, expected_retcode: int, expected_status: str, config: Config, ): m_read_cfg_paths.return_value = config.paths if ensured_file: ensure_file(ensured_file(config)) write_json( config.status_file, status_content, ) if assert_file: assert not os.path.exists( config.result_file), f"Unexpected {config.result_file} found" with mock.patch("sys.stdout", new_callable=StringIO) as m_stdout: retcode = wrap_and_call( M_NAME, {"_is_cloudinit_disabled": (False, "")}, status.handle_status_args, "ignored", cmdargs, ) assert retcode == expected_retcode assert m_stdout.getvalue() == expected_status
def _apply_and_verify_freebsd(self, apply_fn, config, expected_cfgs=None, bringup=False): if not expected_cfgs: raise ValueError('expected_cfg must not be None') tmpd = None with mock.patch('cloudinit.net.freebsd.available') as m_avail: m_avail.return_value = True with self.reRooted(tmpd) as tmpd: util.ensure_dir('/etc') util.ensure_file('/etc/rc.conf') util.ensure_file('/etc/resolv.conf') apply_fn(config, bringup) results = dir2dict(tmpd) for cfgpath, expected in expected_cfgs.items(): print("----------") print(expected) print("^^^^ expected | rendered VVVVVVV") print(results[cfgpath]) print("----------") self.assertEqual(set(expected.split('\n')), set(results[cfgpath].split('\n'))) self.assertEqual(0o644, get_mode(cfgpath, tmpd))
def test_status_returns_running(self): """Report running when status exists with an unfinished stage.""" ensure_file(self.tmp_path("result.json", self.new_root)) write_json(self.status_file, {"v1": { "init": { "start": 1, "finished": None } }}) cmdargs = myargs(long=False, wait=False) with mock.patch("sys.stdout", new_callable=StringIO) as m_stdout: retcode = wrap_and_call( "cloudinit.cmd.status", { "_is_cloudinit_disabled": (False, ""), "Init": { "side_effect": self.init_class }, }, status.handle_status_args, "ignored", cmdargs, ) self.assertEqual(0, retcode) self.assertEqual("status: running\n", m_stdout.getvalue())
def test_status_returns_done_long(self): '''Long format of done status includes datasource info.''' ensure_file(self.tmp_path('result.json', self.new_root)) write_json( self.status_file, {'v1': {'stage': None, 'datasource': ( 'DataSourceNoCloud [seed=/var/.../seed/nocloud-net]' '[dsmode=net]'), 'init': {'start': 124.567, 'finished': 125.678}, 'init-local': {'start': 123.45, 'finished': 123.46}}}) cmdargs = myargs(long=True, wait=False) with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout: retcode = wrap_and_call( 'cloudinit.cmd.status', {'_is_cloudinit_disabled': (False, ''), 'Init': {'side_effect': self.init_class}}, status.handle_status_args, 'ignored', cmdargs) self.assertEqual(0, retcode) expected = dedent('''\ status: done time: Thu, 01 Jan 1970 00:02:05 +0000 detail: DataSourceNoCloud [seed=/var/.../seed/nocloud-net][dsmode=net] ''') self.assertEqual(expected, m_stdout.getvalue())
def test_static_parameters_are_passed(self, m_write_file): """Test that the static write_files parameters are passed correctly.""" util.ensure_file(mock.sentinel.path) assert 1 == m_write_file.call_count _args, kwargs = m_write_file.call_args assert "" == kwargs["content"] assert "ab" == kwargs["omode"]
def test_parse_empty_lease_file_errors(self): """parse_dhcp_lease_file errors when file content is empty.""" empty_file = self.tmp_path('leases') ensure_file(empty_file) with self.assertRaises(InvalidDHCPLeaseFileError) as context_manager: parse_dhcp_lease_file(empty_file) error = context_manager.exception self.assertIn('Cannot parse empty dhcp lease file', str(error))
def test_generate_fallback_config_skips_bonds(self): """generate_fallback_config will skip any bonded interfaces.""" # A connected veth which gets ignored write_file(os.path.join(self.sysdir, 'eth0', 'carrier'), '1') mac = 'aa:bb:cc:aa:bb:cc' write_file(os.path.join(self.sysdir, 'eth0', 'address'), mac) ensure_file(os.path.join(self.sysdir, 'eth0', 'bonding')) self.assertIsNone(net.generate_fallback_config())
def fake_sleep(interval): self.assertEqual(0.25, interval) self.sleep_calls += 1 if self.sleep_calls == 2: write_json(self.status_file, running_json) elif self.sleep_calls == 3: write_json(self.status_file, done_json) result_file = self.tmp_path('result.json', self.new_root) ensure_file(result_file)
def test__is_cloudinit_disabled_true_on_disable_file(self): '''When using systemd and disable_file is present return disabled.''' ensure_file(self.disable_file) # Create observed disable file (is_disabled, reason) = wrap_and_call('cloudinit.cmd.status', {'uses_systemd': True}, status._is_cloudinit_disabled, self.disable_file, self.paths) self.assertTrue(is_disabled, 'expected disabled cloud-init') self.assertEqual( 'Cloud-init disabled by {0}'.format(self.disable_file), reason)
def fake_sleep(interval): nonlocal sleep_calls assert interval == 0.25 sleep_calls += 1 if sleep_calls == 2: write_json(config.status_file, running_json) elif sleep_calls == 3: write_json(config.status_file, done_json) result_file = config.result_file ensure_file(result_file)
def test__is_cloudinit_disabled_false_on_sysvinit(self): '''When not in an environment using systemd, return False.''' ensure_file(self.disable_file) # Create the ignored disable file (is_disabled, reason) = wrap_and_call('cloudinit.cmd.status', {'uses_systemd': False}, status._is_cloudinit_disabled, self.disable_file, self.paths) self.assertFalse(is_disabled, 'expected enabled cloud-init on sysvinit') self.assertEqual('Cloud-init enabled on sysvinit', reason)
def test__is_cloudinit_disabled_false_on_kernel_cmdline_enable(self): '''Not disabled when using systemd and enabled via commandline.''' ensure_file(self.disable_file) # Create ignored disable file (is_disabled, reason) = wrap_and_call( 'cloudinit.cmd.status', {'uses_systemd': True, 'get_cmdline': 'something cloud-init=enabled else'}, status._is_cloudinit_disabled, self.disable_file, self.paths) self.assertFalse(is_disabled, 'expected enabled cloud-init') self.assertEqual( 'Cloud-init enabled by kernel command line cloud-init=enabled', reason)
def test__is_cloudinit_disabled_false_when_enabled_in_systemd(self): '''Report enabled when systemd generator creates the enabled file.''' enabled_file = os.path.join(self.paths.run_dir, 'enabled') ensure_file(enabled_file) (is_disabled, reason) = wrap_and_call( 'cloudinit.cmd.status', {'uses_systemd': True, 'get_cmdline': 'something ignored'}, status._is_cloudinit_disabled, self.disable_file, self.paths) self.assertFalse(is_disabled, 'expected enabled cloud-init') self.assertEqual( 'Cloud-init enabled by systemd cloud-init-generator', reason)
def _initialize_filesystem(self): util.ensure_dirs(self._initial_subdirs()) log_file = util.get_cfg_option_str(self.cfg, "def_log_file") perms = util.get_cfg_option_str(self.cfg, "syslog_fix_perms") if log_file: util.ensure_file(log_file) if perms: u, g = util.extract_usergroup(perms) try: util.chownbyname(log_file, u, g) except OSError: util.logexc(LOG, "Unable to change the ownership of %s to " "user %s, group %s", log_file, u, g)
def _initialize_filesystem(self): util.ensure_dirs(self._initial_subdirs()) log_file = util.get_cfg_option_str(self.cfg, 'def_log_file') perms = util.get_cfg_option_str(self.cfg, 'syslog_fix_perms') if log_file: util.ensure_file(log_file) if perms: u, g = util.extract_usergroup(perms) try: util.chownbyname(log_file, u, g) except OSError: util.logexc(LOG, "Unable to change the ownership of %s to " "user %s, group %s", log_file, u, g)
def test__is_cloudinit_disabled_true_when_generator_disables(self): """When cloud-init-generator writes disabled file return True.""" disabled_file = os.path.join(self.paths.run_dir, "disabled") ensure_file(disabled_file) (is_disabled, reason) = wrap_and_call( "cloudinit.cmd.status", {"uses_systemd": True, "get_cmdline": "something"}, status._is_cloudinit_disabled, self.disable_file, self.paths, ) self.assertTrue(is_disabled, "expected disabled cloud-init") self.assertEqual("Cloud-init disabled by cloud-init-generator", reason)
def test_parameters_passed_through(self, m_write_file): """Test the parameters in the signature are passed to write_file.""" util.ensure_file( mock.sentinel.path, mode=mock.sentinel.mode, preserve_mode=mock.sentinel.preserve_mode, ) assert 1 == m_write_file.call_count args, kwargs = m_write_file.call_args assert (mock.sentinel.path, ) == args assert mock.sentinel.mode == kwargs["mode"] assert mock.sentinel.preserve_mode == kwargs["preserve_mode"]
def test_status_returns_running(self): '''Report running when status exists with an unfinished stage.''' ensure_file(self.tmp_path('result.json', self.new_root)) write_json(self.status_file, {'v1': {'init': {'start': 1, 'finished': None}}}) cmdargs = myargs(long=False, wait=False) with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout: retcode = wrap_and_call( 'cloudinit.cmd.status', {'_is_cloudinit_disabled': (False, ''), 'Init': {'side_effect': self.init_class}}, status.handle_status_args, 'ignored', cmdargs) self.assertEqual(0, retcode) self.assertEqual('status: running\n', m_stdout.getvalue())
def test__is_cloudinit_disabled_false_when_enabled_in_systemd(self): """Report enabled when systemd generator creates the enabled file.""" enabled_file = os.path.join(self.paths.run_dir, "enabled") ensure_file(enabled_file) (is_disabled, reason) = wrap_and_call( "cloudinit.cmd.status", {"uses_systemd": True, "get_cmdline": "something ignored"}, status._is_cloudinit_disabled, self.disable_file, self.paths, ) self.assertFalse(is_disabled, "expected enabled cloud-init") self.assertEqual( "Cloud-init enabled by systemd cloud-init-generator", reason )
def test__is_cloudinit_disabled_false_on_sysvinit(self): """When not in an environment using systemd, return False.""" ensure_file(self.disable_file) # Create the ignored disable file (is_disabled, reason) = wrap_and_call( "cloudinit.cmd.status", { "uses_systemd": False, "get_cmdline": "root=/dev/my-root not-important", }, status._is_cloudinit_disabled, self.disable_file, self.paths, ) self.assertFalse(is_disabled, "expected enabled cloud-init on sysvinit") self.assertEqual("Cloud-init enabled on sysvinit", reason)
def test__is_cloudinit_disabled_true_on_disable_file(self): """When using systemd and disable_file is present return disabled.""" ensure_file(self.disable_file) # Create observed disable file (is_disabled, reason) = wrap_and_call( "cloudinit.cmd.status", { "uses_systemd": True, "get_cmdline": "root=/dev/my-root not-important", }, status._is_cloudinit_disabled, self.disable_file, self.paths, ) self.assertTrue(is_disabled, "expected disabled cloud-init") self.assertEqual( "Cloud-init disabled by {0}".format(self.disable_file), reason)
def execute(self): """ This method copy the post customize run script to cc_scripts_per_instance directory and let this module to run post custom script. """ self.prepare_script() LOG.debug("Copying post customize run script to %s", self.ccScriptPath) util.copy( os.path.join(self.directory, CustomScriptConstant.POST_CUSTOM_SCRIPT_NAME), self.ccScriptPath) st = os.stat(self.ccScriptPath) os.chmod(self.ccScriptPath, st.st_mode | stat.S_IEXEC) LOG.info("Creating post customization pending marker") util.ensure_file(CustomScriptConstant.POST_CUSTOM_PENDING_MARKER)
def test_status_returns_done_long(self): """Long format of done status includes datasource info.""" ensure_file(self.tmp_path("result.json", self.new_root)) write_json( self.status_file, { "v1": { "stage": None, "datasource": ("DataSourceNoCloud [seed=/var/.../seed/nocloud-net]" "[dsmode=net]"), "init": { "start": 124.567, "finished": 125.678 }, "init-local": { "start": 123.45, "finished": 123.46 }, } }, ) cmdargs = myargs(long=True, wait=False) with mock.patch("sys.stdout", new_callable=StringIO) as m_stdout: retcode = wrap_and_call( "cloudinit.cmd.status", { "_is_cloudinit_disabled": (False, ""), "Init": { "side_effect": self.init_class }, }, status.handle_status_args, "ignored", cmdargs, ) self.assertEqual(0, retcode) expected = dedent("""\ status: done time: Thu, 01 Jan 1970 00:02:05 +0000 detail: DataSourceNoCloud [seed=/var/.../seed/nocloud-net][dsmode=net] """) self.assertEqual(expected, m_stdout.getvalue())
def test__is_cloudinit_disabled_false_on_kernel_cmdline_enable(self): """Not disabled when using systemd and enabled via commandline.""" ensure_file(self.disable_file) # Create ignored disable file (is_disabled, reason) = wrap_and_call( "cloudinit.cmd.status", { "uses_systemd": True, "get_cmdline": "something cloud-init=enabled else", }, status._is_cloudinit_disabled, self.disable_file, self.paths, ) self.assertFalse(is_disabled, "expected enabled cloud-init") self.assertEqual( "Cloud-init enabled by kernel command line cloud-init=enabled", reason, )
def test_status_returns_done(self): """Report done results.json exists no stages are unfinished.""" ensure_file(self.tmp_path("result.json", self.new_root)) write_json( self.status_file, { "v1": { "stage": None, # No current stage running "datasource": ("DataSourceNoCloud [seed=/var/.../seed/nocloud-net]" "[dsmode=net]"), "blah": { "finished": 123.456 }, "init": { "errors": [], "start": 124.567, "finished": 125.678, }, "init-local": { "start": 123.45, "finished": 123.46 }, } }, ) cmdargs = myargs(long=False, wait=False) with mock.patch("sys.stdout", new_callable=StringIO) as m_stdout: retcode = wrap_and_call( "cloudinit.cmd.status", { "_is_cloudinit_disabled": (False, ""), "Init": { "side_effect": self.init_class }, }, status.handle_status_args, "ignored", cmdargs, ) self.assertEqual(0, retcode) self.assertEqual("status: done\n", m_stdout.getvalue())
def _initialize_filesystem(self): util.ensure_dirs(self._initial_subdirs()) log_file = util.get_cfg_option_str(self.cfg, 'def_log_file') if log_file: util.ensure_file(log_file) perms = self.cfg.get('syslog_fix_perms') if not perms: perms = {} if not isinstance(perms, list): perms = [perms] error = None for perm in perms: u, g = util.extract_usergroup(perm) try: util.chownbyname(log_file, u, g) return except OSError as e: error = e LOG.warn("Failed changing perms on '%s'. tried: %s. %s", log_file, ','.join(perms), error)
def test_is_wireless(self): """is_wireless is True when /sys/net/devname/wireless exists.""" self.assertFalse(net.is_wireless('eth0')) ensure_file(os.path.join(self.sysdir, 'eth0', 'wireless')) self.assertTrue(net.is_wireless('eth0'))
def test_is_bridge(self): """is_bridge is True when /sys/net/devname/bridge exists.""" self.assertFalse(net.is_bridge('eth0')) ensure_file(os.path.join(self.sysdir, 'eth0', 'bridge')) self.assertTrue(net.is_bridge('eth0'))
def test_is_bond(self): """is_bond is True when /sys/net/devname/bonding exists.""" self.assertFalse(net.is_bond('eth0')) ensure_file(os.path.join(self.sysdir, 'eth0', 'bonding')) self.assertTrue(net.is_bond('eth0'))
def test_is_present(self): """is_present is True when /sys/net/devname exists.""" self.assertFalse(net.is_present('eth0')) ensure_file(os.path.join(self.sysdir, 'eth0', 'device')) self.assertTrue(net.is_present('eth0'))
def test_get_interface_mac_false_with_no_mac(self): """get_device_list returns False when no mac is reported.""" ensure_file(os.path.join(self.sysdir, 'eth0', 'bonding')) mac_path = os.path.join(self.sysdir, 'eth0', 'address') self.assertFalse(os.path.exists(mac_path)) self.assertFalse(net.get_interface_mac('eth0'))
def setUp(self): super(TextKvpReporter, self).setUp() self.tmp_file_path = self.tmp_path('kvp_pool_file') util.ensure_file(self.tmp_file_path)