Merge "Add task command rally task import"

This commit is contained in:
Jenkins 2017-05-31 15:51:35 +00:00 committed by Gerrit Code Review
commit e2f30013af
7 changed files with 206 additions and 0 deletions

View File

@ -32,6 +32,7 @@ _rally()
OPTS["task_delete"]="--force --uuid"
OPTS["task_detailed"]="--uuid --iterations-data"
OPTS["task_export"]="--uuid --connection"
OPTS["task_import"]="--file --deployment --tag"
OPTS["task_list"]="--deployment --all-deployments --status --uuids-only"
OPTS["task_report"]="--tasks --out --open --html --html-static --junit"
OPTS["task_results"]="--uuid"

View File

@ -485,6 +485,39 @@ class _Task(APIGroup):
objects.Task.delete_by_uuid(
task_uuid, status=consts.TaskStatus.FINISHED)
def import_results(self, deployment, task_results, tag=None):
"""Import json results of a test into rally database"""
deployment = objects.Deployment.get(deployment)
if deployment["status"] != consts.DeployStatus.DEPLOY_FINISHED:
raise exceptions.DeploymentNotFinishedStatus(
name=deployment["name"],
uuid=deployment["uuid"],
status=deployment["status"])
task_inst = objects.Task(deployment_uuid=deployment["uuid"], tag=tag)
task_inst.update_status(consts.TaskStatus.RUNNING)
for result in task_results:
subtask_obj = task_inst.add_subtask(title=result["key"]["name"])
workload_obj = subtask_obj.add_workload(result["key"])
chunk_size = CONF.raw_result_chunk_size
workload_data_count = 0
while len(result["result"]) > chunk_size:
results_chunk = result["result"][:chunk_size]
result["result"] = result["result"][chunk_size:]
results_chunk.sort(key=lambda x: x["timestamp"])
workload_obj.add_workload_data(workload_data_count,
{"raw": results_chunk})
workload_data_count += 1
workload_obj.add_workload_data(workload_data_count,
{"raw": result["result"]})
workload_obj.set_results(result)
subtask_obj.update_status(consts.SubtaskStatus.FINISHED)
task_inst.update_status(consts.SubtaskStatus.FINISHED)
LOG.info("Task results have been successfully imported.")
return task_inst.to_dict()
class _Verifier(APIGroup):

View File

@ -867,3 +867,30 @@ class TaskCommands(object):
return ("%(error_type)s: %(error_message)s\n" %
{"error_type": error_type, "error_message": error_message},
error_traceback)
@cliutils.args("--file", dest="task_file", type=str, metavar="<path>",
required=True, help="JSON file with task results")
@cliutils.args("--deployment", dest="deployment", type=str,
metavar="<uuid>", required=False,
help="UUID or name of a deployment.")
@cliutils.args("--tag", help="Tag for this task")
@envutils.with_default_deployment(cli_arg_name="deployment")
@cliutils.alias("import")
@cliutils.suppress_warnings
def import_results(self, api, deployment=None, task_file=None, tag=None):
"""Import json results of a test into rally database
:param task_file: list, pathes files with tasks results
:param deployment: UUID or name of the deployment
:param tag: optional tag for this task
"""
if os.path.exists(os.path.expanduser(task_file)):
tasks_results = self._load_task_results_file(api, task_file)
task = api.task.import_results(deployment, tasks_results, tag=tag)
print(_("Task UUID: %s.") % task["uuid"])
else:
print(_("ERROR: Invalid file name passed: %s"
) % task_file,
file=sys.stderr)
return 1

View File

@ -123,6 +123,7 @@ function run () {
cp $TASK rally-plot/task.txt
tar -czf rally-plot/plugins.tar.gz -C $RALLY_PLUGINS_DIR .
rally task results | python -m json.tool > rally-plot/results.json
rally task import --file rally-plot/results.json
gzip -9 rally-plot/results.json
rally task detailed > rally-plot/detailed.txt
gzip -9 rally-plot/detailed.txt

View File

@ -171,6 +171,20 @@ class TaskTestCase(unittest.TestCase):
self.assertRaises(utils.RallyCliError,
rally, "task results --uuid %s" % FAKE_TASK_UUID)
def test_import_results(self):
rally = utils.Rally()
cfg = self._get_sample_task_config()
config = utils.TaskConfig(cfg)
rally("task start --task %s" % config.filename)
json_report = rally.gen_report_path(extension="json")
with open(json_report, "w+") as f:
f.write(rally("task results"))
import_print = rally("task import --file %s" % json_report)
self.assertIn("successfully", import_print)
task_uuid = re.search("UUID:\s([a-z0-9\-]+)", import_print).group(1)
self.assertIn("Dummy.dummy_random_fail_in_atomic",
rally("task results --uuid %s" % task_uuid))
def test_abort_with_wrong_task_id(self):
rally = utils.Rally()
self.assertRaises(utils.RallyCliError,

View File

@ -1071,3 +1071,31 @@ class TaskCommandsTestCase(test.TestCase):
self.assertRaises(task.FailedToLoadResults,
self.task._load_task_results_file,
api=self.real_api, task_id=task_id)
@mock.patch("rally.cli.commands.task.os.path")
def test_import_results(self, mock_os_path):
mock_os_path.exists.return_value = True
mock_os_path.expanduser = lambda path: path
self.task._load_task_results_file = mock.MagicMock(
return_value=["results"]
)
self.task.import_results(self.fake_api,
"deployment_uuid",
"task_file", "tag")
self.task._load_task_results_file.assert_called_once_with(
self.fake_api, "task_file"
)
self.fake_api.task.import_results.assert_called_once_with(
"deployment_uuid", ["results"], tag="tag"
)
# not exist
mock_os_path.exists.return_value = False
self.assertEqual(
1,
self.task.import_results(self.fake_api,
"deployment_uuid",
"task_file", "tag")
)

View File

@ -415,6 +415,108 @@ class TaskAPITestCase(test.TestCase):
mock_task.get_detailed.assert_called_once_with("foo_uuid")
mock_task.extend_results.assert_called_once_with("raw_results")
@mock.patch("rally.api.objects.Task")
@mock.patch("rally.api.objects.Deployment.get")
def test_import_results(self, mock_deployment_get, mock_task):
mock_deployment_get.return_value = fakes.FakeDeployment(
uuid="deployment_uuid", admin="fake_admin", users=["fake_user"],
status=consts.DeployStatus.DEPLOY_FINISHED)
task_results = [{"key": {"name": "test_scenario"},
"result": []}]
self.assertEqual(
mock_task.return_value.to_dict(),
self.task_inst.import_results(
mock_deployment_get.return_value["uuid"], task_results)
)
mock_task.assert_called_once_with(deployment_uuid="deployment_uuid",
tag=None)
mock_task.return_value.update_status.assert_has_calls(
[mock.call(consts.TaskStatus.RUNNING),
mock.call(consts.SubtaskStatus.FINISHED)]
)
mock_task.return_value.add_subtask.assert_has_calls(
[mock.call(title=task_results[0]["key"]["name"])]
)
sub_task = mock_task.return_value.add_subtask.return_value
sub_task.add_workload.assert_has_calls(
[mock.call(task_results[0]["key"])]
)
sub_task.update_status.assert_has_calls(
[mock.call(consts.SubtaskStatus.FINISHED)]
)
work_load = sub_task.add_workload.return_value
work_load.add_workload_data.assert_has_calls(
[mock.call(0, {"raw": task_results[0]["result"]})]
)
work_load.set_results.assert_has_calls(
[mock.call(task_results[0])]
)
@mock.patch("rally.api.objects.Task")
@mock.patch("rally.api.objects.Deployment.get")
@mock.patch("rally.api.CONF")
def test_import_results_chunk_size(self, mock_conf,
mock_deployment_get,
mock_task):
mock_deployment_get.return_value = fakes.FakeDeployment(
uuid="deployment_uuid", admin="fake_admin", users=["fake_user"],
status=consts.DeployStatus.DEPLOY_FINISHED)
task_results = [{"key": {"name": "test_scenario"},
"result": [{"timestamp": 1},
{"timestamp": 2},
{"timestamp": 3}]}]
mock_conf.raw_result_chunk_size = 2
self.assertEqual(
mock_task.return_value.to_dict(),
self.task_inst.import_results(
mock_deployment_get.return_value["uuid"], task_results)
)
mock_task.assert_called_once_with(deployment_uuid="deployment_uuid",
tag=None)
mock_task.return_value.update_status.assert_has_calls(
[mock.call(consts.TaskStatus.RUNNING),
mock.call(consts.SubtaskStatus.FINISHED)]
)
mock_task.return_value.add_subtask.assert_has_calls(
[mock.call(title=task_results[0]["key"]["name"])]
)
sub_task = mock_task.return_value.add_subtask.return_value
sub_task.add_workload.assert_has_calls(
[mock.call(task_results[0]["key"])]
)
sub_task.update_status.assert_has_calls(
[mock.call(consts.SubtaskStatus.FINISHED)]
)
work_load = sub_task.add_workload.return_value
work_load.add_workload_data.assert_has_calls(
[mock.call(0, {"raw": [{"timestamp": 1},
{"timestamp": 2}]}),
mock.call(1, {"raw": [{"timestamp": 3}]})
]
)
work_load.set_results.assert_has_calls(
[mock.call(task_results[0])]
)
@mock.patch("rally.api.objects.Deployment.get")
def test_import_results_with_inconsistent_deployment(
self, mock_deployment_get):
fake_deployment = fakes.FakeDeployment(
uuid="deployment_uuid", admin="fake_admin", users=["fake_user"],
status=consts.DeployStatus.DEPLOY_INCONSISTENT,
name="foo")
mock_deployment_get.return_value = fake_deployment
self.assertRaises(exceptions.DeploymentNotFinishedStatus,
self.task_inst.import_results,
"deployment_uuid", [], tag="tag")
class BaseDeploymentTestCase(test.TestCase):
def setUp(self):