OLD | NEW |
1 import os, time, commands, re, logging, glob, threading, shutil | 1 import os, time, commands, re, logging, glob, threading, shutil |
2 from autotest_lib.client.bin import utils | 2 from autotest_lib.client.bin import utils |
3 from autotest_lib.client.common_lib import error | 3 from autotest_lib.client.common_lib import error |
4 import kvm_vm, kvm_utils, kvm_subprocess, kvm_monitor, ppm_utils, test_setup | 4 import aexpect, virt_utils, kvm_monitor, ppm_utils, virt_test_setup |
| 5 import virt_vm, kvm_vm |
5 try: | 6 try: |
6 import PIL.Image | 7 import PIL.Image |
7 except ImportError: | 8 except ImportError: |
8 logging.warning('No python imaging library installed. PPM image ' | 9 logging.warning('No python imaging library installed. PPM image ' |
9 'conversion to JPEG disabled. In order to enable it, ' | 10 'conversion to JPEG disabled. In order to enable it, ' |
10 'please install python-imaging or the equivalent for your ' | 11 'please install python-imaging or the equivalent for your ' |
11 'distro.') | 12 'distro.') |
12 | 13 |
13 | 14 |
14 _screendump_thread = None | 15 _screendump_thread = None |
15 _screendump_thread_termination_event = None | 16 _screendump_thread_termination_event = None |
16 | 17 |
17 | 18 |
18 def preprocess_image(test, params): | 19 def preprocess_image(test, params): |
19 """ | 20 """ |
20 Preprocess a single QEMU image according to the instructions in params. | 21 Preprocess a single QEMU image according to the instructions in params. |
21 | 22 |
22 @param test: Autotest test object. | 23 @param test: Autotest test object. |
23 @param params: A dict containing image preprocessing parameters. | 24 @param params: A dict containing image preprocessing parameters. |
24 @note: Currently this function just creates an image if requested. | 25 @note: Currently this function just creates an image if requested. |
25 """ | 26 """ |
26 image_filename = kvm_vm.get_image_filename(params, test.bindir) | 27 image_filename = virt_vm.get_image_filename(params, test.bindir) |
27 | 28 |
28 create_image = False | 29 create_image = False |
29 | 30 |
30 if params.get("force_create_image") == "yes": | 31 if params.get("force_create_image") == "yes": |
31 logging.debug("'force_create_image' specified; creating image...") | 32 logging.debug("'force_create_image' specified; creating image...") |
32 create_image = True | 33 create_image = True |
33 elif (params.get("create_image") == "yes" and not | 34 elif (params.get("create_image") == "yes" and not |
34 os.path.exists(image_filename)): | 35 os.path.exists(image_filename)): |
35 logging.debug("Creating image...") | 36 logging.debug("Creating image...") |
36 create_image = True | 37 create_image = True |
37 | 38 |
38 if create_image and not kvm_vm.create_image(params, test.bindir): | 39 if create_image and not virt_vm.create_image(params, test.bindir): |
39 raise error.TestError("Could not create image") | 40 raise error.TestError("Could not create image") |
40 | 41 |
41 | 42 |
42 def preprocess_vm(test, params, env, name): | 43 def preprocess_vm(test, params, env, name): |
43 """ | 44 """ |
44 Preprocess a single VM object according to the instructions in params. | 45 Preprocess a single VM object according to the instructions in params. |
45 Start the VM if requested and get a screendump. | 46 Start the VM if requested and get a screendump. |
46 | 47 |
47 @param test: An Autotest test object. | 48 @param test: An Autotest test object. |
48 @param params: A dict containing VM preprocessing parameters. | 49 @param params: A dict containing VM preprocessing parameters. |
49 @param env: The environment (a dict-like object). | 50 @param env: The environment (a dict-like object). |
50 @param name: The name of the VM object. | 51 @param name: The name of the VM object. |
51 """ | 52 """ |
52 logging.debug("Preprocessing VM '%s'..." % name) | 53 logging.debug("Preprocessing VM '%s'..." % name) |
53 vm = env.get_vm(name) | 54 vm = env.get_vm(name) |
54 if not vm: | 55 if not vm: |
55 logging.debug("VM object does not exist; creating it") | 56 logging.debug("VM object does not exist; creating it") |
56 vm = kvm_vm.VM(name, params, test.bindir, env.get("address_cache")) | 57 vm_type = params.get('vm_type') |
| 58 if vm_type == 'kvm': |
| 59 vm = kvm_vm.VM(name, params, test.bindir, env.get("address_cache")) |
57 env.register_vm(name, vm) | 60 env.register_vm(name, vm) |
58 | 61 |
59 start_vm = False | 62 start_vm = False |
60 | 63 |
61 if params.get("restart_vm") == "yes": | 64 if params.get("restart_vm") == "yes": |
62 logging.debug("'restart_vm' specified; (re)starting VM...") | 65 logging.debug("'restart_vm' specified; (re)starting VM...") |
63 start_vm = True | 66 start_vm = True |
64 elif params.get("migration_mode"): | 67 elif params.get("migration_mode"): |
65 logging.debug("Starting VM in incoming migration mode...") | 68 logging.debug("Starting VM in incoming migration mode...") |
66 start_vm = True | 69 start_vm = True |
67 elif params.get("start_vm") == "yes": | 70 elif params.get("start_vm") == "yes": |
68 if not vm.is_alive(): | 71 if not vm.is_alive(): |
69 logging.debug("VM is not alive; starting it...") | 72 logging.debug("VM is not alive; starting it...") |
70 start_vm = True | 73 start_vm = True |
71 elif vm.make_qemu_command() != vm.make_qemu_command(name, params, | 74 if vm.needs_restart(name=name, params=params, basedir=test.bindir): |
72 test.bindir): | 75 logging.debug("Current VM specs differ from requested one; " |
73 logging.debug("VM's qemu command differs from requested one; " | |
74 "restarting it...") | 76 "restarting it...") |
75 start_vm = True | 77 start_vm = True |
76 | 78 |
77 if start_vm: | 79 if start_vm: |
78 # Start the VM (or restart it if it's already up) | 80 # Start the VM (or restart it if it's already up) |
79 vm.create(name, params, test.bindir, | 81 vm.create(name, params, test.bindir, |
80 migration_mode=params.get("migration_mode")) | 82 migration_mode=params.get("migration_mode")) |
81 else: | 83 else: |
82 # Don't start the VM, just update its params | 84 # Don't start the VM, just update its params |
83 vm.params = params | 85 vm.params = params |
84 | 86 |
85 scrdump_filename = os.path.join(test.debugdir, "pre_%s.ppm" % name) | 87 scrdump_filename = os.path.join(test.debugdir, "pre_%s.ppm" % name) |
86 try: | 88 try: |
87 if vm.monitor: | 89 if vm.monitor: |
88 vm.monitor.screendump(scrdump_filename, debug=False) | 90 vm.monitor.screendump(scrdump_filename, debug=False) |
89 except kvm_monitor.MonitorError, e: | 91 except kvm_monitor.MonitorError, e: |
90 logging.warn(e) | 92 logging.warn(e) |
91 | 93 |
92 | 94 |
93 def postprocess_image(test, params): | 95 def postprocess_image(test, params): |
94 """ | 96 """ |
95 Postprocess a single QEMU image according to the instructions in params. | 97 Postprocess a single QEMU image according to the instructions in params. |
96 | 98 |
97 @param test: An Autotest test object. | 99 @param test: An Autotest test object. |
98 @param params: A dict containing image postprocessing parameters. | 100 @param params: A dict containing image postprocessing parameters. |
99 """ | 101 """ |
100 if params.get("check_image") == "yes": | 102 if params.get("check_image") == "yes": |
101 kvm_vm.check_image(params, test.bindir) | 103 virt_vm.check_image(params, test.bindir) |
102 if params.get("remove_image") == "yes": | 104 if params.get("remove_image") == "yes": |
103 kvm_vm.remove_image(params, test.bindir) | 105 virt_vm.remove_image(params, test.bindir) |
104 | 106 |
105 | 107 |
106 def postprocess_vm(test, params, env, name): | 108 def postprocess_vm(test, params, env, name): |
107 """ | 109 """ |
108 Postprocess a single VM object according to the instructions in params. | 110 Postprocess a single VM object according to the instructions in params. |
109 Kill the VM if requested and get a screendump. | 111 Kill the VM if requested and get a screendump. |
110 | 112 |
111 @param test: An Autotest test object. | 113 @param test: An Autotest test object. |
112 @param params: A dict containing VM postprocessing parameters. | 114 @param params: A dict containing VM postprocessing parameters. |
113 @param env: The environment (a dict-like object). | 115 @param env: The environment (a dict-like object). |
114 @param name: The name of the VM object. | 116 @param name: The name of the VM object. |
115 """ | 117 """ |
116 logging.debug("Postprocessing VM '%s'..." % name) | 118 logging.debug("Postprocessing VM '%s'..." % name) |
117 vm = env.get_vm(name) | 119 vm = env.get_vm(name) |
118 if not vm: | 120 if not vm: |
119 return | 121 return |
120 | 122 |
121 scrdump_filename = os.path.join(test.debugdir, "post_%s.ppm" % name) | 123 scrdump_filename = os.path.join(test.debugdir, "post_%s.ppm" % name) |
122 try: | 124 try: |
123 if vm.monitor: | 125 if vm.monitor: |
124 vm.monitor.screendump(scrdump_filename, debug=False) | 126 vm.monitor.screendump(scrdump_filename, debug=False) |
125 except kvm_monitor.MonitorError, e: | 127 except kvm_monitor.MonitorError, e: |
126 logging.warn(e) | 128 logging.warn(e) |
127 | 129 |
128 if params.get("kill_vm") == "yes": | 130 if params.get("kill_vm") == "yes": |
129 kill_vm_timeout = float(params.get("kill_vm_timeout", 0)) | 131 kill_vm_timeout = float(params.get("kill_vm_timeout", 0)) |
130 if kill_vm_timeout: | 132 if kill_vm_timeout: |
131 logging.debug("'kill_vm' specified; waiting for VM to shut down " | 133 logging.debug("'kill_vm' specified; waiting for VM to shut down " |
132 "before killing it...") | 134 "before killing it...") |
133 kvm_utils.wait_for(vm.is_dead, kill_vm_timeout, 0, 1) | 135 virt_utils.wait_for(vm.is_dead, kill_vm_timeout, 0, 1) |
134 else: | 136 else: |
135 logging.debug("'kill_vm' specified; killing VM...") | 137 logging.debug("'kill_vm' specified; killing VM...") |
136 vm.destroy(gracefully = params.get("kill_vm_gracefully") == "yes") | 138 vm.destroy(gracefully = params.get("kill_vm_gracefully") == "yes") |
137 | 139 |
138 | 140 |
139 def process_command(test, params, env, command, command_timeout, | 141 def process_command(test, params, env, command, command_timeout, |
140 command_noncritical): | 142 command_noncritical): |
141 """ | 143 """ |
142 Pre- or post- custom commands to be executed before/after a test is run | 144 Pre- or post- custom commands to be executed before/after a test is run |
143 | 145 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 @param env: The environment (a dict-like object). | 196 @param env: The environment (a dict-like object). |
195 """ | 197 """ |
196 error.context("preprocessing") | 198 error.context("preprocessing") |
197 # Start tcpdump if it isn't already running | 199 # Start tcpdump if it isn't already running |
198 if "address_cache" not in env: | 200 if "address_cache" not in env: |
199 env["address_cache"] = {} | 201 env["address_cache"] = {} |
200 if "tcpdump" in env and not env["tcpdump"].is_alive(): | 202 if "tcpdump" in env and not env["tcpdump"].is_alive(): |
201 env["tcpdump"].close() | 203 env["tcpdump"].close() |
202 del env["tcpdump"] | 204 del env["tcpdump"] |
203 if "tcpdump" not in env and params.get("run_tcpdump", "yes") == "yes": | 205 if "tcpdump" not in env and params.get("run_tcpdump", "yes") == "yes": |
204 cmd = "%s -npvi any 'dst port 68'" % kvm_utils.find_command("tcpdump") | 206 cmd = "%s -npvi any 'dst port 68'" % virt_utils.find_command("tcpdump") |
205 logging.debug("Starting tcpdump (%s)...", cmd) | 207 logging.debug("Starting tcpdump (%s)...", cmd) |
206 env["tcpdump"] = kvm_subprocess.Tail( | 208 env["tcpdump"] = aexpect.Tail( |
207 command=cmd, | 209 command=cmd, |
208 output_func=_update_address_cache, | 210 output_func=_update_address_cache, |
209 output_params=(env["address_cache"],)) | 211 output_params=(env["address_cache"],)) |
210 if kvm_utils.wait_for(lambda: not env["tcpdump"].is_alive(), | 212 if virt_utils.wait_for(lambda: not env["tcpdump"].is_alive(), |
211 0.1, 0.1, 1.0): | 213 0.1, 0.1, 1.0): |
212 logging.warn("Could not start tcpdump") | 214 logging.warn("Could not start tcpdump") |
213 logging.warn("Status: %s" % env["tcpdump"].get_status()) | 215 logging.warn("Status: %s" % env["tcpdump"].get_status()) |
214 logging.warn("Output:" + kvm_utils.format_str_for_message( | 216 logging.warn("Output:" + virt_utils.format_str_for_message( |
215 env["tcpdump"].get_output())) | 217 env["tcpdump"].get_output())) |
216 | 218 |
217 # Destroy and remove VMs that are no longer needed in the environment | 219 # Destroy and remove VMs that are no longer needed in the environment |
218 requested_vms = params.objects("vms") | 220 requested_vms = params.objects("vms") |
219 for key in env.keys(): | 221 for key in env.keys(): |
220 vm = env[key] | 222 vm = env[key] |
221 if not kvm_utils.is_vm(vm): | 223 if not virt_utils.is_vm(vm): |
222 continue | 224 continue |
223 if not vm.name in requested_vms: | 225 if not vm.name in requested_vms: |
224 logging.debug("VM '%s' found in environment but not required for " | 226 logging.debug("VM '%s' found in environment but not required for " |
225 "test; removing it..." % vm.name) | 227 "test; removing it..." % vm.name) |
226 vm.destroy() | 228 vm.destroy() |
227 del env[key] | 229 del env[key] |
228 | 230 |
229 # Get the KVM kernel module version and write it as a keyval | 231 # Get the KVM kernel module version and write it as a keyval |
230 logging.debug("Fetching KVM module version...") | 232 logging.debug("Fetching KVM module version...") |
231 if os.path.exists("/dev/kvm"): | 233 if os.path.exists("/dev/kvm"): |
232 try: | 234 try: |
233 kvm_version = open("/sys/module/kvm/version").read().strip() | 235 kvm_version = open("/sys/module/kvm/version").read().strip() |
234 except: | 236 except: |
235 kvm_version = os.uname()[2] | 237 kvm_version = os.uname()[2] |
236 else: | 238 else: |
237 kvm_version = "Unknown" | 239 kvm_version = "Unknown" |
238 logging.debug("KVM module not loaded") | 240 logging.debug("KVM module not loaded") |
239 logging.debug("KVM version: %s" % kvm_version) | 241 logging.debug("KVM version: %s" % kvm_version) |
240 test.write_test_keyval({"kvm_version": kvm_version}) | 242 test.write_test_keyval({"kvm_version": kvm_version}) |
241 | 243 |
242 # Get the KVM userspace version and write it as a keyval | 244 # Get the KVM userspace version and write it as a keyval |
243 logging.debug("Fetching KVM userspace version...") | 245 logging.debug("Fetching KVM userspace version...") |
244 qemu_path = kvm_utils.get_path(test.bindir, params.get("qemu_binary", | 246 qemu_path = virt_utils.get_path(test.bindir, params.get("qemu_binary", |
245 "qemu")) | 247 "qemu")) |
246 version_line = commands.getoutput("%s -help | head -n 1" % qemu_path) | 248 version_line = commands.getoutput("%s -help | head -n 1" % qemu_path) |
247 matches = re.findall("[Vv]ersion .*?,", version_line) | 249 matches = re.findall("[Vv]ersion .*?,", version_line) |
248 if matches: | 250 if matches: |
249 kvm_userspace_version = " ".join(matches[0].split()[1:]).strip(",") | 251 kvm_userspace_version = " ".join(matches[0].split()[1:]).strip(",") |
250 else: | 252 else: |
251 kvm_userspace_version = "Unknown" | 253 kvm_userspace_version = "Unknown" |
252 logging.debug("Could not fetch KVM userspace version") | 254 logging.debug("Could not fetch KVM userspace version") |
253 logging.debug("KVM userspace version: %s" % kvm_userspace_version) | 255 logging.debug("KVM userspace version: %s" % kvm_userspace_version) |
254 test.write_test_keyval({"kvm_userspace_version": kvm_userspace_version}) | 256 test.write_test_keyval({"kvm_userspace_version": kvm_userspace_version}) |
255 | 257 |
256 if params.get("setup_hugepages") == "yes": | 258 if params.get("setup_hugepages") == "yes": |
257 h = test_setup.HugePageConfig(params) | 259 h = virt_test_setup.HugePageConfig(params) |
258 h.setup() | 260 h.setup() |
259 | 261 |
260 # Execute any pre_commands | 262 # Execute any pre_commands |
261 if params.get("pre_command"): | 263 if params.get("pre_command"): |
262 process_command(test, params, env, params.get("pre_command"), | 264 process_command(test, params, env, params.get("pre_command"), |
263 int(params.get("pre_command_timeout", "600")), | 265 int(params.get("pre_command_timeout", "600")), |
264 params.get("pre_command_noncritical") == "yes") | 266 params.get("pre_command_noncritical") == "yes") |
265 | 267 |
266 # Preprocess all VMs and images | 268 # Preprocess all VMs and images |
267 process(test, params, env, preprocess_image, preprocess_vm) | 269 process(test, params, env, preprocess_image, preprocess_vm) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 | 335 |
334 # Kill all unresponsive VMs | 336 # Kill all unresponsive VMs |
335 if params.get("kill_unresponsive_vms") == "yes": | 337 if params.get("kill_unresponsive_vms") == "yes": |
336 logging.debug("'kill_unresponsive_vms' specified; killing all VMs " | 338 logging.debug("'kill_unresponsive_vms' specified; killing all VMs " |
337 "that fail to respond to a remote login request...") | 339 "that fail to respond to a remote login request...") |
338 for vm in env.get_all_vms(): | 340 for vm in env.get_all_vms(): |
339 if vm.is_alive(): | 341 if vm.is_alive(): |
340 try: | 342 try: |
341 session = vm.login() | 343 session = vm.login() |
342 session.close() | 344 session.close() |
343 except (kvm_utils.LoginError, kvm_vm.VMError), e: | 345 except (virt_utils.LoginError, virt_vm.VMError), e: |
344 logging.warn(e) | 346 logging.warn(e) |
345 vm.destroy(gracefully=False) | 347 vm.destroy(gracefully=False) |
346 | 348 |
347 # Kill all kvm_subprocess tail threads | 349 # Kill all aexpect tail threads |
348 kvm_subprocess.kill_tail_threads() | 350 aexpect.kill_tail_threads() |
349 | 351 |
350 # Terminate tcpdump if no VMs are alive | 352 # Terminate tcpdump if no VMs are alive |
351 living_vms = [vm for vm in env.get_all_vms() if vm.is_alive()] | 353 living_vms = [vm for vm in env.get_all_vms() if vm.is_alive()] |
352 if not living_vms and "tcpdump" in env: | 354 if not living_vms and "tcpdump" in env: |
353 env["tcpdump"].close() | 355 env["tcpdump"].close() |
354 del env["tcpdump"] | 356 del env["tcpdump"] |
355 | 357 |
356 if params.get("setup_hugepages") == "yes": | 358 if params.get("setup_hugepages") == "yes": |
357 h = test_setup.HugePageConfig(params) | 359 h = virt_test_setup.HugePageConfig(params) |
358 h.cleanup() | 360 h.cleanup() |
359 | 361 |
360 # Execute any post_commands | 362 # Execute any post_commands |
361 if params.get("post_command"): | 363 if params.get("post_command"): |
362 process_command(test, params, env, params.get("post_command"), | 364 process_command(test, params, env, params.get("post_command"), |
363 int(params.get("post_command_timeout", "600")), | 365 int(params.get("post_command_timeout", "600")), |
364 params.get("post_command_noncritical") == "yes") | 366 params.get("post_command_noncritical") == "yes") |
365 | 367 |
366 | 368 |
367 def postprocess_on_error(test, params, env): | 369 def postprocess_on_error(test, params, env): |
(...skipping 21 matching lines...) Expand all Loading... |
389 mac_address, address_cache.get("last_seen")) | 391 mac_address, address_cache.get("last_seen")) |
390 address_cache[mac_address] = address_cache.get("last_seen") | 392 address_cache[mac_address] = address_cache.get("last_seen") |
391 address_cache["time_%s" % mac_address] = time.time() | 393 address_cache["time_%s" % mac_address] = time.time() |
392 del address_cache["last_seen"] | 394 del address_cache["last_seen"] |
393 | 395 |
394 | 396 |
395 def _take_screendumps(test, params, env): | 397 def _take_screendumps(test, params, env): |
396 global _screendump_thread_termination_event | 398 global _screendump_thread_termination_event |
397 temp_dir = test.debugdir | 399 temp_dir = test.debugdir |
398 if params.get("screendump_temp_dir"): | 400 if params.get("screendump_temp_dir"): |
399 temp_dir = kvm_utils.get_path(test.bindir, | 401 temp_dir = virt_utils.get_path(test.bindir, |
400 params.get("screendump_temp_dir")) | 402 params.get("screendump_temp_dir")) |
401 try: | 403 try: |
402 os.makedirs(temp_dir) | 404 os.makedirs(temp_dir) |
403 except OSError: | 405 except OSError: |
404 pass | 406 pass |
405 temp_filename = os.path.join(temp_dir, "scrdump-%s.ppm" % | 407 temp_filename = os.path.join(temp_dir, "scrdump-%s.ppm" % |
406 kvm_utils.generate_random_string(6)) | 408 virt_utils.generate_random_string(6)) |
407 delay = float(params.get("screendump_delay", 5)) | 409 delay = float(params.get("screendump_delay", 5)) |
408 quality = int(params.get("screendump_quality", 30)) | 410 quality = int(params.get("screendump_quality", 30)) |
409 | 411 |
410 cache = {} | 412 cache = {} |
411 | 413 |
412 while True: | 414 while True: |
413 for vm in env.get_all_vms(): | 415 for vm in env.get_all_vms(): |
414 if not vm.is_alive(): | 416 if not vm.is_alive(): |
415 continue | 417 continue |
416 try: | 418 try: |
(...skipping 28 matching lines...) Expand all Loading... |
445 image = PIL.Image.open(temp_filename) | 447 image = PIL.Image.open(temp_filename) |
446 image.save(screendump_filename, format="JPEG", quality=quali
ty) | 448 image.save(screendump_filename, format="JPEG", quality=quali
ty) |
447 cache[hash] = screendump_filename | 449 cache[hash] = screendump_filename |
448 except NameError: | 450 except NameError: |
449 pass | 451 pass |
450 os.unlink(temp_filename) | 452 os.unlink(temp_filename) |
451 if _screendump_thread_termination_event.isSet(): | 453 if _screendump_thread_termination_event.isSet(): |
452 _screendump_thread_termination_event = None | 454 _screendump_thread_termination_event = None |
453 break | 455 break |
454 _screendump_thread_termination_event.wait(delay) | 456 _screendump_thread_termination_event.wait(delay) |
OLD | NEW |