blob: e9c4caa46d5dadf86e998ca4b658f0d62cf51b2d [file] [log] [blame]
import os
import json
import time
import yaml
import warnings
import functools
import contextlib
from rally import exceptions
from rally.cmd import cliutils
from rally.cmd.main import categories
from rally.benchmark.scenarios.vm.utils import VMScenario
from rally.benchmark.scenarios.vm.vmtasks import VMTasks
import itest
from utils import get_barrier
def log(x):
pass
@contextlib.contextmanager
def patch_VMTasks_boot_runcommand_delete():
try:
orig = VMTasks.boot_runcommand_delete
except AttributeError:
# rally code was changed
log("VMTasks class was changed and have no boot_runcommand_delete"
" method anymore. Update patch code.")
raise exceptions.ScriptError("monkeypatch code fails on "
"VMTasks.boot_runcommand_delete")
@functools.wraps(orig)
def new_boot_runcommand_delete(self, *args, **kwargs):
if 'rally_affinity_group' in os.environ:
group_id = os.environ['rally_affinity_group']
kwargs['scheduler_hints'] = {'group': group_id}
return orig(self, *args, **kwargs)
VMTasks.boot_runcommand_delete = new_boot_runcommand_delete
try:
yield
finally:
VMTasks.boot_runcommand_delete = orig
# should actually use mock module for this,
# but don't wanna to add new dependency
@contextlib.contextmanager
def patch_VMScenario_run_command_over_ssh(test_obj,
barrier=None,
latest_start_time=None):
try:
orig = VMScenario.run_action
except AttributeError:
# rally code was changed
log("VMScenario class was changed and have no run_action"
" method anymore. Update patch code.")
raise exceptions.ScriptError("monkeypatch code fails on "
"VMScenario.run_action")
@functools.wraps(orig)
def closure(self, ssh, *args, **kwargs):
try:
ssh._client.open_sftp
except AttributeError:
# rally code was changed
log("Prototype of VMScenario.run_command_over_ssh "
"was changed. Update patch code.")
raise exceptions.ScriptError("monkeypatch code fails on "
"ssh._client.open_sftp()")
test_iter = itest.run_test_iter(test_obj, ssh)
next(test_iter)
log("Start io test")
if barrier is not None:
if latest_start_time is not None:
timeout = latest_start_time - time.time()
else:
timeout = None
if timeout is not None and timeout > 0:
msg = "Ready and waiting on barrier. " + \
"Will wait at most {0} seconds"
log(msg.format(int(timeout)))
if not barrier(timeout):
log("Barrier timeouted")
try:
code, out, err = next(test_iter)
except Exception as exc:
log("Rally raises exception {0}".format(exc.message))
raise
if 0 != code:
templ = "Script returns error! code={0}\n {1}"
log(templ.format(code, err.rstrip()))
else:
log("Test finished")
result = {"rally": 0}
out = json.dumps(result)
return code, out, err
VMScenario.run_action = closure
try:
yield
finally:
VMScenario.run_action = orig
def run_rally(rally_args):
return cliutils.run(['rally', "--rally-debug"] + rally_args, categories)
def prepare_files(files_dir):
# we do need temporary named files
with warnings.catch_warnings():
warnings.simplefilter("ignore")
yaml_file = os.tmpnam()
yaml_src_cont = open(os.path.join(files_dir, "io.yaml")).read()
task_params = yaml.load(yaml_src_cont)
rcd_params = task_params['VMTasks.boot_runcommand_delete']
rcd_params[0]['args']['script'] = os.path.join(files_dir, "io.py")
yaml_dst_cont = yaml.dump(task_params)
open(yaml_file, "w").write(yaml_dst_cont)
return yaml_file
def run_tests_using_rally(obj,
files_dir,
max_preparation_time,
rally_extra_opts,
keep_temp_files):
yaml_file = prepare_files(files_dir)
try:
do_patch1 = patch_VMScenario_run_command_over_ssh
config = yaml.load(open(yaml_file).read())
vm_sec = 'VMTasks.boot_runcommand_delete'
concurrency = config[vm_sec][0]['runner']['concurrency']
barrier = get_barrier(concurrency)
max_release_time = time.time() + max_preparation_time
with patch_VMTasks_boot_runcommand_delete():
with do_patch1(obj, barrier, max_release_time):
opts = ['task', 'start', yaml_file] + list(rally_extra_opts)
log("Start rally with opts '{0}'".format(" ".join(opts)))
run_rally(opts)
finally:
if not keep_temp_files:
os.unlink(yaml_file)
def get_rally_runner(files_dir,
max_preparation_time,
rally_extra_opts,
keep_temp_files):
def closure(obj):
run_tests_using_rally(obj,
files_dir,
max_preparation_time,
rally_extra_opts,
keep_temp_files)
return closure