From: Or Ozeri Date: Sun, 10 Jul 2022 10:54:56 +0000 (+0300) Subject: qa/tasks/qemu: use formatted clones on encrypted disks X-Git-Tag: v18.1.0~960^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3b2908b6fbb13a48824f8e01d314ff3e13ce06f7;p=ceph.git qa/tasks/qemu: use formatted clones on encrypted disks This commit changes the format for encrypted disks to have the child image and the parent image encrypted with different keys. This to allow testing of the new formatted clones feature in librbd/crypto. Signed-off-by: Or Ozeri --- diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1.yaml index 7f3f3776f2a6..cb3659f97517 100644 --- a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1.yaml +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1.yaml @@ -6,7 +6,7 @@ tasks: - qemu: all: clone: true - encryption_format: luks1 + parent_encryption_format: luks1 type: block disks: 3 test: qa/run_xfstests_qemu.sh diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1_luks1.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1_luks1.yaml new file mode 100644 index 000000000000..1db50d600a60 --- /dev/null +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1_luks1.yaml @@ -0,0 +1,14 @@ +overrides: + install: + ceph: + extra_packages: [rbd-nbd] +tasks: +- qemu: + all: + clone: true + parent_encryption_format: luks1 + encryption_format: luks1 + type: block + disks: 3 + test: qa/run_xfstests_qemu.sh +exclude_arch: armv7l diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1_luks2.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1_luks2.yaml new file mode 100644 index 000000000000..a8ef5f2dde62 --- /dev/null +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks1_luks2.yaml @@ -0,0 +1,14 @@ +overrides: + install: + ceph: + extra_packages: [rbd-nbd] +tasks: +- qemu: + all: + clone: true + parent_encryption_format: luks1 + encryption_format: luks2 + type: block + disks: 3 + test: qa/run_xfstests_qemu.sh +exclude_arch: armv7l diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2.yaml index c9d9829a99f7..203372d60e45 100644 --- a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2.yaml +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2.yaml @@ -6,7 +6,7 @@ tasks: - qemu: all: clone: true - encryption_format: luks2 + parent_encryption_format: luks2 type: block disks: 3 test: qa/run_xfstests_qemu.sh diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2_luks1.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2_luks1.yaml new file mode 100644 index 000000000000..727e5c32a05f --- /dev/null +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2_luks1.yaml @@ -0,0 +1,14 @@ +overrides: + install: + ceph: + extra_packages: [rbd-nbd] +tasks: +- qemu: + all: + clone: true + parent_encryption_format: luks2 + encryption_format: luks1 + type: block + disks: 3 + test: qa/run_xfstests_qemu.sh +exclude_arch: armv7l diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2_luks2.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2_luks2.yaml new file mode 100644 index 000000000000..43ded129fc18 --- /dev/null +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_luks2_luks2.yaml @@ -0,0 +1,14 @@ +overrides: + install: + ceph: + extra_packages: [rbd-nbd] +tasks: +- qemu: + all: + clone: true + parent_encryption_format: luks2 + encryption_format: luks2 + type: block + disks: 3 + test: qa/run_xfstests_qemu.sh +exclude_arch: armv7l diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_none_luks1.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_none_luks1.yaml new file mode 100644 index 000000000000..7f3f3776f2a6 --- /dev/null +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_none_luks1.yaml @@ -0,0 +1,13 @@ +overrides: + install: + ceph: + extra_packages: [rbd-nbd] +tasks: +- qemu: + all: + clone: true + encryption_format: luks1 + type: block + disks: 3 + test: qa/run_xfstests_qemu.sh +exclude_arch: armv7l diff --git a/qa/suites/rbd/encryption/workloads/qemu_xfstests_none_luks2.yaml b/qa/suites/rbd/encryption/workloads/qemu_xfstests_none_luks2.yaml new file mode 100644 index 000000000000..c9d9829a99f7 --- /dev/null +++ b/qa/suites/rbd/encryption/workloads/qemu_xfstests_none_luks2.yaml @@ -0,0 +1,13 @@ +overrides: + install: + ceph: + extra_packages: [rbd-nbd] +tasks: +- qemu: + all: + clone: true + encryption_format: luks2 + type: block + disks: 3 + test: qa/run_xfstests_qemu.sh +exclude_arch: armv7l diff --git a/qa/tasks/qemu.py b/qa/tasks/qemu.py index 3fe8049b72f0..ae02983eeb6a 100644 --- a/qa/tasks/qemu.py +++ b/qa/tasks/qemu.py @@ -32,6 +32,8 @@ def normalize_disks(config): image_url = client_config.get('image_url', DEFAULT_IMAGE_URL) device_type = client_config.get('type', 'filesystem') encryption_format = client_config.get('encryption_format', 'none') + parent_encryption_format = client_config.get( + 'parent_encryption_format', 'none') disks = client_config.get('disks', DEFAULT_NUM_DISKS) if not isinstance(disks, list): @@ -59,7 +61,10 @@ def normalize_disks(config): disk['device_letter'] = chr(ord('a') + i) if 'encryption_format' not in disk: - disk['encryption_format'] = encryption_format + if clone: + disk['encryption_format'] = parent_encryption_format + else: + disk['encryption_format'] = encryption_format assert disk['encryption_format'] in ['none', 'luks1', 'luks2'], 'invalid encryption format' assert disks, 'at least one rbd device must be used' @@ -73,6 +78,13 @@ def normalize_disks(config): clone['parent_name'] = clone['image_name'] clone['image_name'] += '-clone' del disk['device_letter'] + + clone['encryption_format'] = encryption_format + assert clone['encryption_format'] in ['none', 'luks1', 'luks2'], 'invalid encryption format' + + clone['parent_encryption_format'] = parent_encryption_format + assert clone['parent_encryption_format'] in ['none', 'luks1', 'luks2'], 'invalid encryption format' + disks.append(clone) def create_images(ctx, config, managers): @@ -109,7 +121,8 @@ def create_clones(ctx, config, managers): create_config = { client: { 'image_name': disk['image_name'], - 'parent_name': disk['parent_name'] + 'parent_name': disk['parent_name'], + 'encryption_format': disk['encryption_format'], } } managers.append( @@ -121,7 +134,8 @@ def create_encrypted_devices(ctx, config, managers): for client, client_config in config.items(): disks = client_config['disks'] for disk in disks: - if disk['encryption_format'] == 'none' or \ + if (disk['encryption_format'] == 'none' and + disk.get('parent_encryption_format', 'none') == 'none') or \ 'device_letter' not in disk: continue @@ -223,7 +237,8 @@ def generate_iso(ctx, config): 'device_letter' not in disk or \ 'image_url' in disk: continue - if disk['encryption_format'] == 'none': + if disk['encryption_format'] == 'none' and \ + disk.get('parent_encryption_format', 'none') == 'none': dev_name = 'vd' + disk['device_letter'] else: # encrypted disks use if=ide interface, instead of if=virtio @@ -519,7 +534,8 @@ def run_qemu(ctx, config): if 'device_letter' not in disk: continue - if disk['encryption_format'] == 'none': + if disk['encryption_format'] == 'none' and \ + disk.get('parent_encryption_format', 'none') == 'none': interface = 'virtio' disk_spec = 'rbd:rbd/{img}:id={id}'.format( img=disk['image_name'], diff --git a/qa/tasks/rbd.py b/qa/tasks/rbd.py index 6b9786f220ae..b0ffaba83861 100644 --- a/qa/tasks/rbd.py +++ b/qa/tasks/rbd.py @@ -23,6 +23,7 @@ os.environ["RBD_FORCE_ALLOW_V1"] = "1" log = logging.getLogger(__name__) ENCRYPTION_PASSPHRASE = "password" +CLONE_ENCRYPTION_PASSPHRASE = "password2" @contextlib.contextmanager def create_image(ctx, config): @@ -142,6 +143,7 @@ def clone_image(ctx, config): client.0: parent_name: testimage image_name: cloneimage + encryption_format: luks2 """ assert isinstance(config, dict) or isinstance(config, list), \ "task clone_image only supports a list or dictionary for configuration" @@ -152,6 +154,7 @@ def clone_image(ctx, config): images = [(role, None) for role in config] testdir = teuthology.get_testdir(ctx) + clone_passphrase_file = '{tdir}/clone-passphrase'.format(tdir=testdir) for role, properties in images: if properties is None: properties = {} @@ -165,9 +168,29 @@ def clone_image(ctx, config): (remote,) = ctx.cluster.only(role).remotes.keys() log.info('Clone image {parent} to {child}'.format(parent=parent_name, child=name)) - for cmd in [('snap', 'create', parent_spec), + + commands = [('snap', 'create', parent_spec), ('snap', 'protect', parent_spec), - ('clone', parent_spec, name)]: + ('clone', parent_spec, name) + ] + + encryption_format = properties.get('encryption_format', 'none') + if encryption_format != 'none': + remote.run( + args=[ + 'echo', + CLONE_ENCRYPTION_PASSPHRASE, + run.Raw('>'), + clone_passphrase_file + ] + ) + + commands.append( + ('encryption', 'format', name, encryption_format, + clone_passphrase_file) + ) + + for cmd in commands: args = [ 'adjust-ulimits', 'ceph-coverage', @@ -181,6 +204,7 @@ def clone_image(ctx, config): yield finally: log.info('Deleting rbd clones...') + remote.run(args=['rm', '-f', clone_passphrase_file]) for role, properties in images: if properties is None: properties = {} @@ -260,6 +284,7 @@ def dev_create(ctx, config): client.0: image_name: testimage.client.0 encryption_format: luks2 + parent_encryption_format: luks1 """ assert isinstance(config, dict) or isinstance(config, list), \ "task dev_create only supports a list or dictionary for configuration" @@ -273,31 +298,64 @@ def dev_create(ctx, config): testdir = teuthology.get_testdir(ctx) passphrase_file = '{tdir}/passphrase'.format(tdir=testdir) + clone_passphrase_file = '{tdir}/clone-passphrase'.format(tdir=testdir) device_path = {} for role, properties in images: if properties is None: properties = {} name = properties.get('image_name', default_image_name(role)) - encryption_format = properties.get('encryption_format', 'none') + parent_encryption_format = properties.get('parent_encryption_format', + 'none') + encryption_format = properties.get('encryption_format', + parent_encryption_format) (remote,) = ctx.cluster.only(role).remotes.keys() - if encryption_format == 'none': + if encryption_format == 'none' and parent_encryption_format == 'none': device_path[role] = '/dev/rbd/rbd/{image}'.format(image=name) device_specific_args = [] else: - remote.run( - args=[ - 'echo', - ENCRYPTION_PASSPHRASE, - run.Raw('>'), - passphrase_file - ] - ) - device_specific_args = [ - '-t', 'nbd', '-o', - 'encryption-format=%s,encryption-passphrase-file=%s' % ( - encryption_format, passphrase_file)] + device_specific_args = ['-t', 'nbd', '-o'] + + is_cloned = properties.get('parent_name') is not None + encryption_args = "" + if is_cloned and properties.get('encryption_format') != 'none': + remote.run( + args=[ + 'echo', + CLONE_ENCRYPTION_PASSPHRASE, + run.Raw('>'), + clone_passphrase_file + ] + ) + + encryption_args = \ + 'encryption-format=%s,encryption-passphrase-file=%s' % ( + encryption_format, clone_passphrase_file) + + if not is_cloned or parent_encryption_format != 'none': + remote.run( + args=[ + 'echo', + ENCRYPTION_PASSPHRASE, + run.Raw('>'), + passphrase_file + ] + ) + + if is_cloned and properties.get('encryption_format') != 'none': + encryption_args += "," + + if parent_encryption_format != 'none': + encryption_args += \ + 'encryption-format=%s,encryption-passphrase-file=%s' % ( + parent_encryption_format, passphrase_file) + else: + encryption_args += \ + 'encryption-format=%s,encryption-passphrase-file=%s' % ( + encryption_format, passphrase_file) + + device_specific_args.append(encryption_args) map_fp = StringIO() remote.run( @@ -314,7 +372,7 @@ def dev_create(ctx, config): stdout=map_fp, ) - if encryption_format != 'none': + if encryption_format != 'none' or parent_encryption_format != 'none': device_path[role] = map_fp.getvalue().rstrip() properties['device_path'] = device_path[role] remote.run(args=['sudo', 'chmod', '666', device_path[role]]) @@ -322,7 +380,7 @@ def dev_create(ctx, config): yield finally: log.info('Unmapping rbd devices...') - remote.run(args=['rm', '-f', passphrase_file]) + remote.run(args=['rm', '-f', passphrase_file, clone_passphrase_file]) for role, properties in images: if not device_path.get(role): continue @@ -330,9 +388,12 @@ def dev_create(ctx, config): if properties is None: properties = {} encryption_format = properties.get('encryption_format', 'none') + parent_encryption_format = properties.get( + 'parent_encryption_format', 'none') (remote,) = ctx.cluster.only(role).remotes.keys() - if encryption_format == 'none': + if encryption_format == 'none' and \ + parent_encryption_format == 'none': device_specific_args = [] else: device_specific_args = ['-t', 'nbd']