]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
suites/rbd/qemu: excercise CoW support during QEMU testing
authorJason Dillaman <dillaman@redhat.com>
Wed, 21 Oct 2015 20:27:08 +0000 (16:27 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 22 Oct 2015 12:29:58 +0000 (08:29 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 59e768bb29960b4ca411a71342ef982bb2499354)

suites/rbd/qemu/workloads/qemu_bonnie.yaml
suites/rbd/qemu/workloads/qemu_fsstress.yaml
suites/rbd/qemu/workloads/qemu_xfstests.yaml
tasks/qemu.py
tasks/rbd.py

index 7c964265a0b84c7c8835bf8c900335e8560ec591..3e523d61b776b26cd47251bc737140be16f15dbc 100644 (file)
@@ -1,5 +1,6 @@
 tasks:
 - qemu:
     all:
+      clone: true
       test: http://git.ceph.com/?p=ceph.git;a=blob_plain;f=qa/workunits/suites/bonnie.sh
 exclude_arch: armv7l
index 5847653c407ca588c54530135380c01345ec280d..040dc5567b772646957f5802e995d5a54e750a70 100644 (file)
@@ -1,5 +1,6 @@
 tasks:
 - qemu:
     all:
+      clone: true
       test: http://git.ceph.com/?p=ceph.git;a=blob_plain;f=qa/workunits/suites/fsstress.sh
 exclude_arch: armv7l
index c4b2327cc8e33238827e157435e0779152c57aad..b6112d1bb2715ad09b7f97911b9e533301866bcb 100644 (file)
@@ -1,6 +1,7 @@
 tasks:
 - qemu:
     all:
+      clone: true
       type: block
       num_rbd: 2
       test: http://git.ceph.com/?p=ceph.git;a=blob_plain;f=qa/run_xfstests_qemu.sh
index bcd79caa64f588d339db9ade2781d083654fd563..44591a1200381904c80a508dff7bfbf8b79e19f8 100644 (file)
@@ -18,6 +18,42 @@ DEFAULT_NUM_RBD = 1
 DEFAULT_IMAGE_URL = 'http://ceph.com/qa/ubuntu-12.04.qcow2'
 DEFAULT_MEM = 4096 # in megabytes
 
+def create_images(ctx, config, managers):
+    for client, client_config in config.iteritems():
+        num_rbd = client_config.get('num_rbd', 1)
+        clone = client_config.get('clone', False)
+        assert num_rbd > 0, 'at least one rbd device must be used'
+        for i in xrange(num_rbd):
+            create_config = {
+                client: {
+                    'image_name': '{client}.{num}'.format(client=client, num=i),
+                    'image_format': 2 if clone else 1,
+                    }
+                }
+            managers.append(
+                lambda create_config=create_config:
+                rbd.create_image(ctx=ctx, config=create_config)
+                )
+
+def create_clones(ctx, config, managers):
+    for client, client_config in config.iteritems():
+        num_rbd = client_config.get('num_rbd', 1)
+        clone = client_config.get('clone', False)
+        if clone:
+            for i in xrange(num_rbd):
+                create_config = {
+                    client: {
+                        'image_name':
+                        '{client}.{num}-clone'.format(client=client, num=i),
+                        'parent_name':
+                        '{client}.{num}'.format(client=client, num=i),
+                        }
+                    }
+                managers.append(
+                    lambda create_config=create_config:
+                    rbd.clone_image(ctx=ctx, config=create_config)
+                    )
+
 @contextlib.contextmanager
 def create_dirs(ctx, config):
     """
@@ -281,11 +317,14 @@ def run_qemu(ctx, config):
             else:
                 cachemode = 'writethrough'
 
+        clone = client_config.get('clone', False)
         for i in xrange(client_config.get('num_rbd', DEFAULT_NUM_RBD)):
+            suffix = '-clone' if clone else ''
             args.extend([
                 '-drive',
                 'file=rbd:rbd/{img}:id={id},format=raw,if=virtio,cache={cachemode}'.format(
-                    img='{client}.{num}'.format(client=client, num=i),
+                    img='{client}.{num}{suffix}'.format(client=client, num=i,
+                                                        suffix=suffix),
                     id=client[len('client.'):],
                     cachemode=cachemode,
                     ),
@@ -379,6 +418,15 @@ def task(ctx, config):
             client.0:
               test: http://ceph.com/qa/test.sh
               memory: 512 # megabytes
+
+    If you want to run a test against a cloned rbd image, set clone to true::
+
+        tasks:
+        - ceph:
+        - qemu:
+            client.0:
+              test: http://ceph.com/qa/test.sh
+              clone: true
     """
     assert isinstance(config, dict), \
            "task qemu only supports a dictionary for configuration"
@@ -386,27 +434,16 @@ def task(ctx, config):
     config = teuthology.replace_all_with_clients(ctx.cluster, config)
 
     managers = []
-    for client, client_config in config.iteritems():
-        num_rbd = client_config.get('num_rbd', 1)
-        assert num_rbd > 0, 'at least one rbd device must be used'
-        for i in xrange(num_rbd):
-            create_config = {
-                client: {
-                    'image_name':
-                    '{client}.{num}'.format(client=client, num=i),
-                    }
-                }
-            managers.append(
-                lambda create_config=create_config:
-                rbd.create_image(ctx=ctx, config=create_config)
-                )
-
+    create_images(ctx=ctx, config=config, managers=managers)
     managers.extend([
         lambda: create_dirs(ctx=ctx, config=config),
         lambda: generate_iso(ctx=ctx, config=config),
         lambda: download_image(ctx=ctx, config=config),
-        lambda: run_qemu(ctx=ctx, config=config),
         ])
+    create_clones(ctx=ctx, config=config, managers=managers)
+    managers.append(
+        lambda: run_qemu(ctx=ctx, config=config),
+        )
 
     with contextutil.nested(*managers):
         yield
index 8c632513077324cdf4f6b8fb234b75b3ab956664..4bf529373a19de35dc07c1a4b894042b55f02c40 100644 (file)
@@ -69,7 +69,7 @@ def create_image(ctx, config):
         # omit format option if using the default (format 1)
         # since old versions of don't support it
         if int(fmt) != 1:
-            args += ['--format', str(fmt)]
+            args += ['--image-format', str(fmt)]
         remote.run(args=args)
     try:
         yield
@@ -92,6 +92,79 @@ def create_image(ctx, config):
                     ],
                 )
 
+@contextlib.contextmanager
+def clone_image(ctx, config):
+    """
+    Clones a parent imag
+
+    For example::
+
+        tasks:
+        - ceph:
+        - rbd.clone_image:
+            client.0:
+                parent_name: testimage
+                image_name: cloneimage
+    """
+    assert isinstance(config, dict) or isinstance(config, list), \
+        "task clone_image only supports a list or dictionary for configuration"
+
+    if isinstance(config, dict):
+        images = config.items()
+    else:
+        images = [(role, None) for role in config]
+
+    testdir = teuthology.get_testdir(ctx)
+    for role, properties in images:
+        if properties is None:
+            properties = {}
+
+        name = properties.get('image_name', default_image_name(role))
+        parent_name = properties.get('parent_name')
+        assert parent_name is not None, \
+            "parent_name is required"
+        parent_spec = '{name}@{snap}'.format(name=parent_name, snap=name)
+
+        (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),
+                    ('snap', 'protect', parent_spec),
+                    ('clone', parent_spec, name)]:
+            args = [
+                    'adjust-ulimits',
+                    'ceph-coverage'.format(tdir=testdir),
+                    '{tdir}/archive/coverage'.format(tdir=testdir),
+                    'rbd', '-p', 'rbd'
+                    ]
+            args.extend(cmd)
+            remote.run(args=args)
+
+    try:
+        yield
+    finally:
+        log.info('Deleting rbd clones...')
+        for role, properties in images:
+            if properties is None:
+                properties = {}
+            name = properties.get('image_name', default_image_name(role))
+            parent_name = properties.get('parent_name')
+            parent_spec = '{name}@{snap}'.format(name=parent_name, snap=name)
+
+            (remote,) = ctx.cluster.only(role).remotes.keys()
+
+            for cmd in [('rm', name),
+                        ('snap', 'unprotect', parent_spec),
+                        ('snap', 'rm', parent_spec)]:
+                args = [
+                        'adjust-ulimits',
+                        'ceph-coverage'.format(tdir=testdir),
+                        '{tdir}/archive/coverage'.format(tdir=testdir),
+                        'rbd', '-p', 'rbd'
+                        ]
+                args.extend(cmd)
+                remote.run(args=args)
+
 @contextlib.contextmanager
 def modprobe(ctx, config):
     """