diff --git a/rally-jobs/rally-keystone-api-v2.yaml b/rally-jobs/rally-keystone-api-v2.yaml index 3a526835..1ea177d1 100644 --- a/rally-jobs/rally-keystone-api-v2.yaml +++ b/rally-jobs/rally-keystone-api-v2.yaml @@ -438,6 +438,27 @@ failure_rate: max: 0 + GlanceImages.create_and_get_image: + - + args: + image_location: "{{ cirros_image_url }}" + container_format: "bare" + disk_format: "qcow2" + runner: + type: "constant" + times: 4 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + api_versions: + glance: + version: 2 + sla: + failure_rate: + max: 0 + GlanceImages.create_and_delete_image: - args: diff --git a/rally-jobs/rally.yaml b/rally-jobs/rally.yaml index fd42d526..f9d71c5c 100644 --- a/rally-jobs/rally.yaml +++ b/rally-jobs/rally.yaml @@ -453,6 +453,27 @@ failure_rate: max: 0 + GlanceImages.create_and_get_image: + - + args: + image_location: "{{ cirros_image_url }}" + container_format: "bare" + disk_format: "qcow2" + runner: + type: "constant" + times: 4 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + api_versions: + glance: + version: 2 + sla: + failure_rate: + max: 0 + GlanceImages.create_and_delete_image: # - # args: diff --git a/rally/plugins/openstack/scenarios/glance/images.py b/rally/plugins/openstack/scenarios/glance/images.py index 7a09b8f3..d88ee7c8 100644 --- a/rally/plugins/openstack/scenarios/glance/images.py +++ b/rally/plugins/openstack/scenarios/glance/images.py @@ -76,6 +76,39 @@ class CreateAndListImage(GlanceBasic): self.assertIn(image.id, [i.id for i in image_list]) +@types.convert(image_location={"type": "path_or_url"}, + kwargs={"type": "glance_image_args"}) +@validation.required_services(consts.Service.GLANCE) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(context={"cleanup": ["glance"]}, + name="GlanceImages.create_and_get_image") +class CreateAndGetImage(GlanceBasic): + + def run(self, container_format, image_location, disk_format, + visibility="private", min_disk=0, min_ram=0): + """Create and get detailed information of an image. + + :param container_format: container format of image. Acceptable + formats: ami, ari, aki, bare, and ovf + :param image_location: image file location + :param disk_format: disk format of image. Acceptable formats: + ami, ari, aki, vhd, vmdk, raw, qcow2, vdi, and iso + :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 + """ + image = self.glance.create_image( + container_format=container_format, + image_location=image_location, + disk_format=disk_format, + visibility=visibility, + min_disk=min_disk, + min_ram=min_ram) + self.assertTrue(image) + image_info = self.glance.get_image(image) + self.assertEqual(image.id, image_info.id) + + @validation.required_services(consts.Service.GLANCE) @validation.add("required_platform", platform="openstack", users=True) @scenario.configure(context={"cleanup": ["glance"]}, diff --git a/samples/tasks/scenarios/glance/create-and-get-image.json b/samples/tasks/scenarios/glance/create-and-get-image.json new file mode 100644 index 00000000..76d3bcdd --- /dev/null +++ b/samples/tasks/scenarios/glance/create-and-get-image.json @@ -0,0 +1,27 @@ +{ + "GlanceImages.create_and_get_image": [ + { + "args": { + "image_location": "http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img", + "container_format": "bare", + "disk_format": "qcow2" + }, + "runner": { + "type": "constant", + "times": 4, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/glance/create-and-get-image.yaml b/samples/tasks/scenarios/glance/create-and-get-image.yaml new file mode 100644 index 00000000..6d189db5 --- /dev/null +++ b/samples/tasks/scenarios/glance/create-and-get-image.yaml @@ -0,0 +1,18 @@ +--- + GlanceImages.create_and_get_image: + - + args: + image_location: "http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img" + container_format: "bare" + disk_format: "qcow2" + runner: + type: "constant" + times: 4 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 diff --git a/tests/unit/plugins/openstack/scenarios/glance/test_images.py b/tests/unit/plugins/openstack/scenarios/glance/test_images.py index 8acfe5ca..17e0eb08 100644 --- a/tests/unit/plugins/openstack/scenarios/glance/test_images.py +++ b/tests/unit/plugins/openstack/scenarios/glance/test_images.py @@ -104,6 +104,47 @@ class GlanceBasicTestCase(test.ScenarioTestCase): image_service.create_image.assert_called_once_with(**call_args) image_service.delete_image.assert_called_once_with(fake_image.id) + def test_create_and_get_image(self): + image_service = self.mock_image.return_value + + fake_image = fakes.FakeImage(id=1, name="img_name1") + image_service.create_image.return_value = fake_image + fake_image_info = fakes.FakeImage(id=1, name="img_name1", + status="active") + image_service.get_image.return_value = fake_image_info + call_args = {"container_format": "cf", + "image_location": "url", + "disk_format": "df", + "visibility": "vs", + "min_disk": 0, + "min_ram": 0} + + # Positive case + images.CreateAndGetImage(self.context).run( + "cf", "url", "df", "vs", 0, 0) + image_service.create_image.assert_called_once_with(**call_args) + image_service.get_image.assert_called_once_with(fake_image) + + # Negative case: image isn't created + image_service.create_image.reset_mock() + image_service.create_image.return_value = None + self.assertRaises(exceptions.RallyAssertionError, + images.CreateAndGetImage(self.context).run, + "cf", "url", "df", "vs", 0, 0) + image_service.create_image.assert_called_with(**call_args) + + # Negative case: image obtained in _get_image not the created image + image_service.create_image.reset_mock() + image_service.get_image.reset_mock() + image_service.create_image.return_value = fakes.FakeImage( + id=12, name="img_nameN") + self.assertRaises(exceptions.RallyAssertionError, + images.CreateAndGetImage(self.context).run, + "cf", "url", "df", "vs", 0, 0) + image_service.create_image.assert_called_with(**call_args) + image_service.get_image.assert_called_with( + image_service.create_image.return_value) + @mock.patch("%s.CreateImageAndBootInstances._boot_servers" % BASE) def test_create_image_and_boot_instances(self, mock_boot_servers): image_service = self.mock_image.return_value