]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/cephfs/test_misc.py
0367c141f29ccb0634fe2226b33bf6e9f0cfa9c5
1 from io
import StringIO
3 from tasks
.cephfs
.fuse_mount
import FuseMount
4 from tasks
.cephfs
.cephfs_test_case
import CephFSTestCase
5 from teuthology
.exceptions
import CommandFailedError
11 log
= logging
.getLogger(__name__
)
13 class TestMisc(CephFSTestCase
):
16 def test_statfs_on_deleted_fs(self
):
18 That statfs does not cause monitors to SIGSEGV after fs deletion.
21 self
.mount_b
.umount_wait()
22 self
.mount_a
.run_shell_payload("stat -f .")
23 self
.fs
.delete_all_filesystems()
24 # This will hang either way, run in background.
25 p
= self
.mount_a
.run_shell_payload("stat -f .", wait
=False, timeout
=60, check_status
=False)
27 self
.assertFalse(p
.finished
)
28 # the process is stuck in uninterruptible sleep, just kill the mount
29 self
.mount_a
.umount_wait(force
=True)
32 def test_getattr_caps(self
):
34 Check if MDS recognizes the 'mask' parameter of open request.
35 The parameter allows client to request caps when opening file
38 if not isinstance(self
.mount_a
, FuseMount
):
39 self
.skipTest("Require FUSE client")
41 # Enable debug. Client will requests CEPH_CAP_XATTR_SHARED
43 self
.mount_b
.umount_wait()
44 self
.set_conf('client', 'client debug getattr caps', 'true')
45 self
.mount_b
.mount_wait()
47 # create a file and hold it open. MDS will issue CEPH_CAP_EXCL_*
49 p
= self
.mount_a
.open_background("testfile")
50 self
.mount_b
.wait_for_visible("testfile")
52 # this triggers a lookup request and an open request. The debug
53 # code will check if lookup/open reply contains xattrs
54 self
.mount_b
.run_shell(["cat", "testfile"])
56 self
.mount_a
.kill_background(p
)
58 def test_root_rctime(self
):
60 Check that the root inode has a non-default rctime on startup.
64 rctime
= self
.mount_a
.getfattr(".", "ceph.dir.rctime")
65 log
.info("rctime = {}".format(rctime
))
66 self
.assertGreaterEqual(float(rctime
), t
- 10)
68 def test_fs_new(self
):
69 self
.mount_a
.umount_wait()
70 self
.mount_b
.umount_wait()
72 data_pool_name
= self
.fs
.get_data_pool_name()
76 self
.fs
.mon_manager
.raw_cluster_cmd('fs', 'rm', self
.fs
.name
,
77 '--yes-i-really-mean-it')
79 self
.fs
.mon_manager
.raw_cluster_cmd('osd', 'pool', 'delete',
80 self
.fs
.metadata_pool_name
,
81 self
.fs
.metadata_pool_name
,
82 '--yes-i-really-really-mean-it')
83 self
.fs
.mon_manager
.raw_cluster_cmd('osd', 'pool', 'create',
84 self
.fs
.metadata_pool_name
,
85 '--pg_num_min', str(self
.fs
.pg_num_min
))
87 # insert a garbage object
88 self
.fs
.radosm(["put", "foo", "-"], stdin
=StringIO("bar"))
90 def get_pool_df(fs
, name
):
92 return fs
.get_pool_df(name
)['objects'] > 0
96 self
.wait_until_true(lambda: get_pool_df(self
.fs
, self
.fs
.metadata_pool_name
), timeout
=30)
99 self
.fs
.mon_manager
.raw_cluster_cmd('fs', 'new', self
.fs
.name
,
100 self
.fs
.metadata_pool_name
,
102 except CommandFailedError
as e
:
103 self
.assertEqual(e
.exitstatus
, errno
.EINVAL
)
105 raise AssertionError("Expected EINVAL")
107 self
.fs
.mon_manager
.raw_cluster_cmd('fs', 'new', self
.fs
.name
,
108 self
.fs
.metadata_pool_name
,
109 data_pool_name
, "--force")
111 self
.fs
.mon_manager
.raw_cluster_cmd('fs', 'fail', self
.fs
.name
)
113 self
.fs
.mon_manager
.raw_cluster_cmd('fs', 'rm', self
.fs
.name
,
114 '--yes-i-really-mean-it')
116 self
.fs
.mon_manager
.raw_cluster_cmd('osd', 'pool', 'delete',
117 self
.fs
.metadata_pool_name
,
118 self
.fs
.metadata_pool_name
,
119 '--yes-i-really-really-mean-it')
120 self
.fs
.mon_manager
.raw_cluster_cmd('osd', 'pool', 'create',
121 self
.fs
.metadata_pool_name
,
122 '--pg_num_min', str(self
.fs
.pg_num_min
))
123 self
.fs
.mon_manager
.raw_cluster_cmd('fs', 'new', self
.fs
.name
,
124 self
.fs
.metadata_pool_name
,
127 def test_cap_revoke_nonresponder(self
):
129 Check that a client is evicted if it has not responded to cap revoke
130 request for configured number of seconds.
132 session_timeout
= self
.fs
.get_var("session_timeout")
133 eviction_timeout
= session_timeout
/ 2.0
135 self
.fs
.mds_asok(['config', 'set', 'mds_cap_revoke_eviction_timeout',
136 str(eviction_timeout
)])
138 cap_holder
= self
.mount_a
.open_background()
140 # Wait for the file to be visible from another client, indicating
141 # that mount_a has completed its network ops
142 self
.mount_b
.wait_for_visible()
144 # Simulate client death
145 self
.mount_a
.suspend_netns()
148 # The waiter should get stuck waiting for the capability
149 # held on the MDS by the now-dead client A
150 cap_waiter
= self
.mount_b
.write_background()
153 time
.sleep(eviction_timeout
)
157 log
.info("cap_waiter waited {0}s".format(cap_waited
))
159 # check if the cap is transferred before session timeout kicked in.
160 # this is a good enough check to ensure that the client got evicted
161 # by the cap auto evicter rather than transitioning to stale state
162 # and then getting evicted.
163 self
.assertLess(cap_waited
, session_timeout
,
164 "Capability handover took {0}, expected less than {1}".format(
165 cap_waited
, session_timeout
168 self
.assertTrue(self
.mds_cluster
.is_addr_blocklisted(
169 self
.mount_a
.get_global_addr()))
170 self
.mount_a
._kill
_background
(cap_holder
)
172 self
.mount_a
.resume_netns()
174 def test_filtered_df(self
):
175 pool_name
= self
.fs
.get_data_pool_name()
176 raw_df
= self
.fs
.get_pool_df(pool_name
)
177 raw_avail
= float(raw_df
["max_avail"])
178 out
= self
.fs
.mon_manager
.raw_cluster_cmd('osd', 'pool', 'get',
183 proc
= self
.mount_a
.run_shell(['df', '.'])
184 output
= proc
.stdout
.getvalue()
185 fs_avail
= output
.split('\n')[1].split()[3]
186 fs_avail
= float(fs_avail
) * 1024
188 ratio
= raw_avail
/ fs_avail
189 assert 0.9 < ratio
< 1.1
191 def test_dump_inode(self
):
192 info
= self
.fs
.mds_asok(['dump', 'inode', '1'])
193 assert(info
['path'] == "/")
195 def test_dump_inode_hexademical(self
):
196 self
.mount_a
.run_shell(["mkdir", "-p", "foo"])
197 ino
= self
.mount_a
.path_to_ino("foo")
198 assert type(ino
) is int
199 info
= self
.fs
.mds_asok(['dump', 'inode', hex(ino
)])
200 assert info
['path'] == "/foo"
202 def test_fs_lsflags(self
):
204 Check that the lsflags displays the default state and the new state of flags
207 self
.fs
.set_joinable(False)
208 self
.fs
.set_allow_new_snaps(False)
209 self
.fs
.set_allow_standby_replay(True)
211 lsflags
= json
.loads(self
.fs
.mon_manager
.raw_cluster_cmd('fs', 'lsflags',
213 "--format=json-pretty"))
214 self
.assertEqual(lsflags
["joinable"], False)
215 self
.assertEqual(lsflags
["allow_snaps"], False)
216 self
.assertEqual(lsflags
["allow_multimds_snaps"], True)
217 self
.assertEqual(lsflags
["allow_standby_replay"], True)
219 class TestCacheDrop(CephFSTestCase
):
222 def _run_drop_cache_cmd(self
, timeout
=None):
224 args
= ["cache", "drop"]
225 if timeout
is not None:
226 args
.append(str(timeout
))
227 result
= self
.fs
.rank_tell(args
)
230 def _setup(self
, max_caps
=20, threshold
=400):
232 self
.mount_a
.create_n_files("dc-dir/dc-file", 1000, sync
=True)
234 # Reduce this so the MDS doesn't rkcall the maximum for simple tests
235 self
.fs
.rank_asok(['config', 'set', 'mds_recall_max_caps', str(max_caps
)])
236 self
.fs
.rank_asok(['config', 'set', 'mds_recall_max_decay_threshold', str(threshold
)])
238 def test_drop_cache_command(self
):
240 Basic test for checking drop cache command.
241 Confirm it halts without a timeout.
242 Note that the cache size post trimming is not checked here.
244 mds_min_caps_per_client
= int(self
.fs
.get_config("mds_min_caps_per_client"))
246 result
= self
._run
_drop
_cache
_cmd
()
247 self
.assertEqual(result
['client_recall']['return_code'], 0)
248 self
.assertEqual(result
['flush_journal']['return_code'], 0)
249 # It should take at least 1 second
250 self
.assertGreater(result
['duration'], 1)
251 self
.assertGreaterEqual(result
['trim_cache']['trimmed'], 1000-2*mds_min_caps_per_client
)
253 def test_drop_cache_command_timeout(self
):
255 Basic test for checking drop cache command.
256 Confirm recall halts early via a timeout.
257 Note that the cache size post trimming is not checked here.
260 result
= self
._run
_drop
_cache
_cmd
(timeout
=10)
261 self
.assertEqual(result
['client_recall']['return_code'], -errno
.ETIMEDOUT
)
262 self
.assertEqual(result
['flush_journal']['return_code'], 0)
263 self
.assertGreater(result
['duration'], 10)
264 self
.assertGreaterEqual(result
['trim_cache']['trimmed'], 100) # we did something, right?
266 def test_drop_cache_command_dead_timeout(self
):
268 Check drop cache command with non-responding client using tell
269 interface. Note that the cache size post trimming is not checked
273 self
.mount_a
.suspend_netns()
274 # Note: recall is subject to the timeout. The journal flush will
275 # be delayed due to the client being dead.
276 result
= self
._run
_drop
_cache
_cmd
(timeout
=5)
277 self
.assertEqual(result
['client_recall']['return_code'], -errno
.ETIMEDOUT
)
278 self
.assertEqual(result
['flush_journal']['return_code'], 0)
279 self
.assertGreater(result
['duration'], 5)
280 self
.assertLess(result
['duration'], 120)
281 # Note: result['trim_cache']['trimmed'] may be >0 because dropping the
282 # cache now causes the Locker to drive eviction of stale clients (a
283 # stale session will be autoclosed at mdsmap['session_timeout']). The
284 # particular operation causing this is journal flush which causes the
285 # MDS to wait wait for cap revoke.
286 #self.assertEqual(0, result['trim_cache']['trimmed'])
287 self
.mount_a
.resume_netns()
289 def test_drop_cache_command_dead(self
):
291 Check drop cache command with non-responding client using tell
292 interface. Note that the cache size post trimming is not checked
296 self
.mount_a
.suspend_netns()
297 result
= self
._run
_drop
_cache
_cmd
()
298 self
.assertEqual(result
['client_recall']['return_code'], 0)
299 self
.assertEqual(result
['flush_journal']['return_code'], 0)
300 self
.assertGreater(result
['duration'], 5)
301 self
.assertLess(result
['duration'], 120)
302 # Note: result['trim_cache']['trimmed'] may be >0 because dropping the
303 # cache now causes the Locker to drive eviction of stale clients (a
304 # stale session will be autoclosed at mdsmap['session_timeout']). The
305 # particular operation causing this is journal flush which causes the
306 # MDS to wait wait for cap revoke.
307 self
.mount_a
.resume_netns()