Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / qa / tasks / ceph_fuse.py
1 """
2 Ceph FUSE client task
3 """
4
5 import contextlib
6 import logging
7
8 from teuthology import misc as teuthology
9 from cephfs.fuse_mount import FuseMount
10
11 log = logging.getLogger(__name__)
12
13
14 def get_client_configs(ctx, config):
15     """
16     Get a map of the configuration for each FUSE client in the configuration by
17     combining the configuration of the current task with any global overrides.
18
19     :param ctx: Context instance
20     :param config: configuration for this task
21     :return: dict of client name to config or to None
22     """
23     if config is None:
24         config = dict(('client.{id}'.format(id=id_), None)
25                       for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client'))
26     elif isinstance(config, list):
27         config = dict((name, None) for name in config)
28
29     overrides = ctx.config.get('overrides', {})
30     teuthology.deep_merge(config, overrides.get('ceph-fuse', {}))
31
32     return config
33
34
35 @contextlib.contextmanager
36 def task(ctx, config):
37     """
38     Mount/unmount a ``ceph-fuse`` client.
39
40     The config is optional and defaults to mounting on all clients. If
41     a config is given, it is expected to be a list of clients to do
42     this operation on. This lets you e.g. set up one client with
43     ``ceph-fuse`` and another with ``kclient``.
44
45     Example that mounts all clients::
46
47         tasks:
48         - ceph:
49         - ceph-fuse:
50         - interactive:
51
52     Example that uses both ``kclient` and ``ceph-fuse``::
53
54         tasks:
55         - ceph:
56         - ceph-fuse: [client.0]
57         - kclient: [client.1]
58         - interactive:
59
60     Example that enables valgrind:
61
62         tasks:
63         - ceph:
64         - ceph-fuse:
65             client.0:
66               valgrind: [--tool=memcheck, --leak-check=full, --show-reachable=yes]
67         - interactive:
68
69     Example that stops an already-mounted client:
70
71     ::
72
73         tasks:
74             - ceph:
75             - ceph-fuse: [client.0]
76             - ... do something that requires the FS mounted ...
77             - ceph-fuse:
78                 client.0:
79                     mounted: false
80             - ... do something that requires the FS unmounted ...
81
82     Example that adds more generous wait time for mount (for virtual machines):
83
84         tasks:
85         - ceph:
86         - ceph-fuse:
87             client.0:
88               mount_wait: 60 # default is 0, do not wait before checking /sys/
89               mount_timeout: 120 # default is 30, give up if /sys/ is not populated
90         - interactive:
91
92     :param ctx: Context
93     :param config: Configuration
94     """
95     log.info('Mounting ceph-fuse clients...')
96
97     testdir = teuthology.get_testdir(ctx)
98     config = get_client_configs(ctx, config)
99
100     # List clients we will configure mounts for, default is all clients
101     clients = list(teuthology.get_clients(ctx=ctx, roles=filter(lambda x: 'client.' in x, config.keys())))
102
103     all_mounts = getattr(ctx, 'mounts', {})
104     mounted_by_me = {}
105
106     # Construct any new FuseMount instances
107     for id_, remote in clients:
108         client_config = config.get("client.%s" % id_)
109         if client_config is None:
110             client_config = {}
111
112         if id_ not in all_mounts:
113             fuse_mount = FuseMount(client_config, testdir, id_, remote)
114             all_mounts[id_] = fuse_mount
115         else:
116             # Catch bad configs where someone has e.g. tried to use ceph-fuse and kcephfs for the same client
117             assert isinstance(all_mounts[id_], FuseMount)
118
119         if not config.get("disabled", False) and client_config.get('mounted', True):
120             mounted_by_me[id_] = all_mounts[id_]
121
122     ctx.mounts = all_mounts
123
124     # Mount any clients we have been asked to (default to mount all)
125     for mount in mounted_by_me.values():
126         mount.mount()
127
128     for mount in mounted_by_me.values():
129         mount.wait_until_mounted()
130
131     # Umount any pre-existing clients that we have not been asked to mount
132     for client_id in set(all_mounts.keys()) - set(mounted_by_me.keys()):
133         mount = all_mounts[client_id]
134         if mount.is_mounted():
135             mount.umount_wait()
136
137     try:
138         yield all_mounts
139     finally:
140         log.info('Unmounting ceph-fuse clients...')
141
142         for mount in mounted_by_me.values():
143             # Conditional because an inner context might have umounted it
144             if mount.is_mounted():
145                 mount.umount_wait()