Merge lp:~milo/lava-tool/lava-169 into lp:~linaro-validation/lava-tool/trunk
- lava-169
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 188 |
Proposed branch: | lp:~milo/lava-tool/lava-169 |
Merge into: | lp:~linaro-validation/lava-tool/trunk |
Prerequisite: | lp:~milo/lava-tool/lava-165 |
Diff against target: |
1110 lines (+461/-129) 21 files modified
entry_points.ini (+9/-0) lava/commands.py (+34/-47) lava/config.py (+13/-3) lava/device/__init__.py (+7/-3) lava/device/templates.py (+12/-0) lava/helper/command.py (+80/-16) lava/job/__init__.py (+12/-0) lava/job/commands.py (+21/-0) lava/job/templates.py (+6/-6) lava/job/tests/test_commands.py (+5/-4) lava/parameter.py (+0/-6) lava/script/__init__.py (+51/-0) lava/script/commands.py (+115/-0) lava/testdef/__init__.py (+24/-2) lava/testdef/commands.py (+40/-8) lava/testdef/templates.py (+4/-27) lava/testdef/tests/test_commands.py (+3/-3) lava/tests/test_commands.py (+0/-1) lava/tests/test_config.py (+9/-0) lava/tests/test_parameter.py (+2/-1) lava_tool/utils.py (+14/-2) |
To merge this branch: | bzr merge lp:~milo/lava-tool/lava-169 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Antonio Terceiro | Approve | ||
Linaro Validation Team | Pending | ||
Review via email:
|
Commit message
Description of the change
This is the final step in completing card LAVA-15.
Here there is the "status" command that polls a LAVA server and prints information about the provided job id.
The command can be invoked as:
lava status [ID]
lava job status [ID]
The latter is the actual command and the former just calls it.
If ID is not provided, it will read the stored job IDs from the .lavaconfig file, and ask the user which job to choose.
- 412. By Milo Casagrande
-
Added test for public Config method.
- 413. By Milo Casagrande
-
Fixed missing argument in method call.
- 414. By Milo Casagrande
-
Removed a job id from the config file once it is not running anymore.
- 415. By Milo Casagrande
-
Fixed logic when removing job ids.
- 416. By Milo Casagrande
-
Merged from parent branch.
- 417. By Milo Casagrande
-
Merged from parent branch.
- 418. By Milo Casagrande
-
Fixed logic for URL creation.
- 419. By Milo Casagrande
-
Fixed problem with value read from config and not deserialized.
- 420. By Milo Casagrande
-
Merged from parent.
- 421. By Milo Casagrande
-
Fixed test.
- 422. By Milo Casagrande
-
Merged from parent branch.
- 423. By Milo Casagrande
-
Merged from parent branch.
- 424. By Milo Casagrande
-
Merged from parent branch, fixed conflicts.
- 425. By Milo Casagrande
-
Merged from parent brach.
- 426. By Milo Casagrande
-
Merged from parent branch.
- 427. By Milo Casagrande
-
Merged from parent branch.
- 428. By Milo Casagrande
-
Merged from parent.

Milo Casagrande (milo) wrote : | # |
Hi Antonio,
I updated the code.
I also pushed here the "script" commands. Please, take a look at them.
The big part of the refactoring happened on the lava-165 merge.
On Wed, Jul 24, 2013 at 10:46 PM, Antonio Terceiro
<email address hidden> wrote:
>
> I'm not sure about the first form. `lava status` might be too generic for
> people to memorize that it should be use to get status of jobs. I think we will
> be able to do a better UI review after we get all the code merged in though.
Indeed. Also, it would be better to do it with someone that will
actually use the tool.
>> === modified file 'entry_points.ini'
>> --- entry_points.ini 2013-07-24 14:41:29 +0000
>> +++ entry_points.ini 2013-07-24 14:41:29 +0000
>> @@ -13,6 +13,7 @@
>> init = lava.commands:init
>> submit = lava.commands:
>> run = lava.commands:run
>> +status = lava.commands:
>
> you can just reference lava.job.
> separate command.
>
> BTW this also applies to a similar comment I did in the previous MP, about
> cascading commands: if the arguments are the same, you can just point to the
> original command from another scope in entry_points.ini and you don't have to
> wrap one command inside another
There is actually only the status one, the run and submit are all a
little bit different, in particular when you start from a testdef or a
script file.
> these constants are used in very few places so I think it's better to just use
> the literals directly.
Cleared them out.
> I would use default=None instead, since that -1 is not even a proper number.
Fixed.
> instead of printing the Bundle SHA1 hash, it would be more useful to provide a
> URL to that bundle in the dashboard. Even more useful would be to present the
> results of the tests ... I don't know exactly yet how to do any of those,
> though - presenting the URL should be a lot easier in the short term.
> maybe we could provide a way of listing the latest N jobs submitted by the
> user, together with their results. This would probably require some work on the
> server API side.
I actually removed this from both lava-165 and lava-169.
I want to address that with another merge proposal, but after
everything has been merged.
Will file a bug to keep track of it, and fix the config/cache
"problem" via pyxdg once this code is landed.
Also for the "bundle" one: I prefer to not fix it now, but keep track
of it with a bug. It is tied to the config/cache "problem" since we
need to store information of that job to make the URL (we need to keep
track of the server URL, the stream, and those might change even from
job to job).
--
Milo Casagrande | Automation Engineer
Linaro.org <www.linaro.org> │ Open source software for ARM SoCs
- 429. By Milo Casagrande
-
Merged from parent.
- 430. By Milo Casagrande
-
Added script commands, completed testdef ones.
* Refactored and fixes some of the other methods.
- 431. By Milo Casagrande
-
Added missing entry point commands.
- 432. By Milo Casagrande
-
Removed TODO, unused import.
- 433. By Milo Casagrande
-
Fixed string.
- 434. By Milo Casagrande
-
Fixed the status command.
- 435. By Milo Casagrande
-
Fixed script entry point.
- 436. By Milo Casagrande
-
Fixed import.
- 437. By Milo Casagrande
-
Fixed another import.
- 438. By Milo Casagrande
-
Fixed template.
- 439. By Milo Casagrande
-
Fixed error: used def instead of class.
- 440. By Milo Casagrande
-
PEP8 and pylint fixes.
- 441. By Milo Casagrande
-
Added qemu device type.
- 442. By Milo Casagrande
-
Completed script and testdef run and submit commands.
* Refactored some code.
- 443. By Milo Casagrande
-
Removed refactored method, added missing edit_file call.
- 444. By Milo Casagrande
-
Fixed commands, added missing functionalities.
- 445. By Milo Casagrande
-
Fixed method call.
- 446. By Milo Casagrande
-
Fixed problem with config saving.
- 447. By Milo Casagrande
-
Fixed check on non existing files.
- 448. By Milo Casagrande
-
Fixed error message.

Antonio Terceiro (terceiro) wrote : | # |
The changes you did seem nice. I don't have any specific remarks.
Let's go ahead and merge this, it's getting too big. Then we
start iterating on the code with all the features in.
review approve
Preview Diff
1 | === modified file 'entry_points.ini' |
2 | --- entry_points.ini 2013-07-26 14:14:25 +0000 |
3 | +++ entry_points.ini 2013-07-26 14:14:25 +0000 |
4 | @@ -13,7 +13,9 @@ |
5 | init = lava.commands:init |
6 | submit = lava.commands:submit |
7 | run = lava.commands:run |
8 | +status = lava.job.commands:status |
9 | update = lava.commands:update |
10 | +script = lava.script.commands:script |
11 | |
12 | [lava_tool.commands] |
13 | help = lava.tool.commands.help:help |
14 | @@ -77,6 +79,7 @@ |
15 | [lava.job.commands] |
16 | new = lava.job.commands:new |
17 | submit = lava.job.commands:submit |
18 | +status = lava.job.commands:status |
19 | run = lava.job.commands:run |
20 | |
21 | [lava.device.commands] |
22 | @@ -86,3 +89,9 @@ |
23 | |
24 | [lava.testdef.commands] |
25 | new = lava.testdef.commands:new |
26 | +run = lava.testdef.commands:run |
27 | +submit = lava.testdef.commands:submit |
28 | + |
29 | +[lava.script.commands] |
30 | +run = lava.script.commands:run |
31 | +submit = lava.script.commands:submit |
32 | |
33 | === modified file 'lava/commands.py' |
34 | --- lava/commands.py 2013-07-26 14:14:25 +0000 |
35 | +++ lava/commands.py 2013-07-26 14:14:25 +0000 |
36 | @@ -46,7 +46,6 @@ |
37 | import copy |
38 | import json |
39 | import os |
40 | -import stat |
41 | import sys |
42 | |
43 | from lava.helper.command import BaseCommand |
44 | @@ -63,16 +62,16 @@ |
45 | from lava.parameter import ( |
46 | Parameter, |
47 | ) |
48 | -from lava.testdef.templates import ( |
49 | - DEFAULT_TESTDEF_FILE, |
50 | - DEFAULT_TESTDEF_SCRIPT, |
51 | - DEFAULT_TESTDEF_SCRIPT_CONTENT, |
52 | +from lava.testdef import ( |
53 | + DEFAULT_TESTDEF_FILENAME, |
54 | ) |
55 | from lava.tool.errors import CommandError |
56 | from lava_tool.utils import ( |
57 | + base64_encode, |
58 | + create_dir, |
59 | + create_tar, |
60 | edit_file, |
61 | retrieve_file, |
62 | - create_dir, |
63 | write_file, |
64 | ) |
65 | |
66 | @@ -110,15 +109,17 @@ |
67 | "file.".format(self.args.DIR)) |
68 | |
69 | create_dir(full_path) |
70 | - |
71 | data = self._update_data() |
72 | |
73 | + # Create the directory that will contain the test definition and |
74 | + # shell script. |
75 | test_path = create_dir(full_path, TESTS_DIR) |
76 | - # TODO |
77 | - self._create_script(test_path) |
78 | + shell_script = self.create_shell_script(test_path) |
79 | + # Let the user modify the file. |
80 | + edit_file(shell_script) |
81 | |
82 | testdef_file = self.create_test_definition( |
83 | - os.path.join(test_path, DEFAULT_TESTDEF_FILE)) |
84 | + os.path.join(test_path, DEFAULT_TESTDEF_FILENAME)) |
85 | |
86 | job = data[JOBFILE_ID] |
87 | self.create_tar_repo_job( |
88 | @@ -137,25 +138,6 @@ |
89 | |
90 | return data |
91 | |
92 | - def _create_script(self, test_path): |
93 | - # This is the default script file as defined in the testdef template. |
94 | - default_script = os.path.join(test_path, DEFAULT_TESTDEF_SCRIPT) |
95 | - |
96 | - if not os.path.isfile(default_script): |
97 | - # We do not have the default testdef script. Create it, but |
98 | - # remind the user to update it. |
99 | - print >> sys.stdout, ("\nCreating default test script " |
100 | - "'{0}'.".format(DEFAULT_TESTDEF_SCRIPT)) |
101 | - |
102 | - write_file(default_script, DEFAULT_TESTDEF_SCRIPT_CONTENT) |
103 | - |
104 | - # Prompt the user to write the script file. |
105 | - edit_file(default_script) |
106 | - |
107 | - # Make sure the script is executable. |
108 | - os.chmod(default_script, |
109 | - stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH) |
110 | - |
111 | |
112 | class run(BaseCommand): |
113 | """Runs a job on the local dispatcher.""" |
114 | @@ -194,7 +176,7 @@ |
115 | |
116 | def invoke(self): |
117 | full_path = os.path.abspath(self.args.JOB) |
118 | - job_file = self.retrieve_file(full_path, JOB_FILE_EXTENSIONS) |
119 | + job_file = retrieve_file(full_path, JOB_FILE_EXTENSIONS) |
120 | |
121 | super(submit, self).submit(job_file) |
122 | |
123 | @@ -219,22 +201,27 @@ |
124 | tests_dir = os.path.join(job_dir, TESTS_DIR) |
125 | |
126 | if os.path.isdir(tests_dir): |
127 | - # TODO |
128 | - encoded_tests = None |
129 | - |
130 | - json_data = None |
131 | - with open(job_file, "r") as json_file: |
132 | - try: |
133 | - json_data = json.load(json_file) |
134 | - set_value( |
135 | - json_data, LAVA_TEST_SHELL_TAR_REPO_KEY, encoded_tests) |
136 | - except Exception: |
137 | - raise CommandError("Cannot read job file '{0}'.".format( |
138 | - job_file)) |
139 | - |
140 | - content = json.dumps(json_data, indent=4) |
141 | - write_file(job_file, content) |
142 | - |
143 | - print >> sys.stdout, "Job definition updated." |
144 | + tar_repo = None |
145 | + try: |
146 | + tar_repo = create_tar(tests_dir) |
147 | + encoded_tests = base64_encode(tar_repo) |
148 | + |
149 | + json_data = None |
150 | + with open(job_file, "r") as json_file: |
151 | + try: |
152 | + json_data = json.load(json_file) |
153 | + set_value(json_data, LAVA_TEST_SHELL_TAR_REPO_KEY, |
154 | + encoded_tests) |
155 | + except Exception: |
156 | + raise CommandError("Cannot read job file " |
157 | + "'{0}'.".format(job_file)) |
158 | + |
159 | + content = json.dumps(json_data, indent=4) |
160 | + write_file(job_file, content) |
161 | + |
162 | + print >> sys.stdout, "Job definition updated." |
163 | + finally: |
164 | + if tar_repo and os.path.isfile(tar_repo): |
165 | + os.unlink(tar_repo) |
166 | else: |
167 | raise CommandError("Cannot find tests directory.") |
168 | |
169 | === modified file 'lava/config.py' |
170 | --- lava/config.py 2013-07-26 14:14:25 +0000 |
171 | +++ lava/config.py 2013-07-26 14:14:25 +0000 |
172 | @@ -33,7 +33,6 @@ |
173 | from lava.parameter import Parameter |
174 | from lava.tool.errors import CommandError |
175 | |
176 | - |
177 | __all__ = ['Config', 'InteractiveConfig'] |
178 | |
179 | # Store for function calls to be made at exit time. |
180 | @@ -55,6 +54,7 @@ |
181 | call() |
182 | atexit.register(_run_at_exit) |
183 | |
184 | + |
185 | class Config(object): |
186 | """A generic config object.""" |
187 | |
188 | @@ -119,6 +119,12 @@ |
189 | value = self._get_from_backend(parameter, section) |
190 | return value |
191 | |
192 | + def get_from_backend(self, parameter, section=None): |
193 | + """Gets a configuration parameter directly from the config file.""" |
194 | + if not section: |
195 | + section = self._calculate_config_section(parameter) |
196 | + return self._get_from_backend(parameter, section) |
197 | + |
198 | def _get_from_backend(self, parameter, section): |
199 | """Gets the parameter value from the config backend. |
200 | |
201 | @@ -200,8 +206,12 @@ |
202 | |
203 | def save(self): |
204 | """Saves the config to file.""" |
205 | - with open(self.config_file, "w") as write_file: |
206 | - self.config_backend.write(write_file) |
207 | + # Since we lazy load the config_backend property, this check is needed |
208 | + # when a user enters a wrong command or it will overwrite the 'config' |
209 | + # file with empty contents. |
210 | + if self._config_backend: |
211 | + with open(self.config_file, "w") as write_file: |
212 | + self.config_backend.write(write_file) |
213 | |
214 | |
215 | class InteractiveConfig(Config): |
216 | |
217 | === modified file 'lava/device/__init__.py' |
218 | --- lava/device/__init__.py 2013-07-26 14:14:25 +0000 |
219 | +++ lava/device/__init__.py 2013-07-26 14:14:25 +0000 |
220 | @@ -16,6 +16,8 @@ |
221 | # You should have received a copy of the GNU Lesser General Public License |
222 | # along with lava-tool. If not, see <http://www.gnu.org/licenses/>. |
223 | |
224 | +"""Device class.""" |
225 | + |
226 | import re |
227 | |
228 | from copy import deepcopy |
229 | @@ -46,9 +48,11 @@ |
230 | |
231 | |
232 | class Device(object): |
233 | + |
234 | """A generic device.""" |
235 | - def __init__(self, template, hostname=None): |
236 | - self.data = deepcopy(template) |
237 | + |
238 | + def __init__(self, data, hostname=None): |
239 | + self.data = deepcopy(data) |
240 | self.hostname = hostname |
241 | |
242 | def write(self, conf_file): |
243 | @@ -86,7 +90,7 @@ |
244 | :return A Device instance. |
245 | """ |
246 | instance = Device(DEFAULT_TEMPLATE, hostname=name) |
247 | - for known_dev, (matcher, dev_template) in KNOWN_DEVICES.iteritems(): |
248 | + for _, (matcher, dev_template) in KNOWN_DEVICES.iteritems(): |
249 | if matcher.match(name): |
250 | instance = Device(dev_template, hostname=name) |
251 | break |
252 | |
253 | === modified file 'lava/device/templates.py' |
254 | --- lava/device/templates.py 2013-07-26 14:14:25 +0000 |
255 | +++ lava/device/templates.py 2013-07-26 14:14:25 +0000 |
256 | @@ -55,6 +55,13 @@ |
257 | VEXPRESS_CONNECTION_COMMAND = copy(CONNECTION_COMMAND_PARMAETER) |
258 | VEXPRESS_CONNECTION_COMMAND.depends = VEXPRESS_DEVICE_TYPE |
259 | |
260 | +QEMU_DEVICE_TYPE = copy(DEVICE_TYPE_PARAMETER) |
261 | +QEMU_DEVICE_TYPE.value = "qemu" |
262 | +QEMU_DEVICE_TYPE.asked = True |
263 | + |
264 | +QEMU_CONNECTION_COMMAND = copy(CONNECTION_COMMAND_PARMAETER) |
265 | +QEMU_CONNECTION_COMMAND.depends = QEMU_DEVICE_TYPE |
266 | + |
267 | # Dictionary with templates of known devices. |
268 | KNOWN_TEMPLATES = { |
269 | 'panda': { |
270 | @@ -67,4 +74,9 @@ |
271 | 'device_type': VEXPRESS_DEVICE_TYPE, |
272 | 'connection_command': VEXPRESS_CONNECTION_COMMAND, |
273 | }, |
274 | + 'qemu': { |
275 | + 'hostname': HOSTNAME_PARAMETER, |
276 | + 'device_type': QEMU_DEVICE_TYPE, |
277 | + 'connection_command': QEMU_CONNECTION_COMMAND, |
278 | + } |
279 | } |
280 | |
281 | === modified file 'lava/helper/command.py' |
282 | --- lava/helper/command.py 2013-07-26 14:14:25 +0000 |
283 | +++ lava/helper/command.py 2013-07-26 14:14:25 +0000 |
284 | @@ -24,10 +24,25 @@ |
285 | |
286 | from lava.config import InteractiveConfig |
287 | from lava.helper.dispatcher import get_devices |
288 | +from lava.job import Job |
289 | +from lava.job.templates import ( |
290 | + LAVA_TEST_SHELL_TAR_REPO, |
291 | + LAVA_TEST_SHELL_TAR_REPO_KEY, |
292 | + LAVA_TEST_SHELL_TESDEF_KEY, |
293 | +) |
294 | from lava.parameter import ( |
295 | Parameter, |
296 | SingleChoiceParameter, |
297 | ) |
298 | +from lava.script import ( |
299 | + ShellScript, |
300 | + DEFAULT_TESTDEF_SCRIPT, |
301 | +) |
302 | +from lava.testdef import TestDefinition |
303 | +from lava.testdef.templates import ( |
304 | + TESTDEF_STEPS_KEY, |
305 | + TESTDEF_TEMPLATE, |
306 | +) |
307 | from lava.tool.command import Command |
308 | from lava.tool.errors import CommandError |
309 | from lava_tool.authtoken import ( |
310 | @@ -35,22 +50,13 @@ |
311 | KeyringAuthBackend |
312 | ) |
313 | from lava_tool.utils import ( |
314 | + base64_encode, |
315 | + create_tar, |
316 | has_command, |
317 | + to_list, |
318 | verify_and_create_url, |
319 | - create_tar, |
320 | - base64_encode, |
321 | -) |
322 | -from lava.job import Job |
323 | -from lava.job.templates import ( |
324 | - LAVA_TEST_SHELL_TAR_REPO, |
325 | - LAVA_TEST_SHELL_TAR_REPO_KEY, |
326 | - LAVA_TEST_SHELL_TESDEF_KEY, |
327 | ) |
328 | |
329 | -from lava.testdef import TestDefinition |
330 | -from lava.testdef.templates import ( |
331 | - TESTDEF_TEMPLATE, |
332 | -) |
333 | CONFIG = InteractiveConfig() |
334 | |
335 | |
336 | @@ -66,7 +72,7 @@ |
337 | @classmethod |
338 | def register_arguments(cls, parser): |
339 | super(BaseCommand, cls).register_arguments(parser) |
340 | - parser.add_argument("--non-interactive", |
341 | + parser.add_argument("--non-interactive", "-n", |
342 | action='store_false', |
343 | help=("Do not ask for input parameters.")) |
344 | |
345 | @@ -76,6 +82,8 @@ |
346 | It will ask the user the necessary parameters to establish the |
347 | connection. |
348 | """ |
349 | + print >> sys.stdout, "\nServer connection parameters:" |
350 | + |
351 | server_name_parameter = Parameter("server") |
352 | rpc_endpoint_parameter = Parameter("rpc_endpoint", |
353 | depends=server_name_parameter) |
354 | @@ -134,6 +142,26 @@ |
355 | raise CommandError("Job file '{0}' does not exists, or it is not " |
356 | "a file.".format(job_file)) |
357 | |
358 | + def status(self, job_id): |
359 | + """Retrieves the status of a LAVA job. |
360 | + |
361 | + :param job_id: The ID of the job to look up. |
362 | + """ |
363 | + job_id = str(job_id) |
364 | + |
365 | + try: |
366 | + server = self.authenticated_server() |
367 | + job_status = server.scheduler.job_status(job_id) |
368 | + |
369 | + status = job_status["job_status"].lower() |
370 | + bundle = job_status["bundle_sha1"] |
371 | + |
372 | + print >> sys.stdout, "\nJob id: {0}".format(job_id) |
373 | + print >> sys.stdout, "Status: {0}".format(status) |
374 | + print >> sys.stdout, "Bundle: {0}".format(bundle) |
375 | + except xmlrpclib.Fault, exc: |
376 | + raise CommandError(str(exc)) |
377 | + |
378 | def create_tar_repo_job(self, job_file, testdef_file, tar_content): |
379 | """Creates a job file based on the tar-repo template. |
380 | |
381 | @@ -144,6 +172,9 @@ |
382 | :param tar_content: What should go into the tarball repository. |
383 | :return The path of the job file created. |
384 | """ |
385 | + |
386 | + print >> sys.stdout, "\nCreating job file..." |
387 | + |
388 | try: |
389 | tar_repo = create_tar(tar_content) |
390 | |
391 | @@ -157,22 +188,55 @@ |
392 | |
393 | job_instance.write() |
394 | |
395 | + basename = os.path.basename(job_instance.file_name) |
396 | + print >> sys.stdout, ("\nCreated job file " |
397 | + "'{0}'.".format(basename)) |
398 | + |
399 | return job_instance.file_name |
400 | finally: |
401 | if os.path.isfile(tar_repo): |
402 | os.unlink(tar_repo) |
403 | |
404 | - def create_test_definition(self, testdef_file, template=TESTDEF_TEMPLATE): |
405 | + def create_test_definition(self, testdef_file, template=TESTDEF_TEMPLATE, |
406 | + steps=None): |
407 | """Creates a test definition YAML file. |
408 | |
409 | :param testdef_file: The file to create. |
410 | :return The path of the file created. |
411 | """ |
412 | + |
413 | + print >> sys.stdout, "\nCreating test definition file..." |
414 | + |
415 | testdef = TestDefinition(template, testdef_file) |
416 | + if steps: |
417 | + steps = to_list(steps) |
418 | + testdef.set(TESTDEF_STEPS_KEY, steps) |
419 | testdef.update(self.config) |
420 | testdef.write() |
421 | |
422 | - print >> sys.stdout, ("Create test definition " |
423 | - "'{0}'.".format(testdef.file_name)) |
424 | + basename = os.path.basename(testdef.file_name) |
425 | + print >> sys.stdout, ("\nCreated test definition " |
426 | + "'{0}'.".format(basename)) |
427 | |
428 | return testdef.file_name |
429 | + |
430 | + def create_shell_script(self, test_path, |
431 | + script_name=DEFAULT_TESTDEF_SCRIPT): |
432 | + """Creates a shell script with some default content. |
433 | + |
434 | + :param test_path: The directory where to create the script. |
435 | + :param script_name: The name of the script. |
436 | + :return The full path to the script file. |
437 | + """ |
438 | + default_script = os.path.join(test_path, script_name) |
439 | + |
440 | + if not os.path.isfile(default_script): |
441 | + print >> sys.stdout, "Creating shell script..." |
442 | + |
443 | + shell_script = ShellScript(default_script) |
444 | + shell_script.write() |
445 | + |
446 | + print >> sys.stdout, ("\nCreated shell script " |
447 | + "'{0}'.".format(script_name)) |
448 | + |
449 | + return default_script |
450 | |
451 | === modified file 'lava/job/__init__.py' |
452 | --- lava/job/__init__.py 2013-07-26 14:14:25 +0000 |
453 | +++ lava/job/__init__.py 2013-07-26 14:14:25 +0000 |
454 | @@ -16,6 +16,8 @@ |
455 | # You should have received a copy of the GNU Lesser General Public License |
456 | # along with lava-tool. If not, see <http://www.gnu.org/licenses/>. |
457 | |
458 | +"""Job class.""" |
459 | + |
460 | import json |
461 | |
462 | from copy import deepcopy |
463 | @@ -30,6 +32,8 @@ |
464 | write_file |
465 | ) |
466 | |
467 | +# A default name for job files. |
468 | +DEFAULT_JOB_FILENAME = "lava-tool-job.json" |
469 | # Default job file extension. |
470 | DEFAULT_JOB_EXTENSION = "json" |
471 | # Possible extension for a job file. |
472 | @@ -37,6 +41,14 @@ |
473 | |
474 | |
475 | class Job(object): |
476 | + |
477 | + """A Job object. |
478 | + |
479 | + This class should be used to create new job files. The initialization |
480 | + enforces a default file name extension, and makes sure that the file is |
481 | + not already present on the file system. |
482 | + """ |
483 | + |
484 | def __init__(self, data, file_name): |
485 | self.file_name = verify_file_extension(file_name, |
486 | DEFAULT_JOB_EXTENSION, |
487 | |
488 | === modified file 'lava/job/commands.py' |
489 | --- lava/job/commands.py 2013-07-26 14:14:25 +0000 |
490 | +++ lava/job/commands.py 2013-07-26 14:14:25 +0000 |
491 | @@ -29,6 +29,7 @@ |
492 | JOB_TYPES, |
493 | ) |
494 | from lava.tool.command import CommandGroup |
495 | +from lava.tool.errors import CommandError |
496 | |
497 | |
498 | class job(CommandGroup): |
499 | @@ -84,3 +85,23 @@ |
500 | |
501 | def invoke(self): |
502 | super(run, self).run(self.args.FILE) |
503 | + |
504 | + |
505 | +class status(BaseCommand): |
506 | + |
507 | + """Retrieves the status of a job.""" |
508 | + |
509 | + @classmethod |
510 | + def register_arguments(cls, parser): |
511 | + super(status, cls).register_arguments(parser) |
512 | + parser.add_argument("JOB_ID", |
513 | + help=("Prints status information about the " |
514 | + "provided job id."), |
515 | + nargs="?", |
516 | + default=None) |
517 | + |
518 | + def invoke(self): |
519 | + if self.args.JOB_ID: |
520 | + super(status, self).status(self.args.JOB_ID) |
521 | + else: |
522 | + raise CommandError("It is necessary to specify a job id.") |
523 | |
524 | === modified file 'lava/job/templates.py' |
525 | --- lava/job/templates.py 2013-07-26 14:14:25 +0000 |
526 | +++ lava/job/templates.py 2013-07-26 14:14:25 +0000 |
527 | @@ -71,7 +71,7 @@ |
528 | }, |
529 | { |
530 | "command": "submit_results", |
531 | - "parameters" : { |
532 | + "parameters": { |
533 | "stream": STREAM_PARAMETER, |
534 | "server": SERVER_PARAMETER |
535 | } |
536 | @@ -97,16 +97,16 @@ |
537 | "parameters": { |
538 | "timeout": 1800, |
539 | "testdef_repos": [ |
540 | - { |
541 | - LAVA_TEST_SHELL_TESDEF_KEY: None, |
542 | - LAVA_TEST_SHELL_TAR_REPO_KEY: None, |
543 | - } |
544 | + { |
545 | + LAVA_TEST_SHELL_TESDEF_KEY: None, |
546 | + LAVA_TEST_SHELL_TAR_REPO_KEY: None, |
547 | + } |
548 | ] |
549 | } |
550 | }, |
551 | { |
552 | "command": "submit_results", |
553 | - "parameters" : { |
554 | + "parameters": { |
555 | "stream": STREAM_PARAMETER, |
556 | "server": SERVER_PARAMETER |
557 | } |
558 | |
559 | === modified file 'lava/job/tests/test_commands.py' |
560 | --- lava/job/tests/test_commands.py 2013-07-26 14:14:25 +0000 |
561 | +++ lava/job/tests/test_commands.py 2013-07-26 14:14:25 +0000 |
562 | @@ -23,7 +23,7 @@ |
563 | import json |
564 | import os |
565 | |
566 | -from mock import MagicMock, patch |
567 | +from mock import patch |
568 | |
569 | from lava.config import Config |
570 | from lava.helper.tests.helper_test import HelperTest |
571 | @@ -99,9 +99,10 @@ |
572 | command = run(self.parser, self.args) |
573 | self.assertRaises(CommandError, command.invoke) |
574 | |
575 | - @patch("lava_tool.utils.has_command", new=MagicMock(return_value=False)) |
576 | - def test_invoke_raises_1(self): |
577 | - # Users passes a valid file to the run command, but she does not have |
578 | + @patch("lava.helper.command.has_command", create=True) |
579 | + def test_invoke_raises_1(self, mocked_has_command): |
580 | + # User passes a valid file to the run command, but she does not have |
581 | # the dispatcher installed. |
582 | + mocked_has_command.return_value = False |
583 | command = run(self.parser, self.args) |
584 | self.assertRaises(CommandError, command.invoke) |
585 | |
586 | === modified file 'lava/parameter.py' |
587 | --- lava/parameter.py 2013-07-26 14:14:25 +0000 |
588 | +++ lava/parameter.py 2013-07-26 14:14:25 +0000 |
589 | @@ -20,15 +20,9 @@ |
590 | Parameter class and its accessory methods/functions. |
591 | """ |
592 | |
593 | -import StringIO |
594 | -import base64 |
595 | -import os |
596 | import sys |
597 | -import tarfile |
598 | -import tempfile |
599 | import types |
600 | |
601 | -from lava.tool.errors import CommandError |
602 | from lava_tool.utils import to_list |
603 | |
604 | # Character used to join serialized list parameters. |
605 | |
606 | === added directory 'lava/script' |
607 | === added file 'lava/script/__init__.py' |
608 | --- lava/script/__init__.py 1970-01-01 00:00:00 +0000 |
609 | +++ lava/script/__init__.py 2013-07-26 14:14:25 +0000 |
610 | @@ -0,0 +1,51 @@ |
611 | +# Copyright (C) 2013 Linaro Limited |
612 | +# |
613 | +# Author: Milo Casagrande <milo.casagrande@linaro.org> |
614 | +# |
615 | +# This file is part of lava-tool. |
616 | +# |
617 | +# lava-tool is free software: you can redistribute it and/or modify |
618 | +# it under the terms of the GNU Lesser General Public License version 3 |
619 | +# as published by the Free Software Foundation |
620 | +# |
621 | +# lava-tool is distributed in the hope that it will be useful, |
622 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
623 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
624 | +# GNU General Public License for more details. |
625 | +# |
626 | +# You should have received a copy of the GNU Lesser General Public License |
627 | +# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. |
628 | + |
629 | +"""Scripts handling class.""" |
630 | + |
631 | +import os |
632 | +import stat |
633 | + |
634 | +from lava_tool.utils import write_file |
635 | + |
636 | + |
637 | +DEFAULT_MOD = stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH |
638 | +DEFAULT_TESTDEF_SCRIPT_CONTENT = """#!/bin/sh |
639 | +# Automatic generated content by lava-tool. |
640 | +# Please add your own instructions. |
641 | +# |
642 | +# You can use all the avialable Bash commands. |
643 | +# |
644 | +# For the available LAVA commands, see: |
645 | +# http://lava.readthedocs.org/ |
646 | +# |
647 | +""" |
648 | +DEFAULT_TESTDEF_SCRIPT = "mytest.sh" |
649 | + |
650 | + |
651 | +class ShellScript(object): |
652 | + |
653 | + """Creates a shell script on the file system with some content.""" |
654 | + |
655 | + def __init__(self, file_name): |
656 | + self.file_name = file_name |
657 | + |
658 | + def write(self): |
659 | + write_file(self.file_name, DEFAULT_TESTDEF_SCRIPT_CONTENT) |
660 | + # Make sure the script is executable. |
661 | + os.chmod(self.file_name, DEFAULT_MOD) |
662 | |
663 | === added file 'lava/script/commands.py' |
664 | --- lava/script/commands.py 1970-01-01 00:00:00 +0000 |
665 | +++ lava/script/commands.py 2013-07-26 14:14:25 +0000 |
666 | @@ -0,0 +1,115 @@ |
667 | +# Copyright (C) 2013 Linaro Limited |
668 | +# |
669 | +# Author: Milo Casagrande <milo.casagrande@linaro.org> |
670 | +# |
671 | +# This file is part of lava-tool. |
672 | +# |
673 | +# lava-tool is free software: you can redistribute it and/or modify |
674 | +# it under the terms of the GNU Lesser General Public License version 3 |
675 | +# as published by the Free Software Foundation |
676 | +# |
677 | +# lava-tool is distributed in the hope that it will be useful, |
678 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
679 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
680 | +# GNU General Public License for more details. |
681 | +# |
682 | +# You should have received a copy of the GNU Lesser General Public License |
683 | +# along with lava-tool. If not, see <http://www.gnu.org/licenses/>. |
684 | + |
685 | +"""Commands to run or submit a script.""" |
686 | + |
687 | +import os |
688 | +import tempfile |
689 | + |
690 | +from lava.helper.command import BaseCommand |
691 | +from lava.job import DEFAULT_JOB_FILENAME |
692 | +from lava.testdef import DEFAULT_TESTDEF_FILENAME |
693 | +from lava.tool.command import CommandGroup |
694 | +from lava_tool.utils import verify_path_non_existance |
695 | + |
696 | + |
697 | +class script(CommandGroup): |
698 | + |
699 | + """LAVA script file handling.""" |
700 | + |
701 | + namespace = "lava.script.commands" |
702 | + |
703 | + |
704 | +class ScriptBaseCommand(BaseCommand): |
705 | + |
706 | + def _create_tmp_job_file(self, script_file): |
707 | + """Creates a temporary job file to run or submit the passed file. |
708 | + |
709 | + The temporary job file and its accessory test definition file are |
710 | + not removed by this method. |
711 | + |
712 | + :param script_file: The script file that has to be run or submitted. |
713 | + :return A tuple with the job file path, and the test definition path. |
714 | + """ |
715 | + script_file = os.path.abspath(script_file) |
716 | + verify_path_non_existance(script_file) |
717 | + |
718 | + temp_dir = tempfile.gettempdir() |
719 | + |
720 | + # The name of the job and testdef files. |
721 | + job_file = os.path.join(temp_dir, DEFAULT_JOB_FILENAME) |
722 | + testdef_file = os.path.join(temp_dir, DEFAULT_TESTDEF_FILENAME) |
723 | + |
724 | + # The steps that the testdef file should have. We need to change it |
725 | + # from the default one, since the users are passing their own file. |
726 | + steps = "./" + os.path.basename(script_file) |
727 | + testdef_file = self.create_test_definition(testdef_file, |
728 | + steps=steps) |
729 | + |
730 | + # The content of the tar file. |
731 | + tar_content = [script_file, testdef_file] |
732 | + job_file = self.create_tar_repo_job(job_file, testdef_file, |
733 | + tar_content) |
734 | + |
735 | + return (job_file, testdef_file) |
736 | + |
737 | + |
738 | +class run(ScriptBaseCommand): |
739 | + |
740 | + """Runs the specified shell script on a local device.""" |
741 | + |
742 | + @classmethod |
743 | + def register_arguments(cls, parser): |
744 | + super(run, cls).register_arguments(parser) |
745 | + parser.add_argument("FILE", help="Shell script file to run.") |
746 | + |
747 | + def invoke(self): |
748 | + job_file = "" |
749 | + testdef_file = "" |
750 | + |
751 | + try: |
752 | + job_file, testdef_file = self._create_tmp_job_file(self.args.FILE) |
753 | + super(run, self).run(job_file) |
754 | + finally: |
755 | + if os.path.isfile(job_file): |
756 | + os.unlink(job_file) |
757 | + if os.path.isfile(testdef_file): |
758 | + os.unlink(testdef_file) |
759 | + |
760 | + |
761 | +class submit(ScriptBaseCommand): |
762 | + |
763 | + """Submits the specified shell script to a LAVA server.""" |
764 | + |
765 | + @classmethod |
766 | + def register_arguments(cls, parser): |
767 | + super(submit, cls).register_arguments(parser) |
768 | + parser.add_argument("FILE", help="Shell script file to send.") |
769 | + |
770 | + def invoke(self): |
771 | + job_file = "" |
772 | + testdef_file = "" |
773 | + |
774 | + try: |
775 | + job_file, testdef_file = self._create_tmp_job_file(self.args.FILE) |
776 | + super(submit, self).submit(job_file) |
777 | + finally: |
778 | + if os.path.isfile(job_file): |
779 | + os.unlink(job_file) |
780 | + if os.path.isfile(testdef_file): |
781 | + os.unlink(testdef_file) |
782 | |
783 | === modified file 'lava/testdef/__init__.py' |
784 | --- lava/testdef/__init__.py 2013-07-26 14:14:25 +0000 |
785 | +++ lava/testdef/__init__.py 2013-07-26 14:14:25 +0000 |
786 | @@ -16,17 +16,24 @@ |
787 | # You should have received a copy of the GNU Lesser General Public License |
788 | # along with lava-tool. If not, see <http://www.gnu.org/licenses/>. |
789 | |
790 | +"""TestDefinition class.""" |
791 | + |
792 | import yaml |
793 | |
794 | from copy import deepcopy |
795 | |
796 | -from lava.helper.template import expand_template |
797 | +from lava.helper.template import ( |
798 | + expand_template, |
799 | + set_value, |
800 | +) |
801 | from lava_tool.utils import ( |
802 | write_file, |
803 | verify_path_existance, |
804 | - verify_file_extension |
805 | + verify_file_extension, |
806 | ) |
807 | |
808 | +# Default name for a test definition. |
809 | +DEFAULT_TESTDEF_FILENAME = "lavatest.yaml" |
810 | # Default test def file extension. |
811 | DEFAULT_TESTDEF_EXTENSION = "yaml" |
812 | # Possible extensions for a test def file. |
813 | @@ -35,6 +42,13 @@ |
814 | |
815 | class TestDefinition(object): |
816 | |
817 | + """A test definition object. |
818 | + |
819 | + This class should be used to create test definitions. The initialization |
820 | + enforces a default file name extension, and makes sure that the file is |
821 | + not already present on the file system. |
822 | + """ |
823 | + |
824 | def __init__(self, data, file_name): |
825 | """Initialize the object. |
826 | |
827 | @@ -50,6 +64,14 @@ |
828 | |
829 | self.data = deepcopy(data) |
830 | |
831 | + def set(self, key, value): |
832 | + """Set key to the specified value. |
833 | + |
834 | + :param key: The key to look in the object data. |
835 | + :param value: The value to set. |
836 | + """ |
837 | + set_value(self.data, key, value) |
838 | + |
839 | def write(self): |
840 | """Writes the test definition to file.""" |
841 | content = yaml.dump(self.data, default_flow_style=False, indent=4) |
842 | |
843 | === modified file 'lava/testdef/commands.py' |
844 | --- lava/testdef/commands.py 2013-07-26 14:14:25 +0000 |
845 | +++ lava/testdef/commands.py 2013-07-26 14:14:25 +0000 |
846 | @@ -21,9 +21,12 @@ |
847 | """ |
848 | |
849 | import os |
850 | +import tempfile |
851 | |
852 | from lava.helper.command import BaseCommand |
853 | +from lava.job import DEFAULT_JOB_FILENAME |
854 | from lava.tool.command import CommandGroup |
855 | +from lava_tool.utils import verify_path_non_existance |
856 | |
857 | |
858 | class testdef(CommandGroup): |
859 | @@ -33,7 +36,23 @@ |
860 | namespace = "lava.testdef.commands" |
861 | |
862 | |
863 | -class new(BaseCommand): |
864 | +class TestdefBaseCommand(BaseCommand): |
865 | + |
866 | + def _create_tmp_job_file(self, testdef_file): |
867 | + testdef_file = os.path.abspath(testdef_file) |
868 | + verify_path_non_existance(testdef_file) |
869 | + |
870 | + job_file = os.path.join(tempfile.gettempdir(), |
871 | + DEFAULT_JOB_FILENAME) |
872 | + |
873 | + tar_content = [testdef_file] |
874 | + job_file = self.create_tar_repo_job(job_file, testdef_file, |
875 | + tar_content) |
876 | + |
877 | + return job_file |
878 | + |
879 | + |
880 | +class new(TestdefBaseCommand): |
881 | |
882 | """Creates a new test definition file.""" |
883 | |
884 | @@ -47,7 +66,7 @@ |
885 | self.create_test_definition(full_path) |
886 | |
887 | |
888 | -class run(BaseCommand): |
889 | +class run(TestdefBaseCommand): |
890 | |
891 | """Runs the specified test definition on a local device.""" |
892 | |
893 | @@ -57,11 +76,18 @@ |
894 | parser.add_argument("FILE", help="Test definition file to run.") |
895 | |
896 | def invoke(self): |
897 | - pass |
898 | - |
899 | - |
900 | -def submit(BaseCommand): |
901 | - """Submits the specified test definition to a remove LAVA server.""" |
902 | + job_file = "" |
903 | + try: |
904 | + job_file = self._create_tmp_job_file(self.args.FILE) |
905 | + super(run, self).run(job_file) |
906 | + finally: |
907 | + if os.path.isfile(job_file): |
908 | + os.unlink(job_file) |
909 | + |
910 | + |
911 | +class submit(TestdefBaseCommand): |
912 | + |
913 | + """Submits the specified test definition to a LAVA server.""" |
914 | |
915 | @classmethod |
916 | def register_arguments(cls, parser): |
917 | @@ -69,4 +95,10 @@ |
918 | parser.add_argument("FILE", help="Test definition file to send.") |
919 | |
920 | def invoke(self): |
921 | - pass |
922 | + job_file = "" |
923 | + try: |
924 | + job_file = self._create_tmp_job_file(self.args.FILE) |
925 | + super(submit, self).submit(job_file) |
926 | + finally: |
927 | + if os.path.isfile(job_file): |
928 | + os.unlink(job_file) |
929 | |
930 | === modified file 'lava/testdef/templates.py' |
931 | --- lava/testdef/templates.py 2013-07-26 14:14:25 +0000 |
932 | +++ lava/testdef/templates.py 2013-07-26 14:14:25 +0000 |
933 | @@ -19,23 +19,11 @@ |
934 | """Test definition templates.""" |
935 | |
936 | from lava.parameter import ( |
937 | - ListParameter, |
938 | Parameter, |
939 | ) |
940 | |
941 | -DEFAULT_TESTDEF_FILE = "lavatest.yaml" |
942 | - |
943 | DEFAULT_TESTDEF_VERSION = "1.0" |
944 | DEFAULT_TESTDEF_FORMAT = "Lava-Test Test Definition 1.0" |
945 | - |
946 | -# This is what will be called by default by the test definition yaml file. |
947 | -DEFAULT_TESTDEF_SCRIPT = "mytest.sh" |
948 | -DEFAULT_TESTDEF_SCRIPT_CONTENT = """#!/bin/sh |
949 | -# Automatic generated content by lava-tool. |
950 | -# Please add your own instructions. |
951 | -""" |
952 | -DEFAULT_TESTDEF_STEP = "./mytest.sh" |
953 | - |
954 | DEFAULT_ENVIRONMET_VALUE = "lava_test_shell" |
955 | |
956 | # All these parameters will not be stored on the local config file. |
957 | @@ -45,18 +33,7 @@ |
958 | DESCRIPTION_PARAMETER = Parameter("description", depends=NAME_PARAMETER) |
959 | DESCRIPTION_PARAMETER.store = False |
960 | |
961 | -ENVIRONMENT_PARAMETER = ListParameter("environment", |
962 | - depends=NAME_PARAMETER) |
963 | -ENVIRONMENT_PARAMETER.add(DEFAULT_ENVIRONMET_VALUE) |
964 | -ENVIRONMENT_PARAMETER.asked = True |
965 | -ENVIRONMENT_PARAMETER.store = False |
966 | - |
967 | -# Steps parameter. Default to a local shell script that the user defines. |
968 | -# We do not ask this parameter, and we do not store it either. |
969 | -STEPS_PARAMETER = ListParameter("steps", depends=NAME_PARAMETER) |
970 | -STEPS_PARAMETER.add(DEFAULT_TESTDEF_STEP) |
971 | -STEPS_PARAMETER.asked = True |
972 | -STEPS_PARAMETER.store = False |
973 | +TESTDEF_STEPS_KEY = "steps" |
974 | |
975 | TESTDEF_TEMPLATE = { |
976 | "metadata": { |
977 | @@ -64,12 +41,12 @@ |
978 | "format": DEFAULT_TESTDEF_FORMAT, |
979 | "version": DEFAULT_TESTDEF_VERSION, |
980 | "description": DESCRIPTION_PARAMETER, |
981 | - "environment": ENVIRONMENT_PARAMETER, |
982 | + "environment": [DEFAULT_ENVIRONMET_VALUE], |
983 | }, |
984 | "run": { |
985 | - "steps": STEPS_PARAMETER, |
986 | + TESTDEF_STEPS_KEY: ["./mytest.sh"] |
987 | }, |
988 | "parse": { |
989 | - "pattern": '^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$' |
990 | + "pattern": r'^\s*(?P<test_case_id>\w+)=(?P<result>\w+)\s*$' |
991 | } |
992 | } |
993 | |
994 | === modified file 'lava/testdef/tests/test_commands.py' |
995 | --- lava/testdef/tests/test_commands.py 2013-07-26 14:14:25 +0000 |
996 | +++ lava/testdef/tests/test_commands.py 2013-07-26 14:14:25 +0000 |
997 | @@ -47,7 +47,7 @@ |
998 | self.args.FILE = self.file_path |
999 | |
1000 | self.temp_yaml = tempfile.NamedTemporaryFile(suffix=".yaml", |
1001 | - delete=False) |
1002 | + delete=False) |
1003 | |
1004 | self.config_file = tempfile.NamedTemporaryFile(delete=False) |
1005 | self.config = InteractiveConfig() |
1006 | @@ -110,7 +110,7 @@ |
1007 | 'name': ''}, |
1008 | 'parse': { |
1009 | 'pattern': |
1010 | - '^\\s*(?P<test_case_id>\\w+)=(?P<result>\\w+)\\s*$' |
1011 | + '^\\s*(?P<test_case_id>\\w+)=(?P<result>\\w+)\\s*$' |
1012 | }, |
1013 | } |
1014 | obtained = None |
1015 | @@ -144,7 +144,7 @@ |
1016 | }, |
1017 | 'parse': { |
1018 | 'pattern': |
1019 | - '^\\s*(?P<test_case_id>\\w+)=(?P<result>\\w+)\\s*$' |
1020 | + '^\\s*(?P<test_case_id>\\w+)=(?P<result>\\w+)\\s*$' |
1021 | }, |
1022 | } |
1023 | obtained = None |
1024 | |
1025 | === modified file 'lava/tests/test_commands.py' |
1026 | --- lava/tests/test_commands.py 2013-07-26 14:14:25 +0000 |
1027 | +++ lava/tests/test_commands.py 2013-07-26 14:14:25 +0000 |
1028 | @@ -64,7 +64,6 @@ |
1029 | _, args, _ = self.parser.method_calls[1] |
1030 | self.assertIn("DIR", args) |
1031 | |
1032 | - |
1033 | @patch("lava.commands.edit_file", create=True) |
1034 | def test_command_invoke_0(self, mocked_edit_file): |
1035 | # Invoke the init command passing a path to a file. Should raise an |
1036 | |
1037 | === modified file 'lava/tests/test_config.py' |
1038 | --- lava/tests/test_config.py 2013-07-26 14:14:25 +0000 |
1039 | +++ lava/tests/test_config.py 2013-07-26 14:14:25 +0000 |
1040 | @@ -148,6 +148,15 @@ |
1041 | obtained = tmp_file.read() |
1042 | self.assertEqual(expected, obtained) |
1043 | |
1044 | + def test_config_get_from_backend_public(self): |
1045 | + # Need to to this, since we want a clean Config instance, with |
1046 | + # a config_file with some content. |
1047 | + with open(self.config.config_file, "w") as write_config: |
1048 | + write_config.write("[DEFAULT]\nfoo=bar\n") |
1049 | + param = Parameter("foo") |
1050 | + obtained = self.config.get_from_backend(param) |
1051 | + self.assertEquals("bar", obtained) |
1052 | + |
1053 | |
1054 | class InteractiveConfigTest(ConfigTestCase): |
1055 | |
1056 | |
1057 | === modified file 'lava/tests/test_parameter.py' |
1058 | --- lava/tests/test_parameter.py 2013-07-26 14:14:25 +0000 |
1059 | +++ lava/tests/test_parameter.py 2013-07-26 14:14:25 +0000 |
1060 | @@ -27,7 +27,6 @@ |
1061 | ListParameter, |
1062 | Parameter, |
1063 | ) |
1064 | - |
1065 | from lava_tool.utils import to_list |
1066 | |
1067 | |
1068 | @@ -78,7 +77,9 @@ |
1069 | self.assertIsInstance(obtained, list) |
1070 | self.assertEquals(expected, obtained) |
1071 | |
1072 | + |
1073 | class ListParameterTest(GeneralParameterTest): |
1074 | + |
1075 | """Tests for the specialized ListParameter class.""" |
1076 | |
1077 | def setUp(self): |
1078 | |
1079 | === modified file 'lava_tool/utils.py' |
1080 | --- lava_tool/utils.py 2013-07-26 14:14:25 +0000 |
1081 | +++ lava_tool/utils.py 2013-07-26 14:14:25 +0000 |
1082 | @@ -191,15 +191,27 @@ |
1083 | |
1084 | |
1085 | def verify_path_existance(path): |
1086 | - """Verifies if a given path exists or not on the file system. |
1087 | + """Verifies if a given path exists on the file system. |
1088 | |
1089 | Raises a CommandError in case it exists. |
1090 | |
1091 | - :param path: The path to verify.""" |
1092 | + :param path: The path to verify. |
1093 | + """ |
1094 | if os.path.exists(path): |
1095 | raise CommandError("{0} already exists.".format(path)) |
1096 | |
1097 | |
1098 | +def verify_path_non_existance(path): |
1099 | + """Verifies if a given path does not exist on the file system. |
1100 | + |
1101 | + Raises a CommandError in case it does not exist. |
1102 | + |
1103 | + :param path: The path to verify. |
1104 | + """ |
1105 | + if not os.path.exists(path): |
1106 | + raise CommandError("{0} does not exists.".format(path)) |
1107 | + |
1108 | + |
1109 | def write_file(path, content): |
1110 | """Creates a file with the specified content. |
1111 |
Another great job here, thanks! I have some comments below.
review needs-fixing
On Thu, Jul 18, 2013 at 04:04:26PM -0000, Milo Casagrande wrote: /code.launchpad .net/~milo/ lava-tool/ lava-169/ +merge/ 175622
> Milo Casagrande has proposed merging lp:~milo/lava-tool/lava-169 into lp:lava-tool with lp:~milo/lava-tool/lava-165 as a prerequisite.
>
> Requested reviews:
> Antonio Terceiro (terceiro)
> Linaro Validation Team (linaro-validation)
>
> For more details, see:
> https:/
>
> This is the final step in completing card LAVA-15.
> Here there is the "status" command that polls a LAVA server and prints information about the provided job id.
>
> The command can be invoked as:
>
> lava status [ID]
> lava job status [ID]
>
> The latter is the actual command and the former just calls it.
I'm not sure about the first form. `lava status` might be too generic for
people to memorize that it should be use to get status of jobs. I think we will
be able to do a better UI review after we get all the code merged in though.
> If ID is not provided, it will read the stored job IDs from the .lavaconfig file, and ask the user which job to choose.
(what follows is an updated diff from a few hours ago, not the original diff
from when the MP was created)
> === modified file 'entry_points.ini' submit status
> --- entry_points.ini 2013-07-24 14:41:29 +0000
> +++ entry_points.ini 2013-07-24 14:41:29 +0000
> @@ -13,6 +13,7 @@
> init = lava.commands:init
> submit = lava.commands:
> run = lava.commands:run
> +status = lava.commands:
you can just reference lava.job. commands: status here, you don't need to write a
separate command.
BTW this also applies to a similar comment I did in the previous MP, about
cascading commands: if the arguments are the same, you can just point to the
original command from another scope in entry_points.ini and you don't have to
wrap one command inside another
> update = lava.commands: update commands] commands: new commands: submit commands: status commands: run commands] BaseCommand) : arguments( cls, parser): arguments( parser) add_argument( "JOB_ID" , self.args) self.parser, args) BaseCommand) :
>
> [lava_tool.
> @@ -77,6 +78,7 @@
> [lava.job.commands]
> new = lava.job.
> submit = lava.job.
> +status = lava.job.
> run = lava.job.
>
> [lava.device.
>
> === modified file 'lava/commands.py'
> --- lava/commands.py 2013-07-24 14:41:29 +0000
> +++ lava/commands.py 2013-07-24 14:41:29 +0000
> @@ -251,6 +251,29 @@
> submit_cmd.invoke()
>
>
> +class status(
> +
> + """Checks the status of a job."""
> +
> + @classmethod
> + def register_
> + super(status, cls).register_
> + parser.
> + help=("Prints a job status information."),
> + nargs="?",
> + default="-1")
> +
> + def invoke(self):
> + """Runs the job.status command."""
> + from lava.job.commands import status as job_status
> +
> + args = copy.copy(
> + args.JOB_ID = self.args.JOB_ID
> +
> + status_cmd = job_status(
> + status_cmd.invoke()
> +
> +
> class update(
> """Updates a job file with the correct data."""
ditto - this s...