Add vgpu guest creation testcase
Purpose of this commit is to test basic server creation while attaching a vGPU device as documented for KVM systems here [1]. The commit adds a new whitebox configuration group ‘whitebox-hardware’. This group currently contains one parameters: vgpu_vendor_id. It works as both a skip check for the new testcase and as the specific gpu vendor id to look for when analyzing the guest. The new test method, test_create_vgpu_instance, was added to the file test_vgpu.py in the test class VGPUTest. The test creates the necessary flavor to launch a guest with an attached vgpu device and creates an instance. It then ssh’s into the guest and validates the vgpu vendor id is present when checking /sys/bus/pci/devices/<pci_address>/vendor. A helper method get_pci_address() was lifted from nova.pci.utils [2]. This method is used to assemble the PCI components that are pulled from the guest instance's device xml. [1] https://docs.openstack.org/nova/train/admin/virtual-gpu.html [2] https://github.com/openstack/nova/blob/master/nova/pci/utils.py Change-Id: I736c0bf59c8c9c14aa8848d59077ef51071ffbbe
This commit is contained in:
parent
c4ec528269
commit
9a309d64c6
101
whitebox_tempest_plugin/api/compute/test_vgpu.py
Normal file
101
whitebox_tempest_plugin/api/compute/test_vgpu.py
Normal file
@ -0,0 +1,101 @@
|
||||
# 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.common.utils.linux import remote_client
|
||||
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__)
|
||||
|
||||
|
||||
def get_pci_address(domain, bus, slot, func):
|
||||
"""Assembles PCI address components into a fully-specified PCI address.
|
||||
|
||||
NOTE(jparker): This has been lifted from nova.pci.utils with no
|
||||
adjustments
|
||||
|
||||
Does not validate that the components are valid hex or wildcard values.
|
||||
:param domain, bus, slot, func: Hex or wildcard strings.
|
||||
:return: A string of the form "<domain>:<bus>:<slot>.<function>".
|
||||
"""
|
||||
return '%s:%s:%s.%s' % (domain, bus, slot, func)
|
||||
|
||||
|
||||
class VGPUTest(base.BaseWhiteboxComputeTest):
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(VGPUTest, cls).skip_checks()
|
||||
if (CONF.whitebox_hardware.vgpu_vendor_id is None):
|
||||
msg = "CONF.whitebox_hardware.vgpu_vendor_id needs to be set."
|
||||
raise cls.skipException(msg)
|
||||
|
||||
@classmethod
|
||||
def setup_credentials(cls):
|
||||
cls.prepare_instance_network()
|
||||
super(VGPUTest, cls).setup_credentials()
|
||||
|
||||
def test_create_vgpu_instance(self):
|
||||
# Create a flavor that will request a VGPU resource
|
||||
flavor = self.create_flavor(extra_specs={"resources:VGPU": "1"})
|
||||
|
||||
# Determine validation resources, and create a server based on the
|
||||
# resources
|
||||
validation_resources = self.get_class_validation_resources(
|
||||
self.os_primary)
|
||||
server = self.create_test_server(
|
||||
flavor=flavor['id'],
|
||||
validatable=True,
|
||||
validation_resources=validation_resources
|
||||
)
|
||||
|
||||
# Find all hostdev devices on the instance of type mdev and validate
|
||||
# one and only one exist
|
||||
vgpu_device = self.get_server_xml(server['id']).findall(
|
||||
"./devices/hostdev[@type='mdev']"
|
||||
)
|
||||
self.assertEqual(1, len(vgpu_device), "Expected 1 xml hostdev vgpu "
|
||||
"element on instance %s but instead found %d" %
|
||||
(server['id'], len(vgpu_device)))
|
||||
|
||||
# Create an SSH client to access the guest
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.image_ssh_user,
|
||||
self.image_ssh_password,
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.servers_client)
|
||||
linux_client.validate_authentication()
|
||||
|
||||
# Determine the pci address of the vgpu hostdev element and use this
|
||||
# address to search for the vendor id in the guest sysfs
|
||||
pci_addr_element = vgpu_device[0].find(".address[@type='pci']")
|
||||
domain = pci_addr_element.get('domain').replace('0x', '')
|
||||
bus = pci_addr_element.get('bus').replace('0x', '')
|
||||
slot = pci_addr_element.get('slot').replace('0x', '')
|
||||
func = pci_addr_element.get('function').replace('0x', '')
|
||||
pci_address = get_pci_address(domain, bus, slot, func)
|
||||
|
||||
# Validate the vendor id is present in the output
|
||||
cmd = "cat /sys/bus/pci/devices/%s/vendor" % pci_address
|
||||
sys_out = linux_client.exec_command(cmd)
|
||||
self.assertIn(CONF.whitebox_hardware.vgpu_vendor_id, sys_out,
|
||||
"Vendor ID %s not found in output %s" %
|
||||
(CONF.whitebox_hardware.vgpu_vendor_id, sys_out))
|
@ -130,3 +130,16 @@ database_opts = [
|
||||
default=3306,
|
||||
help="SSH port forwarding gateway number")
|
||||
]
|
||||
|
||||
hardware_group = cfg.OptGroup(
|
||||
name='whitebox-hardware',
|
||||
title='Config options that describe the underlying compute node hardware '
|
||||
'in the environment.')
|
||||
|
||||
hardware_opts = [
|
||||
cfg.StrOpt(
|
||||
'vgpu_vendor_id',
|
||||
default=None,
|
||||
help='The vendor id of the underlying vgpu hardware of the compute. '
|
||||
'An example with Nvidia would be 10de'),
|
||||
]
|
||||
|
@ -40,6 +40,8 @@ class WhiteboxTempestPlugin(plugins.TempestPlugin):
|
||||
whitebox_config.database_opts)
|
||||
config.register_opt_group(conf, whitebox_config.nova_libvirt_group,
|
||||
whitebox_config.nova_libvirt_opts)
|
||||
config.register_opt_group(conf, whitebox_config.hardware_group,
|
||||
whitebox_config.hardware_opts)
|
||||
|
||||
def get_opt_lists(self):
|
||||
return [(whitebox_config.general_group.name,
|
||||
@ -49,4 +51,6 @@ class WhiteboxTempestPlugin(plugins.TempestPlugin):
|
||||
(whitebox_config.nova_libvirt_group.name,
|
||||
whitebox_config.nova_libvirt_opts),
|
||||
(whitebox_config.database_group.name,
|
||||
whitebox_config.database_opts)]
|
||||
whitebox_config.database_opts),
|
||||
(whitebox_config.hardware_group.name,
|
||||
whitebox_config.hardware_opts)]
|
||||
|
Loading…
Reference in New Issue
Block a user