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)
|