Merge lp:~soren/vmbuilder/0.12.refactoring into lp:vmbuilder

Proposed by Soren Hansen
Status: Merged
Merged at revision: not available
Proposed branch: lp:~soren/vmbuilder/0.12.refactoring
Merge into: lp:vmbuilder
Diff against target: 3100 lines (+1205/-727)
33 files modified
VMBuilder/__init__.py (+31/-5)
VMBuilder/disk.py (+84/-58)
VMBuilder/distro.py (+53/-3)
VMBuilder/exception.py (+1/-1)
VMBuilder/frontend.py (+30/-27)
VMBuilder/hypervisor.py (+68/-5)
VMBuilder/log.py (+1/-1)
VMBuilder/plugins/__init__.py (+40/-33)
VMBuilder/plugins/cli/__init__.py (+131/-72)
VMBuilder/plugins/ec2/__init__.py (+43/-43)
VMBuilder/plugins/firstscripts/__init__.py (+20/-20)
VMBuilder/plugins/kvm/vm.py (+13/-9)
VMBuilder/plugins/libvirt/__init__.py (+14/-14)
VMBuilder/plugins/network/__init__.py (+58/-30)
VMBuilder/plugins/postinst/__init__.py (+22/-22)
VMBuilder/plugins/ubuntu/dapper.py (+162/-113)
VMBuilder/plugins/ubuntu/distro.py (+135/-97)
VMBuilder/plugins/ubuntu/edgy.py (+5/-5)
VMBuilder/plugins/ubuntu/hardy.py (+8/-5)
VMBuilder/plugins/ubuntu/intrepid.py (+1/-1)
VMBuilder/plugins/ubuntu/jaunty.py (+5/-5)
VMBuilder/plugins/ubuntu/karmic.py (+2/-2)
VMBuilder/plugins/ubuntu/suite.py (+2/-2)
VMBuilder/plugins/ubuntu/templates/dapper_fstab.tmpl (+1/-0)
VMBuilder/plugins/virtualbox/vm.py (+8/-8)
VMBuilder/plugins/vmware/vm.py (+13/-13)
VMBuilder/plugins/xen/vm.py (+16/-16)
VMBuilder/util.py (+30/-28)
VMBuilder/vm.py (+0/-74)
test/disk_tests.py (+196/-2)
test/plugin_tests.py (+1/-1)
test/ubuntu_tests.py (+2/-3)
test/util_tests.py (+9/-9)
To merge this branch: bzr merge lp:~soren/vmbuilder/0.12.refactoring
Reviewer Review Type Date Requested Status
VMBuilder Pending
Review via email: mp+19624@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'VMBuilder/__init__.py'
2--- VMBuilder/__init__.py 2010-01-22 13:27:16 +0000
3+++ VMBuilder/__init__.py 2010-02-18 16:03:14 +0000
4@@ -31,7 +31,8 @@
5 # Internal bookkeeping
6 distros = {}
7 hypervisors = {}
8-_plugins = []
9+_distro_plugins = []
10+_hypervisor_plugins = []
11 frontends = {}
12 frontend = None
13
14@@ -41,18 +42,35 @@
15 """Register a hypervisor plugin with VMBuilder"""
16 hypervisors[cls.arg] = cls
17
18+def get_hypervisor(name):
19+ if name in hypervisors:
20+ return hypervisors[name]
21+ else:
22+ raise VMBuilderUserError('No such hypervisor. Available hypervisors: %s' % (' '.join(hypervisors.keys())))
23+
24 def register_distro(cls):
25 """Register a distro plugin with VMBuilder"""
26 distros[cls.arg] = cls
27
28+def get_distro(name):
29+ if name in distros:
30+ return distros[name]
31+ else:
32+ raise VMBuilderUserError('No such distro. Available distros: %s' % (' '.join(distros.keys())))
33+
34 def register_frontend(cls):
35 """Register a frontend plugin with VMBuilder"""
36 frontends[cls.arg] = cls
37
38-def register_plugin(cls):
39- """Register a plugin with VMBuilder"""
40- _plugins.append(cls)
41- _plugins.sort(key=lambda x: x.priority)
42+def register_distro_plugin(cls):
43+ """Register a plugin with VMBuilder"""
44+ _distro_plugins.append(cls)
45+ _distro_plugins.sort(key=lambda x: x.priority)
46+
47+def register_hypervisor_plugin(cls):
48+ """Register a plugin with VMBuilder"""
49+ _hypervisor_plugins.append(cls)
50+ _hypervisor_plugins.sort(key=lambda x: x.priority)
51
52 def set_frontend(arg):
53 global frontend
54@@ -65,5 +83,13 @@
55 """This is sort of weird, but a handy shortcut, if you want to use one of the frontends"""
56 return(frontend.run())
57
58+def get_version_info():
59+ import vcsversion
60+ info = vcsversion.version_info
61+ info['major'] = 0
62+ info['minor'] = 11
63+ info['micro'] = 3
64+ return info
65+
66 logging.debug('Loading plugins')
67 VMBuilder.plugins.load_plugins()
68
69=== modified file 'VMBuilder/disk.py'
70--- VMBuilder/disk.py 2009-10-23 07:17:47 +0000
71+++ VMBuilder/disk.py 2010-02-18 16:03:14 +0000
72@@ -18,7 +18,9 @@
73 #
74 # Virtual disk management
75
76+import fcntl
77 import logging
78+import os
79 import os.path
80 import re
81 import stat
82@@ -27,6 +29,7 @@
83 import VMBuilder
84 from VMBuilder.util import run_cmd
85 from VMBuilder.exception import VMBuilderUserError, VMBuilderException
86+from struct import unpack
87
88 TYPE_EXT2 = 0
89 TYPE_EXT3 = 1
90@@ -34,62 +37,63 @@
91 TYPE_SWAP = 3
92
93 class Disk(object):
94- def __init__(self, vm, size='5G', preallocated=False, filename=None):
95+ def __init__(self, vm, filename, size=None):
96 """
97 @type size: string or number
98 @param size: The size of the disk image (passed to L{parse_size})
99
100- @type preallocated: boolean
101- @param preallocated: if True, the disk image already exists and will not be created (useful for raw devices)
102-
103 @type filename: string
104- @param filename: force a certain filename or to give the name of the preallocated disk image
105+ @param filename: filename of the disk image. If size is given, this
106+ file will be overwritten with an image of the given size
107 """
108
109- # We need this for "introspection"
110 self.vm = vm
111-
112- # Perhaps this should be the frontend's responsibility?
113- self.size = parse_size(size)
114-
115- self.preallocated = preallocated
116-
117- # If filename isn't given, make one up
118- if filename:
119- self.filename = filename
120+ self.filename = filename
121+ self.preallocated = False
122+
123+ if not os.path.exists(self.filename):
124+ if not size:
125+ raise VMBuilderUserError('%s does not exist, but no size was given.' % (self.filename))
126+ self.size = parse_size(size)
127 else:
128- if self.preallocated:
129- raise VMBuilderUserError('Preallocated was set, but no filename given')
130- self.filename = 'disk%d.img' % len(self.vm.disks)
131+ if size:
132+ raise VMBuilderUserError('%s exists, but size was given.' % (self.filename))
133+ self.preallocated = True
134+ self.size = detect_size(self.filename)
135
136 self.partitions = []
137
138- def devletters(self):
139+ def devletters(self, vm):
140 """
141+ @type vm: VM object
142+ @param vm: The VM object to which the disk belongs L{parse_size})
143+
144 @rtype: string
145 @return: the series of letters that ought to correspond to the device inside
146 the VM. E.g. the first disk of a VM would return 'a', while the 702nd would return 'zz'
147 """
148
149- return index_to_devname(self.vm.disks.index(self))
150-
151- def create(self, directory):
152- """
153- Creates the disk image (unless preallocated), partitions it, creates the partition mapping devices and mkfs's the partitions
154-
155- @type directory: string
156- @param directory: If set, the disk image is created in this directory
157- """
158-
159- if not self.preallocated:
160- if directory:
161- self.filename = '%s/%s' % (directory, self.filename)
162- logging.info('Creating disk image: %s' % self.filename)
163+ return index_to_devname(vm.disks.index(self))
164+
165+ def create(self):
166+ """
167+ Creates the disk image (unless preallocated)
168+
169+ It is safe to call this method even if the disk image already exists,
170+ in which case, it's a no-op.
171+
172+ Once this method returns, self.filename points to whatever holds the virtual disk
173+ (be it a file, partition, logical volume, etc.).
174+ """
175+
176+ if not os.path.exists(self.filename):
177+ logging.info('Creating disk image: "%s" of size: %dMB' % (self.filename, self.size))
178 run_cmd(qemu_img_path(), 'create', '-f', 'raw', self.filename, '%dM' % self.size)
179- os.chmod(self.filename, stat.S_IRUSR | stat.S_IWUSR)
180
181- # From here, we assume that self.filename refers to whatever holds the disk image,
182- # be it a file, a partition, logical volume, actual disk..
183+ def partition(self):
184+ """
185+ Partitions the disk image. Call this once you've added all partitions.
186+ """
187
188 logging.info('Adding partition table to disk image: %s' % self.filename)
189 run_cmd('parted', '--script', self.filename, 'mklabel', 'msdos')
190@@ -98,6 +102,10 @@
191 for part in self.partitions:
192 part.create(self)
193
194+ def map_partitions(self):
195+ """
196+ Create loop devices corresponding to the partitions
197+ """
198 logging.info('Creating loop devices corresponding to the created partitions')
199 self.vm.add_clean_cb(lambda : self.unmap(ignore_fail=True))
200 kpartx_output = run_cmd('kpartx', '-av', self.filename)
201@@ -113,11 +121,12 @@
202 for line in parts:
203 mapdevs.append(line.split(' ')[2])
204 for (part, mapdev) in zip(self.partitions, mapdevs):
205- part.mapdev = '/dev/mapper/%s' % mapdev
206+ part.set_filename('/dev/mapper/%s' % mapdev)
207
208 # At this point, all partitions are created and their mapping device has been
209- # created and set as .mapdev
210+ # created and set as .filename
211
212+ def mkfs(self):
213 # Adds a filesystem to the partition
214 logging.info("Creating file systems")
215 for part in self.partitions:
216@@ -158,16 +167,15 @@
217 @type mntpnt: string
218 @param mntpnt: Intended mountpoint inside the guest of the new partition
219 """
220+ length = parse_size(length)
221 end = begin+length-1
222- logging.debug("add_part - begin %d, length %d, end %d" % (begin, length, end))
223+ logging.debug("add_part - begin %d, length %d, end %d, type %s, mntpnt %s" % (begin, length, end, type, mntpnt))
224 for part in self.partitions:
225 if (begin >= part.begin and begin <= part.end) or \
226 (end >= part.begin and end <= part.end):
227- raise Exception('Partitions are overlapping')
228- if begin > end:
229- raise Exception('Partition\'s last block is before its first')
230- if begin < 0 or end > self.size:
231- raise Exception('Partition is out of bounds. start=%d, end=%d, disksize=%d' % (begin,end,self.size))
232+ raise VMBuilderUserError('Partitions are overlapping')
233+ if begin < 0 or end > self.size:
234+ raise VMBuilderUserError('Partition is out of bounds. start=%d, end=%d, disksize=%d' % (begin,end,self.size))
235 part = self.Partition(disk=self, begin=begin, end=end, type=str_to_type(type), mntpnt=mntpnt)
236 self.partitions.append(part)
237
238@@ -211,6 +219,12 @@
239 self.type = type
240 self.mntpnt = mntpnt
241 self.mapdev = None
242+ self.fs = Filesystem(vm=self.disk.vm, preallocated=True, type=self.type, mntpnt=self.mntpnt)
243+
244+ def set_filename(self, filename):
245+ print 'set_filename called'
246+ self.filename = filename
247+ self.fs.filename = filename
248
249 def parted_fstype(self):
250 """
251@@ -226,9 +240,6 @@
252
253 def mkfs(self):
254 """Adds Filesystem object"""
255- if not self.mapdev:
256- raise Exception('We can\'t mkfs before we have a mapper device')
257- self.fs = Filesystem(self.disk.vm, preallocated=True, filename=self.mapdev, type=self.type, mntpnt=self.mntpnt)
258 self.fs.mkfs()
259
260 def get_grub_id(self):
261@@ -245,11 +256,10 @@
262 return self.disk.partitions.index(self)
263
264 class Filesystem(object):
265- def __init__(self, vm, size=0, preallocated=False, type=None, mntpnt=None, filename=None, devletter='a', device='', dummy=False):
266+ def __init__(self, vm=None, size=0, preallocated=False, type=None, mntpnt=None, filename=None, devletter='a', device='', dummy=False):
267 self.vm = vm
268 self.filename = filename
269 self.size = parse_size(size)
270- self.preallocated = preallocated
271 self.devletter = devletter
272 self.device = device
273 self.dummy = dummy
274@@ -266,7 +276,7 @@
275
276 def create(self):
277 logging.info('Creating filesystem: %s, size: %d, dummy: %s' % (self.mntpnt, self.size, repr(self.dummy)))
278- if not self.preallocated:
279+ if not os.path.exists(self.filename):
280 logging.info('Not preallocated, so we create it.')
281 if not self.filename:
282 if self.mntpnt:
283@@ -288,6 +298,8 @@
284 self.mkfs()
285
286 def mkfs(self):
287+ if not self.filename:
288+ raise VMBuilderException('We can\'t mkfs if filename is not set. Did you forget to call .create()?')
289 if not self.dummy:
290 cmd = self.mkfs_fstype() + [self.filename]
291 run_cmd(*cmd)
292@@ -297,12 +309,12 @@
293 self.uuid = run_cmd('blkid', '-sUUID', '-ovalue', self.filename).rstrip()
294
295 def mkfs_fstype(self):
296- if self.vm.suite in ['dapper', 'edgy', 'feisty', 'gutsy']:
297- logging.debug('%s: 128 bit inode' % self.vm.suite)
298- return { TYPE_EXT2: ['mkfs.ext2', '-F'], TYPE_EXT3: ['mkfs.ext3', '-I 128', '-F'], TYPE_XFS: ['mkfs.xfs'], TYPE_SWAP: ['mkswap'] }[self.type]
299- else:
300- logging.debug('%s: 256 bit inode' % self.vm.suite)
301- return { TYPE_EXT2: ['mkfs.ext2', '-F'], TYPE_EXT3: ['mkfs.ext3', '-F'], TYPE_XFS: ['mkfs.xfs'], TYPE_SWAP: ['mkswap'] }[self.type]
302+ map = { TYPE_EXT2: ['mkfs.ext2', '-F'], TYPE_EXT3: ['mkfs.ext3', '-F'], TYPE_XFS: ['mkfs.xfs'], TYPE_SWAP: ['mkswap'] }
303+
304+ if not self.vm.distro.has_256_bit_inode_ext3_support():
305+ map[TYPE_EXT3] = ['mkfs.ext3', '-I 128', '-F']
306+
307+ return map[self.type]
308
309 def fstab_fstype(self):
310 return { TYPE_EXT2: 'ext2', TYPE_EXT3: 'ext3', TYPE_XFS: 'xfs', TYPE_SWAP: 'swap' }[self.type]
311@@ -310,10 +322,10 @@
312 def fstab_options(self):
313 return 'defaults'
314
315- def mount(self):
316+ def mount(self, rootmnt):
317 if (self.type != TYPE_SWAP) and not self.dummy:
318 logging.debug('Mounting %s', self.mntpnt)
319- self.mntpath = '%s%s' % (self.vm.rootmnt, self.mntpnt)
320+ self.mntpath = '%s%s' % (rootmnt, self.mntpnt)
321 if not os.path.exists(self.mntpath):
322 os.makedirs(self.mntpath)
323 run_cmd('mount', '-o', 'loop', self.filename, self.mntpath)
324@@ -426,6 +438,20 @@
325 return suffix
326 return index_to_devname(index / 26 -1, string.ascii_lowercase[index % 26]) + suffix
327
328+def detect_size(filename):
329+ st = os.stat(filename)
330+ if stat.S_ISREG(st.st_mode):
331+ return st.st_size / 1024*1024
332+ elif stat.S_ISBLK(st.st_mode):
333+ # I really wish someone would make these available in Python
334+ BLKGETSIZE64 = 2148012658
335+ fp = open(filename, 'r')
336+ fd = fp.fileno()
337+ s = fcntl.ioctl(fd, BLKGETSIZE64, ' '*8)
338+ return unpack('L', s)[0] / 1024*1024
339+
340+ raise VMBuilderException('No idea how to find the size of %s' % filename)
341+
342 def qemu_img_path():
343 exes = ['kvm-img', 'qemu-img']
344 for dir in os.environ['PATH'].split(os.path.pathsep):
345
346=== modified file 'VMBuilder/distro.py'
347--- VMBuilder/distro.py 2009-06-10 13:40:41 +0000
348+++ VMBuilder/distro.py 2010-02-18 16:03:14 +0000
349@@ -17,10 +17,60 @@
350 # along with this program. If not, see <http://www.gnu.org/licenses/>.
351 #
352 # Distro super class
353-from VMBuilder.util import run_cmd
354+from VMBuilder.util import run_cmd, call_hooks
355 import VMBuilder.plugins
356-
357-class Distro(VMBuilder.plugins.Plugin):
358+import logging
359+
360+class Context(VMBuilder.plugins.Plugin):
361+ def __init__(self):
362+ self._config = {}
363+ super(Context, self).__init__(self)
364+ self.plugins = [plugin_class(self) for plugin_class in self.plugin_classes]
365+ self.plugins.sort(key=lambda x:x.priority)
366+ self._cleanup_cbs = []
367+
368+ # Cleanup
369+ def cleanup(self):
370+ logging.info("Cleaning up")
371+ while len(self._cleanup_cbs) > 0:
372+ self._cleanup_cbs.pop(0)()
373+
374+ def add_clean_cb(self, cb):
375+ self._cleanup_cbs.insert(0, cb)
376+
377+ def add_clean_cmd(self, *argv, **kwargs):
378+ cb = lambda : run_cmd(*argv, **kwargs)
379+ self.add_clean_cb(cb)
380+ return cb
381+
382+ def cancel_cleanup(self, cb):
383+ try:
384+ self._cleanup_cbs.remove(cb)
385+ except ValueError, e:
386+ # Wasn't in there. No worries.
387+ pass
388+
389+ def call_hooks(self, *args, **kwargs):
390+ try:
391+ call_hooks(self, *args, **kwargs)
392+ except Exception, e:
393+ #self.cleanup()
394+ raise
395+
396+class Distro(Context):
397+ def __init__(self):
398+ self.plugin_classes = VMBuilder._distro_plugins
399+ super(Distro, self).__init__()
400+
401+ def set_chroot_dir(self, chroot_dir):
402+ self.chroot_dir = chroot_dir
403+
404+ def build_chroot(self):
405+ self.call_hooks('preflight_check')
406+ self.call_hooks('set_defaults')
407+ self.call_hooks('bootstrap')
408+ self.call_hooks('configure_os')
409+
410 def has_xen_support(self):
411 """Install the distro into destdir"""
412 raise NotImplemented('Distro subclasses need to implement the has_xen_support method')
413
414=== modified file 'VMBuilder/exception.py'
415--- VMBuilder/exception.py 2009-06-10 13:40:41 +0000
416+++ VMBuilder/exception.py 2010-02-18 16:03:14 +0000
417@@ -22,6 +22,6 @@
418 """Something failed inside VMBuilder"""
419 pass
420
421-class VMBuilderUserError(Exception):
422+class VMBuilderUserError(VMBuilderException):
423 """The user did something silly."""
424 pass
425
426=== modified file 'VMBuilder/frontend.py'
427--- VMBuilder/frontend.py 2009-06-10 13:40:41 +0000
428+++ VMBuilder/frontend.py 2010-02-18 16:03:14 +0000
429@@ -18,33 +18,36 @@
430 #
431 # Frontend interface and classes
432
433-import VMBuilder
434-import optparse
435+import VMBuilder.plugins
436
437-class Frontend(object):
438+class Frontend(VMBuilder.plugins.Plugin):
439 def __init__(self):
440- self.settings = []
441-
442- def setting_group(self, help=None):
443- return self.SettingsGroup(help)
444-
445- def add_setting_group(self, group):
446- self.settings.append(group)
447-
448- def add_setting(self, **kwargs):
449- self.settings.append(Setting(**kwargs))
450-
451- setting_types = ['store', 'store']
452- class Setting(object):
453- def __init__(self, **kwargs):
454- self.shortarg = kwargs.get('shortarg', None)
455- self.longarg = kwargs.get('shortarg', None)
456- self.default = kwargs.get('default', None)
457- self.help = kwargs.get('help', None)
458- type = kwargs.get('type', 'store')
459- if type not in setting_types:
460- raise VMBuilderException("Invalid option type: %s" % type)
461-
462- class SettingsGroup(Setting):
463- pass
464+ self._setting_groups = []
465+ self._config = {}
466+ self.context = self
467+
468+# self.settings = []
469+
470+# def setting_group(self, help=None):
471+# return self.SettingsGroup(help)
472+#
473+# def add_setting_group(self, group):
474+# self.settings.append(group)
475+#
476+# def add_setting(self, **kwargs):
477+# self.settings.append(Setting(**kwargs))
478+#
479+# setting_types = ['store', 'store']
480+# class Setting(object):
481+# def __init__(self, **kwargs):
482+# self.shortarg = kwargs.get('shortarg', None)
483+# self.longarg = kwargs.get('shortarg', None)
484+# self.default = kwargs.get('default', None)
485+# self.help = kwargs.get('help', None)
486+# type = kwargs.get('type', 'store')
487+# if type not in setting_types:
488+# raise VMBuilderException("Invalid option type: %s" % type)
489+#
490+# class SettingsGroup(Setting):
491+# pass
492
493
494=== modified file 'VMBuilder/hypervisor.py'
495--- VMBuilder/hypervisor.py 2009-06-10 13:40:41 +0000
496+++ VMBuilder/hypervisor.py 2010-02-18 16:03:14 +0000
497@@ -18,12 +18,75 @@
498 #
499 # Hypervisor super class
500
501-import VMBuilder.plugins
502+import logging
503+import VMBuilder.distro
504+import VMBuilder.disk
505+from VMBuilder.util import call_hooks, run_cmd, tmpdir
506
507 STORAGE_DISK_IMAGE = 0
508 STORAGE_FS_IMAGE = 1
509
510-class Hypervisor(VMBuilder.plugins.Plugin):
511- def finalize(self):
512- raise NotImplemented('Hypervisor subclasses need to implement the finalize method')
513-
514+class Hypervisor(VMBuilder.distro.Context):
515+ def __init__(self, distro):
516+ self.plugin_classes = VMBuilder._hypervisor_plugins
517+ super(Hypervisor, self).__init__()
518+ self.plugins += [distro]
519+ self.distro = distro
520+ self.filesystems = []
521+ self.disks = []
522+ self.nics = []
523+
524+ def add_disk(self, *args, **kwargs):
525+ """Adds a disk image to the virtual machine"""
526+ from VMBuilder.disk import Disk
527+ disk = Disk(self, *args, **kwargs)
528+ self.disks.append(disk)
529+ return disk
530+
531+ def install_os(self):
532+ self.nics = [self.NIC()]
533+ self.call_hooks('configure_networking', self.nics)
534+ self.call_hooks('configure_mounting', self.disks, self.filesystems)
535+
536+ self.chroot_dir = tmpdir()
537+ self.call_hooks('mount_partitions', self.chroot_dir)
538+ run_cmd('rsync', '-aHA', '%s/' % self.distro.chroot_dir, self.chroot_dir)
539+ self.distro.set_chroot_dir(self.chroot_dir)
540+ self.call_hooks('install_bootloader', self.chroot_dir, self.disks)
541+ self.call_hooks('install_kernel', self.chroot_dir)
542+ self.call_hooks('unmount_partitions')
543+
544+ def finalise(self, destdir):
545+ self.call_hooks('convert', self.disks, destdir)
546+ self.call_hooks('deploy', destdir)
547+
548+ def mount_partitions(self, mntdir):
549+ """Mounts all the vm's partitions and filesystems below .rootmnt"""
550+ logging.info('Mounting target filesystems')
551+ for disk in self.disks:
552+ disk.create()
553+ disk.partition()
554+ disk.map_partitions()
555+ disk.mkfs()
556+ fss = VMBuilder.disk.get_ordered_filesystems(self)
557+ for fs in fss:
558+ fs.mount(mntdir)
559+ self.distro.post_mount(fs)
560+
561+ def unmount_partitions(self):
562+ """Unmounts all the vm's partitions and filesystems"""
563+ logging.info('Unmounting target filesystem')
564+ fss = VMBuilder.disk.get_ordered_filesystems(self)
565+ fss.reverse()
566+ for fs in fss:
567+ fs.umount()
568+ for disk in self.disks:
569+ disk.unmap()
570+
571+ def convert_disks(self, disks, destdir):
572+ for disk in disks:
573+ disk.convert(destdir, self.filetype)
574+
575+ class NIC(object):
576+ def __init__(self, type='dhcp'):
577+ self.type = type
578
579=== modified file 'VMBuilder/log.py'
580--- VMBuilder/log.py 2009-06-10 13:40:41 +0000
581+++ VMBuilder/log.py 2010-02-18 16:03:14 +0000
582@@ -30,7 +30,7 @@
583 logging.basicConfig(format=format, level=logging.DEBUG, datefmt='%Y-%m-%d %H:%M', stream=os.fdopen(fd, 'a+'), filemode='w')
584
585 console = logging.StreamHandler()
586-console.setLevel(logging.INFO)
587+console.setLevel(logging.DEBUG)
588 console.setFormatter(logging.Formatter(format))
589 logging.getLogger('').addHandler(console)
590
591
592=== modified file 'VMBuilder/plugins/__init__.py'
593--- VMBuilder/plugins/__init__.py 2010-02-09 10:06:43 +0000
594+++ VMBuilder/plugins/__init__.py 2010-02-18 16:03:14 +0000
595@@ -20,7 +20,7 @@
596 import re
597
598 import VMBuilder
599-from VMBuilder.util import run_cmd
600+import VMBuilder.util as util
601 from VMBuilder.exception import VMBuilderException
602
603 def load_plugins():
604@@ -39,8 +39,8 @@
605 class Plugin(object):
606 priority = 10
607
608- def __init__(self, vm):
609- self.vm = vm
610+ def __init__(self, context):
611+ self.context = context
612 self._setting_groups = []
613 self.register_options()
614
615@@ -64,31 +64,34 @@
616 """
617 pass
618
619- def deploy(self):
620- """
621- Perform deployment of the VM.
622-
623- If True is returned, no further deployment will be done.
624- """
625- return False
626+ def install_file(self, path, contents=None, source=None, mode=None):
627+ fullpath = '%s%s' % (self.chroot_dir, path)
628+ if source and not contents:
629+ shutil.copy(source, fullpath)
630+ else:
631+ fp = open(fullpath, 'w')
632+ fp.write(contents)
633+ fp.close()
634+ if mode:
635+ os.chmod(fullpath, mode)
636+ return fullpath
637
638 def install_from_template(self, path, tmplname, context=None, mode=None):
639- if not self.vm.fsmounted:
640- raise VMBuilderException('install_from_template called while file system is not mounted')
641- return self.vm.install_file(path, VMBuilder.util.render_template(self.__module__.split('.')[2], self.vm, tmplname, context), mode=mode)
642+ return self.install_file(path, VMBuilder.util.render_template(self.__module__.split('.')[2], self.context, tmplname, context), mode=mode)
643
644 def run_in_target(self, *args, **kwargs):
645- if not self.vm.fsmounted:
646- raise VMBuilderException('install_from_template called while file system is not mounted')
647- return run_cmd('chroot', self.vm.installdir, *args, **kwargs)
648+ return util.run_cmd('chroot', self.chroot_dir, *args, **kwargs)
649+
650+ def call_hooks(self, *args, **kwargs):
651+ return util.call_hooks(self.context, *args, **kwargs)
652
653 # Settings
654 class SettingGroup(object):
655- def __init__(self, plugin, vm, name):
656+ def __init__(self, plugin, context, name):
657 # The plugin that owns this setting
658 self.plugin = plugin
659 # The VM object
660- self.vm = vm
661+ self.context = context
662 # Name of the Setting Group
663 self.name = name
664 # A list of Setting objects
665@@ -136,18 +139,19 @@
666 self.help = help
667 # Alternate names (for the CLI)
668 self.extra_args = extra_args or []
669+ self.metavar = metavar
670 self.value = None
671 self.value_set = False
672 self.valid_options = valid_options
673
674- if self.name in self.setting_group.vm._config:
675+ if self.name in self.setting_group.context._config:
676 raise VMBuilderException("Setting named %s already exists. Previous definition in %s/%s/%s." %
677 (self.name,
678 self.setting_group.plugin.__name__,
679 self.setting_group.plugin._config[self.name].setting_group.name,
680 self.setting_group.plugin._config[self.name].name))
681
682- self.setting_group.vm._config[self.name] = self
683+ self.setting_group.context._config[self.name] = self
684
685 def get_value(self):
686 """
687@@ -230,37 +234,40 @@
688 raise VMBuilderException('%r is type %s, expected str.' % (value, type(value)))
689
690 def setting_group(self, name):
691- setting_group = self.SettingGroup(self, self.vm, name)
692+ setting_group = self.SettingGroup(self, self.context, name)
693 self._setting_groups.append(setting_group)
694 return setting_group
695
696+ def has_setting(self, name):
697+ return name in self.context._config
698+
699 def get_setting(self, name):
700- if not name in self._config:
701+ if not name in self.context._config:
702 raise VMBuilderException('Unknown config key: %s' % name)
703- return self._config[name].get_value()
704+ return self.context._config[name].get_value()
705
706 def set_setting(self, name, value):
707- if not name in self.vm._config:
708+ if not name in self.context._config:
709 raise VMBuilderException('Unknown config key: %s' % name)
710- self._config[name].set_value(value)
711+ self.context._config[name].set_value(value)
712
713 def set_setting_default(self, name, value):
714- if not name in self.vm._config:
715+ if not name in self.context._config:
716 raise VMBuilderException('Unknown config key: %s' % name)
717- self._config[name].set_default(value)
718+ self.context._config[name].set_default(value)
719
720 def get_setting_default(self, name):
721- if not name in self.vm._config:
722+ if not name in self.context._config:
723 raise VMBuilderException('Unknown config key: %s' % name)
724- return self._config[name].get_default()
725+ return self.context._config[name].get_default()
726
727 def get_setting_valid_options(self, name):
728- if not name in self._config:
729+ if not name in self.context._config:
730 raise VMBuilderException('Unknown config key: %s' % name)
731- return self._config[name].get_valid_options()
732+ return self.context._config[name].get_valid_options()
733
734 def set_setting_valid_options(self, name, valid_options):
735- if not name in self._config:
736+ if not name in self.context._config:
737 raise VMBuilderException('Unknown config key: %s' % name)
738- self._config[name].set_valid_options(valid_options)
739+ self.context._config[name].set_valid_options(valid_options)
740
741
742=== modified file 'VMBuilder/plugins/cli/__init__.py'
743--- VMBuilder/plugins/cli/__init__.py 2009-12-08 22:27:46 +0000
744+++ VMBuilder/plugins/cli/__init__.py 2010-02-18 16:03:14 +0000
745@@ -19,9 +19,12 @@
746 from gettext import gettext
747 import logging
748 import optparse
749+import os
750+import pwd
751 import sys
752 import textwrap
753 import VMBuilder
754+import VMBuilder.util as util
755 from VMBuilder.disk import parse_size
756 import VMBuilder.hypervisor
757 _ = gettext
758@@ -31,89 +34,145 @@
759 arg = 'cli'
760
761 def run(self):
762- try:
763- next = False
764- conf = None
765- for val in sys.argv:
766- if (val == '-c') | (val == '--config'):
767- next = True
768- elif next:
769- conf = val
770- break
771-
772- vm = VMBuilder.VM(conf)
773- vm.register_setting('--version', action='callback', callback=self.versioninfo, callback_kwargs={ 'vm' : vm }, help='Show version information')
774- vm.register_setting('--rootsize', metavar='SIZE', default=4096, help='Size (in MB) of the root filesystem [default: %default]')
775- vm.register_setting('--optsize', metavar='SIZE', default=0, help='Size (in MB) of the /opt filesystem. If not set, no /opt filesystem will be added.')
776- vm.register_setting('--swapsize', metavar='SIZE', default=1024, help='Size (in MB) of the swap partition [default: %default]')
777- vm.register_setting('--raw', metavar='PATH', type='string', help="Specify a file (or block device) to as first disk image.")
778- vm.register_setting('--part', metavar='PATH', type='string', help="Allows to specify a partition table in PATH each line of partfile should specify (root first): \n mountpoint size \none per line, separated by space, where size is in megabytes. You can have up to 4 virtual disks, a new disk starts on a line containing only '---'. ie: \n root 2000 \n /boot 512 \n swap 1000 \n --- \n /var 8000 \n /var/log 2000")
779- self.set_usage(vm)
780-
781- vm.optparser.disable_interspersed_args()
782- (foo, args) = vm.optparser.parse_args()
783- self.handle_args(vm, args)
784- vm.optparser.enable_interspersed_args()
785-
786- for opt in vm.optparser.option_list + sum([grp.option_list for grp in vm.optparser.option_groups], []):
787- if len(opt._long_opts) > 1 or (opt.action == 'store' and opt._long_opts[0][2:] != opt.dest):
788- opt.help += " Config option: %s" % opt.dest
789-
790- (settings, args) = vm.optparser.parse_args(values=optparse.Values())
791- for (k,v) in settings.__dict__.iteritems():
792- setattr(vm, k, v)
793-
794- self.set_disk_layout(vm)
795-
796- vm.create()
797- except VMBuilder.VMBuilderUserError, e:
798- print >> sys.stderr, e
799- return(1)
800-
801- return(0)
802-
803- def versioninfo(self, option, opt, value, parser, vm=None):
804- print '%(major)d.%(minor)d.%(micro).r%(revno)d' % vm.get_version_info()
805+
806+ if len(sys.argv) < 3:
807+ print 'Usage: %s hypervisor distro [options]' % sys.argv[0]
808+ sys.exit(1)
809+
810+ group = self.setting_group(' ')
811+ group.add_setting('config', extra_args=['-c'], type='str', help='Configuration file')
812+ group.add_setting('destdir', extra_args=['-d'], type='str', help='Destination directory')
813+
814+ group = self.setting_group('Disk')
815+ group.add_setting('rootsize', metavar='SIZE', default=4096, help='Size (in MB) of the root filesystem [default: %default]')
816+ group.add_setting('optsize', metavar='SIZE', default=0, help='Size (in MB) of the /opt filesystem. If not set, no /opt filesystem will be added.')
817+ group.add_setting('swapsize', metavar='SIZE', default=1024, help='Size (in MB) of the swap partition [default: %default]')
818+ group.add_setting('raw', metavar='PATH', type='str', help="Specify a file (or block device) to as first disk image.")
819+ group.add_setting('part', metavar='PATH', type='str', help="Allows to specify a partition table in PATH each line of partfile should specify (root first): \n mountpoint size \none per line, separated by space, where size is in megabytes. You can have up to 4 virtual disks, a new disk starts on a line containing only '---'. ie: \n root 2000 \n /boot 512 \n swap 1000 \n --- \n /var 8000 \n /var/log 2000")
820+
821+ optparser = optparse.OptionParser()
822+ optparser.add_option('--version', action='callback', callback=self.versioninfo, help='Show version information')
823+ distro_name = sys.argv[2]
824+ distro_class = VMBuilder.get_distro(distro_name)
825+ distro = distro_class()
826+ distro.plugins.append(self)
827+ self.add_settings_from_context(optparser, distro)
828+
829+ hypervisor_name = sys.argv[1]
830+ hypervisor_class = VMBuilder.get_hypervisor(hypervisor_name)
831+ hypervisor = hypervisor_class(distro)
832+ hypervisor.plugins.append(self)
833+ self.add_settings_from_context(optparser, hypervisor)
834+
835+ self.set_setting_default('destdir', '%s-%s' % (distro_name, hypervisor_name))
836+
837+ (options, args) = optparser.parse_args(sys.argv[2:])
838+ for option in dir(options):
839+ if option.startswith('_') or option in ['ensure_value', 'read_module', 'read_file']:
840+ continue
841+ val = getattr(options, option)
842+ if val:
843+ if distro.has_setting(option):
844+ distro.set_setting(option, val)
845+ else:
846+ hypervisor.set_setting(option, val)
847+
848+ chroot_dir = util.tmpdir()
849+
850+ distro.set_chroot_dir(chroot_dir)
851+ distro.build_chroot()
852+
853+ self.set_disk_layout(hypervisor)
854+ hypervisor.install_os()
855+
856+ destdir = self.get_setting('destdir')
857+ os.mkdir(destdir)
858+ self.fix_ownership(destdir)
859+ hypervisor.finalise(destdir)
860+
861+ sys.exit(1)
862+
863+ def fix_ownership(self, filename):
864+ """
865+ Change ownership of file to $SUDO_USER.
866+
867+ @type path: string
868+ @param path: file or directory to give to $SUDO_USER
869+ """
870+
871+ if 'SUDO_USER' in os.environ:
872+ logging.debug('Changing ownership of %s to %s' % (filename, os.environ['SUDO_USER']))
873+ (uid, gid) = pwd.getpwnam(os.environ['SUDO_USER'])[2:4]
874+ os.chown(filename, uid, gid)
875+
876+ def add_settings_from_context(self, optparser, context):
877+ setting_groups = set([setting.setting_group for setting in context._config.values()])
878+ for setting_group in setting_groups:
879+ optgroup = optparse.OptionGroup(optparser, setting_group.name)
880+ for setting in setting_group._settings:
881+ args = ['--%s' % setting.name]
882+ args += setting.extra_args
883+ kwargs = {}
884+ if setting.help:
885+ kwargs['help'] = setting.help
886+ if len(setting.extra_args) > 0:
887+ setting.help += " Config option: %s" % setting.name
888+ if setting.metavar:
889+ kwargs['metavar'] = setting.metavar
890+ if setting.get_default():
891+ kwargs['default'] = setting.get_default()
892+ if type(setting) == VMBuilder.plugins.Plugin.BooleanSetting:
893+ kwargs['action'] = 'store_true'
894+ if type(setting) == VMBuilder.plugins.Plugin.ListSetting:
895+ kwargs['action'] = 'append'
896+ optgroup.add_option(*args, **kwargs)
897+ optparser.add_option_group(optgroup)
898+
899+ def versioninfo(self, option, opt, value, parser):
900+ print '%(major)d.%(minor)d.%(micro)s.r%(revno)d' % VMBuilder.get_version_info()
901 sys.exit(0)
902
903- def set_usage(self, vm):
904- vm.optparser.set_usage('%prog hypervisor distro [options]')
905- vm.optparser.arg_help = (('hypervisor', vm.hypervisor_help), ('distro', vm.distro_help))
906+ def set_usage(self, optparser):
907+ optparser.set_usage('%prog hypervisor distro [options]')
908+ optparser.arg_help = (('hypervisor', vm.hypervisor_help), ('distro', vm.distro_help))
909
910 def handle_args(self, vm, args):
911 if len(args) < 2:
912 vm.optparser.error("You need to specify at least the hypervisor type and the distro")
913- vm.set_hypervisor(args[0])
914- vm.set_distro(args[1])
915+ self.hypervisor = vm.get_hypervisor(args[0])
916+ self.distro = distro.vm.get_distro(args[1])
917
918- def set_disk_layout(self, vm):
919- if not vm.part:
920- vm.rootsize = parse_size(vm.rootsize)
921- vm.swapsize = parse_size(vm.swapsize)
922- vm.optsize = parse_size(vm.optsize)
923- if vm.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
924- vm.add_filesystem(size='%dM' % vm.rootsize, type='ext3', mntpnt='/')
925- vm.add_filesystem(size='%dM' % vm.swapsize, type='swap', mntpnt=None)
926- if vm.optsize > 0:
927- vm.add_filesystem(size='%dM' % optsize, type='ext3', mntpnt='/opt')
928+ def set_disk_layout(self, hypervisor):
929+ if not self.get_setting('part'):
930+ rootsize = parse_size(self.get_setting('rootsize'))
931+ swapsize = parse_size(self.get_setting('swapsize'))
932+ optsize = parse_size(self.get_setting('optsize'))
933+ if hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
934+ hypervisor.add_filesystem(size='%dM' % rootsize, type='ext3', mntpnt='/')
935+ hypervisor.add_filesystem(size='%dM' % swapsize, type='swap', mntpnt=None)
936+ if optsize > 0:
937+ hypervisor.add_filesystem(size='%dM' % optsize, type='ext3', mntpnt='/opt')
938 else:
939- if vm.raw:
940- disk = vm.add_disk(filename=vm.raw, preallocated=True)
941+ raw = self.get_setting('raw')
942+ if raw:
943+ disk = hypervisor.add_disk(filename=raw, preallocated=True)
944 else:
945- size = vm.rootsize + vm.swapsize + vm.optsize
946- disk = vm.add_disk(size='%dM' % size)
947+ size = rootsize + swapsize + optsize
948+ tmpfile = util.tmpfile(keep=False)
949+ disk = hypervisor.add_disk(tmpfile, size='%dM' % size)
950 offset = 0
951- disk.add_part(offset, vm.rootsize, 'ext3', '/')
952- offset += vm.rootsize
953- disk.add_part(offset, vm.swapsize, 'swap', 'swap')
954- offset += vm.swapsize
955- if vm.optsize > 0:
956- disk.add_part(offset, vm.optsize, 'ext3', '/opt')
957+ disk.add_part(offset, rootsize, 'ext3', '/')
958+ offset += rootsize
959+ disk.add_part(offset, swapsize, 'swap', 'swap')
960+ offset += swapsize
961+ if optsize > 0:
962+ disk.add_part(offset, optsize, 'ext3', '/opt')
963 else:
964 # We need to parse the file specified
965+ part = self.get_setting('part')
966 if vm.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
967 try:
968- for line in file(vm.part):
969+ for line in file(part):
970 elements = line.strip().split(' ')
971 if elements[0] == 'root':
972 vm.add_filesystem(elements[1], type='ext3', mntpnt='/')
973@@ -133,7 +192,7 @@
974 try:
975 curdisk = list()
976 size = 0
977- for line in file(vm.part):
978+ for line in file(part):
979 pair = line.strip().split(' ',1)
980 if pair[0] == '---':
981 self.do_disk(vm, curdisk, size)
982@@ -167,8 +226,8 @@
983 arg = 'ubuntu-vm-builder'
984
985 def set_usage(self, vm):
986- vm.optparser.set_usage('%prog hypervisor suite [options]')
987- vm.optparser.arg_help = (('hypervisor', vm.hypervisor_help), ('suite', self.suite_help))
988+ optparser.set_usage('%prog hypervisor suite [options]')
989+ optparser.arg_help = (('hypervisor', vm.hypervisor_help), ('suite', self.suite_help))
990
991 def suite_help(self):
992 return 'Suite. Valid options: %s' % " ".join(VMBuilder.plugins.ubuntu.distro.Ubuntu.suites)
993
994=== modified file 'VMBuilder/plugins/ec2/__init__.py'
995--- VMBuilder/plugins/ec2/__init__.py 2009-07-07 11:14:54 +0000
996+++ VMBuilder/plugins/ec2/__init__.py 2010-02-18 16:03:14 +0000
997@@ -17,7 +17,7 @@
998 # along with this program. If not, see <http://www.gnu.org/licenses/>.
999 #
1000 import VMBuilder
1001-from VMBuilder import register_plugin, Plugin, VMBuilderUserError, VMBuilderException
1002+from VMBuilder import register_distro_plugin, register_hypervisor_plugin, Plugin, VMBuilderUserError, VMBuilderException
1003 from VMBuilder.util import run_cmd
1004 import logging
1005 import os
1006@@ -27,9 +27,9 @@
1007
1008 def register_options(self):
1009 # Don't pretend like we can do EC2
1010- if not isinstance(self.vm.hypervisor, VMBuilder.plugins.xen.Xen):
1011+ if not isinstance(self.context.hypervisor, VMBuilder.plugins.xen.Xen):
1012 return
1013- group = self.vm.setting_group('EC2 integation')
1014+ group = self.context.setting_group('EC2 integation')
1015 group.add_option('--ec2', action='store_true', help='Build for EC2')
1016 group.add_option('--ec2-name','--ec2-prefix', metavar='EC2_NAME', help='Name for the EC2 image.')
1017 group.add_option('--ec2-cert', metavar='CERTFILE', help='PEM encoded public certificate for EC2.')
1018@@ -45,106 +45,106 @@
1019 group.add_option('--ec2-bundle', action='store_true', help='Bundle the instance')
1020 group.add_option('--ec2-upload', action='store_true', help='Upload the instance')
1021 group.add_option('--ec2-register', action='store_true', help='Register the instance')
1022- self.vm.register_setting_group(group)
1023+ self.context.register_setting_group(group)
1024
1025 def preflight_check(self):
1026 if not getattr(self.vm, 'ec2', False):
1027 return True
1028
1029- if not self.vm.hypervisor.name == 'Xen':
1030+ if not self.context.hypervisor.name == 'Xen':
1031 raise VMBuilderUserError('When building for EC2 you must use the xen hypervisor.')
1032
1033- if self.vm.ec2_bundle:
1034+ if self.context.ec2_bundle:
1035 try:
1036 run_cmd('ec2-ami-tools-version')
1037 except VMBuilderException, e:
1038 raise VMBuilderUserError('You need to have the Amazon EC2 AMI tools installed')
1039
1040- if not self.vm.ec2_name:
1041+ if not self.context.ec2_name:
1042 raise VMBuilderUserError('When building for EC2 you must supply the name for the image.')
1043
1044- if not self.vm.ec2_cert:
1045+ if not self.context.ec2_cert:
1046 if "EC2_CERT" in os.environ:
1047- self.vm.ec2_cert = os.environ["EC2_CERT"]
1048+ self.context.ec2_cert = os.environ["EC2_CERT"]
1049 else:
1050 raise VMBuilderUserError('When building for EC2 you must provide your PEM encoded public key certificate')
1051
1052- if not self.vm.ec2_key:
1053+ if not self.context.ec2_key:
1054 if "EC2_PRIVATE_KEY" in os.environ:
1055- self.vm.ec2_key = os.environ["EC2_PRIVATE_KEY"]
1056+ self.context.ec2_key = os.environ["EC2_PRIVATE_KEY"]
1057 else:
1058 raise VMBuilderUserError('When building for EC2 you must provide your PEM encoded private key file')
1059
1060- if not self.vm.ec2_user:
1061+ if not self.context.ec2_user:
1062 raise VMBuilderUserError('When building for EC2 you must provide your EC2 user ID (your AWS account number, not your AWS access key ID)')
1063
1064- if not self.vm.ec2_kernel:
1065- self.vm.ec2_kernel = self.vm.distro.get_ec2_kernel()
1066- logging.debug('%s - to be used for AKI.' %(self.vm.ec2_kernel))
1067-
1068- if not self.vm.ec2_ramdisk:
1069- self.vm.ec2_ramdisk = self.vm.distro.ec2_ramdisk_id()
1070- logging.debug('%s - to be use for the ARI.' %(self.vm.ec2_ramdisk))
1071-
1072- if self.vm.ec2_upload:
1073- if not self.vm.ec2_bucket:
1074+ if not self.context.ec2_kernel:
1075+ self.context.ec2_kernel = self.vm.distro.get_ec2_kernel()
1076+ logging.debug('%s - to be used for AKI.' %(self.context.ec2_kernel))
1077+
1078+ if not self.context.ec2_ramdisk:
1079+ self.context.ec2_ramdisk = self.vm.distro.ec2_ramdisk_id()
1080+ logging.debug('%s - to be use for the ARI.' %(self.context.ec2_ramdisk))
1081+
1082+ if self.context.ec2_upload:
1083+ if not self.context.ec2_bucket:
1084 raise VMBuilderUserError('When building for EC2 you must provide an S3 bucket to hold the AMI')
1085
1086- if not self.vm.ec2_access_key:
1087+ if not self.context.ec2_access_key:
1088 raise VMBuilderUserError('When building for EC2 you must provide your AWS access key ID.')
1089
1090- if not self.vm.ec2_secret_key:
1091+ if not self.context.ec2_secret_key:
1092 raise VMBuilderUserError('When building for EC2 you must provide your AWS secret access key.')
1093
1094- if not self.vm.ec2_version:
1095+ if not self.context.ec2_version:
1096 raise VMBuilderUserError('When building for EC2 you must provide version info.')
1097
1098- if not self.vm.addpkg:
1099- self.vm.addpkg = []
1100+ if not self.context.addpkg:
1101+ self.context.addpkg = []
1102
1103- if self.vm.ec2_landscape:
1104+ if self.context.ec2_landscape:
1105 logging.info('Installing landscape support')
1106- self.vm.addpkg += ['landscape-client']
1107+ self.context.addpkg += ['landscape-client']
1108
1109 def post_install(self):
1110 if not getattr(self.vm, 'ec2', False):
1111 return
1112
1113 logging.info("Running ec2 postinstall")
1114- self.install_from_template('/etc/ec2_version', 'ec2_version', { 'version' : self.vm.ec2_version } )
1115+ self.install_from_template('/etc/ec2_version', 'ec2_version', { 'version' : self.context.ec2_version } )
1116 self.install_from_template('/etc/ssh/sshd_config', 'sshd_config')
1117 self.install_from_template('/etc/sudoers', 'sudoers')
1118
1119- if self.vm.ec2_landscape:
1120+ if self.context.ec2_landscape:
1121 self.install_from_template('/etc/default/landscape-client', 'landscape_client')
1122
1123- self.vm.distro.disable_hwclock_access()
1124+ self.context.distro.disable_hwclock_access()
1125
1126 def deploy(self):
1127 if not getattr(self.vm, 'ec2', False):
1128 return False
1129
1130- if self.vm.ec2_bundle:
1131+ if self.context.ec2_bundle:
1132 logging.info("Building EC2 bundle")
1133- bundle_cmdline = ['ec2-bundle-image', '--image', self.vm.filesystems[0].filename, '--cert', self.vm.ec2_cert, '--privatekey', self.vm.ec2_key, '--user', self.vm.ec2_user, '--prefix', self.vm.ec2_name, '-r', ['i386', 'x86_64'][self.vm.arch == 'amd64'], '-d', self.vm.workdir, '--kernel', self.vm.ec2_kernel, '--ramdisk', self.vm.ec2_ramdisk]
1134+ bundle_cmdline = ['ec2-bundle-image', '--image', self.context.filesystems[0].filename, '--cert', self.vm.ec2_cert, '--privatekey', self.vm.ec2_key, '--user', self.vm.ec2_user, '--prefix', self.vm.ec2_name, '-r', ['i386', 'x86_64'][self.vm.arch == 'amd64'], '-d', self.vm.workdir, '--kernel', self.vm.ec2_kernel, '--ramdisk', self.vm.ec2_ramdisk]
1135 run_cmd(*bundle_cmdline)
1136
1137- manifest = '%s/%s.manifest.xml' % (self.vm.workdir, self.vm.ec2_name)
1138- if self.vm.ec2_upload:
1139+ manifest = '%s/%s.manifest.xml' % (self.context.workdir, self.vm.ec2_name)
1140+ if self.context.ec2_upload:
1141 logging.info("Uploading EC2 bundle")
1142- upload_cmdline = ['ec2-upload-bundle', '--retry', '--manifest', manifest, '--bucket', self.vm.ec2_bucket, '--access-key', self.vm.ec2_access_key, '--secret-key', self.vm.ec2_secret_key]
1143+ upload_cmdline = ['ec2-upload-bundle', '--retry', '--manifest', manifest, '--bucket', self.context.ec2_bucket, '--access-key', self.vm.ec2_access_key, '--secret-key', self.vm.ec2_secret_key]
1144 run_cmd(*upload_cmdline)
1145
1146- if self.vm.ec2_register:
1147+ if self.context.ec2_register:
1148 from boto.ec2.connection import EC2Connection
1149- conn = EC2Connection(self.vm.ec2_access_key, self.vm.ec2_secret_key)
1150- amiid = conn.register_image('%s/%s.manifest.xml' % (self.vm.ec2_bucket, self.vm.ec2_name))
1151+ conn = EC2Connection(self.context.ec2_access_key, self.vm.ec2_secret_key)
1152+ amiid = conn.register_image('%s/%s.manifest.xml' % (self.context.ec2_bucket, self.vm.ec2_name))
1153 print 'Image registered as %s' % amiid
1154 else:
1155- self.vm.result_files.append(manifest)
1156+ self.context.result_files.append(manifest)
1157 else:
1158- self.vm.result_files.append(self.vm.filesystems[0].filename)
1159+ self.context.result_files.append(self.vm.filesystems[0].filename)
1160
1161 return True
1162
1163-register_plugin(EC2)
1164+#register_plugin(EC2)
1165
1166=== modified file 'VMBuilder/plugins/firstscripts/__init__.py'
1167--- VMBuilder/plugins/firstscripts/__init__.py 2009-06-10 13:40:41 +0000
1168+++ VMBuilder/plugins/firstscripts/__init__.py 2010-02-18 16:03:14 +0000
1169@@ -16,7 +16,7 @@
1170 # You should have received a copy of the GNU General Public License
1171 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1172 #
1173-from VMBuilder import register_plugin, Plugin, VMBuilderUserError
1174+from VMBuilder import register_distro_plugin, Plugin, VMBuilderUserError
1175 from VMBuilder.util import run_cmd
1176
1177 import logging
1178@@ -31,36 +31,36 @@
1179 name = 'First-Scripts plugin'
1180
1181 def register_options(self):
1182- group = self.vm.setting_group('Scripts')
1183+ group = self.context.setting_group('Scripts')
1184 group.add_option('--firstboot', metavar='PATH', default='', help='Specify a script that will be copied into the guest and executed the first time the machine boots. This script must not be interactive.')
1185 group.add_option('--firstlogin', metavar='PATH', default='', help='Specify a script that will be copied into the guest and will be executed the first time the user logs in. This script can be interactive.')
1186- self.vm.register_setting_group(group)
1187+ self.context.register_setting_group(group)
1188
1189 def preflight_check(self):
1190
1191- if self.vm.firstboot:
1192- logging.debug("Checking if firstboot script %s exists" % (self.vm.firstboot,))
1193- if not(os.path.isfile(self.vm.firstboot)):
1194- raise VMBuilderUserError('The path to the first-boot script is invalid: %s. Make sure you are providing a full path.' % self.vm.firstboot)
1195+ if self.context.firstboot:
1196+ logging.debug("Checking if firstboot script %s exists" % (self.context.firstboot,))
1197+ if not(os.path.isfile(self.context.firstboot)):
1198+ raise VMBuilderUserError('The path to the first-boot script is invalid: %s. Make sure you are providing a full path.' % self.context.firstboot)
1199
1200- if self.vm.firstlogin:
1201- logging.debug("Checking if first login script %s exists" % (self.vm.firstlogin,))
1202- if not(os.path.isfile(self.vm.firstlogin)):
1203- raise VMBuilderUserError('The path to the first-login script is invalid: %s. Make sure you are providing a full path.' % self.vm.firstlogin)
1204+ if self.context.firstlogin:
1205+ logging.debug("Checking if first login script %s exists" % (self.context.firstlogin,))
1206+ if not(os.path.isfile(self.context.firstlogin)):
1207+ raise VMBuilderUserError('The path to the first-login script is invalid: %s. Make sure you are providing a full path.' % self.context.firstlogin)
1208
1209 def post_install(self):
1210- logging.debug("Installing firstboot script %s" % (self.vm.firstboot,))
1211- if self.vm.firstboot:
1212- self.vm.install_file('/root/firstboot.sh', source=self.vm.firstboot, mode=0700)
1213- os.rename('%s/etc/rc.local' % self.vm.installdir, '%s/etc/rc.local.orig' % self.vm.installdir)
1214+ logging.debug("Installing firstboot script %s" % (self.context.firstboot,))
1215+ if self.context.firstboot:
1216+ self.context.install_file('/root/firstboot.sh', source=self.vm.firstboot, mode=0700)
1217+ os.rename('%s/etc/rc.local' % self.context.installdir, '%s/etc/rc.local.orig' % self.vm.installdir)
1218 self.install_from_template('/etc/rc.local', 'firstbootrc', mode=0755)
1219
1220- logging.debug("Installing first login script %s" % (self.vm.firstlogin,))
1221- if self.vm.firstlogin:
1222- self.vm.install_file('/root/firstlogin.sh', source=self.vm.firstlogin, mode=0755)
1223- os.rename('%s/etc/bash.bashrc' % self.vm.installdir, '%s/etc/bash.bashrc.orig' % self.vm.installdir)
1224+ logging.debug("Installing first login script %s" % (self.context.firstlogin,))
1225+ if self.context.firstlogin:
1226+ self.context.install_file('/root/firstlogin.sh', source=self.vm.firstlogin, mode=0755)
1227+ os.rename('%s/etc/bash.bashrc' % self.context.installdir, '%s/etc/bash.bashrc.orig' % self.vm.installdir)
1228 self.install_from_template('/etc/bash.bashrc', 'firstloginrc')
1229
1230 return True
1231
1232-register_plugin(Firstscripts)
1233+#register_plugin(Firstscripts)
1234
1235=== modified file 'VMBuilder/plugins/kvm/vm.py'
1236--- VMBuilder/plugins/kvm/vm.py 2009-06-10 13:40:41 +0000
1237+++ VMBuilder/plugins/kvm/vm.py 2010-02-18 16:03:14 +0000
1238@@ -30,24 +30,28 @@
1239 preferred_storage = VMBuilder.hypervisor.STORAGE_DISK_IMAGE
1240 needs_bootloader = True
1241
1242- def finalize(self):
1243+ def register_options(self):
1244+ group = self.setting_group('VM settings')
1245+ group.add_setting('mem', extra_args=['-m'], default='128', help='Assign MEM megabytes of memory to the guest vm. [default: %default]')
1246+ group.add_setting('cpus', type='int', default=1, help='Number of virtual CPU\'s. [default: %default]')
1247+
1248+ def convert(self, disks, destdir):
1249 self.imgs = []
1250- self.cmdline = ['kvm', '-m', str(self.vm.mem), '-smp', str(self.vm.cpus) ]
1251- for disk in self.vm.disks:
1252- img_path = disk.convert(self.vm.destdir, self.filetype)
1253+ self.cmdline = ['kvm', '-m', str(self.context.get_setting('mem')), '-smp', str(self.context.get_setting('cpus')) ]
1254+ for disk in disks:
1255+ img_path = disk.convert(destdir, self.filetype)
1256 self.imgs.append(img_path)
1257- self.vm.result_files.append(img_path)
1258+ self.call_hooks('fix_ownership', img_path)
1259 self.cmdline += ['-drive', 'file=%s' % os.path.basename(img_path)]
1260-
1261
1262 self.cmdline += ['"$@"']
1263
1264- def deploy(self):
1265- script = '%s/run.sh' % self.vm.destdir
1266+ def deploy(self, destdir):
1267+ script = '%s/run.sh' % destdir
1268 fp = open(script, 'w')
1269 fp.write("#!/bin/sh\n\nexec %s\n" % ' '.join(self.cmdline))
1270 fp.close()
1271 os.chmod(script, stat.S_IRWXU | stat.S_IRWXU | stat.S_IROTH | stat.S_IXOTH)
1272- self.vm.result_files.append(script)
1273+ self.call_hooks('fix_ownership', script)
1274
1275 register_hypervisor(KVM)
1276
1277=== modified file 'VMBuilder/plugins/libvirt/__init__.py'
1278--- VMBuilder/plugins/libvirt/__init__.py 2009-06-10 13:40:41 +0000
1279+++ VMBuilder/plugins/libvirt/__init__.py 2010-02-18 16:03:14 +0000
1280@@ -16,53 +16,53 @@
1281 # You should have received a copy of the GNU General Public License
1282 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1283 #
1284-from VMBuilder import register_plugin, Plugin, VMBuilderUserError
1285+from VMBuilder import register_hypervisor_plugin, Plugin, VMBuilderUserError
1286 import VMBuilder.util
1287
1288 class Libvirt(Plugin):
1289 name = 'libvirt integration'
1290
1291 def register_options(self):
1292- group = self.vm.setting_group('libvirt integration')
1293+ group = self.context.setting_group('libvirt integration')
1294 group.add_option('--libvirt', metavar='URI', help='Add VM to given URI')
1295 group.add_option('--bridge', metavar="BRIDGE", help='Set up bridged network connected to BRIDGE.')
1296- self.vm.register_setting_group(group)
1297+ self.context.register_setting_group(group)
1298
1299 def all_domains(self):
1300 # This does not seem to work when any domain is already running
1301 return self.conn.listDefinedDomains() + [self.conn.lookupByID(id).name() for id in self.conn.listDomainsID()]
1302
1303 def preflight_check(self):
1304- if not self.vm.libvirt:
1305+ if not self.context.libvirt:
1306 return True
1307
1308 import libvirt
1309
1310- self.conn = libvirt.open(self.vm.libvirt)
1311- if self.vm.hostname in self.all_domains() and not self.vm.overwrite:
1312- raise VMBuilderUserError('Domain %s already exists at %s' % (self.vm.hostname, self.vm.libvirt))
1313+ self.conn = libvirt.open(self.context.libvirt)
1314+ if self.context.hostname in self.all_domains() and not self.vm.overwrite:
1315+ raise VMBuilderUserError('Domain %s already exists at %s' % (self.context.hostname, self.vm.libvirt))
1316
1317- if not self.vm.hypervisor.name == 'KVM':
1318+ if not self.context.hypervisor.name == 'KVM':
1319 raise VMBuilderUserError('The libvirt plugin is only equiped to work with KVM at the moment.')
1320
1321- if not self.vm.hypervisor.name == 'KVM':
1322+ if not self.context.hypervisor.name == 'KVM':
1323 raise VMBuilderUserError('The libvirt plugin is only equiped to work with KVM at the moment.')
1324
1325 def deploy(self):
1326- if not self.vm.libvirt:
1327+ if not self.context.libvirt:
1328 # Not for us
1329 return False
1330
1331- if self.vm.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
1332+ if self.context.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
1333 vmxml = VMBuilder.util.render_template('libvirt', self.vm, 'libvirtxml_fsimage')
1334 else:
1335 vmxml = VMBuilder.util.render_template('libvirt', self.vm, 'libvirtxml')
1336
1337- if self.vm.hostname in self.all_domains() and not self.vm.overwrite:
1338- raise VMBuilderUserError('Domain %s already exists at %s' % (self.vm.hostname, self.vm.libvirt))
1339+ if self.context.hostname in self.all_domains() and not self.vm.overwrite:
1340+ raise VMBuilderUserError('Domain %s already exists at %s' % (self.context.hostname, self.vm.libvirt))
1341 else:
1342 self.conn.defineXML(vmxml)
1343
1344 return True
1345
1346-register_plugin(Libvirt)
1347+#register_plugin(Libvirt)
1348
1349=== modified file 'VMBuilder/plugins/network/__init__.py'
1350--- VMBuilder/plugins/network/__init__.py 2010-02-02 15:36:35 +0000
1351+++ VMBuilder/plugins/network/__init__.py 2010-02-18 16:03:14 +0000
1352@@ -23,7 +23,7 @@
1353 import struct
1354 import socket
1355
1356-from VMBuilder import register_plugin
1357+from VMBuilder import register_hypervisor_plugin, register_distro_plugin
1358 from VMBuilder.plugins import Plugin
1359 from VMBuilder.exception import VMBuilderUserError
1360
1361@@ -64,52 +64,80 @@
1362 def guess_gw_from_ip(ip):
1363 return ip + 0x01000000
1364
1365-class NetworkPlugin(Plugin):
1366+class NetworkDistroPlugin(Plugin):
1367+ def register_options(self):
1368+ group = self.setting_group('Network')
1369+ domainname = '.'.join(socket.gethostbyname_ex(socket.gethostname())[0].split('.')[1:]) or "defaultdomain"
1370+ group.add_setting('domain', metavar='DOMAIN', default=domainname, help='Set DOMAIN as the domain name of the guest [default: %default].')
1371+
1372+ def preflight_check(self):
1373+ domain = self.context.get_setting('domain')
1374+ if domain == '':
1375+ raise VMBuilderUserError('Domain is undefined and host has no domain set.')
1376+
1377+class NetworkHypervisorPlugin(Plugin):
1378+ def register_options(self):
1379+ group = self.setting_group('Network')
1380+ group.add_setting('ip', metavar='ADDRESS', default='dhcp', help='IP address in dotted form [default: %default].')
1381+ group.add_setting('mac', metavar='MAC', help='MAC address of the guest [default: random].')
1382+ group.add_setting('mask', metavar='VALUE', help='IP mask in dotted form [default: based on ip setting]. Ignored if ip is not specified.')
1383+ group.add_setting('net', metavar='ADDRESS', help='IP net address in dotted form [default: based on ip setting]. Ignored if ip is not specified.')
1384+ group.add_setting('bcast', metavar='VALUE', help='IP broadcast in dotted form [default: based on ip setting]. Ignored if ip is not specified.')
1385+ group.add_setting('gw', metavar='ADDRESS', help='Gateway (router) address in dotted form [default: based on ip setting (first valid address in the network)]. Ignored if ip is not specified.')
1386+ group.add_setting('dns', metavar='ADDRESS', help='DNS address in dotted form [default: based on ip setting (first valid address in the network)] Ignored if ip is not specified.')
1387+
1388+
1389 def preflight_check(self):
1390 """
1391 Validate the ip configuration given and set defaults
1392 """
1393
1394- logging.debug("ip: %s" % self.vm.ip)
1395+ ip = self.context.get_setting('ip')
1396+ logging.debug("ip: %s" % ip)
1397
1398- if self.vm.mac:
1399+ mac = self.context.get_setting('mac')
1400+ if mac:
1401 if not validate_mac(mac):
1402 raise VMBuilderUserError("Malformed MAC address entered: %s" % mac)
1403
1404- if self.vm.ip != 'dhcp':
1405- if self.vm.domain == '':
1406- raise VMBuilderUserError('Domain is undefined and host has no domain set.')
1407-
1408+ if ip != 'dhcp':
1409 # num* are numeric representations
1410- numip = dotted_to_numeric_ip(self.vm.ip)
1411+ numip = dotted_to_numeric_ip(ip)
1412
1413- if not self.vm.mask:
1414+ mask = self.context.get_setting('mask')
1415+ if not mask:
1416 nummask = guess_mask_from_ip(numip)
1417 else:
1418- nummask = dotted_to_numeric_ip(self.vm.mask)
1419+ nummask = dotted_to_numeric_ip(mask)
1420
1421 numnet = calculate_net_address_from_ip_and_netmask(numip, nummask)
1422
1423- if not self.vm.net:
1424- self.vm.net = numeric_to_dotted_ip(numnet)
1425+ net = self.context.get_setting('net')
1426+ if not net:
1427+ self.context.set_setting('net', numeric_to_dotted_ip(numnet))
1428
1429- if not self.vm.bcast:
1430+ bcast = self.context.get_setting('bcast')
1431+ if not bcast:
1432 numbcast = calculate_broadcast_address_from_ip_and_netmask(numnet, nummask)
1433- self.vm.bcast = numeric_to_dotted_ip(numbcast)
1434+ self.context.set_setting('bcast', numeric_to_dotted_ip(numbcast))
1435
1436- if not self.vm.gw:
1437+ gw = self.context.get_setting('gw')
1438+ if not gw:
1439 numgw = guess_gw_from_ip(numip)
1440- self.vm.gw = numeric_to_dotted_ip(numgw)
1441-
1442- if not self.vm.dns:
1443- self.vm.dns = self.vm.gw
1444-
1445- self.vm.mask = numeric_to_dotted_ip(nummask)
1446-
1447- logging.debug("net: %s" % self.vm.net)
1448- logging.debug("netmask: %s" % self.vm.mask)
1449- logging.debug("broadcast: %s" % self.vm.bcast)
1450- logging.debug("gateway: %s" % self.vm.gw)
1451- logging.debug("dns: %s" % self.vm.dns)
1452-
1453-register_plugin(NetworkPlugin)
1454+ self.context.set_setting('gw', numeric_to_dotted_ip(numgw))
1455+
1456+ dns = self.context.get_setting('dns')
1457+ if not dns:
1458+ self.context.dns = self.context.gw
1459+ self.context.set_setting('dns', self.context.get_setting('gw'))
1460+
1461+ self.context.set_setting('mask', numeric_to_dotted_ip(nummask))
1462+
1463+ logging.debug("net: %s" % self.context.get_setting('net'))
1464+ logging.debug("netmask: %s" % self.context.get_setting('mask'))
1465+ logging.debug("broadcast: %s" % self.context.get_setting('bcast'))
1466+ logging.debug("gateway: %s" % self.context.get_setting('gw'))
1467+ logging.debug("dns: %s" % self.context.get_setting('dns'))
1468+
1469+register_distro_plugin(NetworkDistroPlugin)
1470+register_hypervisor_plugin(NetworkHypervisorPlugin)
1471
1472=== modified file 'VMBuilder/plugins/postinst/__init__.py'
1473--- VMBuilder/plugins/postinst/__init__.py 2009-08-12 22:45:45 +0000
1474+++ VMBuilder/plugins/postinst/__init__.py 2010-02-18 16:03:14 +0000
1475@@ -16,7 +16,7 @@
1476 # You should have received a copy of the GNU General Public License
1477 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1478 #
1479-from VMBuilder import register_plugin, Plugin, VMBuilderUserError
1480+from VMBuilder import register_distro_plugin, Plugin, VMBuilderUserError
1481 from VMBuilder.util import run_cmd
1482
1483 import logging
1484@@ -32,43 +32,43 @@
1485 name ='Post install plugin'
1486
1487 def register_options(self):
1488- group = self.vm.setting_group('Post install actions')
1489+ group = self.context.setting_group('Post install actions')
1490 group.add_option('--copy', metavar='FILE', help="Read 'source dest' lines from FILE, copying source files from host to dest in the guest's file system.")
1491 group.add_option('--execscript', '--exec', metavar='SCRIPT', help="Run SCRIPT after distro installation finishes. Script will be called with the guest's chroot as first argument, so you can use 'chroot $1 <cmd>' to run code in the virtual machine.")
1492- self.vm.register_setting_group(group)
1493+ self.context.register_setting_group(group)
1494
1495 def preflight_check(self):
1496- if self.vm.copy:
1497- logging.debug("Checking if --copy PATH exists: %s" % self.vm.copy)
1498- if not(os.path.isfile(self.vm.copy)):
1499- raise VMBuilderUserError('The path to the --copy directives is invalid: %s. Make sure you are providing a full path.' % self.vm.copy)
1500+ if self.context.copy:
1501+ logging.debug("Checking if --copy PATH exists: %s" % self.context.copy)
1502+ if not(os.path.isfile(self.context.copy)):
1503+ raise VMBuilderUserError('The path to the --copy directives is invalid: %s. Make sure you are providing a full path.' % self.context.copy)
1504
1505- if self.vm.execscript:
1506- logging.debug("Checking if --exec PATH exists: %s" % self.vm.execscript)
1507- if not(os.path.isfile(self.vm.execscript)):
1508- raise VMBuilderUserError('The path to the --execscript file is invalid: %s. Make sure you are providing a full path.' % self.vm.execscript)
1509+ if self.context.execscript:
1510+ logging.debug("Checking if --exec PATH exists: %s" % self.context.execscript)
1511+ if not(os.path.isfile(self.context.execscript)):
1512+ raise VMBuilderUserError('The path to the --execscript file is invalid: %s. Make sure you are providing a full path.' % self.context.execscript)
1513
1514- logging.debug("Checking permissions of --exec PATH: %s" % self.vm.execscript)
1515- if not os.access(self.vm.execscript, os.X_OK|os.R_OK):
1516- raise VMBuilderUserError('The path to the --execscript file has invalid permissions: %s. Make sure the path is readable and executable.' % self.vm.execscript)
1517+ logging.debug("Checking permissions of --exec PATH: %s" % self.context.execscript)
1518+ if not os.access(self.context.execscript, os.X_OK|os.R_OK):
1519+ raise VMBuilderUserError('The path to the --execscript file has invalid permissions: %s. Make sure the path is readable and executable.' % self.context.execscript)
1520
1521 def post_install(self):
1522- if self.vm.copy:
1523- logging.info("Copying files specified by --copy in: %s" % self.vm.copy)
1524+ if self.context.copy:
1525+ logging.info("Copying files specified by --copy in: %s" % self.context.copy)
1526 try:
1527- for line in file(self.vm.copy):
1528+ for line in file(self.context.copy):
1529 pair = line.strip().split(' ')
1530 if len(pair) < 2: # skip blank and incomplete lines
1531 continue
1532- util.run_cmd('cp', '-LpR', pair[0], '%s%s' % (self.vm.installdir, pair[1]))
1533+ util.run_cmd('cp', '-LpR', pair[0], '%s%s' % (self.context.installdir, pair[1]))
1534
1535 except IOError, (errno, strerror):
1536 raise VMBuilderUserError("%s executing --copy directives: %s" % (errno, strerror))
1537
1538- if self.vm.execscript:
1539- logging.info("Executing script: %s" % self.vm.execscript)
1540- util.run_cmd(self.vm.execscript, self.vm.installdir)
1541+ if self.context.execscript:
1542+ logging.info("Executing script: %s" % self.context.execscript)
1543+ util.run_cmd(self.context.execscript, self.vm.installdir)
1544
1545 return True
1546
1547-register_plugin(postinst)
1548+#register_plugin(postinst)
1549
1550=== modified file 'VMBuilder/plugins/ubuntu/dapper.py'
1551--- VMBuilder/plugins/ubuntu/dapper.py 2009-12-12 04:12:30 +0000
1552+++ VMBuilder/plugins/ubuntu/dapper.py 2010-02-18 16:03:14 +0000
1553@@ -25,7 +25,7 @@
1554 import tempfile
1555 import VMBuilder
1556 import VMBuilder.disk as disk
1557-from VMBuilder.util import run_cmd, give_to_caller
1558+from VMBuilder.util import run_cmd #, give_to_caller
1559
1560 class Dapper(suite.Suite):
1561 updategrub = "/sbin/update-grub"
1562@@ -48,6 +48,7 @@
1563 return arch in self.valid_flavours.keys()
1564
1565 def install(self, destdir):
1566+ raise VMBuilderException('Do not call this method!')
1567 self.destdir = destdir
1568
1569 logging.debug("debootstrapping")
1570@@ -67,7 +68,7 @@
1571 logging.debug("Creating devices")
1572 self.create_devices()
1573
1574- if self.vm.hypervisor.needs_bootloader:
1575+ if self.distro.hypervisor.needs_bootloader:
1576 logging.debug("Installing grub")
1577 self.install_grub()
1578
1579@@ -80,7 +81,7 @@
1580 logging.debug('Binding /dev and /proc filesystems')
1581 self.mount_dev_proc()
1582
1583- if self.vm.hypervisor.needs_bootloader:
1584+ if self.context.hypervisor.needs_bootloader:
1585 logging.debug("Installing menu.list")
1586 self.install_menu_lst()
1587
1588@@ -120,130 +121,166 @@
1589 logging.debug('Unbinding /dev and /proc filesystems')
1590 self.unmount_dev_proc()
1591
1592- if hasattr(self.vm, 'ec2') and self.vm.ec2:
1593+ if hasattr(self.context, 'ec2') and self.context.ec2:
1594 logging.debug("Configuring for ec2")
1595 self.install_ec2()
1596
1597 logging.debug("Unpreventing daemons from starting")
1598 self.unprevent_daemons_starting()
1599
1600- if self.vm.manifest:
1601+ if self.context.manifest:
1602 logging.debug("Creating manifest")
1603 manifest_contents = self.run_in_target('dpkg-query', '-W', '--showformat=${Package} ${Version}\n')
1604- fp = open(self.vm.manifest, 'w')
1605+ fp = open(self.context.manifest, 'w')
1606 fp.write(manifest_contents)
1607 fp.close
1608- give_to_caller(self.vm.manifest)
1609+ give_to_caller(self.context.manifest)
1610
1611 def update(self):
1612 self.run_in_target('apt-get', '-y', '--force-yes', 'dist-upgrade',
1613 env={ 'DEBIAN_FRONTEND' : 'noninteractive' })
1614
1615 def install_authorized_keys(self):
1616- if self.vm.ssh_key:
1617- os.mkdir('%s/root/.ssh' % self.destdir, 0700)
1618- shutil.copy(self.vm.ssh_key, '%s/root/.ssh/authorized_keys' % self.destdir)
1619- os.chmod('%s/root/.ssh/authorized_keys' % self.destdir, 0644)
1620- if self.vm.ssh_user_key:
1621- os.mkdir('%s/home/%s/.ssh' % (self.destdir, self.vm.user), 0700)
1622- shutil.copy(self.vm.ssh_user_key, '%s/home/%s/.ssh/authorized_keys' % (self.destdir, self.vm.user))
1623- os.chmod('%s/home/%s/.ssh/authorized_keys' % (self.destdir, self.vm.user), 0644)
1624- self.run_in_target('chown', '-R', '%s:%s' % (self.vm.user,)*2, '/home/%s/.ssh/' % (self.vm.user))
1625-
1626- if self.vm.ssh_user_key or self.vm.ssh_key:
1627- if not self.vm.addpkg:
1628- self.vm.addpkg = []
1629- self.vm.addpkg += ['openssh-server']
1630+ ssh_key = self.context.get_setting('ssh-key')
1631+ if ssh_key:
1632+ os.mkdir('%s/root/.ssh' % self.context.chroot_dir, 0700)
1633+ shutil.copy(ssh_key, '%s/root/.ssh/authorized_keys' % self.context.chroot_dir)
1634+ os.chmod('%s/root/.ssh/authorized_keys' % self.context.chroot_dir, 0644)
1635+
1636+ user = self.context.get_setting('user')
1637+ ssh_user_key = self.context.get_setting('ssh-user-key')
1638+ if ssh_user_key:
1639+ os.mkdir('%s/home/%s/.ssh' % (self.context.chroot_dir, user), 0700)
1640+ shutil.copy(ssh_user_key, '%s/home/%s/.ssh/authorized_keys' % (self.context.chroot_dir, user))
1641+ os.chmod('%s/home/%s/.ssh/authorized_keys' % (self.context.chroot_dir, user), 0644)
1642+ self.run_in_target('chown', '-R', '%s:%s' % (user,)*2, '/home/%s/.ssh/' % (user))
1643+
1644+ if ssh_user_key or ssh_key:
1645+ addpkg = self.context.get_setting('addpkg')
1646+ addpkg += ['openssh-server']
1647+ self.context.set_setting('addpkg', addpkg)
1648
1649 def mount_dev_proc(self):
1650- run_cmd('mount', '--bind', '/dev', '%s/dev' % self.destdir)
1651- self.vm.add_clean_cmd('umount', '%s/dev' % self.destdir, ignore_fail=True)
1652+ run_cmd('mount', '--bind', '/dev', '%s/dev' % self.context.chroot_dir)
1653+ self.context.add_clean_cb(self.unmount_dev)
1654
1655- run_cmd('mount', '--bind', '/dev/pts', '%s/dev/pts' % self.destdir)
1656- self.vm.add_clean_cmd('umount', '%s/dev/pts' % self.destdir, ignore_fail=True)
1657+ run_cmd('mount', '--bind', '/dev/pts', '%s/dev/pts' % self.context.chroot_dir)
1658+ self.context.add_clean_cb(self.unmount_dev_pts)
1659
1660 self.run_in_target('mount', '-t', 'proc', 'proc', '/proc')
1661- self.vm.add_clean_cmd('umount', '%s/proc' % self.destdir, ignore_fail=True)
1662-
1663- def unmount_dev_proc(self):
1664- run_cmd('umount', '%s/dev/pts' % self.destdir)
1665- run_cmd('umount', '%s/dev' % self.destdir)
1666- run_cmd('umount', '%s/proc' % self.destdir)
1667+ self.context.add_clean_cb(self.unmount_proc)
1668+
1669+ def unmount_proc(self):
1670+ self.context.cancel_cleanup(self.unmount_proc)
1671+ run_cmd('umount', '%s/proc' % self.context.chroot_dir)
1672+
1673+ def unmount_dev_pts(self):
1674+ self.context.cancel_cleanup(self.unmount_dev_pts)
1675+ run_cmd('umount', '%s/dev/pts' % self.context.chroot_dir)
1676+
1677+ def unmount_dev(self):
1678+ self.context.cancel_cleanup(self.unmount_dev)
1679+ run_cmd('umount', '%s/dev' % self.context.chroot_dir)
1680
1681 def update_passwords(self):
1682 # Set the user password, using md5
1683- self.run_in_target(stdin=('%s:%s\n' % (self.vm.user, getattr(self.vm, 'pass'))), *self.chpasswd_cmd)
1684+ user = self.context.get_setting('user')
1685+ passwd = self.context.get_setting('pass')
1686+ self.run_in_target(stdin=('%s:%s\n' % (user, passwd)), *self.chpasswd_cmd)
1687
1688 # Lock root account only if we didn't set the root password
1689- if self.vm.rootpass:
1690- self.run_in_target(stdin=('%s:%s\n' % ('root', self.vm.rootpass)), *self.chpasswd_cmd)
1691+ rootpass = self.context.get_setting('rootpass')
1692+ if rootpass:
1693+ self.run_in_target(stdin=('%s:%s\n' % ('root', rootpass)), *self.chpasswd_cmd)
1694 else:
1695 self.run_in_target('usermod', '-L', 'root')
1696
1697- if self.vm.lock_user:
1698- logging.info('Locking %s' %(self.vm.user))
1699- self.run_in_target('usermod', '-L', self.vm.user)
1700+ lock_user = self.context.get_setting('lock-user')
1701+ if lock_user:
1702+ logging.info('Locking %s' % (user, ))
1703+ self.run_in_target('usermod', '-L', user)
1704
1705 def create_initial_user(self):
1706- if self.vm.uid:
1707- self.run_in_target('adduser', '--disabled-password', '--uid', self.vm.uid, '--gecos', self.vm.name, self.vm.user)
1708+ uid = self.context.get_setting('uid')
1709+ name = self.context.get_setting('name')
1710+ user = self.context.get_setting('user')
1711+ if uid:
1712+ self.run_in_target('adduser', '--disabled-password', '--uid', uid, '--gecos', name, user)
1713 else:
1714- self.run_in_target('adduser', '--disabled-password', '--gecos', self.vm.name, self.vm.user)
1715+ self.run_in_target('adduser', '--disabled-password', '--gecos', name, user)
1716+
1717 self.run_in_target('addgroup', '--system', 'admin')
1718- self.run_in_target('adduser', self.vm.user, 'admin')
1719+ self.run_in_target('adduser', user, 'admin')
1720
1721 self.install_from_template('/etc/sudoers', 'sudoers')
1722 for group in ['adm', 'audio', 'cdrom', 'dialout', 'floppy', 'video', 'plugdev', 'dip', 'netdev', 'powerdev', 'lpadmin', 'scanner']:
1723- self.run_in_target('adduser', self.vm.user, group, ignore_fail=True)
1724+ self.run_in_target('adduser', user, group, ignore_fail=True)
1725
1726 self.update_passwords()
1727
1728 def kernel_name(self):
1729- return 'linux-image-%s' % (self.vm.flavour or self.default_flavour[self.vm.arch],)
1730-
1731- def config_network(self):
1732- self.vm.install_file('/etc/hostname', self.vm.hostname)
1733- self.install_from_template('/etc/hosts', 'etc_hosts', { 'hostname' : self.vm.hostname, 'domain' : self.vm.domain })
1734- self.install_from_template('/etc/network/interfaces', 'interfaces')
1735+ flavour = self.context.get_setting('flavour')
1736+ arch = self.context.get_setting('arch')
1737+ return 'linux-image-%s' % (flavour or self.default_flavour[arch],)
1738+
1739+ def config_host_and_domainname(self):
1740+ hostname = self.context.get_setting('hostname')
1741+ domain = self.context.get_setting('domain')
1742+ self.context.install_file('/etc/hostname', hostname)
1743+ self.install_from_template('/etc/hosts', 'etc_hosts', { 'hostname' : hostname, 'domain' : domain })
1744+
1745+ def config_interfaces(self, nics):
1746+ self.install_from_template('/etc/network/interfaces', 'interfaces', { 'ip' : nics[0].type == 'dhcp' and 'dhcp' or nics[0].ip })
1747
1748 def unprevent_daemons_starting(self):
1749- os.unlink('%s/usr/sbin/policy-rc.d' % self.destdir)
1750+ os.unlink('%s/usr/sbin/policy-rc.d' % self.context.chroot_dir)
1751
1752 def prevent_daemons_starting(self):
1753 os.chmod(self.install_from_template('/usr/sbin/policy-rc.d', 'nostart-policy-rc.d'), 0755)
1754
1755 def install_extras(self):
1756- if not self.vm.addpkg and not self.vm.removepkg:
1757+ addpkg = self.context.get_setting('addpkg')
1758+ removepkg = self.context.get_setting('removepkg')
1759+ if not addpkg and not removepkg:
1760 return
1761 cmd = ['apt-get', 'install', '-y', '--force-yes']
1762- cmd += self.vm.addpkg or []
1763- cmd += ['%s-' % pkg for pkg in self.vm.removepkg or []]
1764+ cmd += addpkg or []
1765+ cmd += ['%s-' % pkg for pkg in removepkg or []]
1766 self.run_in_target(env={ 'DEBIAN_FRONTEND' : 'noninteractive' }, *cmd)
1767
1768 def unmount_volatile(self):
1769- for mntpnt in glob.glob('%s/lib/modules/*/volatile' % self.destdir):
1770+ for mntpnt in glob.glob('%s/lib/modules/*/volatile' % self.context.chroot_dir):
1771 logging.debug("Unmounting %s" % mntpnt)
1772 run_cmd('umount', mntpnt)
1773
1774- def install_menu_lst(self):
1775+ def install_menu_lst(self, disks):
1776 self.run_in_target(self.updategrub, '-y')
1777- self.mangle_grub_menu_lst()
1778+ self.mangle_grub_menu_lst(disks)
1779 self.run_in_target(self.updategrub)
1780 self.run_in_target('grub-set-default', '0')
1781
1782- def mangle_grub_menu_lst(self):
1783- bootdev = disk.bootpart(self.vm.disks)
1784- run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=\/dev\/hd%s%d\\2/g' % (bootdev.disk.devletters(), bootdev.get_index()+1), '%s/boot/grub/menu.lst' % self.destdir)
1785- run_cmd('sed', '-ie', 's/^# groot.*/# groot %s/g' % bootdev.get_grub_id(), '%s/boot/grub/menu.lst' % self.destdir)
1786- run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.destdir)
1787+ def mangle_grub_menu_lst(self, disks):
1788+ bootdev = disk.bootpart(disks)
1789+ run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=\/dev\/hd%s%d\\2/g' % (bootdev.disk.devletters(), bootdev.get_index()+1), '%s/boot/grub/menu.lst' % self.context.chroot_dir)
1790+ run_cmd('sed', '-ie', 's/^# groot.*/# groot %s/g' % bootdev.get_grub_id(), '%s/boot/grub/menu.lst' % self.context.chroot_dir)
1791+ run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.context.chroot_dir)
1792
1793 def install_sources_list(self, final=False):
1794 if final:
1795- mirror, updates_mirror, security_mirror = self.vm.mirror, self.vm.mirror, self.vm.security_mirror
1796+ mirror = updates_mirror = self.context.get_setting('mirror')
1797+ security_mirror = self.context.get_setting('security-mirror')
1798 else:
1799 mirror, updates_mirror, security_mirror = self.install_mirrors()
1800
1801- self.install_from_template('/etc/apt/sources.list', 'sources.list', { 'mirror' : mirror, 'security_mirror' : security_mirror, 'updates_mirror' : updates_mirror })
1802+ components = self.context.get_setting('components')
1803+ ppa = self.context.get_setting('ppa')
1804+ suite = self.context.get_setting('suite')
1805+ self.install_from_template('/etc/apt/sources.list', 'sources.list', { 'mirror' : mirror,
1806+ 'security_mirror' : security_mirror,
1807+ 'updates_mirror' : updates_mirror,
1808+ 'components' : components,
1809+ 'ppa' : ppa,
1810+ 'suite' : suite })
1811
1812 # If setting up the final mirror, allow apt-get update to fail
1813 # (since we might be on a complete different network than the
1814@@ -251,34 +288,40 @@
1815 self.run_in_target('apt-get', 'update', ignore_fail=final)
1816
1817 def install_apt_proxy(self):
1818- if self.vm.proxy is not None:
1819- self.vm.install_file('/etc/apt/apt.conf', '// Proxy added by vmbuilder\nAcquire::http { Proxy "%s"; };' % self.vm.proxy)
1820+ proxy = self.context.get_setting('proxy')
1821+ if proxy is not None:
1822+ self.context.install_file('/etc/apt/apt.conf', '// Proxy added by vmbuilder\nAcquire::http { Proxy "%s"; };' % proxy)
1823
1824- def install_fstab(self):
1825- if self.vm.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
1826- self.install_from_template('/etc/fstab', 'dapper_fstab_fsimage', { 'fss' : disk.get_ordered_filesystems(self.vm), 'prefix' : self.disk_prefix })
1827- else:
1828- self.install_from_template('/etc/fstab', 'dapper_fstab', { 'parts' : disk.get_ordered_partitions(self.vm.disks), 'prefix' : self.disk_prefix })
1829+ def install_fstab(self, disks, filesystems):
1830+ self.install_from_template('/etc/fstab', 'dapper_fstab', { 'parts' : disk.get_ordered_partitions(disks), 'prefix' : self.disk_prefix })
1831
1832 def install_device_map(self):
1833 self.install_from_template('/boot/grub/device.map', 'devicemap', { 'prefix' : self.disk_prefix })
1834
1835 def debootstrap(self):
1836- cmd = ['/usr/sbin/debootstrap', '--arch=%s' % self.vm.arch]
1837- if self.vm.variant:
1838- cmd += ['--variant=%s' % self.vm.variant]
1839- cmd += [self.vm.suite, self.destdir, self.debootstrap_mirror()]
1840+ arch = self.context.get_setting('arch')
1841+ cmd = ['/usr/sbin/debootstrap', '--arch=%s' % arch]
1842+
1843+ variant = self.context.get_setting('variant')
1844+ if variant:
1845+ cmd += ['--variant=%s' % variant]
1846+
1847+ suite = self.context.get_setting('suite')
1848+ cmd += [suite, self.context.chroot_dir, self.debootstrap_mirror()]
1849 kwargs = { 'env' : { 'DEBIAN_FRONTEND' : 'noninteractive' } }
1850- if self.vm.proxy:
1851- kwargs['env']['http_proxy'] = self.vm.proxy
1852+
1853+ proxy = self.context.get_setting('proxy')
1854+ if proxy:
1855+ kwargs['env']['http_proxy'] = proxy
1856 run_cmd(*cmd, **kwargs)
1857
1858 def debootstrap_mirror(self):
1859- if self.vm.iso:
1860+ iso = self.context.get_setting('iso')
1861+ if iso:
1862 isodir = tempfile.mkdtemp()
1863- self.vm.add_clean_cb(lambda:os.rmdir(isodir))
1864- run_cmd('mount', '-o', 'loop', '-t', 'iso9660', self.vm.iso, isodir)
1865- self.vm.add_clean_cmd('umount', isodir)
1866+ self.context.add_clean_cb(lambda:os.rmdir(isodir))
1867+ run_cmd('mount', '-o', 'loop', '-t', 'iso9660', iso, isodir)
1868+ self.context.add_clean_cmd('umount', isodir)
1869 self.iso_mounted = True
1870
1871 return 'file://%s' % isodir
1872@@ -287,46 +330,48 @@
1873
1874
1875 def install_mirrors(self):
1876- if self.vm.install_mirror:
1877- mirror = self.vm.install_mirror
1878- else:
1879- mirror = self.vm.mirror
1880-
1881- if self.vm.install_mirror:
1882- updates_mirror = self.vm.install_mirror
1883- else:
1884- updates_mirror = self.vm.mirror
1885-
1886- if self.vm.install_security_mirror:
1887- security_mirror = self.vm.install_security_mirror
1888- else:
1889- security_mirror = self.vm.security_mirror
1890+ install_mirror = self.context.get_setting('install-mirror')
1891+ if install_mirror:
1892+ mirror = install_mirror
1893+ else:
1894+ mirror = self.context.get_setting('mirror')
1895+
1896+ updates_mirror = mirror
1897+
1898+ install_security_mirror = self.context.get_setting('install-security-mirror')
1899+ if install_security_mirror:
1900+ security_mirror = install_security_mirror
1901+ else:
1902+ security_mirror = self.context.get_setting('security-mirror')
1903
1904 return (mirror, updates_mirror, security_mirror)
1905
1906- def install_kernel(self):
1907+ def install_kernel(self, destdir):
1908 self.install_from_template('/etc/kernel-img.conf', 'kernelimg', { 'updategrub' : self.updategrub })
1909- run_cmd('chroot', self.destdir, 'apt-get', '--force-yes', '-y', 'install', self.kernel_name(), 'grub')
1910+ run_cmd('chroot', destdir, 'apt-get', '--force-yes', '-y', 'install', self.kernel_name(), 'grub')
1911
1912- def install_grub(self):
1913+ def install_grub(self, chroot_dir):
1914+ arch = self.context.get_setting('arch')
1915 self.run_in_target('apt-get', '--force-yes', '-y', 'install', 'grub')
1916- run_cmd('rsync', '-a', '%s%s/%s/' % (self.destdir, self.grubroot, self.vm.arch == 'amd64' and 'x86_64-pc' or 'i386-pc'), '%s/boot/grub/' % self.destdir)
1917+ run_cmd('rsync', '-a', '%s%s/%s/' % (chroot_dir, self.grubroot, arch == 'amd64' and 'x86_64-pc' or 'i386-pc'), '%s/boot/grub/' % chroot_dir)
1918
1919 def create_devices(self):
1920- import VMBuilder.plugins.xen
1921+ pass
1922+# FIXME
1923+# import VMBuilder.plugins.xen
1924
1925- if isinstance(self.vm.hypervisor, VMBuilder.plugins.xen.Xen):
1926- self.run_in_target('mknod', '/dev/xvda', 'b', '202', '0')
1927- self.run_in_target('mknod', '/dev/xvda1', 'b', '202', '1')
1928- self.run_in_target('mknod', '/dev/xvda2', 'b', '202', '2')
1929- self.run_in_target('mknod', '/dev/xvda3', 'b', '202', '3')
1930- self.run_in_target('mknod', '/dev/xvc0', 'c', '204', '191')
1931+# if isinstance(self.context.hypervisor, VMBuilder.plugins.xen.Xen):
1932+# self.run_in_target('mknod', '/dev/xvda', 'b', '202', '0')
1933+# self.run_in_target('mknod', '/dev/xvda1', 'b', '202', '1')
1934+# self.run_in_target('mknod', '/dev/xvda2', 'b', '202', '2')
1935+# self.run_in_target('mknod', '/dev/xvda3', 'b', '202', '3')
1936+# self.run_in_target('mknod', '/dev/xvc0', 'c', '204', '191')
1937
1938 def install_from_template(self, *args, **kwargs):
1939- return self.vm.distro.install_from_template(*args, **kwargs)
1940+ return self.context.install_from_template(*args, **kwargs)
1941
1942 def run_in_target(self, *args, **kwargs):
1943- return self.vm.distro.run_in_target(*args, **kwargs)
1944+ return self.context.run_in_target(*args, **kwargs)
1945
1946 def copy_to_target(self, infile, destpath):
1947 logging.debug("Copying %s on host to %s in guest" % (infile, destpath))
1948@@ -350,9 +395,9 @@
1949 self.copy_to_target('/etc/default/locale', '/etc/default/locale')
1950 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'libc6')
1951 self.run_in_target('locale-gen', 'en_US')
1952- if self.vm.lang:
1953- self.run_in_target('locale-gen', self.vm.lang)
1954- self.install_from_template('/etc/default/locale', 'locale', { 'lang' : self.vm.lang })
1955+ if self.context.lang:
1956+ self.run_in_target('locale-gen', self.context.lang)
1957+ self.install_from_template('/etc/default/locale', 'locale', { 'lang' : self.context.lang })
1958 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'locales')
1959 self.run_in_target('dpkg-reconfigure', '-pcritical', 'locales')
1960
1961@@ -360,12 +405,13 @@
1962 shutil.copy(logfile, '%s/var/log/vmbuilder-install.log' % (rootdir,))
1963
1964 def set_timezone(self):
1965- if self.vm.timezone:
1966- os.unlink('%s/etc/localtime' % self.destdir)
1967- shutil.copy('%s/usr/share/zoneinfo/%s' % (self.destdir, self.vm.timezone), '%s/etc/localtime' % (self.destdir,))
1968+ timezone = self.context.get_setting('timezone')
1969+ if timezone:
1970+ os.unlink('%s/etc/localtime' % self.context.chroot_dir)
1971+ shutil.copy('%s/usr/share/zoneinfo/%s' % (self.context.chroot_dir, timezone), '%s/etc/localtime' % (self.context.chroot_dir,))
1972
1973 def install_ec2(self):
1974- if self.vm.ec2:
1975+ if self.context.ec2:
1976 logging.debug('This suite does not support ec2')
1977
1978 def disable_hwclock_access(self):
1979@@ -373,3 +419,6 @@
1980 fp.write('HWCLOCKACCESS=no')
1981 fp.close()
1982
1983+ def has_256_bit_inode_ext3_support(self):
1984+ return False
1985+
1986
1987=== modified file 'VMBuilder/plugins/ubuntu/distro.py'
1988--- VMBuilder/plugins/ubuntu/distro.py 2010-01-19 17:43:04 +0000
1989+++ VMBuilder/plugins/ubuntu/distro.py 2010-02-18 16:03:14 +0000
1990@@ -39,66 +39,66 @@
1991 xen_kernel = ''
1992
1993 def register_options(self):
1994- group = self.vm.setting_group('Package options')
1995- group.add_option('--addpkg', action='append', metavar='PKG', help='Install PKG into the guest (can be specfied multiple times).')
1996- group.add_option('--removepkg', action='append', metavar='PKG', help='Remove PKG from the guest (can be specfied multiple times)')
1997- self.vm.register_setting_group(group)
1998+ group = self.setting_group('Package options')
1999+ group.add_setting('addpkg', type='list', metavar='PKG', help='Install PKG into the guest (can be specfied multiple times).')
2000+ group.add_setting('removepkg', type='list', metavar='PKG', help='Remove PKG from the guest (can be specfied multiple times)')
2001
2002- group = self.vm.setting_group('General OS options')
2003+ group = self.setting_group('General OS options')
2004 self.host_arch = run_cmd('dpkg', '--print-architecture').rstrip()
2005- group.add_option('-a', '--arch', default=self.host_arch, help='Specify the target architecture. Valid options: amd64 i386 lpia (defaults to host arch)')
2006- group.add_option('--hostname', default='ubuntu', help='Set NAME as the hostname of the guest. Default: ubuntu. Also uses this name as the VM name.')
2007- self.vm.register_setting_group(group)
2008-
2009- group = self.vm.setting_group('Installation options')
2010- group.add_option('--suite', default='jaunty', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
2011- group.add_option('--flavour', '--kernel-flavour', help='Kernel flavour to use. Default and valid options depend on architecture and suite')
2012- group.add_option('--variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.')
2013- group.add_option('--iso', metavar='PATH', help='Use an iso image as the source for installation of file. Full path to the iso must be provided. If --mirror is also provided, it will be used in the final sources.list of the vm. This requires suite and kernel parameter to match what is available on the iso, obviously.')
2014- group.add_option('--mirror', metavar='URL', help='Use Ubuntu mirror at URL instead of the default, which is http://archive.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise')
2015- group.add_option('--proxy', metavar='URL', help='Use proxy at URL for cached packages')
2016- group.add_option('--install-mirror', metavar='URL', help='Use Ubuntu mirror at URL for the installation only. Apt\'s sources.list will still use default or URL set by --mirror')
2017- group.add_option('--security-mirror', metavar='URL', help='Use Ubuntu security mirror at URL instead of the default, which is http://security.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise.')
2018- group.add_option('--install-security-mirror', metavar='URL', help='Use the security mirror at URL for installation only. Apt\'s sources.list will still use default or URL set by --security-mirror')
2019- group.add_option('--components', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,universe).')
2020- group.add_option('--ppa', metavar='PPA', action='append', help='Add ppa belonging to PPA to the vm\'s sources.list.')
2021- group.add_option('--lang', metavar='LANG', default=self.get_locale(), help='Set the locale to LANG [default: %default]')
2022- group.add_option('--timezone', metavar='TZ', default='UTC', help='Set the timezone to TZ in the vm. [default: %default]')
2023- self.vm.register_setting_group(group)
2024-
2025- group = self.vm.setting_group('Settings for the initial user')
2026- group.add_option('--user', default='ubuntu', help='Username of initial user [default: %default]')
2027- group.add_option('--name', default='Ubuntu', help='Full name of initial user [default: %default]')
2028- group.add_option('--pass', default='ubuntu', help='Password of initial user [default: %default]')
2029- group.add_option('--rootpass', help='Initial root password (WARNING: this has strong security implications).')
2030- group.add_option('--uid', help='Initial UID value.')
2031- group.add_option('--gid', help='Initial GID value.')
2032- group.add_option('--lock-user', action='store_true', help='Lock the initial user [default %default]')
2033- self.vm.register_setting_group(group)
2034-
2035- group = self.vm.setting_group('Other options')
2036- group.add_option('--ssh-key', metavar='PATH', help='Add PATH to root\'s ~/.ssh/authorized_keys (WARNING: this has strong security implications).')
2037- group.add_option('--ssh-user-key', help='Add PATH to the user\'s ~/.ssh/authorized_keys.')
2038- group.add_option('--manifest', metavar='PATH', help='If passed, a manifest will be written to PATH')
2039- self.vm.register_setting_group(group)
2040+ group.add_setting('arch', extra_args=['-a'], default=self.host_arch, help='Specify the target architecture. Valid options: amd64 i386 lpia (defaults to host arch)')
2041+ group.add_setting('hostname', default='ubuntu', help='Set NAME as the hostname of the guest. Default: ubuntu. Also uses this name as the VM name.')
2042+
2043+ group = self.setting_group('Installation options')
2044+ group.add_setting('suite', default='jaunty', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
2045+ group.add_setting('flavour', extra_args=['--kernel-flavour'], help='Kernel flavour to use. Default and valid options depend on architecture and suite')
2046+ group.add_setting('variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.')
2047+ group.add_setting('iso', metavar='PATH', help='Use an iso image as the source for installation of file. Full path to the iso must be provided. If --mirror is also provided, it will be used in the final sources.list of the vm. This requires suite and kernel parameter to match what is available on the iso, obviously.')
2048+ group.add_setting('mirror', metavar='URL', help='Use Ubuntu mirror at URL instead of the default, which is http://archive.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise')
2049+ group.add_setting('proxy', metavar='URL', help='Use proxy at URL for cached packages')
2050+ group.add_setting('install-mirror', metavar='URL', help='Use Ubuntu mirror at URL for the installation only. Apt\'s sources.list will still use default or URL set by --mirror')
2051+ group.add_setting('security-mirror', metavar='URL', help='Use Ubuntu security mirror at URL instead of the default, which is http://security.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise.')
2052+ group.add_setting('install-security-mirror', metavar='URL', help='Use the security mirror at URL for installation only. Apt\'s sources.list will still use default or URL set by --security-mirror')
2053+ group.add_setting('components', type='list', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,universe).')
2054+ group.add_setting('ppa', metavar='PPA', type='list', help='Add ppa belonging to PPA to the vm\'s sources.list.')
2055+ group.add_setting('lang', metavar='LANG', default=self.get_locale(), help='Set the locale to LANG [default: %default]')
2056+ group.add_setting('timezone', metavar='TZ', default='UTC', help='Set the timezone to TZ in the vm. [default: %default]')
2057+
2058+ group = self.setting_group('Settings for the initial user')
2059+ group.add_setting('user', default='ubuntu', help='Username of initial user [default: %default]')
2060+ group.add_setting('name', default='Ubuntu', help='Full name of initial user [default: %default]')
2061+ group.add_setting('pass', default='ubuntu', help='Password of initial user [default: %default]')
2062+ group.add_setting('rootpass', help='Initial root password (WARNING: this has strong security implications).')
2063+ group.add_setting('uid', type='int', help='Initial UID value.')
2064+ group.add_setting('gid', help='Initial GID value.')
2065+ group.add_setting('lock-user', type='bool', default=False, help='Lock the initial user [default: %default]')
2066+
2067+ group = self.setting_group('Other options')
2068+ group.add_setting('ssh-key', metavar='PATH', help='Add PATH to root\'s ~/.ssh/authorized_keys (WARNING: this has strong security implications).')
2069+ group.add_setting('ssh-user-key', help='Add PATH to the user\'s ~/.ssh/authorized_keys.')
2070+ group.add_setting('manifest', metavar='PATH', help='If passed, a manifest will be written to PATH')
2071
2072 def set_defaults(self):
2073- if not self.vm.mirror:
2074- if self.vm.arch == 'lpia':
2075- self.vm.mirror = 'http://ports.ubuntu.com/ubuntu-ports'
2076- else:
2077- self.vm.mirror = 'http://archive.ubuntu.com/ubuntu'
2078-
2079- if not self.vm.security_mirror:
2080- if self.vm.arch == 'lpia':
2081- self.vm.security_mirror = 'http://ports.ubuntu.com/ubuntu-ports'
2082- else:
2083- self.vm.security_mirror = 'http://security.ubuntu.com/ubuntu'
2084-
2085- if not self.vm.components:
2086- self.vm.components = ['main', 'restricted', 'universe']
2087+ mirror = self.get_setting('mirror')
2088+ security_mirror = self.get_setting('security-mirror')
2089+ arch = self.get_setting('arch')
2090+ components = self.get_setting('components')
2091+
2092+ if not mirror:
2093+ if arch == 'lpia':
2094+ self.set_setting_default('mirror', 'http://ports.ubuntu.com/ubuntu-ports')
2095+ else:
2096+ self.set_setting_default('mirror', 'http://archive.ubuntu.com/ubuntu')
2097+
2098+ if not security_mirror:
2099+ if arch == 'lpia':
2100+ self.set_setting_default('security-mirror', 'http://ports.ubuntu.com/ubuntu-ports')
2101+ else:
2102+ self.set_setting_default('security-mirror', 'http://security.ubuntu.com/ubuntu')
2103+
2104+ if not components:
2105+ self.set_setting_default('components', ['main', 'restricted', 'universe'])
2106 else:
2107- self.vm.components = self.vm.components.split(',')
2108+ self.set_setting_default('components', components.split(','))
2109
2110 def get_locale(self):
2111 return os.getenv('LANG')
2112@@ -108,40 +108,70 @@
2113 lead to failure, and since we can check them before we start setting up disk
2114 and whatnot, we might as well go ahead an do this now."""
2115
2116- if not self.vm.suite in self.suites:
2117- raise VMBuilderUserError('Invalid suite. Valid suites are: %s' % ' '.join(self.suites))
2118+ suite = self.get_setting('suite')
2119+ if not suite in self.suites:
2120+ raise VMBuilderUserError('Invalid suite: "%s". Valid suites are: %s' % (suite, ' '.join(self.suites)))
2121
2122- modname = 'VMBuilder.plugins.ubuntu.%s' % (self.vm.suite, )
2123- mod = __import__(modname, fromlist=[self.vm.suite])
2124- self.suite = getattr(mod, self.vm.suite.capitalize())(self.vm)
2125+ modname = 'VMBuilder.plugins.ubuntu.%s' % (suite, )
2126+ mod = __import__(modname, fromlist=[suite])
2127+ self.suite = getattr(mod, suite.capitalize())(self)
2128
2129- if self.vm.arch not in self.valid_archs[self.host_arch] or \
2130- not self.suite.check_arch_validity(self.vm.arch):
2131- raise VMBuilderUserError('%s is not a valid architecture. Valid architectures are: %s' % (self.vm.arch,
2132+ arch = self.get_setting('arch')
2133+ if arch not in self.valid_archs[self.host_arch] or \
2134+ not self.suite.check_arch_validity(arch):
2135+ raise VMBuilderUserError('%s is not a valid architecture. Valid architectures are: %s' % (arch,
2136 ' '.join(self.valid_archs[self.host_arch])))
2137
2138- if not self.vm.components:
2139- self.vm.components = ['main', 'restricted', 'universe']
2140+ components = self.get_setting('components')
2141+ if not components:
2142+ self.set_config_value_list = ['main', 'restricted', 'universe']
2143 else:
2144- if type(self.vm.components) is str:
2145+ if type(components) is str:
2146 self.vm.components = self.vm.components.split(',')
2147
2148- if self.vm.hypervisor.name == 'Xen':
2149- logging.info('Xen kernel default: linux-image-%s %s', self.suite.xen_kernel_flavour, self.xen_kernel_version())
2150-
2151- self.vm.virtio_net = self.use_virtio_net()
2152-
2153- if self.vm.lang:
2154+ self.context.virtio_net = self.use_virtio_net()
2155+
2156+ lang = self.get_setting('lang')
2157+ if lang:
2158 try:
2159- run_cmd('locale-gen', '%s' % self.vm.lang)
2160+ run_cmd('locale-gen', '%s' % lang)
2161 except VMBuilderException, e:
2162- msg = "locale-gen does not recognize your locale '%s'" % self.vm.lang
2163- raise VMBuilderUserError(msg)
2164-
2165- if getattr(self.vm, 'ec2', False):
2166- self.get_ec2_kernel()
2167- self.get_ec2_ramdisk()
2168- self.apply_ec2_settings()
2169+ raise VMBuilderUserError("Unrecognised locale: '%s'" % (lang, ))
2170+
2171+# FIXME
2172+# if getattr(self.vm, 'ec2', False):
2173+# self.get_ec2_kernel()
2174+# self.get_ec2_ramdisk()
2175+# self.apply_ec2_settings()
2176+
2177+ def bootstrap(self):
2178+ self.suite.debootstrap()
2179+ self.suite.pre_install()
2180+
2181+ def configure_os(self):
2182+ self.suite.install_sources_list()
2183+ self.suite.install_apt_proxy()
2184+ self.suite.create_devices()
2185+ self.suite.prevent_daemons_starting()
2186+ self.suite.mount_dev_proc()
2187+ self.suite.install_extras()
2188+ self.suite.create_initial_user()
2189+ self.suite.install_authorized_keys()
2190+ self.suite.config_host_and_domainname()
2191+ self.suite.set_timezone()
2192+ self.suite.install_sources_list(final=True)
2193+ self.suite.run_in_target('apt-get', 'clean');
2194+ self.suite.unmount_volatile()
2195+ self.suite.unmount_proc()
2196+ self.suite.unmount_dev_pts()
2197+ self.suite.unmount_dev()
2198+ self.suite.unprevent_daemons_starting()
2199+
2200+ def configure_networking(self, nics):
2201+ self.suite.config_interfaces(nics)
2202+
2203+ def configure_mounting(self, disks, filesystems):
2204+ self.suite.install_fstab(disks, filesystems)
2205
2206 def install(self, destdir):
2207 self.destdir = destdir
2208@@ -156,37 +186,42 @@
2209 def use_virtio_net(self):
2210 return self.suite.virtio_net
2211
2212- def install_bootloader_cleanup(self):
2213- self.vm.cancel_cleanup(self.install_bootloader_cleanup)
2214- tmpdir = '%s/tmp/vmbuilder-grub' % self.destdir
2215+ def install_bootloader_cleanup(self, chroot_dir):
2216+ self.context.cancel_cleanup(self.install_bootloader_cleanup)
2217+ tmpdir = '%s/tmp/vmbuilder-grub' % chroot_dir
2218 for disk in os.listdir(tmpdir):
2219 if disk != 'device.map':
2220 run_cmd('umount', os.path.join(tmpdir, disk))
2221 shutil.rmtree(tmpdir)
2222
2223- def install_bootloader(self):
2224+ def install_kernel(self, destdir):
2225+ self.suite.install_kernel(destdir)
2226+
2227+ def install_bootloader(self, chroot_dir, disks):
2228 tmpdir = '/tmp/vmbuilder-grub'
2229- os.makedirs('%s%s' % (self.destdir, tmpdir))
2230- self.vm.add_clean_cb(self.install_bootloader_cleanup)
2231+ os.makedirs('%s%s' % (chroot_dir, tmpdir))
2232+ self.context.add_clean_cb(self.install_bootloader_cleanup)
2233 devmapfile = os.path.join(tmpdir, 'device.map')
2234- devmap = open('%s%s' % (self.destdir, devmapfile), 'w')
2235- for (disk, id) in zip(self.vm.disks, range(len(self.vm.disks))):
2236+ devmap = open('%s%s' % (chroot_dir, devmapfile), 'w')
2237+ for (disk, id) in zip(disks, range(len(disks))):
2238 new_filename = os.path.join(tmpdir, os.path.basename(disk.filename))
2239- open('%s%s' % (self.destdir, new_filename), 'w').close()
2240- run_cmd('mount', '--bind', disk.filename, '%s%s' % (self.destdir, new_filename))
2241+ open('%s%s' % (chroot_dir, new_filename), 'w').close()
2242+ run_cmd('mount', '--bind', disk.filename, '%s%s' % (chroot_dir, new_filename))
2243 devmap.write("(hd%d) %s\n" % (id, new_filename))
2244 devmap.close()
2245+ self.suite.install_grub(chroot_dir)
2246 self.run_in_target('grub', '--device-map=%s' % devmapfile, '--batch', stdin='''root (hd0,0)
2247 setup (hd0)
2248-EOT''')
2249- self.install_bootloader_cleanup()
2250+EOT''')
2251+ self.suite.install_menu_lst(disks)
2252+ self.install_bootloader_cleanup(chroot_dir)
2253
2254 def xen_kernel_version(self):
2255 if self.suite.xen_kernel_flavour:
2256 # if this is ec2, do not call rmadison.
2257 # this could be replaced with a method to get most recent
2258 # stable kernel, but really, this is not used at all for ec2
2259- if hasattr(self.vm, 'ec2') and self.vm.ec2:
2260+ if hasattr(self.vm, 'ec2') and self.context.ec2:
2261 logging.debug("selecting ec2 kernel")
2262 self.xen_kernel = "2.6.ec2-kernel"
2263 return self.xen_kernel
2264@@ -197,7 +232,7 @@
2265 for line in rmad.splitlines():
2266 sline = line.split('|')
2267
2268- if sline[2].strip().startswith(self.vm.suite):
2269+ if sline[2].strip().startswith(self.context.suite):
2270 vt = sline[1].strip().split('.')
2271 for i in range(4):
2272 if int(vt[i]) > int(version[i]):
2273@@ -205,7 +240,7 @@
2274 break
2275
2276 if version[0] == '0':
2277- raise VMBuilderException('Something is wrong, no valid xen kernel for the suite %s found by rmadison' % self.vm.suite)
2278+ raise VMBuilderException('Something is wrong, no valid xen kernel for the suite %s found by rmadison' % self.context.suite)
2279
2280 self.xen_kernel = '%s.%s.%s-%s' % (version[0],version[1],version[2],version[3])
2281 return self.xen_kernel
2282@@ -224,13 +259,13 @@
2283
2284 def get_ec2_kernel(self):
2285 if self.suite.ec2_kernel_info:
2286- return self.suite.ec2_kernel_info[self.vm.arch]
2287+ return self.suite.ec2_kernel_info[self.context.arch]
2288 else:
2289 raise VMBuilderUserError('EC2 is not supported for the suite selected')
2290
2291 def get_ec2_ramdisk(self):
2292 if self.suite.ec2_ramdisk_info:
2293- return self.suite.ec2_ramdisk_info[self.vm.arch]
2294+ return self.suite.ec2_ramdisk_info[self.context.arch]
2295 else:
2296 raise VMBuilderUserError('EC2 is not supported for the suite selected')
2297
2298@@ -240,4 +275,7 @@
2299 def apply_ec2_settings(self):
2300 return self.suite.apply_ec2_settings()
2301
2302+ def has_256_bit_inode_ext3_support(self):
2303+ return self.suite.has_256_bit_inode_ext3_support()
2304+
2305 register_distro(Ubuntu)
2306
2307=== modified file 'VMBuilder/plugins/ubuntu/edgy.py'
2308--- VMBuilder/plugins/ubuntu/edgy.py 2009-08-07 16:07:55 +0000
2309+++ VMBuilder/plugins/ubuntu/edgy.py 2010-02-18 16:03:14 +0000
2310@@ -31,7 +31,7 @@
2311 disk_prefix = 'sd'
2312
2313 def mangle_grub_menu_lst(self):
2314- bootdev = disk.bootpart(self.vm.disks)
2315+ bootdev = disk.bootpart(self.context.disks)
2316 run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=UUID=%s\\2/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
2317 run_cmd('sed', '-ie', 's/^# groot.*/# groot %s/g' % bootdev.get_grub_id(), '%s/boot/grub/menu.lst' % self.destdir)
2318 run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.destdir)
2319@@ -42,7 +42,7 @@
2320 # <file system> <mount point> <type> <options> <dump> <pass>
2321 proc /proc proc defaults 0 0
2322 '''
2323- parts = disk.get_ordered_partitions(self.vm.disks)
2324+ parts = disk.get_ordered_partitions(self.context.disks)
2325 for part in parts:
2326 retval += "UUID=%-40s %15s %7s %15s %d %d\n" % (part.fs.uuid, part.fs.mntpnt, part.fs.fstab_fstype(), part.fs.fstab_options(), 0, 0)
2327 return retval
2328@@ -58,9 +58,9 @@
2329 self.copy_to_target('/etc/default/console-setup', '/etc/default/console-setup')
2330 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'tzdata')
2331 self.run_in_target('locale-gen', 'en_US')
2332- if self.vm.lang:
2333- self.run_in_target('locale-gen', self.vm.lang)
2334- self.install_from_template('/etc/default/locale', 'locale', { 'lang' : self.vm.lang })
2335+ if self.context.lang:
2336+ self.run_in_target('locale-gen', self.context.lang)
2337+ self.install_from_template('/etc/default/locale', 'locale', { 'lang' : self.context.lang })
2338 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'locales')
2339 if have_cs:
2340 self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'console-setup')
2341
2342=== modified file 'VMBuilder/plugins/ubuntu/hardy.py'
2343--- VMBuilder/plugins/ubuntu/hardy.py 2009-11-05 01:42:05 +0000
2344+++ VMBuilder/plugins/ubuntu/hardy.py 2010-02-18 16:03:14 +0000
2345@@ -25,21 +25,21 @@
2346 ec2_ramdisk_info = { 'i386' : 'ari-6c709705', 'amd64' : 'ari-61709708' }
2347
2348 def apply_ec2_settings(self):
2349- self.vm.addpkg += ['ec2-init',
2350+ self.context.addpkg += ['ec2-init',
2351 'openssh-server',
2352 'ec2-modules',
2353 'standard^',
2354 'ec2-ami-tools',
2355 'update-motd']
2356
2357- if not self.vm.ppa:
2358- self.vm.ppa = []
2359+ if not self.context.ppa:
2360+ self.context.ppa = []
2361
2362- self.vm.ppa += ['ubuntu-on-ec2/ppa']
2363+ self.context.ppa += ['ubuntu-on-ec2/ppa']
2364
2365 def install_ec2(self):
2366
2367- if self.vm.arch == 'i386':
2368+ if self.context.arch == 'i386':
2369 self.run_in_target('apt-get' ,'--force-yes', '-y', 'install', 'libc6-xen')
2370 self.run_in_target('apt-get','--purge','--force-yes', '-y', 'remove', 'libc6-i686')
2371 self.install_from_template('/etc/ld.so.conf.d/libc6-xen.conf', 'xen-ld-so-conf')
2372@@ -54,3 +54,6 @@
2373
2374 def xen_ramdisk_path(self):
2375 return '/boot/initrd.img-2.6.24-19-xen'
2376+
2377+ def has_256_bit_inode_ext3_support(self):
2378+ return True
2379
2380=== modified file 'VMBuilder/plugins/ubuntu/intrepid.py'
2381--- VMBuilder/plugins/ubuntu/intrepid.py 2009-11-05 01:42:05 +0000
2382+++ VMBuilder/plugins/ubuntu/intrepid.py 2010-02-18 16:03:14 +0000
2383@@ -40,7 +40,7 @@
2384 self.install_from_template('/etc/ec2-init/is-compat-env', 'is-compat-env')
2385
2386 def mangle_grub_menu_lst(self):
2387- bootdev = disk.bootpart(self.vm.disks)
2388+ bootdev = disk.bootpart(self.context.disks)
2389 run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=UUID=%s\\2/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
2390 run_cmd('sed', '-ie', 's/^# groot.*/# groot=%s/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
2391 run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.destdir)
2392
2393=== modified file 'VMBuilder/plugins/ubuntu/jaunty.py'
2394--- VMBuilder/plugins/ubuntu/jaunty.py 2009-09-26 17:39:48 +0000
2395+++ VMBuilder/plugins/ubuntu/jaunty.py 2010-02-18 16:03:14 +0000
2396@@ -34,9 +34,9 @@
2397 self.install_from_template('/etc/ec2-init/is-compat-env', 'is-compat-env')
2398 self.run_in_target('chmod', '755', '/etc/update-motd.d/51_update-motd')
2399
2400- def mangle_grub_menu_lst(self):
2401- bootdev = disk.bootpart(self.vm.disks)
2402- run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=UUID=%s\\2/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
2403- run_cmd('sed', '-ie', 's/^# groot.*/# groot=%s/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
2404- run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.destdir)
2405+ def mangle_grub_menu_lst(self, disks):
2406+ bootdev = disk.bootpart(disks)
2407+ run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=UUID=%s\\2/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.context.chroot_dir)
2408+ run_cmd('sed', '-ie', 's/^# groot.*/# groot=%s/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.context.chroot_dir)
2409+ run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.context.chroot_dir)
2410
2411
2412=== modified file 'VMBuilder/plugins/ubuntu/karmic.py'
2413--- VMBuilder/plugins/ubuntu/karmic.py 2009-09-25 19:14:04 +0000
2414+++ VMBuilder/plugins/ubuntu/karmic.py 2010-02-18 16:03:14 +0000
2415@@ -24,8 +24,8 @@
2416
2417 class Karmic(Jaunty):
2418 def apply_ec2_settings(self):
2419- self.vm.addpkg += ['standard^',
2420+ self.context.addpkg += ['standard^',
2421 'uec^']
2422
2423 def pre_install(self):
2424- self.vm.install_file('/etc/hosts', contents='')
2425+ self.context.install_file('/etc/hosts', contents='')
2426
2427=== modified file 'VMBuilder/plugins/ubuntu/suite.py'
2428--- VMBuilder/plugins/ubuntu/suite.py 2009-06-10 13:40:41 +0000
2429+++ VMBuilder/plugins/ubuntu/suite.py 2010-02-18 16:03:14 +0000
2430@@ -24,8 +24,8 @@
2431 import sys
2432
2433 class Suite(object):
2434- def __init__(self, vm):
2435- self.vm = vm
2436+ def __init__(self, context):
2437+ self.context = context
2438 self.isodir = '/media/vmbuilder_inst_image'
2439 self.iso_mounted = False
2440
2441
2442=== modified file 'VMBuilder/plugins/ubuntu/templates/dapper_fstab.tmpl'
2443--- VMBuilder/plugins/ubuntu/templates/dapper_fstab.tmpl 2008-09-18 09:11:09 +0000
2444+++ VMBuilder/plugins/ubuntu/templates/dapper_fstab.tmpl 2010-02-18 16:03:14 +0000
2445@@ -2,6 +2,7 @@
2446 #
2447 # <file system> <mount point> <type> <options> <dump> <pass>
2448 proc /proc proc defaults 0 0
2449+#*
2450 #for $part in $parts
2451 #echo '/dev/%s%-40s %-15s %-7s %-15s %d %d\n' % ($prefix, part.get_suffix(), part.mntpnt, part.fs.fstab_fstype(), part.fs.fstab_options(), 0, 0)
2452 #*
2453
2454=== modified file 'VMBuilder/plugins/virtualbox/vm.py'
2455--- VMBuilder/plugins/virtualbox/vm.py 2009-06-10 13:40:41 +0000
2456+++ VMBuilder/plugins/virtualbox/vm.py 2010-02-18 16:03:14 +0000
2457@@ -32,25 +32,25 @@
2458 arg = 'vbox'
2459
2460 def register_options(self):
2461- group = self.vm.setting_group('VirtualBox options')
2462+ group = self.context.setting_group('VirtualBox options')
2463 group.add_option('--vbox-disk-format', metavar='FORMAT', default='vdi', help='Desired disk format. Valid options are: vdi vmdk. [default: %default]')
2464- self.vm.register_setting_group(group)
2465+ self.context.register_setting_group(group)
2466
2467 def finalize(self):
2468 self.imgs = []
2469- for disk in self.vm.disks:
2470- img_path = disk.convert(self.vm.destdir, self.vm.vbox_disk_format)
2471+ for disk in self.context.disks:
2472+ img_path = disk.convert(self.context.destdir, self.context.vbox_disk_format)
2473 self.imgs.append(img_path)
2474- self.vm.result_files.append(img_path)
2475+ self.context.result_files.append(img_path)
2476
2477 def deploy(self):
2478- vm_deploy_script = VMBuilder.util.render_template('virtualbox', self.vm, 'vm_deploy_script', { 'os_type' : self.vm.distro.__class__.__name__, 'vm_name' : self.vm.hostname, 'vm_disks' : self.imgs, 'memory' : self.vm.mem })
2479+ vm_deploy_script = VMBuilder.util.render_template('virtualbox', self.context, 'vm_deploy_script', { 'os_type' : self.context.distro.__class__.__name__, 'vm_name' : self.context.hostname, 'vm_disks' : self.imgs, 'memory' : self.context.mem })
2480
2481- script_file = '%s/deploy_%s.sh' % (self.vm.destdir, self.vm.hostname)
2482+ script_file = '%s/deploy_%s.sh' % (self.context.destdir, self.context.hostname)
2483 fp = open(script_file, 'w')
2484 fp.write(vm_deploy_script)
2485 fp.close()
2486 os.chmod(script_file, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
2487- self.vm.result_files.append(script_file)
2488+ self.context.result_files.append(script_file)
2489
2490 register_hypervisor(VirtualBox)
2491
2492=== modified file 'VMBuilder/plugins/vmware/vm.py'
2493--- VMBuilder/plugins/vmware/vm.py 2009-06-10 13:40:41 +0000
2494+++ VMBuilder/plugins/vmware/vm.py 2010-02-18 16:03:14 +0000
2495@@ -33,23 +33,23 @@
2496
2497 def finalize(self):
2498 self.imgs = []
2499- for disk in self.vm.disks:
2500- img_path = disk.convert(self.vm.destdir, self.filetype)
2501+ for disk in self.context.disks:
2502+ img_path = disk.convert(self.context.destdir, self.filetype)
2503 self.imgs.append(img_path)
2504- self.vm.result_files.append(img_path)
2505+ self.context.result_files.append(img_path)
2506
2507 def disks(self):
2508- return self.vm.disks
2509+ return self.context.disks
2510
2511 def deploy(self):
2512- vmdesc = VMBuilder.util.render_template('vmware', self.vm, self.vmxtemplate, { 'disks' : self.disks(), 'vmhwversion' : self.vmhwversion, 'cpus' : self.vm.cpus, 'mem' : self.vm.mem, 'hostname' : self.vm.hostname, 'arch' : self.vm.arch, 'guestos' : (self.vm.arch == 'amd64' and 'ubuntu-64' or 'ubuntu') })
2513+ vmdesc = VMBuilder.util.render_template('vmware', self.context, self.vmxtemplate, { 'disks' : self.disks(), 'vmhwversion' : self.vmhwversion, 'cpus' : self.context.cpus, 'mem' : self.context.mem, 'hostname' : self.context.hostname, 'arch' : self.context.arch, 'guestos' : (self.context.arch == 'amd64' and 'ubuntu-64' or 'ubuntu') })
2514
2515- vmx = '%s/%s.vmx' % (self.vm.destdir, self.vm.hostname)
2516+ vmx = '%s/%s.vmx' % (self.context.destdir, self.context.hostname)
2517 fp = open(vmx, 'w')
2518 fp.write(vmdesc)
2519 fp.close()
2520 os.chmod(vmx, stat.S_IRWXU | stat.S_IRWXU | stat.S_IROTH | stat.S_IXOTH)
2521- self.vm.result_files.append(vmx)
2522+ self.context.result_files.append(vmx)
2523
2524 class VMWareWorkstation6(VMWare):
2525 name = 'VMWare Workstation 6'
2526@@ -72,33 +72,33 @@
2527
2528 def finalize(self):
2529 self.imgs = []
2530- for disk in self.vm.disks:
2531+ for disk in self.context.disks:
2532
2533 # Move raw image to <imagename>-flat.vmdk
2534 diskfilename = os.path.basename(disk.filename)
2535 if '.' in diskfilename:
2536 diskfilename = diskfilename[:diskfilename.rindex('.')]
2537
2538- flat = '%s/%s-flat.vmdk' % (self.vm.destdir, diskfilename)
2539+ flat = '%s/%s-flat.vmdk' % (self.context.destdir, diskfilename)
2540 self.vmdks.append(diskfilename)
2541
2542 move(disk.filename, flat)
2543
2544- self.vm.result_files.append(flat)
2545+ self.context.result_files.append(flat)
2546
2547 # Create disk descriptor file
2548 sectorTotal = disk.size * 2048
2549 sector = int(floor(sectorTotal / 16065)) # pseudo geometry
2550
2551- diskdescriptor = VMBuilder.util.render_template('vmware', self.vm, 'flat.vmdk', { 'adaptertype' : self.adaptertype, 'sectors' : sector, 'diskname' : os.path.basename(flat), 'disksize' : sectorTotal })
2552- vmdk = '%s/%s.vmdk' % (self.vm.destdir, diskfilename)
2553+ diskdescriptor = VMBuilder.util.render_template('vmware', self.context, 'flat.vmdk', { 'adaptertype' : self.adaptertype, 'sectors' : sector, 'diskname' : os.path.basename(flat), 'disksize' : sectorTotal })
2554+ vmdk = '%s/%s.vmdk' % (self.context.destdir, diskfilename)
2555
2556 fp = open(vmdk, 'w')
2557 fp.write(diskdescriptor)
2558 fp.close()
2559 os.chmod(vmdk, stat.S_IRWXU | stat.S_IRWXU | stat.S_IROTH | stat.S_IXOTH)
2560
2561- self.vm.result_files.append(vmdk)
2562+ self.context.result_files.append(vmdk)
2563
2564 def disks(self):
2565 return self.vmdks
2566
2567=== modified file 'VMBuilder/plugins/xen/vm.py'
2568--- VMBuilder/plugins/xen/vm.py 2009-06-10 13:40:41 +0000
2569+++ VMBuilder/plugins/xen/vm.py 2010-02-18 16:03:14 +0000
2570@@ -31,29 +31,29 @@
2571 needs_bootloader = False
2572
2573 def register_options(self):
2574- group = self.vm.setting_group('Xen option')
2575+ group = self.context.setting_group('Xen option')
2576 group.add_option('--xen-kernel', metavar='PATH', help='Path to the kernel to use (e.g.: /boot/vmlinux-2.6.27-7-server). Default depends on distribution and suite')
2577 group.add_option('--xen-ramdisk', metavar='PATH', help='Path to the ramdisk to use (e.g.: /boot/initrd.img-2.6.27-7-server). Default depends on distribution and suite.')
2578- self.vm.register_setting_group(group)
2579+ self.context.register_setting_group(group)
2580
2581 def finalize(self):
2582 destimages = []
2583- for filesystem in self.vm.filesystems:
2584+ for filesystem in self.context.filesystems:
2585 if not filesystem.preallocated:
2586- destfile = '%s/%s' % (self.vm.destdir, os.path.basename(filesystem.filename))
2587+ destfile = '%s/%s' % (self.context.destdir, os.path.basename(filesystem.filename))
2588 logging.info('Moving %s to %s' % (filesystem.filename, destfile))
2589- self.vm.result_files.append(destfile)
2590+ self.context.result_files.append(destfile)
2591 run_cmd('cp', '--sparse=always', filesystem.filename, destfile)
2592 os.unlink(filesystem.filename)
2593 filesystem.filename = os.path.abspath(destfile)
2594 destimages.append(destfile)
2595
2596- if not self.vm.xen_kernel:
2597- self.vm.xen_kernel = self.vm.distro.xen_kernel_path()
2598- if not self.vm.xen_ramdisk:
2599- self.vm.xen_ramdisk = self.vm.distro.xen_ramdisk_path()
2600+ if not self.context.xen_kernel:
2601+ self.context.xen_kernel = self.context.distro.xen_kernel_path()
2602+ if not self.context.xen_ramdisk:
2603+ self.context.xen_ramdisk = self.context.distro.xen_ramdisk_path()
2604
2605- xenconf = '%s/xen.conf' % self.vm.destdir
2606+ xenconf = '%s/xen.conf' % self.context.destdir
2607 fp = open(xenconf, 'w')
2608 fp.write("""
2609 # Configuration file for the Xen instance %s, created
2610@@ -78,13 +78,13 @@
2611
2612 extra = 'xencons=tty console=tty1 console=hvc0'
2613
2614-""" % (self.vm.name,
2615- self.vm.xen_kernel,
2616- self.vm.xen_ramdisk,
2617- self.vm.mem,
2618+""" % (self.context.name,
2619+ self.context.xen_kernel,
2620+ self.context.xen_ramdisk,
2621+ self.context.mem,
2622 ',\n'.join(["'tap:aio:%s,xvda%d,w'" % (os.path.abspath(img), id+1) for (img, id) in zip(destimages, range(len(destimages)))]),
2623- self.vm.name))
2624+ self.context.name))
2625 fp.close()
2626- self.vm.result_files.append(xenconf)
2627+ self.context.result_files.append(xenconf)
2628
2629 register_hypervisor(Xen)
2630
2631=== modified file 'VMBuilder/util.py'
2632--- VMBuilder/util.py 2009-09-16 15:27:15 +0000
2633+++ VMBuilder/util.py 2010-02-18 16:03:14 +0000
2634@@ -21,10 +21,10 @@
2635 import logging
2636 import os
2637 import os.path
2638-import pwd
2639 import select
2640 import subprocess
2641 import sys
2642+import tempfile
2643 import time
2644 from exception import VMBuilderException, VMBuilderUserError
2645
2646@@ -135,19 +135,6 @@
2647 raise VMBuilderException, "Process (%s) returned %d. stdout: %s, stderr: %s" % (args.__repr__(), status, stdout, stderr)
2648 return stdout
2649
2650-def give_to_caller(path):
2651- """
2652- Change ownership of file to $SUDO_USER.
2653-
2654- @type path: string
2655- @param path: file or directory to give to $SUDO_USER
2656- """
2657-
2658- if 'SUDO_USER' in os.environ:
2659- logging.debug('Changing ownership of %s to %s' % (path, os.environ['SUDO_USER']))
2660- (uid, gid) = pwd.getpwnam(os.environ['SUDO_USER'])[2:4]
2661- os.chown(path, uid, gid)
2662-
2663 def checkroot():
2664 """
2665 Check if we're running as root, and bail out if we're not.
2666@@ -156,18 +143,6 @@
2667 if os.geteuid() != 0:
2668 raise VMBuilderUserError("This script must be run as root (e.g. via sudo)")
2669
2670-def fix_ownership(files):
2671- """
2672- Goes through files and fixes their ownership of them.
2673-
2674- @type files: list
2675- @param files: files whose ownership should be fixed up (currently
2676- simply calls L{give_to_caller})
2677-
2678- """
2679- for file in files:
2680- give_to_caller(file)
2681-
2682 def render_template(plugin, vm, tmplname, context=None):
2683 # Import here to avoid having to build-dep on python-cheetah
2684 from Cheetah.Template import Template
2685@@ -180,8 +155,8 @@
2686 os.path.dirname(__file__) + '/plugins/%s/templates',
2687 '/etc/vmbuilder/%s']
2688
2689- if vm.templates:
2690- tmpldirs.insert(0,'%s/%%s' % vm.templates)
2691+# if vm.templates:
2692+# tmpldirs.insert(0,'%s/%%s' % vm.templates)
2693
2694 tmpldirs = [dir % plugin for dir in tmpldirs]
2695
2696@@ -194,3 +169,30 @@
2697 return output
2698
2699 raise VMBuilderException('Template %s.tmpl not found in any of %s' % (tmplname, ', '.join(tmpldirs)))
2700+
2701+def call_hooks(context, func, *args, **kwargs):
2702+ logging.debug('Calling hook: %s(args=%r, kwargs=%r)' % (func, args, kwargs))
2703+ for plugin in context.plugins:
2704+ logging.debug('Calling %s method in %s plugin.' % (func, plugin.__module__))
2705+ getattr(plugin, func, log_no_such_method)(*args, **kwargs)
2706+
2707+ logging.debug('Calling %s method in context plugin %s.' % (func, context.__module__))
2708+ getattr(context, func, log_no_such_method)(*args, **kwargs)
2709+
2710+def log_no_such_method(*args, **kwargs):
2711+ logging.debug('No such method')
2712+ return
2713+
2714+def tmpfile(suffix='', keep=True):
2715+ (fd, filename) = tempfile.mkstemp(suffix=suffix)
2716+ os.close(fd)
2717+ if not keep:
2718+ os.unlink(filename)
2719+ return filename
2720+
2721+def tmpdir(suffix='', keep=True):
2722+ dir = tempfile.mkdtemp(suffix=suffix)
2723+ if not keep:
2724+ os.rmdir(dir)
2725+ return dir
2726+
2727
2728=== modified file 'VMBuilder/vm.py'
2729--- VMBuilder/vm.py 2010-02-02 15:36:35 +0000
2730+++ VMBuilder/vm.py 2010-02-18 16:03:14 +0000
2731@@ -92,34 +92,6 @@
2732
2733 self.add_clean_cmd('rm', log.logfile)
2734
2735- def get_version_info(self):
2736- import vcsversion
2737- info = vcsversion.version_info
2738- info['major'] = 0
2739- info['minor'] = 11
2740- info['micro'] = 3
2741- return info
2742-
2743- def cleanup(self):
2744- logging.info("Cleaning up")
2745- while len(self._cleanup_cbs) > 0:
2746- self._cleanup_cbs.pop(0)()
2747-
2748- def add_clean_cb(self, cb):
2749- self._cleanup_cbs.insert(0, cb)
2750-
2751- def add_clean_cmd(self, *argv, **kwargs):
2752- cb = lambda : util.run_cmd(*argv, **kwargs)
2753- self.add_clean_cb(cb)
2754- return cb
2755-
2756- def cancel_cleanup(self, cb):
2757- try:
2758- self._cleanup_cbs.remove(cb)
2759- except ValueError, e:
2760- # Wasn't in there. No worries.
2761- pass
2762-
2763 def distro_help(self):
2764 return 'Distro. Valid options: %s' % " ".join(VMBuilder.distros.keys())
2765
2766@@ -149,18 +121,6 @@
2767 self.register_setting('-m', '--mem', type='int', default=128, help='Assign MEM megabytes of memory to the guest vm. [default: %default]')
2768 self.register_setting('--cpus', type='int', default=1, help='Number of virtual CPU\'s. [default: %default]')
2769
2770- group = self.setting_group('Network related options')
2771- domainname = '.'.join(socket.gethostbyname_ex(socket.gethostname())[0].split('.')[1:]) or "defaultdomain"
2772- group.add_option('--domain', metavar='DOMAIN', default=domainname, help='Set DOMAIN as the domain name of the guest [default: The domain of the machine running this script: %default].')
2773- group.add_option('--ip', metavar='ADDRESS', default='dhcp', help='IP address in dotted form [default: %default].')
2774- group.add_option('--mac', metavar='VALUE', help='MAC address of the guest [default: one will be automatically generated on first run].')
2775- group.add_option('--mask', metavar='VALUE', help='IP mask in dotted form [default: based on ip setting]. Ignored if --ip is not specified.')
2776- group.add_option('--net', metavar='ADDRESS', help='IP net address in dotted form [default: based on ip setting]. Ignored if --ip is not specified.')
2777- group.add_option('--bcast', metavar='VALUE', help='IP broadcast in dotted form [default: based on ip setting]. Ignored if --ip is not specified.')
2778- group.add_option('--gw', metavar='ADDRESS', help='Gateway (router) address in dotted form [default: based on ip setting (first valid address in the network)]. Ignored if --ip is not specified.')
2779- group.add_option('--dns', metavar='ADDRESS', help='DNS address in dotted form [default: based on ip setting (first valid address in the network)] Ignored if --ip is not specified.')
2780- self.register_setting_group(group)
2781-
2782 def add_disk(self, *args, **kwargs):
2783 """Adds a disk image to the virtual machine"""
2784 disk = Disk(self, *args, **kwargs)
2785@@ -319,28 +279,6 @@
2786 """Creates the working directory for this vm and returns its path"""
2787 return tempfile.mkdtemp('', 'vmbuilder', self.tmp)
2788
2789- def mount_partitions(self):
2790- """Mounts all the vm's partitions and filesystems below .rootmnt"""
2791- logging.info('Mounting target filesystems')
2792- fss = disk.get_ordered_filesystems(self)
2793- for fs in fss:
2794- fs.mount()
2795- self.distro.post_mount(fs)
2796-
2797- self.fsmounted = True
2798-
2799- def umount_partitions(self):
2800- """Unmounts all the vm's partitions and filesystems"""
2801- logging.info('Unmounting target filesystem')
2802- fss = VMBuilder.disk.get_ordered_filesystems(self)
2803- fss.reverse()
2804- for fs in fss:
2805- fs.umount()
2806- for disk in self.disks:
2807- disk.unmap()
2808-
2809- self.fsmounted = False
2810-
2811 def install(self):
2812 if self.in_place:
2813 self.installdir = self.rootmnt
2814@@ -383,18 +321,6 @@
2815
2816 testnet.close()
2817
2818- def install_file(self, path, contents=None, source=None, mode=None):
2819- fullpath = '%s%s' % (self.installdir, path)
2820- if source and not contents:
2821- shutil.copy(source, fullpath)
2822- else:
2823- fp = open(fullpath, 'w')
2824- fp.write(contents)
2825- fp.close()
2826- if mode:
2827- os.chmod(fullpath, mode)
2828- return fullpath
2829-
2830 def create(self):
2831 """
2832 The core vm creation method
2833
2834=== modified file 'test/disk_tests.py'
2835--- test/disk_tests.py 2009-10-23 09:34:18 +0000
2836+++ test/disk_tests.py 2010-02-18 16:03:14 +0000
2837@@ -15,9 +15,36 @@
2838 #
2839 # You should have received a copy of the GNU General Public License
2840 # along with this program. If not, see <http://www.gnu.org/licenses/>.
2841+import os
2842+import stat
2843+import tempfile
2844 import unittest
2845
2846-from VMBuilder.disk import parse_size, index_to_devname, devname_to_index
2847+import VMBuilder
2848+from VMBuilder.disk import parse_size, index_to_devname, devname_to_index, Disk
2849+from VMBuilder.exception import VMBuilderUserError
2850+
2851+def get_temp_filename():
2852+ (fd, tmpfile) = tempfile.mkstemp()
2853+ os.close(fd)
2854+ return tmpfile
2855+
2856+class MockDistro(object):
2857+ def has_256_bit_inode_ext3_support(self):
2858+ return True
2859+
2860+class MockHypervisor(object):
2861+ def __init__(self):
2862+ self.disks = []
2863+ self.distro = MockDistro()
2864+
2865+ def add_clean_cb(self, *args, **kwargs):
2866+ pass
2867+
2868+ def add_disk(self, *args, **kwargs):
2869+ disk = Disk(self, *args, **kwargs)
2870+ self.disks.append(disk)
2871+ return disk
2872
2873 class TestSizeParser(unittest.TestCase):
2874 def test_suffixesAreCaseInsensitive(self):
2875@@ -67,4 +94,171 @@
2876 for i in range(18277):
2877 self.assertEqual(i, devname_to_index(index_to_devname(i)))
2878
2879-
2880+class TestDiskPlugin(unittest.TestCase):
2881+ def test_detect_size(self):
2882+ "detect_size returns the correct size"
2883+ from VMBuilder.util import run_cmd
2884+ from VMBuilder.disk import detect_size
2885+
2886+ tmpfile = get_temp_filename()
2887+ try:
2888+ # We assume qemu-img is well-behaved
2889+ run_cmd('qemu-img', 'create', tmpfile, '5G')
2890+ self.assertTrue(detect_size(tmpfile), 5*1024)
2891+
2892+ imgdev = run_cmd('losetup', '-f', '--show', tmpfile).strip()
2893+ try:
2894+ self.assertTrue(detect_size(imgdev), 5*1024)
2895+ except:
2896+ raise
2897+ finally:
2898+ run_cmd('losetup', '-d', imgdev)
2899+ except:
2900+ raise
2901+ finally:
2902+ os.unlink(tmpfile)
2903+
2904+ def test_disk_filename(self):
2905+ tmpfile = get_temp_filename()
2906+ os.unlink(tmpfile)
2907+
2908+ disk = Disk(MockHypervisor(), tmpfile, size='1G')
2909+ disk.create()
2910+ self.assertTrue(os.path.exists(tmpfile))
2911+ os.unlink(tmpfile)
2912+
2913+ def test_disk_size(self):
2914+ # parse_size only deals with MB resolution
2915+ sizes = [('10G', 10*1024*1024*1024),
2916+ ('400M', 400*1024*1024),
2917+ ('345', 345*1024*1024),
2918+ ('10240k', 10*1024*1024),
2919+ ('10250k', 10*1024*1024),
2920+ ('10230k', 9*1024*1024)]
2921+
2922+ for (sizestr, size) in sizes:
2923+ tmpfile = get_temp_filename()
2924+ os.unlink(tmpfile)
2925+
2926+ disk = Disk(MockHypervisor(), filename=tmpfile, size=sizestr)
2927+ disk.create()
2928+ actual_size = os.stat(tmpfile)[stat.ST_SIZE]
2929+ self.assertEqual(size, actual_size, 'Asked for %s, expected %d, got %d' % (sizestr, size, actual_size))
2930+ os.unlink(tmpfile)
2931+
2932+
2933+ def test_disk_no_size_given(self):
2934+ tmpname = get_temp_filename()
2935+ os.unlink(tmpname)
2936+
2937+ self.assertRaises(VMBuilderUserError, Disk, MockHypervisor(), filename=tmpname)
2938+
2939+ def test_disk_size_given_file_exists(self):
2940+ tmpname = get_temp_filename()
2941+
2942+ self.assertRaises(VMBuilderUserError, Disk, MockHypervisor(), filename=tmpname, size='1G')
2943+
2944+ def test_existing_image_no_overwrite(self):
2945+ tmpfile = get_temp_filename()
2946+
2947+ fp = open(tmpfile, 'w')
2948+ fp.write('canary')
2949+ fp.close()
2950+
2951+ disk = Disk(MockHypervisor(), tmpfile)
2952+ disk.create()
2953+ fp = open(tmpfile, 'r')
2954+ self.assertEqual(fp.read(), 'canary')
2955+ fp.close()
2956+ os.unlink(tmpfile)
2957+
2958+class TestDiskPartitioningPlugin(unittest.TestCase):
2959+ def setUp(self):
2960+ self.tmpfile = get_temp_filename()
2961+ os.unlink(self.tmpfile)
2962+
2963+ self.vm = MockHypervisor()
2964+ self.disk = self.vm.add_disk(self.tmpfile, size='1G')
2965+ self.disk.create()
2966+
2967+ def tearDown(self):
2968+ os.unlink(self.tmpfile)
2969+
2970+ def test_partition_overlap(self):
2971+ self.disk.add_part(1, 512, 'ext3', '/')
2972+ self.assertRaises(VMBuilderUserError, self.disk.add_part, 512, 512, 'ext3', '/mnt')
2973+
2974+ def test_partition_extends_beyond_disk(self):
2975+ self.assertRaises(VMBuilderUserError, self.disk.add_part, 512, 514, 'ext3', '/')
2976+
2977+ def test_partition_table_empty(self):
2978+ from VMBuilder.util import run_cmd
2979+
2980+ file_output = run_cmd('file', self.tmpfile)
2981+ self.assertEqual('%s: data' % self.tmpfile, file_output.strip())
2982+ self.disk.partition()
2983+ file_output = run_cmd('file', self.tmpfile)
2984+ self.assertEqual('%s: x86 boot sector, code offset 0xb8' % self.tmpfile, file_output.strip())
2985+
2986+ file_output = run_cmd('parted', '--script', self.tmpfile, 'print')
2987+ self.assertEqual('''Model: (file)
2988+Disk %s: 1074MB
2989+Sector size (logical/physical): 512B/512B
2990+Partition Table: msdos
2991+
2992+Number Start End Size Type File system Flags''' % self.tmpfile, file_output.strip())
2993+
2994+ def test_partition_table_nonempty(self):
2995+ from VMBuilder.util import run_cmd
2996+
2997+ self.disk.add_part(1, 1023, 'ext3', '/')
2998+ self.disk.partition()
2999+ file_output = run_cmd('parted', '--script', self.tmpfile, 'print')
3000+ self.assertEqual('''Model: (file)
3001+Disk %s: 1074MB
3002+Sector size (logical/physical): 512B/512B
3003+Partition Table: msdos
3004+
3005+Number Start End Size Type File system Flags
3006+ 1 16.4kB 1023MB 1023MB primary''' % self.tmpfile, file_output.strip())
3007+
3008+ def test_map_partitions(self):
3009+ self.disk.add_part(1, 1023, 'ext3', '/')
3010+ self.disk.partition()
3011+ self.disk.map_partitions()
3012+ try:
3013+ from VMBuilder.disk import detect_size
3014+ self.assertEqual(detect_size(self.disk.partitions[0].filename), 1023000576)
3015+ except:
3016+ raise
3017+ finally:
3018+ self.disk.unmap()
3019+
3020+ def test_mkfs(self):
3021+ self.disk.add_part(1, 1023, 'ext3', '/')
3022+ self.disk.partition()
3023+ self.disk.map_partitions()
3024+ try:
3025+ self.disk.mkfs()
3026+ except:
3027+ raise
3028+ finally:
3029+ self.disk.unmap()
3030+
3031+ def test_get_grub_id(self):
3032+ self.assertEqual(self.disk.get_grub_id(), '(hd0)')
3033+
3034+ tmpfile2 = get_temp_filename()
3035+ os.unlink(tmpfile2)
3036+ disk2 = self.vm.add_disk(tmpfile2, '1G')
3037+ self.assertEqual(self.disk.get_grub_id(), '(hd0)')
3038+ self.assertEqual(disk2.get_grub_id(), '(hd1)')
3039+
3040+ def test_get_index(self):
3041+ self.assertEqual(self.disk.get_index(), 0)
3042+
3043+ tmpfile2 = get_temp_filename()
3044+ os.unlink(tmpfile2)
3045+ disk2 = self.vm.add_disk(tmpfile2, '1G')
3046+ self.assertEqual(self.disk.get_index(), 0)
3047+ self.assertEqual(disk2.get_index(), 1)
3048
3049=== modified file 'test/plugin_tests.py'
3050--- test/plugin_tests.py 2010-01-27 13:38:16 +0000
3051+++ test/plugin_tests.py 2010-02-18 16:03:14 +0000
3052@@ -7,7 +7,7 @@
3053 class VM(VMBuilder.plugins.Plugin):
3054 def __init__(self, *args, **kwargs):
3055 self._config = {}
3056- self.vm = self
3057+ self.context = self
3058
3059 class TestPlugin(VMBuilder.plugins.Plugin):
3060 pass
3061
3062=== modified file 'test/ubuntu_tests.py'
3063--- test/ubuntu_tests.py 2009-10-23 09:27:26 +0000
3064+++ test/ubuntu_tests.py 2010-02-18 16:03:14 +0000
3065@@ -33,7 +33,6 @@
3066 def test_invalid_suite_raises_UserError(self):
3067 'Building Ubuntu VMs with an invalid suite raises UserError'
3068
3069- vm = VMBuilder.VM()
3070- vm.suite = 'foo'
3071- ubuntu = Ubuntu(vm)
3072+ ubuntu = Ubuntu()
3073+ ubuntu.set_setting('suite', 'foo')
3074 self.assertRaises(VMBuilderUserError, ubuntu.preflight_check)
3075
3076=== modified file 'test/util_tests.py'
3077--- test/util_tests.py 2010-01-22 13:27:16 +0000
3078+++ test/util_tests.py 2010-02-18 16:03:14 +0000
3079@@ -20,12 +20,12 @@
3080 class PluginC(Plugin):
3081 priority = 15
3082
3083- saved_plugins = VMBuilder._plugins
3084- VMBuilder._plugins = []
3085- VMBuilder.register_plugin(PluginA)
3086- VMBuilder.register_plugin(PluginB)
3087- VMBuilder.register_plugin(PluginC)
3088- self.assertEqual(VMBuilder._plugins[0], PluginB)
3089- self.assertEqual(VMBuilder._plugins[1], PluginA)
3090- self.assertEqual(VMBuilder._plugins[2], PluginC)
3091- VMBuilder._plugins = saved_plugins
3092+ saved_hypervisor_plugins = VMBuilder._hypervisor_plugins
3093+ VMBuilder._hypervisor_plugins = []
3094+ VMBuilder.register_hypervisor_plugin(PluginA)
3095+ VMBuilder.register_hypervisor_plugin(PluginB)
3096+ VMBuilder.register_hypervisor_plugin(PluginC)
3097+ self.assertEqual(VMBuilder._hypervisor_plugins[0], PluginB)
3098+ self.assertEqual(VMBuilder._hypervisor_plugins[1], PluginA)
3099+ self.assertEqual(VMBuilder._hypervisor_plugins[2], PluginC)
3100+ VMBuilder._hypervisor_plugins = saved_hypervisor_plugins

Subscribers

People subscribed via source and target branches