Reworked script generating tempest.conf
* The config.py script generating tempest.conf was significantly reworked. * The config.ini file was updated. * A context class to create/delete all resources needed for Tempest was added. How does it work? Before running tests: 1. The context class creates all roles needed for Tempest; 2. If the image_ref option is not specified in the tempest.conf file, the context class will create an image for this option and add ID of the created image to tempest.conf; 3. The same is for 'image_ref_alt', 'flavor_ref' and 'flavor_ref_alt'; 4. Once tests finish, all created resources will be deleted. All IDs of created resources will be deleted from tempest.conf. * The TempestConfigCreationFailure exception was moved to the exceptions.py file. In addition, the TempestResourceCreationFailure exception was added. * The rally-verify.sh script was changed. The index_verify.mako file was changed as well in accordance with changes in rally-verify.sh. * All relevant unit tests were updated in accordance with new changes. Closes-bug: #1454648 Change-Id: If32e51d6ce1f6bf7421021d151005cc75ed34953
This commit is contained in:
parent
77861e2c2f
commit
1dfb99574a
@ -615,14 +615,29 @@
|
||||
# From rally
|
||||
#
|
||||
|
||||
# Version of cirros image (string value)
|
||||
#cirros_version = 0.3.4
|
||||
# CirrOS image URL (string value)
|
||||
#cirros_img_url = http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img
|
||||
|
||||
# Cirros image name (string value)
|
||||
#cirros_image = cirros-0.3.4-x86_64-disk.img
|
||||
|
||||
# Cirros image base URL (string value)
|
||||
#cirros_base_url = http://download.cirros-cloud.net
|
||||
[role]
|
||||
|
||||
#
|
||||
# From rally
|
||||
#
|
||||
|
||||
# Role required for users to be able to create Swift containers
|
||||
# (string value)
|
||||
#swift_operator_role = Member
|
||||
|
||||
# User role that has reseller admin (string value)
|
||||
#swift_reseller_admin_role = ResellerAdmin
|
||||
|
||||
# Role required for users to be able to manage Heat stacks (string
|
||||
# value)
|
||||
#heat_stack_owner_role = heat_stack_owner
|
||||
|
||||
# Role for Heat template-defined users (string value)
|
||||
#heat_stack_user_role = heat_stack_user
|
||||
|
||||
|
||||
[users_context]
|
||||
|
@ -43,6 +43,7 @@ def list_opts():
|
||||
ec2_utils.EC2_BENCHMARK_OPTS)),
|
||||
("image",
|
||||
itertools.chain(tempest_conf.IMAGE_OPTS)),
|
||||
("role", itertools.chain(tempest_conf.ROLE_OPTS)),
|
||||
("users_context", itertools.chain(users.USER_CONTEXT_OPTS)),
|
||||
("cleanup", itertools.chain(cleanup_base.CLEANUP_OPTS))
|
||||
]
|
||||
|
@ -231,3 +231,11 @@ class InvalidHostException(RallyException):
|
||||
|
||||
class MultipleMatchesFound(RallyException):
|
||||
msg_fmt = _("Found multiple %(needle)s: %(haystack)s")
|
||||
|
||||
|
||||
class TempestConfigCreationFailure(RallyException):
|
||||
msg_fmt = _("Unable to create Tempest config file: %(message)s")
|
||||
|
||||
|
||||
class TempestResourceCreationFailure(RallyException):
|
||||
msg_fmt = _("Unable to create resource needed for Tempest: %(message)s")
|
||||
|
@ -23,7 +23,6 @@ from rally.common import utils
|
||||
from rally import consts
|
||||
from rally import exceptions
|
||||
from rally.task import context
|
||||
from rally.verification.tempest import config
|
||||
from rally.verification.tempest import tempest
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -65,7 +64,7 @@ class Tempest(context.Context):
|
||||
msg = _("Failing to install tempest.")
|
||||
LOG.error(msg)
|
||||
raise exceptions.BenchmarkSetupFailure(msg)
|
||||
except config.TempestConfigCreationFailure:
|
||||
except exceptions.TempestConfigCreationFailure:
|
||||
msg = _("Failing to configure tempest.")
|
||||
LOG.error(msg)
|
||||
raise exceptions.BenchmarkSetupFailure(msg)
|
||||
|
@ -3,50 +3,55 @@ debug = True
|
||||
log_file = tempest.log
|
||||
use_stderr = False
|
||||
|
||||
[auth]
|
||||
allow_tenant_isolation = False
|
||||
|
||||
[boto]
|
||||
instance_type = m1.nano
|
||||
http_socket_timeout = 30
|
||||
build_interval = 1
|
||||
build_timeout = 196
|
||||
|
||||
[compute]
|
||||
ssh_connect_method = floating
|
||||
image_ref =
|
||||
image_ref_alt =
|
||||
flavor_ref =
|
||||
flavor_ref_alt =
|
||||
ssh_user = cirros
|
||||
image_ssh_user = cirros
|
||||
image_alt_ssh_user = cirros
|
||||
network_for_ssh = private
|
||||
ssh_user = cirros
|
||||
build_interval = 1
|
||||
build_timeout = 196
|
||||
|
||||
[compute-feature-enabled]
|
||||
change_password = False
|
||||
live_migration = False
|
||||
block_migration_for_live_migration = False
|
||||
resize = True
|
||||
vnc_console = False
|
||||
attach_encrypted_volume = False
|
||||
|
||||
[dashboard]
|
||||
|
||||
[data_processing-feature-enabled]
|
||||
plugins = vanilla,cdh,mapr,spark,ambari
|
||||
|
||||
[identity]
|
||||
|
||||
[image-feature-enabled]
|
||||
deactivate_image = True
|
||||
|
||||
[network]
|
||||
tenant_networks_reachable = False
|
||||
|
||||
[network-feature-enabled]
|
||||
api_extensions = all
|
||||
ipv6_subnet_attributes = True
|
||||
ipv6 = True
|
||||
|
||||
[object-storage]
|
||||
|
||||
[oslo_concurrency]
|
||||
|
||||
[orchestration]
|
||||
max_template_size = 5440000
|
||||
max_resources_per_stack = 20000
|
||||
|
||||
[scenario]
|
||||
large_ops_number = 0
|
||||
ssh_user = cirros
|
||||
large_ops_number = 2
|
||||
|
||||
[service_available]
|
||||
|
||||
[validation]
|
||||
ssh_timeout = 196
|
||||
ip_version_for_ssh = 4
|
||||
run_validation = False
|
||||
|
||||
[volume]
|
||||
build_interval = 1
|
||||
build_timeout = 196
|
||||
[volume-feature-enabled]
|
||||
bootable = True
|
||||
|
@ -13,10 +13,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
import inspect
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
import requests
|
||||
@ -30,236 +29,328 @@ from rally.common import objects
|
||||
from rally import exceptions
|
||||
from rally import osclients
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
IMAGE_OPTS = [
|
||||
cfg.StrOpt("cirros_version",
|
||||
default="0.3.4",
|
||||
help="Version of cirros image"),
|
||||
cfg.StrOpt("cirros_image",
|
||||
default="cirros-0.3.4-x86_64-disk.img",
|
||||
help="Cirros image name"),
|
||||
cfg.StrOpt("cirros_base_url",
|
||||
default="http://download.cirros-cloud.net",
|
||||
help="Cirros image base URL"),
|
||||
cfg.StrOpt("cirros_img_url",
|
||||
default="http://download.cirros-cloud.net/"
|
||||
"0.3.4/cirros-0.3.4-x86_64-disk.img",
|
||||
help="CirrOS image URL")
|
||||
]
|
||||
|
||||
ROLE_OPTS = [
|
||||
cfg.StrOpt("swift_operator_role",
|
||||
default="Member",
|
||||
help="Role required for users "
|
||||
"to be able to create Swift containers"),
|
||||
cfg.StrOpt("swift_reseller_admin_role",
|
||||
default="ResellerAdmin",
|
||||
help="User role that has reseller admin"),
|
||||
cfg.StrOpt("heat_stack_owner_role",
|
||||
default="heat_stack_owner",
|
||||
help="Role required for users "
|
||||
"to be able to manage Heat stacks"),
|
||||
cfg.StrOpt("heat_stack_user_role",
|
||||
default="heat_stack_user",
|
||||
help="Role for Heat template-defined users")
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(IMAGE_OPTS, "image")
|
||||
CONF.register_opts(ROLE_OPTS, "role")
|
||||
|
||||
IMAGE_NAME = parse.urlparse(CONF.image.cirros_img_url).path.split("/")[-1]
|
||||
|
||||
|
||||
class TempestConfigCreationFailure(exceptions.RallyException):
|
||||
msg_fmt = _("Unable create tempest.conf: '%(message)s'")
|
||||
def _create_or_get_data_dir():
|
||||
data_dir = os.path.join(
|
||||
os.path.expanduser("~"), ".rally", "tempest", "data")
|
||||
if not os.path.exists(data_dir):
|
||||
os.makedirs(data_dir)
|
||||
|
||||
return data_dir
|
||||
|
||||
|
||||
class TempestConf(object):
|
||||
def _write_config(conf_path, conf_data):
|
||||
with open(conf_path, "w+") as conf_file:
|
||||
conf_data.write(conf_file)
|
||||
|
||||
|
||||
class TempestConfig(object):
|
||||
"""Class to generate Tempest configuration file."""
|
||||
|
||||
def __init__(self, deployment):
|
||||
self.deployment = deployment
|
||||
|
||||
self.endpoint = db.deployment_get(deployment)["admin"]
|
||||
self.clients = osclients.Clients(objects.Endpoint(**self.endpoint))
|
||||
try:
|
||||
self.keystoneclient = self.clients.verified_keystone()
|
||||
except exceptions.InvalidAdminException:
|
||||
msg = (_("Admin permission is required to generate tempest "
|
||||
"configuration file. User %s doesn't have admin role.") %
|
||||
self.endpoint["username"])
|
||||
raise TempestConfigCreationFailure(msg)
|
||||
self.keystone = self.clients.verified_keystone()
|
||||
|
||||
self.available_services = self.clients.services().values()
|
||||
|
||||
self.data_dir = _create_or_get_data_dir()
|
||||
|
||||
self.conf = configparser.ConfigParser()
|
||||
self.conf.read(os.path.join(os.path.dirname(__file__), "config.ini"))
|
||||
self.deployment = deployment
|
||||
self.data_path = os.path.join(os.path.expanduser("~"), ".rally",
|
||||
"tempest", "data")
|
||||
if not os.path.exists(self.data_path):
|
||||
os.makedirs(self.data_path)
|
||||
self.img_path = os.path.join(self.data_path,
|
||||
CONF.image.cirros_image)
|
||||
if not os.path.isfile(self.img_path):
|
||||
self._load_img()
|
||||
|
||||
def _load_img(self):
|
||||
cirros_url = ("%s/%s/%s" %
|
||||
(CONF.image.cirros_base_url,
|
||||
CONF.image.cirros_version,
|
||||
CONF.image.cirros_image))
|
||||
self._download_cirros_image()
|
||||
|
||||
def _download_cirros_image(self):
|
||||
img_path = os.path.join(self.data_dir, IMAGE_NAME)
|
||||
if os.path.isfile(img_path):
|
||||
return
|
||||
|
||||
try:
|
||||
response = requests.get(cirros_url, stream=True)
|
||||
response = requests.get(CONF.image.cirros_img_url, stream=True)
|
||||
except requests.ConnectionError as err:
|
||||
msg = _("Error on downloading cirros image, possibly"
|
||||
" no connection to Internet with message %s") % str(err)
|
||||
raise TempestConfigCreationFailure(msg)
|
||||
msg = _("Failed to download CirrOS 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(self.img_path + ".tmp", "wb") as img_file:
|
||||
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(self.img_path + ".tmp", self.img_path)
|
||||
os.rename(img_path + ".tmp", img_path)
|
||||
else:
|
||||
if response.status_code == 404:
|
||||
msg = _("Error on downloading cirros image, possibly"
|
||||
"invalid cirros_version or cirros_image in rally.conf")
|
||||
msg = _("Failed to download CirrOS image. "
|
||||
"Image was not found.")
|
||||
else:
|
||||
msg = _("Error on downloading cirros image, "
|
||||
"HTTP error code %s") % response.getcode()
|
||||
raise TempestConfigCreationFailure(msg)
|
||||
msg = _("Failed to download CirrOS image. "
|
||||
"HTTP error code %d.") % response.status_code
|
||||
raise exceptions.TempestConfigCreationFailure(msg)
|
||||
|
||||
def _get_url(self, servicename):
|
||||
services_type2name_map = self.clients.services()
|
||||
for service in self.keystoneclient.auth_ref["serviceCatalog"]:
|
||||
if services_type2name_map.get(service["type"]) == servicename:
|
||||
def _get_service_url(self, service_type):
|
||||
for service in self.keystone.auth_ref["serviceCatalog"]:
|
||||
if self.clients.services().get(service["type"]) == service_type:
|
||||
return service["endpoints"][0]["publicURL"]
|
||||
|
||||
def _set_default(self):
|
||||
# Nothing to set up in this section for now
|
||||
pass
|
||||
|
||||
def _set_oslo_concurrency(self, section_name="oslo_concurrency"):
|
||||
lock_path = os.path.join(self.data_path,
|
||||
"lock_files_%s" % self.deployment)
|
||||
if not os.path.exists(lock_path):
|
||||
os.makedirs(lock_path)
|
||||
self.conf.set(section_name, "lock_path", lock_path)
|
||||
|
||||
def _set_boto(self, section_name="boto"):
|
||||
self.conf.set(section_name, "ec2_url", self._get_url("ec2"))
|
||||
self.conf.set(section_name, "s3_url", self._get_url("s3"))
|
||||
materials_path = os.path.join(self.data_path, "s3materials")
|
||||
self.conf.set(section_name, "s3_materials_path", materials_path)
|
||||
def _configure_boto(self, section_name="boto"):
|
||||
self.conf.set(section_name, "ec2_url", self._get_service_url("ec2"))
|
||||
self.conf.set(section_name, "s3_url", self._get_service_url("s3"))
|
||||
self.conf.set(section_name, "s3_materials_path",
|
||||
os.path.join(self.data_dir, "s3materials"))
|
||||
# TODO(olkonami): find out how can we get ami, ari, aki manifest files
|
||||
|
||||
def _set_compute_images(self, section_name="compute"):
|
||||
glanceclient = self.clients.glance()
|
||||
image_list = [img for img in glanceclient.images.list()
|
||||
if img.status.lower() == "active" and
|
||||
img.name is not None and "cirros" in img.name]
|
||||
# Upload new images if there are no
|
||||
# necessary images in the cloud (cirros)
|
||||
while len(image_list) < 2:
|
||||
now = (datetime.datetime.fromtimestamp(time.time()).
|
||||
strftime("%Y_%m_%d_%H_%M_%S"))
|
||||
try:
|
||||
image = glanceclient.images.create(name=("cirros_%s" % now),
|
||||
disk_format="qcow2",
|
||||
container_format="bare")
|
||||
image.update(data=open(self.img_path, "rb"))
|
||||
image_list.append(image)
|
||||
except Exception as e:
|
||||
msg = _("There are no desired images (cirros) or only one and "
|
||||
"new image could not be created.\n"
|
||||
"Reason: %s") % getattr(e, "message", "unknown")
|
||||
raise TempestConfigCreationFailure(msg)
|
||||
self.conf.set(section_name, "image_ref", image_list[0].id)
|
||||
self.conf.set(section_name, "image_ref_alt", image_list[1].id)
|
||||
def _configure_default(self, section_name="DEFAULT"):
|
||||
# Nothing to configure in this section for now
|
||||
pass
|
||||
|
||||
def _set_compute_flavors(self, section_name="compute"):
|
||||
novaclient = self.clients.nova()
|
||||
flavor_list = sorted(novaclient.flavors.list(),
|
||||
key=lambda flv: flv.ram)
|
||||
# Create new flavors if they are missing
|
||||
while len(flavor_list) < 2:
|
||||
now = (datetime.datetime.fromtimestamp(time.time()).
|
||||
strftime("%Y_%m_%d_%H_%M_%S"))
|
||||
try:
|
||||
flv = novaclient.flavors.create("m1.tiny_%s" % now, 512, 1, 1)
|
||||
flavor_list.append(flv)
|
||||
except Exception as e:
|
||||
msg = _("There are no desired flavors or only one and "
|
||||
"new flavor could not be created.\n"
|
||||
"Reason: %s") % getattr(e, "message", "unknown")
|
||||
raise TempestConfigCreationFailure(msg)
|
||||
self.conf.set(section_name, "flavor_ref", flavor_list[0].id)
|
||||
self.conf.set(section_name, "flavor_ref_alt", flavor_list[1].id)
|
||||
def _configure_dashboard(self, section_name="dashboard"):
|
||||
url = "http://%s/" % parse.urlparse(self.endpoint["auth_url"]).hostname
|
||||
self.conf.set(section_name, "dashboard_url", url)
|
||||
|
||||
def _set_compute_ssh_connect_method(self, section_name="compute"):
|
||||
if "neutron" in self.available_services:
|
||||
self.conf.set(section_name, "ssh_connect_method", "floating")
|
||||
else:
|
||||
self.conf.set(section_name, "ssh_connect_method", "fixed")
|
||||
|
||||
def _set_identity(self, section_name="identity"):
|
||||
def _configure_identity(self, section_name="identity"):
|
||||
self.conf.set(section_name, "username", self.endpoint["username"])
|
||||
self.conf.set(section_name, "password", self.endpoint["password"])
|
||||
self.conf.set(section_name, "tenant_name",
|
||||
self.endpoint["tenant_name"])
|
||||
self.conf.set(section_name, "alt_username", self.endpoint["username"])
|
||||
self.conf.set(section_name, "alt_password", self.endpoint["password"])
|
||||
self.conf.set(section_name, "alt_tenant_name",
|
||||
self.endpoint["tenant_name"])
|
||||
|
||||
self.conf.set(section_name, "admin_username",
|
||||
self.endpoint["username"])
|
||||
self.conf.set(section_name, "admin_password",
|
||||
self.endpoint["password"])
|
||||
self.conf.set(section_name, "admin_tenant_name",
|
||||
self.endpoint["tenant_name"])
|
||||
|
||||
self.conf.set(section_name, "uri", self.endpoint["auth_url"])
|
||||
v2_url_trailer = parse.urlparse(self.endpoint["auth_url"]).path
|
||||
self.conf.set(section_name, "uri_v3",
|
||||
self.endpoint["auth_url"].replace("/v2.0", "/v3"))
|
||||
self.endpoint["auth_url"].replace(v2_url_trailer, "/v3"))
|
||||
|
||||
self.conf.set(section_name, "admin_domain_name",
|
||||
self.endpoint["admin_domain_name"])
|
||||
|
||||
def _set_network(self, section_name="network"):
|
||||
if "neutron" in self.available_services:
|
||||
neutron = self.clients.neutron()
|
||||
public_net = [net for net in neutron.list_networks()["networks"] if
|
||||
net["status"] == "ACTIVE" and
|
||||
net["router:external"] is True]
|
||||
if public_net:
|
||||
net_id = public_net[0]["id"]
|
||||
self.conf.set(section_name, "public_network_id", net_id)
|
||||
public_router = neutron.list_routers(
|
||||
network_id=net_id)["routers"][0]
|
||||
self.conf.set(section_name, "public_router_id",
|
||||
public_router["id"])
|
||||
subnets = neutron.list_subnets(network_id=net_id)["subnets"]
|
||||
if subnets:
|
||||
subnet = subnets[0]
|
||||
else:
|
||||
# TODO(akurilin): create public subnet
|
||||
LOG.warn("No public subnet is found.")
|
||||
else:
|
||||
subnets = neutron.list_subnets()["subnets"]
|
||||
if subnets:
|
||||
subnet = subnets[0]
|
||||
else:
|
||||
# TODO(akurilin): create subnet
|
||||
LOG.warn("No subnet is found.")
|
||||
self.conf.set(section_name, "tenant_network_cidr", subnet["cidr"])
|
||||
else:
|
||||
network = self.clients.nova().networks.list()[0]
|
||||
self.conf.set(section_name, "tenant_network_cidr", network.cidr)
|
||||
# The compute section is configured in context class for Tempest resources.
|
||||
# Options which are configured there: 'image_ref', 'image_ref_alt',
|
||||
# 'flavor_ref', 'flavor_ref_alt'.
|
||||
|
||||
def _set_service_available(self, section_name="service_available"):
|
||||
services = ["neutron", "heat", "ceilometer", "swift",
|
||||
"cinder", "nova", "glance"]
|
||||
def _configure_network(self, section_name="network"):
|
||||
if "neutron" in self.available_services:
|
||||
neutronclient = self.clients.neutron()
|
||||
public_nets = [net for net
|
||||
in neutronclient.list_networks()["networks"]
|
||||
if net["status"] == "ACTIVE" and
|
||||
net["router:external"] is True]
|
||||
if public_nets:
|
||||
net_id = public_nets[0]["id"]
|
||||
self.conf.set(section_name, "public_network_id", net_id)
|
||||
else:
|
||||
novaclient = self.clients.nova()
|
||||
net_name = next(net.human_id for net in novaclient.networks.list()
|
||||
if net.human_id is not None)
|
||||
self.conf.set("compute", "fixed_network_name", net_name)
|
||||
self.conf.set("compute", "network_for_ssh", net_name)
|
||||
|
||||
def _configure_network_feature_enabled(
|
||||
self, section_name="network-feature-enabled"):
|
||||
if "neutron" in self.available_services:
|
||||
neutronclient = self.clients.neutron()
|
||||
ext_list = [ext["alias"] for ext in
|
||||
neutronclient.list_ext("/extensions")["extensions"]]
|
||||
ext_list_str = ",".join(ext_list)
|
||||
self.conf.set(section_name, "api_extensions", ext_list_str)
|
||||
|
||||
def _configure_oslo_concurrency(self, section_name="oslo_concurrency"):
|
||||
lock_path = os.path.join(self.data_dir,
|
||||
"lock_files_%s" % self.deployment)
|
||||
if not os.path.exists(lock_path):
|
||||
os.makedirs(lock_path)
|
||||
self.conf.set(section_name, "lock_path", lock_path)
|
||||
|
||||
def _configure_object_storage(self, section_name="object-storage"):
|
||||
self.conf.set(section_name, "operator_role",
|
||||
CONF.role.swift_operator_role)
|
||||
self.conf.set(section_name, "reseller_admin_role",
|
||||
CONF.role.swift_reseller_admin_role)
|
||||
|
||||
def _configure_scenario(self, section_name="scenario"):
|
||||
self.conf.set(section_name, "img_dir", self.data_dir)
|
||||
self.conf.set(section_name, "img_file", IMAGE_NAME)
|
||||
|
||||
def _configure_service_available(self, section_name="service_available"):
|
||||
services = ["ceilometer", "cinder", "glance",
|
||||
"heat", "neutron", "nova", "sahara", "swift"]
|
||||
for service in services:
|
||||
# Convert boolean to string because ConfigParser fails
|
||||
# on attempt to get option with boolean value
|
||||
self.conf.set(section_name, service,
|
||||
str(service in self.available_services))
|
||||
horizon_url = ("http://" +
|
||||
parse.urlparse(self.endpoint["auth_url"]).hostname)
|
||||
try:
|
||||
horizon_req = requests.get(horizon_url)
|
||||
except requests.RequestException as e:
|
||||
LOG.debug("Failed to connect to Horizon: %s" % e)
|
||||
except requests.RequestException:
|
||||
LOG.debug("Horizon is unavailable!")
|
||||
horizon_availability = False
|
||||
else:
|
||||
horizon_availability = (horizon_req.status_code == 200)
|
||||
# convert boolean to string because ConfigParser fails
|
||||
# Convert boolean to string because ConfigParser fails
|
||||
# on attempt to get option with boolean value
|
||||
self.conf.set(section_name, "horizon", str(horizon_availability))
|
||||
|
||||
def write_config(self, file_name):
|
||||
with open(file_name, "w+") as f:
|
||||
self.conf.write(f)
|
||||
def _configure_validation(self, section_name="validation"):
|
||||
if "neutron" in self.available_services:
|
||||
self.conf.set(section_name, "connect_method", "floating")
|
||||
else:
|
||||
self.conf.set(section_name, "connect_method", "fixed")
|
||||
|
||||
def generate(self, file_name=None):
|
||||
for name, func in inspect.getmembers(self, predicate=inspect.ismethod):
|
||||
if name.startswith("_set_"):
|
||||
func()
|
||||
if file_name:
|
||||
self.write_config(file_name)
|
||||
def generate(self, conf_path=None):
|
||||
for name, method in inspect.getmembers(self, inspect.ismethod):
|
||||
if name.startswith("_configure_"):
|
||||
method()
|
||||
|
||||
return self.conf
|
||||
if conf_path:
|
||||
_write_config(conf_path, self.conf)
|
||||
|
||||
|
||||
class TempestResourcesContext(object):
|
||||
"""Context class to create/delete resources needed for Tempest."""
|
||||
|
||||
def __init__(self, deployment, conf_path):
|
||||
endpoint = db.deployment_get(deployment)["admin"]
|
||||
self.clients = osclients.Clients(objects.Endpoint(**endpoint))
|
||||
self.keystone = self.clients.verified_keystone()
|
||||
|
||||
self.conf_path = conf_path
|
||||
self.conf = configparser.ConfigParser()
|
||||
self.conf.read(conf_path)
|
||||
|
||||
def __enter__(self):
|
||||
self._created_roles = []
|
||||
self._created_images = []
|
||||
self._created_flavors = []
|
||||
|
||||
self._create_tempest_roles()
|
||||
self._configure_option("image_ref", self._create_image)
|
||||
self._configure_option("image_ref_alt", self._create_image)
|
||||
self._configure_option("flavor_ref", self._create_flavor, 64)
|
||||
self._configure_option("flavor_ref_alt", self._create_flavor, 128)
|
||||
|
||||
_write_config(self.conf_path, self.conf)
|
||||
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
self._cleanup_roles()
|
||||
self._cleanup_resource("image", self._created_images)
|
||||
self._cleanup_resource("flavor", self._created_flavors)
|
||||
|
||||
def _create_tempest_roles(self):
|
||||
roles = [CONF.role.swift_operator_role,
|
||||
CONF.role.swift_reseller_admin_role,
|
||||
CONF.role.heat_stack_owner_role,
|
||||
CONF.role.heat_stack_user_role]
|
||||
existing_roles = set(role.name for role in self.keystone.roles.list())
|
||||
|
||||
for role in roles:
|
||||
if role not in existing_roles:
|
||||
LOG.debug("Creating role '%s'" % role)
|
||||
self._created_roles.append(self.keystone.roles.create(role))
|
||||
|
||||
def _configure_option(self, option, create_method, *args, **kwargs):
|
||||
option_value = self.conf.get("compute", option)
|
||||
if not option_value:
|
||||
LOG.debug("Option '%s' is not configured" % option)
|
||||
resource = create_method(*args, **kwargs)
|
||||
self.conf.set("compute", option, resource.id)
|
||||
LOG.debug("Option '{opt}' is configured. {opt} = {resource_id}"
|
||||
.format(opt=option, resource_id=resource.id))
|
||||
else:
|
||||
LOG.debug("Option '{opt}' was configured manually "
|
||||
"in Tempest config file. {opt} = {opt_val}"
|
||||
.format(opt=option, opt_val=option_value))
|
||||
|
||||
def _create_image(self):
|
||||
glanceclient = self.clients.glance()
|
||||
image_name = "rally-verify-cirros-img-%s" % uuid.uuid4()
|
||||
LOG.debug("Creating image '%s'" % image_name)
|
||||
try:
|
||||
image = glanceclient.images.create(
|
||||
name=image_name,
|
||||
disk_format="qcow2",
|
||||
container_format="bare",
|
||||
is_public=True)
|
||||
self._created_images.append(image)
|
||||
image.update(data=open(
|
||||
os.path.join(_create_or_get_data_dir(), IMAGE_NAME), "rb"))
|
||||
except Exception as exc:
|
||||
msg = _("Image could not be created. "
|
||||
"Reason: %s") % (str(exc) or "unknown")
|
||||
raise exceptions.TempestResourceCreationFailure(msg)
|
||||
|
||||
return image
|
||||
|
||||
def _create_flavor(self, flv_ram):
|
||||
novaclient = self.clients.nova()
|
||||
flavor_name = "m1.rally-verify-flv-%s" % uuid.uuid4()
|
||||
LOG.debug("Creating flavor '%s'" % flavor_name)
|
||||
try:
|
||||
flavor = novaclient.flavors.create(
|
||||
flavor_name, ram=flv_ram, vcpus=1, disk=0)
|
||||
except Exception as exc:
|
||||
msg = _("Flavor could not be created. "
|
||||
"Reason: %s") % (str(exc) or "unknown")
|
||||
raise exceptions.TempestResourceCreationFailure(msg)
|
||||
|
||||
self._created_flavors.append(flavor)
|
||||
|
||||
return flavor
|
||||
|
||||
def _cleanup_roles(self):
|
||||
for role in self._created_roles:
|
||||
LOG.debug("Deleting role '%s'" % role.name)
|
||||
role.delete()
|
||||
|
||||
def _cleanup_resource(self, resource_type, created_resources):
|
||||
for res in created_resources:
|
||||
LOG.debug("Deleting %s '%s'" % (resource_type, res.name))
|
||||
if res.id == self.conf.get("compute", "%s_ref" % resource_type):
|
||||
self.conf.set("compute", "%s_ref" % resource_type, "")
|
||||
else:
|
||||
self.conf.set("compute", "%s_ref_alt" % resource_type, "")
|
||||
res.delete()
|
||||
|
||||
_write_config(self.conf_path, self.conf)
|
||||
|
@ -229,7 +229,7 @@ class Tempest(object):
|
||||
msg = _("Creation of configuration file for tempest.")
|
||||
LOG.info(_("Starting: ") + msg)
|
||||
|
||||
config.TempestConf(self.deployment).generate(self.config_file)
|
||||
config.TempestConfig(self.deployment).generate(self.config_file)
|
||||
LOG.info(_("Completed: ") + msg)
|
||||
else:
|
||||
LOG.info("Tempest is already configured.")
|
||||
@ -345,6 +345,10 @@ class Tempest(object):
|
||||
"log_file": log_file or self.log_file_raw
|
||||
})
|
||||
LOG.debug("Test(s) started by the command: %s" % test_cmd)
|
||||
# Create all resources needed for Tempest before running tests.
|
||||
# Once tests finish, all created resources will be deleted.
|
||||
with config.TempestResourcesContext(self.deployment, self.config_file):
|
||||
# Run tests
|
||||
subprocess.check_call(test_cmd, cwd=self.path(),
|
||||
env=self.env, shell=True)
|
||||
|
||||
|
@ -62,27 +62,26 @@
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vr_1_html}">[${vr_1_html}]</span>
|
||||
<a href="rally-verify/1_verify_results.html.gz">Display raw results in HTML</a>
|
||||
<a href="rally-verify/1_verify_results_compute_set.html.gz">Display raw results in HTML</a>
|
||||
<code>$ rally verify results --html</code>
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vr_1_json}">[${vr_1_json}]</span>
|
||||
<a href="rally-verify/1_verify_results.json.gz">Display raw results in JSON</a>
|
||||
<a href="rally-verify/1_verify_results_compute_set.json.gz">Display raw results in JSON</a>
|
||||
<code>$ rally verify results --json</code>
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vs_1}">[${vs_1}]</span>
|
||||
<a href="rally-verify/1_verify_show.txt.gz">Display results table of the verification</a>
|
||||
<a href="rally-verify/1_verify_show_compute_set.txt.gz">Display results table of the verification</a>
|
||||
<code>$ rally verify show</code>
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vsd_1}">[${vsd_1}]</span>
|
||||
<a href="rally-verify/1_verify_show_detailed.txt.gz">Display results table of the verification with detailed errors</a><br />
|
||||
<a href="rally-verify/1_verify_show_compute_set_detailed.txt.gz">Display results table of the verification with detailed errors</a><br />
|
||||
<code style="display: inline">$ rally verify show --detailed</code> or <code style="display: inline">$ rally verify detailed</code>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
||||
Second verification run
|
||||
<ol>
|
||||
<li>
|
||||
@ -92,22 +91,22 @@
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vr_2_html}">[${vr_2_html}]</span>
|
||||
<a href="rally-verify/2_verify_results.html.gz">Display results in HTML</a>
|
||||
<a href="rally-verify/2_verify_results_compute_set.html.gz">Display results in HTML</a>
|
||||
<code>$ rally verify results --html</code>
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vr_2_json}">[${vr_2_json}]</span>
|
||||
<a href="rally-verify/2_verify_results.json.gz">Display results in JSON</a>
|
||||
<a href="rally-verify/2_verify_results_compute_set.json.gz">Display results in JSON</a>
|
||||
<code>$ rally verify results --json</code>
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vs_2}">[${vs_2}]</span>
|
||||
<a href="rally-verify/2_verify_show.txt.gz">Display table results of the verification</a>
|
||||
<a href="rally-verify/2_verify_show_compute_set.txt.gz">Display table results of the verification</a>
|
||||
<code>$ rally verify show</code>
|
||||
</li>
|
||||
<li>
|
||||
<span class="${vsd_2}">[${vsd_2}]</span>
|
||||
<a href="rally-verify/2_verify_show_detailed.txt.gz">Display table results of the verification with detailed errors</a><br />
|
||||
<a href="rally-verify/2_verify_show_compute_set_detailed.txt.gz">Display table results of the verification with detailed errors</a><br />
|
||||
<code style="display: inline">$ rally verify show --detailed</code> or <code style="display: inline">$ rally verify detailed</code>
|
||||
</li>
|
||||
</ol>
|
||||
|
@ -48,8 +48,8 @@ gzip -9 ${RESULTS_DIR}/tempest_installation.txt
|
||||
gzip -9 ${RESULTS_DIR}/tempest_config_generation.txt
|
||||
|
||||
function do_verification {
|
||||
OUTPUT_FILE=${RESULTS_DIR}/${1}_verification_${SET_NAME}_set.txt
|
||||
rally --rally-debug verify start --regex tempest.api.compute.servers.test_servers > ${OUTPUT_FILE} 2>&1
|
||||
OUTPUT_FILE=${RESULTS_DIR}/${1}_verification_${2}_set.txt
|
||||
rally --rally-debug verify start --set ${2} > ${OUTPUT_FILE} 2>&1
|
||||
RESULTS+="v${1}=$(do_status $?) "
|
||||
gzip -9 ${OUTPUT_FILE}
|
||||
source ~/.rally/globals && VERIFICATIONS[${1}]=${RALLY_VERIFICATION}
|
||||
@ -57,24 +57,24 @@ function do_verification {
|
||||
# Check different "rally verify" commands, which displays verification results
|
||||
for OUTPUT_FORMAT in "html" "json"
|
||||
do
|
||||
OUTPUT_FILE=${RESULTS_DIR}/${1}_verify_results.${OUTPUT_FORMAT}
|
||||
OUTPUT_FILE=${RESULTS_DIR}/${1}_verify_results_${2}_set.${OUTPUT_FORMAT}
|
||||
rally verify results --uuid ${RALLY_VERIFICATION} --${OUTPUT_FORMAT} --output-file ${OUTPUT_FILE}
|
||||
RESULTS+="vr_${1}_${OUTPUT_FORMAT}=$(do_status $?) "
|
||||
gzip -9 ${OUTPUT_FILE}
|
||||
done
|
||||
|
||||
rally verify show --uuid ${RALLY_VERIFICATION} > ${RESULTS_DIR}/${1}_verify_show.txt
|
||||
rally verify show --uuid ${RALLY_VERIFICATION} > ${RESULTS_DIR}/${1}_verify_show_${2}_set.txt
|
||||
RESULTS+="vs_${1}=$(do_status $?) "
|
||||
gzip -9 ${RESULTS_DIR}/${1}_verify_show.txt
|
||||
gzip -9 ${RESULTS_DIR}/${1}_verify_show_${2}_set.txt
|
||||
|
||||
rally verify show --uuid ${RALLY_VERIFICATION} --detailed > ${RESULTS_DIR}/${1}_verify_show_detailed.txt
|
||||
rally verify show --uuid ${RALLY_VERIFICATION} --detailed > ${RESULTS_DIR}/${1}_verify_show_${2}_set_detailed.txt
|
||||
RESULTS+="vsd_${1}=$(do_status $?) "
|
||||
gzip -9 ${RESULTS_DIR}/${1}_verify_show_detailed.txt
|
||||
gzip -9 ${RESULTS_DIR}/${1}_verify_show_${2}_set_detailed.txt
|
||||
}
|
||||
|
||||
function main {
|
||||
do_verification 1
|
||||
do_verification 2
|
||||
do_verification 1 compute
|
||||
do_verification 2 compute
|
||||
|
||||
rally verify list > ${RESULTS_DIR}/verify_list.txt
|
||||
RESULTS+="l=$(do_status $?) "
|
||||
|
@ -17,7 +17,6 @@ import mock
|
||||
|
||||
from rally import exceptions
|
||||
from rally.plugins.openstack.context.not_for_production import tempest
|
||||
from rally.verification.tempest import config
|
||||
from rally.verification.tempest import tempest as tempest_verifier
|
||||
from tests.unit import test
|
||||
|
||||
@ -75,7 +74,7 @@ class TempestContextTestCase(test.TestCase):
|
||||
self, mock_tempest_generate_config_file, mock_tempest_is_installed,
|
||||
mock_tempest_is_configured, mock_mkdir):
|
||||
mock_tempest_generate_config_file.side_effect = (
|
||||
config.TempestConfigCreationFailure()
|
||||
exceptions.TempestConfigCreationFailure()
|
||||
)
|
||||
|
||||
benchmark = tempest.Tempest(self.context)
|
||||
|
@ -19,7 +19,8 @@ from rally.plugins.openstack.scenarios.tempest import tempest
|
||||
from rally.verification.tempest import tempest as verifier
|
||||
from tests.unit import test
|
||||
|
||||
VERIFIER = "rally.verification.tempest.tempest"
|
||||
TEMPEST_DIR = "rally.verification.tempest"
|
||||
VERIFIER = TEMPEST_DIR + ".tempest"
|
||||
TS = "rally.plugins.openstack.scenarios.tempest"
|
||||
|
||||
|
||||
@ -51,7 +52,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_single_test(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_single_test(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
fake_test = "tempest.api.fake.test"
|
||||
|
||||
@ -64,7 +67,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_single_test_negative(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_single_test_negative(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
fake_test = "tempest.api.network"
|
||||
|
||||
@ -77,7 +82,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_single_test_without_prefix(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_single_test_without_prefix(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
|
||||
self.scenario.single_test("network")
|
||||
@ -89,7 +96,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_all(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_all(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
|
||||
self.scenario.all()
|
||||
@ -101,7 +110,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_set_smoke(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_set_smoke(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
|
||||
self.scenario.set("smoke")
|
||||
@ -113,7 +124,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_set_full(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_set_full(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
|
||||
self.scenario.set("full")
|
||||
@ -124,7 +137,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
env=self.verifier.env, shell=True)
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
def test_set_from_list(self, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_set_from_list(self, mock_tempest_resources_context,
|
||||
mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
|
||||
fake_scenarios = ["network", "volume", "baremetal",
|
||||
@ -143,7 +158,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_set_selective(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_set_selective(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
|
||||
self.scenario.set("network")
|
||||
@ -155,7 +172,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_list_of_tests(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_list_of_tests(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
fake_tests = ["tempest.fake.test1", "tempest.fake.test2"]
|
||||
|
||||
@ -168,7 +187,9 @@ class TempestScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(TS + ".utils.tempfile")
|
||||
@mock.patch(VERIFIER + ".subprocess")
|
||||
def test_specific_regex(self, mock_subprocess, mock_tempfile):
|
||||
@mock.patch(TEMPEST_DIR + ".config.TempestResourcesContext")
|
||||
def test_specific_regex(self, mock_tempest_resources_context,
|
||||
mock_subprocess, mock_tempfile):
|
||||
mock_tempfile.NamedTemporaryFile().name = "/dev/null"
|
||||
regex = "tempest.fake.test1"
|
||||
|
||||
|
@ -19,6 +19,7 @@ import mock
|
||||
from oslo_config import cfg
|
||||
import requests
|
||||
|
||||
from rally import exceptions
|
||||
from rally.verification.tempest import config
|
||||
from tests.unit import fakes
|
||||
from tests.unit import test
|
||||
@ -37,23 +38,31 @@ class ConfigTestCase(test.TestCase):
|
||||
def setUp(self, mock_isfile, mock_clients_verified_keystone,
|
||||
mock_clients_services, mock_deployment_get):
|
||||
super(ConfigTestCase, self).setUp()
|
||||
self.endpoint = {"username": "test",
|
||||
|
||||
self.endpoint = {
|
||||
"username": "test",
|
||||
"tenant_name": "test",
|
||||
"password": "test",
|
||||
"auth_url": "http://test/v2.0",
|
||||
"auth_url": "http://test/v2.0/",
|
||||
"permission": "admin",
|
||||
"admin_domain_name": "Default"}
|
||||
"admin_domain_name": "Default"
|
||||
}
|
||||
mock_deployment_get.return_value = {"admin": self.endpoint}
|
||||
|
||||
self.deployment = "fake_deployment"
|
||||
self.conf_generator = config.TempestConf(self.deployment)
|
||||
self.conf_generator = config.TempestConfig(self.deployment)
|
||||
self.conf_generator.clients.services = mock_clients_services
|
||||
self.context = config.TempestResourcesContext(self.deployment,
|
||||
"/path/to/fake/conf")
|
||||
self.context.conf.add_section("compute")
|
||||
|
||||
keystone_patcher = mock.patch("rally.osclients.create_keystone_client")
|
||||
keystone_patcher.start()
|
||||
self.addCleanup(keystone_patcher.stop)
|
||||
|
||||
def _remove_default_section(self, items):
|
||||
# getting items from configparser by specified section name
|
||||
@staticmethod
|
||||
def _remove_default_section(items):
|
||||
# Getting items from config parser by specified section name
|
||||
# returns also values from DEFAULT section
|
||||
defaults = (("log_file", "tempest.log"), ("debug", "True"),
|
||||
("use_stderr", "False"))
|
||||
@ -63,269 +72,223 @@ class ConfigTestCase(test.TestCase):
|
||||
@mock.patch("rally.verification.tempest.config.os.rename")
|
||||
@mock.patch("six.moves.builtins.open", side_effect=mock.mock_open(),
|
||||
create=True)
|
||||
def test__load_img_success(self, mock_open, mock_rename, mock_requests):
|
||||
def test__download_cirros_image_success(self, mock_open, mock_rename,
|
||||
mock_requests):
|
||||
mock_result = mock.MagicMock()
|
||||
mock_result.status_code = 200
|
||||
mock_requests.get.return_value = mock_result
|
||||
self.conf_generator._load_img()
|
||||
cirros_url = ("http://download.cirros-cloud.net/%s/%s" %
|
||||
(CONF.image.cirros_version,
|
||||
CONF.image.cirros_image))
|
||||
mock_requests.get.assert_called_once_with(cirros_url, stream=True)
|
||||
self.conf_generator._download_cirros_image()
|
||||
mock_requests.get.assert_called_once_with(CONF.image.cirros_img_url,
|
||||
stream=True)
|
||||
|
||||
@mock.patch("rally.verification.tempest.config.requests")
|
||||
def test__load_img_notfound(self, mock_requests):
|
||||
def test__download_cirros_image_notfound(self, mock_requests):
|
||||
mock_result = mock.MagicMock()
|
||||
mock_result.status_code = 404
|
||||
mock_requests.get.return_value = mock_result
|
||||
self.assertRaises(config.TempestConfigCreationFailure,
|
||||
self.conf_generator._load_img)
|
||||
self.assertRaises(exceptions.TempestConfigCreationFailure,
|
||||
self.conf_generator._download_cirros_image)
|
||||
|
||||
def test__get_url(self):
|
||||
def test__get_service_url(self):
|
||||
service = "test_service"
|
||||
service_type = "test_service_type"
|
||||
url = "test_url"
|
||||
# mocked at setUp
|
||||
self.conf_generator.keystoneclient.auth_ref = {
|
||||
"serviceCatalog": [{
|
||||
# Mocked at setUp
|
||||
self.conf_generator.keystone.auth_ref = {
|
||||
"serviceCatalog": [
|
||||
{
|
||||
"name": service,
|
||||
"type": service_type,
|
||||
"endpoints": [{"publicURL": url}]
|
||||
}]}
|
||||
self.assertEqual(self.conf_generator._get_url(service), url)
|
||||
}
|
||||
]
|
||||
}
|
||||
self.assertEqual(self.conf_generator._get_service_url(service), url)
|
||||
|
||||
@mock.patch("rally.verification.tempest.config.TempestConf"
|
||||
"._get_url")
|
||||
def test__set_boto(self, mock_tempest_conf__get_url):
|
||||
@mock.patch("rally.verification.tempest."
|
||||
"config.TempestConfig._get_service_url")
|
||||
def test__configure_boto(self, mock_tempest_config__get_service_url):
|
||||
url = "test_url"
|
||||
mock_tempest_conf__get_url.return_value = url
|
||||
self.conf_generator._set_boto()
|
||||
mock_tempest_config__get_service_url.return_value = url
|
||||
s3_materials_path = os.path.join(
|
||||
self.conf_generator.data_dir, "s3materials")
|
||||
self.conf_generator._configure_boto()
|
||||
expected = (("ec2_url", url),
|
||||
("s3_url", url),
|
||||
("build_interval", "1"),
|
||||
("build_timeout", "196"),
|
||||
("http_socket_timeout", "30"),
|
||||
("instance_type", "m1.nano"),
|
||||
("s3_materials_path",
|
||||
os.path.join(self.conf_generator.data_path,
|
||||
"s3materials")))
|
||||
("s3_materials_path", s3_materials_path))
|
||||
results = self._remove_default_section(
|
||||
self.conf_generator.conf.items("boto"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__set_compute_flavors(self):
|
||||
mock_novaclient = mock.MagicMock()
|
||||
mock_novaclient.flavors.list.return_value = [
|
||||
fakes.FakeFlavor(id="id1"), fakes.FakeFlavor(id="id2")]
|
||||
mock_nova = mock.MagicMock()
|
||||
mock_nova.client.Client.return_value = mock_novaclient
|
||||
with mock.patch.dict("sys.modules", {"novaclient": mock_nova}):
|
||||
self.conf_generator._set_compute_flavors()
|
||||
expected = ("id1", "id2")
|
||||
results = (self.conf_generator.conf.get("compute", "flavor_ref"),
|
||||
self.conf_generator.conf.get("compute",
|
||||
"flavor_ref_alt"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__set_compute_flavors_create(self):
|
||||
mock_novaclient = mock.MagicMock()
|
||||
mock_novaclient.flavors.list.return_value = []
|
||||
mock_novaclient.flavors.create.side_effect = [
|
||||
fakes.FakeFlavor(id="id1"), fakes.FakeFlavor(id="id2")]
|
||||
mock_nova = mock.MagicMock()
|
||||
mock_nova.client.Client.return_value = mock_novaclient
|
||||
with mock.patch.dict("sys.modules", {"novaclient": mock_nova}):
|
||||
self.conf_generator._set_compute_flavors()
|
||||
self.assertEqual(mock_novaclient.flavors.create.call_count, 2)
|
||||
expected = ("id1", "id2")
|
||||
results = (self.conf_generator.conf.get("compute", "flavor_ref"),
|
||||
self.conf_generator.conf.get("compute",
|
||||
"flavor_ref_alt"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__set_compute_flavors_create_fails(self):
|
||||
mock_novaclient = mock.MagicMock()
|
||||
mock_novaclient.flavors.list.return_value = []
|
||||
mock_novaclient.flavors.create.side_effect = Exception()
|
||||
mock_nova = mock.MagicMock()
|
||||
mock_nova.client.Client.return_value = mock_novaclient
|
||||
with mock.patch.dict("sys.modules", {"novaclient": mock_nova}):
|
||||
self.assertRaises(config.TempestConfigCreationFailure,
|
||||
self.conf_generator._set_compute_flavors)
|
||||
|
||||
def test__set_compute_images(self):
|
||||
mock_glanceclient = mock.MagicMock()
|
||||
mock_glanceclient.images.list.return_value = [
|
||||
fakes.FakeImage(id="id1", name="cirros1"),
|
||||
fakes.FakeImage(id="id2", name="cirros2")]
|
||||
mock_glance = mock.MagicMock()
|
||||
mock_glance.Client.return_value = mock_glanceclient
|
||||
with mock.patch.dict("sys.modules", {"glanceclient": mock_glance}):
|
||||
self.conf_generator._set_compute_images()
|
||||
expected = ("id1", "id2")
|
||||
results = (self.conf_generator.conf.get("compute", "image_ref"),
|
||||
self.conf_generator.conf.get("compute",
|
||||
"image_ref_alt"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
@mock.patch("six.moves.builtins.open")
|
||||
def test__set_compute_images_create(self, mock_open):
|
||||
mock_glanceclient = mock.MagicMock()
|
||||
mock_glanceclient.images.list.return_value = []
|
||||
mock_glanceclient.images.create.side_effect = [
|
||||
fakes.FakeImage(id="id1"), fakes.FakeImage(id="id2")]
|
||||
mock_glance = mock.MagicMock()
|
||||
mock_glance.Client.return_value = mock_glanceclient
|
||||
with mock.patch.dict("sys.modules", {"glanceclient": mock_glance}):
|
||||
self.conf_generator._set_compute_images()
|
||||
self.assertEqual(mock_glanceclient.images.create.call_count, 2)
|
||||
expected = ("id1", "id2")
|
||||
results = (self.conf_generator.conf.get("compute", "image_ref"),
|
||||
self.conf_generator.conf.get("compute",
|
||||
"image_ref_alt"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__set_compute_images_create_fails(self):
|
||||
mock_glanceclient = mock.MagicMock()
|
||||
mock_glanceclient.images.list.return_value = []
|
||||
mock_glanceclient.images.create.side_effect = Exception()
|
||||
mock_glance = mock.MagicMock()
|
||||
mock_glance.Client.return_value = mock_glanceclient
|
||||
with mock.patch.dict("sys.modules", {"glanceclient": mock_glance}):
|
||||
self.assertRaises(config.TempestConfigCreationFailure,
|
||||
self.conf_generator._set_compute_images)
|
||||
|
||||
def test__set_compute_ssh_connect_method_if_neutron(self):
|
||||
self.conf_generator._set_compute_ssh_connect_method()
|
||||
self.assertEqual("fixed",
|
||||
self.conf_generator.conf.get("compute",
|
||||
"ssh_connect_method"))
|
||||
# if neutron is available
|
||||
self.conf_generator.available_services = ["neutron"]
|
||||
self.conf_generator._set_compute_ssh_connect_method()
|
||||
self.assertEqual("floating",
|
||||
self.conf_generator.conf.get("compute",
|
||||
"ssh_connect_method"))
|
||||
|
||||
def test__set_default(self):
|
||||
self.conf_generator._set_default()
|
||||
def test__configure_default(self):
|
||||
self.conf_generator._configure_default()
|
||||
expected = (("debug", "True"), ("log_file", "tempest.log"),
|
||||
("use_stderr", "False"))
|
||||
results = self.conf_generator.conf.items("DEFAULT")
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__configure_identity(self):
|
||||
self.conf_generator._configure_identity()
|
||||
expected = (
|
||||
("username", self.endpoint["username"]),
|
||||
("password", self.endpoint["password"]),
|
||||
("tenant_name", self.endpoint["tenant_name"]),
|
||||
("admin_username", self.endpoint["username"]),
|
||||
("admin_password", self.endpoint["password"]),
|
||||
("admin_tenant_name", self.endpoint["username"]),
|
||||
("admin_domain_name", self.endpoint["admin_domain_name"]),
|
||||
("uri", self.endpoint["auth_url"]),
|
||||
("uri_v3", self.endpoint["auth_url"].replace("/v2.0/", "/v3")))
|
||||
results = self._remove_default_section(
|
||||
self.conf_generator.conf.items("identity"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__configure_option_flavor(self):
|
||||
mock_novaclient = mock.MagicMock()
|
||||
mock_novaclient.flavors.create.side_effect = [
|
||||
fakes.FakeFlavor(id="id1"), fakes.FakeFlavor(id="id2")]
|
||||
mock_nova = mock.MagicMock()
|
||||
mock_nova.client.Client.return_value = mock_novaclient
|
||||
self.context.conf.set("compute", "flavor_ref", "")
|
||||
self.context.conf.set("compute", "flavor_ref_alt", "")
|
||||
with mock.patch.dict("sys.modules", {"novaclient": mock_nova}):
|
||||
self.context._configure_option("flavor_ref",
|
||||
mock_novaclient.flavors.create, 64)
|
||||
self.context._configure_option("flavor_ref_alt",
|
||||
mock_novaclient.flavors.create, 128)
|
||||
self.assertEqual(mock_novaclient.flavors.create.call_count, 2)
|
||||
expected = ("id1", "id2")
|
||||
results = (self.context.conf.get("compute", "flavor_ref"),
|
||||
self.context.conf.get("compute", "flavor_ref_alt"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
@mock.patch("six.moves.builtins.open")
|
||||
def test__configure_option_image(self, mock_open):
|
||||
mock_glanceclient = mock.MagicMock()
|
||||
mock_glanceclient.images.create.side_effect = [
|
||||
fakes.FakeImage(id="id1"), fakes.FakeImage(id="id2")]
|
||||
mock_glance = mock.MagicMock()
|
||||
mock_glance.Client.return_value = mock_glanceclient
|
||||
self.context.conf.set("compute", "image_ref", "")
|
||||
self.context.conf.set("compute", "image_ref_alt", "")
|
||||
with mock.patch.dict("sys.modules", {"glanceclient": mock_glance}):
|
||||
self.context._configure_option("image_ref",
|
||||
mock_glanceclient.images.create)
|
||||
self.context._configure_option("image_ref_alt",
|
||||
mock_glanceclient.images.create)
|
||||
self.assertEqual(mock_glanceclient.images.create.call_count, 2)
|
||||
expected = ("id1", "id2")
|
||||
results = (self.context.conf.get("compute", "image_ref"),
|
||||
self.context.conf.get("compute", "image_ref_alt"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__configure_network_if_neutron(self):
|
||||
fake_neutronclient = mock.MagicMock()
|
||||
fake_neutronclient.list_networks.return_value = {
|
||||
"networks": [
|
||||
{
|
||||
"status": "ACTIVE",
|
||||
"id": "test_id",
|
||||
"router:external": True
|
||||
}
|
||||
]
|
||||
}
|
||||
mock_neutron = mock.MagicMock()
|
||||
mock_neutron.client.Client.return_value = fake_neutronclient
|
||||
with mock.patch.dict("sys.modules", {"neutronclient.neutron":
|
||||
mock_neutron}):
|
||||
self.conf_generator.available_services = ["neutron"]
|
||||
self.conf_generator._configure_network()
|
||||
expected = (("public_network_id", "test_id"),)
|
||||
results = self._remove_default_section(
|
||||
self.conf_generator.conf.items("network"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__configure_network_if_nova(self):
|
||||
self.conf_generator.available_services = ["nova"]
|
||||
mock_novaclient = mock.MagicMock()
|
||||
mock_network = mock.MagicMock()
|
||||
mock_network.human_id = "fake-network"
|
||||
mock_novaclient.networks.list.return_value = [mock_network]
|
||||
mock_nova = mock.MagicMock()
|
||||
mock_nova.client.Client.return_value = mock_novaclient
|
||||
with mock.patch.dict("sys.modules", {"novaclient": mock_nova}):
|
||||
self.conf_generator._configure_network()
|
||||
self.assertEqual("fake-network",
|
||||
self.conf_generator.conf.get(
|
||||
"compute", "fixed_network_name"))
|
||||
self.assertEqual("fake-network",
|
||||
self.conf_generator.conf.get(
|
||||
"compute", "network_for_ssh"))
|
||||
|
||||
@mock.patch("rally.verification.tempest.config.os.path.exists",
|
||||
return_value=False)
|
||||
@mock.patch("rally.verification.tempest.config.os.makedirs")
|
||||
def test__set_oslo_concurrency(self, mock_makedirs, mock_exists):
|
||||
self.conf_generator._set_oslo_concurrency()
|
||||
lock_path = os.path.join(self.conf_generator.data_path, "lock_files_%s"
|
||||
% self.deployment)
|
||||
def test__configure_oslo_concurrency(self, mock_makedirs, mock_exists):
|
||||
self.conf_generator._configure_oslo_concurrency()
|
||||
lock_path = os.path.join(
|
||||
self.conf_generator.data_dir, "lock_files_%s" % self.deployment)
|
||||
mock_makedirs.assert_called_once_with(lock_path)
|
||||
expected = (("lock_path", lock_path),)
|
||||
results = self._remove_default_section(
|
||||
self.conf_generator.conf.items("oslo_concurrency"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__set_identity(self):
|
||||
self.conf_generator._set_identity()
|
||||
expected = (("username", self.endpoint["username"]),
|
||||
("password", self.endpoint["password"]),
|
||||
("tenant_name", self.endpoint["tenant_name"]),
|
||||
("alt_username", self.endpoint["username"]),
|
||||
("alt_password", self.endpoint["password"]),
|
||||
("alt_tenant_name", self.endpoint["tenant_name"]),
|
||||
("admin_username", self.endpoint["username"]),
|
||||
("admin_password", self.endpoint["password"]),
|
||||
("admin_tenant_name", self.endpoint["username"]),
|
||||
("admin_domain_name", self.endpoint["admin_domain_name"]),
|
||||
("uri", self.endpoint["auth_url"]),
|
||||
("uri_v3", self.endpoint["auth_url"].replace("/v2.0",
|
||||
"/v3")))
|
||||
results = self._remove_default_section(
|
||||
self.conf_generator.conf.items("identity"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__set_network_if_neutron(self):
|
||||
fake_neutronclient = mock.MagicMock()
|
||||
fake_neutronclient.list_networks.return_value = {"networks": [
|
||||
{"status": "ACTIVE",
|
||||
"id": "test_id",
|
||||
"router:external":
|
||||
True}]}
|
||||
fake_neutronclient.list_routers.return_value = {"routers": [
|
||||
{"id": "test_router"}]}
|
||||
fake_neutronclient.list_subnets.return_value = {"subnets": [
|
||||
{"cidr":
|
||||
"10.0.0.0/24"}]}
|
||||
mock_neutron = mock.MagicMock()
|
||||
mock_neutron.client.Client.return_value = fake_neutronclient
|
||||
with mock.patch.dict("sys.modules", {"neutronclient.neutron":
|
||||
mock_neutron}):
|
||||
self.conf_generator.available_services = ["neutron"]
|
||||
self.conf_generator._set_network()
|
||||
expected = (("tenant_network_cidr", "10.0.0.0/24"),
|
||||
("tenant_networks_reachable", "False"),
|
||||
("public_network_id", "test_id"),
|
||||
("public_router_id", "test_router"))
|
||||
results = self._remove_default_section(
|
||||
self.conf_generator.conf.items("network"))
|
||||
self.assertEqual(sorted(expected), sorted(results))
|
||||
|
||||
def test__set_network_if_nova(self):
|
||||
network = "10.0.0.0/24"
|
||||
mock_novaclient = mock.MagicMock()
|
||||
mock_network = mock.MagicMock()
|
||||
mock_network.cidr = network
|
||||
mock_novaclient.networks.list.return_value = [mock_network]
|
||||
mock_nova = mock.MagicMock()
|
||||
mock_nova.client.Client.return_value = mock_novaclient
|
||||
with mock.patch.dict("sys.modules", {"novaclient": mock_nova}):
|
||||
self.conf_generator._set_network()
|
||||
self.assertEqual(network,
|
||||
self.conf_generator.conf.get(
|
||||
"network", "tenant_network_cidr"))
|
||||
|
||||
@mock.patch("rally.verification.tempest.config.requests")
|
||||
def test__set_service_available(self, mock_requests):
|
||||
def test__configure_service_available(self, mock_requests):
|
||||
mock_result = mock.MagicMock()
|
||||
mock_result.status_code = 404
|
||||
mock_requests.get.return_value = mock_result
|
||||
available_services = ("nova", "cinder", "glance")
|
||||
available_services = ("nova", "cinder", "glance", "sahara")
|
||||
self.conf_generator.available_services = available_services
|
||||
self.conf_generator._set_service_available()
|
||||
self.conf_generator._configure_service_available()
|
||||
expected = (("neutron", "False"), ("heat", "False"),
|
||||
("ceilometer", "False"), ("swift", "False"),
|
||||
("cinder", "True"), ("nova", "True"),
|
||||
("glance", "True"), ("horizon", "False"))
|
||||
("glance", "True"), ("horizon", "False"),
|
||||
("sahara", "True"))
|
||||
options = self._remove_default_section(
|
||||
self.conf_generator.conf.items("service_available"))
|
||||
self.assertEqual(sorted(expected), sorted(options))
|
||||
|
||||
@mock.patch("rally.verification.tempest.config.requests")
|
||||
def test__set_service_available_horizon(self, mock_requests):
|
||||
def test__configure_service_available_horizon(self, mock_requests):
|
||||
mock_result = mock.MagicMock()
|
||||
mock_result.status_code = 200
|
||||
mock_requests.get.return_value = mock_result
|
||||
self.conf_generator._set_service_available()
|
||||
self.assertEqual(self.conf_generator.conf.get(
|
||||
self.conf_generator._configure_service_available()
|
||||
self.assertEqual(
|
||||
self.conf_generator.conf.get(
|
||||
"service_available", "horizon"), "True")
|
||||
|
||||
@mock.patch("rally.verification.tempest.config.requests.get")
|
||||
def test__set_service_not_available_horizon(self, mock_get):
|
||||
def test__configure_service_not_available_horizon(self, mock_get):
|
||||
mock_get.side_effect = requests.Timeout()
|
||||
self.conf_generator._set_service_available()
|
||||
self.assertEqual(self.conf_generator.conf.get(
|
||||
self.conf_generator._configure_service_available()
|
||||
self.assertEqual(
|
||||
self.conf_generator.conf.get(
|
||||
"service_available", "horizon"), "False")
|
||||
|
||||
@mock.patch("six.moves.builtins.open", side_effect=mock.mock_open(),
|
||||
create=True)
|
||||
def test_write_config(self, mock_open):
|
||||
self.conf_generator.conf = mock.Mock()
|
||||
file_name = "/path/to/fake/conf"
|
||||
def test__configure_validation_if_neutron(self):
|
||||
# if neutron is available
|
||||
self.conf_generator.available_services = ["neutron"]
|
||||
self.conf_generator._configure_validation()
|
||||
self.assertEqual("floating",
|
||||
self.conf_generator.conf.get("validation",
|
||||
"connect_method"))
|
||||
|
||||
self.conf_generator.write_config(file_name)
|
||||
def test__configure_validation_if_novanetwork(self):
|
||||
self.conf_generator._configure_validation()
|
||||
self.assertEqual("fixed",
|
||||
self.conf_generator.conf.get("validation",
|
||||
"connect_method"))
|
||||
|
||||
mock_open.assert_called_once_with(file_name, "w+")
|
||||
self.conf_generator.conf.write.assert_called_once_with(
|
||||
mock_open.side_effect())
|
||||
@mock.patch("six.moves.builtins.open",
|
||||
side_effect=mock.mock_open(), create=True)
|
||||
def test__write_config(self, mock_open):
|
||||
conf_path = "/path/to/fake/conf"
|
||||
conf_data = mock.Mock()
|
||||
config._write_config(conf_path, conf_data)
|
||||
mock_open.assert_called_once_with(conf_path, "w+")
|
||||
conf_data.write.assert_called_once_with(mock_open.side_effect())
|
||||
|
@ -339,12 +339,14 @@ class TempestVerifyTestCase(BaseTestCase):
|
||||
return_value=(None, None))
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.Tempest.env")
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.subprocess")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestConf")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestResourcesContext")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestConfig")
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.Tempest.is_configured",
|
||||
return_value=False)
|
||||
def test_verify_not_configured(
|
||||
self, mock_tempest_is_configured, mock_tempest_conf,
|
||||
mock_subprocess, mock_tempest_env, mock_tempest_parse_results):
|
||||
self, mock_tempest_is_configured, mock_tempest_config,
|
||||
mock_tempest_resources_context, mock_subprocess, mock_tempest_env,
|
||||
mock_tempest_parse_results):
|
||||
|
||||
set_name = "compute"
|
||||
fake_call = self._get_fake_call(set_name)
|
||||
@ -352,8 +354,8 @@ class TempestVerifyTestCase(BaseTestCase):
|
||||
self.verifier.verify(set_name, None)
|
||||
|
||||
self.assertEqual(2, mock_tempest_is_configured.call_count)
|
||||
mock_tempest_conf.assert_called_once_with(self.verifier.deployment)
|
||||
mock_tempest_conf.return_value.generate.assert_called_once_with(
|
||||
mock_tempest_config.assert_called_once_with(self.verifier.deployment)
|
||||
mock_tempest_config.return_value.generate.assert_called_once_with(
|
||||
self.verifier.config_file
|
||||
)
|
||||
self.verifier.verification.start_verifying.assert_called_once_with(
|
||||
@ -368,20 +370,22 @@ class TempestVerifyTestCase(BaseTestCase):
|
||||
return_value=(None, None))
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.Tempest.env")
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.subprocess")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestConf")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestResourcesContext")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestConfig")
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.Tempest.is_configured",
|
||||
return_value=True)
|
||||
def test_verify_when_tempest_configured(
|
||||
self, mock_tempest_is_configured, mock_tempest_conf,
|
||||
mock_subprocess, mock_tempest_env, mock_tempest_parse_results):
|
||||
self, mock_tempest_is_configured, mock_tempest_config,
|
||||
mock_tempest_resources_context, mock_subprocess, mock_tempest_env,
|
||||
mock_tempest_parse_results):
|
||||
set_name = "identity"
|
||||
fake_call = self._get_fake_call(set_name)
|
||||
|
||||
self.verifier.verify(set_name, None)
|
||||
|
||||
mock_tempest_is_configured.assert_called_once_with()
|
||||
self.assertFalse(mock_tempest_conf.called)
|
||||
self.assertFalse(mock_tempest_conf().generate.called)
|
||||
self.assertFalse(mock_tempest_config.called)
|
||||
self.assertFalse(mock_tempest_config().generate.called)
|
||||
self.verifier.verification.start_verifying.assert_called_once_with(
|
||||
set_name)
|
||||
|
||||
@ -394,12 +398,14 @@ class TempestVerifyTestCase(BaseTestCase):
|
||||
return_value=(None, None))
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.Tempest.env")
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.subprocess")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestConf")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestResourcesContext")
|
||||
@mock.patch(TEMPEST_PATH + ".config.TempestConfig")
|
||||
@mock.patch(TEMPEST_PATH + ".tempest.Tempest.is_configured",
|
||||
return_value=True)
|
||||
def test_verify_failed_and_tempest_is_configured(
|
||||
self, mock_tempest_is_configured, mock_tempest_conf,
|
||||
mock_subprocess, mock_tempest_env, mock_tempest_parse_results):
|
||||
self, mock_tempest_is_configured, mock_tempest_config,
|
||||
mock_tempest_resources_context, mock_subprocess, mock_tempest_env,
|
||||
mock_tempest_parse_results):
|
||||
set_name = "identity"
|
||||
fake_call = self._get_fake_call(set_name)
|
||||
mock_subprocess.side_effect = subprocess.CalledProcessError
|
||||
@ -407,8 +413,8 @@ class TempestVerifyTestCase(BaseTestCase):
|
||||
self.verifier.verify(set_name, None)
|
||||
|
||||
mock_tempest_is_configured.assert_called_once_with()
|
||||
self.assertFalse(mock_tempest_conf.called)
|
||||
self.assertFalse(mock_tempest_conf().generate.called)
|
||||
self.assertFalse(mock_tempest_config.called)
|
||||
self.assertFalse(mock_tempest_config().generate.called)
|
||||
self.verifier.verification.start_verifying.assert_called_once_with(
|
||||
set_name)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user