Current location

narf Source control manager Git

aboutsummaryrefslogtreecommitdiff
blob: 2698738b95c2f9904c117e08501d4b74b9bb99da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
diff --git a/vmdebootstrap b/vmdebootstrap
index 4895147..c46be43 100755
--- a/vmdebootstrap
+++ b/vmdebootstrap
@@ -218,6 +218,25 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
                     self.runcmd(['mkswap', swapdev])
                 self.mkfs(rootdev, fstype=roottype)
                 rootdir = self.mount(rootdev)
+                rootfsdir = rootdir
+                if 'btrfs' == roottype:
+                    # Put root in a subvolume, to ease snapshots and volume management
+                    self.message("Creating root file system as btrfs subvolume @")
+                    self.runcmd(['btrfs', 'subvolume', 'create', "%s/@" % rootdir])
+
+                    # Make sure the subvolume mount point show in in
+                    # /proc/mounts for grub-update to figure out the
+                    # device for the root file system.
+                    newrootdir = "%s/build" % rootdir
+                    os.mkdir(newrootdir)
+                    self.mount(rootdev, newrootdir, ['-o','subvol=@'])
+#                    self.runcmd(['btrfs', 'subvolume', 'set-default', '@', rootdir])
+
+                    # Make the btrfs root file system available in the chroot.
+                    os.mkdir("%s/btrfs" % newrootdir)
+                    self.mount(rootdev, "%s/btrfs" % newrootdir)
+
+                    rootdir = newrootdir
                 if bootdev:
                     if self.settings['boottype']:
                         boottype = self.settings['boottype']
@@ -245,9 +264,9 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
 
             if self.settings['image']:
                 if self.settings['grub']:
-                    self.install_grub2(rootdev, rootdir)
+                    self.install_grub2(rootdev, rootdir, rootfsdir)
                 elif self.settings['extlinux']:
-                    self.install_extlinux(rootdev, rootdir)
+                    self.install_extlinux(rootdev, rootdir, rootfsdir)
                 self.append_serial_console(rootdir)
                 self.optimize_image(rootdir)
                 if self.settings['squash']:
@@ -300,13 +319,19 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
         logging.debug('mkdir %s', dirname)
         return dirname
 
-    def mount(self, device, path=None):
+    def mount(self, device, path=None, opts=None):
         if not path:
             mount_point = self.mkdtemp()
         else:
             mount_point = path
         self.message('Mounting %s on %s' % (device, mount_point))
-        self.runcmd(['mount', device, mount_point])
+        cmd = ['mount']
+        if opts is not None:
+            for opt in opts:
+                cmd.append(opt)
+        cmd.append(device)
+        cmd.append(mount_point)
+        self.runcmd(cmd)
         self.mount_points.append(mount_point)
         logging.debug('mounted %s on %s', device, mount_point)
         return mount_point
@@ -458,6 +483,9 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
         if self.settings['grub']:
             include.append('grub-pc')
 
+        if 'btrfs' == self.settings['roottype']:
+            include.append('btrfs-tools')
+
         if not self.settings['no-kernel']:
             if self.settings['kernel-package']:
                 kernel_image = self.settings['kernel-package']
@@ -546,7 +574,12 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
         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 defaults 0 1\n' % (rootdevstr, roottype))
+                f.write('%s / %s subvol=@ 0 1\n' % (rootdevstr, roottype))
+                f.write('%s /btrfs %s defaults 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))
                 if self.settings['swap'] > 0:
@@ -661,7 +694,8 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
             cfg.write("%s\n" % terminal)
             cfg.write("%s\n" % command)
 
-    def install_grub2(self, rootdev, rootdir):
+    def install_grub2(self, rootdev, rootdir, rootfsdir):
+        # FIXME use rootfsdir
         self.message("Configuring grub2")
         # rely on kpartx using consistent naming to map loop0p1 to loop0
         install_dev = os.path.join('/dev', os.path.basename(rootdev)[:-2])
@@ -679,12 +713,12 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
             self.runcmd(['chroot', rootdir, 'grub-install', install_dev])
         except cliapp.AppException:
             self.message("Failed. Is grub2-common installed? Using extlinux.")
-            self.install_extlinux(rootdev, rootdir)
+            self.install_extlinux(rootdev, rootdir, rootfsdir)
         self.runcmd(['umount', os.path.join(rootdir, 'sys')])
         self.runcmd(['umount', os.path.join(rootdir, 'proc')])
         self.runcmd(['umount', os.path.join(rootdir, 'dev')])
 
-    def install_extlinux(self, rootdev, rootdir):
+    def install_extlinux(self, rootdev, rootdir, rootfsdir):
         if not os.path.exists("/usr/bin/extlinux"):
             self.message("extlinux not installed, skipping.")
             return
@@ -711,7 +745,7 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
                            '-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)
         kserial = 'console=ttyS0,115200' if self.settings['serial-console'] else ''
         extserial = 'serial 0 115200' if self.settings['serial-console'] else ''
@@ -721,13 +755,14 @@ 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,  # pylint: disable=bad-continuation
             'initrd': initrd_image,  # pylint: disable=bad-continuation
             'uuid': uuid,  # pylint: disable=bad-continuation
             'kserial': kserial,  # pylint: disable=bad-continuation
+            'rootflags': 'rootfsflags=subvol=@' if 'btrfs' == self.settings['roottype'] else '',  # pylint: disable=bad-continuation
             'extserial': extserial,  # pylint: disable=bad-continuation
         }  # pylint: disable=bad-continuation
         logging.debug("extlinux config:\n%s", msg)
@@ -738,7 +773,7 @@ append initrd=%(initrd)s root=UUID=%(uuid)s ro %(kserial)s
         f = open(conf, 'w')
         f.write(msg)
 
-        self.runcmd(['extlinux', '--install', rootdir])
+        self.runcmd(['extlinux', '--install', rootfsdir])
         self.runcmd(['sync'])
         time.sleep(2)