179
class CommandError(StandardError):
181
def __init__(self, cmd, retcode, out, err):
182
joined_cmd = ' '.join(cmd)
179
class SetupVmError(Exception):
181
msg = 'setup_vm Generic Error: %r'
183
def __init__(self, msg=None, **kwds):
186
for key, value in kwds.items():
187
setattr(self, key, value)
190
return self.msg.format((), **self.__dict__)
195
class CommandError(SetupVmError):
184
198
command: {joined_cmd}
185
199
retcode: {retcode}
188
'''.format((), **locals())
189
super(CommandError, self).__init__(msg)
204
def __init__(self, cmd, retcode, out, err):
205
super(CommandError, self).__init__(joined_cmd=' '.join(cmd),
206
retcode=retcode, err=err, out=out)
191
209
def run_subprocess(args):
192
210
proc = subprocess.Popen(args,
231
249
self._seed_path = None
232
250
self._disk_image_path = None
234
def _download_in_cache(self, source_url, name):
252
def _download_in_cache(self, source_url, name, force=False):
235
253
"""Download ``name`` from ``source_url`` in ``vm.download_cache``.
255
:param source_url: The url where the file to download is located
257
:param name: The name of the file to download (also used as the name
258
for the downloaded file).
260
:param force: Remove the file from the cache if present.
237
262
:return: False if the file is in the download cache, True if a download
240
265
source = urlutils.join(source_url, name)
241
266
download_dir = self.conf.get('vm.download_cache')
242
267
target = os.path.join(download_dir, name)
268
# FIXME: By default the download dir may be under root control, but if
269
# a user chose to use a different one under his own control, it would
270
# be nice to not require sudo usage. -- vila 2013-02-06
272
run_subprocess(['sudo', 'rm', '-f', target])
243
273
if not os.path.exists(target):
244
run_subprocess(['wget', '--progress=dot:mega','-O', target, source])
274
run_subprocess(['sudo', 'wget', '--progress=dot:mega','-O',
249
def download_iso(self):
280
def download_iso(self, force=False):
250
281
"""Download the iso to install the vm.
252
283
:return: False if the iso is in the download cache, True if a download
255
286
return self._download_in_cache(self.conf.get('vm.iso_url'),
256
self.conf.get('vm.iso_name'))
287
self.conf.get('vm.iso_name'),
258
def download_cloud_image(self):
290
def download_cloud_image(self, force=False):
259
291
"""Download the cloud image to install the vm.
261
293
:return: False if the image is in the download cache, True if a
262
294
download occurred.
264
296
return self._download_in_cache(self.conf.get('vm.cloud_image_url'),
265
self.conf.get('vm.cloud_image_name'))
297
self.conf.get('vm.cloud_image_name'),
267
300
def _create_tempfile_with_content(self, content):
268
301
temp = tempfile.NamedTemporaryFile()
372
406
['sudo', 'virsh', 'undefine', self.conf.get('vm.name'),
373
407
'--remove-all-storage'])
410
class ArgParser(argparse.ArgumentParser):
411
"""A parser for the setup_vm script."""
414
description = 'Set up virtual machines from a configuration file.'
415
super(ArgParser, self).__init__(
416
prog='setup_vm.py', description=description)
418
'name', help='Virtual machine section in the configuration file.')
419
self.add_argument('--download', '-d', action="store_true",
420
help='Force download of the required image.')
421
self.add_argument('--install', '-i', action="store_true",
422
help='Install the virtual machine.')
424
def parse_args(self, args=None, out=None, err=None):
425
"""Parse arguments, overridding stdout/stderr if provided.
427
Overridding stdout/stderr is provided for tests.
429
:params args: Defaults to sys.argv[1:].
431
:param out: Defaults to sys.stdout.
433
:param err: Defaults to sys.stderr.
435
out_orig = sys.stdout
436
err_orig = sys.stderr
442
return super(ArgParser, self).parse_args(args)
444
sys.stdout = out_orig
445
sys.stderr = err_orig
449
arg_parser = ArgParser()
451
class Command(object):
453
def __init__(self, vm):
457
class Download(Command):
460
# FIXME: what needs to be downloaded should depend on the type of the
461
# vm (possibly errors if there is nothing to download). -- vila
463
self.vm.download_cloud_image(force=True)
466
class Install(Command):
469
# FIXME: Should we check whether the vm already exist and delete it or
470
# should we delete it unconditionally ? -- vila 2013-02-06
472
# FIXME: The installation method may vary depending on the vm type.
474
self.vm.install_with_seed()
479
def build_commands(args=None, out=None, err=None):
484
ns = arg_parser.parse_args(args, out=out, err=err)
486
conf = VmStack(ns.name)
489
cmds.append(Download(vm))
491
cmds.append(Install(vm))
496
cmds = build_commands(args)
500
except SetupVmError, e:
501
# Stop on first error
502
print 'ERROR: %s' % e
506
if __name__ == "__main__":