suites/rbd/qemu: excercise CoW support during QEMU testing

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2015-10-21 16:27:08 -04:00
parent 12d7576ead
commit 59e768bb29
5 changed files with 131 additions and 18 deletions

View 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

View 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

View 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

View 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):
"""
@ -284,11 +320,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,
),
@ -382,6 +421,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"
@ -389,27 +437,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

View 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):
"""