From: Petter Reinholdtsen Date: Sat, 26 Oct 2013 19:38:20 +0000 (+0200) Subject: Add support for building "foreign" images, ie non host arch images. This make it... X-Git-Url: https://git.siccegge.de//index.cgi?p=forks%2Fvmdebootstrap.git;a=commitdiff_plain;h=54291d325c2eec72ff56ce283398bcf6b3e12361 Add support for building "foreign" images, ie non host arch images. This make it possible to use vmdebootstrap to create Raspberry Pi images. It add support for these new options: --bootsize size when not the defautl '0%', create /boot/ partition of the given size --boottype fstype file system type of /boot/ (default ext2) --foreign /path/to/binfmt_handler When set, use foreign support in debootstrap. --variant variant ask debootstrap to build variant, not the default base system. --no-extlinux skip installation of extlinux, depend on customize script to make image bootable. With this patch in place, I got a working Raspberry PI image by adding a small customize script to install the binary blob needed to boot the Raspberry Pi. --- diff --git a/vmdebootstrap b/vmdebootstrap index a7a67e1..1de3e56 100755 --- a/vmdebootstrap +++ b/vmdebootstrap @@ -37,6 +37,18 @@ class VmDebootstrap(cliapp.Application): 'create a disk image of size SIZE (%default)', metavar='SIZE', default='1G') + self.settings.bytesize(['bootsize'], + 'create boot partition of size SIZE (%default)', + metavar='BOOTSIZE', + default='0%') + self.settings.string(['boottype'], + 'specify file system type for /boot/', + default='ext2') + self.settings.string(['foreign'], + 'set up foreign debootstrap environment using provided program (ie binfmt handler)') + self.settings.string(['variant'], + 'select debootstrap variant it not using the default') + self.settings.boolean(['no-extlinux'], 'do not install extlinux') self.settings.string(['tarball'], "tar up the disk's contents in FILE", metavar='FILE') self.settings.string(['mirror'], @@ -98,9 +110,18 @@ class VmDebootstrap(cliapp.Application): self.create_empty_image() self.partition_image() self.install_mbr() - rootdev = self.setup_kpartx() + (rootdev,bootdev) = self.setup_kpartx() self.mkfs(rootdev) rootdir = self.mount(rootdev) + if bootdev: + if self.settings['boottype']: + fstype = self.settings['boottype'] + else: + fstype = 'ext2' + self.mkfs(bootdev, type=fstype) + bootdir = '%s/%s' % (rootdir, 'boot/') + os.mkdir(bootdir) + bootdir = self.mount(bootdev, bootdir) else: rootdir = self.mkdtemp() self.debootstrap(rootdir) @@ -114,8 +135,14 @@ class VmDebootstrap(cliapp.Application): self.setup_networking(rootdir) self.customize(rootdir) if self.settings['image']: - self.install_extlinux(rootdev, rootdir) + if not self.settings['no-extlinux']: + self.install_extlinux(rootdev, rootdir) self.optimize_image(rootdir) + + if self.settings['foreign']: + os.unlink('%s/usr/bin/%s' % + (rootdir, os.path.basename(self.settings['foreign']))) + if self.settings['tarball']: self.create_tarball(rootdir) except BaseException, e: @@ -149,9 +176,12 @@ class VmDebootstrap(cliapp.Application): logging.debug('mkdir %s' % dirname) return dirname - def mount(self, device): + def mount(self, device, path=None): self.message('Mounting %s' % device) - mount_point = self.mkdtemp() + if not path: + mount_point = self.mkdtemp() + else: + mount_point = path self.runcmd(['mount', device, mount_point]) self.mount_points.append(mount_point) logging.debug('mounted %s on %s' % (device, mount_point)) @@ -167,8 +197,14 @@ class VmDebootstrap(cliapp.Application): self.message('Creating partitions') self.runcmd(['parted', '-s', self.settings['image'], 'mklabel', 'msdos']) + if self.settings['bootsize'] and self.settings['bootsize'] is not '0%': + bootsize=str(self.settings['bootsize']/(1024*1024)) + self.runcmd(['parted', '-s', self.settings['image'], + 'mkpart', 'primary', 'fat16', '0', bootsize]) + else: + bootsize='0%' self.runcmd(['parted', '-s', self.settings['image'], - 'mkpart', 'primary', '0%', '100%']) + 'mkpart', 'primary', bootsize, '100%']) self.runcmd(['parted', '-s', self.settings['image'], 'set', '1', 'boot', 'on']) @@ -178,21 +214,35 @@ class VmDebootstrap(cliapp.Application): def setup_kpartx(self): out = self.runcmd(['kpartx', '-av', self.settings['image']]) + if self.settings['bootsize']: + bootindex = 0 + rootindex = 1 + parts = 2 + else: + rootindex = 0 + parts = 1 + boot = None devices = [line.split()[2] for line in out.splitlines() if line.startswith('add map ')] - if len(devices) != 1: + if len(devices) != parts: raise cliapp.AppException('Surprising number of partitions') - return '/dev/mapper/%s' % devices[0] + root = '/dev/mapper/%s' % devices[rootindex] + if self.settings['bootsize']: + boot = '/dev/mapper/%s' % devices[bootindex] + return (root,boot) - def mkfs(self, device): + def mkfs(self, device, type='ext2'): self.message('Creating filesystem') - self.runcmd(['mkfs', '-t', 'ext2', device]) + self.runcmd(['mkfs', '-t', type, device]) def debootstrap(self, rootdir): self.message('Debootstrapping') - necessary_packages = ['acpid'] + if self.settings['foreign']: + necessary_packages = [] + else: + necessary_packages = ['acpid'] include = self.settings['package'] @@ -210,9 +260,20 @@ class VmDebootstrap(cliapp.Application): args = ['debootstrap', '--arch=%s' % self.settings['arch']] args.append( '--include=%s' % ','.join(necessary_packages + include)) + if self.settings['foreign']: + args.append('--foreign') + if self.settings['variant']: + args.append('--variant') + args.append(self.settings['variant']) args += [self.settings['distribution'], rootdir, self.settings['mirror']] self.runcmd(args) + if self.settings['foreign']: + # First copy the binfmt handler over + shutil.copy(self.settings['foreign'], '%s/usr/bin/' % rootdir) + # Next, run the package install scripts etc. + self.runcmd(['chroot', rootdir, + '/debootstrap/debootstrap', '--second-stage']) def set_hostname(self, rootdir): hostname = self.settings['hostname'] @@ -380,8 +441,10 @@ append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s self.message('Cleaning up') + # Umount in the reverse mount order if self.settings['image']: - for mount_point in self.mount_points: + for i in xrange(len(self.mount_points) - 1, -1, -1): + mount_point = self.mount_points[i] self.runcmd(['umount', mount_point], ignore_fail=True) self.runcmd(['kpartx', '-d', self.settings['image']], ignore_fail=True)