Skip to content

Commit

Permalink
PCIe, Slots in pcie-root numbered [1,31]
Browse files Browse the repository at this point in the history
This commit adds automation of tests where pcie-root-port controllers
should have target with slot numbered from 1 to 31 (in hexadecimal
numbers).

VIRT-55414
  • Loading branch information
Vaclav Hodina committed Feb 27, 2023
1 parent b5e5210 commit 63cf311
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 24 deletions.
27 changes: 24 additions & 3 deletions libvirt/tests/cfg/controller/pcie_root_port_controller.cfg
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
- pcie_root_port_controller:
type = pcie_root_port_controller
start_vm = "no"
controller_type = "pci"
controller_model = "pcie-root-port"
controller_target = '{"chassis":1,"port":"0x8"}'
slot_equal_after_define = "yes"
variants:
- positive_test:
status_error = "no"
variants:
- controllers_different_chassis_same_port:
second_controller_model = "pcie-root-port"
second_controller_target = "{'chassis':2,'port':'0x8'}"
index_offset = 2
- address_slot_too_low:
check_slot = "yes"
wipe_devices = "yes"
test_define_only = "yes"
controller_address = '{"type": "pci", "domain": "0x0000", "bus": "0x00", "slot": "0x00", "function":"0x0"}'
slot_equal_after_define = "no"
- address_slot_min_value:
check_slot = "yes"
wipe_devices = "yes"
test_define_only = "yes"
controller_address = '{"type": "pci", "domain": "0x0000", "bus": "0x00", "slot": "0x03", "function":"0x0"}'
- negative_test:
status_error = "yes"
variants:
Expand All @@ -22,25 +36,27 @@
test_define_only = "yes"
interface_slot_type = "hex"
interface_slot = 1
minimal_interface_dict = '{"source": {"network": "default"}}'
minimal_interface_dict = '{"source": {"network": "default"}, "model": "virtio"}'
failure_message = "Invalid PCI address .* slot must be <= 0"
- controllers_same_chassis_same_port:
second_controller_model = "pcie-root-port"
second_controller_target = "{'chassis':1,'port':'0x8'}"
index_offset = 2
- controllers_same_chassis_different_port:
second_controller_model = "pcie-root-port"
second_controller_target = "{'chassis':1,'port':'0x4'}"
index_offset = 2
- model_name_invalid:
test_define_only = "yes"
controller_model = "dmi-to-pci-bridge"
- index_equals_address_bus:
test_define_only = "yes"
controller_address = '{"type": "pci", "domain": "0x0000", "bus": "0x01", "slot": "0x1", "function":"0x0"}'
controller_address = '{"type": "pci", "domain": "0x0000", "slot": "0x1", "function":"0x0"}'
failure_message = ".*The device at PCI address .* cannot be plugged into the PCI controller with index='.*'. It requires a controller that accepts a pcie\-root\-port.*"
- index_less_than_address_bus:
bus_offset = 1
test_define_only = "yes"
controller_address = '{"type": "pci", "domain": "0x0000", "bus": "0x02", "slot": "0x1", "function":"0x0"}'
controller_address = '{"type": "pci", "domain": "0x0000", "slot": "0x1", "function":"0x0"}'
failure_message = ".*a PCI slot is needed to connect a PCI controller model='pcie\-root\-port', but none is available, and it cannot be automatically added.*"
- controller_index_zero:
test_define_only = "yes"
Expand Down Expand Up @@ -68,3 +84,8 @@
test_define_only = "yes"
controller_target = '{"chassis":"a","port":"0x8"}'
failure_message = "XML error: Invalid value for attribute 'chassis' in element 'target': 'a'. Expected integer value"
- address_slot_too_high:
wipe_devices = "yes"
test_define_only = "yes"
controller_address = '{"type": "pci", "domain": "0x0000", "bus": "0x02", "slot": "0x20", "function":"0x0"}'
failure_message = "Invalid PCI address slot='0x20', must be <= 0x1F"
102 changes: 81 additions & 21 deletions libvirt/tests/src/controller/pcie_root_port_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,29 @@ def setup_test(params):
:param params: Test parameters object
"""
controller_type = params.get("controller_type")
controller_model = params.get("controller_model")
controller_target = ast.literal_eval(params.get("controller_target"))
controller_index = params.get("controller_index", 0)
second_controller_model = params.get("second_controller_model")
second_controller_target = ast.literal_eval(
params.get("second_controller_target", "{}"))
index_offset = params.get("index_offset", 2)
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(params.get("main_vm", "avocado-vt-vm1"))
test_define_only = params.get("test_define_only") == "yes"

vmxml.remove_all_device_by_type("controller")

index = 0
contr_dict = {"type": "pci", "model": "pcie-root", "index": index}
libvirt_vmxml.modify_vm_device(vmxml, "controller", contr_dict, index)
wipe_pcie_root_ports(vmxml)

if test_define_only:
return

index += 1
contr_dict = create_controller_dict(controller_model, controller_target, index)
index = 1
contr_dict = create_controller_dict(controller_type, controller_model,
controller_target, index)
libvirt_vmxml.modify_vm_device(vmxml, "controller", contr_dict, index)

if second_controller_model and second_controller_target:
index += 1
contr_dict = create_controller_dict(second_controller_model,
index += index_offset
contr_dict = create_controller_dict(controller_type, second_controller_model,
second_controller_target, index)
libvirt_vmxml.modify_vm_device(vmxml, "controller", contr_dict, index)

Expand All @@ -59,12 +57,12 @@ def execute_test(vm, test, params):
test_define_only = params.get("test_define_only") == "yes"
if test_define_only:
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm.name)
check_define_vm(vmxml, params)
check_define_vm(vmxml, test, params)
else:
check_vm_start(vm, params)


def create_controller_dict(model, target, index, address=None):
def create_controller_dict(controller_type, model, target, index, address=None):
"""
Creates a dictionary for PCI controller.
Expand All @@ -74,26 +72,30 @@ def create_controller_dict(model, target, index, address=None):
:param address: Dict, optional, device address example: {'attrs': {'bus': 0x01}}
:returns Built in dictionary, prepared to be added to VM XML
"""
contr_dict = {'type': 'pci',
'model': model,
"index": index,
'target': target}
contr_dict = {'type': controller_type,
"index": index}
if target:
contr_dict.update({"target": target})
if model:
contr_dict.update({"model": model})
if address:
contr_dict.update({"address": address})
LOG.debug("Created controller %s", contr_dict)
return contr_dict


def check_define_vm(vmxml, params):
def check_define_vm(vmxml, test, params):
"""
Alternate function for checking and finishing the test.
Checks only if VM define action was successful instead of VM start.
:param vmxml: VM XML object
:param test: Avocado test object
:param params: Test parameters object
"""
LOG.info("Checking VM in define only mode.")
model = params.get("controller_model")
controller_type = params.get("controller_type")
target = params.get("controller_target")
address = ast.literal_eval(params.get("controller_address", "{}"))
bus_offset = int(params.get("bus_offset", 0))
Expand All @@ -102,19 +104,28 @@ def check_define_vm(vmxml, params):
minimal_interface_dict = ast.literal_eval(params.get("minimal_interface_dict", "{}"))
interface_slot = params.get("interface_slot", 0)
interface_slot_type = params.get("interface_slot_type", "int")
check_slot = params.get("check_slot", "no") == "yes"
wipe_devices = params.get("wipe_devices", "no") == "yes"
if wipe_devices:
wipe_pcie_root_ports(vmxml)
if interface_slot_type == "hex":
interface_slot = hex(int(interface_slot))
index = get_controller_index(vmxml, params)
if address:
if address and "bus" not in address:
address["bus"] = hex(index + bus_offset)
contr_dict = {'controller_type': 'pci',
'controller_model': model,
slot_equal_after_define = params.get("slot_equal_after_define", "yes") == "yes"
contr_dict = {'controller_type': controller_type,
"controller_index": index,
'controller_target': target,
"controller_addr": str(address)}
if model:
contr_dict.update({"controller_model": model})
contr_object = libvirt.create_controller_xml(contr_dict)
if index == 0:
contr_object.index = 0 # Workaround for non-working avocado-vt
vmxml.add_device(contr_object)
if minimal_interface_dict:
index += 1
interface_dict = customize_interface_dict(minimal_interface_dict,
interface_bus=hex(index),
interface_slot=interface_slot)
Expand All @@ -125,14 +136,50 @@ def check_define_vm(vmxml, params):
libvirt.check_result(cmd_result, [failure_message])
else:
libvirt.check_exit_status(cmd_result, status_error)
if check_slot:
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(
params.get("main_vm", "avocado-vt-vm1"))
expected_value = address["slot"]
if not check_slot_in_controller(vmxml, index, expected_value,
slot_equal_after_define):
test.fail("Controller slot doesn't have the"
"expected value of %s.", expected_value)


def check_slot_in_controller(vmxml, device_index, expected_value, expected_equal=True):
"""
This function checks if address_slot value in a controller in VM XML equals
expected value or not.
:param vmxml: VM XML object to check
:param device_index: Int, device index to check
:param expected_value: The value that is used in the check
:param expected_equal: Bool, true if expected_value should be equal to
value in xml
:returns Bool, based on the value comparison
"""
controllers = vmxml.get_devices("controller")
device = controllers[device_index]
if expected_equal:
return device.address.attrs["slot"] == expected_value
return device.address.attrs["slot"] != expected_value


def get_controller_index(vmxml, params):
"""
Function that finds index for a PCIe controller and returns it
:param vmxml: VM XML object to check
:param params: Test parameters object
:returns Index number
"""
# We want to default to None so we can differentiate between None and 0
controller_index = params.get("controller_index", None)
model = params.get("controller_model")
if controller_index is not None:
if controller_index == "xxx":
return controller_index
if controller_index is not None:
return int(controller_index)
max_indexes = libvirt_pcicontr.get_max_contr_indexes(vmxml, 'pci', model, 1)
if max_indexes:
return max_indexes[0] + 1
Expand Down Expand Up @@ -190,6 +237,19 @@ def check_vm_start(vm, params, **virsh_options):
libvirt.check_exit_status(cmd_result, status_error)


def wipe_pcie_root_ports(vmxml):
"""
Function that removes all pcie-root-port devices from VM XML
:param vmxml: VM XML object to check
"""

vmxml.remove_all_device_by_type("controller")
index = 0
contr_dict = {"type": "pci", "model": "pcie-root", "index": index}
libvirt_vmxml.modify_vm_device(vmxml, "controller", contr_dict, index)


def run(test, params, env):
"""
Function executed by avocado. Similar to "main" function of a module.
Expand Down

0 comments on commit 63cf311

Please sign in to comment.