Merge "Make `boot_runcommand_delete' accept command-dict"
This commit is contained in:
commit
557f1ef21e
@ -599,7 +599,19 @@
|
|||||||
name: {{image_name}}
|
name: {{image_name}}
|
||||||
floating_network: "public"
|
floating_network: "public"
|
||||||
use_floatingip: true
|
use_floatingip: true
|
||||||
script: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
command:
|
||||||
|
script_inline: |
|
||||||
|
time_seconds(){ (time -p $1 ) 2>&1 |awk '/real/{print $2}'; }
|
||||||
|
file=/tmp/test.img
|
||||||
|
c=100 #100M
|
||||||
|
write_seq=$(time_seconds "dd if=/dev/zero of=$file bs=1M count=$c")
|
||||||
|
read_seq=$(time_seconds "dd if=$file of=/dev/null bs=1M count=$c")
|
||||||
|
[ -f $file ] && rm $file
|
||||||
|
|
||||||
|
echo "{
|
||||||
|
\"write_seq\": $write_seq,
|
||||||
|
\"read_seq\": $read_seq
|
||||||
|
}"
|
||||||
interpreter: "/bin/sh"
|
interpreter: "/bin/sh"
|
||||||
username: "cirros"
|
username: "cirros"
|
||||||
runner:
|
runner:
|
||||||
@ -623,7 +635,8 @@
|
|||||||
volume_args:
|
volume_args:
|
||||||
size: 2
|
size: 2
|
||||||
use_floatingip: true
|
use_floatingip: true
|
||||||
script: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
command:
|
||||||
|
script_file: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
||||||
interpreter: "/bin/sh"
|
interpreter: "/bin/sh"
|
||||||
username: "cirros"
|
username: "cirros"
|
||||||
runner:
|
runner:
|
||||||
@ -645,7 +658,8 @@
|
|||||||
image:
|
image:
|
||||||
name: {{image_name}}
|
name: {{image_name}}
|
||||||
use_floatingip: false
|
use_floatingip: false
|
||||||
script: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
command:
|
||||||
|
script_file: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
||||||
interpreter: "/bin/sh"
|
interpreter: "/bin/sh"
|
||||||
username: "cirros"
|
username: "cirros"
|
||||||
runner:
|
runner:
|
||||||
|
@ -295,7 +295,8 @@
|
|||||||
name: "TestVM|cirros.*uec"
|
name: "TestVM|cirros.*uec"
|
||||||
floating_network: "net04_ext"
|
floating_network: "net04_ext"
|
||||||
use_floatingip: true
|
use_floatingip: true
|
||||||
script: "/home/rally/.rally/extra/instance_dd_test.sh"
|
command:
|
||||||
|
script_file: "/home/rally/.rally/extra/instance_dd_test.sh"
|
||||||
interpreter: "/bin/sh"
|
interpreter: "/bin/sh"
|
||||||
username: "cirros"
|
username: "cirros"
|
||||||
runner:
|
runner:
|
||||||
|
@ -459,7 +459,8 @@
|
|||||||
name: "m1.tiny"
|
name: "m1.tiny"
|
||||||
image:
|
image:
|
||||||
name: {{image_name}}
|
name: {{image_name}}
|
||||||
script: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
command:
|
||||||
|
script_file: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
||||||
interpreter: "/bin/sh"
|
interpreter: "/bin/sh"
|
||||||
username: "cirros"
|
username: "cirros"
|
||||||
runner:
|
runner:
|
||||||
|
@ -47,7 +47,8 @@ class VMScenario(base.Scenario):
|
|||||||
|
|
||||||
:param ssh: A SSHClient instance.
|
:param ssh: A SSHClient instance.
|
||||||
:param command: Dictionary specifying command to execute.
|
:param command: Dictionary specifying command to execute.
|
||||||
See `validation.valid_command' docstring for details.
|
See `rally info find VMTasks.boot_runcommand_delete' parameter
|
||||||
|
`command' docstring for explanation.
|
||||||
|
|
||||||
:returns: tuple (exit_status, stdout, stderr)
|
:returns: tuple (exit_status, stdout, stderr)
|
||||||
"""
|
"""
|
||||||
@ -150,7 +151,8 @@ class VMScenario(base.Scenario):
|
|||||||
:param username: str. ssh username for server
|
:param username: str. ssh username for server
|
||||||
:param password: Password for SSH authentication
|
:param password: Password for SSH authentication
|
||||||
:param command: Dictionary specifying command to execute.
|
:param command: Dictionary specifying command to execute.
|
||||||
See `valiation.valid_command' docstring for explanation.
|
See `rally info find VMTasks.boot_runcommand_delete' parameter
|
||||||
|
`command' docstring for explanation.
|
||||||
:param pkey: key for SSH authentication
|
:param pkey: key for SSH authentication
|
||||||
|
|
||||||
:returns: tuple (exit_status, stdout, stderr)
|
:returns: tuple (exit_status, stdout, stderr)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from rally.common import utils
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally.plugins.openstack.scenarios.cinder import utils as cinder_utils
|
from rally.plugins.openstack.scenarios.cinder import utils as cinder_utils
|
||||||
@ -35,7 +36,10 @@ class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario,
|
|||||||
@types.set(image=types.ImageResourceType,
|
@types.set(image=types.ImageResourceType,
|
||||||
flavor=types.FlavorResourceType)
|
flavor=types.FlavorResourceType)
|
||||||
@validation.image_valid_on_flavor("flavor", "image")
|
@validation.image_valid_on_flavor("flavor", "image")
|
||||||
@validation.file_exists("script")
|
@utils.log_deprecated_args("Use `command' argument instead", "0.0.5",
|
||||||
|
("script", "interpreter"), once=True)
|
||||||
|
@validation.file_exists("script", required=False)
|
||||||
|
@validation.valid_command("command", required=False)
|
||||||
@validation.number("port", minval=1, maxval=65535, nullable=True,
|
@validation.number("port", minval=1, maxval=65535, nullable=True,
|
||||||
integer_only=True)
|
integer_only=True)
|
||||||
@validation.external_network_exists("floating_network")
|
@validation.external_network_exists("floating_network")
|
||||||
@ -44,8 +48,11 @@ class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario,
|
|||||||
@base.scenario(context={"cleanup": ["nova", "cinder"],
|
@base.scenario(context={"cleanup": ["nova", "cinder"],
|
||||||
"keypair": {}, "allow_ssh": {}})
|
"keypair": {}, "allow_ssh": {}})
|
||||||
def boot_runcommand_delete(self, image, flavor,
|
def boot_runcommand_delete(self, image, flavor,
|
||||||
script, interpreter, username,
|
username,
|
||||||
password=None,
|
password=None,
|
||||||
|
script=None,
|
||||||
|
interpreter=None,
|
||||||
|
command=None,
|
||||||
volume_args=None,
|
volume_args=None,
|
||||||
floating_network=None,
|
floating_network=None,
|
||||||
port=22,
|
port=22,
|
||||||
@ -58,11 +65,52 @@ class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario,
|
|||||||
|
|
||||||
:param image: glance image name to use for the vm
|
:param image: glance image name to use for the vm
|
||||||
:param flavor: VM flavor name
|
:param flavor: VM flavor name
|
||||||
:param script: script to run on server, must output JSON mapping
|
|
||||||
metric names to values (see the sample script below)
|
|
||||||
:param interpreter: server's interpreter to run the script
|
|
||||||
:param username: ssh username on server, str
|
:param username: ssh username on server, str
|
||||||
:param password: Password on SSH authentication
|
:param password: Password on SSH authentication
|
||||||
|
:param script: DEPRECATED. Use `command' instead. Script to run on
|
||||||
|
server, must output JSON mapping metric names to values (see the
|
||||||
|
sample script below)
|
||||||
|
:param interpreter: DEPRECATED. Use `command' instead. server's
|
||||||
|
interpreter to run the script
|
||||||
|
:param command: Command-specifying dictionary that either specifies
|
||||||
|
remote command path via `remote_path', an inline script via
|
||||||
|
`script_inline' or a local script file path using `script_file'.
|
||||||
|
The `script_file' is checked to be accessible by the `file_exists'
|
||||||
|
validator.
|
||||||
|
|
||||||
|
The `script_inline' and `script_file' both require an `interpreter'
|
||||||
|
value to specify the interpreter script should be run with.
|
||||||
|
|
||||||
|
Note that any of `interpreter' and `remote_path' can be an array
|
||||||
|
prefixed with environment variables and suffixed with args for
|
||||||
|
the `interpreter' command.
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
# Run a `local_script.pl' file sending it to a remote
|
||||||
|
# Perl interpreter
|
||||||
|
command = {
|
||||||
|
"script_file": "local_script.pl",
|
||||||
|
"interpreter": "/usr/bin/perl"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run an inline script sending it to a remote interpreter
|
||||||
|
command = {
|
||||||
|
"script_inline": "echo 'Hello, World!'",
|
||||||
|
"interpreter": "/bin/sh"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run a remote command
|
||||||
|
command = {
|
||||||
|
"remote_path": "/bin/false"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run an inline script sending it to a remote interpreter
|
||||||
|
command = {
|
||||||
|
"script_inline": "echo \"Hello, ${NAME:-World}\"",
|
||||||
|
"interpreter": ["NAME=Earth", "/bin/sh"]
|
||||||
|
}
|
||||||
|
|
||||||
:param volume_args: volume args for booting server from volume
|
:param volume_args: volume args for booting server from volume
|
||||||
:param floating_network: external network name, for floating ip
|
:param floating_network: external network name, for floating ip
|
||||||
:param port: ssh port for SSH connection
|
:param port: ssh port for SSH connection
|
||||||
@ -74,6 +122,9 @@ class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario,
|
|||||||
errors: str, raw data from the script's stderr stream
|
errors: str, raw data from the script's stderr stream
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if command is None and script and interpreter:
|
||||||
|
command = {"script_file": script, "interpreter": interpreter}
|
||||||
|
|
||||||
if volume_args:
|
if volume_args:
|
||||||
volume = self._create_volume(volume_args["size"], imageRef=None)
|
volume = self._create_volume(volume_args["size"], imageRef=None)
|
||||||
kwargs["block_device_mapping"] = {"vdrally": "%s:::1" % volume.id}
|
kwargs["block_device_mapping"] = {"vdrally": "%s:::1" % volume.id}
|
||||||
@ -85,21 +136,20 @@ class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario,
|
|||||||
**kwargs)
|
**kwargs)
|
||||||
try:
|
try:
|
||||||
code, out, err = self._run_command(
|
code, out, err = self._run_command(
|
||||||
fip["ip"], port, username, password,
|
fip["ip"], port, username, password, command=command)
|
||||||
command={"script_file": script, "interpreter": interpreter})
|
|
||||||
if code:
|
if code:
|
||||||
raise exceptions.ScriptError(
|
raise exceptions.ScriptError(
|
||||||
"Error running script %(script)s. "
|
"Error running command %(command)s. "
|
||||||
"Error %(code)s: %(error)s" % {
|
"Error %(code)s: %(error)s" % {
|
||||||
"script": script, "code": code, "error": err})
|
"command": command, "code": code, "error": err})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(out)
|
data = json.loads(out)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise exceptions.ScriptError(
|
raise exceptions.ScriptError(
|
||||||
"Script %(script)s has not output valid JSON: %(error)s. "
|
"Command %(command)s has not output valid JSON: %(error)s."
|
||||||
"Output: %(output)s" % {
|
" Output: %(output)s" % {
|
||||||
"script": script, "error": str(e), "output": out})
|
"command": command, "error": str(e), "output": out})
|
||||||
finally:
|
finally:
|
||||||
self._delete_server_with_fip(server, fip,
|
self._delete_server_with_fip(server, fip,
|
||||||
force_delete=force_delete)
|
force_delete=force_delete)
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from rally.common import log
|
||||||
|
from rally.common import utils
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally.plugins.openstack.scenarios.vm import vmtasks
|
from rally.plugins.openstack.scenarios.vm import vmtasks
|
||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
@ -36,6 +38,7 @@ class VMTasksTestCase(test.TestCase):
|
|||||||
return_value=(0, "\"foo_out\"", "foo_err"))
|
return_value=(0, "\"foo_out\"", "foo_err"))
|
||||||
|
|
||||||
def test_boot_runcommand_delete(self):
|
def test_boot_runcommand_delete(self):
|
||||||
|
with log.LogCatcher(utils.LOG) as catcher:
|
||||||
self.scenario.boot_runcommand_delete(
|
self.scenario.boot_runcommand_delete(
|
||||||
"foo_image", "foo_flavor",
|
"foo_image", "foo_flavor",
|
||||||
script="foo_script", interpreter="foo_interpreter",
|
script="foo_script", interpreter="foo_interpreter",
|
||||||
@ -47,6 +50,37 @@ class VMTasksTestCase(test.TestCase):
|
|||||||
volume_args={"size": 16},
|
volume_args={"size": 16},
|
||||||
foo_arg="foo_value")
|
foo_arg="foo_value")
|
||||||
|
|
||||||
|
catcher.assertInLogs(
|
||||||
|
"Use `command' argument instead (args `script', `interpreter' "
|
||||||
|
"deprecated in Rally v0.0.5)")
|
||||||
|
|
||||||
|
self.scenario._create_volume.assert_called_once_with(
|
||||||
|
16, imageRef=None)
|
||||||
|
self.scenario._boot_server_with_fip.assert_called_once_with(
|
||||||
|
"foo_image", "foo_flavor", use_floating_ip="use_fip",
|
||||||
|
floating_network="ext_network", key_name="keypair_name",
|
||||||
|
block_device_mapping={"vdrally": "foo_volume:::1"},
|
||||||
|
foo_arg="foo_value")
|
||||||
|
|
||||||
|
self.scenario._run_command.assert_called_once_with(
|
||||||
|
"foo_ip", 22, "foo_username", "foo_password",
|
||||||
|
command={"script_file": "foo_script",
|
||||||
|
"interpreter": "foo_interpreter"})
|
||||||
|
self.scenario._delete_server_with_fip.assert_called_once_with(
|
||||||
|
"foo_server", self.ip, force_delete="foo_force")
|
||||||
|
|
||||||
|
def test_boot_runcommand_delete_command(self):
|
||||||
|
self.scenario.boot_runcommand_delete(
|
||||||
|
"foo_image", "foo_flavor",
|
||||||
|
command={"remote_path": "foo"},
|
||||||
|
username="foo_username",
|
||||||
|
password="foo_password",
|
||||||
|
use_floating_ip="use_fip",
|
||||||
|
floating_network="ext_network",
|
||||||
|
force_delete="foo_force",
|
||||||
|
volume_args={"size": 16},
|
||||||
|
foo_arg="foo_value")
|
||||||
|
|
||||||
self.scenario._create_volume.assert_called_once_with(
|
self.scenario._create_volume.assert_called_once_with(
|
||||||
16, imageRef=None)
|
16, imageRef=None)
|
||||||
self.scenario._boot_server_with_fip.assert_called_once_with(
|
self.scenario._boot_server_with_fip.assert_called_once_with(
|
||||||
@ -57,8 +91,7 @@ class VMTasksTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.scenario._run_command.assert_called_once_with(
|
self.scenario._run_command.assert_called_once_with(
|
||||||
"foo_ip", 22, "foo_username", "foo_password",
|
"foo_ip", 22, "foo_username", "foo_password",
|
||||||
command={"script_file": "foo_script",
|
command={"remote_path": "foo"})
|
||||||
"interpreter": "foo_interpreter"})
|
|
||||||
self.scenario._delete_server_with_fip.assert_called_once_with(
|
self.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")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user