Delete only images created by images context

Since the images context allows creating images with arbitrary names,
name-based cleanup won't work for it, so we have to delete the exact
list of images that it created instead.

Implements: blueprint cleanup-refactoring
Change-Id: I3caa0e73a124bb1317492262ea45cd2a4d116721
This commit is contained in:
Chris St. Pierre 2016-03-15 08:56:58 -05:00
parent 81ae39a03b
commit c7c8f577c5
2 changed files with 73 additions and 33 deletions

View File

@ -16,8 +16,8 @@ from rally.common.i18n import _
from rally.common import logging
from rally.common import utils as rutils
from rally import consts
from rally.plugins.openstack.cleanup import manager as resource_manager
from rally.plugins.openstack.scenarios.glance import utils as glance_utils
from rally import osclients
from rally.plugins.openstack.wrappers import glance as glance_wrapper
from rally.task import context
@ -78,10 +78,10 @@ class ImageGenerator(context.Context):
for user, tenant_id in rutils.iterate_per_tenants(
self.context["users"]):
current_images = []
glance_scenario = glance_utils.GlanceScenario(
{"user": user, "task":
self.context["task"],
"config": self.context["config"]})
clients = osclients.Clients(
user["credential"],
api_info=self.context["config"].get("api_versions"))
glance_wrap = glance_wrapper.wrap(clients.glance, self)
kwargs = self.config.get("image_args", {})
if self.config.get("min_ram") is not None:
@ -101,7 +101,7 @@ class ImageGenerator(context.Context):
else:
cur_name = self.generate_random_name()
image = glance_scenario._create_image(
image = glance_wrap.create_image(
image_container, image_url, image_type,
name=cur_name, **kwargs)
current_images.append(image.id)
@ -110,6 +110,11 @@ class ImageGenerator(context.Context):
@logging.log_task_wrapper(LOG.info, _("Exit context: `Images`"))
def cleanup(self):
# TODO(boris-42): Delete only resources created by this context
resource_manager.cleanup(names=["glance.images"],
users=self.context.get("users", []))
for user, tenant_id in rutils.iterate_per_tenants(
self.context["users"]):
clients = osclients.Clients(
user["credential"],
api_info=self.context["config"].get("api_versions"))
glance_wrap = glance_wrapper.wrap(clients.glance, self)
for image in self.context["tenants"][tenant_id].get("images", []):
glance_wrap.delete_image(glance_wrap.get_image(image))

View File

@ -50,15 +50,17 @@ class ImageGeneratorTestCase(test.ScenarioTestCase):
{"min_disk": 1, "min_ram": 2},
{"image_name": "foo"},
{"tenants": 3, "users_per_tenant": 2, "images_per_tenant": 5},
{"image_args": {"min_disk": 1, "min_ram": 2, "visibility": "public"}})
{"image_args": {"min_disk": 1, "min_ram": 2, "visibility": "public"}},
{"api_versions": {"glance": {"version": 2, "service_type": "image"}}})
@ddt.unpack
@mock.patch("%s.utils.GlanceScenario._create_image" % SCN)
def test_setup(self, mock_glance_scenario__create_image,
@mock.patch("rally.plugins.openstack.wrappers.glance.wrap")
@mock.patch("rally.osclients.Clients")
def test_setup(self, mock_clients, mock_wrap,
image_container="bare", image_type="qcow2",
image_url="http://example.com/fake/url",
tenants=1, users_per_tenant=1, images_per_tenant=1,
image_name=None, min_ram=None, min_disk=None,
image_args=None):
image_args=None, api_versions=None):
tenant_data = self._gen_tenants(tenants)
users = []
for tenant_id in tenant_data:
@ -86,6 +88,8 @@ class ImageGeneratorTestCase(test.ScenarioTestCase):
"users": users,
"tenants": tenant_data
})
if api_versions:
self.context["config"]["api_versions"] = api_versions
expected_image_args = {}
if image_args is not None:
@ -100,52 +104,70 @@ class ImageGeneratorTestCase(test.ScenarioTestCase):
self.context["config"]["images"]["min_disk"] = min_disk
expected_image_args["min_disk"] = min_disk
wrapper = mock_wrap.return_value
new_context = copy.deepcopy(self.context)
for tenant_id in new_context["tenants"].keys():
new_context["tenants"][tenant_id]["images"] = [
mock_glance_scenario__create_image.return_value.id
wrapper.create_image.return_value.id
] * images_per_tenant
images_ctx = images.ImageGenerator(self.context)
images_ctx.setup()
self.assertEqual(new_context, self.context)
mock_glance_scenario__create_image.assert_has_calls(
[mock.call(image_container, image_url, image_type,
name=mock.ANY,
**expected_image_args)] * tenants * images_per_tenant)
wrapper_calls = []
wrapper_calls.extend([mock.call(mock_clients.return_value.glance,
images_ctx)] * tenants)
wrapper_calls.extend(
[mock.call().create_image(
image_container, image_url, image_type,
name=mock.ANY, **expected_image_args)] *
tenants * images_per_tenant)
mock_wrap.assert_has_calls(wrapper_calls, any_order=True)
if image_name:
for args in mock_glance_scenario__create_image.call_args_list:
for args in wrapper.create_image.call_args_list:
self.assertTrue(args[1]["name"].startswith(image_name))
mock_clients.assert_has_calls(
[mock.call(mock.ANY, api_info=api_versions)] * tenants)
@mock.patch("%s.images.resource_manager.cleanup" % CTX)
def test_cleanup(self, mock_cleanup):
@ddt.data(
{},
{"api_versions": {"glance": {"version": 2, "service_type": "image"}}})
@ddt.unpack
@mock.patch("rally.plugins.openstack.wrappers.glance.wrap")
@mock.patch("rally.osclients.Clients")
def test_cleanup(self, mock_clients, mock_wrap, api_versions=None):
tenants_count = 2
users_per_tenant = 5
images_per_tenant = 5
tenants = self._gen_tenants(tenants_count)
users = []
for id_ in tenants:
created_images = []
for tenant_id in tenants:
for i in range(users_per_tenant):
users.append({"id": i, "tenant_id": id_,
"credential": "credential"})
tenants[id_].setdefault("images", [])
users.append({"id": i, "tenant_id": tenant_id,
"credential": mock.MagicMock()})
tenants[tenant_id].setdefault("images", [])
for j in range(images_per_tenant):
tenants[id_]["images"].append("uuid")
image = mock.Mock()
created_images.append(image)
tenants[tenant_id]["images"].append(image)
self.context.update({
"config": {
"users": {
"tenants": 2,
"users_per_tenant": 5,
"tenants": tenants_count,
"users_per_tenant": users_per_tenant,
"concurrent": 10,
},
"images": {
"image_url": "mock_url",
"image_type": "qcow2",
"image_container": "bare",
"images_per_tenant": 5,
"images_per_tenant": images_per_tenant,
"image_name": "some_name",
"min_ram": 128,
"min_disk": 1,
@ -157,8 +179,21 @@ class ImageGeneratorTestCase(test.ScenarioTestCase):
"users": users,
"tenants": tenants
})
if api_versions:
self.context["config"]["api_versions"] = api_versions
images_ctx = images.ImageGenerator(self.context)
images_ctx.cleanup()
mock_cleanup.assert_called_once_with(names=["glance.images"],
users=self.context["users"])
wrapper = mock_wrap.return_value
wrapper_calls = []
wrapper_calls.extend([mock.call(mock_clients.return_value.glance,
images_ctx)] * tenants_count)
wrapper_calls.extend([mock.call().get_image(i)
for i in created_images])
wrapper_calls.extend(
[mock.call().delete_image(wrapper.get_image.return_value)] *
len(created_images))
mock_wrap.assert_has_calls(wrapper_calls, any_order=True)
mock_clients.assert_has_calls(
[mock.call(mock.ANY, api_info=api_versions)] * tenants_count)