]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/cephfs/kernel_mount.py
update sources to 12.2.7
[ceph.git] / ceph / qa / tasks / cephfs / kernel_mount.py
CommitLineData
7c673cae
FG
1from StringIO import StringIO
2import json
3import logging
4from textwrap import dedent
5from teuthology.orchestra.run import CommandFailedError
6from teuthology import misc
7
8from teuthology.orchestra import remote as orchestra_remote
9from teuthology.orchestra import run
10from teuthology.contextutil import MaxWhileTries
11from .mount import CephFSMount
12
13log = logging.getLogger(__name__)
14
15
16UMOUNT_TIMEOUT = 300
17
18
19class KernelMount(CephFSMount):
20 def __init__(self, mons, test_dir, client_id, client_remote,
21 ipmi_user, ipmi_password, ipmi_domain):
22 super(KernelMount, self).__init__(test_dir, client_id, client_remote)
23 self.mons = mons
24
25 self.mounted = False
26 self.ipmi_user = ipmi_user
27 self.ipmi_password = ipmi_password
28 self.ipmi_domain = ipmi_domain
29
30 def write_secret_file(self, remote, role, keyring, filename):
31 """
32 Stash the keyring in the filename specified.
33 """
34 remote.run(
35 args=[
36 'adjust-ulimits',
37 'ceph-coverage',
38 '{tdir}/archive/coverage'.format(tdir=self.test_dir),
39 'ceph-authtool',
40 '--name={role}'.format(role=role),
41 '--print-key',
42 keyring,
43 run.Raw('>'),
44 filename,
45 ],
46 )
47
48 def mount(self, mount_path=None, mount_fs_name=None):
49 log.info('Mounting kclient client.{id} at {remote} {mnt}...'.format(
50 id=self.client_id, remote=self.client_remote, mnt=self.mountpoint))
51
52 keyring = self.get_keyring_path()
53 secret = '{tdir}/ceph.data/client.{id}.secret'.format(tdir=self.test_dir, id=self.client_id)
54 self.write_secret_file(self.client_remote, 'client.{id}'.format(id=self.client_id),
55 keyring, secret)
56
57 self.client_remote.run(
58 args=[
59 'mkdir',
60 '--',
61 self.mountpoint,
62 ],
63 )
64
65 if mount_path is None:
66 mount_path = "/"
67
68 opts = 'name={id},secretfile={secret},norequire_active_mds'.format(id=self.client_id,
69 secret=secret)
70
71 if mount_fs_name is not None:
72 opts += ",mds_namespace={0}".format(mount_fs_name)
73
74 self.client_remote.run(
75 args=[
76 'sudo',
77 'adjust-ulimits',
78 'ceph-coverage',
79 '{tdir}/archive/coverage'.format(tdir=self.test_dir),
80 '/sbin/mount.ceph',
81 '{mons}:{mount_path}'.format(mons=','.join(self.mons), mount_path=mount_path),
82 self.mountpoint,
83 '-v',
84 '-o',
85 opts
86 ],
87 )
88
89 self.client_remote.run(
90 args=['sudo', 'chmod', '1777', self.mountpoint])
91
92 self.mounted = True
93
94 def umount(self, force=False):
95 log.debug('Unmounting client client.{id}...'.format(id=self.client_id))
96
97 cmd=['sudo', 'umount', self.mountpoint]
98 if force:
99 cmd.append('-f')
100
c07f9fc5
FG
101 try:
102 self.client_remote.run(args=cmd)
103 except Exception as e:
104 self.client_remote.run(args=[
105 'sudo',
106 run.Raw('PATH=/usr/sbin:$PATH'),
107 'lsof',
108 run.Raw(';'),
109 'ps', 'auxf',
110 ])
111 raise e
7c673cae
FG
112
113 rproc = self.client_remote.run(
114 args=[
115 'rmdir',
116 '--',
117 self.mountpoint,
118 ],
119 wait=False
120 )
121 run.wait([rproc], UMOUNT_TIMEOUT)
122 self.mounted = False
123
124 def cleanup(self):
125 pass
126
28e407b8 127 def umount_wait(self, force=False, require_clean=False, timeout=900):
7c673cae
FG
128 """
129 Unlike the fuse client, the kernel client's umount is immediate
130 """
131 if not self.is_mounted():
132 return
133
134 try:
135 self.umount(force)
136 except (CommandFailedError, MaxWhileTries):
137 if not force:
138 raise
139
140 self.kill()
141 self.kill_cleanup()
142
143 self.mounted = False
144
145 def is_mounted(self):
146 return self.mounted
147
148 def wait_until_mounted(self):
149 """
150 Unlike the fuse client, the kernel client is up and running as soon
151 as the initial mount() function returns.
152 """
153 assert self.mounted
154
155 def teardown(self):
156 super(KernelMount, self).teardown()
157 if self.mounted:
158 self.umount()
159
160 def kill(self):
161 """
162 The Ceph kernel client doesn't have a mechanism to kill itself (doing
163 that in side the kernel would be weird anyway), so we reboot the whole node
164 to get the same effect.
165
166 We use IPMI to reboot, because we don't want the client to send any
167 releases of capabilities.
168 """
169
170 con = orchestra_remote.getRemoteConsole(self.client_remote.hostname,
171 self.ipmi_user,
172 self.ipmi_password,
173 self.ipmi_domain)
174 con.power_off()
175
176 self.mounted = False
177
178 def kill_cleanup(self):
179 assert not self.mounted
180
181 con = orchestra_remote.getRemoteConsole(self.client_remote.hostname,
182 self.ipmi_user,
183 self.ipmi_password,
184 self.ipmi_domain)
185 con.power_on()
186
187 # Wait for node to come back up after reboot
188 misc.reconnect(None, 300, [self.client_remote])
189
190 # Remove mount directory
191 self.client_remote.run(
192 args=[
193 'rmdir',
194 '--',
195 self.mountpoint,
196 ],
197 )
198
199 def _find_debug_dir(self):
200 """
201 Find the debugfs folder for this mount
202 """
203 pyscript = dedent("""
204 import glob
205 import os
206 import json
207
208 def get_id_to_dir():
209 result = {}
210 for dir in glob.glob("/sys/kernel/debug/ceph/*"):
211 mds_sessions_lines = open(os.path.join(dir, "mds_sessions")).readlines()
212 client_id = mds_sessions_lines[1].split()[1].strip('"')
213
214 result[client_id] = dir
215 return result
216
217 print json.dumps(get_id_to_dir())
218 """)
219
220 p = self.client_remote.run(args=[
221 'sudo', 'python', '-c', pyscript
222 ], stdout=StringIO())
223 client_id_to_dir = json.loads(p.stdout.getvalue())
224
225 try:
226 return client_id_to_dir[self.client_id]
227 except KeyError:
228 log.error("Client id '{0}' debug dir not found (clients seen were: {1})".format(
229 self.client_id, ",".join(client_id_to_dir.keys())
230 ))
231 raise
232
233 def _read_debug_file(self, filename):
234 debug_dir = self._find_debug_dir()
235
236 pyscript = dedent("""
237 import os
238
239 print open(os.path.join("{debug_dir}", "{filename}")).read()
240 """).format(debug_dir=debug_dir, filename=filename)
241
242 p = self.client_remote.run(args=[
243 'sudo', 'python', '-c', pyscript
244 ], stdout=StringIO())
245 return p.stdout.getvalue()
246
247 def get_global_id(self):
248 """
249 Look up the CephFS client ID for this mount, using debugfs.
250 """
251
252 assert self.mounted
253
254 mds_sessions = self._read_debug_file("mds_sessions")
255 lines = mds_sessions.split("\n")
256 return int(lines[0].split()[1])
257
258 def get_osd_epoch(self):
259 """
260 Return 2-tuple of osd_epoch, osd_epoch_barrier
261 """
262 osd_map = self._read_debug_file("osdmap")
263 lines = osd_map.split("\n")
264 first_line_tokens = lines[0].split()
265 epoch, barrier = int(first_line_tokens[1]), int(first_line_tokens[3])
266
267 return epoch, barrier