Merge "Add GlanceImages.create_and_deactivate_image"

This commit is contained in:
Jenkins 2017-08-13 14:46:59 +00:00 committed by Gerrit Code Review
commit ef1b52e1ff
9 changed files with 168 additions and 5 deletions

View File

@ -623,6 +623,24 @@
failure_rate: failure_rate:
max: 100 max: 100
GlanceImages.create_and_deactivate_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
sla:
failure_rate:
max: 100
SwiftObjects.create_container_and_object_then_list_objects: SwiftObjects.create_container_and_object_then_list_objects:
- -
args: args:

View File

@ -23,6 +23,7 @@ from rally.common import logging
from rally import consts from rally import consts
from rally.plugins.openstack.cleanup import base from rally.plugins.openstack.cleanup import base
from rally.plugins.openstack.services.identity import identity from rally.plugins.openstack.services.identity import identity
from rally.plugins.openstack.services.image import glance_v2
from rally.plugins.openstack.services.image import image from rally.plugins.openstack.services.image import image
from rally.task import utils as task_utils from rally.task import utils as task_utils
@ -587,10 +588,16 @@ class GlanceImage(base.ResourceManager):
return image.Image(self.admin or self.user) return image.Image(self.admin or self.user)
def list(self): def list(self):
return self._client().list_images(owner=self.tenant_uuid) images = (self._client().list_images(owner=self.tenant_uuid) +
self._client().list_images(status="deactivated",
owner=self.tenant_uuid))
return images
def delete(self): def delete(self):
client = self._client() client = self._client()
if self.raw_resource.status == "deactivated":
glancev2 = glance_v2.GlanceV2Service(self.admin or self.user)
glancev2.reactivate_image(self.raw_resource.id)
client.delete_image(self.raw_resource.id) client.delete_image(self.raw_resource.id)
task_utils.wait_for_status( task_utils.wait_for_status(
self.raw_resource, ["deleted"], self.raw_resource, ["deleted"],

View File

@ -17,6 +17,7 @@ from rally.common import logging
from rally import consts from rally import consts
from rally.plugins.openstack import scenario from rally.plugins.openstack import scenario
from rally.plugins.openstack.scenarios.nova import utils as nova_utils from rally.plugins.openstack.scenarios.nova import utils as nova_utils
from rally.plugins.openstack.services.image import glance_v2
from rally.plugins.openstack.services.image import image from rally.plugins.openstack.services.image import image
from rally.task import types from rally.task import types
from rally.task import validation from rally.task import validation
@ -299,3 +300,37 @@ class CreateAndUpdateImage(GlanceBasic):
min_disk=update_min_disk, min_disk=update_min_disk,
min_ram=update_min_ram, min_ram=update_min_ram,
remove_props=remove_props) remove_props=remove_props)
@validation.add("required_services", services=(consts.Service.GLANCE, ))
@validation.add("required_platform", platform="openstack", users=True)
@validation.add("required_api_versions", component="glance", versions=["2"])
@scenario.configure(context={"cleanup": ["glance"]},
name="GlanceImages.create_and_deactivate_image",
platform="openstack")
class CreateAndDeactivateImage(GlanceBasic):
def run(self, container_format, image_location, disk_format,
visibility="private", min_disk=0, min_ram=0):
"""Create an image, then deactivate it.
: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
"""
service = glance_v2.GlanceV2Service(self._clients,
self.generate_random_name,
atomic_inst=self.atomic_actions())
image = service.create_image(
container_format=container_format,
image_location=image_location,
disk_format=disk_format,
visibility=visibility,
min_disk=min_disk,
min_ram=min_ram)
service.deactivate_image(image.id)

View File

@ -140,6 +140,16 @@ class GlanceV2Service(service.Service, glance_common.GlanceMixin):
self._clients.glance("2").images.update(image_id, self._clients.glance("2").images.update(image_id,
visibility=visibility) visibility=visibility)
@atomic.action_timer("glance_v2.deactivate_image")
def deactivate_image(self, image_id):
"""deactivate image."""
self._clients.glance("2").images.deactivate(image_id)
@atomic.action_timer("glance_v2.reactivate_image")
def reactivate_image(self, image_id):
"""reactivate image."""
self._clients.glance("2").images.reactivate(image_id)
@service.compat_layer(GlanceV2Service) @service.compat_layer(GlanceV2Service)
class UnifiedGlanceV2Service(glance_common.UnifiedGlanceMixin, image.Image): class UnifiedGlanceV2Service(glance_common.UnifiedGlanceMixin, image.Image):

View File

@ -0,0 +1,22 @@
{
"GlanceImages.create_and_deactivate_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": 10,
"concurrency": 1
},
"context": {
"users": {
"tenants": 1,
"users_per_tenant": 1
}
}
}
]
}

View File

@ -0,0 +1,15 @@
---
GlanceImages.create_and_deactivate_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: 10
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1

View File

@ -27,6 +27,8 @@ from rally.plugins.openstack.cleanup import resources
from tests.unit import test from tests.unit import test
BASE = "rally.plugins.openstack.cleanup.resources" BASE = "rally.plugins.openstack.cleanup.resources"
GLANCE_V2_PATH = ("rally.plugins.openstack.services.image.glance_v2."
"GlanceV2Service")
class SynchronizedDeletionTestCase(test.TestCase): class SynchronizedDeletionTestCase(test.TestCase):
@ -624,12 +626,18 @@ class GlanceImageTestCase(test.TestCase):
def test_list(self): def test_list(self):
glance = resources.GlanceImage() glance = resources.GlanceImage()
glance._client = mock.Mock() glance._client = mock.Mock()
list_images = glance._client.return_value.list_images
list_images.side_effect = (
["active-image1", "active-image2"],
["deactivated-image1"])
glance.tenant_uuid = mock.Mock() glance.tenant_uuid = mock.Mock()
self.assertEqual(glance.list(), self.assertEqual(
glance._client.return_value.list_images.return_value) glance.list(),
glance._client.return_value.list_images.assert_called_once_with( ["active-image1", "active-image2", "deactivated-image1"])
owner=glance.tenant_uuid) list_images.assert_has_calls([
mock.call(owner=glance.tenant_uuid),
mock.call(status="deactivated", owner=glance.tenant_uuid)])
def test_delete(self): def test_delete(self):
glance = resources.GlanceImage() glance = resources.GlanceImage()
@ -644,6 +652,24 @@ class GlanceImageTestCase(test.TestCase):
glance.delete() glance.delete()
client.delete_image.assert_called_once_with(glance.raw_resource.id) client.delete_image.assert_called_once_with(glance.raw_resource.id)
self.assertFalse(client.reactivate_image.called)
@mock.patch("%s.reactivate_image" % GLANCE_V2_PATH)
def test_delete_deactivated_image(self, mock_reactivate_image):
glance = resources.GlanceImage()
glance._client = mock.Mock()
glance._wrapper = mock.Mock()
glance.raw_resource = mock.Mock(status="deactivated")
client = glance._client.return_value
deleted_image = mock.Mock(status="DELETED")
client.get_image.side_effect = [glance.raw_resource, deleted_image]
glance.delete()
mock_reactivate_image.assert_called_once_with(glance.raw_resource.id)
client.delete_image.assert_called_once_with(glance.raw_resource.id)
class CeilometerTestCase(test.TestCase): class CeilometerTestCase(test.TestCase):

View File

@ -21,6 +21,8 @@ from tests.unit import fakes
from tests.unit import test from tests.unit import test
BASE = "rally.plugins.openstack.scenarios.glance.images" BASE = "rally.plugins.openstack.scenarios.glance.images"
GLANCE_V2_PATH = ("rally.plugins.openstack.services.image.glance_v2."
"GlanceV2Service")
class GlanceBasicTestCase(test.ScenarioTestCase): class GlanceBasicTestCase(test.ScenarioTestCase):
@ -200,3 +202,21 @@ class GlanceBasicTestCase(test.ScenarioTestCase):
image_service.create_image.assert_called_once_with(**create_args) image_service.create_image.assert_called_once_with(**create_args)
image_service.update_image.assert_called_once_with( image_service.update_image.assert_called_once_with(
fake_image.id, min_disk=0, min_ram=0, remove_props=None) fake_image.id, min_disk=0, min_ram=0, remove_props=None)
@mock.patch("%s.create_image" % GLANCE_V2_PATH)
@mock.patch("%s.deactivate_image" % GLANCE_V2_PATH)
def test_create_and_deactivate_image(self, mock_deactivate_image,
mock_create_image):
fake_image = fakes.FakeImage(id=1, name="img_name1")
mock_create_image.return_value = fake_image
call_args = {"container_format": "cf",
"image_location": "url",
"disk_format": "df",
"visibility": "vs",
"min_disk": 0,
"min_ram": 0}
images.CreateAndDeactivateImage(self.context).run(
"cf", "url", "df", "vs", 0, 0)
mock_create_image.assert_called_once_with(**call_args)
mock_deactivate_image.assert_called_once_with(fake_image.id)

View File

@ -130,6 +130,16 @@ class GlanceV2ServiceTestCase(test.TestCase):
image_id, image_id,
visibility=visibility) visibility=visibility)
def test_deactivate_image(self):
image_id = "image_id"
self.service.deactivate_image(image_id)
self.gc.images.deactivate.assert_called_once_with(image_id)
def test_reactivate_image(self):
image_id = "image_id"
self.service.reactivate_image(image_id)
self.gc.images.reactivate.assert_called_once_with(image_id)
@ddt.ddt @ddt.ddt
class UnifiedGlanceV2ServiceTestCase(test.TestCase): class UnifiedGlanceV2ServiceTestCase(test.TestCase):