blob: 093ae12fd9605ef5bf2346cb77f5e58fdfc80790 [file] [log] [blame]
koder aka kdanilov4643fd62015-02-10 16:20:13 -08001import os
2import json
3import time
4import yaml
5import warnings
6import functools
7import contextlib
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08008import multiprocessing
koder aka kdanilov4643fd62015-02-10 16:20:13 -08009
10from rally import exceptions
11from rally.cmd import cliutils
12from rally.cmd.main import categories
13from rally.benchmark.scenarios.vm.utils import VMScenario
14from rally.benchmark.scenarios.vm.vmtasks import VMTasks
15
16import itest
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080017from log import log
18from utils import get_barrier, wait_on_barrier
koder aka kdanilov4643fd62015-02-10 16:20:13 -080019
20
21@contextlib.contextmanager
22def patch_VMTasks_boot_runcommand_delete():
23
24 try:
25 orig = VMTasks.boot_runcommand_delete
26 except AttributeError:
27 # rally code was changed
28 log("VMTasks class was changed and have no boot_runcommand_delete"
29 " method anymore. Update patch code.")
30 raise exceptions.ScriptError("monkeypatch code fails on "
31 "VMTasks.boot_runcommand_delete")
32
33 @functools.wraps(orig)
34 def new_boot_runcommand_delete(self, *args, **kwargs):
35 if 'rally_affinity_group' in os.environ:
36 group_id = os.environ['rally_affinity_group']
37 kwargs['scheduler_hints'] = {'group': group_id}
38 return orig(self, *args, **kwargs)
39
40 VMTasks.boot_runcommand_delete = new_boot_runcommand_delete
41
42 try:
43 yield
44 finally:
45 VMTasks.boot_runcommand_delete = orig
46
47
48# should actually use mock module for this,
49# but don't wanna to add new dependency
50@contextlib.contextmanager
51def patch_VMScenario_run_command_over_ssh(test_obj,
52 barrier=None,
53 latest_start_time=None):
54
55 try:
56 orig = VMScenario.run_action
57 except AttributeError:
58 # rally code was changed
59 log("VMScenario class was changed and have no run_action"
60 " method anymore. Update patch code.")
61 raise exceptions.ScriptError("monkeypatch code fails on "
62 "VMScenario.run_action")
63
64 @functools.wraps(orig)
65 def closure(self, ssh, *args, **kwargs):
koder aka kdanilov50f18642015-02-11 08:54:44 -080066
koder aka kdanilov4643fd62015-02-10 16:20:13 -080067 try:
68 ssh._client.open_sftp
69 except AttributeError:
70 # rally code was changed
71 log("Prototype of VMScenario.run_command_over_ssh "
72 "was changed. Update patch code.")
73 raise exceptions.ScriptError("monkeypatch code fails on "
74 "ssh._client.open_sftp()")
75
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080076 test_iter = itest.run_test_iter(test_obj, ssh._get_client())
koder aka kdanilov4643fd62015-02-10 16:20:13 -080077
78 next(test_iter)
79
80 log("Start io test")
81
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080082 wait_on_barrier(barrier, latest_start_time)
koder aka kdanilov4643fd62015-02-10 16:20:13 -080083
84 try:
85 code, out, err = next(test_iter)
86 except Exception as exc:
87 log("Rally raises exception {0}".format(exc.message))
88 raise
89
90 if 0 != code:
91 templ = "Script returns error! code={0}\n {1}"
92 log(templ.format(code, err.rstrip()))
93 else:
94 log("Test finished")
95
koder aka kdanilov4643fd62015-02-10 16:20:13 -080096 result = {"rally": 0}
97 out = json.dumps(result)
98
99 return code, out, err
100
101 VMScenario.run_action = closure
102
103 try:
104 yield
105 finally:
106 VMScenario.run_action = orig
107
108
koder aka kdanilov50f18642015-02-11 08:54:44 -0800109def prepare_files(files_dir):
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800110
111 # we do need temporary named files
112 with warnings.catch_warnings():
113 warnings.simplefilter("ignore")
114 yaml_file = os.tmpnam()
115
116 yaml_src_cont = open(os.path.join(files_dir, "io.yaml")).read()
117 task_params = yaml.load(yaml_src_cont)
118 rcd_params = task_params['VMTasks.boot_runcommand_delete']
119 rcd_params[0]['args']['script'] = os.path.join(files_dir, "io.py")
120 yaml_dst_cont = yaml.dump(task_params)
121
122 open(yaml_file, "w").write(yaml_dst_cont)
123
124 return yaml_file
125
126
127def run_tests_using_rally(obj,
128 files_dir,
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800129 max_preparation_time,
130 rally_extra_opts,
131 keep_temp_files):
132
koder aka kdanilov50f18642015-02-11 08:54:44 -0800133 yaml_file = prepare_files(files_dir)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800134
135 try:
136 do_patch1 = patch_VMScenario_run_command_over_ssh
137 config = yaml.load(open(yaml_file).read())
138
139 vm_sec = 'VMTasks.boot_runcommand_delete'
140 concurrency = config[vm_sec][0]['runner']['concurrency']
141
142 barrier = get_barrier(concurrency)
143 max_release_time = time.time() + max_preparation_time
144
145 with patch_VMTasks_boot_runcommand_delete():
146 with do_patch1(obj, barrier, max_release_time):
147 opts = ['task', 'start', yaml_file] + list(rally_extra_opts)
148 log("Start rally with opts '{0}'".format(" ".join(opts)))
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800149 cliutils.run(['rally', "--rally-debug"] + opts, categories)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800150 finally:
151 if not keep_temp_files:
152 os.unlink(yaml_file)
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800153
154
155def get_rally_runner(files_dir,
156 max_preparation_time,
157 rally_extra_opts,
158 keep_temp_files):
159
160 def closure(obj):
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800161 result_queue = multiprocessing.Queue()
162 obj.set_result_cb(result_queue.put)
163
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800164 run_tests_using_rally(obj,
165 files_dir,
166 max_preparation_time,
167 rally_extra_opts,
168 keep_temp_files)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800169
170 test_result = []
171 while not result_queue.empty():
172 test_result.append(result_queue.get())
173
174 return test_result
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800175 return closure