Merge "Add initial vdpa smoke test"

This commit is contained in:
Zuul 2023-04-03 19:32:42 +00:00 committed by Gerrit Code Review
commit 81a677f54f
4 changed files with 328 additions and 224 deletions

View File

@ -258,3 +258,183 @@ class BaseWhiteboxComputeTest(base.BaseV2ComputeAdminTest):
cipher=cipher,
control_location=control_location)
return self.create_volume(volume_type=volume_type['name'])
def _get_expected_xml_interface_type(self, port):
"""Return expected domain xml interface type based on port vnic_type
:param port: dictionary with port details
:return xml_vnic_type: the vnic_type as it is expected to be
represented in a guest's XML
"""
VNIC_MAPPING_DICT = {
'vdpa': 'vdpa',
'direct': 'hostdev',
'macvtap': 'direct'
}
vnic_type = port['port']['binding:vnic_type']
# NOTE: SR-IOV Port binding vnic type has been known to cause confusion
# when mapping the value to the underlying instance XML. A vnic_type
# that is direct is a 'hostdev' or Host device assignment that is
# is passing the device directly from the host to the guest. A
# vnic_type that is macvtap or 'direct' in the guest xml, is using the
# macvtap driver to attach a guests NIC directly to a specified
# physical interface on the host.
return VNIC_MAPPING_DICT.get(vnic_type)
def _get_xml_interface_device(self, server_id, port_id):
"""Returns xml interface element that matches provided port mac
and interface type. It is technically possible to have multiple ports
with the same MAC address in an instance, so method functionality may
break in the future.
:param server_id: str, id of the instance to analyze
:param port_id: str, port id to request from the ports client
:return xml_network_deivce: The xml network device delement that match
the port search criteria
"""
port_info = self.os_admin.ports_client.show_port(port_id)
interface_type = self._get_expected_xml_interface_type(port_info)
root = self.get_server_xml(server_id)
mac = port_info['port']['mac_address']
interface_list = root.findall(
"./devices/interface[@type='%s']/mac[@address='%s'].."
% (interface_type, mac)
)
self.assertEqual(len(interface_list), 1, 'Expect to find one '
'and only one instance of interface but '
'instead found %d instances' %
len(interface_list))
return interface_list[0]
def _get_port_attribute(self, port_id, attribute):
"""Get a specific attribute for provided port id
:param port_id: str the port id to search for
:param attribute: str the attribute or key to check from the returned
port dictionary
:return port_attribute: the requested port attribute value
"""
body = self.os_admin.ports_client.show_port(port_id)
port = body['port']
return port.get(attribute)
def _create_net_from_physical_network(self, vlan_id, physical_net):
"""Create an IPv4 L2 vlan network. Physical network provider comes
from sriov_physnet provided in tempest config
:return net A dictionary describing details about the created network
"""
name_net = data_utils.rand_name(self.__class__.__name__)
net_dict = {
'provider:network_type': 'vlan',
'provider:physical_network': physical_net,
'provider:segmentation_id': vlan_id,
'shared': True
}
net = self.os_admin.networks_client.create_network(
name=name_net,
**net_dict)
self.addCleanup(self.os_admin.networks_client.delete_network,
net['network']['id'])
return net
def _create_subnet(self, network_id):
"""Create an IPv4 L2 vlan network. Physical network provider comes
from sriov_physnet provided in tempest config
:param network_id: str, network id subnet will be associated with
:return net A dictionary describing details about the created network
"""
name_subnet = data_utils.rand_name(self.__class__.__name__)
subnet = self.os_admin.subnets_client.create_subnet(
name=name_subnet,
network_id=network_id,
cidr=CONF.network.project_network_cidr,
ip_version=4
)
self.addCleanup(
self.os_admin.subnets_client.delete_subnet,
subnet['subnet']['id']
)
return subnet
def _create_port_from_vnic_type(self, net, vnic_type,
numa_affinity_policy=None):
"""Create an sr-iov port based on the provided vnic type
:param net: dictionary with network details
:param vnic_type: str, representing the vnic type to use with creating
the sriov port, e.g. direct, macvtap, etc.
:return port: dictionary with details about newly created port provided
by neutron ports client
"""
vnic_params = {'binding:vnic_type': vnic_type}
if numa_affinity_policy:
vnic_params['numa_affinity_policy'] = numa_affinity_policy
port = self.os_primary.ports_client.create_port(
network_id=net['network']['id'],
**vnic_params)
self.addCleanup(self.os_primary.ports_client.delete_port,
port['port']['id'])
return port
def _search_pci_devices(self, column, value):
"""Returns all pci_device's address, status, and dev_type that match
query criteria.
:param column: str, the column in the pci_devices table to search
:param value: str, the specific value in the column to query for
return query_match: json, all pci_devices that match specified query
"""
db_client = clients.DatabaseClient()
db = CONF.whitebox_database.nova_cell1_db_name
with db_client.cursor(db) as cursor:
cursor.execute(
'SELECT address,status,dev_type FROM '
'pci_devices WHERE %s = "%s"' % (column, value))
data = cursor.fetchall()
return data
def _verify_neutron_port_binding(self, server_id, port_id):
"""Verifies db metrics are accurate for the state of the provided
port_id
:param port_id str, the port id to request from the ports client
:param server_id str, the guest id to check
"""
binding_profile = self._get_port_attribute(port_id, 'binding:profile')
pci_info = self._search_pci_devices('instance_uuid', server_id)
vnic_type = self._get_port_attribute(port_id, 'binding:vnic_type')
for pci_device in pci_info:
self.assertEqual(
"allocated", pci_device['status'], 'PCI function %s is '
'status %s and not status allocated' %
(pci_device['address'], pci_device['status']))
self.assertEqual(
pci_device['address'],
binding_profile['pci_slot'], 'PCI device '
'information in Nova and and Binding profile information in '
'Neutron mismatch')
if vnic_type == 'vdpa':
self.assertEqual(pci_device['dev_type'], 'vdpa')
elif vnic_type == 'direct-physical':
self.assertEqual(pci_device['dev_type'], 'type-PF')
else:
# vnic_type direct, macvtap or virtio-forwarder can use VF or
# type pci devices.
self.assertIn(pci_device['dev_type'], ['type-VF', 'type-PCI'])
def _get_pci_status_count(self, status):
"""Return the number of pci devices that match the status argument
:param status: str, value to query from the pci_devices table
return int, the number of rows that match the provided status
"""
db_client = clients.DatabaseClient()
db = CONF.whitebox_database.nova_cell1_db_name
with db_client.cursor(db) as cursor:
cursor.execute('select COUNT(*) from pci_devices WHERE '
'status = "%s"' % status)
data = cursor.fetchall()
return data[0]['COUNT(*)']

View File

@ -19,7 +19,6 @@ from tempest.common import compute
from tempest.common.utils.linux import remote_client
from tempest import config
from tempest import exceptions as tempest_exc
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from whitebox_tempest_plugin.api.compute import base
@ -43,95 +42,13 @@ class SRIOVBase(base.BaseWhiteboxComputeTest):
raise cls.skipException('Requires sriov_physnet parameter '
'to be set in order to execute test '
'cases.')
if getattr(CONF.network_feature_enabled,
'provider_net_base_segmentation_id', None) is None:
if getattr(CONF.whitebox_hardware,
'sriov_vlan_id', None) is None:
raise cls.skipException('Requires '
'provider_net_base_segmentation_id '
'parameter to be set in order to execute '
'sriov_vlan_id parameter '
'to be set in order to execute '
'test cases.')
def _get_expected_xml_interface_type(self, port):
"""Return expected domain xml interface type based on port vnic_type
:param port: dictionary with port details
:return xml_vnic_type: the vnic_type as it is expected to be
represented in a guest's XML
"""
vnic_type = port['port']['binding:vnic_type']
# NOTE: SR-IOV Port binding vnic type has been known to cause confusion
# when mapping the value to the underlying instance XML. A vnic_type
# that is direct is a 'hostdev' or Host device assignment that is
# is passing the device directly from the host to the guest. A
# vnic_type that is macvtap or 'direct' in the guest xml, is using the
# macvtap driver to attach a guests NIC directly to a specified
# physical interface on the host.
if vnic_type == 'direct':
return 'hostdev'
elif vnic_type == 'macvtap':
return 'direct'
def _create_sriov_net(self):
"""Create an IPv4 L2 vlan network. Physical network provider comes
from sriov_physnet provided in tempest config
:return net A dictionary describing details about the created network
"""
name_net = data_utils.rand_name(self.__class__.__name__)
vlan_id = \
CONF.network_feature_enabled.provider_net_base_segmentation_id
physical_net = CONF.whitebox_hardware.sriov_physnet
net_dict = {
'provider:network_type': 'vlan',
'provider:physical_network': physical_net,
'provider:segmentation_id': vlan_id,
'shared': True
}
net = self.os_admin.networks_client.create_network(
name=name_net,
**net_dict)
self.addCleanup(self.os_admin.networks_client.delete_network,
net['network']['id'])
return net
def _create_sriov_subnet(self, network_id):
"""Create an IPv4 L2 vlan network. Physical network provider comes
from sriov_physnet provided in tempest config
:param network_id: str, network id subnet will be associated with
:return net A dictionary describing details about the created network
"""
name_subnet = data_utils.rand_name(self.__class__.__name__)
subnet = self.os_admin.subnets_client.create_subnet(
name=name_subnet,
network_id=network_id,
cidr=CONF.network.project_network_cidr,
ip_version=4
)
self.addCleanup(
self.os_admin.subnets_client.delete_subnet,
subnet['subnet']['id']
)
return subnet
def _create_sriov_port(self, net, vnic_type, numa_affinity_policy=None):
"""Create an sr-iov port based on the provided vnic type
:param net: dictionary with network details
:param vnic_type: str, representing the vnic type to use with creating
the sriov port, e.g. direct, macvtap, etc.
:return port: dictionary with details about newly created port provided
by neutron ports client
"""
vnic_params = {'binding:vnic_type': vnic_type}
if numa_affinity_policy:
vnic_params['numa_affinity_policy'] = numa_affinity_policy
port = self.os_primary.ports_client.create_port(
network_id=net['network']['id'],
**vnic_params)
self.addCleanup(self.os_primary.ports_client.delete_port,
port['port']['id'])
return port
def _validate_pf_pci_address_in_xml(self, port_id, host_dev_xml):
"""Validates pci address matches between port info and guest XML
@ -165,31 +82,6 @@ class SRIOVBase(base.BaseWhiteboxComputeTest):
len(hostdev_list))
return hostdev_list[0]
def _get_xml_interface_device(self, server_id, port_id):
"""Returns xml interface element that matches provided port mac
and interface type. It is technically possible to have multiple ports
with the same MAC address in an instance, so method functionality may
break in the future.
:param server_id: str, id of the instance to analyze
:param port_id: str, port id to request from the ports client
:return xml_network_deivce: The xml network device element that matches
the port search criteria
"""
port_info = self.os_primary.ports_client.show_port(port_id)
interface_type = self._get_expected_xml_interface_type(port_info)
root = self.get_server_xml(server_id)
mac = port_info['port']['mac_address']
interface_list = root.findall(
"./devices/interface[@type='%s']/mac[@address='%s'].."
% (interface_type, mac)
)
self.assertEqual(len(interface_list), 1, 'Expect to find one '
'and only one instance of interface but '
'instead found %d instances' %
len(interface_list))
return interface_list[0]
def _validate_port_xml_vlan_tag(self, port_xml_element, expected_vlan):
"""Validates port count and vlan are accurate in server's XML
@ -202,62 +94,6 @@ class SRIOVBase(base.BaseWhiteboxComputeTest):
'tag %s but instead it is tagged with %s' %
(expected_vlan, interface_vlan))
def _get_port_attribute(self, port_id, attribute):
"""Get a specific attribute for provided port id
:param port_id: str the port id to search for
:param attribute: str the attribute or key to check from the returned
port dictionary
:return port_attribute: the requested port attribute value
"""
body = self.os_admin.ports_client.show_port(port_id)
port = body['port']
return port.get(attribute)
def _search_pci_devices(self, column, value):
"""Returns all pci_device's address, status, and dev_type that match
query criteria.
:param column: str, the column in the pci_devices table to search
:param value: str, the specific value in the column to query for
return query_match: json, all pci_devices that match specified query
"""
db_client = clients.DatabaseClient()
db = CONF.whitebox_database.nova_cell1_db_name
with db_client.cursor(db) as cursor:
cursor.execute(
'SELECT address,status,dev_type FROM '
'pci_devices WHERE %s = "%s"' % (column, value))
data = cursor.fetchall()
return data
def _verify_neutron_port_binding(self, server_id, port_id):
"""Verifies db metrics are accurate for the state of the provided
port_id
:param port_id str, the port id to request from the ports client
:param server_id str, the guest id to check
"""
binding_profile = self._get_port_attribute(port_id, 'binding:profile')
vnic_type = self._get_port_attribute(port_id, 'binding:vnic_type')
pci_info = self._search_pci_devices('instance_uuid', server_id)
for pci_device in pci_info:
self.assertEqual(
"allocated", pci_device['status'], 'Physical function %s is '
'in status %s and not in status allocated' %
(pci_device['address'], pci_device['status']))
self.assertEqual(
pci_device['address'],
binding_profile['pci_slot'], 'PCI device '
'information in Nova and and Binding profile information in '
'Neutron mismatch')
if vnic_type == 'direct-physical':
self.assertEqual(pci_device['dev_type'], 'type-PF')
else:
# vnic_type direct, macvtap or virtio-forwarder can use VF or
# type pci devices.
self.assertIn(pci_device['dev_type'], ['type-VF', 'type-PCI'])
class SRIOVNumaAffinity(SRIOVBase, numa_helper.NUMAHelperMixin):
@ -295,14 +131,17 @@ class SRIOVNumaAffinity(SRIOVBase, numa_helper.NUMAHelperMixin):
def setUp(self):
super(SRIOVNumaAffinity, self).setUp()
self.vlan_id = \
CONF.whitebox_hardware.sriov_vlan_id
self.dedicated_cpus_per_numa = \
CONF.whitebox_hardware.dedicated_cpus_per_numa
self.affinity_node = str(CONF.whitebox_hardware.physnet_numa_affinity)
self.network = self._create_sriov_net()
self._create_sriov_subnet(self.network['network']['id'])
self.physical_net = CONF.whitebox_hardware.sriov_physnet
self.network = self._create_net_from_physical_network(
self.vlan_id,
self.physical_net)
self._create_subnet(self.network['network']['id'])
self.flavor = self.create_flavor(
vcpus=self.dedicated_cpus_per_numa,
extra_specs={'hw:cpu_policy': 'dedicated'}
@ -363,8 +202,6 @@ class SRIOVNumaAffinity(SRIOVBase, numa_helper.NUMAHelperMixin):
# Validate servers A and B have correct sr-iov interface
# information in the xml. Its type and vlan should be accurate.
net_vlan = \
CONF.network_feature_enabled.provider_net_base_segmentation_id
for server, port in zip([server_a, server_b],
[port_a, port_b]):
interface_xml_element = self._get_xml_interface_device(
@ -373,7 +210,7 @@ class SRIOVNumaAffinity(SRIOVBase, numa_helper.NUMAHelperMixin):
)
self._validate_port_xml_vlan_tag(
interface_xml_element,
net_vlan)
self.vlan_id)
def _required_test_procedure(self, flavor, port_a, port_b, image_id):
@ -418,13 +255,11 @@ class SRIOVNumaAffinity(SRIOVBase, numa_helper.NUMAHelperMixin):
# Validate server A has correct sr-iov interface information
# in the xml. Its type and vlan should be accurate.
net_vlan = \
CONF.network_feature_enabled.provider_net_base_segmentation_id
interface_xml_element = self._get_xml_interface_device(
server_a['id'],
port_a['port']['id']
)
self._validate_port_xml_vlan_tag(interface_xml_element, net_vlan)
self._validate_port_xml_vlan_tag(interface_xml_element, self.vlan_id)
class SRIOVNumaAffinityWithFlavor(SRIOVNumaAffinity):
@ -451,10 +286,10 @@ class SRIOVNumaAffinityWithFlavor(SRIOVNumaAffinity):
vcpus=self.dedicated_cpus_per_numa,
extra_specs=self.preferred
)
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
self._preferred_test_procedure(flavor, port_a, port_b, self.image_ref)
@ -490,10 +325,10 @@ class SRIOVNumaAffinityWithFlavor(SRIOVNumaAffinity):
vcpus=self.dedicated_cpus_per_numa,
extra_specs=self.required
)
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
self._required_test_procedure(flavor, port_a, port_b, self.image_ref)
@ -528,10 +363,10 @@ class SRIOVNumaAffinityWithImagePolicy(SRIOVNumaAffinity):
"""
image_id = self.copy_default_image(
hw_pci_numa_affinity_policy='preferred')
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
self._preferred_test_procedure(
@ -558,10 +393,10 @@ class SRIOVNumaAffinityWithImagePolicy(SRIOVNumaAffinity):
"""
image_id = self.copy_default_image(
hw_pci_numa_affinity_policy='required')
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type)
self._required_test_procedure(
@ -594,11 +429,11 @@ class SRIOVNumaAffinityWithPortPolicy(SRIOVNumaAffinity):
guests
"""
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='preferred')
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='preferred')
@ -623,11 +458,11 @@ class SRIOVNumaAffinityWithPortPolicy(SRIOVNumaAffinity):
guests
"""
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='required')
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='preferred')
@ -651,11 +486,11 @@ class SRIOVNumaAffinityWithPortPolicy(SRIOVNumaAffinity):
guest
"""
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='required')
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='required')
@ -684,11 +519,11 @@ class SRIOVNumaAffinityWithPortPolicy(SRIOVNumaAffinity):
required_flavor = self.create_flavor(
vcpus=self.dedicated_cpus_per_numa,
extra_specs=self.required)
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='preferred')
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='preferred')
@ -716,11 +551,11 @@ class SRIOVNumaAffinityWithPortPolicy(SRIOVNumaAffinity):
image_id = self.copy_default_image(
hw_pci_numa_affinity_policy='required')
port_a = self._create_sriov_port(
port_a = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='preferred')
port_b = self._create_sriov_port(
port_b = self._create_port_from_vnic_type(
net=self.network,
vnic_type=CONF.network.port_vnic_type,
numa_affinity_policy='preferred')
@ -737,8 +572,13 @@ class SRIOVMigration(SRIOVBase):
def setUp(self):
super(SRIOVMigration, self).setUp()
self.network = self._create_sriov_net()
self._create_sriov_subnet(self.network['network']['id'])
self.vlan_id = \
CONF.whitebox_hardware.sriov_vlan_id
self.physical_net = CONF.whitebox_hardware.sriov_physnet
self.network = self._create_net_from_physical_network(
self.vlan_id,
self.physical_net)
self._create_subnet(self.network['network']['id'])
@classmethod
def skip_checks(cls):
@ -746,20 +586,6 @@ class SRIOVMigration(SRIOVBase):
if (CONF.compute.min_compute_nodes < 2):
raise cls.skipException('Need 2 or more compute nodes.')
def _get_pci_status_count(self, status):
"""Return the number of pci devices that match the status argument
:param status: str, value to query from the pci_devices table
return int, the number of rows that match the provided status
"""
db_client = clients.DatabaseClient()
db = CONF.whitebox_database.nova_cell1_db_name
with db_client.cursor(db) as cursor:
cursor.execute('select COUNT(*) from pci_devices WHERE '
'status REGEXP "%s"' % status)
data = cursor.fetchall()
return data[0]['COUNT(*)']
def _base_test_live_migration(self, vnic_type):
"""Parent test class that perform sr-iov live migration
@ -770,11 +596,9 @@ class SRIOVMigration(SRIOVBase):
else:
pci_device_status_regex = 'allocated|claimed'
net_vlan = \
CONF.network_feature_enabled.provider_net_base_segmentation_id
flavor = self.create_flavor()
port = self._create_sriov_port(
port = self._create_port_from_vnic_type(
net=self.network,
vnic_type=vnic_type
)
@ -797,7 +621,7 @@ class SRIOVMigration(SRIOVBase):
)
# Validate the vlan tag persisted in instance's XML after migration
self._validate_port_xml_vlan_tag(interface_xml_element, net_vlan)
self._validate_port_xml_vlan_tag(interface_xml_element, self.vlan_id)
# Confirm dev_type, allocation status, and pci address information are
# correct in pci_devices table of openstack DB
@ -829,7 +653,7 @@ class SRIOVMigration(SRIOVBase):
# Confirm vlan tag in interface XML, dev_type, allocation status, and
# pci address information are correct in pci_devices table of openstack
# DB after second migration
self._validate_port_xml_vlan_tag(interface_xml_element, net_vlan)
self._validate_port_xml_vlan_tag(interface_xml_element, self.vlan_id)
self._verify_neutron_port_binding(
server['id'],
port['port']['id']
@ -858,8 +682,13 @@ class SRIOVAttachAndDetach(SRIOVBase):
def setUp(self):
super(SRIOVAttachAndDetach, self).setUp()
self.sriov_network = self._create_sriov_net()
self._create_sriov_subnet(self.sriov_network['network']['id'])
self.vlan_id = \
CONF.whitebox_hardware.sriov_vlan_id
self.physical_net = CONF.whitebox_hardware.sriov_physnet
self.network = self._create_net_from_physical_network(
self.vlan_id,
self.physical_net)
self._create_subnet(self.sriov_network['network']['id'])
@classmethod
def skip_checks(cls):
@ -999,11 +828,9 @@ class SRIOVAttachAndDetach(SRIOVBase):
# Gather SR-IOV network vlan, create two guests, and create an SR-IOV
# port based on the provided vnic_type
net_vlan = \
CONF.network_feature_enabled.provider_net_base_segmentation_id
servers = [self.create_server_and_ssh(),
self.create_server_and_ssh()]
port = self._create_sriov_port(
port = self._create_port_from_vnic_type(
net=self.sriov_network,
vnic_type=vnic_type
)
@ -1032,7 +859,7 @@ class SRIOVAttachAndDetach(SRIOVBase):
# Verify the port's VLAN tag is present in the XML
self._validate_port_xml_vlan_tag(interface_xml_element,
net_vlan)
self.vlan_id)
# Confirm the vendor and vf product id are present in the guest
self._check_device_in_guest(
@ -1086,7 +913,7 @@ class SRIOVAttachAndDetach(SRIOVBase):
# direct-physical
servers = [self.create_server_and_ssh(),
self.create_server_and_ssh()]
port = self._create_sriov_port(
port = self._create_port_from_vnic_type(
net=self.sriov_network,
vnic_type='direct-physical'
)

View File

@ -0,0 +1,85 @@
# Copyright 2020 Red Hat Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from tempest import config
from whitebox_tempest_plugin.api.compute import base
from oslo_log import log as logging
CONF = config.CONF
LOG = logging.getLogger(__name__)
class VDPASmokeTests(base.BaseWhiteboxComputeTest):
@classmethod
def skip_checks(cls):
super(VDPASmokeTests, cls).skip_checks()
if getattr(CONF.whitebox_hardware,
'vdpa_physnet', None) is None:
raise cls.skipException('Requires vdpa_physnet parameter '
'to be set in order to execute test '
'cases.')
if getattr(CONF.whitebox_hardware,
'vdpa_vlan_id', None) is None:
raise cls.skipException('Requires '
'vdpa_vlan_id parameter to be set in '
'order to execute test cases.')
def setUp(self):
super(VDPASmokeTests, self).setUp()
self.vlan_id = \
CONF.whitebox_hardware.vdpa_vlan_id
self.physical_net = CONF.whitebox_hardware.vdpa_physnet
self.network = self._create_net_from_physical_network(
self.vlan_id,
self.physical_net)
self._create_subnet(self.network['network']['id'])
def test_guest_creation_with_vdpa_port(self):
"""Creates a guest that requires a vdpa port"""
flavor = self.create_flavor()
port = self._create_port_from_vnic_type(
net=self.network,
vnic_type='vdpa'
)
server = self.create_test_server(
flavor=flavor['id'],
networks=[{'port': port['port']['id']}],
wait_until='ACTIVE'
)
interface_xml_element = self._get_xml_interface_device(
server['id'],
port['port']['id'],
)
if CONF.whitebox.rx_queue_size:
driver = interface_xml_element.find("./driver[@name='vhost']")
self.assertEqual(
str(CONF.whitebox.rx_queue_size),
driver.attrib['rx_queue_size'],
"VDPA rx_queue_size equaling %s not found" %
str(CONF.whitebox.rx_queue_size))
# Confirm dev_type, allocation status, and pci address information are
# correct in pci_devices table of openstack DB
self._verify_neutron_port_binding(
server['id'],
port['port']['id']
)

View File

@ -269,6 +269,18 @@ hardware_opts = [
'sriov_physnet',
default=None,
help='The physnet to use when creating sr-iov ports'),
cfg.IntOpt(
'sriov_vlan_id',
default=None,
help='The vlan id associated with the sriov port'),
cfg.StrOpt(
'vdpa_physnet',
default=None,
help='The physnet to use when creating vdpa ports'),
cfg.IntOpt(
'vdpa_vlan_id',
default=None,
help='The vlan id associated with the vdpa port'),
cfg.IntOpt(
'physnet_numa_affinity',
default=None,