Merge "Make `boot_runcommand_delete' accept command-dict"

This commit is contained in:
Jenkins 2015-07-14 02:26:00 +00:00 committed by Gerrit Code Review
commit 557f1ef21e
6 changed files with 128 additions and 27 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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")