"""Rally testcases implementation."""
from __future__ import division
+from __future__ import print_function
+import fileinput
import json
import logging
import os
import yaml
from functest.core import singlevm
-from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils import config
from functest.utils import env
class RallyBase(singlevm.VmReady2):
"""Base class form Rally testcases implementation."""
- # pylint: disable=too-many-instance-attributes
+ # pylint: disable=too-many-instance-attributes, too-many-public-methods
TESTS = ['authenticate', 'glance', 'cinder', 'gnocchi', 'heat',
'keystone', 'neutron', 'nova', 'quotas']
+ RALLY_CONF_PATH = "/etc/rally/rally.conf"
+ RALLY_AARCH64_PATCH_PATH = pkg_resources.resource_filename(
+ 'functest', 'ci/rally_aarch64_patch.conf')
RALLY_DIR = pkg_resources.resource_filename(
'functest', 'opnfv_tests/openstack/rally')
RALLY_SCENARIO_DIR = pkg_resources.resource_filename(
self.summary = []
self.scenario_dir = ''
self.smoke = None
- self.test_name = None
self.start_time = None
self.result = None
self.details = None
self.apply_blacklist(scenario_file_name, test_file_name)
return test_file_name
+ @staticmethod
+ def get_verifier_deployment_id():
+ """
+ Returns deployment id for active Rally deployment
+ """
+ cmd = ("rally deployment list | awk '/" +
+ getattr(config.CONF, 'rally_deployment_name') +
+ "/ {print $2}'")
+ proc = subprocess.Popen(cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ deployment_uuid = proc.stdout.readline().rstrip()
+ return deployment_uuid
+
+ @staticmethod
+ def create_rally_deployment(environ=None):
+ """Create new rally deployment"""
+ # set the architecture to default
+ pod_arch = env.get("POD_ARCH")
+ arch_filter = ['aarch64']
+
+ if pod_arch and pod_arch in arch_filter:
+ LOGGER.info("Apply aarch64 specific to rally config...")
+ with open(RallyBase.RALLY_AARCH64_PATCH_PATH, "r") as pfile:
+ rally_patch_conf = pfile.read()
+
+ for line in fileinput.input(RallyBase.RALLY_CONF_PATH):
+ print(line, end=' ')
+ if "cirros|testvm" in line:
+ print(rally_patch_conf)
+
+ LOGGER.info("Creating Rally environment...")
+ try:
+ cmd = ['rally', 'deployment', 'destroy',
+ '--deployment',
+ str(getattr(config.CONF, 'rally_deployment_name'))]
+ output = subprocess.check_output(cmd)
+ LOGGER.info("%s\n%s", " ".join(cmd), output)
+ except subprocess.CalledProcessError:
+ pass
+
+ cmd = ['rally', 'deployment', 'create', '--fromenv',
+ '--name', str(getattr(config.CONF, 'rally_deployment_name'))]
+ output = subprocess.check_output(cmd, env=environ)
+ LOGGER.info("%s\n%s", " ".join(cmd), output)
+
+ cmd = ['rally', 'deployment', 'check']
+ output = subprocess.check_output(cmd)
+ LOGGER.info("%s\n%s", " ".join(cmd), output)
+ return RallyBase.get_verifier_deployment_id()
+
@staticmethod
def update_keystone_default_role(rally_conf='/etc/rally/rally.conf'):
"""Set keystone_default_role in rally.conf"""
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
LOGGER.info("%s\n%s", " ".join(cmd), output)
- # save report as HTML
- report_html_name = '{}.html'.format(test_name)
- report_html_dir = os.path.join(self.results_dir, report_html_name)
- cmd = (["rally", "task", "report", "--html", "--uuid", task_id,
- "--out", report_html_dir])
- LOGGER.debug('running command: %s', cmd)
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- LOGGER.info("%s\n%s", " ".join(cmd), output)
-
json_results = open(report_json_dir).read()
self._append_summary(json_results, test_name)
nb_tests = 0
nb_success = 0
overall_duration = 0.0
+ success = []
+ failures = []
rally_report = json.loads(json_raw)
for task in rally_report.get('tasks'):
for subtask in task.get('subtasks'):
+ has_errors = False
for workload in subtask.get('workloads'):
if workload.get('full_duration'):
overall_duration += workload.get('full_duration')
for result in workload.get('data'):
if not result.get('error'):
nb_success += 1
+ else:
+ has_errors = True
+
+ if has_errors:
+ failures.append(subtask['title'])
+ else:
+ success.append(subtask['title'])
scenario_summary = {'test_name': test_name,
'overall_duration': overall_duration,
'nb_tests': nb_tests,
'nb_success': nb_success,
+ 'success': success,
+ 'failures': failures,
'task_status': self.task_succeed(json_raw)}
self.summary.append(scenario_summary)
- def prepare_run(self):
+ def prepare_run(self, **kwargs):
"""Prepare resources needed by test scenarios."""
assert self.cloud
- LOGGER.debug('Validating the test name...')
- if self.test_name == 'all':
- self.tests = self.TESTS
- elif self.test_name in self.TESTS:
- self.tests = [self.test_name]
- else:
- raise Exception("Test name '%s' is invalid" % self.test_name)
+ LOGGER.debug('Validating run tests...')
+ for test in kwargs.get('tests', self.TESTS):
+ if test in self.TESTS:
+ self.tests.append(test)
+ else:
+ raise Exception("Test name '%s' is invalid" % test)
if not os.path.exists(self.TASK_DIR):
os.makedirs(self.TASK_DIR)
payload.append({'module': item['test_name'],
'details': {'duration': item['overall_duration'],
'nb tests': item['nb_tests'],
- 'success': success_str}})
+ 'success rate': success_str,
+ 'success': item['success'],
+ 'failures': item['failures']}})
total_duration_str = time.strftime("%H:%M:%S",
time.gmtime(total_duration))
'nb success': success_rate}})
self.details = payload
+ @staticmethod
+ def export_task(file_name, export_type="html"):
+ """Export all task results (e.g. html or xunit report)
+
+ Raises:
+ subprocess.CalledProcessError: if Rally doesn't return 0
+
+ Returns:
+ None
+ """
+ cmd = ["rally", "task", "export", "--type", export_type,
+ "--deployment",
+ str(getattr(config.CONF, 'rally_deployment_name')),
+ "--to", file_name]
+ LOGGER.debug('running command: %s', cmd)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ LOGGER.info("%s\n%s", " ".join(cmd), output)
+
+ @staticmethod
+ def verify_report(file_name, uuid, export_type="html"):
+ """Generate the verifier report (e.g. html or xunit report)
+
+ Raises:
+ subprocess.CalledProcessError: if Rally doesn't return 0
+
+ Returns:
+ None
+ """
+ cmd = ["rally", "verify", "report", "--type", export_type,
+ "--uuid", uuid, "--to", file_name]
+ LOGGER.debug('running command: %s', cmd)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ LOGGER.info("%s\n%s", " ".join(cmd), output)
+
def clean(self):
"""Cleanup of OpenStack resources. Should be called on completion."""
self.clean_rally_conf()
del environ['OS_TENANT_ID']
except Exception: # pylint: disable=broad-except
pass
- conf_utils.create_rally_deployment(environ=environ)
- self.prepare_run()
+ self.create_rally_deployment(environ=environ)
+ self.prepare_run(**kwargs)
self.run_tests(**kwargs)
self._generate_report()
+ self.export_task(
+ "{}/{}.html".format(self.results_dir, self.case_name))
+ self.export_task(
+ "{}/{}.xml".format(self.results_dir, self.case_name),
+ export_type="junit-xml")
res = testcase.TestCase.EX_OK
except Exception as exc: # pylint: disable=broad-except
LOGGER.error('Error with run: %s', exc)
if "case_name" not in kwargs:
kwargs["case_name"] = "rally_sanity"
super(RallySanity, self).__init__(**kwargs)
- self.test_name = 'all'
self.smoke = True
self.scenario_dir = os.path.join(self.RALLY_SCENARIO_DIR, 'sanity')
if "case_name" not in kwargs:
kwargs["case_name"] = "rally_full"
super(RallyFull, self).__init__(**kwargs)
- self.test_name = 'all'
self.smoke = False
self.scenario_dir = os.path.join(self.RALLY_SCENARIO_DIR, 'full')
if "case_name" not in kwargs:
kwargs["case_name"] = "rally_jobs"
super(RallyJobs, self).__init__(**kwargs)
- self.test_name = 'all'
self.task_file = os.path.join(self.RALLY_DIR, 'rally_jobs.yaml')
self.task_yaml = None
- def prepare_run(self):
+ def prepare_run(self, **kwargs):
"""Create resources needed by test scenarios."""
- super(RallyJobs, self).prepare_run()
+ super(RallyJobs, self).prepare_run(**kwargs)
with open(os.path.join(self.RALLY_DIR,
'rally_jobs.yaml'), 'r') as task_file:
self.task_yaml = yaml.safe_load(task_file)
- if not all(task in self.task_yaml for task in self.tests):
- raise Exception("Test '%s' not in '%s'" %
- (self.test_name, self.tests))
+ for task in self.task_yaml:
+ if task not in self.tests:
+ raise Exception("Test '%s' not in '%s'" %
+ (task, self.tests))
def apply_blacklist(self, case_file_name, result_file_name):
# pylint: disable=too-many-branches