def test_markerid_file_exist(self): """Return False when markerid file path does not exist, True otherwise.""" self.assertFalse( dsovf.check_marker_exists('123', self.tdir)) marker_file = self.tmp_path('.markerfile-123.txt', self.tdir) util.write_file(marker_file, '') self.assertTrue( dsovf.check_marker_exists('123', self.tdir) )
def test_found_when_guestinfo_present(self, m_subp, m_which): """When there is a ovf info, transport should return it.""" m_which.return_value = self.rpctool_path content = fill_properties({}) m_subp.return_value = (content, '') self.assertEqual(content, dsovf.transport_vmware_guestinfo()) self.assertEqual(1, m_subp.call_count)
def test_mount_cb_not_called_no_matches(self): """Check we don't call mount_cb if nothing matches""" self.m_mounts.return_value = {} self.m_find_devs_with.return_value = ['/dev/vg/myovf'] self.assertEqual(NOT_FOUND, dsovf.transport_iso9660()) self.assertEqual(0, self.m_mount_cb.call_count)
def test_with_no_userdata(self): props = {"password": "******", "instance-id": "inst-001"} env = fill_properties(props) md, ud, cfg = dsovf.read_ovf_environment(env) self.assertEqual({"instance-id": "inst-001"}, md) self.assertEqual({'password': "******"}, cfg) self.assertEqual(None, ud)
def test_with_non_b64_userdata(self): user_data = "my-user-data" props = {"user-data": user_data, "instance-id": "inst-001"} env = fill_properties(props) md, ud, cfg = dsovf.read_ovf_environment(env) self.assertEqual({"instance-id": "inst-001"}, md) self.assertEqual(user_data.encode(), ud) self.assertEqual({}, cfg)
def test_notfound_and_warns_on_unexpected_exit_code(self, m_subp, m_which): """If vmware-rpctool exits non zero or 1, warnings should be logged.""" m_which.return_value = self.rpctool_path m_subp.side_effect = util.ProcessExecutionError( stdout=None, stderr="No value found", exit_code=2, cmd=["unused"]) self.assertEqual(NOT_FOUND, dsovf.transport_vmware_guestinfo()) self.assertEqual(1, m_subp.call_count) self.assertIn("WARNING", self.logs.getvalue(), "exit code of 2 by rpctool should log WARNING.")
def test_mount_cb_called_on_blkdevs_with_iso9660(self): """Check we call mount_cb on blockdevs with iso9660 only""" self.m_mounts.return_value = {} self.m_find_devs_with.return_value = ['/dev/sr0'] self.m_mount_cb.return_value = ("myfile", "mycontent") self.assertEqual("mycontent", dsovf.transport_iso9660()) self.m_mount_cb.assert_called_with( "/dev/sr0", dsovf.get_ovf_env, mtype="iso9660")
def test_notfound_on_exit_code_1(self, m_subp, m_which): """If vmware-rpctool exits 1, then must return not found.""" m_which.return_value = self.rpctool_path m_subp.side_effect = util.ProcessExecutionError( stdout="", stderr="No value found", exit_code=1, cmd=["unused"]) self.assertEqual(NOT_FOUND, dsovf.transport_vmware_guestinfo()) self.assertEqual(1, m_subp.call_count) self.assertNotIn("WARNING", self.logs.getvalue(), "exit code of 1 by rpctool should not cause warning.")
def test_with_b64_userdata(self): user_data = "#!/bin/sh\necho hello world\n" user_data_b64 = base64.b64encode(user_data.encode()).decode() props = {"user-data": user_data_b64, "password": "******", "instance-id": "inst-001"} env = fill_properties(props) md, ud, cfg = dsovf.read_ovf_environment(env) self.assertEqual({"instance-id": "inst-001"}, md) self.assertEqual(user_data.encode(), ud) self.assertEqual({'password': "******"}, cfg)
def test_notfound_if_no_content_but_exit_zero(self, m_subp, m_which): """If vmware-rpctool exited 0 with no stdout is normal not-found. This isn't actually a case I've seen. normally on "not found", rpctool would exit 1 with 'No value found' on stderr. But cover the case where it exited 0 and just wrote nothing to stdout. """ m_which.return_value = self.rpctool_path m_subp.return_value = ('', '') self.assertEqual(NOT_FOUND, dsovf.transport_vmware_guestinfo()) self.assertEqual(1, m_subp.call_count)
def test_mount_cb_called_require_iso_false(self): """Check we call mount_cb on blockdevs with require_iso=False""" self.m_mounts.return_value = {} self.m_find_devs_with.return_value = ['/dev/xvdz'] self.m_mount_cb.return_value = ("myfile", "mycontent") self.assertEqual( "mycontent", dsovf.transport_iso9660(require_iso=False)) self.m_mount_cb.assert_called_with( "/dev/xvdz", dsovf.get_ovf_env, mtype=None)
def test_find_already_mounted(self): """Check we call get_ovf_env from on matching mounted devices""" mounts = { '/dev/sr9': { 'fstype': 'iso9660', 'mountpoint': 'wark/media/sr9', 'opts': 'ro', } } self.m_mounts.return_value = mounts self.assertEqual("mycontent", dsovf.transport_iso9660())
def test_find_already_mounted_matches_kname(self): """Check we dont regex match on basename of the device""" mounts = { '/dev/foo/bar/xvdc': { 'fstype': 'iso9660', 'mountpoint': 'wark/media/sr9', 'opts': 'ro', } } # we're skipping an entry which fails to match. self.m_mounts.return_value = mounts self.assertEqual(NOT_FOUND, dsovf.transport_iso9660())
def test_with_b64_userdata(self): user_data = "#!/bin/sh\necho hello world\n" user_data_b64 = base64.b64encode(user_data.encode()).decode() props = { "user-data": user_data_b64, "password": "******", "instance-id": "inst-001" } env = fill_properties(props) md, ud, cfg = dsovf.read_ovf_environment(env) self.assertEqual({"instance-id": "inst-001"}, md) self.assertEqual(user_data.encode(), ud) self.assertEqual({'password': "******"}, cfg)
def test_mount_cb_called_on_blkdevs_with_iso9660(self): """Check we call mount_cb on blockdevs with iso9660 only""" self.m_mounts.return_value = {} self.m_find_devs_with.return_value = ['/dev/sr0'] self.m_mount_cb.return_value = ("myfile", "mycontent") (contents, fullp, fname) = dsovf.transport_iso9660() self.m_mount_cb.assert_called_with("/dev/sr0", dsovf.get_ovf_env, mtype="iso9660") self.assertEqual("mycontent", contents) self.assertEqual("/dev/sr0", fullp) self.assertEqual("myfile", fname)
def test_mount_cb_called_require_iso_false(self): """Check we call mount_cb on blockdevs with require_iso=False""" self.m_mounts.return_value = {} self.m_find_devs_with.return_value = ['/dev/xvdz'] self.m_mount_cb.return_value = ("myfile", "mycontent") (contents, fullp, fname) = dsovf.transport_iso9660(require_iso=False) self.m_mount_cb.assert_called_with("/dev/xvdz", dsovf.get_ovf_env, mtype=None) self.assertEqual("mycontent", contents) self.assertEqual("/dev/xvdz", fullp) self.assertEqual("myfile", fname)
def test_mount_cb_called_on_blkdevs_with_iso9660_check_regex(self): """Check we call mount_cb on blockdevs with iso9660 and match regex""" self.m_mounts.return_value = {} self.m_find_devs_with.return_value = [ "/dev/abc", "/dev/my-cdrom", "/dev/sr0", ] self.m_mount_cb.return_value = ("myfile", "mycontent") self.assertEqual("mycontent", dsovf.transport_iso9660()) self.m_mount_cb.assert_called_with( "/dev/sr0", dsovf.get_ovf_env, mtype="iso9660" )
def test_with_b64_network_config_enable_read_network(self): network_config = dedent( """\ network: version: 2 ethernets: nics: nameservers: addresses: - 127.0.0.53 search: - eng.vmware.com - vmware.com match: name: eth* gateway4: 10.10.10.253 dhcp4: false addresses: - 10.10.10.1/24 """ ) network_config_b64 = base64.b64encode(network_config.encode()).decode() props = { "network-config": network_config_b64, "password": "******", "instance-id": "inst-001", } env = fill_properties(props) md, ud, cfg = dsovf.read_ovf_environment(env, True) self.assertEqual("inst-001", md["instance-id"]) self.assertEqual({"password": "******"}, cfg) self.assertEqual( { "version": 2, "ethernets": { "nics": { "nameservers": { "addresses": ["127.0.0.53"], "search": ["eng.vmware.com", "vmware.com"], }, "match": {"name": "eth*"}, "gateway4": "10.10.10.253", "dhcp4": False, "addresses": ["10.10.10.1/24"], } }, }, md["network-config"], ) self.assertIsNone(ud)
def test_find_already_mounted(self): """Check we call get_ovf_env from on matching mounted devices""" mounts = { '/dev/sr9': { 'fstype': 'iso9660', 'mountpoint': 'wark/media/sr9', 'opts': 'ro', } } self.m_mounts.return_value = mounts (contents, fullp, fname) = dsovf.transport_iso9660() self.assertEqual("mycontent", contents) self.assertEqual("/dev/sr9", fullp) self.assertEqual("myfile", fname)
def test_with_b64_network_config_enable_read_network(self): network_config = dedent("""\ network: version: 2 ethernets: nics: nameservers: addresses: - 127.0.0.53 search: - eng.vmware.com - vmware.com match: name: eth* gateway4: 10.10.10.253 dhcp4: false addresses: - 10.10.10.1/24 """) network_config_b64 = base64.b64encode(network_config.encode()).decode() props = { "network-config": network_config_b64, "password": "******", "instance-id": "inst-001" } env = fill_properties(props) md, ud, cfg = dsovf.read_ovf_environment(env, True) self.assertEqual("inst-001", md["instance-id"]) self.assertEqual({'password': "******"}, cfg) self.assertEqual( { 'version': 2, 'ethernets': { 'nics': { 'nameservers': { 'addresses': ['127.0.0.53'], 'search': ['eng.vmware.com', 'vmware.com'] }, 'match': { 'name': 'eth*' }, 'gateway4': '10.10.10.253', 'dhcp4': False, 'addresses': ['10.10.10.1/24'] } } }, md["network-config"]) self.assertIsNone(ud)
def test_find_already_mounted_skips_non_iso9660(self): """Check we call get_ovf_env ignoring non iso9660""" mounts = { '/dev/xvdb': { 'fstype': 'vfat', 'mountpoint': 'wark/foobar', 'opts': 'defaults,noatime', }, '/dev/xvdc': { 'fstype': 'iso9660', 'mountpoint': 'wark/media/sr9', 'opts': 'ro', } } # We use an OrderedDict here to ensure we check xvdb before xvdc # as we're not mocking the regex matching, however, if we place # an entry in the results then we can be reasonably sure that # we're skipping an entry which fails to match. self.m_mounts.return_value = ( OrderedDict(sorted(mounts.items(), key=lambda t: t[0]))) self.assertEqual("mycontent", dsovf.transport_iso9660())
def test_find_already_mounted_skips_non_iso9660(self): """Check we call get_ovf_env ignoring non iso9660""" mounts = { '/dev/xvdb': { 'fstype': 'vfat', 'mountpoint': 'wark/foobar', 'opts': 'defaults,noatime', }, '/dev/xvdc': { 'fstype': 'iso9660', 'mountpoint': 'wark/media/sr9', 'opts': 'ro', } } # We use an OrderedDict here to ensure we check xvdb before xvdc # as we're not mocking the regex matching, however, if we place # an entry in the results then we can be reasonably sure that # we're skipping an entry which fails to match. self.m_mounts.return_value = (OrderedDict( sorted(mounts.items(), key=lambda t: t[0]))) self.assertEqual("mycontent", dsovf.transport_iso9660())
def test_find_already_mounted_skips_non_iso9660(self): """Check we call get_ovf_env ignoring non iso9660""" mounts = { "/dev/xvdb": { "fstype": "vfat", "mountpoint": "wark/foobar", "opts": "defaults,noatime", }, "/dev/xvdc": { "fstype": "iso9660", "mountpoint": "wark/media/sr9", "opts": "ro", }, } # We use an OrderedDict here to ensure we check xvdb before xvdc # as we're not mocking the regex matching, however, if we place # an entry in the results then we can be reasonably sure that # we're skipping an entry which fails to match. self.m_mounts.return_value = OrderedDict( sorted(mounts.items(), key=lambda t: t[0]) ) self.assertEqual("mycontent", dsovf.transport_iso9660())
def test_marker_file_setup(self): """Test creation of marker files.""" markerfilepath = self.tmp_path(".markerfile-hi.txt", self.tdir) self.assertFalse(os.path.exists(markerfilepath)) dsovf.setup_marker_files(markerid="hi", marker_dir=self.tdir) self.assertTrue(os.path.exists(markerfilepath))
def test_false_when_markerid_none(self): """Return False when markerid provided is None.""" self.assertFalse( dsovf.check_marker_exists(markerid=None, marker_dir=self.tdir) )
def test_without_vmware_rpctool_returns_notfound(self, m_subp, m_which): m_which.return_value = None self.assertEqual(NOT_FOUND, dsovf.transport_vmware_guestinfo()) self.assertEqual(0, m_subp.call_count, "subp should not be called if no rpctool in path.")
def test_maybe_cdrom_device_true_on_hd_partitions(self): """Test maybe_cdrom_device is false on /dev/hd[a-z][0-9]+ paths""" self.assertTrue(dsovf.maybe_cdrom_device('/dev/hda1')) self.assertTrue(dsovf.maybe_cdrom_device('hdz9'))
def test_maybe_cdrom_device_true_on_hd_partitions(self): """Test maybe_cdrom_device is false on /dev/hd[a-z][0-9]+ paths""" self.assertTrue(dsovf.maybe_cdrom_device("/dev/hda1")) self.assertTrue(dsovf.maybe_cdrom_device("hdz9"))
def test_false_when_markerid_none(self): """Return False when markerid provided is None.""" self.assertFalse( dsovf.check_marker_exists(markerid=None, marker_dir=self.tdir))
def test_maybe_cdrom_device_true_on_xvd_partitions(self): """Test maybe_cdrom_device returns true on xvd*""" self.assertTrue(dsovf.maybe_cdrom_device("/dev/xvda")) self.assertTrue(dsovf.maybe_cdrom_device("/dev/xvda1")) self.assertTrue(dsovf.maybe_cdrom_device("xvdza1"))
def test_maybe_cdrom_device_none(self): """Test maybe_cdrom_device returns False for none/empty input""" self.assertFalse(dsovf.maybe_cdrom_device(None)) self.assertFalse(dsovf.maybe_cdrom_device(''))
def test_maybe_cdrom_device_non_string_exception(self): """Test maybe_cdrom_device raises ValueError on non-string types""" with self.assertRaises(ValueError): dsovf.maybe_cdrom_device({'a': 'eleven'})
def test_maybe_cdrom_device_false_on_multi_dir_paths(self): """Test maybe_cdrom_device is false on /dev[/.*]/* paths""" self.assertFalse(dsovf.maybe_cdrom_device('/dev/foo/sr0')) self.assertFalse(dsovf.maybe_cdrom_device('foo/sr0')) self.assertFalse(dsovf.maybe_cdrom_device('../foo/sr0')) self.assertFalse(dsovf.maybe_cdrom_device('../foo/sr0'))
def test_maybe_cdrom_device_non_string_exception(self): """Test maybe_cdrom_device raises ValueError on non-string types""" with self.assertRaises(ValueError): dsovf.maybe_cdrom_device({"a": "eleven"})
def test_maybe_cdrom_device_true_on_xvd_partitions(self): """Test maybe_cdrom_device returns true on xvd*""" self.assertTrue(dsovf.maybe_cdrom_device('/dev/xvda')) self.assertTrue(dsovf.maybe_cdrom_device('/dev/xvda1')) self.assertTrue(dsovf.maybe_cdrom_device('xvdza1'))
def test_maybe_cdrom_device_none(self): """Test maybe_cdrom_device returns False for none/empty input""" self.assertFalse(dsovf.maybe_cdrom_device(None)) self.assertFalse(dsovf.maybe_cdrom_device(""))
def test_maybe_cdrom_device_true_on_valid_relative_paths(self): """Test maybe_cdrom_device normalizes paths""" self.assertTrue(dsovf.maybe_cdrom_device('/dev/wark/../sr9')) self.assertTrue(dsovf.maybe_cdrom_device('///sr0')) self.assertTrue(dsovf.maybe_cdrom_device('/sr0')) self.assertTrue(dsovf.maybe_cdrom_device('//dev//hda'))
def test_maybe_cdrom_device_false_on_multi_dir_paths(self): """Test maybe_cdrom_device is false on /dev[/.*]/* paths""" self.assertFalse(dsovf.maybe_cdrom_device("/dev/foo/sr0")) self.assertFalse(dsovf.maybe_cdrom_device("foo/sr0")) self.assertFalse(dsovf.maybe_cdrom_device("../foo/sr0")) self.assertFalse(dsovf.maybe_cdrom_device("../foo/sr0"))
def test_maybe_cdrom_device_true_on_valid_relative_paths(self): """Test maybe_cdrom_device normalizes paths""" self.assertTrue(dsovf.maybe_cdrom_device("/dev/wark/../sr9")) self.assertTrue(dsovf.maybe_cdrom_device("///sr0")) self.assertTrue(dsovf.maybe_cdrom_device("/sr0")) self.assertTrue(dsovf.maybe_cdrom_device("//dev//hda"))
def handle_args(name, args): if not args.directory.endswith("/"): args.directory += "/" if not os.path.isdir(args.directory): os.makedirs(args.directory) if args.debug: log.setupBasicLogging(level=log.DEBUG) else: log.setupBasicLogging(level=log.WARN) if args.mac: known_macs = {} for item in args.mac: iface_name, iface_mac = item.split(",", 1) known_macs[iface_mac] = iface_name else: known_macs = None net_data = args.network_data.read() if args.kind == "eni": pre_ns = eni.convert_eni_data(net_data) elif args.kind == "yaml": pre_ns = yaml.load(net_data) if 'network' in pre_ns: pre_ns = pre_ns.get('network') if args.debug: sys.stderr.write('\n'.join( ["Input YAML", yaml.dump(pre_ns, default_flow_style=False, indent=4), ""])) elif args.kind == 'network_data.json': pre_ns = openstack.convert_net_json( json.loads(net_data), known_macs=known_macs) elif args.kind == 'azure-imds': pre_ns = azure.parse_network_config(json.loads(net_data)) elif args.kind == 'vmware-imc': config = ovf.Config(ovf.ConfigFile(args.network_data.name)) pre_ns = ovf.get_network_config_from_conf(config, False) ns = network_state.parse_net_config_data(pre_ns) if not ns: raise RuntimeError("No valid network_state object created from" "input data") if args.debug: sys.stderr.write('\n'.join([ "", "Internal State", yaml.dump(ns, default_flow_style=False, indent=4), ""])) distro_cls = distros.fetch(args.distro) distro = distro_cls(args.distro, {}, None) config = {} if args.output_kind == "eni": r_cls = eni.Renderer config = distro.renderer_configs.get('eni') elif args.output_kind == "netplan": r_cls = netplan.Renderer config = distro.renderer_configs.get('netplan') # don't run netplan generate/apply config['postcmds'] = False # trim leading slash config['netplan_path'] = config['netplan_path'][1:] else: r_cls = sysconfig.Renderer config = distro.renderer_configs.get('sysconfig') r = r_cls(config=config) sys.stderr.write(''.join([ "Read input format '%s' from '%s'.\n" % ( args.kind, args.network_data.name), "Wrote output format '%s' to '%s'\n" % ( args.output_kind, args.directory)]) + "\n") r.render_network_state(network_state=ns, target=args.directory)
def handle_args(name, args): if not args.directory.endswith("/"): args.directory += "/" if not os.path.isdir(args.directory): os.makedirs(args.directory) if args.debug: log.setupBasicLogging(level=log.DEBUG) else: log.setupBasicLogging(level=log.WARN) if args.mac: known_macs = {} for item in args.mac: iface_name, iface_mac = item.split(",", 1) known_macs[iface_mac] = iface_name else: known_macs = None net_data = args.network_data.read() if args.kind == "eni": pre_ns = eni.convert_eni_data(net_data) elif args.kind == "yaml": pre_ns = safeyaml.load(net_data) if 'network' in pre_ns: pre_ns = pre_ns.get('network') if args.debug: sys.stderr.write('\n'.join( ["Input YAML", safeyaml.dumps(pre_ns), ""])) elif args.kind == 'network_data.json': pre_ns = openstack.convert_net_json( json.loads(net_data), known_macs=known_macs) elif args.kind == 'azure-imds': pre_ns = azure.parse_network_config(json.loads(net_data)) elif args.kind == 'vmware-imc': config = ovf.Config(ovf.ConfigFile(args.network_data.name)) pre_ns = ovf.get_network_config_from_conf(config, False) ns = network_state.parse_net_config_data(pre_ns) if args.debug: sys.stderr.write('\n'.join( ["", "Internal State", safeyaml.dumps(ns), ""])) distro_cls = distros.fetch(args.distro) distro = distro_cls(args.distro, {}, None) config = {} if args.output_kind == "eni": r_cls = eni.Renderer config = distro.renderer_configs.get('eni') elif args.output_kind == "netplan": r_cls = netplan.Renderer config = distro.renderer_configs.get('netplan') # don't run netplan generate/apply config['postcmds'] = False # trim leading slash config['netplan_path'] = config['netplan_path'][1:] # enable some netplan features config['features'] = ['dhcp-use-domains', 'ipv6-mtu'] elif args.output_kind == "networkd": r_cls = networkd.Renderer config = distro.renderer_configs.get('networkd') elif args.output_kind == "sysconfig": r_cls = sysconfig.Renderer config = distro.renderer_configs.get('sysconfig') else: raise RuntimeError("Invalid output_kind") r = r_cls(config=config) sys.stderr.write(''.join([ "Read input format '%s' from '%s'.\n" % ( args.kind, args.network_data.name), "Wrote output format '%s' to '%s'\n" % ( args.output_kind, args.directory)]) + "\n") r.render_network_state(network_state=ns, target=args.directory)
def test_marker_file_setup(self): """Test creation of marker files.""" markerfilepath = self.tmp_path('.markerfile-hi.txt', self.tdir) self.assertFalse(os.path.exists(markerfilepath)) dsovf.setup_marker_files(markerid='hi', marker_dir=self.tdir) self.assertTrue(os.path.exists(markerfilepath))