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