Merge "[Verify] Fixing issue with downloading images for the tests"
This commit is contained in:
commit
538916bb1c
@ -43,6 +43,7 @@ ipv6 = True
|
||||
instance_type =
|
||||
|
||||
[scenario]
|
||||
img_file =
|
||||
|
||||
[service_available]
|
||||
|
||||
|
@ -116,6 +116,41 @@ def _create_or_get_data_dir():
|
||||
return data_dir
|
||||
|
||||
|
||||
def _download_image(image_path, image=None):
|
||||
if image:
|
||||
LOG.debug("Downloading image '%s' "
|
||||
"from Glance to %s" % (image.name, image_path))
|
||||
with open(image_path, "wb") as image_file:
|
||||
for chunk in image.data():
|
||||
image_file.write(chunk)
|
||||
else:
|
||||
LOG.debug("Downloading image from %s "
|
||||
"to %s" % (CONF.tempest.img_url, image_path))
|
||||
try:
|
||||
response = requests.get(CONF.tempest.img_url, stream=True)
|
||||
except requests.ConnectionError as err:
|
||||
msg = _("Failed to download image. "
|
||||
"Possibly there is no connection to Internet. "
|
||||
"Error: %s.") % (str(err) or "unknown")
|
||||
raise exceptions.TempestConfigCreationFailure(msg)
|
||||
|
||||
if response.status_code == 200:
|
||||
with open(image_path, "wb") as image_file:
|
||||
for chunk in response.iter_content(chunk_size=1024):
|
||||
if chunk: # filter out keep-alive new chunks
|
||||
image_file.write(chunk)
|
||||
image_file.flush()
|
||||
else:
|
||||
if response.status_code == 404:
|
||||
msg = _("Failed to download image. Image was not found.")
|
||||
else:
|
||||
msg = _("Failed to download image. "
|
||||
"HTTP error code %d.") % response.status_code
|
||||
raise exceptions.TempestConfigCreationFailure(msg)
|
||||
|
||||
LOG.debug("The image has been successfully downloaded!")
|
||||
|
||||
|
||||
def _write_config(conf_path, conf_data):
|
||||
with open(conf_path, "w+") as conf_file:
|
||||
conf_data.write(conf_file)
|
||||
@ -137,39 +172,6 @@ class TempestConfig(utils.RandomNameGeneratorMixin):
|
||||
self.conf = configparser.ConfigParser()
|
||||
self.conf.read(os.path.join(os.path.dirname(__file__), "config.ini"))
|
||||
|
||||
self.image_name = parse.urlparse(
|
||||
CONF.tempest.img_url).path.split("/")[-1]
|
||||
self._download_image()
|
||||
|
||||
def _download_image(self):
|
||||
img_path = os.path.join(self.data_dir, self.image_name)
|
||||
if os.path.isfile(img_path):
|
||||
return
|
||||
|
||||
try:
|
||||
response = requests.get(CONF.tempest.img_url, stream=True)
|
||||
except requests.ConnectionError as err:
|
||||
msg = _("Failed to download image. "
|
||||
"Possibly there is no connection to Internet. "
|
||||
"Error: %s.") % (str(err) or "unknown")
|
||||
raise exceptions.TempestConfigCreationFailure(msg)
|
||||
|
||||
if response.status_code == 200:
|
||||
with open(img_path + ".tmp", "wb") as img_file:
|
||||
for chunk in response.iter_content(chunk_size=1024):
|
||||
if chunk: # filter out keep-alive new chunks
|
||||
img_file.write(chunk)
|
||||
img_file.flush()
|
||||
os.rename(img_path + ".tmp", img_path)
|
||||
else:
|
||||
if response.status_code == 404:
|
||||
msg = _("Failed to download image. "
|
||||
"Image was not found.")
|
||||
else:
|
||||
msg = _("Failed to download image. "
|
||||
"HTTP error code %d.") % response.status_code
|
||||
raise exceptions.TempestConfigCreationFailure(msg)
|
||||
|
||||
def _get_service_url(self, service_name):
|
||||
s_type = self._get_service_type_by_service_name(service_name)
|
||||
available_endpoints = self.keystone.service_catalog.get_endpoints()
|
||||
@ -284,7 +286,6 @@ class TempestConfig(utils.RandomNameGeneratorMixin):
|
||||
|
||||
def _configure_scenario(self, section_name="scenario"):
|
||||
self.conf.set(section_name, "img_dir", self.data_dir)
|
||||
self.conf.set(section_name, "img_file", self.image_name)
|
||||
|
||||
def _configure_service_available(self, section_name="service_available"):
|
||||
services = ["cinder", "glance", "heat", "ironic", "neutron", "nova",
|
||||
@ -338,8 +339,8 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
self.conf = configparser.ConfigParser()
|
||||
self.conf.read(conf_path)
|
||||
|
||||
self.image_name = parse.urlparse(
|
||||
CONF.tempest.img_url).path.split("/")[-1]
|
||||
self.data_dir = _create_or_get_data_dir()
|
||||
self.image_name = "tempest-image"
|
||||
|
||||
self._created_roles = []
|
||||
self._created_images = []
|
||||
@ -348,16 +349,19 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
|
||||
def __enter__(self):
|
||||
self._create_tempest_roles()
|
||||
|
||||
self._configure_option("scenario", "img_file", self.image_name,
|
||||
helper_method=self._download_image)
|
||||
self._configure_option("compute", "image_ref",
|
||||
self._discover_or_create_image)
|
||||
helper_method=self._discover_or_create_image)
|
||||
self._configure_option("compute", "image_ref_alt",
|
||||
self._discover_or_create_image)
|
||||
helper_method=self._discover_or_create_image)
|
||||
self._configure_option("compute", "flavor_ref",
|
||||
self._discover_or_create_flavor,
|
||||
CONF.tempest.flavor_ref_ram)
|
||||
helper_method=self._discover_or_create_flavor,
|
||||
flv_ram=CONF.tempest.flavor_ref_ram)
|
||||
self._configure_option("compute", "flavor_ref_alt",
|
||||
self._discover_or_create_flavor,
|
||||
CONF.tempest.flavor_ref_alt_ram)
|
||||
helper_method=self._discover_or_create_flavor,
|
||||
flv_ram=CONF.tempest.flavor_ref_alt_ram)
|
||||
if "neutron" in self.available_services:
|
||||
neutronclient = self.clients.neutron()
|
||||
if neutronclient.list_networks(shared=True)["networks"]:
|
||||
@ -370,12 +374,14 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
# resources.
|
||||
LOG.debug("Shared networks found. "
|
||||
"'fixed_network_name' option should be configured")
|
||||
self._configure_option("compute", "fixed_network_name",
|
||||
self._create_network_resources)
|
||||
self._configure_option(
|
||||
"compute", "fixed_network_name",
|
||||
helper_method=self._create_network_resources)
|
||||
if "heat" in self.available_services:
|
||||
self._configure_option("orchestration", "instance_type",
|
||||
self._discover_or_create_flavor,
|
||||
CONF.tempest.heat_instance_type_ram)
|
||||
self._configure_option(
|
||||
"orchestration", "instance_type",
|
||||
helper_method=self._discover_or_create_flavor,
|
||||
flv_ram=CONF.tempest.heat_instance_type_ram)
|
||||
|
||||
_write_config(self.conf_path, self.conf)
|
||||
|
||||
@ -406,14 +412,46 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
LOG.debug("Creating role '%s'" % role)
|
||||
self._created_roles.append(keystoneclient.roles.create(role))
|
||||
|
||||
def _configure_option(self, section, option,
|
||||
create_method, *args, **kwargs):
|
||||
def _discover_image(self):
|
||||
LOG.debug("Trying to discover a public image with name matching "
|
||||
"regular expression '%s'. Note that case insensitive "
|
||||
"matching is performed." % CONF.tempest.img_name_regex)
|
||||
glance_wrapper = glance.wrap(self.clients.glance, self)
|
||||
images = glance_wrapper.list_images(status="active",
|
||||
visibility="public")
|
||||
for image in images:
|
||||
if image.name and re.match(CONF.tempest.img_name_regex,
|
||||
image.name, re.IGNORECASE):
|
||||
LOG.debug("The following public "
|
||||
"image discovered: '%s'" % image.name)
|
||||
return image
|
||||
|
||||
LOG.debug("There is no public image with name matching "
|
||||
"regular expression '%s'" % CONF.tempest.img_name_regex)
|
||||
|
||||
def _download_image(self):
|
||||
image_path = os.path.join(self.data_dir, self.image_name)
|
||||
if os.path.isfile(image_path):
|
||||
LOG.debug("Image is already downloaded to %s" % image_path)
|
||||
return
|
||||
|
||||
if CONF.tempest.img_name_regex:
|
||||
image = self._discover_image()
|
||||
if image:
|
||||
return _download_image(image_path, image)
|
||||
|
||||
_download_image(image_path)
|
||||
|
||||
def _configure_option(self, section, option, value=None,
|
||||
helper_method=None, *args, **kwargs):
|
||||
option_value = self.conf.get(section, option)
|
||||
if not option_value:
|
||||
LOG.debug("Option '%s' from '%s' section "
|
||||
"is not configured" % (option, section))
|
||||
resource = create_method(*args, **kwargs)
|
||||
value = resource["name"] if "network" in option else resource.id
|
||||
if helper_method:
|
||||
res = helper_method(*args, **kwargs)
|
||||
if res:
|
||||
value = res["name"] if "network" in option else res.id
|
||||
LOG.debug("Setting value '%s' for option '%s'" % (value, option))
|
||||
self.conf.set(section, option, value)
|
||||
LOG.debug("Option '{opt}' is configured. "
|
||||
@ -424,35 +462,25 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
.format(opt=option, opt_val=option_value))
|
||||
|
||||
def _discover_or_create_image(self):
|
||||
glance_wrapper = glance.wrap(self.clients.glance, self)
|
||||
|
||||
if CONF.tempest.img_name_regex:
|
||||
LOG.debug("Trying to discover a public image with name matching "
|
||||
"regular expression '%s'. Note that case insensitive "
|
||||
"matching is performed" % CONF.tempest.img_name_regex)
|
||||
images = glance_wrapper.list_images(status="active",
|
||||
visibility="public")
|
||||
for img in images:
|
||||
if img.name and re.match(CONF.tempest.img_name_regex,
|
||||
img.name, re.IGNORECASE):
|
||||
LOG.debug(
|
||||
"The following public image discovered: '{0}'. "
|
||||
"Using image '{0}' for the tests".format(img.name))
|
||||
return img
|
||||
|
||||
LOG.debug("There is no public image with name matching "
|
||||
"regular expression '%s'" % CONF.tempest.img_name_regex)
|
||||
image = self._discover_image()
|
||||
if image:
|
||||
LOG.debug("Using image '%s' (ID = %s) "
|
||||
"for the tests" % (image.name, image.id))
|
||||
return image
|
||||
|
||||
params = {
|
||||
"name": self.generate_random_name(),
|
||||
"disk_format": CONF.tempest.img_disk_format,
|
||||
"container_format": CONF.tempest.img_container_format,
|
||||
"image_location": os.path.join(_create_or_get_data_dir(),
|
||||
self.image_name),
|
||||
"image_location": os.path.join(self.data_dir, self.image_name),
|
||||
"visibility": "public"
|
||||
}
|
||||
LOG.debug("Creating image '%s'" % params["name"])
|
||||
glance_wrapper = glance.wrap(self.clients.glance, self)
|
||||
image = glance_wrapper.create_image(**params)
|
||||
LOG.debug("Image '%s' (ID = %s) has been "
|
||||
"successfully created!" % (image.name, image.id))
|
||||
self._created_images.append(image)
|
||||
|
||||
return image
|
||||
@ -463,10 +491,11 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
LOG.debug("Trying to discover a flavor with the following "
|
||||
"properties: RAM = %dMB, VCPUs = 1, disk = 0GB" % flv_ram)
|
||||
for flavor in novaclient.flavors.list():
|
||||
if (flavor.ram == flv_ram
|
||||
and flavor.vcpus == 1 and flavor.disk == 0):
|
||||
LOG.debug("The following flavor discovered: '{0}'. Using "
|
||||
"flavor '{0}' for the tests".format(flavor.name))
|
||||
if (flavor.ram == flv_ram and
|
||||
flavor.vcpus == 1 and flavor.disk == 0):
|
||||
LOG.debug("The following flavor discovered: '{0}'. "
|
||||
"Using flavor '{0}' (ID = {1}) for the tests"
|
||||
.format(flavor.name, flavor.id))
|
||||
return flavor
|
||||
|
||||
LOG.debug("There is no flavor with the mentioned properties")
|
||||
@ -480,6 +509,8 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
LOG.debug("Creating flavor '%s' with the following properties: RAM "
|
||||
"= %dMB, VCPUs = 1, disk = 0GB" % (params["name"], flv_ram))
|
||||
flavor = novaclient.flavors.create(**params)
|
||||
LOG.debug("Flavor '%s' (ID = %s) has been "
|
||||
"successfully created!" % (flavor.name, flavor.id))
|
||||
self._created_flavors.append(flavor)
|
||||
|
||||
return flavor
|
||||
@ -491,6 +522,7 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
net = neutron_wrapper.create_network(
|
||||
tenant_id, subnets_num=1, add_router=True,
|
||||
network_create_args={"shared": True})
|
||||
LOG.debug("Network resources have been successfully created!")
|
||||
self._created_networks.append(net)
|
||||
|
||||
return net
|
||||
@ -500,6 +532,7 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
for role in self._created_roles:
|
||||
LOG.debug("Deleting role '%s'" % role.name)
|
||||
keystoneclient.roles.delete(role.id)
|
||||
LOG.debug("Role '%s' has been deleted" % role.name)
|
||||
|
||||
def _cleanup_images(self):
|
||||
glance_wrapper = glance.wrap(self.clients.glance, self)
|
||||
@ -513,6 +546,7 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
timeout=CONF.benchmark.glance_image_delete_timeout,
|
||||
check_interval=CONF.benchmark.
|
||||
glance_image_delete_poll_interval)
|
||||
LOG.debug("Image '%s' has been deleted" % image.name)
|
||||
self._remove_opt_value_from_config("compute", image.id)
|
||||
|
||||
def _cleanup_flavors(self):
|
||||
@ -520,6 +554,7 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
for flavor in self._created_flavors:
|
||||
LOG.debug("Deleting flavor '%s'" % flavor.name)
|
||||
novaclient.flavors.delete(flavor.id)
|
||||
LOG.debug("Flavor '%s' has been deleted" % flavor.name)
|
||||
self._remove_opt_value_from_config("compute", flavor.id)
|
||||
self._remove_opt_value_from_config("orchestration", flavor.id)
|
||||
|
||||
@ -529,6 +564,7 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
LOG.debug("Deleting network resources: router, subnet, network")
|
||||
neutron_wrapper.delete_network(net)
|
||||
self._remove_opt_value_from_config("compute", net["name"])
|
||||
LOG.debug("Network resources have been deleted")
|
||||
|
||||
def _remove_opt_value_from_config(self, section, opt_value):
|
||||
for option, value in self.conf.items(section):
|
||||
@ -536,3 +572,4 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
|
||||
LOG.debug("Removing value '%s' for option '%s' "
|
||||
"from Tempest config file" % (opt_value, option))
|
||||
self.conf.set(section, option, "")
|
||||
LOG.debug("Value '%s' has been removed" % opt_value)
|
||||
|
@ -46,7 +46,7 @@ EXPECTED_FAILURES = {
|
||||
"This test fails because 'novnc' console type is unavailable."
|
||||
}
|
||||
|
||||
TEMPEST_PLUGIN = "https://github.com/MBonell/hello-world-tempest-plugin"
|
||||
TEMPEST_PLUGIN = "https://git.openstack.org/openstack/ceilometer"
|
||||
|
||||
# NOTE(andreykurilin): this variable is used to generate output file names
|
||||
# with prefix ${CALL_COUNT}_ .
|
||||
@ -249,7 +249,7 @@ def main():
|
||||
render_vars["reinstall"] = call_rally(
|
||||
"verify reinstall --version %s" % tempest_commit_id)
|
||||
|
||||
# Install a simple Tempest plugin
|
||||
# Install a Tempest plugin
|
||||
render_vars["installplugin"] = call_rally(
|
||||
"verify installplugin --source %s" % TEMPEST_PLUGIN)
|
||||
|
||||
|
@ -20,7 +20,6 @@ import mock
|
||||
from oslo_config import cfg
|
||||
import requests
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from rally import exceptions
|
||||
from rally.verification.tempest import config
|
||||
@ -53,35 +52,9 @@ class TempestConfigTestCase(test.TestCase):
|
||||
mock.patch("rally.common.objects.deploy.db.deployment_get",
|
||||
return_value=CREDS).start()
|
||||
mock.patch("rally.osclients.Clients").start()
|
||||
self.mock_isfile = mock.patch("os.path.isfile",
|
||||
return_value=True).start()
|
||||
|
||||
self.tempest_conf = config.TempestConfig("fake_deployment")
|
||||
|
||||
@mock.patch("os.rename")
|
||||
@mock.patch("six.moves.builtins.open", side_effect=mock.mock_open())
|
||||
@mock.patch("requests.get", return_value=mock.MagicMock(status_code=200))
|
||||
def test__download_image_success(self, mock_get,
|
||||
mock_open, mock_rename):
|
||||
self.mock_isfile.return_value = False
|
||||
self.tempest_conf._download_image()
|
||||
mock_get.assert_called_once_with(
|
||||
CONF.tempest.img_url, stream=True)
|
||||
|
||||
@mock.patch("requests.get")
|
||||
@ddt.data(404, 500)
|
||||
def test__download_image_failure(self, status_code, mock_get):
|
||||
self.mock_isfile.return_value = False
|
||||
mock_get.return_value = mock.MagicMock(status_code=status_code)
|
||||
self.assertRaises(exceptions.TempestConfigCreationFailure,
|
||||
self.tempest_conf._download_image)
|
||||
|
||||
@mock.patch("requests.get", side_effect=requests.ConnectionError())
|
||||
def test__download_image_connection_error(self, mock_requests_get):
|
||||
self.mock_isfile.return_value = False
|
||||
self.assertRaises(exceptions.TempestConfigCreationFailure,
|
||||
self.tempest_conf._download_image)
|
||||
|
||||
@ddt.data({"publicURL": "test_url"},
|
||||
{"interface": "public", "url": "test_url"})
|
||||
def test__get_service_url(self, endpoint):
|
||||
@ -223,10 +196,7 @@ class TempestConfigTestCase(test.TestCase):
|
||||
def test__configure_scenario(self):
|
||||
self.tempest_conf._configure_scenario()
|
||||
|
||||
image_name = parse.urlparse(
|
||||
config.CONF.tempest.img_url).path.split("/")[-1]
|
||||
expected = (("img_dir", self.tempest_conf.data_dir),
|
||||
("img_file", image_name))
|
||||
expected = (("img_dir", self.tempest_conf.data_dir),)
|
||||
result = self.tempest_conf.conf.items("scenario")
|
||||
for item in expected:
|
||||
self.assertIn(item, result)
|
||||
@ -284,6 +254,7 @@ class TempestConfigTestCase(test.TestCase):
|
||||
conf_data.write.assert_called_once_with(mock_open.side_effect())
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TempestResourcesContextTestCase(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -292,6 +263,8 @@ class TempestResourcesContextTestCase(test.TestCase):
|
||||
mock.patch("rally.common.objects.deploy.db.deployment_get",
|
||||
return_value=CREDS).start()
|
||||
mock.patch("rally.osclients.Clients").start()
|
||||
self.mock_isfile = mock.patch("os.path.isfile",
|
||||
return_value=True).start()
|
||||
|
||||
fake_verification = {"uuid": "uuid"}
|
||||
self.context = config.TempestResourcesContext("fake_deployment",
|
||||
@ -299,6 +272,54 @@ class TempestResourcesContextTestCase(test.TestCase):
|
||||
"/fake/path/to/config")
|
||||
self.context.conf.add_section("compute")
|
||||
self.context.conf.add_section("orchestration")
|
||||
self.context.conf.add_section("scenario")
|
||||
|
||||
@mock.patch("six.moves.builtins.open", side_effect=mock.mock_open(),
|
||||
create=True)
|
||||
def test__download_image_from_glance(self, mock_open):
|
||||
self.mock_isfile.return_value = False
|
||||
img_path = os.path.join(self.context.data_dir, "foo")
|
||||
img = mock.MagicMock()
|
||||
img.data.return_value = "data"
|
||||
|
||||
config._download_image(img_path, img)
|
||||
mock_open.assert_called_once_with(img_path, "wb")
|
||||
mock_open().write.assert_has_calls([mock.call("d"),
|
||||
mock.call("a"),
|
||||
mock.call("t"),
|
||||
mock.call("a")])
|
||||
|
||||
@mock.patch("six.moves.builtins.open", side_effect=mock.mock_open())
|
||||
@mock.patch("requests.get", return_value=mock.MagicMock(status_code=200))
|
||||
def test__download_image_from_url_success(self, mock_get, mock_open):
|
||||
self.mock_isfile.return_value = False
|
||||
img_path = os.path.join(self.context.data_dir, "foo")
|
||||
mock_get.return_value.iter_content.return_value = "data"
|
||||
|
||||
config._download_image(img_path)
|
||||
mock_get.assert_called_once_with(CONF.tempest.img_url, stream=True)
|
||||
mock_open.assert_called_once_with(img_path, "wb")
|
||||
mock_open().write.assert_has_calls([mock.call("d"),
|
||||
mock.call("a"),
|
||||
mock.call("t"),
|
||||
mock.call("a")])
|
||||
|
||||
@mock.patch("requests.get")
|
||||
@ddt.data(404, 500)
|
||||
def test__download_image_from_url_failure(self, status_code, mock_get):
|
||||
self.mock_isfile.return_value = False
|
||||
mock_get.return_value = mock.MagicMock(status_code=status_code)
|
||||
self.assertRaises(
|
||||
exceptions.TempestConfigCreationFailure, config._download_image,
|
||||
os.path.join(self.context.data_dir, "foo"))
|
||||
|
||||
@mock.patch("requests.get", side_effect=requests.ConnectionError())
|
||||
def test__download_image_from_url_connection_error(
|
||||
self, mock_requests_get):
|
||||
self.mock_isfile.return_value = False
|
||||
self.assertRaises(
|
||||
exceptions.TempestConfigCreationFailure, config._download_image,
|
||||
os.path.join(self.context.data_dir, "foo"))
|
||||
|
||||
@mock.patch("rally.plugins.openstack.wrappers."
|
||||
"network.NeutronWrapper.create_network")
|
||||
@ -313,6 +334,7 @@ class TempestResourcesContextTestCase(test.TestCase):
|
||||
self.context.conf.set("compute", "flavor_ref_alt", "id4")
|
||||
self.context.conf.set("compute", "fixed_network_name", "name1")
|
||||
self.context.conf.set("orchestration", "instance_type", "id5")
|
||||
self.context.conf.set("scenario", "img_file", "id6")
|
||||
|
||||
self.context.__enter__()
|
||||
|
||||
@ -342,16 +364,45 @@ class TempestResourcesContextTestCase(test.TestCase):
|
||||
self.assertIn(role3, created_roles)
|
||||
self.assertIn(role4, created_roles)
|
||||
|
||||
@mock.patch("rally.plugins.openstack.wrappers.glance.wrap")
|
||||
def test__discover_image(self, mock_wrap):
|
||||
client = mock_wrap.return_value
|
||||
client.list_images.return_value = [fakes.FakeImage(name="Foo"),
|
||||
fakes.FakeImage(name="CirrOS")]
|
||||
|
||||
image = self.context._discover_image()
|
||||
self.assertEqual("CirrOS", image.name)
|
||||
|
||||
@mock.patch("six.moves.builtins.open", side_effect=mock.mock_open(),
|
||||
create=True)
|
||||
@mock.patch("rally.plugins.openstack.wrappers.glance.wrap")
|
||||
@mock.patch("os.path.isfile", return_value=False)
|
||||
def test__download_image(self, mock_isfile, mock_wrap, mock_open):
|
||||
img_1 = mock.MagicMock()
|
||||
img_1.name = "Foo"
|
||||
img_2 = mock.MagicMock()
|
||||
img_2.name = "CirrOS"
|
||||
img_2.data.return_value = "data"
|
||||
mock_wrap.return_value.list_images.return_value = [img_1, img_2]
|
||||
|
||||
self.context._download_image()
|
||||
img_path = os.path.join(self.context.data_dir, self.context.image_name)
|
||||
mock_open.assert_called_once_with(img_path, "wb")
|
||||
mock_open().write.assert_has_calls([mock.call("d"),
|
||||
mock.call("a"),
|
||||
mock.call("t"),
|
||||
mock.call("a")])
|
||||
|
||||
# We can choose any option to test the '_configure_option' method. So let's
|
||||
# configure the 'flavor_ref' option.
|
||||
def test__configure_option(self):
|
||||
create_method = mock.MagicMock()
|
||||
create_method.side_effect = [fakes.FakeFlavor(id="id1")]
|
||||
helper_method = mock.MagicMock()
|
||||
helper_method.side_effect = [fakes.FakeFlavor(id="id1")]
|
||||
|
||||
self.context.conf.set("compute", "flavor_ref", "")
|
||||
self.context._configure_option("compute",
|
||||
"flavor_ref", create_method, 64)
|
||||
self.assertEqual(create_method.call_count, 1)
|
||||
self.context._configure_option("compute", "flavor_ref",
|
||||
helper_method=helper_method, flv_ram=64)
|
||||
self.assertEqual(helper_method.call_count, 1)
|
||||
|
||||
result = self.context.conf.get("compute", "flavor_ref")
|
||||
self.assertEqual("id1", result)
|
||||
@ -374,8 +425,6 @@ class TempestResourcesContextTestCase(test.TestCase):
|
||||
self.assertEqual(image, client.create_image.return_value)
|
||||
self.assertEqual(self.context._created_images[0],
|
||||
client.create_image.return_value)
|
||||
mock_wrap.assert_called_once_with(self.context.clients.glance,
|
||||
self.context)
|
||||
client.create_image.assert_called_once_with(
|
||||
container_format=CONF.tempest.img_container_format,
|
||||
image_location=mock.ANY,
|
||||
|
Loading…
Reference in New Issue
Block a user