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

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

Issue 6246035: Merge remote branch 'cros/upstream' into master (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/autotest.git@master
Patch Set: patch Created 9 years, 10 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
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 """ 2 """
3 KVM configuration file utility functions. 3 KVM configuration file utility functions.
4 4
5 @copyright: Red Hat 2008-2010 5 @copyright: Red Hat 2008-2010
6 """ 6 """
7 7
8 import logging, re, os, sys, optparse, array, traceback, cPickle 8 import logging, re, os, sys, optparse, array, traceback, cPickle
9 import common 9 import common
10 import kvm_utils 10 import kvm_utils
11 from autotest_lib.client.common_lib import error 11 from autotest_lib.client.common_lib import error
12 from autotest_lib.client.common_lib import logging_config, logging_manager 12 from autotest_lib.client.common_lib import logging_manager
13 13
14 14
15 class config: 15 class config:
16 """ 16 """
17 Parse an input file or string that follows the KVM Test Config File format 17 Parse an input file or string that follows the KVM Test Config File format
18 and generate a list of dicts that will be later used as configuration 18 and generate a list of dicts that will be later used as configuration
19 parameters by the KVM tests. 19 parameters by the KVM tests.
20 20
21 @see: http://www.linux-kvm.org/page/KVM-Autotest/Test_Config_File 21 @see: http://www.linux-kvm.org/page/KVM-Autotest/Test_Config_File
22 """ 22 """
23 23
24 def __init__(self, filename=None, debug=True): 24 def __init__(self, filename=None, debug=True):
25 """ 25 """
26 Initialize the list and optionally parse a file. 26 Initialize the list and optionally parse a file.
27 27
28 @param filename: Path of the file that will be taken. 28 @param filename: Path of the file that will be taken.
29 @param debug: Whether to turn on debugging output. 29 @param debug: Whether to turn on debugging output.
30 """ 30 """
31 self.list = [array.array("H", [4, 4, 4, 4])] 31 self.list = [array.array("H", [4, 4, 4, 4])]
32 self.object_cache = [] 32 self.object_cache = []
33 self.object_cache_indices = {} 33 self.object_cache_indices = {}
34 self.regex_cache = {} 34 self.regex_cache = {}
35 self.filename = filename
36 self.debug = debug 35 self.debug = debug
37 if filename: 36 if filename:
38 self.parse_file(filename) 37 self.parse_file(filename)
39 38
40 39
41 def parse_file(self, filename): 40 def parse_file(self, filename):
42 """ 41 """
43 Parse file. If it doesn't exist, raise an IOError. 42 Parse file. If it doesn't exist, raise an IOError.
44 43
45 @param filename: Path of the configuration file. 44 @param filename: Path of the configuration file.
46 """ 45 """
47 if not os.path.exists(filename): 46 if not os.path.exists(filename):
48 raise IOError("File %s not found" % filename) 47 raise IOError("File %s not found" % filename)
49 self.filename = filename
50 str = open(filename).read() 48 str = open(filename).read()
51 self.list = self.parse(configreader(str), self.list) 49 self.list = self.parse(configreader(filename, str), self.list)
52 50
53 51
54 def parse_string(self, str): 52 def parse_string(self, str):
55 """ 53 """
56 Parse a string. 54 Parse a string.
57 55
58 @param str: String to parse. 56 @param str: String to parse.
59 """ 57 """
60 self.list = self.parse(configreader(str), self.list) 58 self.list = self.parse(configreader('<string>', str, real_file=False), s elf.list)
61 59
62 60
63 def fork_and_parse(self, filename=None, str=None): 61 def fork_and_parse(self, filename=None, str=None):
64 """ 62 """
65 Parse a file and/or a string in a separate process to save memory. 63 Parse a file and/or a string in a separate process to save memory.
66 64
67 Python likes to keep memory to itself even after the objects occupying 65 Python likes to keep memory to itself even after the objects occupying
68 it have been destroyed. If during a call to parse_file() or 66 it have been destroyed. If during a call to parse_file() or
69 parse_string() a lot of memory is used, it can only be freed by 67 parse_string() a lot of memory is used, it can only be freed by
70 terminating the process. This function works around the problem by 68 terminating the process. This function works around the problem by
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 "context, %d remain)" % 288 "context, %d remain)" %
291 (len_list, len(list))) 289 (len_list, len(list)))
292 continue 290 continue
293 291
294 # Parse 'variants' 292 # Parse 'variants'
295 if line == "variants:": 293 if line == "variants:":
296 # 'variants' not allowed in restricted mode 294 # 'variants' not allowed in restricted mode
297 # (inside an exception or inside subvariants) 295 # (inside an exception or inside subvariants)
298 if restricted: 296 if restricted:
299 e_msg = "Using variants in this context is not allowed" 297 e_msg = "Using variants in this context is not allowed"
300 raise error.AutotestError(e_msg) 298 cr.raise_error(e_msg)
301 if self.debug and not restricted: 299 if self.debug and not restricted:
302 _debug_print(indented_line, 300 _debug_print(indented_line,
303 "Entering variants block (%d dicts in " 301 "Entering variants block (%d dicts in "
304 "current context)" % len_list) 302 "current context)" % len_list)
305 list = self.parse_variants(cr, list, subvariants=False, 303 list = self.parse_variants(cr, list, subvariants=False,
306 prev_indent=indent) 304 prev_indent=indent)
307 continue 305 continue
308 306
309 # Parse 'subvariants' (the block is parsed for each dict 307 # Parse 'subvariants' (the block is parsed for each dict
310 # separately) 308 # separately)
(...skipping 19 matching lines...) Expand all
330 prev_indent=indent) 328 prev_indent=indent)
331 list = new_list 329 list = new_list
332 continue 330 continue
333 331
334 # Parse 'include' statements 332 # Parse 'include' statements
335 if words[0] == "include": 333 if words[0] == "include":
336 if len(words) <= 1: 334 if len(words) <= 1:
337 continue 335 continue
338 if self.debug and not restricted: 336 if self.debug and not restricted:
339 _debug_print(indented_line, "Entering file %s" % words[1]) 337 _debug_print(indented_line, "Entering file %s" % words[1])
340 if self.filename: 338
341 filename = os.path.join(os.path.dirname(self.filename), 339 cur_filename = cr.real_filename()
342 words[1]) 340 if cur_filename is None:
343 if os.path.exists(filename): 341 cr.raise_error("'include' is valid only when parsing a file" )
344 str = open(filename).read() 342
345 list = self.parse(configreader(str), list, restricted) 343 filename = os.path.join(os.path.dirname(cur_filename),
346 if self.debug and not restricted: 344 words[1])
347 _debug_print("", "Leaving file %s" % words[1]) 345 if not os.path.exists(filename):
348 else: 346 cr.raise_error("Cannot include %s -- file not found" % (file name))
349 logging.warning("Cannot include %s -- file not found", 347
350 filename) 348 str = open(filename).read()
351 else: 349 list = self.parse(configreader(filename, str), list, restricted)
352 logging.warning("Cannot include %s because no file is " 350 if self.debug and not restricted:
353 "currently open", words[1]) 351 _debug_print("", "Leaving file %s" % words[1])
352
354 continue 353 continue
355 354
356 # Parse multi-line exceptions 355 # Parse multi-line exceptions
357 # (the block is parsed for each dict separately) 356 # (the block is parsed for each dict separately)
358 if line.endswith(":"): 357 if line.endswith(":"):
359 if self.debug and not restricted: 358 if self.debug and not restricted:
360 _debug_print(indented_line, 359 _debug_print(indented_line,
361 "Entering multi-line exception block " 360 "Entering multi-line exception block "
362 "(%d dicts in current context outside " 361 "(%d dicts in current context outside "
363 "exception)" % len_list) 362 "exception)" % len_list)
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 531
533 # configreader 532 # configreader
534 533
535 class configreader: 534 class configreader:
536 """ 535 """
537 Preprocess an input string and provide file-like services. 536 Preprocess an input string and provide file-like services.
538 This is intended as a replacement for the file and StringIO classes, 537 This is intended as a replacement for the file and StringIO classes,
539 whose readline() and/or seek() methods seem to be slow. 538 whose readline() and/or seek() methods seem to be slow.
540 """ 539 """
541 540
542 def __init__(self, str): 541 def __init__(self, filename, str, real_file=True):
543 """ 542 """
544 Initialize the reader. 543 Initialize the reader.
545 544
545 @param filename: the filename we're parsing
546 @param str: The string to parse. 546 @param str: The string to parse.
547 @param real_file: Indicates if filename represents a real file. Defaults to True.
547 """ 548 """
549 self.filename = filename
550 self.is_real_file = real_file
548 self.line_index = 0 551 self.line_index = 0
549 self.lines = [] 552 self.lines = []
550 for line in str.splitlines(): 553 self.real_number = []
554 for num, line in enumerate(str.splitlines()):
551 line = line.rstrip().expandtabs() 555 line = line.rstrip().expandtabs()
552 stripped_line = line.strip() 556 stripped_line = line.strip()
553 indent = len(line) - len(stripped_line) 557 indent = len(line) - len(stripped_line)
554 if (not stripped_line 558 if (not stripped_line
555 or stripped_line.startswith("#") 559 or stripped_line.startswith("#")
556 or stripped_line.startswith("//")): 560 or stripped_line.startswith("//")):
557 continue 561 continue
558 self.lines.append((line, stripped_line, indent)) 562 self.lines.append((line, stripped_line, indent))
563 self.real_number.append(num + 1)
559 564
560 565
566 def real_filename(self):
567 """Returns the filename we're reading, in case it is a real file
568
569 @returns the filename we are parsing, or None in case we're not parsing a real file
570 """
571 if self.is_real_file:
572 return self.filename
573
561 def get_next_line(self): 574 def get_next_line(self):
562 """ 575 """
563 Get the next non-empty, non-comment line in the string. 576 Get the next non-empty, non-comment line in the string.
564 577
565 @param file: File like object. 578 @param file: File like object.
566 @return: (line, stripped_line, indent), where indent is the line's 579 @return: (line, stripped_line, indent), where indent is the line's
567 indent level or -1 if no line is available. 580 indent level or -1 if no line is available.
568 """ 581 """
569 try: 582 try:
570 if self.line_index < len(self.lines): 583 if self.line_index < len(self.lines):
(...skipping 10 matching lines...) Expand all
581 """ 594 """
582 return self.line_index 595 return self.line_index
583 596
584 597
585 def seek(self, index): 598 def seek(self, index):
586 """ 599 """
587 Set the current line index. 600 Set the current line index.
588 """ 601 """
589 self.line_index = index 602 self.line_index = index
590 603
604 def raise_error(self, msg):
605 """Raise an error related to the last line returned by get_next_line()
606 """
607 if self.line_index == 0: # nothing was read. shouldn't happen, but...
608 line_id = 'BEGIN'
609 elif self.line_index >= len(self.lines): # past EOF
610 line_id = 'EOF'
611 else:
612 # line_index is the _next_ line. get the previous one
613 line_id = str(self.real_number[self.line_index-1])
614 raise error.AutotestError("%s:%s: %s" % (self.filename, line_id, msg))
615
591 616
592 # Array structure: 617 # Array structure:
593 # ---------------- 618 # ----------------
594 # The first 4 elements contain the indices of the 4 segments. 619 # The first 4 elements contain the indices of the 4 segments.
595 # a[0] -- Index of beginning of 'name' segment (always 4). 620 # a[0] -- Index of beginning of 'name' segment (always 4).
596 # a[1] -- Index of beginning of 'shortname' segment. 621 # a[1] -- Index of beginning of 'shortname' segment.
597 # a[2] -- Index of beginning of 'depend' segment. 622 # a[2] -- Index of beginning of 'depend' segment.
598 # a[3] -- Index of beginning of 'content' segment. 623 # a[3] -- Index of beginning of 'content' segment.
599 # The next elements in the array comprise the aforementioned segments: 624 # The next elements in the array comprise the aforementioned segments:
600 # The 'name' segment begins with a[a[0]] and ends with a[a[1]-1]. 625 # The 'name' segment begins with a[a[0]] and ends with a[a[1]-1].
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 700
676 701
677 if __name__ == "__main__": 702 if __name__ == "__main__":
678 parser = optparse.OptionParser("usage: %prog [options] [filename]") 703 parser = optparse.OptionParser("usage: %prog [options] [filename]")
679 parser.add_option('--verbose', dest="debug", action='store_true', 704 parser.add_option('--verbose', dest="debug", action='store_true',
680 help='include debug messages in console output') 705 help='include debug messages in console output')
681 706
682 options, args = parser.parse_args() 707 options, args = parser.parse_args()
683 debug = options.debug 708 debug = options.debug
684 if args: 709 if args:
685 filename = args[0] 710 filenames = args
686 else: 711 else:
687 filename = os.path.join(os.path.dirname(sys.argv[0]), "tests.cfg") 712 filenames = [os.path.join(os.path.dirname(sys.argv[0]), "tests.cfg")]
688 713
689 # Here we configure the stand alone program to use the autotest 714 # Here we configure the stand alone program to use the autotest
690 # logging system. 715 # logging system.
691 logging_manager.configure_logging(kvm_utils.KvmLoggingConfig(), 716 logging_manager.configure_logging(kvm_utils.KvmLoggingConfig(),
692 verbose=debug) 717 verbose=debug)
693 dicts = config(filename, debug=debug).get_generator() 718 cfg = config(debug=debug)
719 for fn in filenames:
720 cfg.parse_file(fn)
721 dicts = cfg.get_generator()
694 for i, dict in enumerate(dicts): 722 for i, dict in enumerate(dicts):
695 logging.info("Dictionary #%d:", i) 723 print "Dictionary #%d:" % (i)
696 keys = dict.keys() 724 keys = dict.keys()
697 keys.sort() 725 keys.sort()
698 for key in keys: 726 for key in keys:
699 logging.info(" %s = %s", key, dict[key]) 727 print " %s = %s" % (key, dict[key])
OLDNEW
« cli/job.py ('K') | « client/tests/kvm/kvm.py ('k') | client/tests/kvm/kvm_monitor.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698