Merge "Add task command rally task import
"
This commit is contained in:
commit
e2f30013af
@ -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"
|
||||
|
33
rally/api.py
33
rally/api.py
@ -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):
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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")
|
||||
)
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user