Merge lp:~nuclearbob/utah/consolidate-scripts into lp:utah
- consolidate-scripts
- Merge into dev
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Javier Collado | ||||||||
Approved revision: | 922 | ||||||||
Merged at revision: | 881 | ||||||||
Proposed branch: | lp:~nuclearbob/utah/consolidate-scripts | ||||||||
Merge into: | lp:utah | ||||||||
Prerequisite: | lp:~nuclearbob/utah/cleanup-cleanup | ||||||||
Diff against target: |
1559 lines (+257/-849) (has conflicts) 19 files modified
debian/changelog (+11/-0) debian/utah.manpages (+0/-3) docs/source/conf.py (+1/-9) docs/source/man/run_install_test.py.rst (+0/-26) docs/source/man/run_test_cobbler.py.rst (+0/-26) docs/source/man/run_test_vm.py.rst (+0/-26) examples/run_install_test.py (+0/-114) examples/run_test_bamboo_feeder.py (+0/-119) examples/run_test_cobbler.py (+0/-127) examples/run_test_vm.py (+0/-115) examples/run_utah_tests.py (+146/-57) tests/test_run.py (+4/-3) utah/config.py (+28/-9) utah/provisioning/baremetal/bamboofeeder.py (+7/-10) utah/provisioning/baremetal/cobbler.py (+2/-2) utah/provisioning/baremetal/power.py (+3/-3) utah/provisioning/provisioning.py (+24/-46) utah/provisioning/vm/vm.py (+14/-31) utah/run.py (+17/-123) Text conflict in debian/changelog |
||||||||
To merge this branch: | bzr merge lp:~nuclearbob/utah/consolidate-scripts | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Javier Collado (community) | Approve | ||
Max Brustkern (community) | Needs Resubmitting | ||
Review via email: mp+160963@code.launchpad.net |
This proposal supersedes a proposal from 2013-04-19.
Commit message
Description of the change
This branch removes the scripts other than run_utah_tests.py and consolidates their functionality into run_utah_tests.py
It relies on the cleanup-cleanup branch to ensure that explicit destruction calls for machines are not necessary.
Principally, it moves command line handling back in run_utah_tests.py. The script is responsible for parsing the command line options and getting a Machine object (from an Inventory in all cases except --skip-
Some try/catch stuff is simplified as well, since the number of possible paths should be reduced. I also cleaned up the handling of command line options/config options/defaults in a few cases, and moved some things around between the different types of Machine classes so that the arguments passed to the different Machine constructors could be more straightforward.
Javier Collado (javier.collado) wrote : Posted in a previous version of this proposal | # |
Andy Doan (doanac) wrote : Posted in a previous version of this proposal | # |
should we keep the original scripts and just print an error, so people don't think dpkg failed or something?
Andy Doan (doanac) wrote : Posted in a previous version of this proposal | # |
i agree about breaking out the if/else stuff.
Also it might be worth using context managers for the machine/inventory API's now that its in one spot. It could get rid of the destroy/del stuff?
Max Brustkern (nuclearbob) wrote : Posted in a previous version of this proposal | # |
I'd like to see different provisioning methods, whether those are functions or not, that basically only consist of getting the inventory and machine objects. Everything else I'd like to see handled the same way, either in run_utah_test.py or run.py. I'll work on cleaning up the documentation, and I think if we can land this proposal:
https:/
That'll put me in better shape to make the changes we've talked about in this branch.
Max Brustkern (nuclearbob) wrote : Posted in a previous version of this proposal | # |
The documentation should be updated now. I'm pondering the best place for machine getting functions. Right now, each machine type only works with a single inventory type. Would it make sense to provide functions at the level of a Machine subclass or at an Inventory level that would parse some arguments and request a machine? Or maybe we should be pulling the Machine-specific stuff out of args to pass that in? I'm not sure.
Javier Collado (javier.collado) wrote : Posted in a previous version of this proposal | # |
There still a few .rst files under docs/source/man that should be removed.
If you try to build the documentation you'll see some error messages because
those .rst files include the .txt file that was generated from the script help
output to generate the man page.
Regarding what should be the way to get a machine, I think a function or a
class method in the inventory module would be a good fit with how the code
works now.
Andy Doan (doanac) wrote : | # |
On 04/25/2013 12:32 PM, Max Brustkern wrote:
> https:/
> === modified file 'examples/
> def get_parser():
looking these two snippets
1)
> + parser.
> + choices=('i386', 'amd64', 'arm'),
> + help=('Architecture to use for VM creation '
> + '(%(choices)s)'))
2)
> + if args.arch:
> + arch = args.arch
> + else:
> + arch = config.arch
You could just set the default value in argparse to config.arch and save
4 lines of code.
> + if args.machinetype:
> + machinetype = args.machinetype
> + else:
> machinetype = config.machinetype
> - else:
> - machinetype = args.machinetype
you could probably do the same with this as well by assigning the
default in the argparse.
> + else:
> + kw = {'clean': (not args.no_destroy),
> + 'new': True,
> + }
> + for arg in ['arch',
> + 'boot',
> + 'debug',
> + 'image',
> + 'initrd',
> + 'kernel',
> + 'name',
> + 'preseed',
> + 'rewrite',
> + 'series',
> + ]:
> + kw[arg] = getattr(args, arg)
this can be done explicityline and save two lines of code doing
something like:
kw['arch'] = args.arch
and i think it might look more readable.
> + kw['installtype'] = args.type
> + if machinetype == 'physical':
> + if arch and 'arm' in arch:
> + inventory = ManualBaremetal
> + db=os.path.
> + lockfile=
> + kw['machinetype'] = BambooFeederMachine
> + else:
> + inventory = ManualBaremetal
> + kw['machinetype'] = CobblerMachine
> + else:
> + inventory = TinySQLiteInven
> + for arg in ['diskbus', 'emulator', 'xml']:
> + kw[arg] = getattr(args, arg)
> + kw['disksizes'] = args.gigabytes
> + machine = inventory.
also - i think I'd break the whole block of "if args.skip_
to here. into a utility function called something like:
def _get_machine(args)
> if __name__ == '__main__':
> try:
> - try:
> - if isinstance(
> - timeout(
> - else:
> - run_utah_tests()
> - except AttributeError:
> - run_utah_tests()
> - finally:
> - cleanup.run()
> + exitstatus = timeout(
> + run_utah_tests)
why the "getattr" - can't we ensure this will always be available by
providing a default in config.py?
> === modified file 'utah/provision
> - self...
Max Brustkern (nuclearbob) wrote : | # |
> On 04/25/2013 12:32 PM, Max Brustkern wrote:
>
> > https:/
> scripts/
>
> > === modified file 'examples/
>
> > def get_parser():
>
> looking these two snippets
> 1)
> > + parser.
> > + choices=('i386', 'amd64', 'arm'),
> > + help=('Architecture to use for VM creation '
> > + '(%(choices)s)'))
>
> 2)
> > + if args.arch:
> > + arch = args.arch
> > + else:
> > + arch = config.arch
>
> You could just set the default value in argparse to config.arch and save
> 4 lines of code.
>
There used to be some reason that didn't work, but I can't think of why now, so I'll try it.
> > + if args.machinetype:
> > + machinetype = args.machinetype
> > + else:
> > machinetype = config.machinetype
> > - else:
> > - machinetype = args.machinetype
>
> you could probably do the same with this as well by assigning the
> default in the argparse.
>
Ditto.
> > + else:
> > + kw = {'clean': (not args.no_destroy),
> > + 'new': True,
> > + }
> > + for arg in ['arch',
> > + 'boot',
> > + 'debug',
> > + 'image',
> > + 'initrd',
> > + 'kernel',
> > + 'name',
> > + 'preseed',
> > + 'rewrite',
> > + 'series',
> > + ]:
> > + kw[arg] = getattr(args, arg)
>
> this can be done explicityline and save two lines of code doing
> something like:
>
> kw['arch'] = args.arch
>
> and i think it might look more readable.
>
I'm interested in what everybody else thinks of this, since I find the repetition very unpleasant to look at. Every time I see it, I think "we could just do that to a whole list of things and then add things to the list and I'll never make an error copying and pasting the code."
> > + kw['installtype'] = args.type
> > + if machinetype == 'physical':
> > + if arch and 'arm' in arch:
> > + inventory = ManualBaremetal
> > + db=os.path.
> > + lockfile=
> > + kw['machinetype'] = BambooFeederMachine
> > + else:
> > + inventory = ManualBaremetal
> > + kw['machinetype'] = CobblerMachine
> > + else:
> > + inventory = TinySQLiteInven
> > + for arg in ['diskbus', 'emulator', 'xml']:
> > + kw[arg] = getattr(args, arg)
> > + kw['disksizes'] = args.gigabytes
> > + machine = inventory.
>
> also - i think I'd break the whole block of "if args.skip_
> to here. into a utility function called something like:
>
> def _get_machine(args)
>
That seems reasonable. I didn't do that initially because I didn't think we'd be using that function a...
Andy Doan (doanac) wrote : | # |
On 04/25/2013 05:39 PM, Max Brustkern wrote:
>>> + else:
>>> > >+ kw = {'clean': (not args.no_destroy),
>>> > >+ 'new': True,
>>> > >+ }
>>> > >+ for arg in ['arch',
>>> > >+ 'boot',
>>> > >+ 'debug',
>>> > >+ 'image',
>>> > >+ 'initrd',
>>> > >+ 'kernel',
>>> > >+ 'name',
>>> > >+ 'preseed',
>>> > >+ 'rewrite',
>>> > >+ 'series',
>>> > >+ ]:
>>> > >+ kw[arg] = getattr(args, arg)
>> >
>> >this can be done explicityline and save two lines of code doing
>> >something like:
>> >
>> > kw['arch'] = args.arch
>> >
>> >and i think it might look more readable.
>> >
> I'm interested in what everybody else thinks of this, since I find the repetition very unpleasant to look at. Every time I see it, I think "we could just do that to a whole list of things and then add things to the list and I'll never make an error copying and pasting the code."
Two things:
1) fair enough - this is mostly subjective so we should decide as a team
2) I think this is actually more of a symptom of a larger problem.
Having a constructor that takes in 18 parameters is a bit extreme. Its
possible what I'm going to say is beyond the scope of this MP, but think
about the two cases we are using the "attr" hacks:
a) to set parameters in the call to the constructor
b) to take the parameters from the constructor and make them member
variables.
Now also remember the fact that we default things not provided to args
with a value from config.py.
I can't help but wonder if we shouldn't just pass "args" to the
constructor instead. I don't really like the idea of using "args", but
it feels cleaner than insane constructors.
Doing that would clean up my complain about run_utah_tests.py. You could
go extreme and then just assign self.args = args in Machine.__init__.
That feels a little crazy - and would probably turn into a fairly
big/error-prone refactor.
Andy Doan (doanac) wrote : | # |
On 04/25/2013 05:39 PM, Max Brustkern wrote:
>>> === modified file 'utah/run.py'
>> >
>>> > >- try:
>>> > >- shutil.
>>> > >- except (IOError, shutil.Error) as err:
>>> > >- logging.
>>> > >+ if machine.
>> >
>> >do we really need hasattr instead of just doing machine.
> I don't like explicitly checking for ProvisionedMachine, which is what we did before. I don't think run.py should know or care about what Machine subclass it's using. We could just do a try and catch the AttributeError, but that seems like it could open us up to other problems.
I didn't like the ProvisionedMachine check either and I see your point
now. I say keep it as is.
Max Brustkern (nuclearbob) wrote : | # |
> On 04/25/2013 05:39 PM, Max Brustkern wrote:
> ...
> Two things:
>
> 1) fair enough - this is mostly subjective so we should decide as a team
>
Looks like your idea is preferred, so I implemented that.
> 2) I think this is actually more of a symptom of a larger problem.
> Having a constructor that takes in 18 parameters is a bit extreme. Its
> possible what I'm going to say is beyond the scope of this MP, but think
> about the two cases we are using the "attr" hacks:
>
> a) to set parameters in the call to the constructor
> b) to take the parameters from the constructor and make them member
> variables.
>
> Now also remember the fact that we default things not provided to args
> with a value from config.py.
>
> I can't help but wonder if we shouldn't just pass "args" to the
> constructor instead. I don't really like the idea of using "args", but
> it feels cleaner than insane constructors.
>
> Doing that would clean up my complain about run_utah_tests.py. You could
> go extreme and then just assign self.args = args in Machine.__init__.
> That feels a little crazy - and would probably turn into a fairly
> big/error-prone refactor.
I think this larger problem is better solved by separating installation, and probably coming up with a completely new interface. I think as part of that sorting out which arguments are used for installation, machine management, and test running might serve us well and allow us to pass those around in ways that make more sense.
Andy Doan (doanac) wrote : | # |
On 04/26/2013 03:02 PM, Max Brustkern wrote:
> I think this larger problem is better solved by separating installation, and probably coming up with a completely new interface. I think as part of that sorting out which arguments are used for installation, machine management, and test running might serve us well and allow us to pass those around in ways that make more sense.
+1 - I hesitated to say that because its even more work :)
Javier Collado (javier.collado) wrote : | # |
There are a few lines that have to be removed in:
debian/
to avoid generating manual pages for the scripts that have been removed.
- 878. By Javier Collado
-
Merged changes to fix DefaultValidator and updated schemas to draftv4 (LP: #1165175)
Source branch: lp:~javier.collado/utah/bug1165175
- 879. By Javier Collado
-
Merged changes to refactor cleanup for the machine class
Source branch: lp:~nuclearbob/utah/cleanup-cleanup
Javier Collado (javier.collado) wrote : | # |
The exception handling in run_utah_tests.py has been updated so that the cleanup is executed after all exceptions are handled. The way it was written before, exceptions were handled just after the cleanup to make sure that error messages were printed at the bottom of the log file so that it was easy to know the error cause without having to read the log backwards and skip all the cleanup. I think I prefer that unless there's some other thing I'm missing. Please let me know your thoughts on this.
Aside from this, I see a few new default values have been added to command line parameters. Please consider adding those values to the help string via %(default)s, so that the user knows that values when passing -h/--help to run_utah_tests.py.
Max Brustkern (nuclearbob) wrote : | # |
You have a good point about the finally for the cleanup. Does this look better to you:
if __name__ == '__main__':
try:
try:
finally:
except UTAHTimeout as exception:
except UTAHException as error:
except Exception:
sys.
As far as the default values, do you think I should add all of them, or just the ones that aren't inherited from config? It seems weird to have a default potentially dependent on environment variables, but since that's how we're processing things it makes sense.
Javier Collado (javier.collado) wrote : | # |
Yes, that would look good to me.
Regarding default values, I was thinking about the ones that were newly added, but it's true that to be consistent lot of others default could be added as well. Maybe we should skip this for now, since I understand is out of the scope of this merge request.
- 918. By Max Brustkern
-
Moved cleanup before exception handling
Javier Collado (javier.collado) wrote : | # |
When passing the -i/--image argument through the command line, I see that utah is trying to download the mini image instead of using the one that was passed as an argument.
- 919. By Max Brustkern
-
Updated help strings
Javier Collado (javier.collado) wrote : | # |
Example output:
$ PYTHONPATH=. examples/
2013-05-01 11:02:30,082 root INFO: UTAH version: dev-r881~raring
2013-05-01 11:02:30,083 root DEBUG: Executing SQL statement: CREATE TABLE IF NOT EXISTS machines(machineid INTEGER PRIMARY KEY, state TEXT), [
]
2013-05-01 11:02:30,083 root DEBUG: Executing SQL statement: INSERT INTO machines (state) VALUES ('provisioned'), []
2013-05-01 11:02:30,259 utah-22 INFO: Attempting to retrieve raring-
2013-05-01 11:02:30,266 utah-22 INFO: Download attempt 0
2013-05-01 11:02:30,284 utah-22 DEBUG: Server md5 is 69c919c499068b1
2013-05-01 11:02:30,284 utah-22 INFO: Attempting to download http://
/./netboot/mini.iso
2013-05-01 11:02:30,320 utah-22 INFO: File 0% downloaded
2013-05-01 11:02:30,321 utah-22 DEBUG: 0 read, 0% of 36700160 total
2013-05-01 11:02:30,324 utah-22 DEBUG: 8192 read, 0% of 36700160 total
Max Brustkern (nuclearbob) wrote : | # |
I moved cleanup and updated the help strings. I'll sort out the image thing, thanks for finding that.
- 920. By Max Brustkern
-
Fixed image handling typos
Max Brustkern (nuclearbob) wrote : | # |
Fixed some dumb typos on the image thing.
Javier Collado (javier.collado) wrote : | # |
When trying to provision a VM, I got the following traceback:
Unhandled error in UTAH:
Traceback (most recent call last):
File "examples/
exitstatus = timeout(
File "utah/timeout.py", line 65, in timeout
return command(*args, **kw)
File "examples/
exitstatus, locallogs = run_tests(args, _get_machine(args))
File "examples/
machine = inventory.
File "utah/provision
return machinetype(
File "utah/provision
self.
File "utah/provision
self.name = self._makename()
File "utah/provision
machineid = str(self.machineid)
AttributeError: 'CustomVM' object has no attribute 'machineid'
- 921. By Max Brustkern
-
Fixed machineid not being set
- 922. By Max Brustkern
-
Fixed failure to chmod preseed when it doesn't exist, and fixed self tests
Javier Collado (javier.collado) wrote : | # |
Working fine for me now. Thanks.
Preview Diff
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2013-05-01 17:37:58 +0000 | |||
3 | +++ debian/changelog 2013-05-01 21:24:29 +0000 | |||
4 | @@ -14,9 +14,20 @@ | |||
5 | 14 | * Make rsyslog timeout error message clearer (LP: #1169846) | 14 | * Make rsyslog timeout error message clearer (LP: #1169846) |
6 | 15 | * Write to log UTAH version as soon as possible (LP: #1152216) | 15 | * Write to log UTAH version as soon as possible (LP: #1152216) |
7 | 16 | * Fixed help output to use just one runlist (LP: #1112597) | 16 | * Fixed help output to use just one runlist (LP: #1112597) |
8 | 17 | <<<<<<< TREE | ||
9 | 17 | * Setup rc.local to use output passed via command line (LP: #1155615) | 18 | * Setup rc.local to use output passed via command line (LP: #1155615) |
10 | 19 | ======= | ||
11 | 20 | * Combined current provisioning functions into one script and removed | ||
12 | 21 | old scripts | ||
13 | 22 | * Set permissions when copying preseed so overwrite works (LP: #1130901) | ||
14 | 23 | * Enabled reading power command from config (LP: #1153735) | ||
15 | 24 | >>>>>>> MERGE-SOURCE | ||
16 | 18 | 25 | ||
17 | 26 | <<<<<<< TREE | ||
18 | 19 | -- Max Brustkern <max@canonical.com> Fri, 26 Apr 2013 13:58:25 -0400 | 27 | -- Max Brustkern <max@canonical.com> Fri, 26 Apr 2013 13:58:25 -0400 |
19 | 28 | ======= | ||
20 | 29 | -- Max Brustkern <max@canonical.com> Thu, 25 Apr 2013 11:02:23 -0400 | ||
21 | 30 | >>>>>>> MERGE-SOURCE | ||
22 | 20 | 31 | ||
23 | 21 | utah (0.10ubuntu1) UNRELEASED; urgency=low | 32 | utah (0.10ubuntu1) UNRELEASED; urgency=low |
24 | 22 | 33 | ||
25 | 23 | 34 | ||
26 | === modified file 'debian/utah.manpages' | |||
27 | --- debian/utah.manpages 2012-08-31 15:36:31 +0000 | |||
28 | +++ debian/utah.manpages 2013-05-01 21:24:29 +0000 | |||
29 | @@ -1,4 +1,1 @@ | |||
30 | 1 | docs/build/man/run_install_test.py.1 | ||
31 | 2 | docs/build/man/run_test_cobbler.py.1 | ||
32 | 3 | docs/build/man/run_test_vm.py.1 | ||
33 | 4 | docs/build/man/run_utah_tests.py.1 | 1 | docs/build/man/run_utah_tests.py.1 |
34 | 5 | 2 | ||
35 | === modified file 'docs/source/conf.py' | |||
36 | --- docs/source/conf.py 2013-04-18 10:46:00 +0000 | |||
37 | +++ docs/source/conf.py 2013-05-01 21:24:29 +0000 | |||
38 | @@ -148,8 +148,7 @@ | |||
39 | 148 | 148 | ||
40 | 149 | return description, options, epilog | 149 | return description, options, epilog |
41 | 150 | 150 | ||
44 | 151 | module_names = ('client', 'run_install_test', 'run_test_cobbler', | 151 | module_names = ('client', 'run_utah_tests') |
43 | 152 | 'run_test_vm', 'run_utah_tests') | ||
45 | 153 | for module_name in module_names: | 152 | for module_name in module_names: |
46 | 154 | module = __import__(module_name) | 153 | module = __import__(module_name) |
47 | 155 | parser = module.get_parser() | 154 | parser = module.get_parser() |
48 | @@ -367,13 +366,6 @@ | |||
49 | 367 | man_pages = [ | 366 | man_pages = [ |
50 | 368 | ('man/utah', 'utah', u'UTAH client test runner', | 367 | ('man/utah', 'utah', u'UTAH client test runner', |
51 | 369 | [u'Canonical Ltd'], 1), | 368 | [u'Canonical Ltd'], 1), |
52 | 370 | ('man/run_install_test.py', 'run_install_test.py', | ||
53 | 371 | u'UTAH server test runner (provisioning)', [u'Canonical Ltd'], 1), | ||
54 | 372 | ('man/run_test_cobbler.py', 'run_test_cobbler.py', | ||
55 | 373 | u'UTAH server test runner (physical hardware)', [u'Canonical Ltd'], 1), | ||
56 | 374 | ('man/run_test_vm.py', 'run_test_vm.py', | ||
57 | 375 | u'UTAH server test runner (virtual hardware)', | ||
58 | 376 | [u'Canonical Ltd'], 1), | ||
59 | 377 | ('man/run_utah_tests.py', 'run_utah_tests.py', | 369 | ('man/run_utah_tests.py', 'run_utah_tests.py', |
60 | 378 | u'UTAH server test runner (any hardware)', [u'Canonical Ltd'], 1), | 370 | u'UTAH server test runner (any hardware)', [u'Canonical Ltd'], 1), |
61 | 379 | ] | 371 | ] |
62 | 380 | 372 | ||
63 | === removed file 'docs/source/man/run_install_test.py.rst' | |||
64 | --- docs/source/man/run_install_test.py.rst 2012-09-05 11:30:16 +0000 | |||
65 | +++ docs/source/man/run_install_test.py.rst 1970-01-01 00:00:00 +0000 | |||
66 | @@ -1,26 +0,0 @@ | |||
67 | 1 | :orphan: | ||
68 | 2 | |||
69 | 3 | run_install_test.py manual page | ||
70 | 4 | =============================== | ||
71 | 5 | |||
72 | 6 | Synopsis | ||
73 | 7 | -------- | ||
74 | 8 | **run_install_test.py** [options] [runlist ...] | ||
75 | 9 | |||
76 | 10 | Description | ||
77 | 11 | ----------- | ||
78 | 12 | .. include:: run_install_test_description.txt | ||
79 | 13 | |||
80 | 14 | Options | ||
81 | 15 | ------- | ||
82 | 16 | .. include:: run_install_test_options.txt | ||
83 | 17 | |||
84 | 18 | Examples | ||
85 | 19 | -------- | ||
86 | 20 | .. include:: run_install_test_epilog.txt | ||
87 | 21 | |||
88 | 22 | See also | ||
89 | 23 | -------- | ||
90 | 24 | :manpage:`run_test_cobbler.py(1)` | ||
91 | 25 | :manpage:`run_test_vm.py(1)` | ||
92 | 26 | :manpage:`run_utah_tests.py(1)` | ||
93 | 27 | 0 | ||
94 | === removed file 'docs/source/man/run_test_cobbler.py.rst' | |||
95 | --- docs/source/man/run_test_cobbler.py.rst 2012-09-05 11:30:16 +0000 | |||
96 | +++ docs/source/man/run_test_cobbler.py.rst 1970-01-01 00:00:00 +0000 | |||
97 | @@ -1,26 +0,0 @@ | |||
98 | 1 | :orphan: | ||
99 | 2 | |||
100 | 3 | run_test_cobbler.py manual page | ||
101 | 4 | =============================== | ||
102 | 5 | |||
103 | 6 | Synopsis | ||
104 | 7 | -------- | ||
105 | 8 | **run_test_cobbler.py** [options] [runlist ...] | ||
106 | 9 | |||
107 | 10 | Description | ||
108 | 11 | ----------- | ||
109 | 12 | .. include:: run_test_cobbler_description.txt | ||
110 | 13 | |||
111 | 14 | Options | ||
112 | 15 | ------- | ||
113 | 16 | .. include:: run_test_cobbler_options.txt | ||
114 | 17 | |||
115 | 18 | Examples | ||
116 | 19 | -------- | ||
117 | 20 | .. include:: run_test_cobbler_epilog.txt | ||
118 | 21 | |||
119 | 22 | See also | ||
120 | 23 | -------- | ||
121 | 24 | :manpage:`run_install_test.py(1)` | ||
122 | 25 | :manpage:`run_test_vm.py(1)` | ||
123 | 26 | :manpage:`run_utah_tests.py(1)` | ||
124 | 27 | 0 | ||
125 | === removed file 'docs/source/man/run_test_vm.py.rst' | |||
126 | --- docs/source/man/run_test_vm.py.rst 2012-09-05 11:30:16 +0000 | |||
127 | +++ docs/source/man/run_test_vm.py.rst 1970-01-01 00:00:00 +0000 | |||
128 | @@ -1,26 +0,0 @@ | |||
129 | 1 | :orphan: | ||
130 | 2 | |||
131 | 3 | run_test_vm.py manual page | ||
132 | 4 | ========================== | ||
133 | 5 | |||
134 | 6 | Synopsis | ||
135 | 7 | -------- | ||
136 | 8 | **run_test_vm.py** [options] [runlist ...] | ||
137 | 9 | |||
138 | 10 | Description | ||
139 | 11 | ----------- | ||
140 | 12 | .. include:: run_test_vm_description.txt | ||
141 | 13 | |||
142 | 14 | Options | ||
143 | 15 | ------- | ||
144 | 16 | .. include:: run_test_vm_options.txt | ||
145 | 17 | |||
146 | 18 | Examples | ||
147 | 19 | -------- | ||
148 | 20 | .. include:: run_test_vm_epilog.txt | ||
149 | 21 | |||
150 | 22 | See also | ||
151 | 23 | -------- | ||
152 | 24 | :manpage:`run_install_test.py(1)` | ||
153 | 25 | :manpage:`run_test_cobbler.py(1)` | ||
154 | 26 | :manpage:`run_utah_tests.py(1)` | ||
155 | 27 | 0 | ||
156 | === removed file 'examples/run_install_test.py' | |||
157 | --- examples/run_install_test.py 2013-04-18 14:15:12 +0000 | |||
158 | +++ examples/run_install_test.py 1970-01-01 00:00:00 +0000 | |||
159 | @@ -1,114 +0,0 @@ | |||
160 | 1 | #!/usr/bin/env python | ||
161 | 2 | |||
162 | 3 | # Ubuntu Testing Automation Harness | ||
163 | 4 | # Copyright 2012 Canonical Ltd. | ||
164 | 5 | |||
165 | 6 | # This program is free software: you can redistribute it and/or modify it | ||
166 | 7 | # under the terms of the GNU General Public License version 3, as published | ||
167 | 8 | # by the Free Software Foundation. | ||
168 | 9 | |||
169 | 10 | # This program is distributed in the hope that it will be useful, but | ||
170 | 11 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
171 | 12 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
172 | 13 | # PURPOSE. See the GNU General Public License for more details. | ||
173 | 14 | |||
174 | 15 | # You should have received a copy of the GNU General Public License along | ||
175 | 16 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
176 | 17 | |||
177 | 18 | """Create a VM and run a test.""" | ||
178 | 19 | |||
179 | 20 | |||
180 | 21 | import argparse | ||
181 | 22 | import logging | ||
182 | 23 | import sys | ||
183 | 24 | |||
184 | 25 | from utah.cleanup import cleanup | ||
185 | 26 | from utah.exceptions import UTAHException | ||
186 | 27 | from utah.group import check_user_group, print_group_error_message | ||
187 | 28 | from utah.provisioning.vm.vm import CustomVM, TinySQLiteInventory | ||
188 | 29 | from utah.run import ( | ||
189 | 30 | common_arguments, | ||
190 | 31 | custom_arguments, | ||
191 | 32 | file_arguments, | ||
192 | 33 | run_tests, | ||
193 | 34 | virtual_arguments, | ||
194 | 35 | configure_logging, | ||
195 | 36 | ReturnCodes, | ||
196 | 37 | ) | ||
197 | 38 | |||
198 | 39 | |||
199 | 40 | def get_parser(): | ||
200 | 41 | parser = argparse.ArgumentParser( | ||
201 | 42 | description=('Provision a machine ' | ||
202 | 43 | 'and run one or more UTAH runlists there.'), | ||
203 | 44 | epilog=("For example:\n" | ||
204 | 45 | "Provision a VM using a precise server image " | ||
205 | 46 | "with i386 architecture and run the two given runlists\n" | ||
206 | 47 | "\t%(prog)s -s precise -t server -a i386 \\\n" | ||
207 | 48 | "\t\t/usr/share/utah/client/examples/master.run \\\n" | ||
208 | 49 | "\t\t'http://people.canonical.com/~max/max_test.run'"), | ||
209 | 50 | formatter_class=argparse.RawDescriptionHelpFormatter) | ||
210 | 51 | parser = common_arguments(parser) | ||
211 | 52 | parser = custom_arguments(parser) | ||
212 | 53 | parser = file_arguments(parser) | ||
213 | 54 | parser = virtual_arguments(parser) | ||
214 | 55 | return parser | ||
215 | 56 | |||
216 | 57 | |||
217 | 58 | def run_install_test(args=None): | ||
218 | 59 | if args is None: | ||
219 | 60 | args = get_parser().parse_args() | ||
220 | 61 | |||
221 | 62 | if not check_user_group(): | ||
222 | 63 | print_group_error_message(__file__) | ||
223 | 64 | sys.exit(ReturnCodes.GROUP_ERROR) | ||
224 | 65 | |||
225 | 66 | locallogs = [] | ||
226 | 67 | exitstatus = ReturnCodes.SUCCESS | ||
227 | 68 | machine = None | ||
228 | 69 | |||
229 | 70 | configure_logging(args.debug) | ||
230 | 71 | |||
231 | 72 | try: | ||
232 | 73 | inventory = TinySQLiteInventory() | ||
233 | 74 | machine = inventory.request( | ||
234 | 75 | CustomVM, | ||
235 | 76 | arch=args.arch, boot=args.boot, clean=(not args.no_destroy), | ||
236 | 77 | debug=args.debug, diskbus=args.diskbus, | ||
237 | 78 | disksizes=args.gigabytes, dlpercentincrement=10, | ||
238 | 79 | emulator=args.emulator, image=args.image, initrd=args.initrd, | ||
239 | 80 | installtype=args.type, kernel=args.kernel, new=True, | ||
240 | 81 | preseed=args.preseed, rewrite=args.rewrite, | ||
241 | 82 | series=args.series, xml=args.xml) | ||
242 | 83 | exitstatus, locallogs = run_tests(args, machine) | ||
243 | 84 | finally: | ||
244 | 85 | if not args.no_destroy and machine is not None: | ||
245 | 86 | try: | ||
246 | 87 | machine.destroy() | ||
247 | 88 | except UTAHException as error: | ||
248 | 89 | sys.stderr.write('Failed to destroy machine: ' + str(error)) | ||
249 | 90 | finally: | ||
250 | 91 | try: | ||
251 | 92 | inventory.destroy(machine.machineid) | ||
252 | 93 | except UTAHException as error: | ||
253 | 94 | sys.stderr.write('Failed to update inventory: ' | ||
254 | 95 | + str(error)) | ||
255 | 96 | finally: | ||
256 | 97 | del machine | ||
257 | 98 | if len(locallogs) != 0: | ||
258 | 99 | print('Test logs copied to the following files:') | ||
259 | 100 | print("\t" + "\n\t".join(locallogs)) | ||
260 | 101 | |||
261 | 102 | sys.exit(exitstatus) | ||
262 | 103 | |||
263 | 104 | |||
264 | 105 | if __name__ == '__main__': | ||
265 | 106 | logging.warning('This script is deprecated; please use run_utah_tests.py') | ||
266 | 107 | logging.warning('The same command line arguments should work there, i.e.:') | ||
267 | 108 | argv = list(sys.argv) | ||
268 | 109 | argv[0] = 'run_utah_tests.py' | ||
269 | 110 | logging.warning(' '.join(argv)) | ||
270 | 111 | try: | ||
271 | 112 | run_install_test() | ||
272 | 113 | finally: | ||
273 | 114 | cleanup.run() | ||
274 | 115 | 0 | ||
275 | === removed file 'examples/run_test_bamboo_feeder.py' | |||
276 | --- examples/run_test_bamboo_feeder.py 2013-04-10 15:34:49 +0000 | |||
277 | +++ examples/run_test_bamboo_feeder.py 1970-01-01 00:00:00 +0000 | |||
278 | @@ -1,119 +0,0 @@ | |||
279 | 1 | #!/usr/bin/env python | ||
280 | 2 | |||
281 | 3 | # Ubuntu Testing Automation Harness | ||
282 | 4 | # Copyright 2012 Canonical Ltd. | ||
283 | 5 | |||
284 | 6 | # This program is free software: you can redistribute it and/or modify it | ||
285 | 7 | # under the terms of the GNU General Public License version 3, as published | ||
286 | 8 | # by the Free Software Foundation. | ||
287 | 9 | |||
288 | 10 | # This program is distributed in the hope that it will be useful, but | ||
289 | 11 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
290 | 12 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
291 | 13 | # PURPOSE. See the GNU General Public License for more details. | ||
292 | 14 | |||
293 | 15 | # You should have received a copy of the GNU General Public License along | ||
294 | 16 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
295 | 17 | |||
296 | 18 | """Provision a panda board in a bamboo-feeder setup and run a test.""" | ||
297 | 19 | |||
298 | 20 | |||
299 | 21 | import argparse | ||
300 | 22 | import os | ||
301 | 23 | import sys | ||
302 | 24 | import logging | ||
303 | 25 | |||
304 | 26 | from utah.cleanup import cleanup | ||
305 | 27 | from utah.exceptions import UTAHException | ||
306 | 28 | from utah.group import check_user_group, print_group_error_message | ||
307 | 29 | from utah.provisioning.baremetal.bamboofeeder import BambooFeederMachine | ||
308 | 30 | from utah.provisioning.baremetal.inventory import \ | ||
309 | 31 | ManualBaremetalSQLiteInventory | ||
310 | 32 | from utah.run import ( | ||
311 | 33 | common_arguments, | ||
312 | 34 | custom_arguments, | ||
313 | 35 | name_argument, | ||
314 | 36 | run_tests, | ||
315 | 37 | configure_logging, | ||
316 | 38 | ReturnCodes, | ||
317 | 39 | ) | ||
318 | 40 | |||
319 | 41 | |||
320 | 42 | def get_parser(): | ||
321 | 43 | parser = argparse.ArgumentParser( | ||
322 | 44 | description=('Provision a pandaboard in a bamboo-feeder setup ' | ||
323 | 45 | 'and run one or more UTAH runlists there.'), | ||
324 | 46 | epilog=("For example:\n" | ||
325 | 47 | "Provision a machine using a precise server image " | ||
326 | 48 | "with i386 architecture and run the two given runlists\n" | ||
327 | 49 | "\t%(prog)s -s precise -t server -a i386 \\\n" | ||
328 | 50 | "\t\t/usr/share/utah/client/examples/master.run \\\n" | ||
329 | 51 | "\t\t'http://people.canonical.com/~max/max_test.run'"), | ||
330 | 52 | formatter_class=argparse.RawDescriptionHelpFormatter) | ||
331 | 53 | parser = common_arguments(parser) | ||
332 | 54 | parser = custom_arguments(parser) | ||
333 | 55 | parser = name_argument(parser) | ||
334 | 56 | return parser | ||
335 | 57 | |||
336 | 58 | |||
337 | 59 | def run_test_bamboo_feeder(args=None): | ||
338 | 60 | if args is None: | ||
339 | 61 | args = get_parser().parse_args() | ||
340 | 62 | |||
341 | 63 | if not check_user_group(): | ||
342 | 64 | print_group_error_message(__file__) | ||
343 | 65 | sys.exit(ReturnCodes.GROUP_ERROR) | ||
344 | 66 | |||
345 | 67 | locallogs = [] | ||
346 | 68 | exitstatus = ReturnCodes.SUCCESS | ||
347 | 69 | machine = None | ||
348 | 70 | |||
349 | 71 | configure_logging(args.debug) | ||
350 | 72 | |||
351 | 73 | try: | ||
352 | 74 | inventory = ManualBaremetalSQLiteInventory( | ||
353 | 75 | db=os.path.join('~', '.utah-bamboofeeder-inventory'), | ||
354 | 76 | lockfile=os.path.join('~', '.utah-bamboofeeder-lock')) | ||
355 | 77 | kw = {} | ||
356 | 78 | for arg in ['boot', 'image', 'preseed']: | ||
357 | 79 | value = getattr(args, arg) | ||
358 | 80 | if value is not None: | ||
359 | 81 | kw[arg] = value | ||
360 | 82 | machine = inventory.request(machinetype=BambooFeederMachine, | ||
361 | 83 | clean=(not args.no_destroy), | ||
362 | 84 | debug=args.debug, new=True, | ||
363 | 85 | dlpercentincrement=10, **kw) | ||
364 | 86 | exitstatus, locallogs = run_tests(args, machine) | ||
365 | 87 | |||
366 | 88 | except UTAHException as error: | ||
367 | 89 | mesg = 'Exception: ' + str(error) | ||
368 | 90 | try: | ||
369 | 91 | logging.error(mesg) | ||
370 | 92 | except (AttributeError, NameError): | ||
371 | 93 | sys.stderr.write(mesg) | ||
372 | 94 | exitstatus = ReturnCodes.UTAH_EXCEPTION_ERROR | ||
373 | 95 | except Exception: | ||
374 | 96 | logging.exception('Unhandled error in UTAH') | ||
375 | 97 | exitstatus = ReturnCodes.UNHANDLED_ERROR | ||
376 | 98 | finally: | ||
377 | 99 | if machine is not None: | ||
378 | 100 | try: | ||
379 | 101 | machine.destroy() | ||
380 | 102 | except UTAHException as error: | ||
381 | 103 | sys.stderr.write('Failed to destroy machine: ' + str(error)) | ||
382 | 104 | |||
383 | 105 | if len(locallogs) != 0: | ||
384 | 106 | print('Test logs copied to the following files:') | ||
385 | 107 | print("\t" + "\n\t".join(locallogs)) | ||
386 | 108 | |||
387 | 109 | sys.exit(exitstatus) | ||
388 | 110 | |||
389 | 111 | |||
390 | 112 | if __name__ == '__main__': | ||
391 | 113 | logging.warning('This script is thought to be broken') | ||
392 | 114 | logging.warning('If it is working, please report it to the UTAH team via ' | ||
393 | 115 | 'ubuntu-utah-devel@lists.ubuntu.com') | ||
394 | 116 | try: | ||
395 | 117 | run_test_bamboo_feeder() | ||
396 | 118 | finally: | ||
397 | 119 | cleanup.run() | ||
398 | 120 | 0 | ||
399 | === removed file 'examples/run_test_cobbler.py' | |||
400 | --- examples/run_test_cobbler.py 2013-04-10 15:34:49 +0000 | |||
401 | +++ examples/run_test_cobbler.py 1970-01-01 00:00:00 +0000 | |||
402 | @@ -1,127 +0,0 @@ | |||
403 | 1 | #!/usr/bin/env python | ||
404 | 2 | |||
405 | 3 | # Ubuntu Testing Automation Harness | ||
406 | 4 | # Copyright 2012 Canonical Ltd. | ||
407 | 5 | |||
408 | 6 | # This program is free software: you can redistribute it and/or modify it | ||
409 | 7 | # under the terms of the GNU General Public License version 3, as published | ||
410 | 8 | # by the Free Software Foundation. | ||
411 | 9 | |||
412 | 10 | # This program is distributed in the hope that it will be useful, but | ||
413 | 11 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
414 | 12 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
415 | 13 | # PURPOSE. See the GNU General Public License for more details. | ||
416 | 14 | |||
417 | 15 | # You should have received a copy of the GNU General Public License along | ||
418 | 16 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
419 | 17 | |||
420 | 18 | """Provision a machine with cobbler and run a test.""" | ||
421 | 19 | |||
422 | 20 | |||
423 | 21 | import argparse | ||
424 | 22 | import sys | ||
425 | 23 | import logging | ||
426 | 24 | |||
427 | 25 | from utah.cleanup import cleanup | ||
428 | 26 | from utah.exceptions import UTAHException | ||
429 | 27 | from utah.group import check_user_group, print_group_error_message | ||
430 | 28 | from utah.provisioning.baremetal.cobbler import CobblerMachine | ||
431 | 29 | from utah.provisioning.baremetal.inventory import \ | ||
432 | 30 | ManualBaremetalSQLiteInventory | ||
433 | 31 | from utah.run import ( | ||
434 | 32 | common_arguments, | ||
435 | 33 | custom_arguments, | ||
436 | 34 | name_argument, | ||
437 | 35 | run_tests, | ||
438 | 36 | configure_logging, | ||
439 | 37 | ReturnCodes, | ||
440 | 38 | ) | ||
441 | 39 | |||
442 | 40 | |||
443 | 41 | def get_parser(): | ||
444 | 42 | parser = argparse.ArgumentParser( | ||
445 | 43 | description=('Provision a machine using cobbler ' | ||
446 | 44 | 'and run one or more UTAH runlists there.'), | ||
447 | 45 | epilog=("For example:\n" | ||
448 | 46 | "Provision a machine using a precise server image " | ||
449 | 47 | "with i386 architecture and run the two given runlists\n" | ||
450 | 48 | "\t%(prog)s -s precise -t server -a i386 \\\n" | ||
451 | 49 | "\t\t/usr/share/utah/client/examples/master.run \\\n" | ||
452 | 50 | "\t\t'http://people.canonical.com/~max/max_test.run'"), | ||
453 | 51 | formatter_class=argparse.RawDescriptionHelpFormatter) | ||
454 | 52 | parser = common_arguments(parser) | ||
455 | 53 | parser = custom_arguments(parser) | ||
456 | 54 | parser = name_argument(parser) | ||
457 | 55 | return parser | ||
458 | 56 | |||
459 | 57 | |||
460 | 58 | def run_test_cobbler(args=None): | ||
461 | 59 | if args is None: | ||
462 | 60 | args = get_parser().parse_args() | ||
463 | 61 | |||
464 | 62 | if not check_user_group(): | ||
465 | 63 | print_group_error_message(__file__) | ||
466 | 64 | sys.exit(ReturnCodes.GROUP_ERROR) | ||
467 | 65 | |||
468 | 66 | locallogs = [] | ||
469 | 67 | exitstatus = ReturnCodes.SUCCESS | ||
470 | 68 | machine = None | ||
471 | 69 | |||
472 | 70 | configure_logging(args.debug) | ||
473 | 71 | |||
474 | 72 | try: | ||
475 | 73 | inventory = ManualBaremetalSQLiteInventory() | ||
476 | 74 | kw = {} | ||
477 | 75 | for arg in ['arch', | ||
478 | 76 | 'boot', | ||
479 | 77 | 'image', | ||
480 | 78 | 'preseed', | ||
481 | 79 | 'rewrite', | ||
482 | 80 | 'series', | ||
483 | 81 | ]: | ||
484 | 82 | value = getattr(args, arg) | ||
485 | 83 | if value is not None: | ||
486 | 84 | kw[arg] = value | ||
487 | 85 | if getattr(args, 'type') is not None: | ||
488 | 86 | kw['installtype'] = args.type | ||
489 | 87 | machine = inventory.request(CobblerMachine, | ||
490 | 88 | clean=(not args.no_destroy), | ||
491 | 89 | debug=args.debug, dlpercentincrement=10, | ||
492 | 90 | name=args.name, new=True, **kw) | ||
493 | 91 | exitstatus, locallogs = run_tests(args, machine) | ||
494 | 92 | |||
495 | 93 | except UTAHException as error: | ||
496 | 94 | mesg = 'Exception: ' + str(error) | ||
497 | 95 | try: | ||
498 | 96 | logging.error(mesg) | ||
499 | 97 | except (AttributeError, NameError): | ||
500 | 98 | sys.stderr.write(mesg) | ||
501 | 99 | exitstatus = ReturnCodes.UTAH_EXCEPTION_ERROR | ||
502 | 100 | except Exception: | ||
503 | 101 | logging.exception('Unhandled error in UTAH') | ||
504 | 102 | exitstatus = ReturnCodes.UNHANDLED_ERROR | ||
505 | 103 | finally: | ||
506 | 104 | if machine is not None: | ||
507 | 105 | try: | ||
508 | 106 | machine.destroy() | ||
509 | 107 | except UTAHException as error: | ||
510 | 108 | sys.stderr.write('Failed to destroy machine: ' + str(error)) | ||
511 | 109 | |||
512 | 110 | if len(locallogs) != 0: | ||
513 | 111 | print('Test logs copied to the following files:') | ||
514 | 112 | print("\t" + "\n\t".join(locallogs)) | ||
515 | 113 | |||
516 | 114 | sys.exit(exitstatus) | ||
517 | 115 | |||
518 | 116 | |||
519 | 117 | if __name__ == '__main__': | ||
520 | 118 | logging.warning('This script is deprecated; please use run_utah_tests.py') | ||
521 | 119 | logging.warning('Add the -m physical argument to your existing list, i.e.:') | ||
522 | 120 | argv = list(sys.argv) | ||
523 | 121 | argv[0] = 'run_utah_tests.py' | ||
524 | 122 | argv.extend(['-m', 'physical']) | ||
525 | 123 | logging.warning(' '.join(argv)) | ||
526 | 124 | try: | ||
527 | 125 | run_test_cobbler() | ||
528 | 126 | finally: | ||
529 | 127 | cleanup.run() | ||
530 | 128 | 0 | ||
531 | === removed file 'examples/run_test_vm.py' | |||
532 | --- examples/run_test_vm.py 2013-04-10 15:34:49 +0000 | |||
533 | +++ examples/run_test_vm.py 1970-01-01 00:00:00 +0000 | |||
534 | @@ -1,115 +0,0 @@ | |||
535 | 1 | #!/usr/bin/env python | ||
536 | 2 | |||
537 | 3 | # Ubuntu Testing Automation Harness | ||
538 | 4 | # Copyright 2012 Canonical Ltd. | ||
539 | 5 | |||
540 | 6 | # This program is free software: you can redistribute it and/or modify it | ||
541 | 7 | # under the terms of the GNU General Public License version 3, as published | ||
542 | 8 | # by the Free Software Foundation. | ||
543 | 9 | |||
544 | 10 | # This program is distributed in the hope that it will be useful, but | ||
545 | 11 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
546 | 12 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
547 | 13 | # PURPOSE. See the GNU General Public License for more details. | ||
548 | 14 | |||
549 | 15 | # You should have received a copy of the GNU General Public License along | ||
550 | 16 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
551 | 17 | |||
552 | 18 | """Create a VM and run a test.""" | ||
553 | 19 | |||
554 | 20 | |||
555 | 21 | import argparse | ||
556 | 22 | import logging | ||
557 | 23 | import sys | ||
558 | 24 | |||
559 | 25 | from utah.cleanup import cleanup | ||
560 | 26 | from utah.exceptions import UTAHException | ||
561 | 27 | from utah.group import check_user_group, print_group_error_message | ||
562 | 28 | from utah.provisioning.vm.vm import TinySQLiteInventory | ||
563 | 29 | from utah.run import ( | ||
564 | 30 | common_arguments, | ||
565 | 31 | run_tests, | ||
566 | 32 | configure_logging, | ||
567 | 33 | ReturnCodes, | ||
568 | 34 | ) | ||
569 | 35 | |||
570 | 36 | |||
571 | 37 | def get_parser(): | ||
572 | 38 | parser = argparse.ArgumentParser( | ||
573 | 39 | description=('Create a virtual machine ' | ||
574 | 40 | 'and run a UTAH runlist there.'), | ||
575 | 41 | epilog=("For example:\n" | ||
576 | 42 | "Provision a VM using a precise server image " | ||
577 | 43 | "with i386 architecture and run the two given runlists\n" | ||
578 | 44 | "\t%(prog)s -s precise -t server -a i386 \\\n" | ||
579 | 45 | "\t\t/usr/share/utah/client/examples/master.run \\\n" | ||
580 | 46 | "\t\t'http://people.canonical.com/~max/max_test.run'"), | ||
581 | 47 | formatter_class=argparse.RawDescriptionHelpFormatter) | ||
582 | 48 | return common_arguments(parser) | ||
583 | 49 | |||
584 | 50 | |||
585 | 51 | def run_test_vm(args=None): | ||
586 | 52 | if args is None: | ||
587 | 53 | args = get_parser().parse_args() | ||
588 | 54 | |||
589 | 55 | if not check_user_group(): | ||
590 | 56 | print_group_error_message(__file__) | ||
591 | 57 | sys.exit(ReturnCodes.GROUP_ERROR) | ||
592 | 58 | |||
593 | 59 | locallogs = [] | ||
594 | 60 | exitstatus = ReturnCodes.SUCCESS | ||
595 | 61 | machine = None | ||
596 | 62 | |||
597 | 63 | configure_logging(args.debug) | ||
598 | 64 | |||
599 | 65 | try: | ||
600 | 66 | inventory = TinySQLiteInventory() | ||
601 | 67 | kw = {} | ||
602 | 68 | for arg in ['arch', 'series']: | ||
603 | 69 | value = getattr(args, arg) | ||
604 | 70 | if value is not None: | ||
605 | 71 | kw[arg] = value | ||
606 | 72 | if args.type is not None: | ||
607 | 73 | kw.update([('installtype', args.type)]) | ||
608 | 74 | machine = inventory.request(clean=(not args.no_destroy), | ||
609 | 75 | debug=args.debug, new=True, | ||
610 | 76 | dlpercentincrement=10, **kw) | ||
611 | 77 | exitstatus, locallogs = run_tests(args, machine) | ||
612 | 78 | |||
613 | 79 | except UTAHException as error: | ||
614 | 80 | sys.stderr.write('Exception: ' + str(error)) | ||
615 | 81 | exitstatus = ReturnCodes.UTAH_EXCEPTION_ERROR | ||
616 | 82 | except Exception: | ||
617 | 83 | logging.exception('Unhandled error in UTAH') | ||
618 | 84 | exitstatus = ReturnCodes.UNHANDLED_ERROR | ||
619 | 85 | finally: | ||
620 | 86 | if not args.no_destroy and machine is not None: | ||
621 | 87 | try: | ||
622 | 88 | machine.destroy() | ||
623 | 89 | except UTAHException as error: | ||
624 | 90 | sys.stderr.write('Failed to destroy machine: ' + str(error)) | ||
625 | 91 | finally: | ||
626 | 92 | try: | ||
627 | 93 | inventory.destroy(machine.machineid) | ||
628 | 94 | except UTAHException as error: | ||
629 | 95 | sys.stderr.write('Failed to update inventory: ' | ||
630 | 96 | + str(error)) | ||
631 | 97 | finally: | ||
632 | 98 | del machine | ||
633 | 99 | if len(locallogs) != 0: | ||
634 | 100 | print('Test logs copied to the following files:') | ||
635 | 101 | print("\t" + "\n\t".join(locallogs)) | ||
636 | 102 | |||
637 | 103 | sys.exit(exitstatus) | ||
638 | 104 | |||
639 | 105 | |||
640 | 106 | if __name__ == '__main__': | ||
641 | 107 | logging.warning('This script is deprecated; please use run_utah_tests.py') | ||
642 | 108 | logging.warning('The same command line arguments should work there, i.e.:') | ||
643 | 109 | argv = list(sys.argv) | ||
644 | 110 | argv[0] = 'run_utah_tests.py' | ||
645 | 111 | logging.warning(' '.join(argv)) | ||
646 | 112 | try: | ||
647 | 113 | run_test_vm() | ||
648 | 114 | finally: | ||
649 | 115 | cleanup.run() | ||
650 | 116 | 0 | ||
651 | === modified file 'examples/run_utah_tests.py' | |||
652 | --- examples/run_utah_tests.py 2013-04-25 12:29:33 +0000 | |||
653 | +++ examples/run_utah_tests.py 2013-05-01 21:24:29 +0000 | |||
654 | @@ -20,27 +20,31 @@ | |||
655 | 20 | 20 | ||
656 | 21 | import argparse | 21 | import argparse |
657 | 22 | import logging | 22 | import logging |
658 | 23 | import os | ||
659 | 23 | import sys | 24 | import sys |
660 | 25 | |||
661 | 24 | from traceback import format_exception | 26 | from traceback import format_exception |
662 | 25 | 27 | ||
663 | 26 | import utah | 28 | import utah |
664 | 29 | |||
665 | 27 | from utah import config | 30 | from utah import config |
666 | 28 | from utah.cleanup import cleanup | 31 | from utah.cleanup import cleanup |
667 | 32 | from utah.exceptions import UTAHException | ||
668 | 29 | from utah.group import check_user_group, print_group_error_message | 33 | from utah.group import check_user_group, print_group_error_message |
669 | 34 | from utah.provisioning.baremetal.bamboofeeder import BambooFeederMachine | ||
670 | 35 | from utah.provisioning.baremetal.cobbler import CobblerMachine | ||
671 | 36 | from utah.provisioning.baremetal.inventory import \ | ||
672 | 37 | ManualBaremetalSQLiteInventory | ||
673 | 38 | from utah.provisioning.ssh import ProvisionedMachine | ||
674 | 39 | from utah.provisioning.vm.vm import TinySQLiteInventory | ||
675 | 30 | from utah.run import ( | 40 | from utah.run import ( |
676 | 31 | common_arguments, | ||
677 | 32 | custom_arguments, | ||
678 | 33 | file_arguments, | ||
679 | 34 | name_argument, | ||
680 | 35 | virtual_arguments, | ||
681 | 36 | configure_logging, | 41 | configure_logging, |
682 | 42 | master_runlist_argument, | ||
683 | 37 | run_tests, | 43 | run_tests, |
684 | 38 | ReturnCodes, | 44 | ReturnCodes, |
685 | 39 | ) | 45 | ) |
686 | 40 | from utah.timeout import timeout, UTAHTimeout | 46 | from utah.timeout import timeout, UTAHTimeout |
690 | 41 | from run_install_test import run_install_test | 47 | from utah.url import url_argument |
688 | 42 | from utah.provisioning.ssh import ProvisionedMachine | ||
689 | 43 | from utah.exceptions import UTAHException | ||
691 | 44 | 48 | ||
692 | 45 | 49 | ||
693 | 46 | def get_parser(): | 50 | def get_parser(): |
694 | @@ -57,75 +61,159 @@ | |||
695 | 57 | formatter_class=argparse.RawDescriptionHelpFormatter) | 61 | formatter_class=argparse.RawDescriptionHelpFormatter) |
696 | 58 | parser.add_argument('-m', '--machinetype', metavar='MACHINETYPE', | 62 | parser.add_argument('-m', '--machinetype', metavar='MACHINETYPE', |
697 | 59 | choices=('physical', 'virtual'), | 63 | choices=('physical', 'virtual'), |
699 | 60 | help='Type of machine to provision (%(choices)s)') | 64 | default=config.machinetype, |
700 | 65 | help='Type of machine to provision (%(choices)s) ' | ||
701 | 66 | '(Default is %(default)s)') | ||
702 | 61 | parser.add_argument('-v', '--variant', | 67 | parser.add_argument('-v', '--variant', |
703 | 68 | default=config.variant, | ||
704 | 62 | help='Variant of architecture, i.e., armel, armhf') | 69 | help='Variant of architecture, i.e., armel, armhf') |
705 | 63 | parser.add_argument('--skip-provisioning', action='store_true', | 70 | parser.add_argument('--skip-provisioning', action='store_true', |
713 | 64 | help=('Reuse a system that is already provisioned ' | 71 | help='Reuse a system that is already provisioned ' |
714 | 65 | '(name argument must be passed)')) | 72 | '(name argument must be passed)') |
715 | 66 | parser = common_arguments(parser) | 73 | parser.add_argument('runlist', metavar='runlist', |
716 | 67 | parser = custom_arguments(parser) | 74 | type=master_runlist_argument, |
717 | 68 | parser = file_arguments(parser) | 75 | help='URLs of runlist files to run') |
718 | 69 | parser = name_argument(parser) | 76 | parser.add_argument('-s', '--series', metavar='SERIES', |
719 | 70 | parser = virtual_arguments(parser) | 77 | choices=config.serieschoices, |
720 | 78 | default=config.series, | ||
721 | 79 | help='Series to use for installation (%(choices)s) ' | ||
722 | 80 | '(Default is %(default)s)') | ||
723 | 81 | parser.add_argument('-t', '--type', metavar='TYPE', | ||
724 | 82 | choices=('desktop', 'server', 'mini', 'alternate'), | ||
725 | 83 | default=config.installtype, | ||
726 | 84 | help='Install type to use for installation ' | ||
727 | 85 | '(%(choices)s) (Default is %(default)s)') | ||
728 | 86 | parser.add_argument('-a', '--arch', metavar='ARCH', | ||
729 | 87 | choices=('i386', 'amd64', 'arm'), | ||
730 | 88 | default=config.arch, | ||
731 | 89 | help='Architecture to use for installation ' | ||
732 | 90 | '(%(choices)s) (Default is %(default)s)') | ||
733 | 91 | parser.add_argument('-n', '--no-destroy', action='store_true', | ||
734 | 92 | help='Preserve VM after tests have run') | ||
735 | 93 | parser.add_argument('-d', '--debug', action='store_true', | ||
736 | 94 | help='Enable debug logging') | ||
737 | 95 | parser.add_argument('-j', '--json', action='store_true', | ||
738 | 96 | help='Enable json logging (default is YAML)') | ||
739 | 97 | parser.add_argument('-f', '--files', action='append', | ||
740 | 98 | help='File or directory to copy from test system ') | ||
741 | 99 | parser.add_argument('-o', '--outdir', | ||
742 | 100 | help=('Directory to store locally copied files ' | ||
743 | 101 | '(Default is {}/machine-name)' | ||
744 | 102 | .format(config.logpath))) | ||
745 | 103 | parser.add_argument('--dumplogs', action='store_true', | ||
746 | 104 | help='Write client output logs to standard out') | ||
747 | 105 | parser.add_argument('--outputpreseed', action='store_true', | ||
748 | 106 | help='Copy preseed to logs directory and list as ' | ||
749 | 107 | 'log file in output') | ||
750 | 108 | parser.add_argument('-i', '--image', type=url_argument, | ||
751 | 109 | default=config.image, | ||
752 | 110 | help='Image/ISO file to use for installation') | ||
753 | 111 | parser.add_argument('-p', '--preseed', type=url_argument, | ||
754 | 112 | default=config.preseed, | ||
755 | 113 | help='Preseed file to use for installation') | ||
756 | 114 | parser.add_argument('-b', '--boot', | ||
757 | 115 | default=config.boot, | ||
758 | 116 | help='Boot arguments for initial installation') | ||
759 | 117 | parser.add_argument('--rewrite', | ||
760 | 118 | choices=('all', 'minimal', 'casperonly', 'none'), | ||
761 | 119 | default=config.rewrite, | ||
762 | 120 | help='Set level of automatic configuration rewriting ' | ||
763 | 121 | '(Default is %(default)s)') | ||
764 | 122 | parser.add_argument('-k', '--kernel', type=url_argument, | ||
765 | 123 | default=config.kernel, | ||
766 | 124 | help='Kernel file to use for installation') | ||
767 | 125 | parser.add_argument('-r', '--initrd', type=url_argument, | ||
768 | 126 | default=config.initrd, | ||
769 | 127 | help='InitRD file to use for installation') | ||
770 | 128 | parser.add_argument('--name', | ||
771 | 129 | default=config.name, | ||
772 | 130 | help='Name of machine to provision') | ||
773 | 131 | parser.add_argument('-e', '--emulator', | ||
774 | 132 | default=config.emulator, | ||
775 | 133 | help='Emulator to use (kvm and qemu are supported, ' | ||
776 | 134 | 'kvm will be favored if available)') | ||
777 | 135 | parser.add_argument('-x', '--xml', type=url_argument, | ||
778 | 136 | default=config.xml, | ||
779 | 137 | help='XML VM definition file ' | ||
780 | 138 | '(Default is %(default)s)') | ||
781 | 139 | parser.add_argument('-g', '--gigabytes', action='append', | ||
782 | 140 | default=config.disksizes, | ||
783 | 141 | help='Size in gigabytes of virtual disk, ' | ||
784 | 142 | 'specify more than once for multiple disks ' | ||
785 | 143 | '(Default is %(default)s)') | ||
786 | 144 | parser.add_argument('--diskbus', metavar='DISKBUS', | ||
787 | 145 | choices=('virtio', 'sata', 'ide'), | ||
788 | 146 | default=config.diskbus, | ||
789 | 147 | help='Disk bus to use for customvm installation ' | ||
790 | 148 | '(%(choices)s) (Default is %(default)s)') | ||
791 | 71 | return parser | 149 | return parser |
792 | 72 | 150 | ||
793 | 73 | 151 | ||
794 | 152 | def _get_machine(args): | ||
795 | 153 | if args.skip_provisioning: | ||
796 | 154 | # TBD: Inventory should be used to verify machine | ||
797 | 155 | # is not running other tests | ||
798 | 156 | machine = ProvisionedMachine(name=args.name) | ||
799 | 157 | else: | ||
800 | 158 | kw = {'clean': (not args.no_destroy), | ||
801 | 159 | 'new': True, | ||
802 | 160 | } | ||
803 | 161 | kw['arch'] = args.arch | ||
804 | 162 | kw['boot'] = args.boot | ||
805 | 163 | kw['debug'] = args.debug | ||
806 | 164 | kw['image'] = args.image | ||
807 | 165 | kw['initrd'] = args.initrd | ||
808 | 166 | kw['kernel'] = args.kernel | ||
809 | 167 | kw['name'] = args.name | ||
810 | 168 | kw['preseed'] = args.preseed | ||
811 | 169 | kw['rewrite'] = args.rewrite | ||
812 | 170 | kw['series'] = args.series | ||
813 | 171 | kw['xml'] = args.xml | ||
814 | 172 | kw['installtype'] = args.type | ||
815 | 173 | if args.machinetype == 'physical': | ||
816 | 174 | if 'arm' in args.arch: | ||
817 | 175 | inventory = ManualBaremetalSQLiteInventory( | ||
818 | 176 | db=os.path.join('~', '.utah-bamboofeeder-inventory'), | ||
819 | 177 | lockfile=os.path.join('~', '.utah-bamboofeeder-lock')) | ||
820 | 178 | kw['machinetype'] = BambooFeederMachine | ||
821 | 179 | else: | ||
822 | 180 | inventory = ManualBaremetalSQLiteInventory() | ||
823 | 181 | kw['machinetype'] = CobblerMachine | ||
824 | 182 | else: | ||
825 | 183 | inventory = TinySQLiteInventory() | ||
826 | 184 | kw['diskbus'] = args.diskbus | ||
827 | 185 | kw['emulator'] = args.emulator | ||
828 | 186 | kw['disksizes'] = args.gigabytes | ||
829 | 187 | machine = inventory.request(**kw) | ||
830 | 188 | return machine | ||
831 | 189 | |||
832 | 190 | |||
833 | 74 | def run_utah_tests(args=None): | 191 | def run_utah_tests(args=None): |
834 | 75 | if args is None: | 192 | if args is None: |
835 | 76 | args = get_parser().parse_args() | 193 | args = get_parser().parse_args() |
836 | 77 | 194 | ||
837 | 78 | if not check_user_group(): | 195 | if not check_user_group(): |
838 | 79 | print_group_error_message(__file__) | 196 | print_group_error_message(__file__) |
845 | 80 | sys.exit(ReturnCodes.GROUP_ERROR) | 197 | return ReturnCodes.GROUP_ERROR |
840 | 81 | |||
841 | 82 | if args.machinetype is None: | ||
842 | 83 | machinetype = config.machinetype | ||
843 | 84 | else: | ||
844 | 85 | machinetype = args.machinetype | ||
846 | 86 | 198 | ||
847 | 87 | configure_logging(args.debug) | 199 | configure_logging(args.debug) |
848 | 88 | logging.info('UTAH version: %s', utah.__version__) | 200 | logging.info('UTAH version: %s', utah.__version__) |
849 | 89 | 201 | ||
879 | 90 | # Default is now CustomVM | 202 | exitstatus = ReturnCodes.SUCCESS |
880 | 91 | function = run_install_test | 203 | locallogs = [] |
881 | 92 | 204 | ||
882 | 93 | if args.skip_provisioning: | 205 | exitstatus, locallogs = run_tests(args, _get_machine(args)) |
883 | 94 | def run_provisioned_tests(args): | 206 | if len(locallogs) > 0: |
884 | 95 | """Run test cases in a provisioned machine.""" | 207 | print('Test logs copied to the following files:') |
885 | 96 | locallogs = [] | 208 | print("\t" + "\n\t".join(locallogs)) |
886 | 97 | try: | 209 | |
887 | 98 | # TBD: Inventory should be used to verify machine | 210 | return(exitstatus) |
888 | 99 | # is not running other tests | 211 | |
860 | 100 | machine = ProvisionedMachine(name=args.name) | ||
861 | 101 | exitstatus, locallogs = run_tests(args, machine) | ||
862 | 102 | finally: | ||
863 | 103 | if len(locallogs) != 0: | ||
864 | 104 | print('Test logs copied to the following files:') | ||
865 | 105 | print("\t" + "\n\t".join(locallogs)) | ||
866 | 106 | sys.exit(ReturnCodes.SUCCESS) | ||
867 | 107 | |||
868 | 108 | function = run_provisioned_tests | ||
869 | 109 | if args.arch is not None and 'arm' in args.arch: | ||
870 | 110 | # If arch is arm, use BambooFeederMachine | ||
871 | 111 | from run_test_bamboo_feeder import run_test_bamboo_feeder | ||
872 | 112 | function = run_test_bamboo_feeder | ||
873 | 113 | elif machinetype == 'physical': | ||
874 | 114 | # If machinetype is physical but arch isn't arm, use CobblerMachine | ||
875 | 115 | from run_test_cobbler import run_test_cobbler | ||
876 | 116 | function = run_test_cobbler | ||
877 | 117 | |||
878 | 118 | function(args=args) | ||
889 | 119 | 212 | ||
890 | 120 | if __name__ == '__main__': | 213 | if __name__ == '__main__': |
891 | 121 | try: | 214 | try: |
892 | 122 | try: | 215 | try: |
899 | 123 | if isinstance(config.jobtimeout, int): | 216 | exitstatus = timeout(config.jobtimeout, run_utah_tests) |
894 | 124 | timeout(config.jobtimeout, run_utah_tests) | ||
895 | 125 | else: | ||
896 | 126 | run_utah_tests() | ||
897 | 127 | except AttributeError: | ||
898 | 128 | run_utah_tests() | ||
900 | 129 | finally: | 217 | finally: |
901 | 130 | cleanup.run() | 218 | cleanup.run() |
902 | 131 | except UTAHTimeout as exception: | 219 | except UTAHTimeout as exception: |
903 | @@ -138,3 +226,4 @@ | |||
904 | 138 | sys.stderr.write('Unhandled error in UTAH:\n{}\n' | 226 | sys.stderr.write('Unhandled error in UTAH:\n{}\n' |
905 | 139 | .format(''.join(format_exception(*sys.exc_info())))) | 227 | .format(''.join(format_exception(*sys.exc_info())))) |
906 | 140 | sys.exit(ReturnCodes.UNHANDLED_ERROR) | 228 | sys.exit(ReturnCodes.UNHANDLED_ERROR) |
907 | 229 | sys.exit(exitstatus) | ||
908 | 141 | 230 | ||
909 | === modified file 'tests/test_run.py' | |||
910 | --- tests/test_run.py 2013-04-23 17:17:44 +0000 | |||
911 | +++ tests/test_run.py 2013-05-01 21:24:29 +0000 | |||
912 | @@ -134,10 +134,9 @@ | |||
913 | 134 | logs = [] | 134 | logs = [] |
914 | 135 | args = Mock() | 135 | args = Mock() |
915 | 136 | args.outputpreseed = True | 136 | args.outputpreseed = True |
916 | 137 | |||
917 | 138 | machine = Mock() | 137 | machine = Mock() |
918 | 139 | machine.configure_mock(name='name', finalpreseed='/bad file name') | 138 | machine.configure_mock(name='name', finalpreseed='/bad file name') |
920 | 140 | _copy_preseed(machine, machine, logs) | 139 | _copy_preseed(machine, args, logs) |
921 | 141 | self.assertEqual(0, len(logs)) | 140 | self.assertEqual(0, len(logs)) |
922 | 142 | self.assertTrue(warning.called) | 141 | self.assertTrue(warning.called) |
923 | 143 | call_args, _call_kwargs = warning.call_args | 142 | call_args, _call_kwargs = warning.call_args |
924 | @@ -148,8 +147,10 @@ | |||
925 | 148 | def test_copy_preseed_good(self, copyfile): | 147 | def test_copy_preseed_good(self, copyfile): |
926 | 149 | """Ensure _copy_preseed works for good data.""" | 148 | """Ensure _copy_preseed works for good data.""" |
927 | 150 | logs = [] | 149 | logs = [] |
928 | 150 | args = Mock() | ||
929 | 151 | args.outputpreseed = True | ||
930 | 151 | machine = Mock() | 152 | machine = Mock() |
931 | 152 | machine.configure_mock(name='name', finalpreseed='/bin/true') | 153 | machine.configure_mock(name='name', finalpreseed='/bin/true') |
933 | 153 | _copy_preseed(machine, machine, logs) | 154 | _copy_preseed(machine, args, logs) |
934 | 154 | self.assertEqual(1, len(logs)) | 155 | self.assertEqual(1, len(logs)) |
935 | 155 | self.assertTrue(copyfile.called) | 156 | self.assertTrue(copyfile.called) |
936 | 156 | 157 | ||
937 | === modified file 'utah/config.py' | |||
938 | --- utah/config.py 2013-04-04 14:55:25 +0000 | |||
939 | +++ utah/config.py 2013-05-01 21:24:29 +0000 | |||
940 | @@ -60,6 +60,8 @@ | |||
941 | 60 | boottimeout=90, | 60 | boottimeout=90, |
942 | 61 | # Time to wait between checking if system is available over ssh | 61 | # Time to wait between checking if system is available over ssh |
943 | 62 | checktimeout=15, | 62 | checktimeout=15, |
944 | 63 | # Default setting for whether to clean up after a test run | ||
945 | 64 | clean=True, | ||
946 | 63 | # Default log level to print to the console | 65 | # Default log level to print to the console |
947 | 64 | consoleloglevel=logging.WARNING, | 66 | consoleloglevel=logging.WARNING, |
948 | 65 | # Default debug setting | 67 | # Default debug setting |
949 | @@ -67,7 +69,7 @@ | |||
950 | 67 | # Command to download test images | 69 | # Command to download test images |
951 | 68 | dlcommand='dl-ubuntu-test-iso', | 70 | dlcommand='dl-ubuntu-test-iso', |
952 | 69 | # Percentage increment at which to report download updates | 71 | # Percentage increment at which to report download updates |
954 | 70 | dlpercentincrement=1, | 72 | dlpercentincrement=10, |
955 | 71 | # Number of times to retry image download | 73 | # Number of times to retry image download |
956 | 72 | dlretries=10, | 74 | dlretries=10, |
957 | 73 | # Default diskbus for VMs | 75 | # Default diskbus for VMs |
958 | @@ -93,14 +95,24 @@ | |||
959 | 93 | installtype='mini', | 95 | installtype='mini', |
960 | 94 | # Directory to store local images | 96 | # Directory to store local images |
961 | 95 | isodir='/var/cache/utah/iso', | 97 | isodir='/var/cache/utah/iso', |
962 | 98 | # Overall timeout for run_utah_tests | ||
963 | 99 | jobtimeout=None, | ||
964 | 96 | # Default kernel for installation | 100 | # Default kernel for installation |
965 | 97 | kernel=None, | 101 | kernel=None, |
966 | 98 | # Default location of log directory | 102 | # Default location of log directory |
967 | 99 | logpath=os.path.join('/', 'var', 'log', 'utah'), | 103 | logpath=os.path.join('/', 'var', 'log', 'utah'), |
968 | 104 | # Directory to hold non-temporary files (mostly for VM) | ||
969 | 105 | machinedir=None, | ||
970 | 100 | # Default machine ID | 106 | # Default machine ID |
971 | 101 | machineid=None, | 107 | machineid=None, |
972 | 108 | # Machine information object for physical machines | ||
973 | 109 | machineinfo=None, | ||
974 | 102 | # Default machine type | 110 | # Default machine type |
975 | 103 | machinetype='virtual', | 111 | machinetype='virtual', |
976 | 112 | # UUID for machine | ||
977 | 113 | machineuuid=None, | ||
978 | 114 | # List of mac addresses for VM | ||
979 | 115 | macs=[], | ||
980 | 104 | # Default machine name | 116 | # Default machine name |
981 | 105 | name=None, | 117 | name=None, |
982 | 106 | # Default setting of installing a new machine vs. using an existing one | 118 | # Default setting of installing a new machine vs. using an existing one |
983 | @@ -117,14 +129,22 @@ | |||
984 | 117 | outputpreseed=False, | 129 | outputpreseed=False, |
985 | 118 | # Directory where utah client and other needed packages reside | 130 | # Directory where utah client and other needed packages reside |
986 | 119 | packagedir=os.path.join('/', 'usr', 'share', 'utah'), | 131 | packagedir=os.path.join('/', 'usr', 'share', 'utah'), |
987 | 132 | # Command to use to power cycle machine | ||
988 | 133 | powercmd=None, | ||
989 | 120 | # Time to wait between power off and power on for physical systems | 134 | # Time to wait between power off and power on for physical systems |
990 | 121 | powertimeout=15, | 135 | powertimeout=15, |
991 | 136 | # Preboot for bamboo-feeder panda boards | ||
992 | 137 | preboot=None, | ||
993 | 138 | # Prefix for machine names | ||
994 | 139 | prefix='utah', | ||
995 | 122 | # Default preseed | 140 | # Default preseed |
996 | 123 | preseed=os.path.join('/', 'etc', 'utah', 'default-preseed.cfg'), | 141 | preseed=os.path.join('/', 'etc', 'utah', 'default-preseed.cfg'), |
997 | 124 | # Location of PXE configuration files | 142 | # Location of PXE configuration files |
998 | 125 | pxedir=os.path.join('/', 'var', 'lib', 'tftpboot', 'pxelinux.cfg'), | 143 | pxedir=os.path.join('/', 'var', 'lib', 'tftpboot', 'pxelinux.cfg'), |
999 | 126 | # libvirt URL for virtual machine creation | 144 | # libvirt URL for virtual machine creation |
1000 | 127 | qemupath='qemu:///system', | 145 | qemupath='qemu:///system', |
1001 | 146 | # default timeout between retry attempts | ||
1002 | 147 | retry_timeout=3, | ||
1003 | 128 | # Default setting for configuration rewriting | 148 | # Default setting for configuration rewriting |
1004 | 129 | rewrite='all', | 149 | rewrite='all', |
1005 | 130 | # Time to wait for client process to finish in run.py | 150 | # Time to wait for client process to finish in run.py |
1006 | @@ -140,17 +160,19 @@ | |||
1007 | 140 | 'quantal', | 160 | 'quantal', |
1008 | 141 | 'raring', | 161 | 'raring', |
1009 | 142 | ], | 162 | ], |
1010 | 163 | # sqlite database connection timeout | ||
1011 | 164 | # a value higher than the default is used to avoid db locking problems | ||
1012 | 165 | sqlite3_db_connection_timeout=30, | ||
1013 | 143 | # Default machine template | 166 | # Default machine template |
1014 | 144 | template=None, | 167 | template=None, |
1015 | 168 | # location of the jinja2 templates used by the provisionig module | ||
1016 | 169 | template_dir=os.path.join('/', 'usr', 'share', 'utah', 'templates'), | ||
1017 | 145 | # Directory to hold web-accessible files | 170 | # Directory to hold web-accessible files |
1018 | 146 | wwwdir=os.path.join('/', 'var', 'www', 'utah'), | 171 | wwwdir=os.path.join('/', 'var', 'www', 'utah'), |
1019 | 172 | # Default architecture variant (armel, armhd, non-pae, etc.) | ||
1020 | 173 | variant=None, | ||
1021 | 147 | # Default VM XML file | 174 | # Default VM XML file |
1022 | 148 | xml=os.path.join('/', 'etc', 'utah', 'default-vm.xml'), | 175 | xml=os.path.join('/', 'etc', 'utah', 'default-vm.xml'), |
1023 | 149 | # sqlite database connection timeout | ||
1024 | 150 | # a value higher than the default is used to avoid db locking problems | ||
1025 | 151 | sqlite3_db_connection_timeout=30, | ||
1026 | 152 | # location of the jinja2 templates used by the provisionig module | ||
1027 | 153 | template_dir=os.path.join('/', 'usr', 'share', 'utah', 'templates'), | ||
1028 | 154 | 176 | ||
1029 | 155 | install_steps=[ | 177 | install_steps=[ |
1030 | 156 | { | 178 | { |
1031 | @@ -208,9 +230,6 @@ | |||
1032 | 208 | 'timeout': 180, | 230 | 'timeout': 180, |
1033 | 209 | } | 231 | } |
1034 | 210 | ], | 232 | ], |
1035 | 211 | |||
1036 | 212 | # default timeout between retry attempts | ||
1037 | 213 | retry_timeout=3, | ||
1038 | 214 | ) | 233 | ) |
1039 | 215 | 234 | ||
1040 | 216 | # These depend on the local user/path, and need to be filtered out | 235 | # These depend on the local user/path, and need to be filtered out |
1041 | 217 | 236 | ||
1042 | === modified file 'utah/provisioning/baremetal/bamboofeeder.py' | |||
1043 | --- utah/provisioning/baremetal/bamboofeeder.py 2013-04-24 14:27:37 +0000 | |||
1044 | +++ utah/provisioning/baremetal/bamboofeeder.py 2013-05-01 21:24:29 +0000 | |||
1045 | @@ -40,8 +40,8 @@ | |||
1046 | 40 | 40 | ||
1047 | 41 | # TODO: raise more exceptions if ProcessRunner fails | 41 | # TODO: raise more exceptions if ProcessRunner fails |
1048 | 42 | # maybe get some easy way to do that like failok | 42 | # maybe get some easy way to do that like failok |
1051 | 43 | def __init__(self, machineinfo=None, name=None, preboot=None, *args, | 43 | def __init__(self, machineinfo=config.machineinfo, name=config.name, |
1052 | 44 | **kw): | 44 | preboot=config.preboot, *args, **kw): |
1053 | 45 | # TODO: respect rewrite setting | 45 | # TODO: respect rewrite setting |
1054 | 46 | if name is None: | 46 | if name is None: |
1055 | 47 | raise UTAHBMProvisioningException( | 47 | raise UTAHBMProvisioningException( |
1056 | @@ -55,23 +55,20 @@ | |||
1057 | 55 | name=name, **kw) | 55 | name=name, **kw) |
1058 | 56 | if self.inventory is not None: | 56 | if self.inventory is not None: |
1059 | 57 | self.cleanfunction(self.inventory.release, machine=self) | 57 | self.cleanfunction(self.inventory.release, machine=self) |
1060 | 58 | self._depcheck() | ||
1061 | 59 | if self.image is None: | 58 | if self.image is None: |
1062 | 60 | raise UTAHBMProvisioningException( | 59 | raise UTAHBMProvisioningException( |
1063 | 61 | 'Image file required for bamboo-feeder installation') | 60 | 'Image file required for bamboo-feeder installation') |
1064 | 61 | self._depcheck() | ||
1065 | 62 | self.ip = self._ipaddr(config.wwwiface) | 62 | self.ip = self._ipaddr(config.wwwiface) |
1066 | 63 | self.logger.debug('Configuring for %s with IP %s', | 63 | self.logger.debug('Configuring for %s with IP %s', |
1067 | 64 | config.wwwiface, self.ip) | 64 | config.wwwiface, self.ip) |
1068 | 65 | self._cmdlinesetup() | 65 | self._cmdlinesetup() |
1069 | 66 | imageurl = 'http://{}/utah/{}.img'.format(self.ip, self.name) | 66 | imageurl = 'http://{}/utah/{}.img'.format(self.ip, self.name) |
1070 | 67 | preenvurl = 'http://{}/utah/{}.preEnv'.format(self.ip, self.name) | 67 | preenvurl = 'http://{}/utah/{}.preEnv'.format(self.ip, self.name) |
1078 | 68 | if preboot is None: | 68 | self.preboot = (preboot or |
1079 | 69 | self.preboot = ('console=ttyO2,115200n8 imageurl={imageurl} ' | 69 | 'console=ttyO2,115200n8 imageurl={imageurl} ' |
1080 | 70 | 'bootcfg={preenvurl}'.format( | 70 | 'bootcfg={preenvurl}' |
1081 | 71 | imageurl=imageurl, preenvurl=preenvurl)) | 71 | .format(imageurl=imageurl, preenvurl=preenvurl)) |
1075 | 72 | else: | ||
1076 | 73 | # TODO: maybe make this automatically add needed options | ||
1077 | 74 | self.preboot = preboot | ||
1082 | 75 | self.logger.debug('Preboot setup:') | 72 | self.logger.debug('Preboot setup:') |
1083 | 76 | self.logger.debug(self.preboot) | 73 | self.logger.debug(self.preboot) |
1084 | 77 | self.logger.debug('BambooFeederMachine init finished') | 74 | self.logger.debug('BambooFeederMachine init finished') |
1085 | 78 | 75 | ||
1086 | === modified file 'utah/provisioning/baremetal/cobbler.py' | |||
1087 | --- utah/provisioning/baremetal/cobbler.py 2013-04-24 14:27:37 +0000 | |||
1088 | +++ utah/provisioning/baremetal/cobbler.py 2013-05-01 21:24:29 +0000 | |||
1089 | @@ -39,7 +39,8 @@ | |||
1090 | 39 | 39 | ||
1091 | 40 | # TODO: raise more exceptions if ProcessRunner fails | 40 | # TODO: raise more exceptions if ProcessRunner fails |
1092 | 41 | # maybe get some easy way to do that like failok | 41 | # maybe get some easy way to do that like failok |
1094 | 42 | def __init__(self, machineinfo=None, name=None, *args, **kw): | 42 | def __init__(self, machineinfo=config.machineinfo, name=config.name, |
1095 | 43 | *args, **kw): | ||
1096 | 43 | # TODO: support for reusing existing machines | 44 | # TODO: support for reusing existing machines |
1097 | 44 | if name is None: | 45 | if name is None: |
1098 | 45 | raise UTAHBMProvisioningException( | 46 | raise UTAHBMProvisioningException( |
1099 | @@ -49,7 +50,6 @@ | |||
1100 | 49 | 'No cobbler arguments given for machine creation') | 50 | 'No cobbler arguments given for machine creation') |
1101 | 50 | else: | 51 | else: |
1102 | 51 | self.machineinfo = machineinfo | 52 | self.machineinfo = machineinfo |
1103 | 52 | self.power = {} | ||
1104 | 53 | super(CobblerMachine, self).__init__(*args, machineinfo=machineinfo, | 53 | super(CobblerMachine, self).__init__(*args, machineinfo=machineinfo, |
1105 | 54 | name=name, **kw) | 54 | name=name, **kw) |
1106 | 55 | if self.inventory is not None: | 55 | if self.inventory is not None: |
1107 | 56 | 56 | ||
1108 | === modified file 'utah/provisioning/baremetal/power.py' | |||
1109 | --- utah/provisioning/baremetal/power.py 2013-04-04 13:19:16 +0000 | |||
1110 | +++ utah/provisioning/baremetal/power.py 2013-05-01 21:24:29 +0000 | |||
1111 | @@ -33,15 +33,15 @@ | |||
1112 | 33 | 33 | ||
1113 | 34 | """ | 34 | """ |
1114 | 35 | 35 | ||
1116 | 36 | def __init__(self, machineinfo=None, powercmd=None, *args, **kw): | 36 | def __init__(self, machineinfo=config.machineinfo, |
1117 | 37 | powercmd=config.powercmd, *args, **kw): | ||
1118 | 37 | """Store power control info for later use.""" | 38 | """Store power control info for later use.""" |
1119 | 38 | if machineinfo is not None: | 39 | if machineinfo is not None: |
1120 | 39 | self.power = {} | 40 | self.power = {} |
1121 | 40 | for item in machineinfo: | 41 | for item in machineinfo: |
1122 | 41 | if 'power' in item: | 42 | if 'power' in item: |
1123 | 42 | self.power[item] = machineinfo[item] | 43 | self.power[item] = machineinfo[item] |
1126 | 43 | if powercmd is not None: | 44 | self.powercmd = powercmd |
1125 | 44 | self.powercmd = powercmd | ||
1127 | 45 | super(PowerMixin, self).__init__(*args, **kw) | 45 | super(PowerMixin, self).__init__(*args, **kw) |
1128 | 46 | 46 | ||
1129 | 47 | def powercommand(self): | 47 | def powercommand(self): |
1130 | 48 | 48 | ||
1131 | === modified file 'utah/provisioning/provisioning.py' | |||
1132 | --- utah/provisioning/provisioning.py 2013-04-24 14:27:37 +0000 | |||
1133 | +++ utah/provisioning/provisioning.py 2013-05-01 21:24:29 +0000 | |||
1134 | @@ -64,12 +64,15 @@ | |||
1135 | 64 | 64 | ||
1136 | 65 | """ | 65 | """ |
1137 | 66 | 66 | ||
1144 | 67 | def __init__(self, arch=None, boot=None, clean=True, debug=False, | 67 | def __init__(self, arch=config.arch, boot=config.boot, clean=True, |
1145 | 68 | directory=None, image=None, dlpercentincrement=1, | 68 | debug=False, image=config.image, |
1146 | 69 | initrd=None, installtype=None, inventory=None, kernel=None, | 69 | dlpercentincrement=config.dlpercentincrement, |
1147 | 70 | machineid=None, machineuuid=None, name=None, new=False, | 70 | initrd=config.initrd, installtype=config.installtype, |
1148 | 71 | prefix='utah', preseed=None, rewrite=None, series=None, | 71 | inventory=None, kernel=config.kernel, |
1149 | 72 | template=None, xml=None): | 72 | machineid=config.machineid, machineuuid=config.machineuuid, |
1150 | 73 | name=config.name, new=False, preseed=config.preseed, | ||
1151 | 74 | rewrite=config.rewrite, series=config.series, | ||
1152 | 75 | template=config.template, xml=config.xml): | ||
1153 | 73 | """Initialize the object representing the machine. | 76 | """Initialize the object representing the machine. |
1154 | 74 | 77 | ||
1155 | 75 | One of these groups of arguments should be included: | 78 | One of these groups of arguments should be included: |
1156 | @@ -85,9 +88,6 @@ | |||
1157 | 85 | Other arguments: | 88 | Other arguments: |
1158 | 86 | clean: Enable cleanup functions. | 89 | clean: Enable cleanup functions. |
1159 | 87 | debug: Enable debug logging. | 90 | debug: Enable debug logging. |
1160 | 88 | directory: Where the machine's files go. Should be persistent for | ||
1161 | 89 | VMs, temporary is fine for installation-only files, like those | ||
1162 | 90 | used to install a physical machine using another method. | ||
1163 | 91 | dlpercentincrement: How often to log download updates to INFO | 91 | dlpercentincrement: How often to log download updates to INFO |
1164 | 92 | (All updates logged to DEBUG) | 92 | (All updates logged to DEBUG) |
1165 | 93 | inventory: Inventory object managing the machine; used for cleanup | 93 | inventory: Inventory object managing the machine; used for cleanup |
1166 | @@ -98,7 +98,6 @@ | |||
1167 | 98 | supplied. | 98 | supplied. |
1168 | 99 | new: Request a new machine (or a reinstall if a specific machine | 99 | new: Request a new machine (or a reinstall if a specific machine |
1169 | 100 | was requested.) | 100 | was requested.) |
1170 | 101 | prefix: prefix for automatically named machines. | ||
1171 | 102 | rewrite: How much to alter supplied preseed and xml files. | 101 | rewrite: How much to alter supplied preseed and xml files. |
1172 | 103 | all: everything we need for an automated install | 102 | all: everything we need for an automated install |
1173 | 104 | minimal: insert latecommand into preseed | 103 | minimal: insert latecommand into preseed |
1174 | @@ -117,45 +116,27 @@ | |||
1175 | 117 | """ | 116 | """ |
1176 | 118 | # TODO: Make this work right with super at some point. | 117 | # TODO: Make this work right with super at some point. |
1177 | 119 | # TODO: Consider a global temp file creator, maybe as part of install. | 118 | # TODO: Consider a global temp file creator, maybe as part of install. |
1178 | 119 | # TODO: Make everything use config.dlpercentincrement instead of | ||
1179 | 120 | # passing it around all the time | ||
1180 | 121 | self.arch = arch | ||
1181 | 122 | self.boot = boot | ||
1182 | 123 | self.clean = clean | ||
1183 | 120 | self.debug = debug | 124 | self.debug = debug |
1184 | 121 | self.dlpercentincrement = dlpercentincrement | 125 | self.dlpercentincrement = dlpercentincrement |
1185 | 126 | self.installtype = installtype | ||
1186 | 122 | self.inventory = inventory | 127 | self.inventory = inventory |
1187 | 123 | self.machineid = machineid | 128 | self.machineid = machineid |
1188 | 124 | self.new = new | 129 | self.new = new |
1190 | 125 | self.prefix = prefix | 130 | self.rewrite = rewrite |
1191 | 131 | self.series = series | ||
1192 | 126 | self.template = template | 132 | self.template = template |
1193 | 133 | self.uuid = uuid | ||
1194 | 127 | 134 | ||
1195 | 128 | self.boottimeout = config.boottimeout | 135 | self.boottimeout = config.boottimeout |
1196 | 129 | 136 | ||
1197 | 130 | if clean is None: | ||
1198 | 131 | self.clean = True | ||
1199 | 132 | else: | ||
1200 | 133 | self.clean = clean | ||
1201 | 134 | |||
1202 | 135 | # TODO: Move namesetup into vm | 137 | # TODO: Move namesetup into vm |
1203 | 136 | self._namesetup(name) | 138 | self._namesetup(name) |
1204 | 137 | 139 | ||
1205 | 138 | if arch is None: | ||
1206 | 139 | self.arch = config.arch | ||
1207 | 140 | else: | ||
1208 | 141 | self.arch = arch | ||
1209 | 142 | if boot is None: | ||
1210 | 143 | self.boot = config.boot | ||
1211 | 144 | else: | ||
1212 | 145 | self.boot = boot | ||
1213 | 146 | if installtype is None: | ||
1214 | 147 | self.installtype = config.installtype | ||
1215 | 148 | else: | ||
1216 | 149 | self.installtype = installtype | ||
1217 | 150 | if rewrite is None: | ||
1218 | 151 | self.rewrite = config.rewrite | ||
1219 | 152 | else: | ||
1220 | 153 | self.rewrite = rewrite | ||
1221 | 154 | if series is None: | ||
1222 | 155 | self.series = config.series | ||
1223 | 156 | else: | ||
1224 | 157 | self.series = series | ||
1225 | 158 | |||
1226 | 159 | if machineuuid is None: | 140 | if machineuuid is None: |
1227 | 160 | self.uuid = str(uuid.uuid4()) | 141 | self.uuid = str(uuid.uuid4()) |
1228 | 161 | else: | 142 | else: |
1229 | @@ -165,20 +146,18 @@ | |||
1230 | 165 | self.active = False | 146 | self.active = False |
1231 | 166 | self._loggersetup() | 147 | self._loggersetup() |
1232 | 167 | 148 | ||
1233 | 168 | if preseed is None: | ||
1234 | 169 | preseed = config.preseed | ||
1235 | 170 | |||
1236 | 171 | fileargs = ['initrd', 'kernel', 'preseed', 'xml'] | 149 | fileargs = ['initrd', 'kernel', 'preseed', 'xml'] |
1237 | 172 | 150 | ||
1238 | 173 | if image is None: | 151 | if image is None: |
1239 | 174 | image = config.image | ||
1240 | 175 | if image is None or image.endswith('.iso'): | ||
1241 | 176 | self.image = ISO(arch=arch, | 152 | self.image = ISO(arch=arch, |
1244 | 177 | dlpercentincrement=self.dlpercentincrement, | 153 | dlpercentincrement=dlpercentincrement, |
1243 | 178 | image=image, | ||
1245 | 179 | installtype=installtype, | 154 | installtype=installtype, |
1246 | 180 | logger=self.logger, | 155 | logger=self.logger, |
1247 | 181 | series=series) | 156 | series=series) |
1248 | 157 | elif image.endswith('.iso'): | ||
1249 | 158 | self.image = ISO(dlpercentincrement=dlpercentincrement, | ||
1250 | 159 | image=image, | ||
1251 | 160 | logger=self.logger) | ||
1252 | 182 | else: | 161 | else: |
1253 | 183 | fileargs.append('image') | 162 | fileargs.append('image') |
1254 | 184 | 163 | ||
1255 | @@ -186,8 +165,6 @@ | |||
1256 | 186 | # Ensure every file/url type argument is available locally | 165 | # Ensure every file/url type argument is available locally |
1257 | 187 | arg = locals()[item] | 166 | arg = locals()[item] |
1258 | 188 | if arg is None: | 167 | if arg is None: |
1259 | 189 | arg = getattr(config, item) | ||
1260 | 190 | if arg is None: | ||
1261 | 191 | setattr(self, item, None) | 168 | setattr(self, item, None) |
1262 | 192 | else: | 169 | else: |
1263 | 193 | if arg.startswith('~'): | 170 | if arg.startswith('~'): |
1264 | @@ -199,6 +176,7 @@ | |||
1265 | 199 | 176 | ||
1266 | 200 | self.percent = 0 | 177 | self.percent = 0 |
1267 | 201 | self.logger.info('Preparing %s: %s', item, path) | 178 | self.logger.info('Preparing %s: %s', item, path) |
1268 | 179 | # TODO: implement download utility function and use it here | ||
1269 | 202 | filename = urllib.urlretrieve(path, | 180 | filename = urllib.urlretrieve(path, |
1270 | 203 | reporthook=self.dldisplay)[0] | 181 | reporthook=self.dldisplay)[0] |
1271 | 204 | setattr(self, item, filename) | 182 | setattr(self, item, filename) |
1272 | 205 | 183 | ||
1273 | === modified file 'utah/provisioning/vm/vm.py' | |||
1274 | --- utah/provisioning/vm/vm.py 2013-04-24 14:31:11 +0000 | |||
1275 | +++ utah/provisioning/vm/vm.py 2013-05-01 21:24:29 +0000 | |||
1276 | @@ -134,9 +134,10 @@ | |||
1277 | 134 | """Install a VM from an image using libvirt direct kernel booting.""" | 134 | """Install a VM from an image using libvirt direct kernel booting.""" |
1278 | 135 | 135 | ||
1279 | 136 | # TODO: probably remove parameters from the private methods | 136 | # TODO: probably remove parameters from the private methods |
1283 | 137 | def __init__(self, directory=None, diskbus=None, disksizes=None, | 137 | def __init__(self, directory=config.machinedir, diskbus=config.diskbus, |
1284 | 138 | emulator=None, machineid=None, macs=None, name=None, | 138 | disksizes=config.disksizes, emulator=config.emulator, |
1285 | 139 | prefix='utah', *args, **kw): | 139 | machineid=config.machineid, macs=config.macs, |
1286 | 140 | name=config.name, prefix=config.prefix, *args, **kw): | ||
1287 | 140 | # Make sure that no other virtualization solutions are running | 141 | # Make sure that no other virtualization solutions are running |
1288 | 141 | # TODO: see if this is needed for qemu or just kvm | 142 | # TODO: see if this is needed for qemu or just kvm |
1289 | 142 | process_checker = ProcessChecker() | 143 | process_checker = ProcessChecker() |
1290 | @@ -146,16 +147,11 @@ | |||
1291 | 146 | message = process_checker.get_error_message(app) | 147 | message = process_checker.get_error_message(app) |
1292 | 147 | raise UTAHVMProvisioningException(message) | 148 | raise UTAHVMProvisioningException(message) |
1293 | 148 | 149 | ||
1304 | 149 | if diskbus is None: | 150 | self.diskbus = diskbus |
1305 | 150 | self.diskbus = config.diskbus | 151 | self.disksizes = disksizes |
1306 | 151 | else: | 152 | self.emulator = emulator |
1307 | 152 | self.diskbus = diskbus | 153 | self.macs = macs |
1308 | 153 | if disksizes is None: | 154 | self.prefix = prefix |
1299 | 154 | disksizes = config.disksizes | ||
1300 | 155 | if disksizes is None: | ||
1301 | 156 | self.disksizes = [8] | ||
1302 | 157 | else: | ||
1303 | 158 | self.disksizes = disksizes | ||
1309 | 159 | self.disks = [] | 155 | self.disks = [] |
1310 | 160 | if name is None: | 156 | if name is None: |
1311 | 161 | autoname = True | 157 | autoname = True |
1312 | @@ -178,34 +174,21 @@ | |||
1313 | 178 | self._loggerunsetup() | 174 | self._loggerunsetup() |
1314 | 179 | self._loggersetup() | 175 | self._loggersetup() |
1315 | 180 | self._cmdlinesetup() | 176 | self._cmdlinesetup() |
1319 | 181 | if emulator is None: | 177 | if self.emulator is None: |
1317 | 182 | emulator = config.emulator | ||
1318 | 183 | if emulator is None: | ||
1320 | 184 | if self._supportsdomaintype('kvm'): | 178 | if self._supportsdomaintype('kvm'): |
1321 | 185 | self.logger.info( | 179 | self.logger.info( |
1322 | 186 | 'Setting type to kvm since it is in libvirt capabilities') | 180 | 'Setting type to kvm since it is in libvirt capabilities') |
1324 | 187 | self.domaintype = 'kvm' | 181 | self.emulator = 'kvm' |
1325 | 188 | elif self._supportsdomaintype('qemu'): | 182 | elif self._supportsdomaintype('qemu'): |
1326 | 189 | self.logger.info( | 183 | self.logger.info( |
1327 | 190 | 'Setting type to qemu since it is in libvirt capabilities') | 184 | 'Setting type to qemu since it is in libvirt capabilities') |
1329 | 191 | self.domaintype = 'qemu' | 185 | self.emulator = 'qemu' |
1330 | 192 | else: | 186 | else: |
1331 | 193 | raise UTAHVMProvisioningException( | 187 | raise UTAHVMProvisioningException( |
1332 | 194 | 'kvm and qemu not supported in libvirt capabilities; ' | 188 | 'kvm and qemu not supported in libvirt capabilities; ' |
1333 | 195 | 'please make sure qemu and/or kvm are installed ' | 189 | 'please make sure qemu and/or kvm are installed ' |
1334 | 196 | 'and libvirt is configured correctly') | 190 | 'and libvirt is configured correctly') |
1347 | 197 | else: | 191 | self.directory = (directory or os.path.join(config.vmpath, self.name)) |
1336 | 198 | self.domaintype = emulator | ||
1337 | 199 | if self.domaintype == 'qemu': | ||
1338 | 200 | self.logger.debug('Raising boot timeout for qemu domain') | ||
1339 | 201 | self.boottimeout *= 4 | ||
1340 | 202 | if macs is None: | ||
1341 | 203 | macs = [] | ||
1342 | 204 | self.macs = macs | ||
1343 | 205 | if directory is None: | ||
1344 | 206 | self.directory = os.path.join(config.vmpath, self.name) | ||
1345 | 207 | else: | ||
1346 | 208 | self.directory = directory | ||
1348 | 209 | self.cleanfile(self.directory) | 192 | self.cleanfile(self.directory) |
1349 | 210 | self.logger.info('Checking if machine directory {} exists' | 193 | self.logger.info('Checking if machine directory {} exists' |
1350 | 211 | .format(self.directory)) | 194 | .format(self.directory)) |
1351 | @@ -298,7 +281,7 @@ | |||
1352 | 298 | xmlt.find('uuid').text = self.uuid | 281 | xmlt.find('uuid').text = self.uuid |
1353 | 299 | self.logger.debug( | 282 | self.logger.debug( |
1354 | 300 | 'Setting type to qemu in case no hardware virtualization present') | 283 | 'Setting type to qemu in case no hardware virtualization present') |
1356 | 301 | xmlt.getroot().set('type', self.domaintype) | 284 | xmlt.getroot().set('type', self.emulator) |
1357 | 302 | ose = xmlt.find('os') | 285 | ose = xmlt.find('os') |
1358 | 303 | if self.arch == ('i386'): | 286 | if self.arch == ('i386'): |
1359 | 304 | ose.find('type').set('arch', 'i686') | 287 | ose.find('type').set('arch', 'i686') |
1360 | 305 | 288 | ||
1361 | === modified file 'utah/run.py' | |||
1362 | --- utah/run.py 2013-04-19 19:27:58 +0000 | |||
1363 | +++ utah/run.py 2013-05-01 21:24:29 +0000 | |||
1364 | @@ -33,22 +33,21 @@ | |||
1365 | 33 | parse_yaml_file, | 33 | parse_yaml_file, |
1366 | 34 | ReturnCodes as ClientReturnCodes, | 34 | ReturnCodes as ClientReturnCodes, |
1367 | 35 | ) | 35 | ) |
1368 | 36 | from utah.client.runner import Runner | ||
1369 | 37 | from utah.client.exceptions import ( | 36 | from utah.client.exceptions import ( |
1370 | 38 | YAMLEmptyFile, | 37 | YAMLEmptyFile, |
1371 | 39 | YAMLParsingError, | 38 | YAMLParsingError, |
1372 | 40 | ) | 39 | ) |
1373 | 40 | from utah.client.runner import Runner | ||
1374 | 41 | from utah.exceptions import UTAHException | 41 | from utah.exceptions import UTAHException |
1375 | 42 | from utah.retry import retry | 42 | from utah.retry import retry |
1376 | 43 | from utah.timeout import timeout | 43 | from utah.timeout import timeout |
1377 | 44 | from utah.url import url_argument | 44 | from utah.url import url_argument |
1378 | 45 | from utah.provisioning.ssh import ProvisionedMachine | ||
1379 | 46 | 45 | ||
1380 | 47 | 46 | ||
1381 | 48 | # Return codes for the server | 47 | # Return codes for the server |
1382 | 49 | class ReturnCodes: | 48 | class ReturnCodes: |
1383 | 50 | 49 | ||
1385 | 51 | """Provide standard return codes for run\_ scripts.""" | 50 | r"""Provide standard return codes for run\_ scripts.""" |
1386 | 52 | 51 | ||
1387 | 53 | SUCCESS = 0 # No problems found | 52 | SUCCESS = 0 # No problems found |
1388 | 54 | UTAH_EXCEPTION_ERROR = 1 # UTAH exception caught | 53 | UTAH_EXCEPTION_ERROR = 1 # UTAH exception caught |
1389 | @@ -131,114 +130,8 @@ | |||
1390 | 131 | return filename | 130 | return filename |
1391 | 132 | 131 | ||
1392 | 133 | 132 | ||
1393 | 134 | def common_arguments(parser): | ||
1394 | 135 | """Centralize command line arguments for all run\_ scripts. | ||
1395 | 136 | |||
1396 | 137 | :returns: argparse parser with arguments added | ||
1397 | 138 | :rtype: obj | ||
1398 | 139 | |||
1399 | 140 | """ | ||
1400 | 141 | parser.add_argument('runlist', metavar='runlist', | ||
1401 | 142 | type=master_runlist_argument, | ||
1402 | 143 | help='URLs of runlist files to run') | ||
1403 | 144 | parser.add_argument('-s', '--series', metavar='SERIES', | ||
1404 | 145 | choices=config.serieschoices, | ||
1405 | 146 | help='Series to use for VM creation (%(choices)s)') | ||
1406 | 147 | parser.add_argument('-t', '--type', metavar='TYPE', | ||
1407 | 148 | choices=('desktop', 'server', 'mini', 'alternate'), | ||
1408 | 149 | help=('Install type to use for VM creation ' | ||
1409 | 150 | '(%(choices)s)')) | ||
1410 | 151 | parser.add_argument('-a', '--arch', metavar='ARCH', | ||
1411 | 152 | choices=('i386', 'amd64'), | ||
1412 | 153 | help=('Architecture to use for VM creation ' | ||
1413 | 154 | '(%(choices)s)')) | ||
1414 | 155 | parser.add_argument('-n', '--no-destroy', action='store_true', | ||
1415 | 156 | help='Preserve VM after tests have run') | ||
1416 | 157 | parser.add_argument('-d', '--debug', action='store_true', | ||
1417 | 158 | help='Enable debug logging') | ||
1418 | 159 | parser.add_argument('-j', '--json', action='store_true', | ||
1419 | 160 | help='Enable json logging (default is YAML)') | ||
1420 | 161 | parser.add_argument('-f', '--files', action='append', | ||
1421 | 162 | help='File or directory to copy from test system ') | ||
1422 | 163 | parser.add_argument('-o', '--outdir', | ||
1423 | 164 | help=('Directory to store locally copied files ' | ||
1424 | 165 | '(Default is {}/machine-name)' | ||
1425 | 166 | .format(config.logpath))) | ||
1426 | 167 | parser.add_argument('--dumplogs', action='store_true', | ||
1427 | 168 | help='Write client output logs to standard out') | ||
1428 | 169 | parser.add_argument('--outputpreseed', action='store_true', | ||
1429 | 170 | help='Copy preseed to logs directory and list as ' | ||
1430 | 171 | 'log file in output') | ||
1431 | 172 | return parser | ||
1432 | 173 | |||
1433 | 174 | |||
1434 | 175 | def custom_arguments(parser): | ||
1435 | 176 | """Centralize arguments for installing from an image. | ||
1436 | 177 | |||
1437 | 178 | :returns: argparse parser with arguments added | ||
1438 | 179 | :rtype: obj | ||
1439 | 180 | |||
1440 | 181 | """ | ||
1441 | 182 | parser.add_argument('-i', '--image', type=url_argument, | ||
1442 | 183 | help='Image/ISO file to use for installation') | ||
1443 | 184 | parser.add_argument('-p', '--preseed', type=url_argument, | ||
1444 | 185 | help='Preseed file to use for installation') | ||
1445 | 186 | parser.add_argument('-b', '--boot', | ||
1446 | 187 | help='Boot arguments for initial installation') | ||
1447 | 188 | parser.add_argument('--rewrite', choices=('all', 'minimal', 'casperonly', | ||
1448 | 189 | 'none'), help='Enable or disable automatic ' | ||
1449 | 190 | 'configuration rewriting') | ||
1450 | 191 | return parser | ||
1451 | 192 | |||
1452 | 193 | |||
1453 | 194 | def file_arguments(parser): | ||
1454 | 195 | """Centralize arguments for custom kernel and initrd support. | ||
1455 | 196 | |||
1456 | 197 | :returns: argparse parser with arguments added | ||
1457 | 198 | :rtype: obj | ||
1458 | 199 | |||
1459 | 200 | """ | ||
1460 | 201 | parser.add_argument('-k', '--kernel', type=url_argument, | ||
1461 | 202 | help='Kernel file to use for installation') | ||
1462 | 203 | parser.add_argument('-r', '--initrd', type=url_argument, | ||
1463 | 204 | help='InitRD file to use for installation') | ||
1464 | 205 | return parser | ||
1465 | 206 | |||
1466 | 207 | |||
1467 | 208 | def name_argument(parser): | ||
1468 | 209 | """Centralize arguments for named machines. | ||
1469 | 210 | |||
1470 | 211 | :returns: argparse parser with arguments added | ||
1471 | 212 | :rtype: obj | ||
1472 | 213 | |||
1473 | 214 | """ | ||
1474 | 215 | parser.add_argument('--name', help='Name of machine to provision') | ||
1475 | 216 | return parser | ||
1476 | 217 | |||
1477 | 218 | |||
1478 | 219 | def virtual_arguments(parser): | ||
1479 | 220 | """Centralize arguments for virtual machines. | ||
1480 | 221 | |||
1481 | 222 | :returns: argparse parser with arguments added | ||
1482 | 223 | :rtype: obj | ||
1483 | 224 | |||
1484 | 225 | """ | ||
1485 | 226 | parser.add_argument('-e', '--emulator', | ||
1486 | 227 | help=('Emulator to use (kvm and qemu are supported, ' | ||
1487 | 228 | 'kvm will be favored if available)')) | ||
1488 | 229 | parser.add_argument('-x', '--xml', type=url_argument, | ||
1489 | 230 | help='XML VM definition file') | ||
1490 | 231 | parser.add_argument('-g', '--gigabytes', action='append', | ||
1491 | 232 | help=('Size in gigabytes of virtual disk, ' | ||
1492 | 233 | 'specify more than once for multiple disks')) | ||
1493 | 234 | parser.add_argument('--diskbus', metavar='DISKBUS', | ||
1494 | 235 | choices=('virtio', 'sata', 'ide'), | ||
1495 | 236 | help=('Disk bus to use for customvm installation ' | ||
1496 | 237 | '(%(choices)s)')) | ||
1497 | 238 | return parser | ||
1498 | 239 | |||
1499 | 240 | |||
1500 | 241 | def _get_runlist(url): | 133 | def _get_runlist(url): |
1501 | 134 | # TODO: Make something that this and utah.iso._get_resource can both use | ||
1502 | 242 | try: | 135 | try: |
1503 | 243 | return urllib.urlretrieve(url)[0] | 136 | return urllib.urlretrieve(url)[0] |
1504 | 244 | except urllib.ContentTooShortError as e: | 137 | except urllib.ContentTooShortError as e: |
1505 | @@ -329,21 +222,25 @@ | |||
1506 | 329 | """Copy preseed to locallogs. | 222 | """Copy preseed to locallogs. |
1507 | 330 | 223 | ||
1508 | 331 | If we are provisioning a system, we can optionally copy its preseed along | 224 | If we are provisioning a system, we can optionally copy its preseed along |
1510 | 332 | with other locallogs from the job. Systems already provisioned will not | 225 | with other locallogs from the job. |
1511 | 333 | 226 | ||
1512 | 334 | """ | 227 | """ |
1515 | 335 | if (not isinstance(machine, ProvisionedMachine) and | 228 | if args.outputpreseed or config.outputpreseed: |
1514 | 336 | (args.outputpreseed or config.outputpreseed)): | ||
1516 | 337 | if args.outputpreseed: | 229 | if args.outputpreseed: |
1517 | 338 | logging.debug('Capturing preseed due to command line option') | 230 | logging.debug('Capturing preseed due to command line option') |
1518 | 339 | 231 | ||
1519 | 340 | p = os.path.join(config.logpath, '{}-preseed.cfg'.format(machine.name)) | 232 | p = os.path.join(config.logpath, '{}-preseed.cfg'.format(machine.name)) |
1524 | 341 | try: | 233 | if machine.hasattr('finalpreseed'): |
1525 | 342 | shutil.copyfile(machine.finalpreseed, p) | 234 | try: |
1526 | 343 | except (IOError, shutil.Error) as err: | 235 | if os.path.isfile(p): |
1527 | 344 | logging.warning('Failed to copy preseed file: %s', err) | 236 | os.chmod(p, 0664) |
1528 | 237 | shutil.copyfile(machine.finalpreseed, p) | ||
1529 | 238 | except (IOError, OSError, shutil.Error) as err: | ||
1530 | 239 | logging.warning('Failed to copy preseed file: %s', err) | ||
1531 | 240 | else: | ||
1532 | 241 | locallogs.append(p) | ||
1533 | 345 | else: | 242 | else: |
1535 | 346 | locallogs.append(p) | 243 | logging.debug('Machine has no preseed to capture') |
1536 | 347 | 244 | ||
1537 | 348 | 245 | ||
1538 | 349 | def run_tests(args, machine): | 246 | def run_tests(args, machine): |
1539 | @@ -391,10 +288,7 @@ | |||
1540 | 391 | :rtype: list(str) | 288 | :rtype: list(str) |
1541 | 392 | 289 | ||
1542 | 393 | """ | 290 | """ |
1547 | 394 | if args.outdir is None: | 291 | outdir = (args.outdir or os.path.join(config.logpath, machine.name)) |
1544 | 395 | outdir = os.path.join(config.logpath, machine.name) | ||
1545 | 396 | else: | ||
1546 | 397 | outdir = args.outdir | ||
1548 | 398 | if not os.path.isdir(outdir): | 292 | if not os.path.isdir(outdir): |
1549 | 399 | try: | 293 | try: |
1550 | 400 | os.makedirs(outdir) | 294 | os.makedirs(outdir) |
1551 | @@ -507,7 +401,7 @@ | |||
1552 | 507 | 401 | ||
1553 | 508 | """ | 402 | """ |
1554 | 509 | logging.info('Checking if UTAH client is finished') | 403 | logging.info('Checking if UTAH client is finished') |
1556 | 510 | machine.sshcheck() | 404 | machine.activecheck() |
1557 | 511 | try: | 405 | try: |
1558 | 512 | exitstatus = machine.run('/usr/share/utah/client/utah-done.py', | 406 | exitstatus = machine.run('/usr/share/utah/client/utah-done.py', |
1559 | 513 | quiet=True)[0] | 407 | quiet=True)[0] |
Documentation needs to be updated. In particular, the part in conf.py` that takes care of the manpage generation of the scripts
`docs/source/
that are now gone.
Aside from that, I think it would be a good idea to refactor the code in the
big if/elif/else to still have a function for each different provisioning case.