X-Git-Url: https://git.siccegge.de//index.cgi?p=forks%2Fvmdebootstrap.git;a=blobdiff_plain;f=vmdebootstrap;h=9dd9ba54a6899324ed83704861a1a9eabffd5998;hp=c8fc426c1d8ec295fc150069beb63980a7cdac43;hb=6349ca31965698cab12fdd8038b4b19ba4ab8cfe;hpb=95bcd705060de5255950ac6c2af39578b077bbf3 diff --git a/vmdebootstrap b/vmdebootstrap index c8fc426..9dd9ba5 100755 --- a/vmdebootstrap +++ b/vmdebootstrap @@ -1,5 +1,6 @@ #!/usr/bin/python -# Copyright 2011 Lars Wirzenius +# Copyright 2011, 2012 Lars Wirzenius +# Copyright 2012 Codethink Limited # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -36,6 +37,8 @@ class VmDebootstrap(cliapp.Application): 'create a disk image of size SIZE (%default)', metavar='SIZE', default='1G') + self.settings.string(['tarball'], "tar up the disk's contents in FILE", + metavar='FILE') self.settings.string(['mirror'], 'use MIRROR as package source (%default)', metavar='URL', @@ -52,6 +55,7 @@ class VmDebootstrap(cliapp.Application): 'install package in DEB file onto system ' '(not from mirror)', metavar='DEB') + self.settings.boolean(['no-kernel'], 'do not install a linux package') self.settings.boolean(['enable-dhcp'], 'enable DHCP on eth0') self.settings.string(['root-password'], 'set root password', metavar='PASSWORD') @@ -74,21 +78,26 @@ class VmDebootstrap(cliapp.Application): 'to sudo group') def process_args(self, args): - if not self.settings['image']: - raise cliapp.AppException('You must give image filename.') - if not self.settings['size']: - raise cliapp.AppException('You must give image size.') + if not self.settings['image'] and not self.settings['tarball']: + raise cliapp.AppException('You must give disk image filename, ' + 'or tarball filename') + if self.settings['image'] and not self.settings['size']: + raise cliapp.AppException('If disk image is specified, ' + 'You must give image size.') self.remove_dirs = [] self.mount_points = [] try: - self.create_empty_image() - self.partition_image() - self.install_mbr() - rootdev = self.setup_kpartx() - self.mkfs(rootdev) - rootdir = self.mount(rootdev) + if self.settings['image']: + self.create_empty_image() + self.partition_image() + self.install_mbr() + rootdev = self.setup_kpartx() + self.mkfs(rootdev) + rootdir = self.mount(rootdev) + else: + rootdir = self.mkdtemp() self.debootstrap(rootdir) self.set_hostname(rootdir) self.create_fstab(rootdir) @@ -97,8 +106,11 @@ class VmDebootstrap(cliapp.Application): self.create_users(rootdir) self.remove_udev_persistent_rules(rootdir) self.setup_networking(rootdir) - self.install_extlinux(rootdev, rootdir) self.customize(rootdir) + if self.settings['image']: + self.install_extlinux(rootdev, rootdir) + if self.settings['tarball']: + self.create_tarball(rootdir) except BaseException, e: self.message('EEEK! Something bad happened...') self.cleanup_system() @@ -107,6 +119,7 @@ class VmDebootstrap(cliapp.Application): self.cleanup_system() def message(self, msg): + logging.info(msg) if self.settings['verbose']: print msg @@ -172,22 +185,24 @@ class VmDebootstrap(cliapp.Application): def debootstrap(self, rootdir): self.message('Debootstrapping') - if self.settings['arch'] == 'i386': - kernel_arch = '686' - else: - kernel_arch = self.settings['arch'] - kernel_image = 'linux-image-2.6-%s' % kernel_arch + include = self.settings['package'] + + if not self.settings['no-kernel']: + if self.settings['arch'] == 'i386': + kernel_arch = '686' + else: + kernel_arch = self.settings['arch'] + kernel_image = 'linux-image-2.6-%s' % kernel_arch + include.append(kernel_image) - include = [kernel_image] + self.settings['package'] if self.settings['sudo'] and 'sudo' not in include: include.append('sudo') - self.runcmd(['debootstrap', - '--arch=%s' % self.settings['arch'], - '--include=%s' % ','.join(include), - self.settings['distribution'], - rootdir, - self.settings['mirror']]) + args = ['debootstrap', '--arch=%s' % self.settings['arch']] + if include: args.append('--include=%s' % ','.join(include)) + args += [self.settings['distribution'], + rootdir, self.settings['mirror']] + self.runcmd(args) def set_hostname(self, rootdir): hostname = self.settings['hostname'] @@ -237,7 +252,7 @@ class VmDebootstrap(cliapp.Application): self.runcmd(['chroot', rootdir, 'passwd', '-l', 'root']) else: self.message('Give root an empty password') - self.runcmd(['chroot', rootdir, 'passwd', '-d', 'root']) + self.delete_password(rootdir, 'root') def create_users(self, rootdir): def create_user(user): @@ -253,11 +268,15 @@ class VmDebootstrap(cliapp.Application): self.set_password(rootdir, user, password) else: create_user(userpass) + self.delete_password(rootdir, userpass) def set_password(self, rootdir, user, password): encrypted = crypt.crypt(password, '..') self.runcmd(['chroot', rootdir, 'usermod', '-p', encrypted, user]) + def delete_password(self, rootdir, user): + self.runcmd(['chroot', rootdir, 'passwd', '-d', user]) + def remove_udev_persistent_rules(self, rootdir): self.message('Removing udev persistent cd and net rules') for x in ['70-persistent-cd.rules', '70-persistent-net.rules']: @@ -310,7 +329,7 @@ timeout 1 label linux kernel %(kernel)s -append initrd=%(initrd)s root=UUID=%(uuid)s ro quiet %(kserial)s +append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s %(extserial)s ''' % { 'kernel': kernel_image, @@ -337,10 +356,11 @@ append initrd=%(initrd)s root=UUID=%(uuid)s ro quiet %(kserial)s self.message('Cleaning up') - for mount_point in self.mount_points: - self.runcmd(['umount', mount_point], ignore_fail=True) + if self.settings['image']: + for mount_point in self.mount_points: + self.runcmd(['umount', mount_point], ignore_fail=True) - self.runcmd(['kpartx', '-d', self.settings['image']], ignore_fail=True) + self.runcmd(['kpartx', '-d', self.settings['image']], ignore_fail=True) for dirname in self.remove_dirs: shutil.rmtree(dirname) @@ -349,7 +369,14 @@ append initrd=%(initrd)s root=UUID=%(uuid)s ro quiet %(kserial)s script = self.settings['customize'] if script: self.message('Running customize script %s' % script) - self.runcmd([script, rootdir]) + with open('/dev/tty', 'w') as tty: + cliapp.runcmd([script, rootdir], stdout=tty, stderr=tty) + + def create_tarball(self, rootdir): + # Create a tarball of the disk's contents + # shell out to runcmd since it more easily handles rootdir + self.message('Creating tarball of disk contents') + self.runcmd(['tar', '-cf', self.settings['tarball'], '-C', rootdir, '.']) if __name__ == '__main__':