From 601dc0387f712219ef296f5f6eab43adbe0e1702 Mon Sep 17 00:00:00 2001 From: Maksim Malchuk Date: Mon, 6 Mar 2023 13:54:31 +0300 Subject: [PATCH] Add swap support Adds swap as a valid "filesystem" Closes-Bug: #1816136 Change-Id: Ie50834a9834815b1dfacafd283f505f3323d35c8 Co-Authored-By: luke.odom Signed-off-by: Maksim Malchuk --- diskimage_builder/block_device/level2/mkfs.py | 17 ++-- .../block_device/level3/mount.py | 29 ++++--- .../block_device/level4/fstab.py | 9 ++- .../config/lvm_tree_partition_ordering.yaml | 28 +++++-- .../config/multiple_partitions_graph.yaml | 48 +++++++---- .../config/multiple_partitions_tree.yaml | 81 ++++++++++--------- .../block_device/tests/test_mount_order.py | 16 +++- .../notes/swap_support-9ac267f56a0c0424.yaml | 4 + 8 files changed, 151 insertions(+), 81 deletions(-) create mode 100644 releasenotes/notes/swap_support-9ac267f56a0c0424.yaml diff --git a/diskimage_builder/block_device/level2/mkfs.py b/diskimage_builder/block_device/level2/mkfs.py index 1f623406..b7e957b2 100644 --- a/diskimage_builder/block_device/level2/mkfs.py +++ b/diskimage_builder/block_device/level2/mkfs.py @@ -33,7 +33,8 @@ file_system_max_label_length = { "ext3": 16, "ext4": 16, "xfs": 12, - "vfat": 11 + "vfat": 11, + "swap": 16 } @@ -102,18 +103,20 @@ class FilesystemNode(NodeBase): return (edge_from, edge_to) def create(self): - cmd = ["mkfs"] - - cmd.extend(['-t', self.type]) - if self.opts: - cmd.extend(self.opts) + if self.type in ('swap'): + cmd = ["mkswap"] + else: + cmd = ["mkfs"] + cmd.extend(['-t', self.type]) + if self.opts: + cmd.extend(self.opts) if self.type in ('vfat', 'fat'): cmd.extend(["-n", self.label]) else: cmd.extend(["-L", self.label]) - if self.type in ('ext2', 'ext3', 'ext4'): + if self.type in ('ext2', 'ext3', 'ext4', 'swap'): cmd.extend(['-U', self.uuid]) elif self.type == 'xfs': cmd.extend(['-m', "uuid=%s" % self.uuid]) diff --git a/diskimage_builder/block_device/level3/mount.py b/diskimage_builder/block_device/level3/mount.py index 963f12b5..872372a2 100644 --- a/diskimage_builder/block_device/level3/mount.py +++ b/diskimage_builder/block_device/level3/mount.py @@ -72,17 +72,21 @@ class MountPointNode(NodeBase): return (edge_from, edge_to) def create(self): - logger.debug("mount called [%s]", self.mount_point) - rel_mp = self.mount_point if self.mount_point[0] != '/' \ - else self.mount_point[1:] - mount_point = os.path.join(self.mount_base, rel_mp) - if not os.path.exists(mount_point): - # Need to sudo this because of permissions in the new - # file system tree. - exec_sudo(['mkdir', '-p', mount_point]) - logger.info("Mounting [%s] to [%s]", self.name, mount_point) - exec_sudo(["mount", self.state['filesys'][self.base]['device'], - mount_point]) + if (self.state['filesys'][self.base]['fstype'] == 'swap'): + # No need to mount/activate swap during image build. + mount_point = self.mount_point = 'none' + else: + logger.debug("mount called [%s]", self.mount_point) + rel_mp = self.mount_point if self.mount_point[0] != '/' \ + else self.mount_point[1:] + mount_point = os.path.join(self.mount_base, rel_mp) + if not os.path.exists(mount_point): + # Need to sudo this because of permissions in the new + # file system tree. + exec_sudo(['mkdir', '-p', mount_point]) + logger.info("Mounting [%s] to [%s]", self.name, mount_point) + exec_sudo(["mount", self.state['filesys'][self.base]['device'], + mount_point]) if 'mount' not in self.state: self.state['mount'] = {} @@ -94,6 +98,9 @@ class MountPointNode(NodeBase): self.state['mount_order'].append(self.mount_point) def umount(self): + if (self.state['filesys'][self.base]['fstype'] == 'swap'): + # Swap not mounted/activated during image build. + return logger.info("Called for [%s]", self.name) # Before calling umount, call 'fstrim' on suitable mounted # file systems. This discards unused blocks from the mounted diff --git a/diskimage_builder/block_device/level4/fstab.py b/diskimage_builder/block_device/level4/fstab.py index 38f614da..cda8264f 100644 --- a/diskimage_builder/block_device/level4/fstab.py +++ b/diskimage_builder/block_device/level4/fstab.py @@ -40,12 +40,15 @@ class FstabNode(NodeBase): if 'fstab' not in self.state: self.state['fstab'] = {} + swap = 'none' in self.state['mount'] and \ + self.state['mount']['none']['name'] == self.base + self.state['fstab'][self.base] = { 'name': self.name, 'base': self.base, - 'options': self.options, - 'dump-freq': self.dump_freq, - 'fsck-passno': self.fsck_passno + 'options': 'sw' if swap else self.options, + 'dump-freq': 0 if swap else self.dump_freq, + 'fsck-passno': 0 if swap else self.fsck_passno } diff --git a/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml b/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml index 06526b8a..e28da146 100644 --- a/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml +++ b/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml @@ -7,10 +7,10 @@ label: mbr partitions: - name: boot - flags: [ boot,primary ] + flags: [boot, primary] size: 1G - name: root - flags: [ primary ] + flags: [primary] size: 3G - lvm: @@ -27,12 +27,16 @@ lvs: - name: lv_root base: vg - size: 2000M + size: 1900M - name: lv_var base: vg size: 500M + - name: lv_swap + base: vg + size: 100M + - mkfs: base: boot type: ext3 @@ -50,8 +54,8 @@ mount: mount_point: / fstab: - options: "noacl,errors=remount-ro" - fsck-passno: 1 + options: "noacl,errors=remount-ro" + fsck-passno: 1 - mkfs: name: mkfs_var @@ -60,5 +64,15 @@ mount: mount_point: /var fstab: - options: "noacl" - fsck-passno: 2 + options: "noacl" + fsck-passno: 2 + +- mkfs: + name: mkfs_swap + base: lv_swap + type: "swap" + mount: + mount_point: none + fstab: + options: "sw" + fsck-passno: 0 diff --git a/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml b/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml index fe262a2b..1822a382 100644 --- a/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml +++ b/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml @@ -2,20 +2,23 @@ name: image0 - partitioning: - base: image0 - name: mbr - label: mbr - partitions: - - name: root - base: image0 - flags: [ boot, primary ] - size: 55% - - name: var - base: image0 - size: 40% - - name: var_log - base: image0 - size: 5% + base: image0 + name: mbr + label: mbr + partitions: + - name: root + base: image0 + flags: [boot, primary] + size: 54% + - name: var + base: image0 + size: 40% + - name: var_log + base: image0 + size: 5% + - name: swap + base: image0 + size: 1% - mkfs: base: root @@ -67,3 +70,20 @@ name: fstab_mount_mkfs_var_log fsck-passno: 1 options: defaults + +- mkfs: + base: swap + name: mkfs_swap + type: swap + uuid: swap-uuid-1234 + +- mount: + base: mkfs_swap + name: mount_mkfs_swap + mount_point: none + +- fstab: + base: mount_mkfs_swap + name: fstab_mount_mkfs_swap + fsck-passno: 0 + options: sw diff --git a/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml b/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml index d60d5a8e..39fccd60 100644 --- a/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml +++ b/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml @@ -2,39 +2,48 @@ name: image0 - partitioning: - base: image0 - name: mbr - label: mbr - partitions: - - name: root - flags: [ boot, primary ] - size: 55% - mkfs: - type: xfs - uuid: root-uuid-1234 - mount: - mount_point: / - fstab: - options: "defaults" - fsck-passno: 1 - - name: var - size: 40% - mkfs: - type: xfs - uuid: var-uuid-1234 - mount: - mount_point: /var - fstab: - options: "defaults" - fsck-passno: 1 - - name: var_log - size: 5% - mkfs: - type: vfat - label: varlog - mount: - mount_point: /var/log - fstab: - options: "defaults" - fsck-passno: 1 - + base: image0 + name: mbr + label: mbr + partitions: + - name: root + flags: [boot, primary] + size: 54% + mkfs: + type: xfs + uuid: root-uuid-1234 + mount: + mount_point: / + fstab: + options: "defaults" + fsck-passno: 1 + - name: var + size: 40% + mkfs: + type: xfs + uuid: var-uuid-1234 + mount: + mount_point: /var + fstab: + options: "defaults" + fsck-passno: 1 + - name: var_log + size: 5% + mkfs: + type: vfat + label: varlog + mount: + mount_point: /var/log + fstab: + options: "defaults" + fsck-passno: 1 + - name: swap + size: 1% + mkfs: + type: swap + uuid: swap-uuid-1234 + mount: + mount_point: none + fstab: + fsck-passno: 0 + options: "sw" diff --git a/diskimage_builder/block_device/tests/test_mount_order.py b/diskimage_builder/block_device/tests/test_mount_order.py index 097ae7d4..06d34e48 100644 --- a/diskimage_builder/block_device/tests/test_mount_order.py +++ b/diskimage_builder/block_device/tests/test_mount_order.py @@ -80,6 +80,7 @@ class TestMountOrder(tc.TestGraphGeneration): state['blockdev']['root'] = {'device': '/dev/loopXp1/root'} state['blockdev']['var'] = {'device': '/dev/loopXp2/var'} state['blockdev']['var_log'] = {'device': '/dev/loopXp3/var_log'} + state['blockdev']['swap'] = {'device': '/dev/loopXp4/swap'} for node in call_order: if isinstance(node, (FilesystemNode, MountPointNode)): @@ -89,7 +90,8 @@ class TestMountOrder(tc.TestGraphGeneration): node.umount() # ensure that partitions were mounted in order root->var->var/log - self.assertListEqual(state['mount_order'], ['/', '/var', '/var/log']) + self.assertListEqual(state['mount_order'], + ['/', '/var', '/var/log', 'none']) # fs creation sequence (note we don't care about order of this # as they're all independent) @@ -101,7 +103,9 @@ class TestMountOrder(tc.TestGraphGeneration): '-m', 'uuid=var-uuid-1234', '-q', '/dev/loopXp2/var']), mock.call(['mkfs', '-t', 'vfat', '-n', 'VARLOG', - '/dev/loopXp3/var_log']) + '/dev/loopXp3/var_log']), + mock.call(['mkswap', '-L', 'mkfs_swap', '-U', 'swap-uuid-1234', + '/dev/loopXp4/swap']) ] self.assertEqual(mock_exec_sudo_mkfs.call_count, len(cmd_sequence)) mock_exec_sudo_mkfs.assert_has_calls(cmd_sequence, any_order=True) @@ -154,6 +158,10 @@ class TestMountOrder(tc.TestGraphGeneration): 'device': '/dev/loopXp3', 'fstype': 'vfat', }, + 'mkfs_swap': { + 'device': '/dev/loopXp4', + 'fstype': 'swap', + }, } for node in call_order: @@ -164,7 +172,9 @@ class TestMountOrder(tc.TestGraphGeneration): node.umount() # ensure that partitions are mounted in order / -> /boot -> /var - self.assertListEqual(state['mount_order'], ['/', '/boot', '/var']) + # swap not mounted in runtime, but should be in 'mount_order' list + self.assertListEqual(state['mount_order'], + ['/', '/boot', '/var', 'none']) cmd_sequence = [ # mount sequence diff --git a/releasenotes/notes/swap_support-9ac267f56a0c0424.yaml b/releasenotes/notes/swap_support-9ac267f56a0c0424.yaml new file mode 100644 index 00000000..56df0c20 --- /dev/null +++ b/releasenotes/notes/swap_support-9ac267f56a0c0424.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Adds swap as a valid "filesystem" for block devices