Enabling support of 'script_inline' option
Starting from rev.0.4.2 following format of results is supported:
{"
"\"additive\": [{chart data}, {chart data}, ...], "
"\"complete\": [{chart data}, {chart data}, ...]}\n"
This patch enables support of all other types of output format
by using 'TextArea' widget
Change-Id: I5d31c3450c5f6a622cf66eebb8edf0c5878ab64f
This commit is contained in:
committed by
Staroverov Anton
parent
71fc24e160
commit
4e5d802e0c
@@ -161,19 +161,23 @@ class BootRuncommandDelete(vm_utils.VMScenario):
|
|||||||
|
|
||||||
code, out, err = self._run_command(
|
code, out, err = self._run_command(
|
||||||
fip["ip"], port, username, password, command=command)
|
fip["ip"], port, username, password, command=command)
|
||||||
|
text_area_output = ["StdErr: %s" % (err or "(none)"),
|
||||||
|
"StdOut:"]
|
||||||
if code:
|
if code:
|
||||||
raise exceptions.ScriptError(
|
raise exceptions.ScriptError(
|
||||||
"Error running command %(command)s. "
|
"Error running command %(command)s. "
|
||||||
"Error %(code)s: %(error)s" % {
|
"Error %(code)s: %(error)s" % {
|
||||||
"command": command, "code": code, "error": err})
|
"command": command, "code": code, "error": err})
|
||||||
|
# Let's try to load output data
|
||||||
try:
|
try:
|
||||||
data = json.loads(out)
|
data = json.loads(out)
|
||||||
except ValueError as e:
|
# 'echo 42' produces very json-compatible result
|
||||||
raise exceptions.ScriptError(
|
# - check it here
|
||||||
"Command %(command)s has not output valid JSON: %(error)s."
|
if not isinstance(data, dict):
|
||||||
" Output: %(output)s" % {
|
raise ValueError
|
||||||
"command": command, "error": str(e), "output": out})
|
except ValueError:
|
||||||
|
# It's not a JSON, probably it's 'script_inline' result
|
||||||
|
data = []
|
||||||
except (exceptions.TimeoutException,
|
except (exceptions.TimeoutException,
|
||||||
exceptions.SSHTimeout):
|
exceptions.SSHTimeout):
|
||||||
console_logs = self._get_server_console_output(server,
|
console_logs = self._get_server_console_output(server,
|
||||||
@@ -185,38 +189,16 @@ class BootRuncommandDelete(vm_utils.VMScenario):
|
|||||||
self._delete_server_with_fip(server, fip,
|
self._delete_server_with_fip(server, fip,
|
||||||
force_delete=force_delete)
|
force_delete=force_delete)
|
||||||
|
|
||||||
if type(data) != dict:
|
if isinstance(data, dict) and set(data) == {"additive", "complete"}:
|
||||||
raise exceptions.ScriptError(
|
|
||||||
"Command has returned data in unexpected format.\n"
|
|
||||||
"Expected format: {"
|
|
||||||
"\"additive\": [{chart data}, {chart data}, ...], "
|
|
||||||
"\"complete\": [{chart data}, {chart data}, ...]}\n"
|
|
||||||
"Actual data: %s" % data)
|
|
||||||
|
|
||||||
if set(data) - {"additive", "complete"}:
|
|
||||||
LOG.warning(
|
|
||||||
"Deprecated since Rally release 0.4.1: command has "
|
|
||||||
"returned data in format {\"key\": <value>, ...}\n"
|
|
||||||
"Expected format: {"
|
|
||||||
"\"additive\": [{chart data}, {chart data}, ...], "
|
|
||||||
"\"complete\": [{chart data}, {chart data}, ...]}")
|
|
||||||
output = None
|
|
||||||
try:
|
|
||||||
output = [[str(k), float(v)] for k, v in data.items()]
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
raise exceptions.ScriptError(
|
|
||||||
"Command has returned data in unexpected format.\n"
|
|
||||||
"Expected format: {key1: <number>, "
|
|
||||||
"key2: <number>, ...}.\n"
|
|
||||||
"Actual data: %s" % data)
|
|
||||||
if output:
|
|
||||||
self.add_output(additive={"title": "Command output",
|
|
||||||
"chart_plugin": "Lines",
|
|
||||||
"data": output})
|
|
||||||
else:
|
|
||||||
for chart_type, charts in data.items():
|
for chart_type, charts in data.items():
|
||||||
for chart in charts:
|
for chart in charts:
|
||||||
self.add_output(**{chart_type: chart})
|
self.add_output(**{chart_type: chart})
|
||||||
|
else:
|
||||||
|
# it's a dict with several unknown lines
|
||||||
|
text_area_output.extend(out.split("\n"))
|
||||||
|
self.add_output(complete={"title": "Script Output",
|
||||||
|
"chart_plugin": "TextArea",
|
||||||
|
"data": text_area_output})
|
||||||
|
|
||||||
|
|
||||||
@scenario.configure(context={"cleanup": ["nova", "heat"],
|
@scenario.configure(context={"cleanup": ["nova", "heat"],
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{% set flavor_name = flavor_name or "m1.tiny" %}
|
||||||
|
{
|
||||||
|
"VMTasks.boot_runcommand_delete": [
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"flavor": {
|
||||||
|
"name": "{{flavor_name}}"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"name": "^cirros.*-disk$"
|
||||||
|
},
|
||||||
|
"floating_network": "public",
|
||||||
|
"force_delete": false,
|
||||||
|
"command": {
|
||||||
|
"interpreter": "/bin/sh",
|
||||||
|
"script_inline": "ls -la"
|
||||||
|
},
|
||||||
|
"username": "cirros"
|
||||||
|
},
|
||||||
|
"runner": {
|
||||||
|
"type": "constant",
|
||||||
|
"times": 10,
|
||||||
|
"concurrency": 2
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"users": {
|
||||||
|
"tenants": 3,
|
||||||
|
"users_per_tenant": 2
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{% set flavor_name = flavor_name or "m1.tiny" %}
|
||||||
|
---
|
||||||
|
VMTasks.boot_runcommand_delete:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
flavor:
|
||||||
|
name: "{{flavor_name}}"
|
||||||
|
image:
|
||||||
|
name: "^cirros.*-disk$"
|
||||||
|
floating_network: "public"
|
||||||
|
force_delete: false
|
||||||
|
command:
|
||||||
|
interpreter: "/bin/sh"
|
||||||
|
script_inline: "ls -la"
|
||||||
|
username: "cirros"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 10
|
||||||
|
concurrency: 2
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 3
|
||||||
|
users_per_tenant: 2
|
||||||
|
network: {}
|
||||||
@@ -75,21 +75,43 @@ class VMTasksTestCase(test.ScenarioTestCase):
|
|||||||
scenario._delete_server_with_fip.assert_called_once_with(
|
scenario._delete_server_with_fip.assert_called_once_with(
|
||||||
"foo_server", self.ip, force_delete="foo_force")
|
"foo_server", self.ip, force_delete="foo_force")
|
||||||
scenario.add_output.assert_called_once_with(
|
scenario.add_output.assert_called_once_with(
|
||||||
additive={"title": "Command output", "chart_plugin": "Lines",
|
complete={"chart_plugin": "TextArea",
|
||||||
"data": [["foo", 42.0]]})
|
"data": [
|
||||||
|
"StdErr: foo_err",
|
||||||
|
"StdOut:",
|
||||||
|
"{\"foo\": 42}"],
|
||||||
|
"title": "Script Output"})
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
{"output": (0, "", ""), "raises": exceptions.ScriptError},
|
{"output": (0, "", ""),
|
||||||
{"output": (0, "{\"foo\": 42}", ""),
|
"expected": [{"complete": {"chart_plugin": "TextArea",
|
||||||
"expected": [{"additive": {"chart_plugin": "Lines",
|
"data": [
|
||||||
"data": [["foo", 42.0]],
|
"StdErr: (none)",
|
||||||
"title": "Command output"}}]},
|
"StdOut:",
|
||||||
|
""],
|
||||||
|
"title": "Script Output"}}]},
|
||||||
{"output": (1, "{\"foo\": 42}", ""), "raises": exceptions.ScriptError},
|
{"output": (1, "{\"foo\": 42}", ""), "raises": exceptions.ScriptError},
|
||||||
{"output": ("", 1, ""), "raises": TypeError},
|
{"output": ("", 1, ""), "raises": TypeError},
|
||||||
|
{"output": (0, "{\"foo\": 42}", ""),
|
||||||
|
"expected": [{"complete": {"chart_plugin": "TextArea",
|
||||||
|
"data": [
|
||||||
|
"StdErr: (none)",
|
||||||
|
"StdOut:",
|
||||||
|
"{\"foo\": 42}"],
|
||||||
|
"title": "Script Output"}}]},
|
||||||
{"output": (0, "{\"additive\": [1, 2]}", ""),
|
{"output": (0, "{\"additive\": [1, 2]}", ""),
|
||||||
"expected": [{"additive": 1}, {"additive": 2}]},
|
"expected": [{"complete": {"chart_plugin": "TextArea",
|
||||||
|
"data": [
|
||||||
|
"StdErr: (none)",
|
||||||
|
"StdOut:", "{\"additive\": [1, 2]}"],
|
||||||
|
"title": "Script Output"}}]},
|
||||||
{"output": (0, "{\"complete\": [3, 4]}", ""),
|
{"output": (0, "{\"complete\": [3, 4]}", ""),
|
||||||
"expected": [{"complete": 3}, {"complete": 4}]},
|
"expected": [{"complete": {"chart_plugin": "TextArea",
|
||||||
|
"data": [
|
||||||
|
"StdErr: (none)",
|
||||||
|
"StdOut:",
|
||||||
|
"{\"complete\": [3, 4]}"],
|
||||||
|
"title": "Script Output"}}]},
|
||||||
{"output": (0, "{\"additive\": [1, 2], \"complete\": [3, 4]}", ""),
|
{"output": (0, "{\"additive\": [1, 2], \"complete\": [3, 4]}", ""),
|
||||||
"expected": [{"additive": 1}, {"additive": 2},
|
"expected": [{"additive": 1}, {"additive": 2},
|
||||||
{"complete": 3}, {"complete": 4}]}
|
{"complete": 3}, {"complete": 4}]}
|
||||||
@@ -172,13 +194,14 @@ class VMTasksTestCase(test.ScenarioTestCase):
|
|||||||
scenario = self.create_env(vmtasks.BootRuncommandDelete(self.context))
|
scenario = self.create_env(vmtasks.BootRuncommandDelete(self.context))
|
||||||
|
|
||||||
mock_json.loads.side_effect = ValueError()
|
mock_json.loads.side_effect = ValueError()
|
||||||
self.assertRaises(exceptions.ScriptError,
|
scenario.run("foo_image", "foo_flavor", "foo_interpreter",
|
||||||
scenario.run,
|
"foo_script", "foo_username")
|
||||||
"foo_image", "foo_flavor", "foo_interpreter",
|
scenario.add_output.assert_called_once_with(complete={
|
||||||
"foo_script", "foo_username")
|
"chart_plugin": "TextArea", "data": ["StdErr: foo_err",
|
||||||
|
"StdOut:", "{\"foo\": 42}"],
|
||||||
|
"title": "Script Output"})
|
||||||
scenario._delete_server_with_fip.assert_called_once_with(
|
scenario._delete_server_with_fip.assert_called_once_with(
|
||||||
"foo_server", self.ip, force_delete=False)
|
"foo_server", self.ip, force_delete=False)
|
||||||
self.assertFalse(scenario.add_output.called)
|
|
||||||
|
|
||||||
def test_boot_runcommand_delete_custom_image(self):
|
def test_boot_runcommand_delete_custom_image(self):
|
||||||
context = {
|
context = {
|
||||||
@@ -221,8 +244,11 @@ class VMTasksTestCase(test.ScenarioTestCase):
|
|||||||
scenario._delete_server_with_fip.assert_called_once_with(
|
scenario._delete_server_with_fip.assert_called_once_with(
|
||||||
"foo_server", self.ip, force_delete="foo_force")
|
"foo_server", self.ip, force_delete="foo_force")
|
||||||
scenario.add_output.assert_called_once_with(
|
scenario.add_output.assert_called_once_with(
|
||||||
additive={"title": "Command output", "chart_plugin": "Lines",
|
complete={"chart_plugin": "TextArea",
|
||||||
"data": [["foo", 42.0]]})
|
"data": [
|
||||||
|
"StdErr: foo_err",
|
||||||
|
"StdOut:", "{\"foo\": 42}"],
|
||||||
|
"title": "Script Output"})
|
||||||
|
|
||||||
@mock.patch("%s.heat" % BASE)
|
@mock.patch("%s.heat" % BASE)
|
||||||
@mock.patch("%s.sshutils" % BASE)
|
@mock.patch("%s.sshutils" % BASE)
|
||||||
|
|||||||
Reference in New Issue
Block a user