3 # Copyright (c) 2015 All rights reserved
4 # This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
11 """Rally testcases implementation."""
13 from __future__ import division
14 from __future__ import print_function
27 from ruamel.yaml import YAML
28 from six.moves import configparser
29 from xtesting.core import testcase
32 from functest.core import singlevm
33 from functest.utils import config
34 from functest.utils import env
36 LOGGER = logging.getLogger(__name__)
39 class RallyBase(singlevm.VmReady2):
40 """Base class form Rally testcases implementation."""
42 # pylint: disable=too-many-instance-attributes, too-many-public-methods
43 TESTS = ['authenticate', 'glance', 'cinder', 'gnocchi', 'heat',
44 'keystone', 'neutron', 'nova', 'quotas']
46 RALLY_CONF_PATH = "/etc/rally/rally.conf"
47 RALLY_AARCH64_PATCH_PATH = pkg_resources.resource_filename(
48 'functest', 'ci/rally_aarch64_patch.conf')
49 RALLY_DIR = pkg_resources.resource_filename(
50 'functest', 'opnfv_tests/openstack/rally')
51 RALLY_SCENARIO_DIR = pkg_resources.resource_filename(
52 'functest', 'opnfv_tests/openstack/rally/scenario')
53 TEMPLATE_DIR = pkg_resources.resource_filename(
54 'functest', 'opnfv_tests/openstack/rally/scenario/templates')
55 SUPPORT_DIR = pkg_resources.resource_filename(
56 'functest', 'opnfv_tests/openstack/rally/scenario/support')
59 ITERATIONS_AMOUNT = 10
61 BLACKLIST_FILE = os.path.join(RALLY_DIR, "blacklist.yaml")
62 TASK_DIR = os.path.join(getattr(config.CONF, 'dir_rally_data'), 'task')
63 TEMP_DIR = os.path.join(TASK_DIR, 'var')
68 def __init__(self, **kwargs):
69 """Initialize RallyBase object."""
70 super(RallyBase, self).__init__(**kwargs)
71 assert self.orig_cloud
73 if self.orig_cloud.get_role("admin"):
75 elif self.orig_cloud.get_role("Admin"):
78 raise Exception("Cannot detect neither admin nor Admin")
79 self.orig_cloud.grant_role(
80 role_name, user=self.project.user.id,
81 project=self.project.project.id,
82 domain=self.project.domain.id)
83 self.results_dir = os.path.join(
84 getattr(config.CONF, 'dir_results'), self.case_name)
88 self.scenario_dir = ''
90 self.start_time = None
94 self.flavor_alt = None
97 self.network_extensions = []
100 def build_task_args(self, test_name):
101 """Build arguments for the Rally task."""
102 task_args = {'service_list': [test_name]}
103 task_args['image_name'] = str(self.image.name)
104 task_args['flavor_name'] = str(self.flavor.name)
105 task_args['flavor_alt_name'] = str(self.flavor_alt.name)
106 task_args['glance_image_location'] = str(self.filename)
107 task_args['glance_image_format'] = str(self.image_format)
108 task_args['tmpl_dir'] = str(self.TEMPLATE_DIR)
109 task_args['sup_dir'] = str(self.SUPPORT_DIR)
110 task_args['users_amount'] = self.USERS_AMOUNT
111 task_args['tenants_amount'] = self.TENANTS_AMOUNT
112 task_args['use_existing_users'] = False
113 task_args['iterations'] = self.ITERATIONS_AMOUNT
114 task_args['concurrency'] = self.CONCURRENCY
115 task_args['smoke'] = self.smoke
118 task_args['floating_network'] = str(self.ext_net.name)
120 task_args['floating_network'] = ''
123 task_args['netid'] = str(self.network.id)
125 task_args['netid'] = ''
129 def _prepare_test_list(self, test_name):
130 """Build the list of test cases to be executed."""
131 test_yaml_file_name = 'opnfv-{}.yaml'.format(test_name)
132 scenario_file_name = os.path.join(self.RALLY_SCENARIO_DIR,
135 if not os.path.exists(scenario_file_name):
136 scenario_file_name = os.path.join(self.scenario_dir,
139 if not os.path.exists(scenario_file_name):
140 raise Exception("The scenario '%s' does not exist."
141 % scenario_file_name)
143 LOGGER.debug('Scenario fetched from : %s', scenario_file_name)
144 test_file_name = os.path.join(self.TEMP_DIR, test_yaml_file_name)
146 if not os.path.exists(self.TEMP_DIR):
147 os.makedirs(self.TEMP_DIR)
149 self.apply_blacklist(scenario_file_name, test_file_name)
150 return test_file_name
153 def get_verifier_deployment_id():
155 Returns deployment id for active Rally deployment
157 cmd = ("rally deployment list | awk '/" +
158 getattr(config.CONF, 'rally_deployment_name') +
160 proc = subprocess.Popen(cmd, shell=True,
161 stdout=subprocess.PIPE,
162 stderr=subprocess.STDOUT)
163 deployment_uuid = proc.stdout.readline().rstrip()
164 return deployment_uuid
167 def create_rally_deployment(environ=None):
168 """Create new rally deployment"""
169 # set the architecture to default
170 pod_arch = env.get("POD_ARCH")
171 arch_filter = ['aarch64']
173 if pod_arch and pod_arch in arch_filter:
174 LOGGER.info("Apply aarch64 specific to rally config...")
175 with open(RallyBase.RALLY_AARCH64_PATCH_PATH, "r") as pfile:
176 rally_patch_conf = pfile.read()
178 for line in fileinput.input(RallyBase.RALLY_CONF_PATH):
180 if "cirros|testvm" in line:
181 print(rally_patch_conf)
183 LOGGER.info("Creating Rally environment...")
185 cmd = ['rally', 'deployment', 'destroy',
187 str(getattr(config.CONF, 'rally_deployment_name'))]
188 output = subprocess.check_output(cmd)
189 LOGGER.info("%s\n%s", " ".join(cmd), output)
190 except subprocess.CalledProcessError:
193 cmd = ['rally', 'deployment', 'create', '--fromenv',
194 '--name', str(getattr(config.CONF, 'rally_deployment_name'))]
195 output = subprocess.check_output(cmd, env=environ)
196 LOGGER.info("%s\n%s", " ".join(cmd), output)
198 cmd = ['rally', 'deployment', 'check']
199 output = subprocess.check_output(cmd)
200 LOGGER.info("%s\n%s", " ".join(cmd), output)
201 return RallyBase.get_verifier_deployment_id()
204 def update_keystone_default_role(rally_conf='/etc/rally/rally.conf'):
205 """Set keystone_default_role in rally.conf"""
206 if env.get("NEW_USER_ROLE").lower() != "member":
207 rconfig = configparser.RawConfigParser()
208 rconfig.read(rally_conf)
209 if not rconfig.has_section('openstack'):
210 rconfig.add_section('openstack')
212 'openstack', 'keystone_default_role', env.get("NEW_USER_ROLE"))
213 with open(rally_conf, 'wb') as config_file:
214 rconfig.write(config_file)
217 def clean_rally_conf(rally_conf='/etc/rally/rally.conf'):
218 """Clean Rally config"""
219 if env.get("NEW_USER_ROLE").lower() != "member":
220 rconfig = configparser.RawConfigParser()
221 rconfig.read(rally_conf)
222 if rconfig.has_option('openstack', 'keystone_default_role'):
223 rconfig.remove_option('openstack', 'keystone_default_role')
224 with open(rally_conf, 'wb') as config_file:
225 rconfig.write(config_file)
228 def get_task_id(cmd_raw):
230 Get task id from command rally result.
233 :return: task_id as string
235 taskid_re = re.compile('^Task +(.*): started$')
236 for line in cmd_raw.splitlines(True):
238 match = taskid_re.match(line)
240 return match.group(1)
244 def task_succeed(json_raw):
246 Parse JSON from rally JSON results.
251 rally_report = json.loads(json_raw)
252 tasks = rally_report.get('tasks')
255 if task.get('status') != 'finished' or \
256 task.get('pass_sla') is not True:
262 def _migration_supported(self):
263 """Determine if migration is supported."""
264 if self.compute_cnt > 1:
268 def _network_trunk_supported(self):
269 """Determine if network trunk service is available"""
270 if 'trunk' in self.network_extensions:
276 """Exclude scenario."""
279 with open(RallyBase.BLACKLIST_FILE, 'r') as black_list_file:
280 black_list_yaml = yaml.safe_load(black_list_file)
282 deploy_scenario = env.get('DEPLOY_SCENARIO')
283 if (bool(deploy_scenario) and
284 'scenario' in black_list_yaml.keys()):
285 for item in black_list_yaml['scenario']:
286 scenarios = item['scenarios']
287 in_it = RallyBase.in_iterable_re
288 if in_it(deploy_scenario, scenarios):
289 tests = item['tests']
290 black_tests.extend(tests)
291 except Exception: # pylint: disable=broad-except
292 LOGGER.debug("Scenario exclusion not applied.")
297 def in_iterable_re(needle, haystack):
299 Check if given needle is in the iterable haystack, using regex.
301 :param needle: string to be matched
302 :param haystack: iterable of strings (optionally regex patterns)
303 :return: True if needle is eqial to any of the elements in haystack,
304 or if a nonempty regex pattern in haystack is found in needle.
306 # match without regex
307 if needle in haystack:
310 for pattern in haystack:
311 # match if regex pattern is set and found in the needle
312 if pattern and re.search(pattern, needle) is not None:
318 """Exclude functionalities."""
323 with open(RallyBase.BLACKLIST_FILE, 'r') as black_list_file:
324 black_list_yaml = yaml.safe_load(black_list_file)
326 if not self._migration_supported():
327 func_list.append("no_migration")
328 if not self._network_trunk_supported():
329 func_list.append("no_net_trunk_service")
331 if 'functionality' in black_list_yaml.keys():
332 for item in black_list_yaml['functionality']:
333 functions = item['functions']
334 for func in func_list:
335 if func in functions:
336 tests = item['tests']
337 black_tests.extend(tests)
338 except Exception: # pylint: disable=broad-except
339 LOGGER.debug("Functionality exclusion not applied.")
343 def apply_blacklist(self, case_file_name, result_file_name):
344 """Apply blacklist."""
345 LOGGER.debug("Applying blacklist...")
346 cases_file = open(case_file_name, 'r')
347 result_file = open(result_file_name, 'w')
349 black_tests = list(set(self.excl_func() +
350 self.excl_scenario()))
353 LOGGER.debug("Blacklisted tests: %s", str(black_tests))
356 for cases_line in cases_file:
358 for black_tests_line in black_tests:
359 if re.search(black_tests_line,
360 cases_line.strip().rstrip(':')):
364 result_file.write(str(cases_line))
366 if cases_line.isspace():
373 def file_is_empty(file_name):
374 """Determine is a file is empty."""
376 if os.stat(file_name).st_size > 0:
378 except Exception: # pylint: disable=broad-except
383 def _save_results(self, test_name, task_id):
384 """ Generate and save task execution results"""
385 # check for result directory and create it otherwise
386 if not os.path.exists(self.results_dir):
387 LOGGER.debug('%s does not exist, we create it.',
389 os.makedirs(self.results_dir)
391 # put detailed result to log
392 cmd = (["rally", "task", "detailed", "--uuid", task_id])
393 LOGGER.debug('running command: %s', cmd)
394 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
395 LOGGER.info("%s\n%s", " ".join(cmd), output)
397 # save report as JSON
398 report_json_name = '{}.json'.format(test_name)
399 report_json_dir = os.path.join(self.results_dir, report_json_name)
400 cmd = (["rally", "task", "report", "--json", "--uuid", task_id,
401 "--out", report_json_dir])
402 LOGGER.debug('running command: %s', cmd)
403 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
404 LOGGER.info("%s\n%s", " ".join(cmd), output)
406 json_results = open(report_json_dir).read()
407 self._append_summary(json_results, test_name)
409 # parse JSON operation result
410 if self.task_succeed(json_results):
411 LOGGER.info('Test scenario: "%s" OK.', test_name)
413 LOGGER.info('Test scenario: "%s" Failed.', test_name)
415 def run_task(self, test_name):
417 LOGGER.info('Starting test scenario "%s" ...', test_name)
418 LOGGER.debug('running command: %s', self.run_cmd)
419 proc = subprocess.Popen(self.run_cmd, stdout=subprocess.PIPE,
420 stderr=subprocess.STDOUT)
421 output = proc.communicate()[0]
423 task_id = self.get_task_id(output)
424 LOGGER.debug('task_id : %s', task_id)
426 LOGGER.error("Failed to retrieve task_id")
427 LOGGER.error("Result:\n%s", output)
428 raise Exception("Failed to retrieve task id")
429 self._save_results(test_name, task_id)
431 def _append_summary(self, json_raw, test_name):
432 """Update statistics summary info."""
435 overall_duration = 0.0
437 rally_report = json.loads(json_raw)
438 for task in rally_report.get('tasks'):
439 for subtask in task.get('subtasks'):
440 for workload in subtask.get('workloads'):
441 if workload.get('full_duration'):
442 overall_duration += workload.get('full_duration')
444 if workload.get('data'):
445 nb_tests += len(workload.get('data'))
447 for result in workload.get('data'):
448 if not result.get('error'):
451 scenario_summary = {'test_name': test_name,
452 'overall_duration': overall_duration,
453 'nb_tests': nb_tests,
454 'nb_success': nb_success,
455 'task_status': self.task_succeed(json_raw)}
456 self.summary.append(scenario_summary)
458 def prepare_run(self, **kwargs):
459 """Prepare resources needed by test scenarios."""
461 LOGGER.debug('Validating run tests...')
462 for test in kwargs.get('tests', self.TESTS):
463 if test in self.TESTS:
464 self.tests.append(test)
466 raise Exception("Test name '%s' is invalid" % test)
468 if not os.path.exists(self.TASK_DIR):
469 os.makedirs(self.TASK_DIR)
471 task = os.path.join(self.RALLY_DIR, 'task.yaml')
472 if not os.path.exists(task):
473 LOGGER.error("Task file '%s' does not exist.", task)
474 raise Exception("Task file '{}' does not exist.".
476 self.task_file = os.path.join(self.TASK_DIR, 'task.yaml')
477 shutil.copyfile(task, self.task_file)
479 task_macro = os.path.join(self.RALLY_DIR, 'macro')
480 if not os.path.exists(task_macro):
481 LOGGER.error("Task macro dir '%s' does not exist.", task_macro)
482 raise Exception("Task macro dir '{}' does not exist.".
484 macro_dir = os.path.join(self.TASK_DIR, 'macro')
485 if os.path.exists(macro_dir):
486 shutil.rmtree(macro_dir)
487 shutil.copytree(task_macro, macro_dir)
489 self.update_keystone_default_role()
490 self.compute_cnt = len(self.cloud.list_hypervisors())
491 self.network_extensions = self.cloud.get_network_extensions()
492 self.flavor_alt = self.create_flavor_alt()
493 self.services = [service.name for service in
494 self.cloud.list_services()]
496 LOGGER.debug("flavor: %s", self.flavor_alt)
498 def prepare_task(self, test_name):
499 """Prepare resources for test run."""
500 file_name = self._prepare_test_list(test_name)
501 if self.file_is_empty(file_name):
502 LOGGER.info('No tests for scenario "%s"', test_name)
504 self.run_cmd = (["rally", "task", "start", "--abort-on-sla-failure",
505 "--task", self.task_file, "--task-args",
506 str(self.build_task_args(test_name))])
509 def run_tests(self, **kwargs):
511 optional = kwargs.get('optional', [])
512 for test in self.tests:
513 if test in self.services or test not in optional:
514 if self.prepare_task(test):
517 def _generate_report(self):
518 """Generate test execution summary report."""
525 res_table = prettytable.PrettyTable(
527 field_names=['Module', 'Duration', 'nb. Test Run', 'Success'])
528 res_table.align['Module'] = "l"
529 res_table.align['Duration'] = "r"
530 res_table.align['Success'] = "r"
532 # for each scenario we draw a row for the table
533 for item in self.summary:
534 if item['task_status'] is True:
536 total_duration += item['overall_duration']
537 total_nb_tests += item['nb_tests']
538 total_nb_success += item['nb_success']
540 success_avg = 100 * item['nb_success'] / item['nb_tests']
541 except ZeroDivisionError:
543 success_str = str("{:0.2f}".format(success_avg)) + '%'
544 duration_str = time.strftime("%H:%M:%S",
545 time.gmtime(item['overall_duration']))
546 res_table.add_row([item['test_name'], duration_str,
547 item['nb_tests'], success_str])
548 payload.append({'module': item['test_name'],
549 'details': {'duration': item['overall_duration'],
550 'nb tests': item['nb_tests'],
551 'success': success_str}})
553 total_duration_str = time.strftime("%H:%M:%S",
554 time.gmtime(total_duration))
556 self.result = 100 * total_nb_success / total_nb_tests
557 except ZeroDivisionError:
559 success_rate = "{:0.2f}".format(self.result)
560 success_rate_str = str(success_rate) + '%'
561 res_table.add_row(["", "", "", ""])
562 res_table.add_row(["TOTAL:", total_duration_str, total_nb_tests,
565 LOGGER.info("Rally Summary Report:\n\n%s\n", res_table.get_string())
566 LOGGER.info("Rally '%s' success_rate is %s%% in %s/%s modules",
567 self.case_name, success_rate, nb_modules,
569 payload.append({'summary': {'duration': total_duration,
570 'nb tests': total_nb_tests,
571 'nb success': success_rate}})
572 self.details = payload
575 def export_task(file_name, export_type="html"):
576 """Export all task results (e.g. html or xunit report)
579 subprocess.CalledProcessError: if Rally doesn't return 0
584 cmd = ["rally", "task", "export", "--type", export_type,
586 str(getattr(config.CONF, 'rally_deployment_name')),
588 LOGGER.debug('running command: %s', cmd)
589 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
590 LOGGER.info("%s\n%s", " ".join(cmd), output)
593 def verify_report(file_name, uuid, export_type="html"):
594 """Generate the verifier report (e.g. html or xunit report)
597 subprocess.CalledProcessError: if Rally doesn't return 0
602 cmd = ["rally", "verify", "report", "--type", export_type,
603 "--uuid", uuid, "--to", file_name]
604 LOGGER.debug('running command: %s', cmd)
605 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
606 LOGGER.info("%s\n%s", " ".join(cmd), output)
609 """Cleanup of OpenStack resources. Should be called on completion."""
610 self.clean_rally_conf()
612 self.orig_cloud.delete_flavor(self.flavor_alt.id)
613 super(RallyBase, self).clean()
615 def is_successful(self):
616 """The overall result of the test."""
617 for item in self.summary:
618 if item['task_status'] is False:
619 return testcase.TestCase.EX_TESTCASE_FAILED
621 return super(RallyBase, self).is_successful()
623 def run(self, **kwargs):
625 self.start_time = time.time()
627 assert super(RallyBase, self).run(
628 **kwargs) == testcase.TestCase.EX_OK
631 OS_USERNAME=self.project.user.name,
632 OS_PROJECT_NAME=self.project.project.name,
633 OS_PROJECT_ID=self.project.project.id,
634 OS_PASSWORD=self.project.password)
636 del environ['OS_TENANT_NAME']
637 del environ['OS_TENANT_ID']
638 except Exception: # pylint: disable=broad-except
640 self.create_rally_deployment(environ=environ)
641 self.prepare_run(**kwargs)
642 self.run_tests(**kwargs)
643 self._generate_report()
645 "{}/{}.html".format(self.results_dir, self.case_name))
647 "{}/{}.xml".format(self.results_dir, self.case_name),
648 export_type="junit-xml")
649 res = testcase.TestCase.EX_OK
650 except Exception as exc: # pylint: disable=broad-except
651 LOGGER.error('Error with run: %s', exc)
653 res = testcase.TestCase.EX_RUN_ERROR
654 self.stop_time = time.time()
658 class RallySanity(RallyBase):
659 """Rally sanity testcase implementation."""
661 def __init__(self, **kwargs):
662 """Initialize RallySanity object."""
663 if "case_name" not in kwargs:
664 kwargs["case_name"] = "rally_sanity"
665 super(RallySanity, self).__init__(**kwargs)
667 self.scenario_dir = os.path.join(self.RALLY_SCENARIO_DIR, 'sanity')
670 class RallyFull(RallyBase):
671 """Rally full testcase implementation."""
673 def __init__(self, **kwargs):
674 """Initialize RallyFull object."""
675 if "case_name" not in kwargs:
676 kwargs["case_name"] = "rally_full"
677 super(RallyFull, self).__init__(**kwargs)
679 self.scenario_dir = os.path.join(self.RALLY_SCENARIO_DIR, 'full')
682 class RallyJobs(RallyBase):
683 """Rally OpenStack CI testcase implementation."""
687 def __init__(self, **kwargs):
688 """Initialize RallyJobs object."""
689 if "case_name" not in kwargs:
690 kwargs["case_name"] = "rally_jobs"
691 super(RallyJobs, self).__init__(**kwargs)
692 self.task_file = os.path.join(self.RALLY_DIR, 'rally_jobs.yaml')
693 self.task_yaml = None
695 def prepare_run(self, **kwargs):
696 """Create resources needed by test scenarios."""
697 super(RallyJobs, self).prepare_run(**kwargs)
698 with open(os.path.join(self.RALLY_DIR,
699 'rally_jobs.yaml'), 'r') as task_file:
700 self.task_yaml = yaml.safe_load(task_file)
702 for task in self.task_yaml:
703 if task not in self.tests:
704 raise Exception("Test '%s' not in '%s'" %
707 def apply_blacklist(self, case_file_name, result_file_name):
708 # pylint: disable=too-many-branches
709 """Apply blacklist."""
710 LOGGER.debug("Applying blacklist...")
711 black_tests = list(set(self.excl_func() +
712 self.excl_scenario()))
714 LOGGER.debug("Blacklisted tests: %s", str(black_tests))
716 template = YAML(typ='jinja2')
717 with open(case_file_name, 'r') as fname:
718 cases = template.load(fname)
719 if cases.get("version", 1) == 1:
720 # scenarios in dictionary
721 for name in cases.keys():
722 if self.in_iterable_re(name, black_tests):
725 # workloads in subtasks
726 for sind, subtask in enumerate(cases.get('subtasks', [])):
728 for wind, workload in enumerate(subtask.get('workloads', [])):
729 scenario = workload.get('scenario', {})
730 for name in scenario.keys():
731 if self.in_iterable_re(name, black_tests):
734 for wind in reversed(idx):
735 cases['subtasks'][sind]['workloads'].pop(wind)
736 # scenarios in subtasks
738 for sind, subtask in enumerate(cases.get('subtasks', [])):
739 scenario = subtask.get('scenario', {})
740 for name in scenario.keys():
741 if self.in_iterable_re(name, black_tests):
744 for sind in reversed(idx):
745 cases['subtasks'].pop(sind)
747 with open(result_file_name, 'w') as fname:
748 template.dump(cases, fname)
750 def build_task_args(self, test_name):
751 """Build arguments for the Rally task."""
754 task_args['floating_network'] = str(self.ext_net.name)
756 task_args['floating_network'] = ''
760 def _remove_plugins_extra():
761 inst_dir = getattr(config.CONF, 'dir_rally_inst')
763 shutil.rmtree(os.path.join(inst_dir, 'plugins'))
764 shutil.rmtree(os.path.join(inst_dir, 'extra'))
765 except Exception: # pylint: disable=broad-except
768 def prepare_task(self, test_name):
769 """Prepare resources for test run."""
770 self._remove_plugins_extra()
771 jobs_dir = os.path.join(
772 getattr(config.CONF, 'dir_rally_data'), test_name, 'rally-jobs')
773 inst_dir = getattr(config.CONF, 'dir_rally_inst')
774 shutil.copytree(os.path.join(jobs_dir, 'plugins'),
775 os.path.join(inst_dir, 'plugins'))
776 shutil.copytree(os.path.join(jobs_dir, 'extra'),
777 os.path.join(inst_dir, 'extra'))
779 task_name = self.task_yaml.get(test_name).get("task")
780 task = os.path.join(jobs_dir, task_name)
781 if not os.path.exists(task):
782 raise Exception("The scenario '%s' does not exist." % task)
783 LOGGER.debug('Scenario fetched from : %s', task)
785 if not os.path.exists(self.TEMP_DIR):
786 os.makedirs(self.TEMP_DIR)
787 task_file_name = os.path.join(self.TEMP_DIR, task_name)
788 self.apply_blacklist(task, task_file_name)
789 self.run_cmd = (["rally", "task", "start", "--task", task_file_name,
790 "--task-args", str(self.build_task_args(test_name))])
794 self._remove_plugins_extra()
795 super(RallyJobs, self).clean()