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