aboutsummaryrefslogtreecommitdiffstats
path: root/functest/opnfv_tests/openstack/tempest/tempest.py
diff options
context:
space:
mode:
Diffstat (limited to 'functest/opnfv_tests/openstack/tempest/tempest.py')
-rw-r--r--functest/opnfv_tests/openstack/tempest/tempest.py314
1 files changed, 176 insertions, 138 deletions
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index d2c54262a..7233ffd60 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -39,7 +39,7 @@ class TempestCommon(singlevm.VmReady2):
"""TempestCommon testcases implementation class."""
visibility = 'public'
- filename_alt = '/home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img'
+ filename_alt = '/home/opnfv/functest/images/cirros-0.6.1-x86_64-disk.img'
shared_network = True
tempest_conf_yaml = pkg_resources.resource_filename(
'functest',
@@ -57,7 +57,7 @@ class TempestCommon(singlevm.VmReady2):
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'tempest'
- super(TempestCommon, self).__init__(**kwargs)
+ super().__init__(**kwargs)
assert self.orig_cloud
assert self.cloud
assert self.project
@@ -128,7 +128,7 @@ class TempestCommon(singlevm.VmReady2):
@staticmethod
def read_file(filename):
"""Read file and return content as a stripped list."""
- with open(filename) as src:
+ with open(filename, encoding='utf-8') as src:
return [line.strip() for line in src.readlines()]
@staticmethod
@@ -142,22 +142,22 @@ class TempestCommon(singlevm.VmReady2):
}
cmd = ["rally", "verify", "show", "--uuid", verif_id]
LOGGER.info("Showing result for a verification: '%s'.", cmd)
- proc = subprocess.Popen(cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- for line in proc.stdout:
- LOGGER.info(line.decode("utf-8").rstrip())
- new_line = line.decode("utf-8").replace(' ', '').split('|')
- if 'Tests' in new_line:
- break
- if 'Testscount' in new_line:
- result['num_tests'] = int(new_line[2])
- elif 'Success' in new_line:
- result['num_success'] = int(new_line[2])
- elif 'Skipped' in new_line:
- result['num_skipped'] = int(new_line[2])
- elif 'Failures' in new_line:
- result['num_failures'] = int(new_line[2])
+ with subprocess.Popen(
+ cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT) as proc:
+ for line in proc.stdout:
+ LOGGER.info(line.decode("utf-8").rstrip())
+ new_line = line.decode("utf-8").replace(' ', '').split('|')
+ if 'Tests' in new_line:
+ break
+ if 'Testscount' in new_line:
+ result['num_tests'] = int(new_line[2])
+ elif 'Success' in new_line:
+ result['num_success'] = int(new_line[2])
+ elif 'Skipped' in new_line:
+ result['num_skipped'] = int(new_line[2])
+ elif 'Failures' in new_line:
+ result['num_failures'] = int(new_line[2])
return result
@staticmethod
@@ -199,10 +199,10 @@ class TempestCommon(singlevm.VmReady2):
cmd = ("rally verify list-verifiers | awk '/" +
getattr(config.CONF, 'tempest_verifier_name') +
"/ {print $2}'")
- proc = subprocess.Popen(cmd, shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL)
- verifier_uuid = proc.stdout.readline().rstrip()
+ with subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL) as proc:
+ verifier_uuid = proc.stdout.readline().rstrip()
return verifier_uuid.decode("utf-8")
@staticmethod
@@ -212,7 +212,7 @@ class TempestCommon(singlevm.VmReady2):
"""
return os.path.join(getattr(config.CONF, 'dir_rally_inst'),
'verification',
- 'verifier-{}'.format(verifier_id),
+ f'verifier-{verifier_id}',
'repo')
@staticmethod
@@ -222,13 +222,13 @@ class TempestCommon(singlevm.VmReady2):
"""
return os.path.join(getattr(config.CONF, 'dir_rally_inst'),
'verification',
- 'verifier-{}'.format(verifier_id),
- 'for-deployment-{}'.format(deployment_id))
+ f'verifier-{verifier_id}',
+ f'for-deployment-{deployment_id}')
@staticmethod
def update_tempest_conf_file(conf_file, rconfig):
"""Update defined paramters into tempest config file"""
- with open(TempestCommon.tempest_conf_yaml) as yfile:
+ with open(TempestCommon.tempest_conf_yaml, encoding='utf-8') as yfile:
conf_yaml = yaml.safe_load(yfile)
if conf_yaml:
sections = rconfig.sections()
@@ -239,7 +239,7 @@ class TempestCommon(singlevm.VmReady2):
for key, value in sub_conf.items():
rconfig.set(section, key, value)
- with open(conf_file, 'w') as config_file:
+ with open(conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
@staticmethod
@@ -272,17 +272,6 @@ class TempestCommon(singlevm.VmReady2):
rconfig.set('compute-feature-enabled', 'live_migration', True)
if os.environ.get('OS_REGION_NAME'):
rconfig.set('identity', 'region', os.environ.get('OS_REGION_NAME'))
- if env.get("NEW_USER_ROLE").lower() != "member":
- rconfig.set(
- 'auth', 'tempest_roles',
- functest_utils.convert_list_to_ini([env.get("NEW_USER_ROLE")]))
- if not json.loads(env.get("USE_DYNAMIC_CREDENTIALS").lower()):
- rconfig.set('auth', 'use_dynamic_credentials', False)
- account_file = os.path.join(
- getattr(config.CONF, 'dir_functest_data'), 'accounts.yaml')
- assert os.path.exists(
- account_file), "{} doesn't exist".format(account_file)
- rconfig.set('auth', 'test_accounts_file', account_file)
rconfig.set('identity', 'admin_role', admin_role_name)
rconfig.set('identity', 'default_domain_id', domain_id)
if not rconfig.has_section('network'):
@@ -335,13 +324,13 @@ class TempestCommon(singlevm.VmReady2):
shutil.copyfile(
self.tempest_custom, self.list)
else:
- raise Exception("Tempest test list file %s NOT found."
- % self.tempest_custom)
+ raise Exception(
+ f"Tempest test list file {self.tempest_custom} NOT found.")
else:
testr_mode = kwargs.get(
'mode', r'^tempest\.(api|scenario).*\[.*\bsmoke\b.*\]$')
- cmd = "(cd {0}; stestr list '{1}' >{2} 2>/dev/null)".format(
- self.verifier_repo_dir, testr_mode, self.list)
+ cmd = (f"(cd {self.verifier_repo_dir}; "
+ f"stestr list '{testr_mode}' > {self.list} 2>/dev/null)")
output = subprocess.check_output(cmd, shell=True)
LOGGER.info("%s\n%s", cmd, output.decode("utf-8"))
os.remove('/etc/tempest.conf')
@@ -353,32 +342,31 @@ class TempestCommon(singlevm.VmReady2):
os.remove(self.raw_list)
os.rename(self.list, self.raw_list)
cases_file = self.read_file(self.raw_list)
- result_file = open(self.list, 'w')
- black_tests = []
- try:
- deploy_scenario = env.get('DEPLOY_SCENARIO')
- if bool(deploy_scenario):
- # if DEPLOY_SCENARIO is set we read the file
- black_list_file = open(black_list)
- black_list_yaml = yaml.safe_load(black_list_file)
- black_list_file.close()
- for item in black_list_yaml:
- scenarios = item['scenarios']
- in_it = rally.RallyBase.in_iterable_re
- if in_it(deploy_scenario, scenarios):
- tests = item['tests']
- black_tests.extend(tests)
- except Exception: # pylint: disable=broad-except
+ with open(self.list, 'w', encoding='utf-8') as result_file:
black_tests = []
- LOGGER.debug("Tempest blacklist file does not exist.")
+ try:
+ deploy_scenario = env.get('DEPLOY_SCENARIO')
+ if bool(deploy_scenario):
+ # if DEPLOY_SCENARIO is set we read the file
+ with open(black_list, encoding='utf-8') as black_list_file:
+ black_list_yaml = yaml.safe_load(black_list_file)
+ black_list_file.close()
+ for item in black_list_yaml:
+ scenarios = item['scenarios']
+ in_it = rally.RallyBase.in_iterable_re
+ if in_it(deploy_scenario, scenarios):
+ tests = item['tests']
+ black_tests.extend(tests)
+ except Exception: # pylint: disable=broad-except
+ black_tests = []
+ LOGGER.debug("Tempest blacklist file does not exist.")
- for cases_line in cases_file:
- for black_tests_line in black_tests:
- if re.search(black_tests_line, cases_line):
- break
- else:
- result_file.write(str(cases_line) + '\n')
- result_file.close()
+ for cases_line in cases_file:
+ for black_tests_line in black_tests:
+ if re.search(black_tests_line, cases_line):
+ break
+ else:
+ result_file.write(str(cases_line) + '\n')
def run_verifier_tests(self, **kwargs):
"""Execute tempest test cases."""
@@ -387,33 +375,31 @@ class TempestCommon(singlevm.VmReady2):
cmd.extend(kwargs.get('option', []))
LOGGER.info("Starting Tempest test suite: '%s'.", cmd)
- f_stdout = open(
- os.path.join(self.res_dir, "tempest.log"), 'w+')
-
- proc = subprocess.Popen(
- cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- bufsize=1)
-
- with proc.stdout:
- for line in iter(proc.stdout.readline, b''):
- if re.search(r"\} tempest\.", line.decode("utf-8")):
- LOGGER.info(line.rstrip())
- elif re.search(r'(?=\(UUID=(.*)\))', line.decode("utf-8")):
- self.verification_id = re.search(
- r'(?=\(UUID=(.*)\))', line.decode("utf-8")).group(1)
- f_stdout.write(line.decode("utf-8"))
- proc.wait()
- f_stdout.close()
+ with open(
+ os.path.join(self.res_dir, "tempest.log"), 'w+',
+ encoding='utf-8') as f_stdout:
+ with subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ bufsize=1) as proc:
+ with proc.stdout:
+ for line in iter(proc.stdout.readline, b''):
+ if re.search(r"\} tempest\.", line.decode("utf-8")):
+ LOGGER.info(line.rstrip())
+ elif re.search(r'(?=\(UUID=(.*)\))',
+ line.decode("utf-8")):
+ self.verification_id = re.search(
+ r'(?=\(UUID=(.*)\))',
+ line.decode("utf-8")).group(1)
+ f_stdout.write(line.decode("utf-8"))
+ proc.wait()
if self.verification_id is None:
raise Exception('Verification UUID not found')
LOGGER.info('Verification UUID: %s', self.verification_id)
shutil.copy(
- "{}/tempest.log".format(self.deployment_dir),
- "{}/tempest.debug.log".format(self.res_dir))
+ f"{self.deployment_dir}/tempest.log",
+ f"{self.res_dir}/tempest.debug.log")
def parse_verifier_result(self):
"""Parse and save test results."""
@@ -430,8 +416,8 @@ class TempestCommon(singlevm.VmReady2):
LOGGER.error("No test has been executed")
return
- with open(os.path.join(self.res_dir,
- "rally.log"), 'r') as logfile:
+ with open(os.path.join(self.res_dir, "rally.log"),
+ 'r', encoding='utf-8') as logfile:
output = logfile.read()
success_testcases = []
@@ -466,9 +452,8 @@ class TempestCommon(singlevm.VmReady2):
rconfig.read(rally_conf)
if not rconfig.has_section('openstack'):
rconfig.add_section('openstack')
- rconfig.set('openstack', 'img_name_regex', '^{}$'.format(
- self.image.name))
- with open(rally_conf, 'w') as config_file:
+ rconfig.set('openstack', 'img_name_regex', f'^{self.image.name}$')
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def update_default_role(self, rally_conf='/etc/rally/rally.conf'):
@@ -481,7 +466,7 @@ class TempestCommon(singlevm.VmReady2):
if not rconfig.has_section('openstack'):
rconfig.add_section('openstack')
rconfig.set('openstack', 'swift_operator_role', role.name)
- with open(rally_conf, 'w') as config_file:
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
@staticmethod
@@ -493,18 +478,51 @@ class TempestCommon(singlevm.VmReady2):
rconfig.remove_option('openstack', 'img_name_regex')
if rconfig.has_option('openstack', 'swift_operator_role'):
rconfig.remove_option('openstack', 'swift_operator_role')
- with open(rally_conf, 'w') as config_file:
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_auth_section(self):
+ """Update auth section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if not rconfig.has_section("auth"):
+ rconfig.add_section("auth")
+ if env.get("NEW_USER_ROLE").lower() != "member":
+ tempest_roles = []
+ if rconfig.has_option("auth", "tempest_roles"):
+ tempest_roles = functest_utils.convert_ini_to_list(
+ rconfig.get("auth", "tempest_roles"))
+ rconfig.set(
+ 'auth', 'tempest_roles',
+ functest_utils.convert_list_to_ini(
+ [env.get("NEW_USER_ROLE")] + tempest_roles))
+ if not json.loads(env.get("USE_DYNAMIC_CREDENTIALS").lower()):
+ rconfig.set('auth', 'use_dynamic_credentials', False)
+ account_file = os.path.join(
+ getattr(config.CONF, 'dir_functest_data'), 'accounts.yaml')
+ assert os.path.exists(
+ account_file), f"{account_file} doesn't exist"
+ rconfig.set('auth', 'test_accounts_file', account_file)
+ if env.get('NO_TENANT_NETWORK').lower() == 'true':
+ rconfig.set('auth', 'create_isolated_networks', False)
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def update_network_section(self):
"""Update network section in tempest.conf"""
rconfig = configparser.RawConfigParser()
rconfig.read(self.conf_file)
- if not rconfig.has_section('network'):
- rconfig.add_section('network')
- rconfig.set('network', 'public_network_id', self.ext_net.id)
- rconfig.set('network', 'floating_network_name', self.ext_net.name)
- with open(self.conf_file, 'w') as config_file:
+ if self.ext_net:
+ if not rconfig.has_section('network'):
+ rconfig.add_section('network')
+ rconfig.set('network', 'public_network_id', self.ext_net.id)
+ rconfig.set('network', 'floating_network_name', self.ext_net.name)
+ rconfig.set('network-feature-enabled', 'floating_ips', True)
+ else:
+ if not rconfig.has_section('network-feature-enabled'):
+ rconfig.add_section('network-feature-enabled')
+ rconfig.set('network-feature-enabled', 'floating_ips', False)
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def update_compute_section(self):
@@ -513,8 +531,10 @@ class TempestCommon(singlevm.VmReady2):
rconfig.read(self.conf_file)
if not rconfig.has_section('compute'):
rconfig.add_section('compute')
- rconfig.set('compute', 'fixed_network_name', self.network.name)
- with open(self.conf_file, 'w') as config_file:
+ rconfig.set(
+ 'compute', 'fixed_network_name',
+ self.network.name if self.network else env.get("EXTERNAL_NETWORK"))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def update_validation_section(self):
@@ -523,8 +543,13 @@ class TempestCommon(singlevm.VmReady2):
rconfig.read(self.conf_file)
if not rconfig.has_section('validation'):
rconfig.add_section('validation')
- rconfig.set('validation', 'network_for_ssh', self.network.name)
- with open(self.conf_file, 'w') as config_file:
+ rconfig.set(
+ 'validation', 'connect_method',
+ 'floating' if self.ext_net else 'fixed')
+ rconfig.set(
+ 'validation', 'network_for_ssh',
+ self.network.name if self.network else env.get("EXTERNAL_NETWORK"))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def update_scenario_section(self):
@@ -532,13 +557,12 @@ class TempestCommon(singlevm.VmReady2):
rconfig = configparser.RawConfigParser()
rconfig.read(self.conf_file)
filename = getattr(
- config.CONF, '{}_image'.format(self.case_name), self.filename)
+ config.CONF, f'{self.case_name}_image', self.filename)
if not rconfig.has_section('scenario'):
rconfig.add_section('scenario')
- rconfig.set('scenario', 'img_file', os.path.basename(filename))
- rconfig.set('scenario', 'img_dir', os.path.dirname(filename))
+ rconfig.set('scenario', 'img_file', filename)
rconfig.set('scenario', 'img_disk_format', getattr(
- config.CONF, '{}_image_format'.format(self.case_name),
+ config.CONF, f'{self.case_name}_image_format',
self.image_format))
extra_properties = self.extra_properties.copy()
if env.get('IMAGE_PROPERTIES'):
@@ -546,12 +570,24 @@ class TempestCommon(singlevm.VmReady2):
functest_utils.convert_ini_to_dict(
env.get('IMAGE_PROPERTIES')))
extra_properties.update(
- getattr(config.CONF, '{}_extra_properties'.format(
- self.case_name), {}))
+ getattr(config.CONF, f'{self.case_name}_extra_properties', {}))
rconfig.set(
'scenario', 'img_properties',
functest_utils.convert_dict_to_ini(extra_properties))
- with open(self.conf_file, 'w') as config_file:
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_dashboard_section(self):
+ """Update dashboard section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if env.get('DASHBOARD_URL'):
+ if not rconfig.has_section('dashboard'):
+ rconfig.add_section('dashboard')
+ rconfig.set('dashboard', 'dashboard_url', env.get('DASHBOARD_URL'))
+ else:
+ rconfig.set('service_available', 'horizon', False)
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def configure(self, **kwargs): # pylint: disable=unused-argument
@@ -591,16 +627,18 @@ class TempestCommon(singlevm.VmReady2):
flavor_alt_id=self.flavor_alt.id,
admin_role_name=self.role_name, cidr=self.cidr,
domain_id=self.project.domain.id)
+ self.update_auth_section()
self.update_network_section()
self.update_compute_section()
self.update_validation_section()
self.update_scenario_section()
+ self.update_dashboard_section()
self.backup_tempest_config(self.conf_file, self.res_dir)
def run(self, **kwargs):
self.start_time = time.time()
try:
- assert super(TempestCommon, self).run(
+ assert super().run(
**kwargs) == testcase.TestCase.EX_OK
if not os.path.exists(self.res_dir):
os.makedirs(self.res_dir)
@@ -640,7 +678,7 @@ class TempestCommon(singlevm.VmReady2):
self.cloud.delete_image(self.image_alt)
if self.flavor_alt:
self.orig_cloud.delete_flavor(self.flavor_alt.id)
- super(TempestCommon, self).clean()
+ super().clean()
def is_successful(self):
"""The overall result of the test."""
@@ -650,22 +688,7 @@ class TempestCommon(singlevm.VmReady2):
if self.tests_count and (
self.details.get("tests_number", 0) != self.tests_count):
return testcase.TestCase.EX_TESTCASE_FAILED
- return super(TempestCommon, self).is_successful()
-
-
-class TempestHorizon(TempestCommon):
- """Tempest Horizon testcase implementation class."""
-
- def configure(self, **kwargs):
- super(TempestHorizon, self).configure(**kwargs)
- rconfig = configparser.RawConfigParser()
- rconfig.read(self.conf_file)
- if not rconfig.has_section('dashboard'):
- rconfig.add_section('dashboard')
- rconfig.set('dashboard', 'dashboard_url', env.get('DASHBOARD_URL'))
- with open(self.conf_file, 'w') as config_file:
- rconfig.write(config_file)
- self.backup_tempest_config(self.conf_file, self.res_dir)
+ return super().is_successful()
class TempestHeat(TempestCommon):
@@ -678,11 +701,14 @@ class TempestHeat(TempestCommon):
flavor_alt_disk = 4
def __init__(self, **kwargs):
- super(TempestHeat, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.user2 = self.orig_cloud.create_user(
- name='{}-user2_{}'.format(self.case_name, self.project.guid),
+ name=f'{self.case_name}-user2_{self.project.guid}',
password=self.project.password,
domain_id=self.project.domain.id)
+ self.orig_cloud.grant_role(
+ self.role_name, user=self.user2.id,
+ project=self.project.project.id, domain=self.project.domain.id)
if not self.orig_cloud.get_role("heat_stack_owner"):
self.role = self.orig_cloud.create_role("heat_stack_owner")
self.orig_cloud.grant_role(
@@ -692,7 +718,7 @@ class TempestHeat(TempestCommon):
def configure(self, **kwargs):
assert self.user2
- super(TempestHeat, self).configure(**kwargs)
+ super().configure(**kwargs)
rconfig = configparser.RawConfigParser()
rconfig.read(self.conf_file)
if not rconfig.has_section('heat_plugin'):
@@ -719,11 +745,23 @@ class TempestHeat(TempestCommon):
rconfig.set('heat_plugin', 'instance_type', self.flavor_alt.id)
rconfig.set('heat_plugin', 'minimal_image_ref', self.image.id)
rconfig.set('heat_plugin', 'minimal_instance_type', self.flavor.id)
- rconfig.set('heat_plugin', 'floating_network_name', self.ext_net.name)
- rconfig.set('heat_plugin', 'fixed_network_name', self.network.name)
- rconfig.set('heat_plugin', 'fixed_subnet_name', self.subnet.name)
- rconfig.set('heat_plugin', 'network_for_ssh', self.network.name)
- with open(self.conf_file, 'w') as config_file:
+ if self.ext_net:
+ rconfig.set(
+ 'heat_plugin', 'floating_network_name', self.ext_net.name)
+ if self.network:
+ rconfig.set('heat_plugin', 'fixed_network_name', self.network.name)
+ rconfig.set('heat_plugin', 'fixed_subnet_name', self.subnet.name)
+ rconfig.set('heat_plugin', 'network_for_ssh', self.network.name)
+ else:
+ LOGGER.warning(
+ 'No tenant network created. '
+ 'Trying EXTERNAL_NETWORK as a fallback')
+ rconfig.set(
+ 'heat_plugin', 'fixed_network_name',
+ env.get("EXTERNAL_NETWORK"))
+ rconfig.set(
+ 'heat_plugin', 'network_for_ssh', env.get("EXTERNAL_NETWORK"))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
self.backup_tempest_config(self.conf_file, self.res_dir)
@@ -731,6 +769,6 @@ class TempestHeat(TempestCommon):
"""
Cleanup all OpenStack objects. Should be called on completion.
"""
- super(TempestHeat, self).clean()
+ super().clean()
if self.user2:
self.orig_cloud.delete_user(self.user2.id)