diff --git a/rally-jobs/rally.yaml b/rally-jobs/rally.yaml index e012f6bbe2..d1615e3cf5 100644 --- a/rally-jobs/rally.yaml +++ b/rally-jobs/rally.yaml @@ -590,6 +590,9 @@ flavor: name: "m1.tiny" number_instances: 2 + create_image_kwargs: + properties: + hw_video_model: vga runner: type: "constant" times: 1 diff --git a/rally/plugins/openstack/scenarios/glance/images.py b/rally/plugins/openstack/scenarios/glance/images.py index eb8d09a6cb..37c30806e4 100644 --- a/rally/plugins/openstack/scenarios/glance/images.py +++ b/rally/plugins/openstack/scenarios/glance/images.py @@ -54,7 +54,7 @@ class GlanceBasic(scenario.OpenStackScenario): class CreateAndListImage(GlanceBasic): def run(self, container_format, image_location, disk_format, - visibility="private", min_disk=0, min_ram=0): + visibility="private", min_disk=0, min_ram=0, properties=None): """Create an image and then list all images. Measure the "glance image-list" command performance. @@ -73,6 +73,8 @@ class CreateAndListImage(GlanceBasic): :param visibility: The access permission for the created image :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: A dict of image metadata properties to set + on the image """ image = self.glance.create_image( container_format=container_format, @@ -80,7 +82,8 @@ class CreateAndListImage(GlanceBasic): disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) self.assertTrue(image) image_list = self.glance.list_images() self.assertIn(image.id, [i.id for i in image_list]) @@ -101,7 +104,7 @@ class CreateAndListImage(GlanceBasic): class CreateAndGetImage(GlanceBasic): def run(self, container_format, image_location, disk_format, - visibility="private", min_disk=0, min_ram=0): + visibility="private", min_disk=0, min_ram=0, properties=None): """Create and get detailed information of an image. :param container_format: container format of image. Acceptable @@ -112,6 +115,8 @@ class CreateAndGetImage(GlanceBasic): :param visibility: The access permission for the created image :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: A dict of image metadata properties to set + on the image """ image = self.glance.create_image( container_format=container_format, @@ -119,7 +124,8 @@ class CreateAndGetImage(GlanceBasic): disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) self.assertTrue(image) image_info = self.glance.get_image(image) self.assertEqual(image.id, image_info.id) @@ -159,7 +165,7 @@ class ListImages(GlanceBasic): class CreateAndDeleteImage(GlanceBasic): def run(self, container_format, image_location, disk_format, - visibility="private", min_disk=0, min_ram=0): + visibility="private", min_disk=0, min_ram=0, properties=None): """Create and then delete an image. :param container_format: container format of image. Acceptable @@ -170,6 +176,8 @@ class CreateAndDeleteImage(GlanceBasic): :param visibility: The access permission for the created image :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: A dict of image metadata properties to set + on the image """ image = self.glance.create_image( container_format=container_format, @@ -177,7 +185,8 @@ class CreateAndDeleteImage(GlanceBasic): disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) self.glance.delete_image(image.id) @@ -201,7 +210,7 @@ class CreateImageAndBootInstances(GlanceBasic, nova_utils.NovaScenario): def run(self, container_format, image_location, disk_format, flavor, number_instances, visibility="private", min_disk=0, - min_ram=0, boot_server_kwargs=None, **kwargs): + min_ram=0, properties=None, boot_server_kwargs=None, **kwargs): """Create an image and boot several instances from it. :param container_format: container format of image. Acceptable @@ -212,9 +221,10 @@ class CreateImageAndBootInstances(GlanceBasic, nova_utils.NovaScenario): :param visibility: The access permission for the created image :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: A dict of image metadata properties to set + on the image :param flavor: Nova flavor to be used to launch an instance :param number_instances: number of Nova servers to boot - :param create_image_kwargs: optional parameters to create image :param boot_server_kwargs: optional parameters to boot server :param kwargs: optional parameters to create server (deprecated) """ @@ -231,7 +241,8 @@ class CreateImageAndBootInstances(GlanceBasic, nova_utils.NovaScenario): disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) self._boot_servers(image.id, flavor, number_instances, **boot_server_kwargs) @@ -253,7 +264,8 @@ class CreateAndUpdateImage(GlanceBasic): def run(self, container_format, image_location, disk_format, remove_props=None, visibility="private", create_min_disk=0, - create_min_ram=0, update_min_disk=0, update_min_ram=0): + create_min_ram=0, create_properties=None, + update_min_disk=0, update_min_ram=0): """Create an image then update it. Measure the "glance image-create" and "glance image-update" commands @@ -269,6 +281,8 @@ class CreateAndUpdateImage(GlanceBasic): :param visibility: The access permission for the created image :param create_min_disk: The min disk of created images :param create_min_ram: The min ram of created images + :param create_properties: A dict of image metadata properties to set + on the created image :param update_min_disk: The min disk of updated images :param update_min_ram: The min ram of updated images """ @@ -278,7 +292,8 @@ class CreateAndUpdateImage(GlanceBasic): disk_format=disk_format, visibility=visibility, min_disk=create_min_disk, - min_ram=create_min_ram) + min_ram=create_min_ram, + properties=create_properties) self.glance.update_image(image.id, min_disk=update_min_disk, diff --git a/rally/plugins/openstack/services/image/glance_v1.py b/rally/plugins/openstack/services/image/glance_v1.py index 03aa6a1434..1f234045a8 100644 --- a/rally/plugins/openstack/services/image/glance_v1.py +++ b/rally/plugins/openstack/services/image/glance_v1.py @@ -32,7 +32,8 @@ class GlanceV1Service(service.Service, glance_common.GlanceMixin): @atomic.action_timer("glance_v1.create_image") def create_image(self, image_name=None, container_format=None, image_location=None, disk_format=None, - is_public=True, min_disk=0, min_ram=0): + is_public=True, min_disk=0, min_ram=0, + properties=None): """Creates new image. :param image_name: Image name for which need to be created @@ -42,6 +43,7 @@ class GlanceV1Service(service.Service, glance_common.GlanceMixin): :param is_public: The created image's public status :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: Dict of image properties """ image_location = os.path.expanduser(image_location) image_name = image_name or self.generate_random_name() @@ -60,6 +62,7 @@ class GlanceV1Service(service.Service, glance_common.GlanceMixin): is_public=is_public, min_disk=min_disk, min_ram=min_ram, + properties=properties, **kwargs) rutils.interruptable_sleep(CONF.benchmark. @@ -134,7 +137,7 @@ class UnifiedGlanceV1Service(glance_common.UnifiedGlanceMixin, image.Image): def create_image(self, image_name=None, container_format=None, image_location=None, disk_format=None, visibility="public", min_disk=0, - min_ram=0): + min_ram=0, properties=None): """Creates new image. :param image_name: Image name for which need to be created @@ -144,6 +147,7 @@ class UnifiedGlanceV1Service(glance_common.UnifiedGlanceMixin, image.Image): :param visibility: The created image's visible status :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: Dict of image properties """ self._check_v1_visibility(visibility) @@ -155,7 +159,8 @@ class UnifiedGlanceV1Service(glance_common.UnifiedGlanceMixin, image.Image): disk_format=disk_format, is_public=is_public, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) return self._unify_image(image_obj) def update_image(self, image_id, image_name=None, min_disk=0, diff --git a/rally/plugins/openstack/services/image/glance_v2.py b/rally/plugins/openstack/services/image/glance_v2.py index afe1be8cd3..fbdedda1fe 100644 --- a/rally/plugins/openstack/services/image/glance_v2.py +++ b/rally/plugins/openstack/services/image/glance_v2.py @@ -35,7 +35,7 @@ class GlanceV2Service(service.Service, glance_common.GlanceMixin): def create_image(self, image_name=None, container_format=None, image_location=None, disk_format=None, visibility=None, min_disk=0, - min_ram=0): + min_ram=0, properties=None): """Creates new image. :param image_name: Image name for which need to be created @@ -45,16 +45,19 @@ class GlanceV2Service(service.Service, glance_common.GlanceMixin): :param visibility: The created image's visible status. :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: Dict of image properties """ image_name = image_name or self.generate_random_name() + properties = properties or {} image_obj = self._clients.glance("2").images.create( name=image_name, container_format=container_format, disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + **properties) image_location = os.path.expanduser(image_location) rutils.interruptable_sleep(CONF.benchmark. @@ -153,7 +156,7 @@ class UnifiedGlanceV2Service(glance_common.UnifiedGlanceMixin, image.Image): def create_image(self, image_name=None, container_format=None, image_location=None, disk_format=None, visibility=None, min_disk=0, - min_ram=0): + min_ram=0, properties=None): """Creates new image. :param image_name: Image name for which need to be created @@ -163,6 +166,7 @@ class UnifiedGlanceV2Service(glance_common.UnifiedGlanceMixin, image.Image): :param visibility: The access permission for the created image. :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: Dict of image properties """ image_obj = self._impl.create_image( image_name=image_name, @@ -171,7 +175,8 @@ class UnifiedGlanceV2Service(glance_common.UnifiedGlanceMixin, image.Image): disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) return self._unify_image(image_obj) def update_image(self, image_id, image_name=None, min_disk=0, diff --git a/rally/plugins/openstack/services/image/image.py b/rally/plugins/openstack/services/image/image.py index 8a30e0bf2e..6a5ddd60ac 100644 --- a/rally/plugins/openstack/services/image/image.py +++ b/rally/plugins/openstack/services/image/image.py @@ -48,7 +48,7 @@ class Image(service.UnifiedService): def create_image(self, image_name=None, container_format=None, image_location=None, disk_format=None, visibility="private", min_disk=0, - min_ram=0): + min_ram=0, properties=None): """Creates new image. :param image_name: Image name for which need to be created @@ -58,7 +58,9 @@ class Image(service.UnifiedService): :param visibility: The access permission for the created image. :param min_disk: The min disk of created images :param min_ram: The min ram of created images + :param properties: Dict of image properties """ + properties = properties or {} image = self._impl.create_image( image_name=image_name, container_format=container_format, @@ -66,7 +68,8 @@ class Image(service.UnifiedService): disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) return image @service.should_be_overridden diff --git a/tests/unit/plugins/openstack/scenarios/glance/test_images.py b/tests/unit/plugins/openstack/scenarios/glance/test_images.py index 28c28248cd..17ef792fa8 100644 --- a/tests/unit/plugins/openstack/scenarios/glance/test_images.py +++ b/tests/unit/plugins/openstack/scenarios/glance/test_images.py @@ -56,22 +56,24 @@ class GlanceBasicTestCase(test.ScenarioTestCase): mock.Mock(id=0, name="img_1"), fake_image, mock.Mock(id=2, name="img_3")] + properties = {"fakeprop": "fake"} call_args = {"container_format": "cf", "image_location": "url", "disk_format": "df", "visibility": "vs", "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} # Positive case images.CreateAndListImage(self.context).run( - "cf", "url", "df", "vs", 0, 0) + "cf", "url", "df", "vs", 0, 0, properties) image_service.create_image.assert_called_once_with(**call_args) # Negative case: image isn't created image_service.create_image.return_value = None self.assertRaises(exceptions.RallyAssertionError, images.CreateAndListImage(self.context).run, - "cf", "url", "df", "vs", 0, 0) + "cf", "url", "df", "vs", 0, 0, properties) image_service.create_image.assert_called_with(**call_args) # Negative case: created image n ot in the list of available images @@ -79,7 +81,7 @@ class GlanceBasicTestCase(test.ScenarioTestCase): id=12, name="img_nameN") self.assertRaises(exceptions.RallyAssertionError, images.CreateAndListImage(self.context).run, - "cf", "url", "df", "vs", 0, 0) + "cf", "url", "df", "vs", 0, 0, properties) image_service.create_image.assert_called_with(**call_args) image_service.list_images.assert_called_with() @@ -94,15 +96,17 @@ class GlanceBasicTestCase(test.ScenarioTestCase): fake_image = fakes.FakeImage(id=1, name="imagexxx") image_service.create_image.return_value = fake_image + properties = {"fakeprop": "fake"} call_args = {"container_format": "cf", "image_location": "url", "disk_format": "df", "visibility": "vs", "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} images.CreateAndDeleteImage(self.context).run( - "cf", "url", "df", "vs", 0, 0) + "cf", "url", "df", "vs", 0, 0, properties) image_service.create_image.assert_called_once_with(**call_args) image_service.delete_image.assert_called_once_with(fake_image.id) @@ -115,16 +119,18 @@ class GlanceBasicTestCase(test.ScenarioTestCase): fake_image_info = fakes.FakeImage(id=1, name="img_name1", status="active") image_service.get_image.return_value = fake_image_info + properties = {"fakeprop": "fake"} call_args = {"container_format": "cf", "image_location": "url", "disk_format": "df", "visibility": "vs", "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} # Positive case images.CreateAndGetImage(self.context).run( - "cf", "url", "df", "vs", 0, 0) + "cf", "url", "df", "vs", 0, 0, properties) image_service.create_image.assert_called_once_with(**call_args) image_service.get_image.assert_called_once_with(fake_image) @@ -133,7 +139,7 @@ class GlanceBasicTestCase(test.ScenarioTestCase): image_service.create_image.return_value = None self.assertRaises(exceptions.RallyAssertionError, images.CreateAndGetImage(self.context).run, - "cf", "url", "df", "vs", 0, 0) + "cf", "url", "df", "vs", 0, 0, properties) image_service.create_image.assert_called_with(**call_args) # Negative case: image obtained in _get_image not the created image @@ -143,7 +149,7 @@ class GlanceBasicTestCase(test.ScenarioTestCase): id=12, name="img_nameN") self.assertRaises(exceptions.RallyAssertionError, images.CreateAndGetImage(self.context).run, - "cf", "url", "df", "vs", 0, 0) + "cf", "url", "df", "vs", 0, 0, properties) image_service.create_image.assert_called_with(**call_args) image_service.get_image.assert_called_with( image_service.create_image.return_value) @@ -157,15 +163,18 @@ class GlanceBasicTestCase(test.ScenarioTestCase): image_service.create_image.return_value = fake_image mock_boot_servers.return_value = fake_servers boot_server_kwargs = {"fakeserverarg": "f"} + properties = {"fakeprop": "fake"} call_args = {"container_format": "cf", "image_location": "url", "disk_format": "df", "visibility": "vs", "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} images.CreateImageAndBootInstances(self.context).run( - "cf", "url", "df", "fid", 5, "vs", 0, 0, + "cf", "url", "df", "fid", 5, visibility="vs", min_disk=0, + min_ram=0, properties=properties, boot_server_kwargs=boot_server_kwargs) image_service.create_image.assert_called_once_with(**call_args) mock_boot_servers.assert_called_once_with("image-id-0", "fid", @@ -176,15 +185,17 @@ class GlanceBasicTestCase(test.ScenarioTestCase): fake_image = fakes.FakeImage(id=1, name="imagexxx") image_service.create_image.return_value = fake_image + properties = {"fakeprop": "fake"} create_args = {"container_format": "cf", "image_location": "url", "disk_format": "df", "visibility": "vs", "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} images.CreateAndUpdateImage(self.context).run( - "cf", "url", "df", None, "vs", 0, 0, 0, 0) + "cf", "url", "df", None, "vs", 0, 0, properties, 0, 0) image_service.create_image.assert_called_once_with(**create_args) image_service.update_image.assert_called_once_with( diff --git a/tests/unit/plugins/openstack/services/image/test_glance_v1.py b/tests/unit/plugins/openstack/services/image/test_glance_v1.py index 2de460b04f..ca68c8a363 100755 --- a/tests/unit/plugins/openstack/services/image/test_glance_v1.py +++ b/tests/unit/plugins/openstack/services/image/test_glance_v1.py @@ -50,20 +50,23 @@ class GlanceV1ServiceTestCase(test.TestCase): image_name = "image_name" container_format = "container_format" disk_format = "disk_format" + properties = {"fakeprop": "fake"} image = self.service.create_image( image_name=image_name, container_format=container_format, image_location=location, disk_format=disk_format, - is_public=is_public) + is_public=is_public, + properties=properties) call_args = {"container_format": container_format, "disk_format": disk_format, "is_public": is_public, "name": image_name, "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} if location.startswith("/"): call_args["data"] = mock_open.return_value @@ -141,11 +144,14 @@ class UnifiedGlanceV1ServiceTestCase(test.TestCase): container_format = "container_format" image_location = "image_location" disk_format = "disk_format" + properties = {"fakeprop": "fake"} + image = self.service.create_image(image_name=image_name, container_format=container_format, image_location=image_location, disk_format=disk_format, - visibility=visibility) + visibility=visibility, + properties=properties) is_public = visibility == "public" callargs = {"image_name": image_name, @@ -154,7 +160,8 @@ class UnifiedGlanceV1ServiceTestCase(test.TestCase): "disk_format": disk_format, "is_public": is_public, "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} self.service._impl.create_image.assert_called_once_with(**callargs) self.assertEqual(mock_image__unify_image.return_value, image) diff --git a/tests/unit/plugins/openstack/services/image/test_glance_v2.py b/tests/unit/plugins/openstack/services/image/test_glance_v2.py index fea700a5a1..0db4d56e16 100755 --- a/tests/unit/plugins/openstack/services/image/test_glance_v2.py +++ b/tests/unit/plugins/openstack/services/image/test_glance_v2.py @@ -51,20 +51,23 @@ class GlanceV2ServiceTestCase(test.TestCase): container_format = "container_format" disk_format = "disk_format" visibility = "public" + properties = {"fakeprop": "fake"} image = self.service.create_image( image_name=image_name, container_format=container_format, image_location=location, disk_format=disk_format, - visibility=visibility) + visibility=visibility, + properties=properties) call_args = {"container_format": container_format, "disk_format": disk_format, "name": image_name, "visibility": visibility, "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "fakeprop": "fake"} if location.startswith("/"): mock_open.assert_called_once_with(location) @@ -143,19 +146,22 @@ class UnifiedGlanceV2ServiceTestCase(test.TestCase): image_location = "image_location" disk_format = "disk_format" visibility = "public" + properties = {"fakeprop": "fake"} callargs = {"image_name": image_name, "container_format": container_format, "image_location": image_location, "disk_format": disk_format, "visibility": visibility, "min_disk": 0, - "min_ram": 0} + "min_ram": 0, + "properties": properties} image = self.service.create_image(image_name=image_name, container_format=container_format, image_location=image_location, disk_format=disk_format, - visibility=visibility) + visibility=visibility, + properties=properties) self.assertEqual(mock_image__unify_image.return_value, image) self.service._impl.create_image.assert_called_once_with(**callargs) diff --git a/tests/unit/plugins/openstack/services/image/test_image.py b/tests/unit/plugins/openstack/services/image/test_image.py index e6b08d5e2f..c14020cdad 100755 --- a/tests/unit/plugins/openstack/services/image/test_image.py +++ b/tests/unit/plugins/openstack/services/image/test_image.py @@ -41,17 +41,22 @@ class ImageTestCase(test.TestCase): (image_name, container_format, image_location, disk_format, visibility, min_disk, min_ram) = params service = self.get_service_with_fake_impl() + properties = {"fakeprop": "fake"} + service.create_image(image_name=image_name, container_format=container_format, image_location=image_location, disk_format=disk_format, visibility=visibility, min_disk=min_disk, - min_ram=min_ram) + min_ram=min_ram, + properties=properties) + service._impl.create_image.assert_called_once_with( image_name=image_name, container_format=container_format, image_location=image_location, disk_format=disk_format, - visibility=visibility, min_disk=min_disk, min_ram=min_ram) + visibility=visibility, min_disk=min_disk, min_ram=min_ram, + properties=properties) @ddt.data(("image_id", "image_name", "min_disk", "min_ram", "remove_props"))