1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
"""
Mount/unmount a ``kernel`` client.
"""
import contextlib
import logging
from teuthology.misc import deep_merge
from teuthology.exceptions import CommandFailedError
from teuthology import misc
from teuthology.contextutil import MaxWhileTries
from tasks.cephfs.kernel_mount import KernelMount
log = logging.getLogger(__name__)
@contextlib.contextmanager
def task(ctx, config):
"""
Mount/unmount a ``kernel`` client.
The config is optional and defaults to mounting on all clients. If
a config is given, it is expected to be a list of clients to do
this operation on. This lets you e.g. set up one client with
``ceph-fuse`` and another with ``kclient``.
``brxnet`` should be a Private IPv4 Address range, default range is
[192.168.0.0/16]
Example that mounts all clients::
tasks:
- ceph:
- kclient:
- interactive:
- brxnet: [192.168.0.0/16]
Example that uses both ``kclient` and ``ceph-fuse``::
tasks:
- ceph:
- ceph-fuse: [client.0]
- kclient: [client.1]
- interactive:
Pass a dictionary instead of lists to specify per-client config:
tasks:
-kclient:
client.0:
debug: true
mntopts: ["nowsync"]
:param ctx: Context
:param config: Configuration
"""
log.info('Mounting kernel clients...')
if config is None:
ids = misc.all_roles_of_type(ctx.cluster, 'client')
client_roles = [f'client.{id_}' for id_ in ids]
config = dict([r, dict()] for r in client_roles)
elif isinstance(config, list):
client_roles = config
config = dict([r, dict()] for r in client_roles)
elif isinstance(config, dict):
client_roles = filter(lambda x: 'client.' in x, config.keys())
else:
raise ValueError(f"Invalid config object: {config} ({config.__class__})")
log.info(f"config is {config}")
clients = list(misc.get_clients(ctx=ctx, roles=client_roles))
test_dir = misc.get_testdir(ctx)
for id_, remote in clients:
KernelMount.cleanup_stale_netnses_and_bridge(remote)
mounts = {}
overrides = ctx.config.get('overrides', {}).get('kclient', {})
top_overrides = dict(filter(lambda x: 'client.' not in x[0], overrides.items()))
for id_, remote in clients:
entity = f"client.{id_}"
client_config = config.get(entity)
if client_config is None:
client_config = {}
# top level overrides
deep_merge(client_config, top_overrides)
# mount specific overrides
client_config_overrides = overrides.get(entity)
deep_merge(client_config, client_config_overrides)
log.info(f"{entity} config is {client_config}")
cephfs_name = client_config.get("cephfs_name")
if config.get("disabled", False) or not client_config.get('mounted', True):
continue
kernel_mount = KernelMount(
ctx=ctx,
test_dir=test_dir,
client_id=id_,
client_remote=remote,
brxnet=ctx.teuthology_config.get('brxnet', None),
client_config=client_config,
cephfs_name=cephfs_name)
mounts[id_] = kernel_mount
if client_config.get('debug', False):
remote.run(args=["sudo", "bash", "-c", "echo 'module ceph +p' > /sys/kernel/debug/dynamic_debug/control"])
remote.run(args=["sudo", "bash", "-c", "echo 'module libceph +p' > /sys/kernel/debug/dynamic_debug/control"])
kernel_mount.mount(mntopts=client_config.get('mntopts', []))
def umount_all():
log.info('Unmounting kernel clients...')
forced = False
for mount in mounts.values():
if mount.is_mounted():
try:
mount.umount()
except (CommandFailedError, MaxWhileTries):
log.warning("Ordinary umount failed, forcing...")
forced = True
mount.umount_wait(force=True)
for id_, remote in clients:
KernelMount.cleanup_stale_netnses_and_bridge(remote)
return forced
ctx.mounts = mounts
try:
yield mounts
except:
umount_all() # ignore forced retval, we are already in error handling
finally:
forced = umount_all()
if forced:
# The context managers within the kclient manager worked (i.e.
# the test workload passed) but for some reason we couldn't
# umount, so turn this into a test failure.
raise RuntimeError("Kernel mounts did not umount cleanly")
|