summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Florath <andreas@florath.net>2017-01-29 23:52:40 +0000
committerYolanda Robla <yroblamo@redhat.com>2017-05-12 13:52:02 +0200
commite4e23897a13a3f3b9d28cc8d288990ab0fcc5b92 (patch)
tree8bc26d26aa81aad3e4f813e6f454fdda5701caba
parentb9c065de28371152b7e5914620e7421a9491f60e (diff)
Refactor: block-device filesystem creation, mount and fstab2.4.0
This patch finalizes the block device refactoring. It moves the three remaining levels (filesystem creation, mount and fstab handling) into the new python module. Now it is possible to use any number of disk images, any number of partitions and used them mounted to different directories. Notes: * unmount_dir : modified to only unmount the subdirs mounted by mount_proc_sys_dev(). dib-block-device unmounts $TMP_MOUNT_PATH/mnt (see I85e01f3898d3c043071de5fad82307cb091a64a9) Change-Id: I592c0b1329409307197460cfa8fd69798013f1f8 Signed-off-by: Andreas Florath <andreas@florath.net> Closes-Bug: #1664924
Notes
Notes (review): Code-Review+2: yolanda.robla <yroblamo@redhat.com> Workflow+1: yolanda.robla <yroblamo@redhat.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Fri, 12 May 2017 14:19:49 +0000 Reviewed-on: https://review.openstack.org/444586 Project: openstack/diskimage-builder Branch: refs/heads/master
-rw-r--r--diskimage_builder/block_device/blockdevice.py81
-rw-r--r--diskimage_builder/block_device/level1/partitioning.py3
-rw-r--r--[-rwxr-xr-x]diskimage_builder/block_device/level2/__init__.py (renamed from diskimage_builder/elements/zypper-minimal/install.d/15-zypper-fstab)16
-rw-r--r--diskimage_builder/block_device/level2/mkfs.py186
-rw-r--r--[-rwxr-xr-x]diskimage_builder/block_device/level3/__init__.py (renamed from diskimage_builder/elements/yum-minimal/install.d/15-base-fstab)16
-rw-r--r--diskimage_builder/block_device/level3/mount.py161
-rw-r--r--diskimage_builder/block_device/level4/__init__.py17
-rw-r--r--diskimage_builder/block_device/level4/fstab.py82
-rwxr-xr-xdiskimage_builder/elements/debootstrap/install.d/15-cleanup-debootstrap5
-rwxr-xr-xdiskimage_builder/elements/rpm-distro/post-install.d/05-fstab-rootfs-label12
-rw-r--r--diskimage_builder/elements/vm/block-device-default.yaml18
-rw-r--r--diskimage_builder/elements/vm/block-device-ppc.yaml6
-rw-r--r--diskimage_builder/elements/vm/environment.d/10-partitioning14
-rwxr-xr-xdiskimage_builder/elements/zypper/post-install.d/10-mkinitrd6
-rw-r--r--diskimage_builder/lib/common-functions4
-rw-r--r--diskimage_builder/lib/disk-image-create65
-rw-r--r--doc/source/user_guide/building_an_image.rst171
-rw-r--r--releasenotes/notes/block-device-mkfs-mount-fstab-42d7efe28fc2df04.yaml4
-rw-r--r--setup.cfg3
19 files changed, 739 insertions, 131 deletions
diff --git a/diskimage_builder/block_device/blockdevice.py b/diskimage_builder/block_device/blockdevice.py
index daa1ddd..9ff4918 100644
--- a/diskimage_builder/block_device/blockdevice.py
+++ b/diskimage_builder/block_device/blockdevice.py
@@ -22,6 +22,7 @@ import yaml
22 22
23from stevedore import extension 23from stevedore import extension
24 24
25from diskimage_builder.block_device.utils import exec_sudo
25from diskimage_builder.graph.digraph import Digraph 26from diskimage_builder.graph.digraph import Digraph
26 27
27 28
@@ -55,6 +56,8 @@ class BlockDevice(object):
55 After this call it is possible to copy / install all the needed 56 After this call it is possible to copy / install all the needed
56 files into the appropriate directories. 57 files into the appropriate directories.
57 58
59 cmd_writefstab: creates the (complete) fstab for the system.
60
58 cmd_umount: unmount and detaches all directories and used many 61 cmd_umount: unmount and detaches all directories and used many
59 resources. After this call the used (e.g.) images are still 62 resources. After this call the used (e.g.) images are still
60 available for further handling, e.g. converting from raw in 63 available for further handling, e.g. converting from raw in
@@ -248,6 +251,28 @@ class BlockDevice(object):
248 logger.info("Wrote final block device config to [%s]" 251 logger.info("Wrote final block device config to [%s]"
249 % self.config_json_file_name) 252 % self.config_json_file_name)
250 253
254 def _config_get_mount(self, path):
255 for entry in self.config:
256 for k, v in entry.items():
257 if k == 'mount' and v['mount_point'] == path:
258 return v
259 assert False
260
261 def _config_get_all_mount_points(self):
262 rvec = []
263 for entry in self.config:
264 for k, v in entry.items():
265 if k == 'mount':
266 rvec.append(v['mount_point'])
267 return rvec
268
269 def _config_get_mkfs(self, name):
270 for entry in self.config:
271 for k, v in entry.items():
272 if k == 'mkfs' and v['name'] == name:
273 return v
274 assert False
275
251 def cmd_getval(self, symbol): 276 def cmd_getval(self, symbol):
252 """Retrieve value from block device level 277 """Retrieve value from block device level
253 278
@@ -256,9 +281,25 @@ class BlockDevice(object):
256 (non python) access to internal configuration. 281 (non python) access to internal configuration.
257 282
258 Arguments: 283 Arguments:
259 :symbol: The symbol to find 284 :param symbol: the symbol to get
260 """ 285 """
261 logger.info("Getting value for [%s]" % symbol) 286 logger.info("Getting value for [%s]" % symbol)
287 if symbol == "root-label":
288 root_mount = self._config_get_mount("/")
289 root_fs = self._config_get_mkfs(root_mount['base'])
290 logger.debug("root-label [%s]" % root_fs['label'])
291 print("%s" % root_fs['label'])
292 return 0
293 if symbol == "root-fstype":
294 root_mount = self._config_get_mount("/")
295 root_fs = self._config_get_mkfs(root_mount['base'])
296 logger.debug("root-fstype [%s]" % root_fs['type'])
297 print("%s" % root_fs['type'])
298 return 0
299 if symbol == 'mount-points':
300 mount_points = self._config_get_all_mount_points()
301 print("%s" % " ".join(mount_points))
302 return 0
262 if symbol == 'image-block-partition': 303 if symbol == 'image-block-partition':
263 # If there is no partition needed, pass back directly the 304 # If there is no partition needed, pass back directly the
264 # image. 305 # image.
@@ -270,9 +311,47 @@ class BlockDevice(object):
270 if symbol == 'image-path': 311 if symbol == 'image-path':
271 print("%s" % self.state['blockdev']['image0']['image']) 312 print("%s" % self.state['blockdev']['image0']['image'])
272 return 0 313 return 0
314
273 logger.error("Invalid symbol [%s] for getval" % symbol) 315 logger.error("Invalid symbol [%s] for getval" % symbol)
274 return 1 316 return 1
275 317
318 def cmd_writefstab(self):
319 """Creates the fstab"""
320 logger.info("Creating fstab")
321
322 tmp_fstab = os.path.join(self.state_dir, "fstab")
323 with open(tmp_fstab, "wt") as fstab_fd:
324 # This gives the order in which this must be mounted
325 for mp in self.state['mount_order']:
326 logger.debug("Writing fstab entry for [%s]" % mp)
327 fs_base = self.state['mount'][mp]['base']
328 fs_name = self.state['mount'][mp]['name']
329 fs_val = self.state['filesys'][fs_base]
330 if 'label' in fs_val:
331 diskid = "LABEL=%s" % fs_val['label']
332 else:
333 diskid = "UUID=%s" % fs_val['uuid']
334
335 # If there is no fstab entry - do not write anything
336 if 'fstab' not in self.state:
337 continue
338 if fs_name not in self.state['fstab']:
339 continue
340
341 options = self.state['fstab'][fs_name]['options']
342 dump_freq = self.state['fstab'][fs_name]['dump-freq']
343 fsck_passno = self.state['fstab'][fs_name]['fsck-passno']
344
345 fstab_fd.write("%s %s %s %s %s %s\n"
346 % (diskid, mp, fs_val['fstype'],
347 options, dump_freq, fsck_passno))
348
349 target_etc_dir = os.path.join(self.params['build-dir'], 'built', 'etc')
350 exec_sudo(['mkdir', '-p', target_etc_dir])
351 exec_sudo(['cp', tmp_fstab, os.path.join(target_etc_dir, "fstab")])
352
353 return 0
354
276 def cmd_create(self): 355 def cmd_create(self):
277 """Creates the block device""" 356 """Creates the block device"""
278 357
diff --git a/diskimage_builder/block_device/level1/partitioning.py b/diskimage_builder/block_device/level1/partitioning.py
index 3b1cd54..937379c 100644
--- a/diskimage_builder/block_device/level1/partitioning.py
+++ b/diskimage_builder/block_device/level1/partitioning.py
@@ -85,6 +85,9 @@ class Partition(Digraph.Node):
85 def get_type(self): 85 def get_type(self):
86 return self.ptype 86 return self.ptype
87 87
88 def get_name(self):
89 return self.name
90
88 def insert_edges(self, dg): 91 def insert_edges(self, dg):
89 bnode = dg.find(self.base) 92 bnode = dg.find(self.base)
90 assert bnode is not None 93 assert bnode is not None
diff --git a/diskimage_builder/elements/zypper-minimal/install.d/15-zypper-fstab b/diskimage_builder/block_device/level2/__init__.py
index cffbe1d..2545690 100755..100644
--- a/diskimage_builder/elements/zypper-minimal/install.d/15-zypper-fstab
+++ b/diskimage_builder/block_device/level2/__init__.py
@@ -1,6 +1,4 @@
1#!/bin/bash 1# Copyright 2017 Andreas Florath (andreas@florath.net)
2#
3# Copyright 2015 Hewlett-Packard Development Company, L.P.
4# 2#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may 3# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain 4# not use this file except in compliance with the License. You may obtain
@@ -13,15 +11,7 @@
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations 12# License for the specific language governing permissions and limitations
15# under the License. 13# under the License.
16#
17 14
18if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then 15from diskimage_builder.block_device.level2.mkfs import Mkfs
19 set -x
20fi
21set -eu
22set -o pipefail
23 16
24cat << EOF > /etc/fstab 17__all__ = [Mkfs]
25proc /proc proc nodev,noexec,nosuid 0 0
26LABEL=${DIB_ROOT_LABEL} / ${FS_TYPE} errors=remount-ro 0 1
27EOF
diff --git a/diskimage_builder/block_device/level2/mkfs.py b/diskimage_builder/block_device/level2/mkfs.py
new file mode 100644
index 0000000..fe27dda
--- /dev/null
+++ b/diskimage_builder/block_device/level2/mkfs.py
@@ -0,0 +1,186 @@
1# Copyright 2017 Andreas Florath (andreas@florath.net)
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import logging
16import uuid
17
18from diskimage_builder.block_device.blockdevice \
19 import BlockDeviceSetupException
20from diskimage_builder.block_device.tree_config import TreeConfig
21from diskimage_builder.block_device.utils import exec_sudo
22from diskimage_builder.graph.digraph import Digraph
23
24
25logger = logging.getLogger(__name__)
26
27
28# There is the need that filesystem labels are unique:
29# if not the boot and / or mount (with LABEL=) might fail.
30file_system_labels = set()
31
32# There is the need to check the length of the label of
33# the filesystem. The maximum length depends on the used filesystem.
34# This map provides information about the maximum label length.
35file_system_max_label_length = {
36 "ext2": 16,
37 "ext3": 16,
38 "ext4": 16,
39 "xfs": 12,
40 "vfat": 11
41}
42
43
44class Filesystem(Digraph.Node):
45
46 def _config_error(self, msg):
47 logger.error(msg)
48 raise BlockDeviceSetupException(msg)
49
50 def __init__(self, config):
51 logger.debug("Create filesystem object; config [%s]" % config)
52 # Parameter check (mandatory)
53 for pname in ['base', 'name', 'type']:
54 if pname not in config:
55 self._config_error("Mkfs config needs [%s]" % pname)
56 setattr(self, pname, config[pname])
57
58 # Parameter check (optional)
59 for pname in ['label', 'opts', 'uuid']:
60 setattr(self, pname,
61 config[pname] if pname in config else None)
62
63 if self.label is None:
64 self.label = self.name
65
66 # Historic reasons - this will hopefully vanish in one of
67 # the next major releases
68 if self.label == "cloudimg-rootfs" and self.type == "xfs":
69 logger.warning("Default label [cloudimg-rootfs] too long for xfs "
70 "file system - using [img-rootfs] instead")
71 self.label = "img-rootfs"
72
73 if self.label in file_system_labels:
74 self._config_error(
75 "File system label [%s] used more than once" %
76 self.label)
77 file_system_labels.add(self.label)
78
79 if self.type in file_system_max_label_length:
80 if file_system_max_label_length[self.type] < \
81 len(self.label):
82 self._config_error(
83 "Label [%s] too long for filesystem [%s]: "
84 "maximum length [%d] provided length [%d]" %
85 (self.label, self.type,
86 file_system_max_label_length[self.type],
87 len(self.label)))
88 else:
89 logger.warning("Length of label [%s] cannot be checked for "
90 "filesystem [%s]: unknown max length" %
91 (self.label, self.type))
92 logger.warning("Continue - but this might lead to an error")
93
94 if self.opts is not None:
95 self.opts = self.opts.strip().split(' ')
96
97 if self.uuid is None:
98 self.uuid = str(uuid.uuid4())
99
100 Digraph.Node.__init__(self, self.name)
101
102 logger.debug("Filesystem created [%s]" % self)
103
104 def __repr__(self):
105 return "<Filesystem base [%s] name [%s] type [%s]>" \
106 % (self.base, self.name, self.type)
107
108 def insert_edges(self, dg):
109 logger.debug("Insert edge [%s]" % self)
110 bnode = dg.find(self.base)
111 assert bnode is not None
112 dg.create_edge(bnode, self)
113
114 def create(self, result, rollback):
115 logger.info("create called; result [%s]" % result)
116
117 cmd = ["mkfs"]
118
119 cmd.extend(['-t', self.type])
120 if self.opts:
121 cmd.extend(self.opts)
122 cmd.extend(["-L", self.label])
123
124 if self.type in ('ext2', 'ext3', 'ext4'):
125 cmd.extend(['-U', self.uuid])
126 elif self.type == 'xfs':
127 cmd.extend(['-m', "uuid=%s" % self.uuid])
128 else:
129 logger.warning("UUID will not be written for fs type [%s]"
130 % self.type)
131
132 if self.type in ('ext2', 'ext3', 'ext4', 'xfs'):
133 cmd.append('-q')
134
135 if 'blockdev' not in result:
136 result['blockdev'] = {}
137 device = result['blockdev'][self.base]['device']
138 cmd.append(device)
139
140 logger.debug("Creating fs command [%s]" % (cmd))
141 exec_sudo(cmd)
142
143 if 'filesys' not in result:
144 result['filesys'] = {}
145 result['filesys'][self.name] \
146 = {'uuid': self.uuid, 'label': self.label,
147 'fstype': self.type, 'opts': self.opts,
148 'device': device}
149
150 def umount(self, state):
151 """Mkfs does not need any umount."""
152 pass
153
154 def cleanup(self, state):
155 """Mkfs does not need any cleanup."""
156 pass
157
158 def delete(self, state):
159 """Mkfs does not need any delete."""
160 pass
161
162
163class Mkfs(object):
164 """Module for creating file systems
165
166 This block device module handles creating different file
167 systems.
168 """
169
170 type_string = "mkfs"
171 tree_config = TreeConfig("mkfs")
172
173 def __init__(self, config, default_config):
174 logger.debug("Create Mkfs object; config [%s]" % config)
175 logger.debug("default_config [%s]" % default_config)
176 self.config = config
177 self.default_config = default_config
178 self.filesystems = {}
179
180 fs = Filesystem(self.config)
181 self.filesystems[fs.get_name()] = fs
182
183 def insert_nodes(self, dg):
184 for _, fs in self.filesystems.items():
185 logger.debug("Insert node [%s]" % fs)
186 dg.add_node(fs)
diff --git a/diskimage_builder/elements/yum-minimal/install.d/15-base-fstab b/diskimage_builder/block_device/level3/__init__.py
index a766a9d..5fa3fe4 100755..100644
--- a/diskimage_builder/elements/yum-minimal/install.d/15-base-fstab
+++ b/diskimage_builder/block_device/level3/__init__.py
@@ -1,6 +1,4 @@
1#!/bin/bash 1# Copyright 2017 Andreas Florath (andreas@florath.net)
2#
3# Copyright 2015 Hewlett-Packard Development Company, L.P.
4# 2#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may 3# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain 4# not use this file except in compliance with the License. You may obtain
@@ -13,15 +11,7 @@
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations 12# License for the specific language governing permissions and limitations
15# under the License. 13# under the License.
16#
17 14
18if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then 15from diskimage_builder.block_device.level3.mount import Mount
19 set -x
20fi
21set -eu
22set -o pipefail
23 16
24cat << EOF | tee /etc/fstab > /dev/null 17__all__ = [Mount]
25proc /proc proc nodev,noexec,nosuid 0 0
26LABEL=${DIB_ROOT_LABEL} / ${FS_TYPE} errors=remount-ro 0 1
27EOF
diff --git a/diskimage_builder/block_device/level3/mount.py b/diskimage_builder/block_device/level3/mount.py
new file mode 100644
index 0000000..b247b1f
--- /dev/null
+++ b/diskimage_builder/block_device/level3/mount.py
@@ -0,0 +1,161 @@
1# Copyright 2017 Andreas Florath (andreas@florath.net)
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import logging
16import os
17
18from diskimage_builder.block_device.blockdevice \
19 import BlockDeviceSetupException
20from diskimage_builder.block_device.tree_config import TreeConfig
21from diskimage_builder.block_device.utils import exec_sudo
22from diskimage_builder.block_device.utils import sort_mount_points
23from diskimage_builder.graph.digraph import Digraph
24
25
26logger = logging.getLogger(__name__)
27
28
29# There is the need to collect all mount points to be able to
30# sort them in a sensible way.
31mount_points = {}
32# The order of mounting and unmounting is important.
33sorted_mount_points = None
34
35
36class MountPoint(Digraph.Node):
37
38 @staticmethod
39 def _config_error(msg):
40 logger.error(msg)
41 raise BlockDeviceSetupException(msg)
42
43 def __init__(self, mount_base, config):
44 # Parameter check
45 self.mount_base = mount_base
46 for pname in ['base', 'name', 'mount_point']:
47 if pname not in config:
48 self._config_error("MountPoint config needs [%s]" % pname)
49 setattr(self, pname, config[pname])
50 Digraph.Node.__init__(self, self.name)
51 logger.debug("MountPoint created [%s]" % self)
52
53 def __repr__(self):
54 return "<MountPoint base [%s] name [%s] mount_point [%s]>" \
55 % (self.base, self.name, self.mount_point)
56
57 def insert_node(self, dg):
58 global mount_points
59 if self.mount_point in mount_points:
60 self._config_error("Mount point [%s] specified more than once"
61 % self.mount_point)
62 logger.debug("Insert node [%s]" % self)
63 mount_points[self.mount_point] = self
64 dg.add_node(self)
65
66 def insert_edges(self, dg):
67 """Insert all edges
68
69 After inserting all the nodes, the order of the mounting and
70 umounting can be computed. There is the need to mount
71 mount-points that contain other mount-points first.
72 Example: '/var' must be mounted before '/var/log'. If not the
73 second is not used for files at all.
74
75 The dependency edge is created in all cases from the base
76 element (typically a mkfs) and, if this is not the 'first'
77 mount-point, also depend on the mount point before. This
78 ensures that during mounting (and umounting) the correct
79 order is used.
80 """
81 logger.debug("Insert edge [%s]" % self)
82 global mount_points
83 global sorted_mount_points
84 if sorted_mount_points is None:
85 logger.debug("Mount points [%s]" % mount_points)
86 sorted_mount_points = sort_mount_points(mount_points.keys())
87 logger.info("Sorted mount points [%s]" % (sorted_mount_points))
88
89 # Look for the occurance in the list
90 mpi = sorted_mount_points.index(self.mount_point)
91 if mpi > 0:
92 # If not the first: add also the dependency
93 dg.create_edge(mount_points[sorted_mount_points[mpi - 1]], self)
94
95 bnode = dg.find(self.base)
96 assert bnode is not None
97 dg.create_edge(bnode, self)
98
99 def create(self, result, rollback):
100 logger.debug("mount called [%s]" % self.mount_point)
101 logger.debug("result [%s]" % result)
102 rel_mp = self.mount_point if self.mount_point[0] != '/' \
103 else self.mount_point[1:]
104 mount_point = os.path.join(self.mount_base, rel_mp)
105 if not os.path.exists(mount_point):
106 # Need to sudo this because of permissions in the new
107 # file system tree.
108 exec_sudo(['mkdir', '-p', mount_point])
109 logger.info("Mounting [%s] to [%s]" % (self.name, mount_point))
110 exec_sudo(["mount", result['filesys'][self.base]['device'],
111 mount_point])
112
113 if 'mount' not in result:
114 result['mount'] = {}
115 result['mount'][self.mount_point] \
116 = {'name': self.name, 'base': self.base, 'path': mount_point}
117
118 if 'mount_order' not in result:
119 result['mount_order'] = []
120 result['mount_order'].append(self.mount_point)
121
122 def umount(self, state):
123 logger.info("Called for [%s]" % self.name)
124 exec_sudo(["umount", state['mount'][self.mount_point]['path']])
125
126 def cleanup(self, state):
127 """Mount does not need any cleanup."""
128 pass
129
130 def delete(self, state):
131 self.umount(state)
132
133
134class Mount(object):
135
136 type_string = "mount"
137 tree_config = TreeConfig("mount")
138
139 def _config_error(self, msg):
140 logger.error(msg)
141 raise BlockDeviceSetupException(msg)
142
143 def __init__(self, config, params):
144 logger.debug("Mounting object; config [%s]" % config)
145 self.config = config
146 self.params = params
147
148 if 'mount-base' not in self.params:
149 MountPoint._config_error("Mount default config needs 'mount-base'")
150 self.mount_base = self.params['mount-base']
151
152 self.mount_points = {}
153
154 mp = MountPoint(self.mount_base, self.config)
155 self.mount_points[mp.get_name()] = mp
156
157 def insert_nodes(self, dg):
158 global sorted_mount_points
159 assert sorted_mount_points is None
160 for _, mp in self.mount_points.items():
161 mp.insert_node(dg)
diff --git a/diskimage_builder/block_device/level4/__init__.py b/diskimage_builder/block_device/level4/__init__.py
new file mode 100644
index 0000000..568d86b
--- /dev/null
+++ b/diskimage_builder/block_device/level4/__init__.py
@@ -0,0 +1,17 @@
1# Copyright 2017 Andreas Florath (andreas@florath.net)
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from diskimage_builder.block_device.level4.fstab import Fstab
16
17__all__ = [Fstab]
diff --git a/diskimage_builder/block_device/level4/fstab.py b/diskimage_builder/block_device/level4/fstab.py
new file mode 100644
index 0000000..dc91ebc
--- /dev/null
+++ b/diskimage_builder/block_device/level4/fstab.py
@@ -0,0 +1,82 @@
1# Copyright 2017 Andreas Florath (andreas@florath.net)
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import logging
16
17from diskimage_builder.block_device.blockdevice \
18 import BlockDeviceSetupException
19from diskimage_builder.block_device.tree_config import TreeConfig
20from diskimage_builder.graph.digraph import Digraph
21
22
23logger = logging.getLogger(__name__)
24
25
26class Fstab(Digraph.Node):
27
28 type_string = "fstab"
29 tree_config = TreeConfig("fstab")
30
31 def _config_error(self, msg):
32 logger.error(msg)
33 raise BlockDeviceSetupException(msg)
34
35 def __init__(self, config, params):
36 logger.debug("Fstab object; config [%s]" % config)
37 self.config = config
38 self.params = params
39 self.name = self.config['name']
40 self.base = self.config['base']
41 Digraph.Node.__init__(self, self.name)
42
43 self.options = self.config.get('options', 'defaults')
44 self.dump_freq = self.config.get('dump-freq', 0)
45 self.fsck_passno = self.config.get('fsck-passno', 2)
46
47 def insert_nodes(self, dg):
48 logger.debug("Insert node")
49 dg.add_node(self)
50
51 def insert_edges(self, dg):
52 logger.debug("Insert edge [%s]" % self)
53 bnode = dg.find(self.base)
54 assert bnode is not None
55 dg.create_edge(bnode, self)
56
57 def create(self, result, rollback):
58 logger.debug("fstab create called [%s]" % self.name)
59 logger.debug("result [%s]" % result)
60
61 if 'fstab' not in result:
62 result['fstab'] = {}
63
64 result['fstab'][self.base] = {
65 'name': self.name,
66 'base': self.base,
67 'options': self.options,
68 'dump-freq': self.dump_freq,
69 'fsck-passno': self.fsck_passno
70 }
71
72 def umount(self, state):
73 """Fstab does not need any umount task."""
74 pass
75
76 def cleanup(self, state):
77 """Fstab does not need any cleanup."""
78 pass
79
80 def delete(self, state):
81 """Fstab does not need any cleanup."""
82 pass
diff --git a/diskimage_builder/elements/debootstrap/install.d/15-cleanup-debootstrap b/diskimage_builder/elements/debootstrap/install.d/15-cleanup-debootstrap
index a256612..3059a05 100755
--- a/diskimage_builder/elements/debootstrap/install.d/15-cleanup-debootstrap
+++ b/diskimage_builder/elements/debootstrap/install.d/15-cleanup-debootstrap
@@ -23,8 +23,3 @@ set -o pipefail
23 23
24install -d -m 0755 -o root -g root /etc/sudoers.d 24install -d -m 0755 -o root -g root /etc/sudoers.d
25echo 'blacklist pcspkr' > /etc/modprobe.d/blacklist.conf 25echo 'blacklist pcspkr' > /etc/modprobe.d/blacklist.conf
26
27cat << EOF | tee /etc/fstab > /dev/null
28proc /proc proc nodev,noexec,nosuid 0 0
29LABEL=${DIB_ROOT_LABEL} / ${FS_TYPE} errors=remount-ro 0 1
30EOF
diff --git a/diskimage_builder/elements/rpm-distro/post-install.d/05-fstab-rootfs-label b/diskimage_builder/elements/rpm-distro/post-install.d/05-fstab-rootfs-label
deleted file mode 100755
index bf3e159..0000000
--- a/diskimage_builder/elements/rpm-distro/post-install.d/05-fstab-rootfs-label
+++ /dev/null
@@ -1,12 +0,0 @@
1#!/bin/bash
2
3if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
4 set -x
5fi
6set -eu
7set -o pipefail
8
9# Fedora 18 sets up for root to have a label of "_/"
10# Fedora 19 sets up for root to have a UUID
11# This regex will catch both
12sed -i "s%.*\s\/\s%LABEL=${DIB_ROOT_LABEL} / %" /etc/fstab
diff --git a/diskimage_builder/elements/vm/block-device-default.yaml b/diskimage_builder/elements/vm/block-device-default.yaml
index 85b41a3..31cfdd5 100644
--- a/diskimage_builder/elements/vm/block-device-default.yaml
+++ b/diskimage_builder/elements/vm/block-device-default.yaml
@@ -4,9 +4,15 @@
4 name: image0 4 name: image0
5 5
6- partitioning: 6- partitioning:
7 base: image0 7 base: image0
8 label: mbr 8 label: mbr
9 partitions: 9 partitions:
10 - name: root 10 - name: root
11 flags: [ boot, primary ] 11 flags: [ boot, primary ]
12 size: 100% 12 size: 100%
13 mkfs:
14 mount:
15 mount_point: /
16 fstab:
17 options: "defaults"
18 fsck-passno: 1
diff --git a/diskimage_builder/elements/vm/block-device-ppc.yaml b/diskimage_builder/elements/vm/block-device-ppc.yaml
index 2b3a78d..cf3a26b 100644
--- a/diskimage_builder/elements/vm/block-device-ppc.yaml
+++ b/diskimage_builder/elements/vm/block-device-ppc.yaml
@@ -28,3 +28,9 @@
28 - name: root 28 - name: root
29 flags: [ primary ] 29 flags: [ primary ]
30 size: 100% 30 size: 100%
31 mkfs:
32 mount:
33 mount_point: /
34 fstab:
35 options: "defaults"
36 fsck-passno: 1
diff --git a/diskimage_builder/elements/vm/environment.d/10-partitioning b/diskimage_builder/elements/vm/environment.d/10-partitioning
deleted file mode 100644
index 7aeea5a..0000000
--- a/diskimage_builder/elements/vm/environment.d/10-partitioning
+++ /dev/null
@@ -1,14 +0,0 @@
1_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
2
3if [[ "$ARCH" =~ "ppc" ]] ; then
4 DIB_BLOCK_DEVICE_DEFAULT_CONFIG="$(cat $_DIR/../block-device-ppc.yaml)"
5else
6 DIB_BLOCK_DEVICE_DEFAULT_CONFIG="$(cat $_DIR/../block-device-default.yaml)"
7fi
8
9DIB_BLOCK_DEVICE_CONFIG=${DIB_BLOCK_DEVICE_CONFIG:-${DIB_BLOCK_DEVICE_DEFAULT_CONFIG}}
10export DIB_BLOCK_DEVICE_CONFIG
11
12# Local variables:
13# mode: sh
14# End:
diff --git a/diskimage_builder/elements/zypper/post-install.d/10-mkinitrd b/diskimage_builder/elements/zypper/post-install.d/10-mkinitrd
index 6162655..6d572d6 100755
--- a/diskimage_builder/elements/zypper/post-install.d/10-mkinitrd
+++ b/diskimage_builder/elements/zypper/post-install.d/10-mkinitrd
@@ -12,10 +12,12 @@ set -o pipefail
12# that will actually be used for the final image. This is likely something 12# that will actually be used for the final image. This is likely something
13# different than what the chroot is currently on (which might currently be a 13# different than what the chroot is currently on (which might currently be a
14# tmpfs even). 14# tmpfs even).
15echo "rootfstype=$FS_TYPE" > /etc/sysconfig/initrd 15echo "rootfstype=${DIB_ROOT_FSTYPE}" > /etc/sysconfig/initrd
16 16
17# ToDo: This it not really clear to me.
18# Let's see which error occurs.
17# openSuse mkinitrd requires a valid root device be in fstab. 19# openSuse mkinitrd requires a valid root device be in fstab.
18sed -i 's/vda1/sda1/' /etc/fstab 20##sed -i 's/vda1/sda1/' /etc/fstab
19mkinitrd -A -B 21mkinitrd -A -B
20 22
21# And cleanup again 23# And cleanup again
diff --git a/diskimage_builder/lib/common-functions b/diskimage_builder/lib/common-functions
index e1153a4..7faee8f 100644
--- a/diskimage_builder/lib/common-functions
+++ b/diskimage_builder/lib/common-functions
@@ -353,7 +353,9 @@ function unmount_dir {
353 # /proc/mounts is the real path 353 # /proc/mounts is the real path
354 real_dir=$(readlink -e $dir) 354 real_dir=$(readlink -e $dir)
355 355
356 mnts=$(awk '{print $2}' < /proc/mounts | grep "^$real_dir" | sort -r) 356 # note the "/" on real_dir ... we are just looking for things
357 # mounted *underneath* this directory.
358 mnts=$(awk '{print $2}' < /proc/mounts | grep "^$real_dir/" | sort -r)
357 for m in $mnts; do 359 for m in $mnts; do
358 echo "Unmount $m" 360 echo "Unmount $m"
359 sudo umount -fl $m || true 361 sudo umount -fl $m || true
diff --git a/diskimage_builder/lib/disk-image-create b/diskimage_builder/lib/disk-image-create
index 2fe6a03..3b76af6 100644
--- a/diskimage_builder/lib/disk-image-create
+++ b/diskimage_builder/lib/disk-image-create
@@ -115,7 +115,7 @@ DIB_DEBUG_TRACE=${DIB_DEBUG_TRACE:-0}
115INSTALL_PACKAGES="" 115INSTALL_PACKAGES=""
116IMAGE_TYPES=("qcow2") 116IMAGE_TYPES=("qcow2")
117COMPRESS_IMAGE="true" 117COMPRESS_IMAGE="true"
118export DIB_ROOT_LABEL="" 118ROOT_LABEL=""
119DIB_DEFAULT_INSTALLTYPE=${DIB_DEFAULT_INSTALLTYPE:-"source"} 119DIB_DEFAULT_INSTALLTYPE=${DIB_DEFAULT_INSTALLTYPE:-"source"}
120MKFS_OPTS="" 120MKFS_OPTS=""
121ACI_MANIFEST=${ACI_MANIFEST:-} 121ACI_MANIFEST=${ACI_MANIFEST:-}
@@ -147,7 +147,7 @@ while true ; do
147 --no-tmpfs) shift; export DIB_NO_TMPFS=1;; 147 --no-tmpfs) shift; export DIB_NO_TMPFS=1;;
148 --offline) shift; export DIB_OFFLINE=1;; 148 --offline) shift; export DIB_OFFLINE=1;;
149 --qemu-img-options) QEMU_IMG_OPTIONS=$2; shift 2;; 149 --qemu-img-options) QEMU_IMG_OPTIONS=$2; shift 2;;
150 --root-label) export DIB_ROOT_LABEL=$2; shift 2;; 150 --root-label) ROOT_LABEL=$2; shift 2;;
151 --ramdisk-element) RAMDISK_ELEMENT=$2; shift 2;; 151 --ramdisk-element) RAMDISK_ELEMENT=$2; shift 2;;
152 --install-type) DIB_DEFAULT_INSTALLTYPE=$2; shift 2;; 152 --install-type) DIB_DEFAULT_INSTALLTYPE=$2; shift 2;;
153 --docker-target) export DOCKER_TARGET=$2; shift 2 ;; 153 --docker-target) export DOCKER_TARGET=$2; shift 2 ;;
@@ -250,26 +250,6 @@ if [[ -z "$(which fstrim)" ]]; then
250 exit 1 250 exit 1
251fi 251fi
252 252
253# NOTE: Tuning the rootfs uuid works only for ext filesystems.
254# Rely on the below environment variable only for ext filesystems.
255export DIB_IMAGE_ROOT_FS_UUID=$(uuidgen -r)
256if echo "$FS_TYPE" | grep -q "^ext" && [ -z "${DIB_IMAGE_ROOT_FS_UUID}" ]; then
257 echo "ext filesystem detected but no DIB_IMAGE_ROOT_FS_UUID found."
258 echo "Is the uuidgen utility installed on your system?"
259 exit 1
260fi
261
262# FS_TYPE isn't available until after we source img-defaults
263if [ -z "$DIB_ROOT_LABEL" ]; then
264 # NOTE(bnemec): XFS has a limit of 12 characters for filesystem labels
265 # Not changing the default for other filesystems to maintain backwards compatibility
266 if [ "$FS_TYPE" = "xfs" ]; then
267 DIB_ROOT_LABEL="img-rootfs"
268 else
269 DIB_ROOT_LABEL="cloudimg-rootfs"
270 fi
271fi
272
273# xattr support cannot be relied upon with tmpfs builds 253# xattr support cannot be relied upon with tmpfs builds
274# some kernels supoprt it, some don't 254# some kernels supoprt it, some don't
275if [[ -n "${GENTOO_PROFILE}" ]]; then 255if [[ -n "${GENTOO_PROFILE}" ]]; then
@@ -294,13 +274,22 @@ cat >${DIB_BLOCK_DEVICE_PARAMS_YAML} <<EOF
294config: ${BLOCK_DEVICE_CONFIG_YAML} 274config: ${BLOCK_DEVICE_CONFIG_YAML}
295image-dir: ${TMP_IMAGE_DIR} 275image-dir: ${TMP_IMAGE_DIR}
296root-fs-type: ${FS_TYPE} 276root-fs-type: ${FS_TYPE}
297root-label: ${DIB_ROOT_LABEL} 277root-label: ${ROOT_LABEL}
298mount-base: ${TMP_BUILD_DIR}/mnt 278mount-base: ${TMP_BUILD_DIR}/mnt
299build-dir: ${TMP_BUILD_DIR} 279build-dir: ${TMP_BUILD_DIR}
300EOF 280EOF
301 281
302dib-block-device init 282dib-block-device init
303 283
284# Need to get the real root label because it can be overwritten
285# by the BLOCK_DEVICE_CONFIG.
286DIB_ROOT_LABEL=$(dib-block-device getval root-label)
287export DIB_ROOT_LABEL
288
289# Need to get the real fs type for the root filesystem
290DIB_ROOT_FSTYPE=$(dib-block-device getval root-fstype)
291export DIB_ROOT_FSTYPE
292
304create_base 293create_base
305# This variable needs to be propagated into the chroot 294# This variable needs to be propagated into the chroot
306mkdir -p $TMP_HOOKS_PATH/environment.d 295mkdir -p $TMP_HOOKS_PATH/environment.d
@@ -377,7 +366,7 @@ fi
377 366
378rm -f ${du_output} 367rm -f ${du_output}
379 368
380if [ "$FS_TYPE" = "ext4" ] ; then 369if [ "$DIB_ROOT_FSTYPE" = "ext4" ] ; then
381 # Very conservative to handle images being resized a lot 370 # Very conservative to handle images being resized a lot
382 # We set journal size to 64M so our journal is large enough when we 371 # We set journal size to 64M so our journal is large enough when we
383 # perform an FS resize. 372 # perform an FS resize.
@@ -403,24 +392,15 @@ export TMP_IMAGE_DIR
403# phase. If this gives no result, use the configuration based approach: 392# phase. If this gives no result, use the configuration based approach:
404eval_run_d block-device "IMAGE_BLOCK_DEVICE=" 393eval_run_d block-device "IMAGE_BLOCK_DEVICE="
405 394
406# Because there is currently no generic way of passing in variables
407# from elements to the main, get here the well known config of a well
408# known element.
409# (This is only temporary and will go away when the complete block
410# device handling including file system handling and mounting is
411# implemented using python.)
412if [[ $IMAGE_ELEMENT =~ vm ]]; then
413 for EPATH in $(echo ${ELEMENTS_PATH} | tr ":" " "); do
414 PART_CFG_PATH=${EPATH}/vm/environment.d/10-partitioning
415 [ -e ${PART_CFG_PATH} ] && source ${PART_CFG_PATH}
416 done
417fi
418
419if [ -z ${IMAGE_BLOCK_DEVICE} ] ; then 395if [ -z ${IMAGE_BLOCK_DEVICE} ] ; then
420 # For compatibily reasons in addition to the YAML configuration 396 # For compatibily reasons in addition to the YAML configuration
421 # there is the need to handle the old environment variables. 397 # there is the need to handle the old environment variables.
422 echo "image-size: ${DIB_IMAGE_SIZE}KiB" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML} 398 echo "image-size: ${DIB_IMAGE_SIZE}KiB" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML}
423 399
400 if [ -n "${MKFS_OPTS}" ] ; then
401 echo "root-fs-opts: '${MKFS_OPTS}'" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML}
402 fi
403
424 # After changeing the parameters, there is the need to 404 # After changeing the parameters, there is the need to
425 # re-run dib-block-device init because some value might 405 # re-run dib-block-device init because some value might
426 # change based on the new set parameters. 406 # change based on the new set parameters.
@@ -431,6 +411,9 @@ if [ -z ${IMAGE_BLOCK_DEVICE} ] ; then
431 411
432 # It's called 'DEVICE' but it's the partition. 412 # It's called 'DEVICE' but it's the partition.
433 IMAGE_BLOCK_DEVICE=$(dib-block-device getval image-block-partition) 413 IMAGE_BLOCK_DEVICE=$(dib-block-device getval image-block-partition)
414
415 # Write the fstab
416 dib-block-device writefstab
434fi 417fi
435export IMAGE_BLOCK_DEVICE 418export IMAGE_BLOCK_DEVICE
436LOOPDEV=${IMAGE_BLOCK_DEVICE} 419LOOPDEV=${IMAGE_BLOCK_DEVICE}
@@ -442,14 +425,6 @@ export IMAGE_BLOCK_DEVICE_WITHOUT_PART
442export EXTRA_DETACH="detach_loopback ${IMAGE_BLOCK_DEVICE_WITHOUT_PART}" 425export EXTRA_DETACH="detach_loopback ${IMAGE_BLOCK_DEVICE_WITHOUT_PART}"
443export EXTRA_UNMOUNT="dib-block-device cleanup" 426export EXTRA_UNMOUNT="dib-block-device cleanup"
444 427
445sudo mkfs -t $FS_TYPE $MKFS_OPTS -L ${DIB_ROOT_LABEL} ${IMAGE_BLOCK_DEVICE}
446# Tuning the rootfs uuid works only for ext filesystems.
447if echo "$FS_TYPE" | grep -q "^ext"; then
448 sudo tune2fs -U ${DIB_IMAGE_ROOT_FS_UUID} ${IMAGE_BLOCK_DEVICE}
449fi
450mkdir $TMP_BUILD_DIR/mnt
451sudo mount ${IMAGE_BLOCK_DEVICE} $TMP_BUILD_DIR/mnt
452
453# 'mv' is not usable here - especially when a top level directory 428# 'mv' is not usable here - especially when a top level directory
454# has the same name as a mount point of a partition. If so, 'mv' 429# has the same name as a mount point of a partition. If so, 'mv'
455# will complain: 430# will complain:
diff --git a/doc/source/user_guide/building_an_image.rst b/doc/source/user_guide/building_an_image.rst
index 383e123..e7c8e5d 100644
--- a/doc/source/user_guide/building_an_image.rst
+++ b/doc/source/user_guide/building_an_image.rst
@@ -83,7 +83,7 @@ The default when using the `vm` element is:
83 83
84 DIB_BLOCK_DEVICE_CONFIG=' 84 DIB_BLOCK_DEVICE_CONFIG='
85 - local_loop: 85 - local_loop:
86 name: image0 86 name: image0
87 87
88 - partitioning: 88 - partitioning:
89 base: image0 89 base: image0
@@ -92,6 +92,12 @@ The default when using the `vm` element is:
92 - name: root 92 - name: root
93 flags: [ boot, primary ] 93 flags: [ boot, primary ]
94 size: 100% 94 size: 100%
95 mkfs:
96 mount:
97 mount_point: /
98 fstab:
99 options: "defaults"
100 fsck-passno: 1'
95 101
96The default when not using the `vm` element is: 102The default when not using the `vm` element is:
97 103
@@ -100,6 +106,13 @@ The default when not using the `vm` element is:
100 DIB_BLOCK_DEVICE_CONFIG=' 106 DIB_BLOCK_DEVICE_CONFIG='
101 - local_loop: 107 - local_loop:
102 name: image0 108 name: image0
109 mkfs:
110 name: mkfs_root
111 mount:
112 mount_point: /
113 fstab:
114 options: "defaults"
115 fsck-passno: 1'
103 116
104There are a lot of different options for the different levels. The 117There are a lot of different options for the different levels. The
105following sections describe each level in detail. 118following sections describe each level in detail.
@@ -162,23 +175,21 @@ Tree and digraph notations can be mixed as needed in a configuration.
162 175
163Limitations 176Limitations
164+++++++++++ 177+++++++++++
165The appropriate functionality to use multiple partitions and even LVMs
166is currently under development; therefore the possible configuration
167is currently limited, but will get more flexible as soon as all the
168functionality is implemented.
169 178
170In future this will be a list of some elements, each describing one 179There are a couple of new modules planned, but not yet implemented,
171part of block device setup - but because currently only `local_loop` 180like LVM, MD, encryption, ...
172and `partitioning` are implemented, it contains only the configuration 181
173of these steps. 182To provide an interface towards the existing elements, there are
183currently three fixed keys used - which are not configurable:
174 184
175Currently it is possible to create multiple local loop devices, but 185* `root-label`: this is the label of the block device that is mounted at
176all but the `image0` will be not useable (are deleted during the 186 `/`.
177build process). 187* `image-block-partition`: if there is a block device with the name
188 `root` this is used else the block device with the name `image0` is
189 used.
190* `image-path`: the path of the image that contains the root file
191 system is taken from the `image0`.
178 192
179Currently only one partitions is used for the image. The name of this
180partition must be `root`. Other partitions are created but not
181used.
182 193
183Level 0 194Level 0
184+++++++ 195+++++++
@@ -213,7 +224,6 @@ Example:
213 224
214.. code-block:: yaml 225.. code-block:: yaml
215 226
216::
217 local_loop: 227 local_loop:
218 name: image0 228 name: image0
219 229
@@ -227,8 +237,6 @@ block devices. One image file called `image0` is created with
227default size in the default temp directory. The second image has the 237default size in the default temp directory. The second image has the
228size of 7.5GiB and is created in the `/var/tmp` folder. 238size of 7.5GiB and is created in the `/var/tmp` folder.
229 239
230Please note that due to current implementation restrictions it is only
231allowed to specify one local loop image.
232 240
233Level 1 241Level 1
234+++++++ 242+++++++
@@ -278,7 +286,7 @@ align
278 Set the alignment of the partition. This must be a multiple of the 286 Set the alignment of the partition. This must be a multiple of the
279 block size (i.e. 512 bytes). The default of 1MiB (~ 2048 * 512 287 block size (i.e. 512 bytes). The default of 1MiB (~ 2048 * 512
280 bytes blocks) is the default for modern systems and known to 288 bytes blocks) is the default for modern systems and known to
281 perform well on a wide range of targets [6]. For each partition 289 perform well on a wide range of targets. For each partition
282 there might be some space that is not used - which is `align` - 512 290 there might be some space that is not used - which is `align` - 512
283 bytes. For the default of 1MiB exactly 1048064 bytes (= 1 MiB - 291 bytes. For the default of 1MiB exactly 1048064 bytes (= 1 MiB -
284 512 byte) are not used in the partition itself. Please note that 292 512 byte) are not used in the partition itself. Please note that
@@ -344,6 +352,130 @@ On the `image0` two partitions are created. The size of the first is
3441GiB, the second uses the remaining free space. On the `data_image` 3521GiB, the second uses the remaining free space. On the `data_image`
345three partitions are created: all are about 1/3 of the disk size. 353three partitions are created: all are about 1/3 of the disk size.
346 354
355
356Level 2
357+++++++
358
359Module: Mkfs
360............
361
362This module creates file systems on the block device given as `base`.
363The following key / value pairs can be given:
364
365base
366 (mandatory) The name of the block device where the filesystem will
367 be created on.
368
369name
370 (mandatory) The name of the partition. This can be used to
371 reference (e.g. mounting) the filesystem.
372
373type
374 (mandatory) The type of the filesystem, like `ext4` or `xfs`.
375
376label
377 (optional - defaults to the name)
378 The label of the filesystem. This can be used e.g. by grub or in
379 the fstab.
380
381opts
382 (optional - defaults to empty list)
383 Options that will passed to the mkfs command.
384
385uuid
386 (optional - no default / not used if not givem)
387 The UUID of the filesystem. Not all file systems might
388 support this. Currently there is support for `ext2`, `ext3`,
389 `ext4` and `xfs`.
390
391Example:
392
393.. code-block:: yaml
394
395 - mkfs:
396 name: mkfs_root
397 base: root
398 type: ext4
399 label: cloudimage-root
400 uuid: b733f302-0336-49c0-85f2-38ca109e8bdb
401 opts: "-i 16384"
402
403
404Level 3
405+++++++
406
407Module: Mount
408.............
409
410This module mounts a filesystem. The options are:
411
412base
413 (mandatory) The name of the filesystem that will be mounted.
414
415name
416 (mandatory) The name of the mount point. This can be used for
417 reference the mount (e.g. creating the fstab).
418
419mount_point
420 (mandatory) The mount point of the filesystem.
421
422There is no need to list the mount points in the correct order: an
423algorithm will automatically detect the mount order.
424
425Example:
426
427.. code-block:: yaml
428
429 - mount:
430 name: root_mnt
431 base: mkfs_root
432 mount_point: /
433
434
435Level 4
436+++++++
437
438Module: fstab
439.............
440
441This module creates fstab entries. The following options exists. For
442details please consult the fstab man page.
443
444base
445 (mandatory) The name of the mount point that will be written to
446 fstab.
447
448name
449 (mandatory) The name of the fstab entry. This can be used later on
450 as reference - and is currently unused.
451
452options
453 (optional, defaults to `default`)
454 Special mount options can be given. This is used as the fourth
455 field in the fstab entry.
456
457dump-freq
458 (optional, defaults to 0 - don't dump)
459 This is passed to dump to determine which filesystem should be
460 dumped. This is used as the fifth field in the fstab entry.
461
462fsck-passno
463 (optional, defaults to 2)
464 Determines the order to run fsck. Please note that this should be
465 set to 1 for the root file system. This is used as the sixth field
466 in the fstab entry.
467
468Example:
469
470.. code-block:: yaml
471
472 - fstab:
473 name: var_log_fstab
474 base: var_log_mnt
475 options: nodev,nosuid
476 dump-freq: 2
477
478
347Filesystem Caveat 479Filesystem Caveat
348----------------- 480-----------------
349 481
@@ -381,3 +513,4 @@ creates ramdisk.
381If tmpfs is not used, you will need enough room in /tmp to store two 513If tmpfs is not used, you will need enough room in /tmp to store two
382uncompressed cloud images. If tmpfs is used, you would still need /tmp space 514uncompressed cloud images. If tmpfs is used, you would still need /tmp space
383for one uncompressed cloud image and about 20% of that image for working files. 515for one uncompressed cloud image and about 20% of that image for working files.
516
diff --git a/releasenotes/notes/block-device-mkfs-mount-fstab-42d7efe28fc2df04.yaml b/releasenotes/notes/block-device-mkfs-mount-fstab-42d7efe28fc2df04.yaml
new file mode 100644
index 0000000..4d8fed0
--- /dev/null
+++ b/releasenotes/notes/block-device-mkfs-mount-fstab-42d7efe28fc2df04.yaml
@@ -0,0 +1,4 @@
1---
2features:
3 - |
4 Adds mkfs, mount and fstab to the block device layer.
diff --git a/setup.cfg b/setup.cfg
index f9daac2..c5e5485 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -59,3 +59,6 @@ console_scripts =
59diskimage_builder.block_device.plugin = 59diskimage_builder.block_device.plugin =
60 local_loop = diskimage_builder.block_device.level0.localloop:LocalLoop 60 local_loop = diskimage_builder.block_device.level0.localloop:LocalLoop
61 partitioning = diskimage_builder.block_device.level1.partitioning:Partitioning 61 partitioning = diskimage_builder.block_device.level1.partitioning:Partitioning
62 mkfs = diskimage_builder.block_device.level2.mkfs:Mkfs
63 mount = diskimage_builder.block_device.level3.mount:Mount
64 fstab = diskimage_builder.block_device.level4.fstab:Fstab