OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """A helper module to run Legion multi-machine tests. | |
7 | |
8 Example usage with 1 task machine: | |
9 $ testing/legion/tools/legion.py run \ | |
10 --controller-isolated out/Release/example_test_controller.isolated \ | |
11 --dimension os Ubuntu-14.04 \ | |
12 --task-name test-task-name \ | |
13 --task task_machine out/Release/example_task_machine.isolated | |
14 | |
15 Example usage with 2 task machines with the same isolated file: | |
16 $ testing/legion/tools/legion.py run \ | |
17 --controller-isolated out/Release/example_test_controller.isolated \ | |
18 --dimension os Ubuntu-14.04 \ | |
19 --task-name test-task-name \ | |
20 --task task_machine_1 out/Release/example_task_machine.isolated \ | |
21 --task task_machine_2 out/Release/example_task_machine.isolated | |
22 | |
23 Example usage with 2 task machines with different isolated file: | |
24 $ testing/legion/tools/legion.py run \ | |
25 --controller-isolated out/Release/example_test_controller.isolated \ | |
26 --dimension os Ubuntu-14.04 \ | |
27 --task-name test-task-name \ | |
28 --task task_machine_1 out/Release/example_task_machine_1.isolated \ | |
29 --task task_machine_2 out/Release/example_task_machine_2.isolated | |
30 """ | |
31 | |
32 import argparse | |
33 import logging | |
34 import os | |
35 import subprocess | |
36 import sys | |
37 | |
38 | |
39 THIS_DIR = os.path.split(__file__)[0] | |
40 SWARMING_DIR = os.path.join(THIS_DIR, '..', '..', '..', 'tools', | |
41 'swarming_client') | |
42 ISOLATE_PY = os.path.join(SWARMING_DIR, 'isolate.py') | |
43 SWARMING_PY = os.path.join(SWARMING_DIR, 'swarming.py') | |
44 LOGGING_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR'] | |
45 | |
46 | |
47 class Error(Exception): | |
48 pass | |
49 | |
50 | |
51 def GetArgs(): | |
52 parser = argparse.ArgumentParser(description=__doc__) | |
53 parser.add_argument('action', choices=['run', 'trigger'], | |
54 help='The swarming action to perform.') | |
55 parser.add_argument('-f', '--format-only', action='store_true', | |
56 help='If true the .isolated files are archived but ' | |
57 'swarming is not called, only the command line is built.') | |
58 parser.add_argument('--controller-isolated', required=True, | |
59 help='The isolated file for the test controller.') | |
60 parser.add_argument('--isolate-server', help='Optional. The isolated server ' | |
61 'to use.') | |
62 parser.add_argument('--swarming-server', help='Optional. The swarming server ' | |
63 'to use.') | |
64 parser.add_argument('--task-name', help='Optional. The swarming task name ' | |
65 'to use.') | |
66 parser.add_argument('--dimension', action='append', dest='dimensions', | |
67 nargs=2, default=[], help='Dimensions to pass to ' | |
68 'swarming.py. This is in the form of --dimension key ' | |
69 'value. The minimum required is --dimension os <OS>') | |
70 parser.add_argument('--task', action='append', dest='tasks', | |
71 nargs=2, default=[], help='List of task names used in ' | |
72 'the test controller. This is in the form of --task name ' | |
73 '.isolated and is passed to the controller as --name ' | |
74 '<ISOLATED HASH>.') | |
75 parser.add_argument('--controller-var', action='append', | |
76 dest='controller_vars', nargs=2, default=[], | |
77 help='Command line vars to pass to the controller. These ' | |
78 'are in the form of --controller-var name value and are ' | |
79 'passed to the controller as --name value.') | |
80 parser.add_argument('-v', '--verbosity', default=0, action='count') | |
81 return parser.parse_args() | |
82 | |
83 | |
84 def RunCommand(cmd, stream_stdout=False): | |
85 """Runs the command line and streams stdout if requested.""" | |
86 kwargs = { | |
87 'args': cmd, | |
88 'stderr': subprocess.PIPE, | |
89 } | |
90 if not stream_stdout: | |
91 kwargs['stdout'] = subprocess.PIPE | |
92 | |
93 p = subprocess.Popen(**kwargs) | |
94 stdout, stderr = p.communicate() | |
95 if p.returncode: | |
96 raise Error(stderr) | |
97 if not stream_stdout: | |
98 logging.debug(stdout) | |
99 return stdout | |
100 | |
101 | |
102 def Archive(isolated, isolate_server=None): | |
103 """Calls isolate.py archive with the given args.""" | |
104 cmd = [ | |
105 sys.executable, | |
106 ISOLATE_PY, | |
107 'archive', | |
108 '--isolated', isolated, | |
109 ] | |
110 if isolate_server: | |
111 cmd.extend(['--isolate-server', isolate_server]) | |
112 print ' '.join(cmd) | |
113 return RunCommand(cmd).split()[0] # The isolated hash | |
114 | |
115 | |
116 def GetSwarmingCommandLine(args): | |
117 """Builds and returns the command line for swarming.py run|trigger.""" | |
118 cmd = [ | |
119 sys.executable, | |
120 SWARMING_PY, | |
121 args.action, | |
122 args.controller_isolated | |
M-A Ruel
2015/03/16 17:49:42
add trailing comma
Mike Meade
2015/03/16 18:00:05
Done.
| |
123 ] | |
124 if args.isolate_server: | |
125 cmd.extend(['--isolate-server', args.isolate_server]) | |
126 if args.swarming_server: | |
127 cmd.extend(['--swarming', args.swarming_server]) | |
128 if args.task_name: | |
129 cmd.extend(['--task-name', args.task_name]) | |
130 # swarming.py dimensions | |
131 for name, value in args.dimensions: | |
132 cmd.extend(['--dimension', name, value]) | |
133 | |
134 cmd.append('--') | |
135 | |
136 # Task name/hash values | |
137 for name, isolated in args.tasks: | |
138 cmd.extend(['--' + name, Archive(isolated, args.isolate_server)]) | |
139 # Test controller args | |
140 for name, value in args.controller_vars: | |
141 cmd.extend(['--' + name, value]) | |
142 print ' '.join(cmd) | |
143 return cmd | |
144 | |
145 | |
146 def main(): | |
147 args = GetArgs() | |
148 logging.basicConfig( | |
149 format='%(asctime)s %(filename)s:%(lineno)s %(levelname)s] %(message)s', | |
150 datefmt='%H:%M:%S', | |
151 level=LOGGING_LEVELS[len(LOGGING_LEVELS)-args.verbosity-1]) | |
152 cmd = GetSwarmingCommandLine(args) | |
153 if not args.format_only: | |
154 RunCommand(cmd, True) | |
155 return 0 | |
156 | |
157 | |
158 if __name__ == '__main__': | |
159 sys.exit(main()) | |
OLD | NEW |