]>
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 | |
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 | """ | |
11fdf7f2 | 95 | log.info('Running ceph_fuse task...') |
7c673cae FG |
96 | |
97 | testdir = teuthology.get_testdir(ctx) | |
11fdf7f2 | 98 | log.info("config is {}".format(str(config))) |
7c673cae | 99 | config = get_client_configs(ctx, config) |
11fdf7f2 | 100 | log.info("new config is {}".format(str(config))) |
7c673cae FG |
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 = {} | |
11fdf7f2 | 107 | skipped = {} |
1adf2230 | 108 | |
7c673cae FG |
109 | # Construct any new FuseMount instances |
110 | for id_, remote in clients: | |
111 | client_config = config.get("client.%s" % id_) | |
112 | if client_config is None: | |
113 | client_config = {} | |
114 | ||
9f95a23c TL |
115 | auth_id = client_config.get("auth_id", id_) |
116 | ||
11fdf7f2 TL |
117 | skip = client_config.get("skip", False) |
118 | if skip: | |
119 | skipped[id_] = skip | |
120 | continue | |
121 | ||
7c673cae | 122 | if id_ not in all_mounts: |
9f95a23c | 123 | fuse_mount = FuseMount(ctx, client_config, testdir, auth_id, remote) |
7c673cae FG |
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): | |
9f95a23c | 130 | mounted_by_me[id_] = {"config": client_config, "mount": all_mounts[id_]} |
7c673cae FG |
131 | |
132 | ctx.mounts = all_mounts | |
133 | ||
134 | # Mount any clients we have been asked to (default to mount all) | |
11fdf7f2 | 135 | log.info('Mounting ceph-fuse clients...') |
9f95a23c TL |
136 | for info in mounted_by_me.values(): |
137 | config = info["config"] | |
138 | mount_path = config.get("mount_path") | |
139 | mountpoint = config.get("mountpoint") | |
140 | info["mount"].mount(mountpoint=mountpoint, mount_path=mount_path) | |
7c673cae | 141 | |
9f95a23c TL |
142 | for info in mounted_by_me.values(): |
143 | info["mount"].wait_until_mounted() | |
7c673cae FG |
144 | |
145 | # Umount any pre-existing clients that we have not been asked to mount | |
11fdf7f2 | 146 | for client_id in set(all_mounts.keys()) - set(mounted_by_me.keys()) - set(skipped.keys()): |
7c673cae FG |
147 | mount = all_mounts[client_id] |
148 | if mount.is_mounted(): | |
149 | mount.umount_wait() | |
150 | ||
151 | try: | |
152 | yield all_mounts | |
153 | finally: | |
154 | log.info('Unmounting ceph-fuse clients...') | |
155 | ||
9f95a23c | 156 | for info in mounted_by_me.values(): |
7c673cae | 157 | # Conditional because an inner context might have umounted it |
9f95a23c | 158 | mount = info["mount"] |
7c673cae FG |
159 | if mount.is_mounted(): |
160 | mount.umount_wait() |