From 4c894b9ebb23909a54d6a1282eb528bb0917931a Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 14:48:33 -0800 Subject: [PATCH 01/12] Python 3 compat fixes: py.test and ConfigParser Signed-off-by: Adam Williamson --- oz/RedHat.py | 10 ++++- oz/ozutil.py | 12 +++++- tests/factory/test_factory.py | 14 +++++-- tests/guest/test_guest.py | 71 +++++++++++++++++++++-------------- tests/ozutil/test_ozutil.py | 50 ++++++++++++------------ tests/tdl/test_tdl.py | 4 +- 6 files changed, 97 insertions(+), 64 deletions(-) diff --git a/oz/RedHat.py b/oz/RedHat.py index 868b549f..57e43f43 100644 --- a/oz/RedHat.py +++ b/oz/RedHat.py @@ -507,8 +507,14 @@ def _parse_treeinfo(self, fp): initrd paths out of it. """ self.log.debug("Got treeinfo, parsing") - config = configparser.SafeConfigParser() - config.readfp(fp) + try: + config = configparser.SafeConfigParser() + config.readfp(fp) + except AttributeError: + # SafeConfigParser was deprecated in Python 3.2 and readfp + # was renamed to read_file + config = configparser.ConfigParser() + config.read_file(fp) section = "images-%s" % (self.tdl.arch) kernel = oz.ozutil.config_get_key(config, section, "kernel", None) initrd = oz.ozutil.config_get_key(config, section, "initrd", None) diff --git a/oz/ozutil.py b/oz/ozutil.py index 3a861be3..5e90797d 100644 --- a/oz/ozutil.py +++ b/oz/ozutil.py @@ -724,12 +724,20 @@ def parse_config(config_file): Function to parse the configuration file. If the passed in config_file is None, then the default configuration file is used. """ - config = configparser.SafeConfigParser() + try: + config = configparser.SafeConfigParser() + except AttributeError: + # SafeConfigParser was deprecated in Python 3.2 + config = configparser.ConfigParser() if config_file is not None: # If the config_file passed in is not None, then we want to try to read # that config file (after expanding it). If that config file doesn't # exist, we want to throw an error (which is why we use readfp here). - config.readfp(open(os.path.expanduser(config_file))) + try: + config.readfp(open(os.path.expanduser(config_file))) + except AttributeError: + # readfp was renamed to read_file in Python 3.2 + config.read_file(open(os.path.expanduser(config_file))) else: # The config file was not passed in, so we want to use one of the # defaults. First we check to see if a ~/.oz/oz.cfg exists; if it does, diff --git a/tests/factory/test_factory.py b/tests/factory/test_factory.py index 8f08b62a..1328b9f9 100755 --- a/tests/factory/test_factory.py +++ b/tests/factory/test_factory.py @@ -31,9 +31,9 @@ sys.exit(1) try: - import py.test + import pytest except ImportError: - print('Unable to import py.test. Is py.test installed?') + print('Unable to import pytest. Is pytest installed?') sys.exit(1) def default_route(): @@ -87,8 +87,14 @@ def runtest(**kwargs): try: tdl = oz.TDL.TDL(tdlxml) - config = configparser.SafeConfigParser() - config.readfp(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) + try: + config = configparser.SafeConfigParser() + config.readfp(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) + except AttributeError: + # SafeConfigParser was deprecated in Python 3.2 and + # readfp was renamed to read_file + config = configparser.ConfigParser() + config.read_file(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) if os.getenv('DEBUG') is not None: logging.basicConfig(level=logging.DEBUG, format="%(message)s") diff --git a/tests/guest/test_guest.py b/tests/guest/test_guest.py index 71e869a6..19b08638 100644 --- a/tests/guest/test_guest.py +++ b/tests/guest/test_guest.py @@ -31,9 +31,9 @@ sys.exit(1) try: - import py.test + import pytest except ImportError: - print('Unable to import py.test. Is py.test installed?') + print('Unable to import pytest. Is pytest installed?') sys.exit(1) def default_route(): @@ -63,8 +63,14 @@ def default_route(): def setup_guest(xml, macaddress=None): tdl = oz.TDL.TDL(xml) - config = configparser.SafeConfigParser() - config.readfp(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) + try: + config = configparser.SafeConfigParser() + config.readfp(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) + except AttributeError: + # SafeConfigParser was deprecated in Python 3.2 and readfp + # was renamed to read_file + config = configparser.ConfigParser() + config.read_file(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) guest = oz.GuestFactory.guest_factory(tdl, config, None, macaddress=macaddress) return guest @@ -104,7 +110,7 @@ def setup_guest(xml, macaddress=None): def test_geteltorito_none_src(): guest = setup_guest(tdlxml) - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(None, None) def test_geteltorito_none_dst(tmpdir): @@ -113,7 +119,7 @@ def test_geteltorito_none_dst(tmpdir): src = os.path.join(str(tmpdir), 'src') open(src, 'w').write('src') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, None) def test_geteltorito_short_pvd(tmpdir): @@ -124,7 +130,7 @@ def test_geteltorito_short_pvd(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(Exception): + with pytest.raises(Exception): guest._geteltorito(src, dst) def test_geteltorito_bogus_pvd_desc(tmpdir): @@ -138,7 +144,7 @@ def test_geteltorito_bogus_pvd_desc(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_bogus_pvd_ident(tmpdir): @@ -153,7 +159,7 @@ def test_geteltorito_bogus_pvd_ident(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_bogus_pvd_unused(tmpdir): @@ -170,7 +176,7 @@ def test_geteltorito_bogus_pvd_unused(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_bogus_pvd_unused2(tmpdir): @@ -191,7 +197,7 @@ def test_geteltorito_bogus_pvd_unused2(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_short_boot_sector(tmpdir): @@ -212,7 +218,7 @@ def test_geteltorito_short_boot_sector(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(Exception): + with pytest.raises(Exception): guest._geteltorito(src, dst) def test_geteltorito_bogus_boot_sector(tmpdir): @@ -236,7 +242,7 @@ def test_geteltorito_bogus_boot_sector(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_bogus_boot_isoident(tmpdir): @@ -261,7 +267,7 @@ def test_geteltorito_bogus_boot_isoident(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_bogus_boot_version(tmpdir): @@ -286,7 +292,7 @@ def test_geteltorito_bogus_boot_version(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_bogus_boot_torito(tmpdir): @@ -312,7 +318,7 @@ def test_geteltorito_bogus_boot_torito(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(oz.OzException.OzException): + with pytest.raises(oz.OzException.OzException): guest._geteltorito(src, dst) def test_geteltorito_bogus_bootp(tmpdir): @@ -340,7 +346,7 @@ def test_geteltorito_bogus_bootp(tmpdir): dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(Exception): + with pytest.raises(Exception): guest._geteltorito(src, dst) def test_init_guest(): @@ -354,9 +360,16 @@ def test_init_guest(): def test_init_guest_bad_arch(): tdl = oz.TDL.TDL(tdlxml) tdl.arch = 'armhf' # Done here to make sure the TDL class doesn't error - config = configparser.SafeConfigParser() - config.readfp(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) - with py.test.raises(Exception): + try: + config = configparser.SafeConfigParser() + config.readfp(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) + except AttributeError: + # SafeConfigParser was deprecated in Python 3.2 and readfp + # was renamed to read_file + config = configparser.ConfigParser() + config.read_file(StringIO("[libvirt]\nuri=qemu:///session\nbridge_name=%s" % route)) + + with pytest.raises(Exception): oz.GuestFactory.guest_factory(tdl, config, None) def test_icicle_generation(): @@ -490,7 +503,7 @@ def test_get_disks_and_interfaces_missing_interface_target(): # Get the comparision xml with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._get_disks_and_interfaces(test_xml) @@ -503,7 +516,7 @@ def test_get_disks_and_interfaces_missing_interface_target_device(): # Get the comparision xml with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._get_disks_and_interfaces(test_xml) @@ -516,7 +529,7 @@ def test_get_disks_and_interfaces_missing_disk_target(): # Get the comparision xml with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._get_disks_and_interfaces(test_xml) @@ -528,7 +541,7 @@ def test_get_disks_and_interfaces_missing_disk_target_device(): # Get the comparision xml path = os.path.dirname(__file__) + '/libvirt/test_get_disks_and_interfaces_missing_disk_target_device.xml' with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._get_disks_and_interfaces(test_xml) @@ -557,7 +570,7 @@ def test_modify_libvirt_xml_for_serial_too_many_targets(): # Get the comparision xml path = os.path.dirname(__file__) + '/libvirt/test_modify_libvirt_xml_for_serial_too_many_targets.xml' with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._modify_libvirt_xml_for_serial(test_xml) @@ -569,7 +582,7 @@ def test_modify_libvirt_xml_for_serial_missing_devices(): # Get the comparision xml path = os.path.dirname(__file__) + '/libvirt/test_modify_libvirt_xml_for_serial_missing_devices.xml' with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._modify_libvirt_xml_for_serial(test_xml) @@ -581,7 +594,7 @@ def test_modify_libvirt_xml_for_serial_too_many_devices(): # Get the comparision xml path = os.path.dirname(__file__) + '/libvirt/test_modify_libvirt_xml_for_serial_too_many_devices.xml' with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._modify_libvirt_xml_for_serial(test_xml) @@ -614,7 +627,7 @@ def test_modify_libvirt_xml_diskimage_missing_disk_source(): # Get the comparision xml path = os.path.dirname(__file__) + '/libvirt/test_modify_libvirt_xml_diskimage_missing_disk_source.xml' with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._modify_libvirt_xml_diskimage(test_xml, guest.diskimage, 'qcow2') @@ -626,7 +639,7 @@ def test_modify_libvirt_xml_diskimage_too_many_drivers(): # Get the comparision xml path = os.path.dirname(__file__) + '/libvirt/test_modify_libvirt_xml_diskimage_too_many_drivers.xml' with open(path, 'r') as handle: - with py.test.raises(Exception): + with pytest.raises(Exception): # Replace various smaller items as they are auto generated test_xml = handle.read() % (guest.uuid, route, guest.listen_port, guest.diskimage) guest._modify_libvirt_xml_diskimage(test_xml, guest.diskimage, 'qcow2') diff --git a/tests/ozutil/test_ozutil.py b/tests/ozutil/test_ozutil.py index dd84f5b6..4624251c 100644 --- a/tests/ozutil/test_ozutil.py +++ b/tests/ozutil/test_ozutil.py @@ -4,9 +4,9 @@ import os try: - import py.test + import pytest except ImportError: - print('Unable to import py.test. Is py.test installed?') + print('Unable to import pytest. Is pytest installed?') sys.exit(1) # Find oz @@ -29,7 +29,7 @@ def test_auto(): assert(oz.ozutil.generate_full_auto_path('fedora-14-jeos.ks') == os.path.realpath(os.path.join(prefix, 'oz', 'auto', 'fedora-14-jeos.ks'))) def test_auto_none(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.generate_full_auto_path(None) # test oz.ozutil.executable_exists @@ -37,33 +37,33 @@ def test_exe_exists_bin_ls(): assert(oz.ozutil.executable_exists('/bin/ls')) def test_exe_exists_foo(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.executable_exists('foo') def test_exe_exists_full_foo(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.executable_exists('/bin/foo') def test_exe_exists_not_x(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.executable_exists('/etc/hosts') def test_exe_exists_relative_false(): assert(oz.ozutil.executable_exists('false')) def test_exe_exists_none(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.executable_exists(None) # test oz.ozutil.copyfile_sparse def test_copy_sparse_none_src(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copyfile_sparse(None, None) def test_copy_sparse_none_dst(tmpdir): fullname = os.path.join(str(tmpdir), 'src') open(fullname, 'w').write('src') - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copyfile_sparse(fullname, None) def test_copy_sparse_bad_src_mode(tmpdir): @@ -75,7 +75,7 @@ def test_copy_sparse_bad_src_mode(tmpdir): os.chmod(fullname, 0000) # because copyfile_sparse uses os.open() instead of open(), it throws an # OSError - with py.test.raises(OSError): + with pytest.raises(OSError): oz.ozutil.copyfile_sparse(fullname, 'output') def test_copy_sparse_bad_dst_mode(tmpdir): @@ -87,7 +87,7 @@ def test_copy_sparse_bad_dst_mode(tmpdir): dstname = os.path.join(str(tmpdir), 'dst') open(dstname, 'w').write('dst') os.chmod(dstname, 0o444) - with py.test.raises(OSError): + with pytest.raises(OSError): oz.ozutil.copyfile_sparse(srcname, dstname) def test_copy_sparse_zero_size_src(tmpdir): @@ -151,7 +151,7 @@ def test_copy_sparse_src_not_exists(tmpdir): srcname = os.path.join(str(tmpdir), 'src') dstname = os.path.join(str(tmpdir), 'dst') open(dstname, 'w').write('dst') - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copyfile_sparse(srcname, dstname) def test_copy_sparse_dest_not_exists(tmpdir): @@ -164,13 +164,13 @@ def test_copy_sparse_dest_not_exists(tmpdir): def test_copy_sparse_src_is_dir(tmpdir): dstname = os.path.join(str(tmpdir), 'dst') open(dstname, 'w').write('dst') - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copyfile_sparse(tmpdir, dstname) def test_copy_sparse_dst_is_dir(tmpdir): srcname = os.path.join(str(tmpdir), 'src') open(srcname, 'w').write('src') - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copyfile_sparse(srcname, tmpdir) # test oz.ozutil.string_to_bool @@ -205,7 +205,7 @@ def test_stb_true(): assert(oz.ozutil.string_to_bool(curr) == True) def test_stb_none(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.string_to_bool(None) @@ -231,11 +231,11 @@ def test_mkdir_p_twice(tmpdir): def test_mkdir_p_file_exists(tmpdir): fullname = os.path.join(str(tmpdir), 'file_exists') open(fullname, 'w').write('file_exists') - with py.test.raises(OSError): + with pytest.raises(OSError): oz.ozutil.mkdir_p(fullname) def test_mkdir_p_none(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.mkdir_p(None) def test_mkdir_p_empty_string(): @@ -243,20 +243,20 @@ def test_mkdir_p_empty_string(): # test oz.ozutil.copy_modify_file def test_copy_modify_none_src(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copy_modify_file(None, None, None) def test_copy_modify_none_dst(tmpdir): fullname = os.path.join(str(tmpdir), 'src') open(fullname, 'w').write('src') - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copy_modify_file(fullname, None, None) def test_copy_modify_none_subfunc(tmpdir): src = os.path.join(str(tmpdir), 'src') open(src, 'w').write('src') dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.copy_modify_file(src, dst, None) def test_copy_modify_bad_src_mode(tmpdir): @@ -269,7 +269,7 @@ def sub(line): open(fullname, 'w').write('writeonly') os.chmod(fullname, 0000) dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(IOError): + with pytest.raises(IOError): oz.ozutil.copy_modify_file(fullname, dst, sub) def test_copy_modify_empty_file(tmpdir): @@ -295,11 +295,11 @@ def sub(line): # test oz.ozutil.write_cpio def test_write_cpio_none_input(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.write_cpio(None, None) def test_write_cpio_none_output(): - with py.test.raises(Exception): + with pytest.raises(Exception): oz.ozutil.write_cpio({}, None) def test_write_cpio_empty_dict(tmpdir): @@ -313,7 +313,7 @@ def test_write_cpio_existing_file(tmpdir): dst = os.path.join(str(tmpdir), 'dst') open(dst, 'w').write('hello') os.chmod(dst, 0000) - with py.test.raises(IOError): + with pytest.raises(IOError): oz.ozutil.write_cpio({}, dst) def test_write_cpio_single_file(tmpdir): @@ -344,7 +344,7 @@ def test_write_cpio_exception(tmpdir): open(src, 'w').write('src') os.chmod(src, 0000) dst = os.path.join(str(tmpdir), 'dst') - with py.test.raises(IOError): + with pytest.raises(IOError): oz.ozutil.write_cpio({src: 'src'}, dst) def test_md5sum_regular(tmpdir): diff --git a/tests/tdl/test_tdl.py b/tests/tdl/test_tdl.py index 6846ef10..a94b2c18 100644 --- a/tests/tdl/test_tdl.py +++ b/tests/tdl/test_tdl.py @@ -10,9 +10,9 @@ sys.exit(1) try: - import py.test + import pytest except ImportError: - print('Unable to import py.test. Is py.test installed?') + print('Unable to import pytest. Is pytest installed?') sys.exit(1) # Find oz From ccfcee509da595415582ca168c67e960d77795da Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 14:57:16 -0800 Subject: [PATCH 02/12] Unpick unnecessary 'useuefi' arg on the Guest classes b7728d5 added this new mandatory argument on the Guest class. But it doesn't use it at all. The only code in the commit that uses anything called 'useuefi' is the little bit added to _generate_xml() - but that checks self.config.useuefi, which is a property of the FedoraConfiguration config class, not anything to do with the Guest class itself. None of the __init__ methods on Guest or its subclasses that added this new 'useuefi' arg ever did anything with it. This broke every guest class which didn't have the useless new argument added to it, which seems to be most of the non-Fedora/ non-RHEL ones. They're probably broken in other ways anyway, but this didn't help. It makes a large swathe of the test suite fail. This dumps the useless arg from all Guest classes, and makes the check in _generate_xml() safe for config classes which do not have the useuefi property at all, which is all the non-Fedora ones. Signed-off-by: Adam Williamson --- oz/Fedora.py | 5 ++--- oz/Guest.py | 12 ++++++------ oz/Linux.py | 4 ++-- oz/RHEL_8.py | 4 ++-- oz/RHEL_9.py | 4 ++-- oz/RedHat.py | 12 ++++++------ 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/oz/Fedora.py b/oz/Fedora.py index 7ab800bc..89ecca8c 100644 --- a/oz/Fedora.py +++ b/oz/Fedora.py @@ -248,7 +248,7 @@ class FedoraGuest(oz.RedHat.RedHatLinuxCDYumGuest): # ignored now; we leave it in place for backwards API compatibility. def __init__(self, tdl, config, auto, nicmodel, haverepo, diskbus, # pylint: disable=unused-argument brokenisomethod, output_disk=None, macaddress=None, # pylint: disable=unused-argument - assumed_update=None, useuefi=False): + assumed_update=None): if int(tdl.update) < 31: self.config = version_to_config[tdl.update] else: @@ -263,8 +263,7 @@ def __init__(self, tdl, config, auto, nicmodel, haverepo, diskbus, # pylint: di oz.RedHat.RedHatLinuxCDYumGuest.__init__(self, tdl, config, auto, output_disk, nicmodel, diskbus, True, True, self.config.directkernel, - macaddress, self.config.use_yum, - self.config.useuefi) + macaddress, self.config.use_yum) if self.assumed_update is not None: self.log.warning("==== WARN: TDL contains Fedora update %s, which is newer than Oz knows about; pretending this is Fedora %s, but this may fail ====", tdl.update, assumed_update) diff --git a/oz/Guest.py b/oz/Guest.py index f1ca403e..249cce04 100644 --- a/oz/Guest.py +++ b/oz/Guest.py @@ -129,7 +129,7 @@ def _libvirt_error_handler(ctxt, err): self._discover_libvirt_type() def __init__(self, tdl, config, auto, output_disk, nicmodel, clockoffset, - mousetype, diskbus, iso_allowed, url_allowed, macaddress, useuefi): + mousetype, diskbus, iso_allowed, url_allowed, macaddress): self.tdl = tdl # for backwards compatibility @@ -502,7 +502,7 @@ def _generate_xml(self, bootdev, installdev, kernel=None, initrd=None, oz.ozutil.lxml_subelement(osNode, "loader", loader, {'readonly': 'yes', 'type': 'pflash'}) oz.ozutil.lxml_subelement(osNode, "nvram", None, {'template': nvram}) # x86_64 has legacy requirements so we check for defaults as well as for edk2 - if self.tdl.arch in ["x86_64"] and self.config.useuefi == True: + if self.tdl.arch == "x86_64" and hasattr(self.config, "useuefi") and self.config.useuefi is True: loader, nvram = oz.ozutil.find_uefi_firmware(self.tdl.arch) oz.ozutil.lxml_subelement(osNode, "loader", loader, {'readonly': 'yes', 'type': 'pflash'}) oz.ozutil.lxml_subelement(osNode, "nvram", None, {'template': nvram}) @@ -1333,10 +1333,10 @@ def __init__(self, version, sysid, volid, space_size, set_size, seqnum): self.seqnum = seqnum def __init__(self, tdl, config, auto, output_disk, nicmodel, clockoffset, - mousetype, diskbus, iso_allowed, url_allowed, macaddress, useuefi): + mousetype, diskbus, iso_allowed, url_allowed, macaddress): Guest.__init__(self, tdl, config, auto, output_disk, nicmodel, clockoffset, mousetype, diskbus, iso_allowed, - url_allowed, macaddress, useuefi) + url_allowed, macaddress) self.orig_iso = os.path.join(self.data_dir, "isos", self.tdl.distro + self.tdl.update + self.tdl.arch + "-" + self.tdl.installtype + ".iso") @@ -1801,9 +1801,9 @@ class FDGuest(Guest): Class for guest installation via floppy disk. """ def __init__(self, tdl, config, auto, output_disk, nicmodel, clockoffset, - mousetype, diskbus, macaddress, useuefi): + mousetype, diskbus, macaddress): Guest.__init__(self, tdl, config, auto, output_disk, nicmodel, - clockoffset, mousetype, diskbus, False, True, macaddress, useuefi) + clockoffset, mousetype, diskbus, False, True, macaddress) self.orig_floppy = os.path.join(self.data_dir, "floppies", self.tdl.distro + self.tdl.update + self.tdl.arch + ".img") self.modified_floppy_cache = os.path.join(self.data_dir, "floppies", diff --git a/oz/Linux.py b/oz/Linux.py index aee7abe2..f15260a9 100644 --- a/oz/Linux.py +++ b/oz/Linux.py @@ -33,10 +33,10 @@ class LinuxCDGuest(oz.Guest.CDGuest): Class for Linux installation. """ def __init__(self, tdl, config, auto, output_disk, nicmodel, diskbus, - iso_allowed, url_allowed, macaddress, useuefi): + iso_allowed, url_allowed, macaddress): oz.Guest.CDGuest.__init__(self, tdl, config, auto, output_disk, nicmodel, None, None, diskbus, iso_allowed, - url_allowed, macaddress, useuefi) + url_allowed, macaddress) def _test_ssh_connection(self, guestaddr): """ diff --git a/oz/RHEL_8.py b/oz/RHEL_8.py index 49a6cff4..575f50e9 100644 --- a/oz/RHEL_8.py +++ b/oz/RHEL_8.py @@ -31,12 +31,12 @@ class RHEL8Guest(oz.RedHat.RedHatLinuxCDYumGuest): Class for RHEL-8 installation """ def __init__(self, tdl, config, auto, output_disk=None, netdev=None, - diskbus=None, macaddress=None, useuefi=True): + diskbus=None, macaddress=None): # dnf distro oz.RedHat.RedHatLinuxCDYumGuest.__init__(self, tdl, config, auto, output_disk, netdev, diskbus, True, True, "cpio", macaddress, - False, useuefi) + False) self.virtio_channel_name = 'org.fedoraproject.anaconda.log.0' def _modify_iso(self): diff --git a/oz/RHEL_9.py b/oz/RHEL_9.py index 6a548b60..7a9c90b9 100644 --- a/oz/RHEL_9.py +++ b/oz/RHEL_9.py @@ -31,11 +31,11 @@ class RHEL9Guest(oz.RHEL_8.RHEL8Guest): Class for RHEL-9 installation """ def __init__(self, tdl, config, auto, output_disk=None, netdev=None, - diskbus=None, macaddress=None, useuefi=True): + diskbus=None, macaddress=None): # dnf distro oz.RHEL_8.RHEL8Guest.__init__(self, tdl, config, auto, output_disk, netdev, diskbus, - macaddress, useuefi) + macaddress) # method and ks options were dropped self.cmdline = "inst.repo=" + self.url + " inst.ks=file:/ks.cfg" diff --git a/oz/RedHat.py b/oz/RedHat.py index 57e43f43..e7c42ba7 100644 --- a/oz/RedHat.py +++ b/oz/RedHat.py @@ -40,10 +40,10 @@ class RedHatLinuxCDGuest(oz.Linux.LinuxCDGuest): Class for RedHat-based CD guests. """ def __init__(self, tdl, config, auto, output_disk, nicmodel, diskbus, - iso_allowed, url_allowed, initrdtype, macaddress, useuefi): + iso_allowed, url_allowed, initrdtype, macaddress): oz.Linux.LinuxCDGuest.__init__(self, tdl, config, auto, output_disk, nicmodel, diskbus, iso_allowed, - url_allowed, macaddress, useuefi) + url_allowed, macaddress) self.crond_was_active = False self.sshd_was_active = False self.sshd_config = """\ @@ -732,11 +732,11 @@ class RedHatLinuxCDYumGuest(RedHatLinuxCDGuest): Class for RedHat-based CD guests with yum support. """ def __init__(self, tdl, config, auto, output_disk, nicmodel, diskbus, - iso_allowed, url_allowed, initrdtype, macaddress, use_yum, useuefi): + iso_allowed, url_allowed, initrdtype, macaddress, use_yum): oz.RedHat.RedHatLinuxCDGuest.__init__(self, tdl, config, auto, output_disk, nicmodel, diskbus, iso_allowed, url_allowed, - initrdtype, macaddress, useuefi) + initrdtype, macaddress) self.use_yum = use_yum @@ -855,9 +855,9 @@ class RedHatFDGuest(oz.Guest.FDGuest): Class for RedHat-based floppy guests. """ def __init__(self, tdl, config, auto, output_disk, nicmodel, diskbus, - macaddress, useuefi): + macaddress): oz.Guest.FDGuest.__init__(self, tdl, config, auto, output_disk, - nicmodel, None, None, diskbus, macaddress, useuefi) + nicmodel, None, None, diskbus, macaddress) if self.tdl.arch != "i386": raise oz.OzException.OzException("Invalid arch " + self.tdl.arch + "for " + self.tdl.distro + " guest") From 743dfced8adffbb5103867cd44857bdcbb8eb2a8 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 15:10:02 -0800 Subject: [PATCH 03/12] Python compat: Callable is in collections.abc since Python 3.3 Signed-off-by: Adam Williamson --- oz/ozutil.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/oz/ozutil.py b/oz/ozutil.py index 5e90797d..689559f3 100644 --- a/oz/ozutil.py +++ b/oz/ozutil.py @@ -19,7 +19,10 @@ Miscellaneous utility functions. """ -import collections +try: + from collections.abc import Callable +except ImportError: + from collections import Callable try: import configparser except ImportError: @@ -536,7 +539,7 @@ def copy_modify_file(inname, outname, subfunc): raise Exception("output filename is None") if subfunc is None: raise Exception("subfunction is None") - if not isinstance(subfunc, collections.Callable): + if not isinstance(subfunc, Callable): raise Exception("subfunction is not callable") infile = open(inname, 'r') From 73b291eb61413348c07736208d44a7e0734a5dc5 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 15:20:53 -0800 Subject: [PATCH 04/12] Tests: multiple fixes to expected guest XML The test_xml_generation_1 and _2 tests failed because multiple changes were merged which change the generated libvirt guest XML without the test data being updated: f20a5f9b05a05e88a12cff05483649a550e95491 - bumped memory to 2G f73d7cff45504deb36b502d073157576528a6eb3 - added host-passthrough e8ae9de009d55d73e68f6d0030e88389825a242a - added rng 7ae8898e4a0264b8eb6ea7b89d3269bf16bc5dce - added discard=unmap Apparently not one of the authors or reviewers of any of those commits ever ran the test suite. Signed-off-by: Adam Williamson --- tests/guest/libvirt/test_xml_generation_1.xml | 11 ++++++++--- tests/guest/libvirt/test_xml_generation_2.xml | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/guest/libvirt/test_xml_generation_1.xml b/tests/guest/libvirt/test_xml_generation_1.xml index e976d856..a8ad4d8a 100644 --- a/tests/guest/libvirt/test_xml_generation_1.xml +++ b/tests/guest/libvirt/test_xml_generation_1.xml @@ -1,7 +1,7 @@ tester - 1048576 - 1048576 + 2097152 + 2097152 %s 1 @@ -10,6 +10,7 @@ + hvm @@ -33,10 +34,14 @@ + + + /dev/random + - + diff --git a/tests/guest/libvirt/test_xml_generation_2.xml b/tests/guest/libvirt/test_xml_generation_2.xml index 148c113c..cf6feb40 100644 --- a/tests/guest/libvirt/test_xml_generation_2.xml +++ b/tests/guest/libvirt/test_xml_generation_2.xml @@ -1,7 +1,7 @@ tester - 1048576 - 1048576 + 2097152 + 2097152 %s 1 @@ -10,6 +10,7 @@ + hvm @@ -36,10 +37,14 @@ + + + /dev/random + - + From 3b96485ed42b2e3c048bbb2b05640343e61d50de Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 16:05:24 -0800 Subject: [PATCH 05/12] Add testing instructions to README Signed-off-by: Adam Williamson --- README | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README b/README index ffcea09e..9c78c594 100644 --- a/README +++ b/README @@ -4,7 +4,22 @@ images containing an operating systems and, optionally, programs. The best way to install it is to make an RPM out of it by running "make rpm" or "make srpm", and then installing the resulting RPM on the target machine. +This will probably only work on Fedora or on RHEL 8 or later. Once you have the RPM installed, you will need to build up TDL files to feed as input into the building process. Please see the examples directory to get an idea of what a TDL file looks like. + +Running the tests is also most easily done from a Fedora host. oz uses the +guestfs Python module, which is not available from pypi, and needs a running +libvirtd for most of the tests to run. Install all the test requirements: + +dnf install python3-requests python3-m2crypto python3-libvirt python3-lxml python3-libguestfs python3-pytest python3-monotonic + +If you wish to test on EL 7, make that: + +yum install python-requests m2crypto libvirt-python python-lxml python-libguestfs pytest python-monotonic + +then run the tests: + +py.test tests/ From 523eb1338e6c2474bd57061e61e5d53056772292 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 16:05:40 -0800 Subject: [PATCH 06/12] Add monotonic to requirements We started using this back in 2017, but it was never added to requirements.txt. Signed-off-by: Adam Williamson --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 2f5b4d61..c0a8d464 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ requests m2crypto libvirt-python lxml +monotonic From 7cf900a047f0e84d9fb01b0bcd756ecbe5925e21 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 16:06:04 -0800 Subject: [PATCH 07/12] Update oz.spec.in to match current Fedora This won't work for EL 7, but should work for anything newer than that. The current version doesn't work at all. Signed-off-by: Adam Williamson --- oz.spec.in | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/oz.spec.in b/oz.spec.in index 37716b13..b83ccf1a 100644 --- a/oz.spec.in +++ b/oz.spec.in @@ -1,45 +1,41 @@ -Summary: Library and utilities for automated guest OS installs -Name: oz +Name: oz Version: @VERSION@ Release: @RELEASE@%{?dist} +Summary: Library and utilities for automated guest OS installs License: LGPLv2 -Group: Development/Libraries -URL: http://github.com/clalancette/oz -Source0: http://github.com/clalancette/%{name}/archive/%{name}-%{version}.tar.gz +URL: http://github.com/clalancette/oz + +Source0: https://github.com/clalancette/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz + BuildArch: noarch + +BuildRequires: python3 +BuildRequires: python3-devel +BuildRequires: python3-setuptools Requires: python3 -Requires: python3-libguestfs >= 1.18 Requires: python3-lxml +Requires: python3-libguestfs >= 1.18 Requires: python3-libvirt +Requires: python3-m2crypto +Requires: python3-monotonic +Requires: python3-requests # in theory, oz doesn't really require libvirtd to be local to operate # properly. However, because of the libguestfs manipulations, in practice # it really does. Make it depend on libvirt (so we get libvirtd) for now, # unless/until we are able to make it really be remote. -%if 0%{?fedora} >= 17 Requires: libvirt-daemon-kvm Requires: libvirt-daemon-qemu Requires: libvirt-daemon-config-network -%else -Requires: libvirt >= 0.9.7 -%endif -Requires: python3-requests Requires: genisoimage Requires: mtools -%if 0%{?fedora} < 26 or 0%{?rhel} < 8 -Requires: python-uuid -%endif Requires: openssh-clients -Requires: python3-m2crypto -Requires: python3-monotonic - -BuildRequires: python3 %description Oz is a set of libraries and utilities for doing automated guest OS installations, with minimal input from the user. %prep -%setup -q +%autosetup -p1 %build %py3_build @@ -66,7 +62,8 @@ if [ ! -f %{_sysconfdir}/oz/id_rsa-icicle-gen ]; then fi %files -%doc README COPYING examples +%license COPYING +%doc README examples %dir %attr(0755, root, root) %{_sysconfdir}/oz/ %config(noreplace) %{_sysconfdir}/oz/oz.cfg %dir %attr(0755, root, root) %{_localstatedir}/lib/oz/ @@ -78,13 +75,13 @@ fi %dir %attr(0755, root, root) %{_localstatedir}/lib/oz/jeos/ %dir %attr(0755, root, root) %{_localstatedir}/lib/oz/kernels/ %dir %attr(0755, root, root) %{_localstatedir}/lib/oz/screenshots/ -%{python3_sitelib}/oz %{_bindir}/oz-install %{_bindir}/oz-generate-icicle %{_bindir}/oz-customize %{_bindir}/oz-cleanup-cache -%{python3_sitelib}/%{name}-%{version}-py%{python3_version}.egg-info %{_mandir}/man1/* +%{python3_sitelib}/oz +%{python3_sitelib}/%{name}*.egg-info %changelog * Sat Feb 5 2022 Peter Robinson - 0.18.0-1 From cf60791c8fc759f0f1c325db008c86aef25d4842 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 16:58:45 -0800 Subject: [PATCH 08/12] tests: handle libvirt_type not being kvm This seems necessary for testing in a container. I've mostly got the tests passing in a rootless container, but libvirt_type is qemu not kvm, and I doubt it's easy to get it to come out as kvm. It's easier to just make the tests handle it being qemu. Signed-off-by: Adam Williamson --- tests/guest/libvirt/test_xml_generation_1.xml | 2 +- tests/guest/libvirt/test_xml_generation_2.xml | 2 +- tests/guest/test_guest.py | 10 ++++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/guest/libvirt/test_xml_generation_1.xml b/tests/guest/libvirt/test_xml_generation_1.xml index a8ad4d8a..1a64f61a 100644 --- a/tests/guest/libvirt/test_xml_generation_1.xml +++ b/tests/guest/libvirt/test_xml_generation_1.xml @@ -1,4 +1,4 @@ - + tester 2097152 2097152 diff --git a/tests/guest/libvirt/test_xml_generation_2.xml b/tests/guest/libvirt/test_xml_generation_2.xml index cf6feb40..e46e5819 100644 --- a/tests/guest/libvirt/test_xml_generation_2.xml +++ b/tests/guest/libvirt/test_xml_generation_2.xml @@ -1,4 +1,4 @@ - + tester 2097152 2097152 diff --git a/tests/guest/test_guest.py b/tests/guest/test_guest.py index 19b08638..a9383f25 100644 --- a/tests/guest/test_guest.py +++ b/tests/guest/test_guest.py @@ -456,7 +456,10 @@ def test_xml_generation_1(): test_xml = handle.read() # Replace various smaller items as they are auto generated - test_xml = test_xml % (guest.uuid, route, guest.listen_port, guest.diskimage) + test_xml = test_xml % (guest.libvirt_type, guest.uuid, route, guest.listen_port, guest.diskimage) + # drop host-passthrough line if libvirt_type is not kvm + if guest.libvirt_type != "kvm": + test_xml = "\n".join((line for line in test_xml.splitlines() if "host-passthrough" not in line)) + "\n" bootdev = 'hd' installdev = None @@ -472,7 +475,10 @@ def test_xml_generation_2(): test_xml = handle.read() # Replace various smaller items as they are auto generated - test_xml = test_xml % (guest.uuid, route, guest.listen_port, guest.diskimage) + test_xml = test_xml % (guest.libvirt_type, guest.uuid, route, guest.listen_port, guest.diskimage) + # drop host-passthrough line if libvirt_type is not kvm + if guest.libvirt_type != "kvm": + test_xml = "\n".join((line for line in test_xml.splitlines() if "host-passthrough" not in line)) + "\n" bootdev = 'hd' installdev = guest._InstallDev('blue', '/var/bin/foo', 'muni') From fb26ca961e48ec4bbfa9377073b97c543e90c134 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 23 Jan 2024 17:26:08 -0800 Subject: [PATCH 09/12] tests: handle guest image path being the system one This seems to happen when testing in a container as root. Signed-off-by: Adam Williamson --- tests/guest/test_guest.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/guest/test_guest.py b/tests/guest/test_guest.py index a9383f25..625eb678 100644 --- a/tests/guest/test_guest.py +++ b/tests/guest/test_guest.py @@ -354,7 +354,12 @@ def test_init_guest(): assert guest.disksize == 20 assert guest.image_name() == 'tester' - assert guest.output_image_path() == '%s/.oz/images/tester.dsk' % os.getenv('HOME') + assert guest.output_image_path() in ( + # user's image storage + '%s/.oz/images/tester.dsk' % os.getenv('HOME'), + # system image storage (when testing as root, I think) + '/var/lib/libvirt/images/tester.dsk' + ) assert guest.default_auto_file() == True def test_init_guest_bad_arch(): From 6d2efbcf33e1b6ba64df496b09e4d5820b0320d7 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Wed, 24 Jan 2024 19:07:52 -0800 Subject: [PATCH 10/12] Update pylint and flake8 commands in Makefile These -3 versions haven't existed for years, AFAICT. Signed-off-by: Adam Williamson --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fa813130..c8d94dd0 100644 --- a/Makefile +++ b/Makefile @@ -52,10 +52,10 @@ test-coverage: xdg-open htmlcov/index.html pylint: - pylint-3 --rcfile=pylint.conf oz oz-install oz-customize oz-cleanup-cache oz-generate-icicle + pylint --rcfile=pylint.conf oz oz-install oz-customize oz-cleanup-cache oz-generate-icicle flake8: - flake8-3 --ignore=E501 oz + flake8 --ignore=E501 oz clean: rm -rf MANIFEST build dist usr *~ oz.spec *.pyc oz/*~ oz/*.pyc examples/*~ oz/auto/*~ man/*~ docs/*~ man/*.html $(VENV_DIR) tests/tdl/*~ tests/factory/*~ tests/results.xml htmlcov From 2eb842a0b42c1ce5214a9ffd5005391762386161 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Wed, 24 Jan 2024 17:25:41 -0800 Subject: [PATCH 11/12] Add ability to run the unit tests in Fedora and EL7 containers This adds a convenient way to run the unit tests in containers - a "latest Fedora" container to check things work with the latest shiny bits, and an EL 7 (CentOS 7 plus EPEL) container to check things work with antique bits. This should make it possible to conveniently set up CI with a github action. It also should make it easy to run the tests on non-Fedora/RHEL-ish platforms. `make container-unittests` will build both containers and run the tests. `make container-clean` cleans up the containers and images. Signed-off-by: Adam Williamson --- Containerfile.tests.el7 | 16 ++++++++++++++++ Containerfile.tests.fedora | 14 ++++++++++++++ Makefile | 19 ++++++++++++++++++- README | 22 ++++++++++++++++++++-- 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 Containerfile.tests.el7 create mode 100644 Containerfile.tests.fedora diff --git a/Containerfile.tests.el7 b/Containerfile.tests.el7 new file mode 100644 index 00000000..06a9b789 --- /dev/null +++ b/Containerfile.tests.el7 @@ -0,0 +1,16 @@ +# this container definition is intended *only* for running the oz test suite, it is not +# a general-purpose oz container definition! + +FROM quay.io/centos/centos:7 +RUN set -exo pipefail \ + && yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ + && yum install -y python-requests m2crypto libvirt-python python-lxml python-libguestfs pytest python-monotonic libvirt \ + && yum clean all \ + && rm -rf /var/cache/* /var/log/yum* + +COPY ./ /oz +# the XML generation tests are inherently unreliable before Python 3.8, +# as there was no consistent ordering of XML element attributes. See +# https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.tostring +RUN printf "#!/bin/sh\n/usr/sbin/libvirtd -d\ncd /oz\npy.test -vv -k 'not test_xml_generation and not modify_libvirt_xml_for_serial' tests/" > /usr/local/bin/runtests.sh && chmod ugo+x /usr/local/bin/runtests.sh +CMD /usr/local/bin/runtests.sh diff --git a/Containerfile.tests.fedora b/Containerfile.tests.fedora new file mode 100644 index 00000000..7dd3e414 --- /dev/null +++ b/Containerfile.tests.fedora @@ -0,0 +1,14 @@ +# this container definition is intended *only* for running the oz test suite, it is not +# a general-purpose oz container definition! + +FROM quay.io/fedora/fedora:latest +RUN set -exo pipefail \ + && dnf install -y --setopt install_weak_deps=false --nodocs \ + python3-requests python3-m2crypto python3-setuptools python3-libvirt python3-lxml python3-libguestfs python3-pytest python3-monotonic \ + libvirt-daemon libvirt-daemon-kvm libvirt-daemon-qemu libvirt-daemon-config-network systemd \ + && dnf clean all \ + && rm -rf /var/cache/* /var/log/dnf* + +COPY ./ /oz +RUN printf "#!/bin/sh\n/usr/sbin/libvirtd -d\ncd /oz\npy.test -vv tests/" > /usr/local/bin/runtests.sh && chmod ugo+x /usr/local/bin/runtests.sh +CMD /usr/local/bin/runtests.sh diff --git a/Makefile b/Makefile index c8d94dd0..74d3d998 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,18 @@ unittests: tests: unittests +container-unittests-fedora: + docker rm -f oz-tests-fedora + docker build -f Containerfile.tests.fedora -t oz-tests-fedora-image . + docker run --name oz-tests-fedora oz-tests-fedora-image + +container-unittests-el7: + docker rm -f oz-tests-el7 + docker build -f Containerfile.tests.el7 -t oz-tests-el7-image . + docker run --name oz-tests-el7 oz-tests-el7-image + +container-unittests: container-unittests-fedora container-unittests-el7 + test-coverage: python-coverage run --source oz /usr/bin/py.test --verbose tests python-coverage html @@ -57,7 +69,12 @@ pylint: flake8: flake8 --ignore=E501 oz +container-clean: + docker rm -f oz-tests-fedora + docker rm -f oz-tests-el7 + docker image rm -f -i oz-tests-fedora-image oz-tests-el7-image + clean: rm -rf MANIFEST build dist usr *~ oz.spec *.pyc oz/*~ oz/*.pyc examples/*~ oz/auto/*~ man/*~ docs/*~ man/*.html $(VENV_DIR) tests/tdl/*~ tests/factory/*~ tests/results.xml htmlcov -.PHONY: sdist oz.spec signed-tarball signed-rpm rpm srpm deb release man2html virtualenv unittests tests test-coverage pylint clean +.PHONY: sdist oz.spec signed-tarball signed-rpm rpm srpm deb release man2html virtualenv unittests container-unittests-fedora container-unittests-el7 container-unittests tests test-coverage pylint clean container-clean diff --git a/README b/README index 9c78c594..5f2c983c 100644 --- a/README +++ b/README @@ -10,9 +10,19 @@ Once you have the RPM installed, you will need to build up TDL files to feed as input into the building process. Please see the examples directory to get an idea of what a TDL file looks like. -Running the tests is also most easily done from a Fedora host. oz uses the +You can run the oz unit tests in containers by installing make and docker +(or podman-docker), then running: + +make container-unittests + +You can clean up the containers and images by running: + +make container-clean + +Otherwise, you can try running the tests directly on your host, but oz uses the guestfs Python module, which is not available from pypi, and needs a running -libvirtd for most of the tests to run. Install all the test requirements: +libvirtd for most of the tests to run. To install all the test requirements on +Fedora: dnf install python3-requests python3-m2crypto python3-libvirt python3-lxml python3-libguestfs python3-pytest python3-monotonic @@ -23,3 +33,11 @@ yum install python-requests m2crypto libvirt-python python-lxml python-libguestf then run the tests: py.test tests/ + +You can try `make virtualenv` then `make unittests` to run the tests in a +virtualenv if you like, but this still requires at least the libguestfs library +installed on the host, and a running libvirtd. You may also want to install +m2crypto and libvirt libraries on the host, as otherwise pip will have to +compile them, and you'll need their build dependencies. + +You can use `make pylint` and `make flake8` to run lint checks. From c59c3417db54c26aac092b1463f130f7540aa33a Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Wed, 24 Jan 2024 17:49:12 -0800 Subject: [PATCH 12/12] Add a Github Action workflow to run CI checks I can't really test this, but I think it ought to work. This should run the container unit tests, pylint, and flake8 checks on each pull request. This also removes .travis.yml, as we clearly haven't used travis for about a decade at this point. Signed-off-by: Adam Williamson --- .github/workflows/ci.yml | 41 ++++++++++++++++++++++++++++++++++++++++ .travis.yml | 33 -------------------------------- 2 files changed, 41 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..4fcd2125 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,41 @@ +--- +name: Run CI checks + +on: [pull_request] + +jobs: + unittests-fedora: + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install make and docker + run: apt-get install make docker docker.io + - name: Run the tests + run: make container-unittests-fedora + unittests-el7: + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install make and docker + run: apt-get install make docker + - name: Run the tests + run: make container-unittests-el7 + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install make, pylint and flake8 + run: apt-get install make pylint flake8 + - name: Run pylint + run: make pylint + - name: Run flake8 + run: make flake8 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2a2b8d69..00000000 --- a/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: python - -python: -# - "3.3" -# - "3.2" - - "2.7" - -before_install: - - sudo add-apt-repository -y ppa:pdffs/precise-virt - - sudo apt-get update - - sudo apt-get install -qq genisoimage libvirt-dev mtools openssh-client python-dev python-guestfs swig libssl1.0.0 python-m2crypto python-libvirt - -# Travis uses an isolated virtualenv (see http://about.travis-ci.org/docs/user/languages/python/#Travis-CI-Uses-Isolated-virtualenvs) -# Install the system python packages to get their deps and then install the pip version to have them locally -install: - - pip install -r requirements.txt - - sudo cp /usr/lib/python2.7/dist-packages/*guestfs* $VIRTUAL_ENV/lib/python$TRAVIS_PYTHON_VERSION/site-packages/ - - python setup.py install - - pip install coverage - - pip install coveralls - - py.test --genscript=runtests.py - -env: - - TESTFOLDER=tdl - - TESTFOLDER=guest - - TESTFOLDER=ozutil - - TESTFOLDER=factory - -script: - - coverage run -p --source=oz runtests.py --verbose --tb=short tests/$TESTFOLDER - -after_success: - - coveralls