From 272179a7eeeb14c63fe4581c2eac120c0f21dc9b Mon Sep 17 00:00:00 2001 From: Andrey Kurilin Date: Mon, 21 Sep 2015 17:24:03 +0300 Subject: [PATCH] Implementation of 'rally task abort' command When run with the --soft key, the 'rally task abort' command should wait until the currently running benchmark is finished, otherwise the command interrupts benchmarking immediately after running scenario iterations are finished. Add Task get_status(uuid) method to db sqlalchemy api. NOTE: db schema is updated with new Task statuses. You should execute `rally-manage db recreate` to fix existing databases. Co-Authored-By: Mikhail Dubov Co-Authored-By: Andrey Kurilin Co-Authored-By: Roman Vasilets Change-Id: Ia07d165037eb98a9542ffdc91b7279ef3c3d496f --- etc/rally.bash_completion | 4 +- rally/consts.py | 4 ++ tests/functional/test_cli_task.py | 85 ++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/etc/rally.bash_completion b/etc/rally.bash_completion index 8656a752..4c129449 100644 --- a/etc/rally.bash_completion +++ b/etc/rally.bash_completion @@ -37,7 +37,7 @@ _rally() OPTS["show_keypairs"]="--deployment" OPTS["show_networks"]="--deployment" OPTS["show_secgroups"]="--deployment" - OPTS["task_abort"]="--uuid" + OPTS["task_abort"]="--uuid --soft" OPTS["task_delete"]="--force --uuid" OPTS["task_detailed"]="--uuid --iterations-data" OPTS["task_list"]="--deployment --all-deployments --status --uuids-only" @@ -83,4 +83,4 @@ _rally() return 0 } -complete -o filenames -F _rally rally \ No newline at end of file +complete -o filenames -F _rally rally diff --git a/rally/consts.py b/rally/consts.py index 94c2f616..df2356b2 100644 --- a/rally/consts.py +++ b/rally/consts.py @@ -55,6 +55,10 @@ class _TaskStatus(utils.ImmutableMixin, utils.EnumMixin): CLEANING_UP = "cleaning up" FINISHED = "finished" FAILED = "failed" + ABORTING = "aborting" + SOFT_ABORTING = "soft_aborting" + ABORTED = "aborted" + PAUSED = "paused" class _DeployStatus(utils.ImmutableMixin, utils.EnumMixin): diff --git a/tests/functional/test_cli_task.py b/tests/functional/test_cli_task.py index 41bdf321..f46827fc 100644 --- a/tests/functional/test_cli_task.py +++ b/tests/functional/test_cli_task.py @@ -16,6 +16,8 @@ import json import os import re +import threading +import time import unittest import mock @@ -543,9 +545,88 @@ class TaskTestCase(unittest.TestCase): } self._test_start_abort_on_sla_failure(cfg, times) - # NOTE(oanufriev): Not implemented + def _start_task_in_new_thread(self, rally, cfg, report_file): + deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env) + config = utils.TaskConfig(cfg) + cmd = (("task start --task %(task_file)s " + "--deployment %(deployment_id)s") % + {"task_file": config.filename, + "deployment_id": deployment_id}) + report_path = os.path.join( + os.environ.get("REPORTS_ROOT", "rally-cli-output-files"), + "TaskTestCase", report_file) + task = threading.Thread(target=rally, args=(cmd, ), + kwargs={"report_path": report_path}) + task.start() + uuid = None + while not uuid: + if not uuid: + uuid = utils.get_global("RALLY_TASK", rally.env) + time.sleep(0.5) + return task, uuid + def test_abort(self): - pass + RUNNER_TIMES = 10 + cfg = { + "Dummy.dummy": [ + { + "args": { + "sleep": 5 + }, + "runner": { + "type": "serial", + "times": RUNNER_TIMES + } + } + ] + } + rally = utils.Rally() + task, uuid = self._start_task_in_new_thread( + rally, cfg, "test_abort-thread_with_abort.txt") + rally("task abort %s" % uuid) + task.join() + results = json.loads(rally("task results")) + iterations_completed = len(results[0]["result"]) + # NOTE(msdubov): check that the task is really stopped before + # the specified number of iterations + self.assertTrue(iterations_completed < RUNNER_TIMES) + self.assertIn("aborted", rally("task status")) + report = rally.gen_report_path(extension="html") + rally("task report --out %s" % report) + + def test_abort_soft(self): + cfg = { + "Dummy.dummy": [ + { + "args": { + "sleep": 2 + }, + "runner": { + "type": "serial", + "times": 3, + } + }, + { + "runner": { + "type": "serial", + "times": 10, + } + } + ] + } + rally = utils.Rally() + task, uuid = self._start_task_in_new_thread( + rally, cfg, "test_abort_soft-thread_with_soft_abort.txt") + rally("task abort --soft") + task.join() + results = json.loads(rally("task results")) + iterations_completed = len(results[0]["result"]) + # NOTE(msdubov): check that the task is stopped after first runner + # benchmark finished all its iterations + self.assertEqual(3, iterations_completed) + # NOTE(msdubov): check that the next benchmark scenario is not started + self.assertEqual(1, len(results)) + self.assertIn("aborted", rally("task status")) def test_use(self): rally = utils.Rally()