From 38a0f6ecfac0d20d6a1e822dc1de815b056c8f77 Mon Sep 17 00:00:00 2001 From: Yingshun Cui Date: Tue, 29 Aug 2023 17:45:01 +0800 Subject: [PATCH] guest_os_booting: Add a case about boot order of cdrom device This PR adds: VIRT-297201: Boot vm from cdrom device Signed-off-by: Yingshun Cui --- .../boot_order/boot_from_cdrom_device.cfg | 32 +++++ .../boot_order/boot_from_cdrom_device.py | 114 ++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg create mode 100644 libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py diff --git a/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg new file mode 100644 index 0000000000..25a8596ac6 --- /dev/null +++ b/libvirt/tests/cfg/guest_os_booting/boot_order/boot_from_cdrom_device.cfg @@ -0,0 +1,32 @@ +- guest_os_booting.boot_order.cdrom_device: + type = boot_from_cdrom_device + start_vm = no + disk1_attrs_target = {'dev': 'vda', 'bus': 'virtio'} + cdrom_attrs = "{'type_name': 'file', 'device': 'cdrom', 'driver': {'name': 'qemu', 'type': 'raw', 'cache': 'none'}, 'readonly': True}" + bootable_patterns = ["begin the installation process|Install Red Hat Enterprise"] + variants: + - without_cdrom: + only os_dev + - with_cdrom_with_no_src: + cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'sata'}, **${cdrom_attrs}} + - with_cdrom: + check_bootable_iso = "yes" + cdrom1_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} + - multi_cdroms: + cdrom1_attrs = {'target': {'dev': 'sda', 'bus': 'scsi'}, **${cdrom_attrs}} + cdrom2_attrs = {'source': {'attrs': {'file': boot_img_path}}, 'target': {'dev': 'sdb', 'bus': 'sata'}, **${cdrom_attrs}} + cdrom_boot_order: + check_bootable_iso = "yes" + os_dev: + status_error = "yes" + variants: + - os_dev: + os_attrs_boots = ['cdrom'] + - cdrom_boot_order: + variants firmware_type: + - seabios: + only x86_64 + with_cdrom_with_no_src: + status_error = "yes" + - ovmf: + only q35 diff --git a/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py new file mode 100644 index 0000000000..3ae748bcb5 --- /dev/null +++ b/libvirt/tests/src/guest_os_booting/boot_order/boot_from_cdrom_device.py @@ -0,0 +1,114 @@ +import os + +from avocado.utils import download +from avocado.utils import process + +from virttest import data_dir +from virttest import remote +from virttest.libvirt_xml import vm_xml +from virttest.libvirt_xml.devices import disk + +from provider.guest_os_booting import guest_os_booting_base + + +def parse_cdroms_attrs(params): + """ + Parse cdrom devices' attrs + + :param params: Dictionary with the test parameters + :return: (boot image path, list of cdrom devices' attrs) + """ + + boot_img_path = os.path.join(data_dir.get_data_dir(), 'images', 'boot.iso') + cdrom1_attrs = eval(params.get('cdrom1_attrs', '{}')) + cdrom2_attrs = eval(params.get('cdrom2_attrs', '{}')) + cdrom_attrs_list = [] + if cdrom1_attrs: + cdrom_attrs_list.append(cdrom1_attrs) + if cdrom2_attrs: + cdrom_attrs_list.append(cdrom2_attrs) + + if cdrom1_attrs.get('source') or cdrom2_attrs.get('source'): + cmd = "dnf repolist -v enabled |awk '/Repo-baseurl.*composes.*BaseOS.*os/ {print $NF}'" + repo_url = process.run(cmd, shell=True).stdout_text.strip() + boot_img_url = os.path.join(repo_url, 'images', 'boot.iso') + if os.path.exists(boot_img_path): + os.remove(boot_img_path) + download.get_file(boot_img_url, boot_img_path) + return boot_img_path, cdrom_attrs_list + + +def update_vm_xml(vm, params, cdrom_attrs_list): + """ + Update VM xml + + :param vm: VM object + :param params: Dictionary with the test parameters + :param cdrom_attrs_list: List of cdrom devices' attrs + """ + os_attrs_boots = eval(params.get('os_attrs_boots', '[]')) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + os_attrs = {} + if os_attrs_boots: + os_attrs = {'boots': os_attrs_boots} + vmxml.setup_attrs(os=os_attrs) + else: + vm_os = vmxml.os + vm_os.del_boots() + vmxml.os = vm_os + if "yes" == params.get("check_bootable_iso", "no"): + os_attrs.update({'bios_useserial': 'yes', + 'bootmenu_enable': 'yes', + 'bootmenu_timeout': '3000'}) + vmxml.setup_attrs(os=os_attrs) + + index = 0 + for cdrom_attrs in cdrom_attrs_list: + disk_obj = disk.Disk(cdrom_attrs) + disk_obj.setup_attrs(**cdrom_attrs) + vmxml.add_device(disk_obj) + index += 1 + if 'cdrom_boot_order' in params.get("shortname"): + vmxml.set_boot_order_by_target_dev( + cdrom_attrs['target']['dev'], index) + vmxml.xmltreefile.write() + vmxml.sync() + + +def run(test, params, env): + """ + Boot VM from cdrom devices + This case covers per-device(cdrom) boot elements and os/boot elements. + """ + vm_name = guest_os_booting_base.get_vm(params) + status_error = "yes" == params.get("status_error", "no") + check_bootable_iso = "yes" == params.get("check_bootable_iso", "no") + bootable_patterns = eval(params.get('bootable_patterns', '[]')) + + vm = env.get_vm(vm_name) + vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name) + bkxml = vmxml.copy() + boot_img_path = None + + try: + boot_img_path, cdrom_attrs_list = parse_cdroms_attrs(params) + update_vm_xml(vm, params, cdrom_attrs_list) + test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name)) + + vm.start() + if check_bootable_iso: + vm.serial_console.read_until_output_matches( + bootable_patterns, timeout=60, internal_timeout=0.5) + else: + try: + vm.wait_for_serial_login().close() + except remote.LoginTimeoutError as detail: + if status_error: + test.log.debug("Found the expected error: %s", detail) + else: + test.fail(detail) + finally: + bkxml.sync() + if boot_img_path and os.path.isfile(boot_img_path): + test.log.debug(f"removing {boot_img_path}") + os.remove(boot_img_path)