Merge "Refactor ImageGenerator and validation"

This commit is contained in:
Jenkins 2015-02-28 22:39:59 +00:00 committed by Gerrit Code Review
commit 8995027941
6 changed files with 163 additions and 38 deletions

View File

@ -894,6 +894,54 @@
failure_rate:
max: 0
-
args:
flavor:
name: "m1.tiny"
image:
name: "from_context_uploaded"
runner:
type: "constant"
times: 1
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1
images:
image_name: "from_context_uploaded"
image_url: "http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-disk.img"
image_type: "qcow2"
image_container: "bare"
images_per_tenant: 1
sla:
failure_rate:
max: 0
-
args:
flavor:
name: "m1.tiny"
image:
regex: "^from_context_uploaded$"
runner:
type: "constant"
times: 1
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1
images:
image_name: "from_context_uploaded"
image_url: "http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-disk.img"
image_type: "qcow2"
image_container: "bare"
images_per_tenant: 1
sla:
failure_rate:
max: 0
-
args:
flavor:

View File

@ -14,7 +14,6 @@
from rally.benchmark.context import base
from rally.benchmark.context.cleanup import manager as resource_manager
from rally.benchmark.scenarios import base as scenario_base
from rally.benchmark.scenarios.glance import utils as glance_utils
from rally.common.i18n import _
from rally.common import log as logging
@ -44,6 +43,17 @@ class ImageGenerator(base.Context):
"image_container": {
"type": "string",
},
"image_name": {
"type": "string",
},
"min_ram": { # megabytes
"type": "integer",
"minimum": 0
},
"min_disk": { # gigabytes
"type": "integer",
"minimum": 0
},
"images_per_tenant": {
"type": "integer",
"minimum": 1
@ -63,20 +73,27 @@ class ImageGenerator(base.Context):
image_type = self.config["image_type"]
image_container = self.config["image_container"]
images_per_tenant = self.config["images_per_tenant"]
image_name = self.config.get("image_name")
for user, tenant_id in rutils.iterate_per_tenants(
self.context["users"]):
current_images = []
clients = osclients.Clients(user["endpoint"])
glance_util_class = glance_utils.GlanceScenario(
clients=clients)
glance_scenario = glance_utils.GlanceScenario(
clients=clients)
for i in range(images_per_tenant):
rnd_name = scenario_base.Scenario._generate_random_name()
if image_name and i > 0:
cur_name = image_name + str(i)
elif image_name:
cur_name = image_name
else:
cur_name = glance_scenario._generate_random_name(
prefix="rally_ctx_image_")
image = glance_util_class._create_image(rnd_name,
image_container,
image_url,
image_type)
image = glance_scenario._create_image(
cur_name, image_container, image_url, image_type,
min_ram=self.config.get("min_ram", 0),
min_disk=self.config.get("min_disk", 0))
current_images.append(image.id)
self.context["tenants"][tenant_id]["images"] = current_images

View File

@ -16,6 +16,7 @@
import functools
import os
import re
from glanceclient import exc as glance_exc
from novaclient import exceptions as nova_exc
@ -151,17 +152,33 @@ def file_exists(config, clients, deployment, param_name, mode=os.R_OK):
def _get_validated_image(config, clients, param_name):
image_value = config.get("args", {}).get(param_name)
if not image_value:
msg = "Parameter %s is not specified." % param_name
image_context = config.get("context", {}).get("images", {})
image_args = config.get("args", {}).get(param_name)
image_ctx_name = image_context.get("image_name")
if not image_args:
msg = _("Parameter %s is not specified.") % param_name
return (ValidationResult(False, msg), None)
if "image_name" in image_context:
# NOTE(rvasilets) check string is "exactly equal to" a regex
# or image name from context equal to image name from args
if "regex" in image_args:
match = re.match(image_args.get("regex"), image_ctx_name)
if image_ctx_name == image_args.get("name") or (
"regex" in image_args and match):
image = {
"size": image_context.get("min_disk", 0),
"min_ram": image_context.get("min_ram", 0),
"min_disk": image_context.get("min_disk", 0)
}
return (ValidationResult(True), image)
try:
image_id = types.ImageResourceType.transform(
clients=clients, resource_config=image_value)
image = clients.glance().images.get(image=image_id)
clients=clients, resource_config=image_args)
image = clients.glance().images.get(image=image_id).to_dict()
return (ValidationResult(True), image)
except (glance_exc.HTTPNotFound, exceptions.InvalidScenarioArgument):
message = _("Image '%s' not found") % image_value
message = _("Image '%s' not found") % image_args
return (ValidationResult(False, message), None)
@ -240,20 +257,20 @@ def image_valid_on_flavor(config, clients, deployment, flavor_name,
if not valid_result.is_valid:
return valid_result
if flavor.ram < (image.min_ram or 0):
if flavor.ram < (image["min_ram"] or 0):
message = _("The memory size for flavor '%s' is too small "
"for requested image '%s'") % (flavor.id, image.id)
"for requested image '%s'") % (flavor.id, image["id"])
return ValidationResult(False, message)
if flavor.disk:
if (image.size or 0) > flavor.disk * (1024 ** 3):
if (image["size"] or 0) > flavor.disk * (1024 ** 3):
message = _("The disk size for flavor '%s' is too small "
"for requested image '%s'") % (flavor.id, image.id)
"for requested image '%s'") % (flavor.id, image["id"])
return ValidationResult(False, message)
if (image.min_disk or 0) > flavor.disk:
if (image["min_disk"] or 0) > flavor.disk:
message = _("The disk size for flavor '%s' is too small "
"for requested image '%s'") % (flavor.id, image.id)
"for requested image '%s'") % (flavor.id, image["id"])
return ValidationResult(False, message)

View File

@ -102,7 +102,7 @@ def print_list(objs, fields, formatters=None, sortby_index=0,
if len(field_labels) != len(fields):
raise ValueError(_("Field labels list %(labels)s has different number "
"of elements than fields list %(fields)s"),
{'labels': field_labels, 'fields': fields})
{"labels": field_labels, "fields": fields})
if sortby_index is None:
kwargs = {}

View File

@ -44,6 +44,9 @@ class ImageGeneratorTestCase(test.TestCase):
"image_type": "qcow2",
"image_container": "bare",
"images_per_tenant": 4,
"image_name": "some_name",
"min_ram": 128,
"min_disk": 1,
}
}
@ -93,6 +96,9 @@ class ImageGeneratorTestCase(test.TestCase):
"image_type": "qcow2",
"image_container": "bare",
"images_per_tenant": images_per_tenant,
"image_name": "some_name",
"min_ram": 128,
"min_disk": 1,
}
},
"admin": {
@ -143,6 +149,9 @@ class ImageGeneratorTestCase(test.TestCase):
"image_type": "qcow2",
"image_container": "bare",
"images_per_tenant": 5,
"image_name": "some_name",
"min_ram": 128,
"min_disk": 1,
}
},
"admin": {

View File

@ -120,19 +120,47 @@ class ValidatorsTestCase(test.TestCase):
result = validation._get_validated_image({}, None, "non_existing")
self.assertFalse(result[0].is_valid, result[0].msg)
def test__get_validated_image_from_context(self):
clients = mock.MagicMock()
image = {
"size": 0,
"min_ram": 0,
"min_disk": 0
}
result = validation._get_validated_image({"args": {
"image": {"name": "foo"}}, "context": {
"images": {
"image_name": "foo"}
}}, clients, "image")
self.assertTrue(result[0].is_valid, result[0].msg)
self.assertEqual(result[1], image)
result = validation._get_validated_image({"args": {
"image": {"regex": r"^foo$"}}, "context": {
"images": {
"image_name": "foo"}
}}, clients, "image")
self.assertTrue(result[0].is_valid, result[0].msg)
self.assertEqual(result[1], image)
@mock.patch("rally.benchmark.validation.types.ImageResourceType.transform")
def test__get_validated_image(self, mock_transform):
mock_transform.return_value = "image_id"
clients = mock.MagicMock()
clients.glance().images.get.return_value = "image"
clients.glance().images.get().to_dict.return_value = {
"image": "image_id"}
result = validation._get_validated_image({"args": {"a": "test"}},
result = validation._get_validated_image({"args": {"a": "test"},
"context": {
"image_name": "foo"}},
clients, "a")
self.assertTrue(result[0].is_valid, result[0].msg)
self.assertEqual(result[1], "image")
self.assertEqual(result[1], {"image": "image_id"})
mock_transform.assert_called_once_with(clients=clients,
resource_config="test")
clients.glance().images.get.assert_called_once_with(image="image_id")
clients.glance().images.get.assert_called_with(image="image_id")
@mock.patch("rally.benchmark.validation.types.ImageResourceType.transform")
def test__get_validated_image_transform_error(self, mock_transform):
@ -144,7 +172,8 @@ class ValidatorsTestCase(test.TestCase):
@mock.patch("rally.benchmark.validation.types.ImageResourceType.transform")
def test__get_validated_image_not_found(self, mock_transform):
clients = mock.MagicMock()
clients.glance().images.get.side_effect = glance_exc.HTTPNotFound("")
clients.glance().images.get().to_dict.side_effect = (
glance_exc.HTTPNotFound(""))
result = validation._get_validated_image({"args": {"a": "test"}},
clients, "a")
self.assertFalse(result[0].is_valid, result[0].msg)
@ -254,7 +283,12 @@ class ValidatorsTestCase(test.TestCase):
@mock.patch("rally.benchmark.validation._get_validated_image")
@mock.patch("rally.benchmark.validation._get_validated_flavor")
def test_image_valid_on_flavor(self, mock_get_flavor, mock_get_image):
image = mock.MagicMock()
image = {
"id": "fake_id",
"min_ram": None,
"size": 2,
"min_disk": 0
}
flavor = mock.MagicMock()
success = validation.ValidationResult(True)
mock_get_flavor.return_value = (success, flavor)
@ -265,27 +299,27 @@ class ValidatorsTestCase(test.TestCase):
# test ram
flavor.disk = None
flavor.ram = 2
image.min_ram = None
image["min_ram"] = None
result = validator(None, None, None)
self.assertTrue(result.is_valid, result.msg)
image.min_ram = 4
image["min_ram"] = 4
result = validator(None, None, None)
self.assertFalse(result.is_valid, result.msg)
image.min_ram = 1
image["min_ram"] = 1
result = validator(None, None, None)
self.assertTrue(result.is_valid, result.msg)
# test disk (flavor.disk not None)
image.size = 2
image.min_disk = 0
image["size"] = 2
image["min_disk"] = 0
flavor.disk = 5.0 / (1024 ** 3)
result = validator(None, None, None)
self.assertTrue(result.is_valid, result.msg)
image.min_disk = flavor.disk * 2
image["min_disk"] = flavor.disk * 2
result = validator(None, None, None)
self.assertFalse(result.is_valid, result.msg)
image.min_disk = flavor.disk / 4
image.size = 1000
image["min_disk"] = flavor.disk / 4
image["size"] = 1000
result = validator(None, None, None)
self.assertFalse(result.is_valid, result.msg)
@ -297,7 +331,7 @@ class ValidatorsTestCase(test.TestCase):
clients = mock.MagicMock()
clients.nova().flavors.get.side_effect = nova_exc.NotFound("")
image = mock.MagicMock()
image = {"min_ram": 24, "id": "fake_id"}
success = validation.ValidationResult(True)
mock_get_image.return_value = (success, image)
@ -314,11 +348,11 @@ class ValidatorsTestCase(test.TestCase):
}
# test ram
image.min_ram = None
image["min_ram"] = None
result = validator(config, clients, None)
self.assertTrue(result.is_valid, result.msg)
image.min_ram = 64
image["min_ram"] = 64
result = validator(config, clients, None)
self.assertFalse(result.is_valid, result.msg)