Hi. I had a look at how to implement this, and came up with the attached patch. It is able to set up btrfs, but the resulting image do not boot. I do not understand why, so I thought it was time to ask for feedback. :)
-- Happy hacking Petter Reinholdtsen
diff --git a/vmdebootstrap b/vmdebootstrap index a6d43ac..6eb6d37 100755 --- a/vmdebootstrap +++ b/vmdebootstrap @@ -36,6 +36,9 @@ class VmDebootstrap(cliapp.Application): self.settings.boolean(['verbose'], 'report what is going on') self.settings.string(['image'], 'put created disk image in FILE', metavar='FILE') + self.settings.string(['roottype'], + 'specify file system type for /', + default='ext4') self.settings.bytesize(['size'], 'create a disk image of size SIZE (%default)', metavar='SIZE', @@ -110,7 +113,8 @@ class VmDebootstrap(cliapp.Application): try: rootdev = None - roottype = 'ext4' + self.settings['roottype'] = 'btrfs' + roottype = self.settings['roottype'] bootdev = None boottype = None if self.settings['image']: @@ -120,6 +124,13 @@ class VmDebootstrap(cliapp.Application): (rootdev,bootdev) = self.setup_kpartx() self.mkfs(rootdev, type=roottype) rootdir = self.mount(rootdev) + rootfsdir = rootdir + if 'btrfs' == roottype: + # Put root in a subvolume, to ease snapshots and volume management + newrootdir = "%s/@" % rootdir + self.runcmd(['btrfs', 'subvolume', 'create', newrootdir]) + os.mkdir("%s/btrfs" % newrootdir) + rootdir = newrootdir if bootdev: if self.settings['boottype']: boottype = self.settings['boottype'] @@ -143,7 +154,7 @@ class VmDebootstrap(cliapp.Application): self.customize(rootdir) if self.settings['image']: if not self.settings['no-extlinux']: - self.install_extlinux(rootdev, rootdir) + self.install_extlinux(rootdev, rootdir, rootfsdir) self.optimize_image(rootdir) if self.settings['foreign']: @@ -315,7 +326,11 @@ class VmDebootstrap(cliapp.Application): fstab = os.path.join(rootdir, 'etc', 'fstab') with open(fstab, 'w') as f: f.write('proc /proc proc defaults 0 0\n') - f.write('%s / %s errors=remount-ro 0 1\n' % (rootdevstr, roottype)) + if 'btrfs' == roottype: + f.write('%s / %s subvol=@,errors=remount-ro 0 1\n' % (rootdevstr, roottype)) + f.write('%s /btrfs %s errors=remount-ro 0 1\n' % (rootdevstr, roottype)) + else: + f.write('%s / %s errors=remount-ro 0 1\n' % (rootdevstr, roottype)) if bootdevstr: f.write('%s /boot %s errors=remount-ro 0 2\n' % (bootdevstr, boottype)) @@ -400,7 +415,7 @@ class VmDebootstrap(cliapp.Application): f.close() - def install_extlinux(self, rootdev, rootdir): + def install_extlinux(self, rootdev, rootdir, rootfsdir): self.message('Installing extlinux') def find(pattern): @@ -419,7 +434,7 @@ class VmDebootstrap(cliapp.Application): '-s', 'UUID', rootdev]) uuid = out.splitlines()[0].strip() - conf = os.path.join(rootdir, 'extlinux.conf') + conf = os.path.join(rootfsdir, 'extlinux.conf') logging.debug('configure extlinux %s' % conf) f = open(conf, 'w') f.write(''' @@ -428,7 +443,7 @@ timeout 1 label linux kernel %(kernel)s -append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s +append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s %(rootflags)s %(extserial)s ''' % { 'kernel': kernel_image, @@ -437,6 +452,7 @@ append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s 'kserial': 'console=ttyS0,115200' if self.settings['serial-console'] else '', 'extserial': 'serial 0 115200' if self.settings['serial-console'] else '', + 'rootflags': 'rootflags=subvol=@' if 'btrfs' == self.settings['roottype'] else '', }) f.close() @@ -447,7 +463,7 @@ append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s with open(inittab, 'a') as f: f.write('\nS0:23:respawn:%s\n' % serial_command) - self.runcmd(['extlinux', '--install', rootdir]) + self.runcmd(['extlinux', '--install', rootfsdir]) self.runcmd(['sync']) import time; time.sleep(2)