From dbb2711c59e9a7dab25dd6e0d08e36348b865c75 Mon Sep 17 00:00:00 2001 From: Martin Kopec Date: Mon, 25 Mar 2019 12:48:01 +0000 Subject: [PATCH] Add RNG device to images and flavours Upload new images and flavours with random number generator device [1]. It prevents the tests failing due to an image not ready for login error and can improve image boot time. [1] https://wiki.openstack.org/wiki/LibvirtVirtioRng Change-Id: I50114a3914e0df0e22706ca8a7a1649eb1ced31d --- config_tempest/flavors.py | 15 ++++++++++++--- config_tempest/main.py | 10 ++++++++-- config_tempest/services/image.py | 13 ++++++++----- config_tempest/tests/test_flavors.py | 25 ++++++++++++++++++++----- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/config_tempest/flavors.py b/config_tempest/flavors.py index 912e5b13..658e0ef2 100644 --- a/config_tempest/flavors.py +++ b/config_tempest/flavors.py @@ -19,7 +19,7 @@ from config_tempest.constants import LOG class Flavors(object): - def __init__(self, client, allow_creation, conf): + def __init__(self, client, allow_creation, conf, no_rng=False): """Init. :type client: FlavorsClient object from tempest lib @@ -29,6 +29,7 @@ class Flavors(object): self.client = client self.allow_creation = allow_creation self._conf = conf + self.no_rng = no_rng self.flavor_list = self.client.list_flavors()['flavors'] def create_tempest_flavors(self): @@ -53,10 +54,12 @@ class Flavors(object): " exist", pref['key'], flavor_id) else: # create m1.nano/m1.micro flavor - flavor_id = self.create_flavor(pref['name'], ram=pref['ram']) + flavor_id = self.create_flavor(pref['name'], ram=pref['ram'], + no_rng=self.no_rng) self._conf.set('compute', pref['key'], flavor_id) - def create_flavor(self, flavor_name, ram=64, vcpus=1, disk=1): + def create_flavor(self, flavor_name, ram=64, vcpus=1, + disk=1, no_rng=False): """Create flavors or try to discover two smallest ones available. :param flavor_name: flavor name to be created (usually m1.nano or @@ -64,6 +67,7 @@ class Flavors(object): :param ram: memory of created flavor in MB :param vcpus: number of VCPUs for the flavor :param disk: size of disk for flavor in GB + :param no_rng: boolean, if True, flavor will be created with RNG device """ flavor_id = self.find_flavor_by_name(flavor_name) if flavor_id is not None: @@ -74,6 +78,11 @@ class Flavors(object): resp = self.client.create_flavor(name=flavor_name, ram=ram, vcpus=vcpus, disk=disk, id=None) + args = {'flavor_id': resp['flavor']['id'], + 'hw_rng:allowed': 'True'} + if no_rng: + args.pop('hw_rng:allowed') + self.client.set_flavor_extra_spec(**args) return resp['flavor']['id'] else: if len(self.flavor_list) < 2: diff --git a/config_tempest/main.py b/config_tempest/main.py index 79e85962..8a3dcd73 100755 --- a/config_tempest/main.py +++ b/config_tempest/main.py @@ -261,6 +261,9 @@ def get_arg_parser(): help='Print debugging information.') parser.add_argument('--verbose', '-v', action='store_true', default=False, help='Print more information about the execution.') + parser.add_argument('--no-rng', action='store_true', default=False, + help="""Create new flavors and upload images without + random number generator device.""") parser.add_argument('--non-admin', action='store_true', default=False, help="""Simulate non-admin credentials. When True, the credentials are used as @@ -509,13 +512,15 @@ def config_tempest(**kwargs): if kwargs.get('create', False) and kwargs.get('test_accounts') is None: users = Users(clients.projects, clients.roles, clients.users, conf) users.create_tempest_users(services.is_service('orchestration')) - flavors = Flavors(clients.flavors, kwargs.get('create', False), conf) + flavors = Flavors(clients.flavors, kwargs.get('create', False), conf, + no_rng=kwargs.get('no_rng', False)) flavors.create_tempest_flavors() image = services.get_service('image') image.set_image_preferences(kwargs.get('image_disk_format', C.DEFAULT_IMAGE_FORMAT), - kwargs.get('non_admin', False)) + kwargs.get('non_admin', False), + no_rng=kwargs.get('no_rng', False)) image.create_tempest_images(conf) has_neutron = services.is_service("network") @@ -568,6 +573,7 @@ def main(): image_path=args.image, network_id=args.network_id, non_admin=args.non_admin, + no_rng=args.no_rng, os_cloud=args.os_cloud, out=args.out, overrides=args.overrides, diff --git a/config_tempest/services/image.py b/config_tempest/services/image.py index 0b2796a3..18c7443a 100644 --- a/config_tempest/services/image.py +++ b/config_tempest/services/image.py @@ -31,7 +31,7 @@ class ImageService(VersionedService): disable_ssl_validation, client) - def set_image_preferences(self, disk_format, non_admin): + def set_image_preferences(self, disk_format, non_admin, no_rng=False): """Sets image prefferences. :type disk_format: string @@ -39,6 +39,7 @@ class ImageService(VersionedService): """ self.disk_format = disk_format self.non_admin = non_admin + self.no_rng = no_rng def set_default_tempest_options(self, conf): # When cirros is the image, set validation.image_ssh_user to cirros. @@ -189,10 +190,12 @@ class ImageService(VersionedService): visibility = 'public' with open(path, 'rb') as data: - image = self.client.create_image(name=name, - disk_format=self.disk_format, - container_format='bare', - visibility=visibility) + args = {'name': name, 'disk_format': self.disk_format, + 'container_format': 'bare', 'visibility': visibility, + 'hw_rng_model': 'virtio'} + if self.no_rng: + args.pop('hw_rng_model') + image = self.client.create_image(**args) self.client.store_image_file(image['id'], data) return image diff --git a/config_tempest/tests/test_flavors.py b/config_tempest/tests/test_flavors.py index dabd6aa8..31c28bd1 100644 --- a/config_tempest/tests/test_flavors.py +++ b/config_tempest/tests/test_flavors.py @@ -54,8 +54,8 @@ class TestFlavors(BaseConfigTempestTest): self.Service.create_tempest_flavors() self.assertEqual(self.conf.get('compute', 'flavor_ref'), "FakeID") self.assertEqual(self.conf.get('compute', 'flavor_ref_alt'), "FakeID") - calls = [mock.call('m1.nano', ram=64), - mock.call('m1.micro', ram=128)] + calls = [mock.call('m1.nano', ram=64, no_rng=False), + mock.call('m1.micro', ram=128, no_rng=False)] mock_function.assert_has_calls(calls, any_order=True) def check_call_of_discover_smallest_flavor(self): @@ -110,14 +110,29 @@ class TestFlavors(BaseConfigTempestTest): # it should have ended in the except block above self.assertTrue(False) - def test_create_flavor(self): + def _test_create_flavor(self, no_rng=False): return_value = {"flavor": {"id": "MyFakeID", "name": "MyID"}} self.Service.flavor_list = [] + client = self.CLIENT_MOCK mock_function = mock.Mock(return_value=return_value) - self.useFixture(MonkeyPatch(self.CLIENT_MOCK + '.create_flavor', + self.useFixture(MonkeyPatch(client + '.create_flavor', mock_function)) + mock_function = mock.Mock(return_value={}) + self.useFixture(MonkeyPatch(client + '.set_flavor_extra_spec', mock_function)) - resp = self.Service.create_flavor(flavor_name="MyID") + resp = self.Service.create_flavor(flavor_name="MyID", no_rng=no_rng) self.assertEqual(resp, return_value['flavor']['id']) + return mock_function + + def test_create_flavor_rng(self): + mock_function = self._test_create_flavor() + calls = [mock.call(flavor_id='MyFakeID', **{'hw_rng:allowed': 'True'})] + mock_function.assert_has_calls(calls, any_order=True) + + def test_create_flavor_no_rng(self): + self.Service.no_rng = True + mock_function = self._test_create_flavor(no_rng=True) + calls = [mock.call(flavor_id='MyFakeID')] + mock_function.assert_has_calls(calls, any_order=True) def test_find_flavor_by_id(self): return_value = {"flavors": self.FLAVORS_LIST}