Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: client/tests/kvm/kvm_utils.py

Issue 6124004: Revert "Merge remote branch 'cros/upstream' into autotest-rebase" (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/autotest.git@master
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « client/tests/kvm/kvm_test_utils.py ('k') | client/tests/kvm/kvm_vm.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 """ 1 """
2 KVM test utility functions. 2 KVM test utility functions.
3 3
4 @copyright: 2008-2009 Red Hat Inc. 4 @copyright: 2008-2009 Red Hat Inc.
5 """ 5 """
6 6
7 import time, string, random, socket, os, signal, re, logging, commands, cPickle 7 import time, string, random, socket, os, signal, re, logging, commands, cPickle
8 import fcntl, shelve, ConfigParser, rss_file_transfer, threading, sys, UserDict 8 import fcntl, shelve, ConfigParser
9 from autotest_lib.client.bin import utils, os_dep 9 from autotest_lib.client.bin import utils, os_dep
10 from autotest_lib.client.common_lib import error, logging_config 10 from autotest_lib.client.common_lib import error, logging_config
11 import kvm_subprocess 11 import kvm_subprocess
12 try: 12 try:
13 import koji 13 import koji
14 KOJI_INSTALLED = True 14 KOJI_INSTALLED = True
15 except ImportError: 15 except ImportError:
16 KOJI_INSTALLED = False 16 KOJI_INSTALLED = False
17 17
18 18
19 def _lock_file(filename): 19 def _lock_file(filename):
20 f = open(filename, "w") 20 f = open(filename, "w")
21 fcntl.lockf(f, fcntl.LOCK_EX) 21 fcntl.lockf(f, fcntl.LOCK_EX)
22 return f 22 return f
23 23
24 24
25 def _unlock_file(f): 25 def _unlock_file(f):
26 fcntl.lockf(f, fcntl.LOCK_UN) 26 fcntl.lockf(f, fcntl.LOCK_UN)
27 f.close() 27 f.close()
28 28
29 29
30 def is_vm(obj): 30 def dump_env(obj, filename):
31 """ 31 """
32 Tests whether a given object is a VM object. 32 Dump KVM test environment to a file.
33 33
34 @param obj: Python object. 34 @param filename: Path to a file where the environment will be dumped to.
35 """ 35 """
36 return obj.__class__.__name__ == "VM" 36 file = open(filename, "w")
37 cPickle.dump(obj, file)
38 file.close()
37 39
38 40
39 class Env(UserDict.IterableUserDict): 41 def load_env(filename, version):
40 """ 42 """
41 A dict-like object containing global objects used by tests. 43 Load KVM test environment from an env file.
44 If the version recorded in the file is lower than version, return an empty
45 env. If some other error occurs during unpickling, return an empty env.
46
47 @param filename: Path to an env file.
42 """ 48 """
43 def __init__(self, filename=None, version=0): 49 default = {"version": version}
44 """ 50 try:
45 Create an empty Env object or load an existing one from a file. 51 file = open(filename, "r")
46 52 env = cPickle.load(file)
47 If the version recorded in the file is lower than version, or if some 53 file.close()
48 error occurs during unpickling, or if filename is not supplied, 54 if env.get("version", 0) < version:
49 create an empty Env object. 55 logging.warn("Incompatible env file found. Not using it.")
50 56 return default
51 @param filename: Path to an env file. 57 return env
52 @param version: Required env version (int). 58 # Almost any exception can be raised during unpickling, so let's catch
53 """ 59 # them all
54 UserDict.IterableUserDict.__init__(self) 60 except Exception, e:
55 empty = {"version": version} 61 logging.warn(e)
56 if filename: 62 return default
57 self._filename = filename
58 try:
59 f = open(filename, "r")
60 env = cPickle.load(f)
61 f.close()
62 if env.get("version", 0) >= version:
63 self.data = env
64 else:
65 logging.warn("Incompatible env file found. Not using it.")
66 self.data = empty
67 # Almost any exception can be raised during unpickling, so let's
68 # catch them all
69 except Exception, e:
70 logging.warn(e)
71 self.data = empty
72 else:
73 self.data = empty
74 63
75 64
76 def save(self, filename=None): 65 def get_sub_dict(dict, name):
77 """ 66 """
78 Pickle the contents of the Env object into a file. 67 Return a "sub-dict" corresponding to a specific object.
79 68
80 @param filename: Filename to pickle the dict into. If not supplied, 69 Operate on a copy of dict: for each key that ends with the suffix
81 use the filename from which the dict was loaded. 70 "_" + name, strip the suffix from the key, and set the value of
82 """ 71 the stripped key to that of the key. Return the resulting dict.
83 filename = filename or self._filename 72
84 f = open(filename, "w") 73 @param name: Suffix of the key we want to set the value.
85 cPickle.dump(self.data, f) 74 """
86 f.close() 75 suffix = "_" + name
76 new_dict = dict.copy()
77 for key in dict.keys():
78 if key.endswith(suffix):
79 new_key = key.split(suffix)[0]
80 new_dict[new_key] = dict[key]
81 return new_dict
87 82
88 83
89 def get_all_vms(self): 84 def get_sub_dict_names(dict, keyword):
90 """ 85 """
91 Return a list of all VM objects in this Env object. 86 Return a list of "sub-dict" names that may be extracted with get_sub_dict.
92 """
93 return [o for o in self.values() if is_vm(o)]
94 87
88 This function may be modified to change the behavior of all functions that
89 deal with multiple objects defined in dicts (e.g. VMs, images, NICs).
95 90
96 def get_vm(self, name): 91 @param keyword: A key in dict (e.g. "vms", "images", "nics").
97 """
98 Return a VM object by its name.
99
100 @param name: VM name.
101 """
102 return self.get("vm__%s" % name)
103
104
105 def register_vm(self, name, vm):
106 """
107 Register a VM in this Env object.
108
109 @param name: VM name.
110 @param vm: VM object.
111 """
112 self["vm__%s" % name] = vm
113
114
115 def unregister_vm(self, name):
116 """
117 Remove a given VM.
118
119 @param name: VM name.
120 """
121 del self["vm__%s" % name]
122
123
124 def register_installer(self, installer):
125 """
126 Register a installer that was just run
127
128 The installer will be available for other tests, so that
129 information about the installed KVM modules and qemu-kvm can be used by
130 them.
131 """
132 self['last_installer'] = installer
133
134
135 def previous_installer(self):
136 """
137 Return the last installer that was registered
138 """
139 return self.get('last_installer')
140
141
142 class Params(UserDict.IterableUserDict):
143 """ 92 """
144 A dict-like object passed to every test. 93 names = dict.get(keyword)
145 """ 94 if names:
146 def objects(self, key): 95 return names.split()
147 """ 96 else:
148 Return the names of objects defined using a given key. 97 return []
149
150 @param key: The name of the key whose value lists the objects
151 (e.g. 'nics').
152 """
153 return self.get(key, "").split()
154
155
156 def object_params(self, obj_name):
157 """
158 Return a dict-like object containing the parameters of an individual
159 object.
160
161 This method behaves as follows: the suffix '_' + obj_name is removed
162 from all key names that have it. Other key names are left unchanged.
163 The values of keys with the suffix overwrite the values of their
164 suffixless versions.
165
166 @param obj_name: The name of the object (objects are listed by the
167 objects() method).
168 """
169 suffix = "_" + obj_name
170 new_dict = self.copy()
171 for key in self:
172 if key.endswith(suffix):
173 new_key = key.split(suffix)[0]
174 new_dict[new_key] = self[key]
175 return new_dict
176 98
177 99
178 # Functions related to MAC/IP addresses 100 # Functions related to MAC/IP addresses
179 101
180 def _open_mac_pool(lock_mode): 102 def _open_mac_pool(lock_mode):
181 lock_file = open("/tmp/mac_lock", "w+") 103 lock_file = open("/tmp/mac_lock", "w+")
182 fcntl.lockf(lock_file, lock_mode) 104 fcntl.lockf(lock_file, lock_mode)
183 pool = shelve.open("/tmp/address_pool") 105 pool = shelve.open("/tmp/address_pool")
184 return pool, lock_file 106 return pool, lock_file
185 107
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 if not dev: 233 if not dev:
312 return False 234 return False
313 dev = dev[0].split()[-1] 235 dev = dev[0].split()[-1]
314 236
315 # Send an ARP request 237 # Send an ARP request
316 o = commands.getoutput("%s -f -c 3 -I %s %s" % 238 o = commands.getoutput("%s -f -c 3 -I %s %s" %
317 (find_command("arping"), dev, ip)) 239 (find_command("arping"), dev, ip))
318 return bool(regex.search(o)) 240 return bool(regex.search(o))
319 241
320 242
243 # Functions for working with the environment (a dict-like object)
244
245 def is_vm(obj):
246 """
247 Tests whether a given object is a VM object.
248
249 @param obj: Python object (pretty much everything on python).
250 """
251 return obj.__class__.__name__ == "VM"
252
253
254 def env_get_all_vms(env):
255 """
256 Return a list of all VM objects on a given environment.
257
258 @param env: Dictionary with environment items.
259 """
260 vms = []
261 for obj in env.values():
262 if is_vm(obj):
263 vms.append(obj)
264 return vms
265
266
267 def env_get_vm(env, name):
268 """
269 Return a VM object by its name.
270
271 @param name: VM name.
272 """
273 return env.get("vm__%s" % name)
274
275
276 def env_register_vm(env, name, vm):
277 """
278 Register a given VM in a given env.
279
280 @param env: Environment where we will register the VM.
281 @param name: VM name.
282 @param vm: VM object.
283 """
284 env["vm__%s" % name] = vm
285
286
287 def env_unregister_vm(env, name):
288 """
289 Remove a given VM from a given env.
290
291 @param env: Environment where we will un-register the VM.
292 @param name: VM name.
293 """
294 del env["vm__%s" % name]
295
296
321 # Utility functions for dealing with external processes 297 # Utility functions for dealing with external processes
322 298
323 def find_command(cmd): 299 def find_command(cmd):
324 for dir in ["/usr/local/sbin", "/usr/local/bin", 300 for dir in ["/usr/local/sbin", "/usr/local/bin",
325 "/usr/sbin", "/usr/bin", "/sbin", "/bin"]: 301 "/usr/sbin", "/usr/bin", "/sbin", "/bin"]:
326 file = os.path.join(dir, cmd) 302 file = os.path.join(dir, cmd)
327 if os.path.exists(file): 303 if os.path.exists(file):
328 return file 304 return file
329 raise ValueError('Missing command: %s' % cmd) 305 raise ValueError('Missing command: %s' % cmd)
330 306
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 occasions build may be dependant on the source directory disposition. 414 occasions build may be dependant on the source directory disposition.
439 The reason why the return codes are numbers is that we might have more 415 The reason why the return codes are numbers is that we might have more
440 changes on the source directory layout, so it's not scalable to just use 416 changes on the source directory layout, so it's not scalable to just use
441 strings like 'old_repo', 'new_repo' and such. 417 strings like 'old_repo', 'new_repo' and such.
442 418
443 @param source_dir: Source code path that will be inspected. 419 @param source_dir: Source code path that will be inspected.
444 """ 420 """
445 os.chdir(source_dir) 421 os.chdir(source_dir)
446 has_qemu_dir = os.path.isdir('qemu') 422 has_qemu_dir = os.path.isdir('qemu')
447 has_kvm_dir = os.path.isdir('kvm') 423 has_kvm_dir = os.path.isdir('kvm')
448 if has_qemu_dir: 424 if has_qemu_dir and not has_kvm_dir:
449 logging.debug("qemu directory detected, source dir layout 1") 425 logging.debug("qemu directory detected, source dir layout 1")
450 return 1 426 return 1
451 if has_kvm_dir and not has_qemu_dir: 427 if has_kvm_dir and not has_qemu_dir:
452 logging.debug("kvm directory detected, source dir layout 2") 428 logging.debug("kvm directory detected, source dir layout 2")
453 return 2 429 return 2
454 else: 430 else:
455 raise error.TestError("Unknown source dir layout, cannot proceed.") 431 raise error.TestError("Unknown source dir layout, cannot proceed.")
456 432
457 433
458 # The following are functions used for SSH, SCP and Telnet communication with 434 # The following are functions used for SSH, SCP and Telnet communication with
459 # guests. 435 # guests.
460 436
461 def _remote_login(session, username, password, prompt, timeout=10): 437 def _remote_login(session, username, password, prompt, timeout=10):
462 """ 438 """
463 Log into a remote host (guest) using SSH or Telnet. Wait for questions 439 Log into a remote host (guest) using SSH or Telnet. Wait for questions
464 and provide answers. If timeout expires while waiting for output from the 440 and provide answers. If timeout expires while waiting for output from the
465 child (e.g. a password prompt or a shell prompt) -- fail. 441 child (e.g. a password prompt or a shell prompt) -- fail.
466 442
467 @brief: Log into a remote host (guest) using SSH or Telnet. 443 @brief: Log into a remote host (guest) using SSH or Telnet.
468 444
469 @param session: An Expect or ShellSession instance to operate on 445 @param session: A kvm_expect or kvm_shell_session instance to operate on
470 @param username: The username to send in reply to a login prompt 446 @param username: The username to send in reply to a login prompt
471 @param password: The password to send in reply to a password prompt 447 @param password: The password to send in reply to a password prompt
472 @param prompt: The shell prompt that indicates a successful login 448 @param prompt: The shell prompt that indicates a successful login
473 @param timeout: The maximal time duration (in seconds) to wait for each 449 @param timeout: The maximal time duration (in seconds) to wait for each
474 step of the login procedure (i.e. the "Are you sure" prompt, the 450 step of the login procedure (i.e. the "Are you sure" prompt, the
475 password prompt, the shell prompt, etc) 451 password prompt, the shell prompt, etc)
476 452
477 @return: True on success and False otherwise. 453 @return: True on success and False otherwise.
478 """ 454 """
479 password_prompt_count = 0 455 password_prompt_count = 0
480 login_prompt_count = 0 456 login_prompt_count = 0
481 457
482 while True: 458 while True:
483 try: 459 (match, text) = session.read_until_last_line_matches(
484 match, text = session.read_until_last_line_matches(
485 [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"[Ll]ogin:\s*$", 460 [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"[Ll]ogin:\s*$",
486 r"[Cc]onnection.*closed", r"[Cc]onnection.*refused", 461 r"[Cc]onnection.*closed", r"[Cc]onnection.*refused",
487 r"[Pp]lease wait", prompt], 462 r"[Pp]lease wait", prompt],
488 timeout=timeout, internal_timeout=0.5) 463 timeout=timeout, internal_timeout=0.5)
489 if match == 0: # "Are you sure you want to continue connecting" 464 if match == 0: # "Are you sure you want to continue connecting"
490 logging.debug("Got 'Are you sure...'; sending 'yes'") 465 logging.debug("Got 'Are you sure...'; sending 'yes'")
491 session.sendline("yes") 466 session.sendline("yes")
467 continue
468 elif match == 1: # "password:"
469 if password_prompt_count == 0:
470 logging.debug("Got password prompt; sending '%s'" % password)
471 session.sendline(password)
472 password_prompt_count += 1
492 continue 473 continue
493 elif match == 1: # "password:" 474 else:
494 if password_prompt_count == 0: 475 logging.debug("Got password prompt again")
495 logging.debug("Got password prompt; sending '%s'" % password )
496 session.sendline(password)
497 password_prompt_count += 1
498 continue
499 else:
500 logging.debug("Got password prompt again")
501 return False
502 elif match == 2: # "login:"
503 if login_prompt_count == 0:
504 logging.debug("Got username prompt; sending '%s'" % username )
505 session.sendline(username)
506 login_prompt_count += 1
507 continue
508 else:
509 logging.debug("Got username prompt again")
510 return False
511 elif match == 3: # "Connection closed"
512 logging.debug("Got 'Connection closed'")
513 return False 476 return False
514 elif match == 4: # "Connection refused" 477 elif match == 2: # "login:"
515 logging.debug("Got 'Connection refused'") 478 if login_prompt_count == 0:
479 logging.debug("Got username prompt; sending '%s'" % username)
480 session.sendline(username)
481 login_prompt_count += 1
482 continue
483 else:
484 logging.debug("Got username prompt again")
516 return False 485 return False
517 elif match == 5: # "Please wait" 486 elif match == 3: # "Connection closed"
518 logging.debug("Got 'Please wait'") 487 logging.debug("Got 'Connection closed'")
519 timeout = 30
520 continue
521 elif match == 6: # prompt
522 logging.debug("Got shell prompt -- logged in")
523 return True
524 except kvm_subprocess.ExpectTimeoutError, e:
525 logging.debug("Timeout elapsed (output so far: %r)" % e.output)
526 return False 488 return False
527 except kvm_subprocess.ExpectProcessTerminatedError, e: 489 elif match == 4: # "Connection refused"
528 logging.debug("Process terminated (output so far: %r)" % e.output) 490 logging.debug("Got 'Connection refused'")
491 return False
492 elif match == 5: # "Please wait"
493 logging.debug("Got 'Please wait'")
494 timeout = 30
495 continue
496 elif match == 6: # prompt
497 logging.debug("Got shell prompt -- logged in")
498 return session
499 else: # match == None
500 logging.debug("Timeout elapsed or process terminated")
529 return False 501 return False
530 502
531 503
532 def _remote_scp(session, password, transfer_timeout=600, login_timeout=10): 504 def _remote_scp(session, password, transfer_timeout=600, login_timeout=10):
533 """ 505 """
534 Transfer file(s) to a remote host (guest) using SCP. Wait for questions 506 Transfer file(s) to a remote host (guest) using SCP. Wait for questions
535 and provide answers. If login_timeout expires while waiting for output 507 and provide answers. If login_timeout expires while waiting for output
536 from the child (e.g. a password prompt), fail. If transfer_timeout expires 508 from the child (e.g. a password prompt), fail. If transfer_timeout expires
537 while waiting for the transfer to complete, fail. 509 while waiting for the transfer to complete, fail.
538 510
539 @brief: Transfer files using SCP, given a command line. 511 @brief: Transfer files using SCP, given a command line.
540 512
541 @param session: An Expect or ShellSession instance to operate on 513 @param session: A kvm_expect or kvm_shell_session instance to operate on
542 @param password: The password to send in reply to a password prompt. 514 @param password: The password to send in reply to a password prompt.
543 @param transfer_timeout: The time duration (in seconds) to wait for the 515 @param transfer_timeout: The time duration (in seconds) to wait for the
544 transfer to complete. 516 transfer to complete.
545 @param login_timeout: The maximal time duration (in seconds) to wait for 517 @param login_timeout: The maximal time duration (in seconds) to wait for
546 each step of the login procedure (i.e. the "Are you sure" prompt or 518 each step of the login procedure (i.e. the "Are you sure" prompt or
547 the password prompt) 519 the password prompt)
548 520
549 @return: True if the transfer succeeds and False on failure. 521 @return: True if the transfer succeeds and False on failure.
550 """ 522 """
551 password_prompt_count = 0 523 password_prompt_count = 0
552 timeout = login_timeout 524 timeout = login_timeout
553 525
554 while True: 526 while True:
555 try: 527 (match, text) = session.read_until_last_line_matches(
556 match, text = session.read_until_last_line_matches(
557 [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"lost connection"], 528 [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"lost connection"],
558 timeout=timeout, internal_timeout=0.5) 529 timeout=timeout, internal_timeout=0.5)
559 if match == 0: # "Are you sure you want to continue connecting" 530 if match == 0: # "Are you sure you want to continue connecting"
560 logging.debug("Got 'Are you sure...'; sending 'yes'") 531 logging.debug("Got 'Are you sure...'; sending 'yes'")
561 session.sendline("yes") 532 session.sendline("yes")
533 continue
534 elif match == 1: # "password:"
535 if password_prompt_count == 0:
536 logging.debug("Got password prompt; sending '%s'" % password)
537 session.sendline(password)
538 password_prompt_count += 1
539 timeout = transfer_timeout
562 continue 540 continue
563 elif match == 1: # "password:" 541 else:
564 if password_prompt_count == 0: 542 logging.debug("Got password prompt again")
565 logging.debug("Got password prompt; sending '%s'" % password )
566 session.sendline(password)
567 password_prompt_count += 1
568 timeout = transfer_timeout
569 continue
570 else:
571 logging.debug("Got password prompt again")
572 return False
573 elif match == 2: # "lost connection"
574 logging.debug("Got 'lost connection'")
575 return False 543 return False
576 except kvm_subprocess.ExpectTimeoutError, e: 544 elif match == 2: # "lost connection"
577 logging.debug("Timeout expired") 545 logging.debug("Got 'lost connection'")
578 return False 546 return False
579 except kvm_subprocess.ExpectProcessTerminatedError, e: 547 else: # match == None
580 logging.debug("SCP process terminated with status %s", e.status) 548 if session.is_alive():
581 return e.status == 0 549 logging.debug("Timeout expired")
550 return False
551 else:
552 status = session.get_status()
553 logging.debug("SCP process terminated with status %s", status)
554 return status == 0
582 555
583 556
584 def remote_login(client, host, port, username, password, prompt, linesep="\n", 557 def remote_login(client, host, port, username, password, prompt, linesep="\n",
585 log_filename=None, timeout=10): 558 log_filename=None, timeout=10):
586 """ 559 """
587 Log into a remote host (guest) using SSH/Telnet/Netcat. 560 Log into a remote host (guest) using SSH/Telnet/Netcat.
588 561
589 @param client: The client to use ('ssh', 'telnet' or 'nc') 562 @param client: The client to use ('ssh', 'telnet' or 'nc')
590 @param host: Hostname or IP address 563 @param host: Hostname or IP address
591 @param port: Port to connect to 564 @param port: Port to connect to
592 @param username: Username (if required) 565 @param username: Username (if required)
593 @param password: Password (if required) 566 @param password: Password (if required)
594 @param prompt: Shell prompt (regular expression) 567 @param prompt: Shell prompt (regular expression)
595 @param linesep: The line separator to use when sending lines 568 @param linesep: The line separator to use when sending lines
596 (e.g. '\\n' or '\\r\\n') 569 (e.g. '\\n' or '\\r\\n')
597 @param log_filename: If specified, log all output to this file 570 @param log_filename: If specified, log all output to this file
598 @param timeout: The maximal time duration (in seconds) to wait for 571 @param timeout: The maximal time duration (in seconds) to wait for
599 each step of the login procedure (i.e. the "Are you sure" prompt 572 each step of the login procedure (i.e. the "Are you sure" prompt
600 or the password prompt) 573 or the password prompt)
601 574
602 @return: ShellSession object on success and None on failure. 575 @return: kvm_shell_session object on success and None on failure.
603 """ 576 """
604 if client == "ssh": 577 if client == "ssh":
605 cmd = ("ssh -o UserKnownHostsFile=/dev/null " 578 cmd = ("ssh -o UserKnownHostsFile=/dev/null "
606 "-o PreferredAuthentications=password -p %s %s@%s" % 579 "-o PreferredAuthentications=password -p %s %s@%s" %
607 (port, username, host)) 580 (port, username, host))
608 elif client == "telnet": 581 elif client == "telnet":
609 cmd = "telnet -l %s %s %s" % (username, host, port) 582 cmd = "telnet -l %s %s %s" % (username, host, port)
610 elif client == "nc": 583 elif client == "nc":
611 cmd = "nc %s %s" % (host, port) 584 cmd = "nc %s %s" % (host, port)
612 else: 585 else:
613 logging.error("Unknown remote shell client: %s" % client) 586 logging.error("Unknown remote shell client: %s" % client)
614 return 587 return
615 588
616 logging.debug("Trying to login with command '%s'" % cmd) 589 logging.debug("Trying to login with command '%s'" % cmd)
617 session = kvm_subprocess.ShellSession(cmd, linesep=linesep, prompt=prompt) 590 session = kvm_subprocess.kvm_shell_session(cmd, linesep=linesep,
591 prompt=prompt)
618 if _remote_login(session, username, password, prompt, timeout): 592 if _remote_login(session, username, password, prompt, timeout):
619 if log_filename: 593 if log_filename:
620 session.set_output_func(log_line) 594 session.set_output_func(log_line)
621 session.set_output_params((log_filename,)) 595 session.set_output_params((log_filename,))
622 return session 596 return session
623 else: 597 else:
624 session.close() 598 session.close()
625 599
626 600
627 def remote_scp(command, password, log_filename=None, transfer_timeout=600, 601 def remote_scp(command, password, log_filename=None, transfer_timeout=600,
(...skipping 18 matching lines...) Expand all
646 logging.debug("Trying to SCP with command '%s', timeout %ss", 620 logging.debug("Trying to SCP with command '%s', timeout %ss",
647 command, transfer_timeout) 621 command, transfer_timeout)
648 622
649 if log_filename: 623 if log_filename:
650 output_func = log_line 624 output_func = log_line
651 output_params = (log_filename,) 625 output_params = (log_filename,)
652 else: 626 else:
653 output_func = None 627 output_func = None
654 output_params = () 628 output_params = ()
655 629
656 session = kvm_subprocess.Expect(command, 630 session = kvm_subprocess.kvm_expect(command,
657 output_func=output_func, 631 output_func=output_func,
658 output_params=output_params) 632 output_params=output_params)
659 try: 633 try:
660 return _remote_scp(session, password, transfer_timeout, login_timeout) 634 return _remote_scp(session, password, transfer_timeout, login_timeout)
661 finally: 635 finally:
662 session.close() 636 session.close()
663 637
664 638
665 def copy_files_to(address, client, username, password, port, local_path,
666 remote_path, log_filename=None, timeout=600):
667 """
668 Decide the transfer cleint and copy file to a remote host (guest).
669
670 @param client: Type of transfer client
671 @param username: Username (if required)
672 @param password: Password (if requried)
673 @param local_path: Path on the local machine where we are copying from
674 @param remote_path: Path on the remote machine where we are copying to
675 @param address: Address of remote host(guest)
676 @param log_filename: If specified, log all output to this file
677 @param timeout: The time duration (in seconds) to wait for the transfer to
678 complete.
679
680 @return: True on success and False on failure.
681 """
682
683 if not address or not port:
684 logging.debug("IP address or port unavailable")
685 return None
686
687 if client == "scp":
688 return scp_to_remote(address, port, username, password, local_path,
689 remote_path, log_filename, timeout)
690 elif client == "rss":
691 c = rss_file_transfer.FileUploadClient(address, port)
692 c.upload(local_path, remote_path, timeout)
693 c.close()
694 return True
695
696
697 def copy_files_from(address, client, username, password, port, local_path,
698 remote_path, log_filename=None, timeout=600):
699 """
700 Decide the transfer cleint and copy file from a remote host (guest).
701
702 @param client: Type of transfer client
703 @param username: Username (if required)
704 @param password: Password (if requried)
705 @param local_path: Path on the local machine where we are copying from
706 @param remote_path: Path on the remote machine where we are copying to
707 @param address: Address of remote host(guest)
708 @param log_filename: If specified, log all output to this file
709 @param timeout: The time duration (in seconds) to wait for the transfer to
710 complete.
711
712 @return: True on success and False on failure.
713 """
714
715 if not address or not port:
716 logging.debug("IP address or port unavailable")
717 return None
718
719 if client == "scp":
720 return scp_from_remote(address, port, username, password, remote_path,
721 local_path, log_filename, timeout)
722 elif client == "rss":
723 c = rss_file_transfer.FileDownloadClient(address, port)
724 c.download(remote_path, local_path, timeout)
725 c.close()
726 return True
727
728
729 def scp_to_remote(host, port, username, password, local_path, remote_path, 639 def scp_to_remote(host, port, username, password, local_path, remote_path,
730 log_filename=None, timeout=600): 640 log_filename=None, timeout=600):
731 """ 641 """
732 Copy files to a remote host (guest) through scp. 642 Copy files to a remote host (guest).
733 643
734 @param host: Hostname or IP address 644 @param host: Hostname or IP address
735 @param username: Username (if required) 645 @param username: Username (if required)
736 @param password: Password (if required) 646 @param password: Password (if required)
737 @param local_path: Path on the local machine where we are copying from 647 @param local_path: Path on the local machine where we are copying from
738 @param remote_path: Path on the remote machine where we are copying to 648 @param remote_path: Path on the remote machine where we are copying to
739 @param log_filename: If specified, log all output to this file 649 @param log_filename: If specified, log all output to this file
740 @param timeout: The time duration (in seconds) to wait for the transfer 650 @param timeout: The time duration (in seconds) to wait for the transfer
741 to complete. 651 to complete.
742 652
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 def get_vendor_from_pci_id(pci_id): 971 def get_vendor_from_pci_id(pci_id):
1062 """ 972 """
1063 Check out the device vendor ID according to pci_id. 973 Check out the device vendor ID according to pci_id.
1064 974
1065 @param pci_id: PCI ID of a device. 975 @param pci_id: PCI ID of a device.
1066 """ 976 """
1067 cmd = "lspci -n | awk '/%s/ {print $3}'" % pci_id 977 cmd = "lspci -n | awk '/%s/ {print $3}'" % pci_id
1068 return re.sub(":", " ", commands.getoutput(cmd)) 978 return re.sub(":", " ", commands.getoutput(cmd))
1069 979
1070 980
1071 class Thread(threading.Thread):
1072 """
1073 Run a function in a background thread.
1074 """
1075 def __init__(self, target, args=(), kwargs={}):
1076 """
1077 Initialize the instance.
1078
1079 @param target: Function to run in the thread.
1080 @param args: Arguments to pass to target.
1081 @param kwargs: Keyword arguments to pass to target.
1082 """
1083 threading.Thread.__init__(self)
1084 self._target = target
1085 self._args = args
1086 self._kwargs = kwargs
1087
1088
1089 def run(self):
1090 """
1091 Run target (passed to the constructor). No point in calling this
1092 function directly. Call start() to make this function run in a new
1093 thread.
1094 """
1095 self._e = None
1096 self._retval = None
1097 try:
1098 try:
1099 self._retval = self._target(*self._args, **self._kwargs)
1100 except:
1101 self._e = sys.exc_info()
1102 raise
1103 finally:
1104 # Avoid circular references (start() may be called only once so
1105 # it's OK to delete these)
1106 del self._target, self._args, self._kwargs
1107
1108
1109 def join(self, timeout=None):
1110 """
1111 Join the thread. If target raised an exception, re-raise it.
1112 Otherwise, return the value returned by target.
1113
1114 @param timeout: Timeout value to pass to threading.Thread.join().
1115 """
1116 threading.Thread.join(self, timeout)
1117 try:
1118 if self._e:
1119 raise self._e[0], self._e[1], self._e[2]
1120 else:
1121 return self._retval
1122 finally:
1123 # Avoid circular references (join() may be called multiple times
1124 # so we can't delete these)
1125 self._e = None
1126 self._retval = None
1127
1128
1129 def parallel(targets):
1130 """
1131 Run multiple functions in parallel.
1132
1133 @param targets: A sequence of tuples or functions. If it's a sequence of
1134 tuples, each tuple will be interpreted as (target, args, kwargs) or
1135 (target, args) or (target,) depending on its length. If it's a
1136 sequence of functions, the functions will be called without
1137 arguments.
1138 @return: A list of the values returned by the functions called.
1139 """
1140 threads = []
1141 for target in targets:
1142 if isinstance(target, tuple) or isinstance(target, list):
1143 t = Thread(*target)
1144 else:
1145 t = Thread(target)
1146 threads.append(t)
1147 t.start()
1148 return [t.join() for t in threads]
1149
1150
1151 class KvmLoggingConfig(logging_config.LoggingConfig): 981 class KvmLoggingConfig(logging_config.LoggingConfig):
1152 """ 982 """
1153 Used with the sole purpose of providing convenient logging setup 983 Used with the sole purpose of providing convenient logging setup
1154 for the KVM test auxiliary programs. 984 for the KVM test auxiliary programs.
1155 """ 985 """
1156 def configure_logging(self, results_dir=None, verbose=False): 986 def configure_logging(self, results_dir=None, verbose=False):
1157 super(KvmLoggingConfig, self).configure_logging(use_console=True, 987 super(KvmLoggingConfig, self).configure_logging(use_console=True,
1158 verbose=verbose) 988 verbose=verbose)
1159 989
1160 990
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 if tag and build: 1340 if tag and build:
1511 logging.info("Both tag and build parameters provided, ignoring tag " 1341 logging.info("Both tag and build parameters provided, ignoring tag "
1512 "parameter...") 1342 "parameter...")
1513 1343
1514 if not tag and not build: 1344 if not tag and not build:
1515 raise ValueError("Koji install selected but neither koji_tag " 1345 raise ValueError("Koji install selected but neither koji_tag "
1516 "nor koji_build parameters provided. Please " 1346 "nor koji_build parameters provided. Please "
1517 "provide an appropriate tag or build name.") 1347 "provide an appropriate tag or build name.")
1518 1348
1519 if not build: 1349 if not build:
1520 builds = self.session.listTagged(tag, latest=True, inherit=True, 1350 builds = self.session.listTagged(tag, latest=True,
1521 package=src_package) 1351 package=src_package)
1522 if not builds: 1352 if not builds:
1523 raise ValueError("Tag %s has no builds of %s" % (tag, 1353 raise ValueError("Tag %s has no builds of %s" % (tag,
1524 src_package)) 1354 src_package))
1525 info = builds[0] 1355 info = builds[0]
1526 else: 1356 else:
1527 info = self.session.getBuild(build) 1357 info = self.session.getBuild(build)
1528 1358
1529 if info is None: 1359 if info is None:
1530 raise ValueError('No such brew/koji build: %s' % build) 1360 raise ValueError('No such brew/koji build: %s' % build)
(...skipping 22 matching lines...) Expand all
1553 download = False 1383 download = False
1554 else: 1384 else:
1555 download = True 1385 download = True
1556 1386
1557 if download: 1387 if download:
1558 r = utils.get_file(url, 1388 r = utils.get_file(url,
1559 os.path.join(dst_dir, os.path.basename(url))) 1389 os.path.join(dst_dir, os.path.basename(url)))
1560 rpm_paths.append(r) 1390 rpm_paths.append(r)
1561 1391
1562 return rpm_paths 1392 return rpm_paths
1563
1564
1565 def umount(src, mount_point, type):
1566 """
1567 Umount the src mounted in mount_point.
1568
1569 @src: mount source
1570 @mount_point: mount point
1571 @type: file system type
1572 """
1573
1574 mount_string = "%s %s %s" % (src, mount_point, type)
1575 if mount_string in file("/etc/mtab").read():
1576 umount_cmd = "umount %s" % mount_point
1577 try:
1578 utils.system(umount_cmd)
1579 return True
1580 except error.CmdError:
1581 return False
1582 else:
1583 logging.debug("%s is not mounted under %s" % (src, mount_point))
1584 return True
1585
1586
1587 def mount(src, mount_point, type, perm="rw"):
1588 """
1589 Mount the src into mount_point of the host.
1590
1591 @src: mount source
1592 @mount_point: mount point
1593 @type: file system type
1594 @perm: mount premission
1595 """
1596 umount(src, mount_point, type)
1597 mount_string = "%s %s %s %s" % (src, mount_point, type, perm)
1598
1599 if mount_string in file("/etc/mtab").read():
1600 logging.debug("%s is already mounted in %s with %s" %
1601 (src, mount_point, perm))
1602 return True
1603
1604 mount_cmd = "mount -t %s %s %s -o %s" % (type, src, mount_point, perm)
1605 try:
1606 utils.system(mount_cmd)
1607 except error.CmdError:
1608 return False
1609
1610 logging.debug("Verify the mount through /etc/mtab")
1611 if mount_string in file("/etc/mtab").read():
1612 logging.debug("%s is successfully mounted" % src)
1613 return True
1614 else:
1615 logging.error("Can't find mounted NFS share - /etc/mtab contents \n%s" %
1616 file("/etc/mtab").read())
1617 return False
OLDNEW
« no previous file with comments | « client/tests/kvm/kvm_test_utils.py ('k') | client/tests/kvm/kvm_vm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698