From c7e7443c63b17d41c4a2f940b7018e789c6977e5 Mon Sep 17 00:00:00 2001 From: Billy Olsen Date: Thu, 20 Jan 2022 15:51:49 -0700 Subject: [PATCH] Add vtpm functional tests Add functional tests for vTPM enablement within guests. Signed-off-by: Billy Olsen --- zaza/openstack/charm_tests/glance/setup.py | 21 +++++++ zaza/openstack/charm_tests/nova/setup.py | 4 +- zaza/openstack/charm_tests/nova/tests.py | 67 +++++++++++++++++++++- zaza/openstack/charm_tests/nova/utils.py | 20 +++++++ zaza/openstack/configure/guest.py | 5 ++ 5 files changed, 114 insertions(+), 3 deletions(-) diff --git a/zaza/openstack/charm_tests/glance/setup.py b/zaza/openstack/charm_tests/glance/setup.py index 367c980..3b9fba0 100644 --- a/zaza/openstack/charm_tests/glance/setup.py +++ b/zaza/openstack/charm_tests/glance/setup.py @@ -167,6 +167,27 @@ def add_lts_image(glance_client=None, image_name=None, release=None, properties=properties) +def add_uefi_image(glance_client=None, image_name=None, release=None, + properties=None): + """Add an Ubuntu Focal LTS image to the current deployment. + + :param glance: Authenticated glanceclient + :type glance: glanceclient.Client + :param image_name: Label for the image in glance + :type image_name: str + :param release: Name of Ubuntu release. + :type release: str + :param properties: Custom image properties + :type properties: dict + """ + props = {'hw_firmware_type': 'uefi'} + if properties: + props.update(properties) + add_lts_image(glance_client, image_name=image_name or 'focal', + release=release or 'focal', + properties=props) + + def configure_external_s3_backend(): """Set up Ceph-radosgw as an external S3 backend for Glance.""" logging.info("Creating a test S3 user and credentials for Glance") diff --git a/zaza/openstack/charm_tests/nova/setup.py b/zaza/openstack/charm_tests/nova/setup.py index 7f8ee53..81b3bb1 100644 --- a/zaza/openstack/charm_tests/nova/setup.py +++ b/zaza/openstack/charm_tests/nova/setup.py @@ -40,12 +40,14 @@ def create_flavors(nova_client=None): names = [flavor.name for flavor in nova_client.flavors.list()] for flavor in nova_utils.FLAVORS.keys(): if flavor not in names: - nova_client.flavors.create( + nova_flavor = nova_client.flavors.create( name=flavor, ram=nova_utils.FLAVORS[flavor]['ram'], vcpus=nova_utils.FLAVORS[flavor]['vcpus'], disk=nova_utils.FLAVORS[flavor]['disk'], flavorid=nova_utils.FLAVORS[flavor]['flavorid']) + if 'extra-specs' in nova_utils.FLAVORS[flavor]: + nova_flavor.set_keys(nova_utils.FLAVORS[flavor]['extra-specs']) @tenacity.retry(stop=tenacity.stop_after_attempt(3), diff --git a/zaza/openstack/charm_tests/nova/tests.py b/zaza/openstack/charm_tests/nova/tests.py index 25b8f04..f67d9aa 100644 --- a/zaza/openstack/charm_tests/nova/tests.py +++ b/zaza/openstack/charm_tests/nova/tests.py @@ -29,9 +29,11 @@ import novaclient.exceptions import zaza.model import zaza.openstack.charm_tests.glance.setup as glance_setup +import zaza.openstack.charm_tests.neutron.tests as neutron_tests +import zaza.openstack.charm_tests.nova.utils as nova_utils import zaza.openstack.charm_tests.test_utils as test_utils -import zaza.openstack.configure.guest import zaza.openstack.utilities.generic as generic_utils +import zaza.openstack.configure.guest as guest import zaza.openstack.utilities.openstack as openstack_utils from zaza.utilities import juju as juju_utils @@ -44,7 +46,7 @@ class BaseGuestCreateTest(unittest.TestCase): logging.info('BaseGuestCreateTest.launch_instance is deprecated ' 'please use ' 'zaza.openstack.configure.guest.launch_instance') - zaza.openstack.configure.guest.launch_instance(instance_key) + guest.launch_instance(instance_key) class CirrosGuestCreateTest(test_utils.OpenStackBaseTest): @@ -90,6 +92,67 @@ class LTSGuestCreateVolumeBackedTest(test_utils.OpenStackBaseTest): self.resource_cleanup() +class VTPMGuestCreateTest(test_utils.OpenStackBaseTest): + """Tests launching a guest with vTPM Support. + + These tests are only run for focal-wallaby and newer. + Base version in Wallaby is 23.0.0. + """ + + def _check_tpm_device(self, instance, *devices): + """Check that the instance has TPM devices available. + + :param instance: the instance to determine if TPM devices are available + :type instance: nova_client.Server instance + :param devices: the devices to look for that are present in the guest + :type devices: list of strings + :return: True if the instance has TPM devices, False otherwise + :rtype: bool + """ + fip = neutron_tests.floating_ips_from_instance(instance)[0] + username = guest.boot_tests['focal']['username'] + password = guest.boot_tests['focal'].get('password') + privkey = openstack_utils.get_private_key(nova_utils.KEYPAIR_NAME) + + def check_tpm(stdin, stdout, stderr): + devs = [line.strip() for line in stdout.readlines()] + for expected in devices: + self.assertIn(expected, devs) + + logging.info('Validating TPM devices are present') + openstack_utils.ssh_command(username, ip=fip, vm_name=instance.name, + command='sudo ls -1 /dev/tpm*', + password=password, privkey=privkey, + verify=check_tpm) + + @test_utils.skipUntilVersion('nova-compute', 'nova-common', '3:23.0.0') + def test_launch_vtpm_1_2_instance(self): + """Launch an instance using TPM 1.2.""" + self.RESOURCE_PREFIX = 'zaza-nova' + instance = guest.launch_instance( + 'focal', image_name='focal', flavor_name='vtpm-1.2', + vm_name='zaza-nova-vtpm-1-2', + ) + # Note: TPM 1.2 presents tpm0 as a device + self._check_tpm_device(instance, '/dev/tpm0') + + @test_utils.skipUntilVersion('nova-compute', 'nova-common', '3:23.0.0') + def test_launch_vtpm_2_instance(self): + """Launch an instance using TPM 2.0.""" + self.RESOURCE_PREFIX = 'zaza-nova' + instance = guest.launch_instance( + 'focal', image_name='focal', flavor_name='vtpm-2', + vm_name='zaza-nova-vtpm-2', + ) + # Note: TPM 1.2 and 2.0 both present tpm0 as a device. TPM 2.0 + # devices also include a tpmrm0 device. + self._check_tpm_device(instance, '/dev/tpm0', '/dev/tpmrm0') + + def tearDown(self): + """Cleanup of VM guests.""" + self.resource_cleanup() + + class NovaCommonTests(test_utils.OpenStackBaseTest): """nova-compute and nova-cloud-controller common tests.""" diff --git a/zaza/openstack/charm_tests/nova/utils.py b/zaza/openstack/charm_tests/nova/utils.py index b16eef4..f2c8af9 100644 --- a/zaza/openstack/charm_tests/nova/utils.py +++ b/zaza/openstack/charm_tests/nova/utils.py @@ -45,5 +45,25 @@ FLAVORS = { 'ram': 512, 'disk': 1, 'vcpus': 1}, + 'vtpm-1.2': { + 'flavorid': 'auto', + 'ram': 512, + 'disk': 5, + 'vcpus': 1, + 'extra-specs': { + 'hw:tpm_version': '1.2', + 'hw:tpm_model': 'tpm-tis', + }, + }, + 'vtpm-2': { + 'flavorid': 'auto', + 'ram': 512, + 'disk': 5, + 'vcpus': 1, + 'extra-specs': { + 'hw:tpm_version': '2.0', + 'hw:tpm_model': 'tpm-crb', + }, + }, } KEYPAIR_NAME = 'zaza' diff --git a/zaza/openstack/configure/guest.py b/zaza/openstack/configure/guest.py index d63938d..4e20ef4 100644 --- a/zaza/openstack/configure/guest.py +++ b/zaza/openstack/configure/guest.py @@ -42,6 +42,11 @@ boot_tests = { 'image_name': 'bionic', 'flavor_name': 'm1.small', 'username': 'ubuntu', + 'bootstring': 'finished at'}, + 'focal': { + 'image_name': 'focal', + 'flavor_name': 'm1.small', + 'username': 'ubuntu', 'bootstring': 'finished at'}}