]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/cephfs/test_multimds_misc.py
3 from tasks
.cephfs
.cephfs_test_case
import CephFSTestCase
4 from teuthology
.contextutil
import safe_while
5 from teuthology
.exceptions
import CommandFailedError
7 log
= logging
.getLogger(__name__
)
9 class TestScrub2(CephFSTestCase
):
13 def _check_scrub_status(self
, result
=None, reverse
=False):
14 self
.assertEqual(self
.fs
.wait_until_scrub_complete(result
=result
, rank
=1,
16 reverse
=reverse
), True)
17 self
.assertEqual(self
.fs
.wait_until_scrub_complete(result
=result
, rank
=2,
19 reverse
=reverse
), True)
20 self
.assertEqual(self
.fs
.wait_until_scrub_complete(result
=result
, rank
=0,
22 reverse
=reverse
), True)
24 def _check_task_status_na(self
, timo
=120):
25 """ check absence of scrub status in ceph status """
26 with
safe_while(sleep
=1, tries
=120, action
='wait for task status') as proceed
:
28 active
= self
.fs
.get_active_names()
29 log
.debug("current active={0}".format(active
))
30 task_status
= self
.fs
.get_task_status("scrub status")
31 if not active
[0] in task_status
:
34 def _check_task_status(self
, expected_status
, timo
=120):
35 """ check scrub status for current active mds in ceph status """
36 with
safe_while(sleep
=1, tries
=120, action
='wait for task status') as proceed
:
38 active
= self
.fs
.get_active_names()
39 log
.debug("current active={0}".format(active
))
40 task_status
= self
.fs
.get_task_status("scrub status")
42 if task_status
[active
[0]].startswith(expected_status
):
47 def _find_path_inos(self
, root_path
):
49 p
= self
.mount_a
.run_shell(["find", root_path
])
50 paths
= p
.stdout
.getvalue().strip().split()
52 inos
.append(self
.mount_a
.path_to_ino(path
))
55 def _setup_subtrees(self
):
56 self
.fs
.set_max_mds(3)
57 self
.fs
.wait_for_daemons()
58 status
= self
.fs
.status()
60 path
= 'd1/d2/d3/d4/d5/d6/d7/d8'
61 self
.mount_a
.run_shell(['mkdir', '-p', path
])
62 self
.mount_a
.run_shell(['sync', path
])
64 self
.mount_a
.setfattr("d1/d2", "ceph.dir.pin", "0")
65 self
.mount_a
.setfattr("d1/d2/d3/d4", "ceph.dir.pin", "1")
66 self
.mount_a
.setfattr("d1/d2/d3/d4/d5/d6", "ceph.dir.pin", "2")
68 self
._wait
_subtrees
([('/d1/d2', 0), ('/d1/d2/d3/d4', 1)], status
, 0)
69 self
._wait
_subtrees
([('/d1/d2/d3/d4', 1), ('/d1/d2/d3/d4/d5/d6', 2)], status
, 1)
70 self
._wait
_subtrees
([('/d1/d2/d3/d4', 1), ('/d1/d2/d3/d4/d5/d6', 2)], status
, 2)
73 self
.fs
.rank_tell(["flush", "journal"], rank
)
75 def test_apply_tag(self
):
76 self
._setup
_subtrees
()
77 inos
= self
._find
_path
_inos
('d1/d2/d3/')
80 out_json
= self
.fs
.rank_tell(["tag", "path", "/d1/d2/d3", tag
], 0)
81 self
.assertNotEqual(out_json
, None)
82 self
.assertEqual(out_json
["return_code"], 0)
83 self
.assertEqual(self
.fs
.wait_until_scrub_complete(tag
=out_json
["scrub_tag"]), True)
85 def assertTagged(ino
):
86 file_obj_name
= "{0:x}.00000000".format(ino
)
87 self
.fs
.radosm(["getxattr", file_obj_name
, "scrub_tag"])
92 def test_scrub_backtrace(self
):
93 self
._setup
_subtrees
()
94 inos
= self
._find
_path
_inos
('d1/d2/d3/')
97 file_obj_name
= "{0:x}.00000000".format(ino
)
98 self
.fs
.radosm(["rmxattr", file_obj_name
, "parent"])
100 out_json
= self
.fs
.run_scrub(["start", "/d1/d2/d3", "recursive,force"], 0)
101 self
.assertNotEqual(out_json
, None)
102 self
.assertEqual(out_json
["return_code"], 0)
103 self
.assertEqual(self
.fs
.wait_until_scrub_complete(tag
=out_json
["scrub_tag"]), True)
105 def _check_damage(mds_rank
, inos
):
106 all_damage
= self
.fs
.rank_tell(["damage", "ls"], mds_rank
)
107 damage
= [d
for d
in all_damage
if d
['ino'] in inos
and d
['damage_type'] == "backtrace"]
108 return len(damage
) >= len(inos
)
110 self
.assertTrue(_check_damage(0, inos
[0:2]))
111 self
.assertTrue(_check_damage(1, inos
[2:4]))
112 self
.assertTrue(_check_damage(2, inos
[4:6]))
114 def test_scrub_non_mds0(self
):
115 self
._setup
_subtrees
()
117 def expect_exdev(cmd
, mds
):
119 self
.fs
.mon_manager
.raw_cluster_cmd('tell', 'mds.{0}'.format(mds
), *cmd
)
120 except CommandFailedError
as e
:
121 if e
.exitstatus
== errno
.EXDEV
:
126 raise RuntimeError("expected failure")
128 rank1
= self
.fs
.get_rank(rank
=1)
129 expect_exdev(["scrub", "start", "/d1/d2/d3"], rank1
["name"])
130 expect_exdev(["scrub", "abort"], rank1
["name"])
131 expect_exdev(["scrub", "pause"], rank1
["name"])
132 expect_exdev(["scrub", "resume"], rank1
["name"])
134 def test_scrub_abort_mds0(self
):
135 self
._setup
_subtrees
()
137 inos
= self
._find
_path
_inos
('d1/d2/d3/')
140 file_obj_name
= "{0:x}.00000000".format(ino
)
141 self
.fs
.radosm(["rmxattr", file_obj_name
, "parent"])
143 out_json
= self
.fs
.run_scrub(["start", "/d1/d2/d3", "recursive,force"], 0)
144 self
.assertNotEqual(out_json
, None)
146 res
= self
.fs
.run_scrub(["abort"])
147 self
.assertEqual(res
['return_code'], 0)
149 # Abort and verify in both mdss. We also check the status in rank 0 mds because
150 # it is supposed to gather the scrub status from other mdss.
151 self
._check
_scrub
_status
()
153 # sleep enough to fetch updated task status
154 checked
= self
._check
_task
_status
_na
()
155 self
.assertTrue(checked
)
157 def test_scrub_pause_and_resume_mds0(self
):
158 self
._setup
_subtrees
()
160 inos
= self
._find
_path
_inos
('d1/d2/d3/')
163 file_obj_name
= "{0:x}.00000000".format(ino
)
164 self
.fs
.radosm(["rmxattr", file_obj_name
, "parent"])
166 out_json
= self
.fs
.run_scrub(["start", "/d1/d2/d3", "recursive,force"], 0)
167 self
.assertNotEqual(out_json
, None)
169 res
= self
.fs
.run_scrub(["pause"])
170 self
.assertEqual(res
['return_code'], 0)
172 self
._check
_scrub
_status
(result
="PAUSED")
174 checked
= self
._check
_task
_status
("paused")
175 self
.assertTrue(checked
)
178 res
= self
.fs
.run_scrub(["resume"])
179 self
.assertEqual(res
['return_code'], 0)
181 self
._check
_scrub
_status
(result
="PAUSED", reverse
=True)
183 checked
= self
._check
_task
_status
_na
()
184 self
.assertTrue(checked
)
186 def test_scrub_pause_and_resume_with_abort_mds0(self
):
187 self
._setup
_subtrees
()
189 inos
= self
._find
_path
_inos
('d1/d2/d3/')
192 file_obj_name
= "{0:x}.00000000".format(ino
)
193 self
.fs
.radosm(["rmxattr", file_obj_name
, "parent"])
195 out_json
= self
.fs
.run_scrub(["start", "/d1/d2/d3", "recursive,force"], 0)
196 self
.assertNotEqual(out_json
, None)
198 res
= self
.fs
.run_scrub(["pause"])
199 self
.assertEqual(res
['return_code'], 0)
201 self
._check
_scrub
_status
(result
="PAUSED")
203 checked
= self
._check
_task
_status
("paused")
204 self
.assertTrue(checked
)
206 res
= self
.fs
.run_scrub(["abort"])
207 self
.assertEqual(res
['return_code'], 0)
209 self
._check
_scrub
_status
(result
="PAUSED")
210 self
._check
_scrub
_status
(result
="0 inodes")
212 # scrub status should still be paused...
213 checked
= self
._check
_task
_status
("paused")
214 self
.assertTrue(checked
)
217 res
= self
.fs
.run_scrub(["resume"])
218 self
.assertEqual(res
['return_code'], 0)
220 self
._check
_scrub
_status
(result
="PAUSED", reverse
=True)
222 checked
= self
._check
_task
_status
_na
()
223 self
.assertTrue(checked
)