]> git.siccegge.de Git - forks/vmdebootstrap.git/blobdiff - vmdebootstrap
Create useable fstab for kfreebsd systems
[forks/vmdebootstrap.git] / vmdebootstrap
index 4c3aefc0f64d396ae3809e880c174a291d36bf08..c9764ae67c44fffe66cdff7b42d23fe4acbca7a6 100755 (executable)
@@ -20,6 +20,7 @@ import cliapp
 import crypt
 import logging
 import os
+import glob
 import re
 import sys
 import shutil
@@ -30,7 +31,7 @@ import time
 from distro_info import DebianDistroInfo, UbuntuDistroInfo
 
 
-__version__ = '0.10'
+__version__ = '0.11'
 
 # pylint: disable=invalid-name,line-too-long,missing-docstring,too-many-branches
 
@@ -125,7 +126,10 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
             'set up foreign debootstrap environment using provided program (ie binfmt handler)')
         self.settings.string(
             ['variant'],
-            'select debootstrap variant it not using the default')
+            'select debootstrap variant if not using the default [deprecated]')
+        self.settings.string_list(
+            ['debootstrapopts'],
+            'pass additional options to debootstrap'),
         self.settings.boolean(
             ['extlinux'],
             'install extlinux?',
@@ -479,7 +483,11 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
     def setup_kpartx(self):
         bootindex = None
         swapindex = None
-        out = self.runcmd(['kpartx', '-avs', self.settings['image']])
+        if 'freebsd' in os.sys.platform:
+            out = self.runcmd(['mdconfig', '-a', '-t', 'vnode', '-f',
+                               self.settings['image']])
+        else:
+            out = self.runcmd(['kpartx', '-avs', self.settings['image']])
         if self.settings['bootsize'] and self.settings['swap'] > 0:
             bootindex = 0
             rootindex = 1
@@ -507,19 +515,22 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
             parts = 1
         boot = None
         swap = None
-        devices = [line.split()[2]
-                   for line in out.splitlines()
-                   if line.startswith('add map ')]
+        if 'freebsd' in os.sys.platform:
+            devices = glob.glob("/dev/%ss*" % out.strip())
+        else:
+            devices = ['/dev/mapper/%s' % line.split()[2]
+                       for line in out.splitlines()
+                       if line.startswith('add map ')]
         if len(devices) != parts:
             msg = 'Surprising number of partitions - check output of losetup -a'
             logging.debug("%s", self.runcmd(['losetup', '-a']))
             logging.debug("%s: devices=%s parts=%s", msg, devices, parts)
             raise cliapp.AppException(msg)
-        root = '/dev/mapper/%s' % devices[rootindex]
+        root = devices[rootindex]
         if self.settings['bootsize'] or self.settings['use-uefi']:
-            boot = '/dev/mapper/%s' % devices[bootindex]
+            boot = devices[bootindex]
         if self.settings['swap'] > 0:
-            swap = '/dev/mapper/%s' % devices[swapindex]
+            swap = devices[swapindex]
         return root, boot, swap
 
     def _efi_packages(self):
@@ -641,7 +652,11 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
                 '--include=%s' % ','.join(include))
         if self.settings['foreign']:
             args.append('--foreign')
-        if self.settings['variant']:
+        if self.settings['debootstrapopts']:
+            for opt in self.settings['debootstrapopts']:
+                for part in opt.split(' '):
+                    args.append('--%s' % part)
+        elif self.settings['variant']:
             args.append('--variant')
             args.append(self.settings['variant'])
         args += [self.settings['distribution'],
@@ -685,24 +700,33 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
 
     def create_fstab(self, rootdir, rootdev, roottype, bootdev, boottype):  # pylint: disable=too-many-arguments
         def fsuuid(device):
-            out = self.runcmd(['blkid', '-c', '/dev/null', '-o', 'value',
-                               '-s', 'UUID', device])
-            return out.splitlines()[0].strip()
+            if 'freebsd' in os.sys.platform:
+                out = self.runcmd(['grub-probe', '-d', device, '-t', 'fs_uuid'])
+                return "/dev/ufsid/%s" % out.strip()
+            else:
+                out = self.runcmd(['blkid', '-c', '/dev/null', '-o', 'value',
+                                '-s', 'UUID', device])
+                return "UUID=%s" % out.splitlines()[0].strip()
 
         if rootdev:
-            rootdevstr = 'UUID=%s' % fsuuid(rootdev)
+            rootdevstr = fsuuid(rootdev)
         else:
             rootdevstr = '/dev/sda1'
 
         if bootdev and not self.settings['use-uefi']:
-            bootdevstr = 'UUID=%s' % fsuuid(bootdev)
+            bootdevstr = fsuuid(bootdev)
         else:
             bootdevstr = None
 
         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 'freebsd' in os.sys.platform:
+                f.write('proc  /proc   linprocfs rw 0 0\n')
+                f.write('sys   /sys    linsysfs  rw 0 0\n')
+                f.write('fdesc /dev/fd fdescfs   rw 0 0\n')
+            else:
+                f.write('proc /proc proc defaults 0 0\n')
+            f.write('%s / %s rw 0 1\n' % (rootdevstr, roottype))
             if bootdevstr:
                 f.write('%s /boot %s errors=remount-ro 0 2\n' % (bootdevstr, boottype))
                 if self.settings['swap'] > 0:
@@ -777,20 +801,34 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
             else:
                 logging.debug('not removing non-existent %s', pathname)
 
+    def mask_udev_predictable_rules(self, rootdir):
+        """
+        This can be reset later but to get networking working immediately
+        on boot, the interface we're going to use must be known without
+        reference to the eventual machine.
+        http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
+        """
+        self.message('Disabling systemd predictable interface names')
+        udev_path = os.path.join(
+            'etc', 'udev', 'rules.d', '80-net-setup-link.rules')
+        self.runcmd(['chroot', rootdir, 'ln', '-s', '/dev/null', udev_path])
+
     def setup_networking(self, rootdir):
         self.message('Setting up networking')
+        ifc_file = os.path.join(rootdir, 'etc', 'network', 'interfaces')
+        ifc_d = os.path.join(rootdir, 'etc', 'network', 'interfaces.d')
 
-        # unconditionally write for wheezy (which became oldstable on 04/25/2015)
+        # unconditionally write for wheezy (which became oldstable 2015.04.25)
         if self.was_oldstable(datetime.date(2015, 4, 26)):
-            with open(os.path.join(rootdir, 'etc', 'network', 'interfaces'), 'w') as netfile:
+            with open(ifc_file, 'w') as netfile:
                 netfile.write('source /etc/network/interfaces.d/*\n')
-            os.mkdir(os.path.join(rootdir, 'etc', 'network', 'interfaces.d'))
-
-        elif not os.path.exists(os.path.join(rootdir, 'etc', 'network', 'interfaces')):
-            iface_path = os.path.join(rootdir, 'etc', 'network', 'interfaces')
-            with open(iface_path, 'w') as netfile:
+        elif not os.path.exists(ifc_file):
+            with open(ifc_file, 'a') as netfile:
                 netfile.write('source-directory /etc/network/interfaces.d\n')
-        ethpath = os.path.join(rootdir, 'etc', 'network', 'interfaces.d', 'setup')
+
+        if not os.path.exists(ifc_d):
+            os.mkdir(ifc_d)
+        ethpath = os.path.join(ifc_d, 'setup')
         with open(ethpath, 'w') as eth:
             eth.write('auto lo\n')
             eth.write('iface lo inet loopback\n')
@@ -799,6 +837,8 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
                 eth.write('\n')
                 eth.write('auto eth0\n')
                 eth.write('iface eth0 inet dhcp\n')
+                # force predictable interface names
+                self.mask_udev_predictable_rules(rootdir)
 
     def append_serial_console(self, rootdir):
         if self.settings['serial-console']:
@@ -823,12 +863,20 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
             cfg.write("%s\n" % command)
 
     def _mount_wrapper(self, rootdir):
-        self.runcmd(['mount', '/dev', '-t', 'devfs', '-obind',
-                     '%s' % os.path.join(rootdir, 'dev')])
-        self.runcmd(['mount', '/proc', '-t', 'proc', '-obind',
-                     '%s' % os.path.join(rootdir, 'proc')])
-        self.runcmd(['mount', '/sys', '-t', 'sysfs', '-obind',
-                     '%s' % os.path.join(rootdir, 'sys')])
+        if 'freebsd' in os.sys.platform:
+            self.runcmd(['mount', 'dev', '-t', 'devfs',
+                        '%s' % os.path.join(rootdir, 'dev')])
+            self.runcmd(['mount', 'proc', '-t', 'linprocfs',
+                        '%s' % os.path.join(rootdir, 'proc')])
+            self.runcmd(['mount', 'sys', '-t', 'linsysfs',
+                        '%s' % os.path.join(rootdir, 'sys')])
+        else:
+            self.runcmd(['mount', '/dev', '-t', 'devfs', '-obind',
+                        '%s' % os.path.join(rootdir, 'dev')])
+            self.runcmd(['mount', '/proc', '-t', 'proc', '-obind',
+                        '%s' % os.path.join(rootdir, 'proc')])
+            self.runcmd(['mount', '/sys', '-t', 'sysfs', '-obind',
+                        '%s' % os.path.join(rootdir, 'sys')])
 
     def _umount_wrapper(self, rootdir):
         self.runcmd(['umount', os.path.join(rootdir, 'sys')])
@@ -997,7 +1045,13 @@ append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s
                     time.sleep(5)
                     self.runcmd(['umount', mount_point], ignore_fail=False)
 
-            self.runcmd(['kpartx', '-d', self.settings['image']], ignore_fail=True)
+            if 'freebsd' in os.sys.platform:
+                out = self.runcmd(['mdconfig', '-l', '-f', self.settings['image']])
+                for devid in out.split():
+                    self.runcmd(['mdconfig', '-d', '-u', devid],
+                                ignore_fail=True)
+            else:
+                self.runcmd(['kpartx', '-d', self.settings['image']], ignore_fail=True)
 
         for dirname in self.remove_dirs:
             shutil.rmtree(dirname)