Add swap support

Adds swap as a valid "filesystem"

Closes-Bug: #1816136
Change-Id: Ie50834a9834815b1dfacafd283f505f3323d35c8
Co-Authored-By: luke.odom <luke.odom@dreamhost.com>
Signed-off-by: Maksim Malchuk <maksim.malchuk@gmail.com>
This commit is contained in:
Maksim Malchuk 2023-03-06 13:54:31 +03:00
parent 174089a6a5
commit 601dc0387f
8 changed files with 151 additions and 81 deletions

View File

@ -33,7 +33,8 @@ file_system_max_label_length = {
"ext3": 16, "ext3": 16,
"ext4": 16, "ext4": 16,
"xfs": 12, "xfs": 12,
"vfat": 11 "vfat": 11,
"swap": 16
} }
@ -102,18 +103,20 @@ class FilesystemNode(NodeBase):
return (edge_from, edge_to) return (edge_from, edge_to)
def create(self): def create(self):
cmd = ["mkfs"] if self.type in ('swap'):
cmd = ["mkswap"]
cmd.extend(['-t', self.type]) else:
if self.opts: cmd = ["mkfs"]
cmd.extend(self.opts) cmd.extend(['-t', self.type])
if self.opts:
cmd.extend(self.opts)
if self.type in ('vfat', 'fat'): if self.type in ('vfat', 'fat'):
cmd.extend(["-n", self.label]) cmd.extend(["-n", self.label])
else: else:
cmd.extend(["-L", self.label]) 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]) cmd.extend(['-U', self.uuid])
elif self.type == 'xfs': elif self.type == 'xfs':
cmd.extend(['-m', "uuid=%s" % self.uuid]) cmd.extend(['-m', "uuid=%s" % self.uuid])

View File

@ -72,17 +72,21 @@ class MountPointNode(NodeBase):
return (edge_from, edge_to) return (edge_from, edge_to)
def create(self): def create(self):
logger.debug("mount called [%s]", self.mount_point) if (self.state['filesys'][self.base]['fstype'] == 'swap'):
rel_mp = self.mount_point if self.mount_point[0] != '/' \ # No need to mount/activate swap during image build.
else self.mount_point[1:] mount_point = self.mount_point = 'none'
mount_point = os.path.join(self.mount_base, rel_mp) else:
if not os.path.exists(mount_point): logger.debug("mount called [%s]", self.mount_point)
# Need to sudo this because of permissions in the new rel_mp = self.mount_point if self.mount_point[0] != '/' \
# file system tree. else self.mount_point[1:]
exec_sudo(['mkdir', '-p', mount_point]) mount_point = os.path.join(self.mount_base, rel_mp)
logger.info("Mounting [%s] to [%s]", self.name, mount_point) if not os.path.exists(mount_point):
exec_sudo(["mount", self.state['filesys'][self.base]['device'], # Need to sudo this because of permissions in the new
mount_point]) # 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: if 'mount' not in self.state:
self.state['mount'] = {} self.state['mount'] = {}
@ -94,6 +98,9 @@ class MountPointNode(NodeBase):
self.state['mount_order'].append(self.mount_point) self.state['mount_order'].append(self.mount_point)
def umount(self): 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) logger.info("Called for [%s]", self.name)
# Before calling umount, call 'fstrim' on suitable mounted # Before calling umount, call 'fstrim' on suitable mounted
# file systems. This discards unused blocks from the mounted # file systems. This discards unused blocks from the mounted

View File

@ -40,12 +40,15 @@ class FstabNode(NodeBase):
if 'fstab' not in self.state: if 'fstab' not in self.state:
self.state['fstab'] = {} self.state['fstab'] = {}
swap = 'none' in self.state['mount'] and \
self.state['mount']['none']['name'] == self.base
self.state['fstab'][self.base] = { self.state['fstab'][self.base] = {
'name': self.name, 'name': self.name,
'base': self.base, 'base': self.base,
'options': self.options, 'options': 'sw' if swap else self.options,
'dump-freq': self.dump_freq, 'dump-freq': 0 if swap else self.dump_freq,
'fsck-passno': self.fsck_passno 'fsck-passno': 0 if swap else self.fsck_passno
} }

View File

@ -7,10 +7,10 @@
label: mbr label: mbr
partitions: partitions:
- name: boot - name: boot
flags: [ boot,primary ] flags: [boot, primary]
size: 1G size: 1G
- name: root - name: root
flags: [ primary ] flags: [primary]
size: 3G size: 3G
- lvm: - lvm:
@ -27,12 +27,16 @@
lvs: lvs:
- name: lv_root - name: lv_root
base: vg base: vg
size: 2000M size: 1900M
- name: lv_var - name: lv_var
base: vg base: vg
size: 500M size: 500M
- name: lv_swap
base: vg
size: 100M
- mkfs: - mkfs:
base: boot base: boot
type: ext3 type: ext3
@ -50,8 +54,8 @@
mount: mount:
mount_point: / mount_point: /
fstab: fstab:
options: "noacl,errors=remount-ro" options: "noacl,errors=remount-ro"
fsck-passno: 1 fsck-passno: 1
- mkfs: - mkfs:
name: mkfs_var name: mkfs_var
@ -60,5 +64,15 @@
mount: mount:
mount_point: /var mount_point: /var
fstab: fstab:
options: "noacl" options: "noacl"
fsck-passno: 2 fsck-passno: 2
- mkfs:
name: mkfs_swap
base: lv_swap
type: "swap"
mount:
mount_point: none
fstab:
options: "sw"
fsck-passno: 0

View File

@ -2,20 +2,23 @@
name: image0 name: image0
- partitioning: - partitioning:
base: image0 base: image0
name: mbr name: mbr
label: mbr label: mbr
partitions: partitions:
- name: root - name: root
base: image0 base: image0
flags: [ boot, primary ] flags: [boot, primary]
size: 55% size: 54%
- name: var - name: var
base: image0 base: image0
size: 40% size: 40%
- name: var_log - name: var_log
base: image0 base: image0
size: 5% size: 5%
- name: swap
base: image0
size: 1%
- mkfs: - mkfs:
base: root base: root
@ -67,3 +70,20 @@
name: fstab_mount_mkfs_var_log name: fstab_mount_mkfs_var_log
fsck-passno: 1 fsck-passno: 1
options: defaults 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

View File

@ -2,39 +2,48 @@
name: image0 name: image0
- partitioning: - partitioning:
base: image0 base: image0
name: mbr name: mbr
label: mbr label: mbr
partitions: partitions:
- name: root - name: root
flags: [ boot, primary ] flags: [boot, primary]
size: 55% size: 54%
mkfs: mkfs:
type: xfs type: xfs
uuid: root-uuid-1234 uuid: root-uuid-1234
mount: mount:
mount_point: / mount_point: /
fstab: fstab:
options: "defaults" options: "defaults"
fsck-passno: 1 fsck-passno: 1
- name: var - name: var
size: 40% size: 40%
mkfs: mkfs:
type: xfs type: xfs
uuid: var-uuid-1234 uuid: var-uuid-1234
mount: mount:
mount_point: /var mount_point: /var
fstab: fstab:
options: "defaults" options: "defaults"
fsck-passno: 1 fsck-passno: 1
- name: var_log - name: var_log
size: 5% size: 5%
mkfs: mkfs:
type: vfat type: vfat
label: varlog label: varlog
mount: mount:
mount_point: /var/log mount_point: /var/log
fstab: fstab:
options: "defaults" options: "defaults"
fsck-passno: 1 fsck-passno: 1
- name: swap
size: 1%
mkfs:
type: swap
uuid: swap-uuid-1234
mount:
mount_point: none
fstab:
fsck-passno: 0
options: "sw"

View File

@ -80,6 +80,7 @@ class TestMountOrder(tc.TestGraphGeneration):
state['blockdev']['root'] = {'device': '/dev/loopXp1/root'} state['blockdev']['root'] = {'device': '/dev/loopXp1/root'}
state['blockdev']['var'] = {'device': '/dev/loopXp2/var'} state['blockdev']['var'] = {'device': '/dev/loopXp2/var'}
state['blockdev']['var_log'] = {'device': '/dev/loopXp3/var_log'} state['blockdev']['var_log'] = {'device': '/dev/loopXp3/var_log'}
state['blockdev']['swap'] = {'device': '/dev/loopXp4/swap'}
for node in call_order: for node in call_order:
if isinstance(node, (FilesystemNode, MountPointNode)): if isinstance(node, (FilesystemNode, MountPointNode)):
@ -89,7 +90,8 @@ class TestMountOrder(tc.TestGraphGeneration):
node.umount() node.umount()
# ensure that partitions were mounted in order root->var->var/log # 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 # fs creation sequence (note we don't care about order of this
# as they're all independent) # as they're all independent)
@ -101,7 +103,9 @@ class TestMountOrder(tc.TestGraphGeneration):
'-m', 'uuid=var-uuid-1234', '-m', 'uuid=var-uuid-1234',
'-q', '/dev/loopXp2/var']), '-q', '/dev/loopXp2/var']),
mock.call(['mkfs', '-t', 'vfat', '-n', 'VARLOG', 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)) self.assertEqual(mock_exec_sudo_mkfs.call_count, len(cmd_sequence))
mock_exec_sudo_mkfs.assert_has_calls(cmd_sequence, any_order=True) mock_exec_sudo_mkfs.assert_has_calls(cmd_sequence, any_order=True)
@ -154,6 +158,10 @@ class TestMountOrder(tc.TestGraphGeneration):
'device': '/dev/loopXp3', 'device': '/dev/loopXp3',
'fstype': 'vfat', 'fstype': 'vfat',
}, },
'mkfs_swap': {
'device': '/dev/loopXp4',
'fstype': 'swap',
},
} }
for node in call_order: for node in call_order:
@ -164,7 +172,9 @@ class TestMountOrder(tc.TestGraphGeneration):
node.umount() node.umount()
# ensure that partitions are mounted in order / -> /boot -> /var # 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 = [ cmd_sequence = [
# mount sequence # mount sequence

View File

@ -0,0 +1,4 @@
---
features:
- |
Adds swap as a valid "filesystem" for block devices