From 18b8c963ab7903bc36a96e09a9c0ae6aaae6b021 Mon Sep 17 00:00:00 2001 From: Franziska Kunsmann Date: Fri, 14 Feb 2025 19:32:13 +0100 Subject: [PATCH] bundles/backup-server: support raid0-ing multiple raidz --- bundles/backup-server/metadata.py | 63 ++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/bundles/backup-server/metadata.py b/bundles/backup-server/metadata.py index 3d78ed6..4be6390 100644 --- a/bundles/backup-server/metadata.py +++ b/bundles/backup-server/metadata.py @@ -1,3 +1,5 @@ +from bundlewrap.exceptions import BundleError + defaults = { 'backup-server': { 'my_ssh_port': 22, @@ -69,25 +71,51 @@ def zfs_pool(metadata): return {} crypt_devices = {} - pool_devices = set() unlock_actions = set() - for number, (device, passphrase) in enumerate(sorted(metadata.get('backup-server/encrypted-devices', {}).items())): - crypt_devices[device] = { - 'dm-name': f'backup{number}', - 'passphrase': passphrase, - } - pool_devices.add(f'/dev/mapper/backup{number}') - unlock_actions.add(f'action:dm-crypt_open_backup{number}') + devices = metadata.get('backup-server/encrypted-devices') - pool_opts = { - 'devices': pool_devices, - } + # TODO remove this once we have migrated all systems + if isinstance(devices, dict): + pool_devices = set() - if len(pool_devices) > 2: - pool_opts['type'] = 'raidz' - elif len(pool_devices) > 1: - pool_opts['type'] = 'mirror' + for number, (device, passphrase) in enumerate(sorted(devices.items())): + crypt_devices[device] = { + 'dm-name': f'backup{number}', + 'passphrase': passphrase, + } + pool_devices.add(f'/dev/mapper/backup{number}') + unlock_actions.add(f'action:dm-crypt_open_backup{number}') + + pool_config = [{ + 'devices': pool_devices, + }] + + if len(pool_devices) > 2: + pool_config[0]['type'] = 'raidz' + elif len(pool_devices) > 1: + pool_config[0]['type'] = 'mirror' + + elif isinstance(devices, list): + pool_config = [] + + for idx, intended_pool in enumerate(devices): + pool_devices = set() + + for number, (device, passphrase) in enumerate(sorted(intended_pool.items())): + crypt_devices[device] = { + 'dm-name': f'backup{idx}-{number}', + 'passphrase': passphrase, + } + pool_devices.add(f'/dev/mapper/backup{idx}-{number}') + unlock_actions.add(f'action:dm-crypt_open_backup{idx}-{number}') + + pool_config.append({ + 'devices': pool_devices, + 'type': 'raidz', + }) + else: + raise BundleError(f'{node.name}: unsupported configuration for backup-server/encrypted-devices') return { 'backup-server': { @@ -100,9 +128,8 @@ def zfs_pool(metadata): 'pools': { 'backups': { 'when_creating': { - 'config': [ - pool_opts, - ], + 'config': pool_config, + **metadata.get('backup-server/zpool_create_options', {}), }, 'needs': unlock_actions, # That's a bit hacky. We do it this way to auto-import