]>
git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/cephadm/tests/test_osd_removal.py
3 from cephadm
.services
.osd
import RemoveUtil
, OSDRemovalQueue
, OSD
5 from .fixtures
import rm_util
, osd_obj
, cephadm_module
7 from datetime
import datetime
12 def __init__(self
, osd_id
):
18 @pytest.mark
.parametrize(
19 "osd_id, osd_df, expected",
22 (1, dict(nodes
=[]), -1),
24 (1, dict(nodes
=[dict(id=1)]), -1),
26 (1, dict(nodes
=[dict(id=999, pgs
=1)]), -1),
28 (1, dict(nodes
=[dict(id=1, pgs
=1)]), 1),
31 def test_get_pg_count(self
, rm_util
, osd_id
, osd_df
, expected
):
32 with mock
.patch("cephadm.services.osd.RemoveUtil.osd_df", return_value
=osd_df
):
33 assert rm_util
.get_pg_count(osd_id
) == expected
35 @pytest.mark
.parametrize(
36 "osds, ok_to_stop, expected",
40 # all osds are ok_to_stop
41 ([1, 2], [True], [1, 2]),
42 # osds are ok_to_stop after the second iteration
43 ([1, 2], [False, True], [2]),
44 # osds are never ok_to_stop, (taking the sample size `(len(osd_ids))` into account),
45 # expected to get False
46 ([1, 2], [False, False], []),
49 def test_find_stop_threshold(self
, rm_util
, osds
, ok_to_stop
, expected
):
50 with mock
.patch("cephadm.services.osd.RemoveUtil.ok_to_stop", side_effect
=ok_to_stop
):
51 assert rm_util
.find_osd_stop_threshold(osds
) == expected
53 def test_process_removal_queue(self
, rm_util
):
55 # rm_util.process_removal_queue()
58 def test_ok_to_stop(self
, rm_util
):
59 rm_util
.ok_to_stop([MockOSD(1)])
60 rm_util
._run
_mon
_cmd
.assert_called_with({'prefix': 'osd ok-to-stop', 'ids': ['1']})
62 def test_safe_to_destroy(self
, rm_util
):
63 rm_util
.safe_to_destroy([1])
64 rm_util
._run
_mon
_cmd
.assert_called_with({'prefix': 'osd safe-to-destroy', 'ids': ['1']})
66 def test_destroy_osd(self
, rm_util
):
67 rm_util
.destroy_osd(1)
68 rm_util
._run
_mon
_cmd
.assert_called_with(
69 {'prefix': 'osd destroy-actual', 'id': 1, 'yes_i_really_mean_it': True})
71 def test_purge_osd(self
, rm_util
):
73 rm_util
._run
_mon
_cmd
.assert_called_with(
74 {'prefix': 'osd purge-actual', 'id': 1, 'yes_i_really_mean_it': True})
76 def test_load(self
, cephadm_module
, rm_util
):
86 "drain_started_at": "2020-09-14T11:41:53.960463",
87 "drain_stopped_at": None,
88 "drain_done_at": None,
89 "process_started_at": "2020-09-14T11:41:52.245832"
92 cephadm_module
.set_store('osd_remove_queue', data
)
93 cephadm_module
.to_remove_osds
.load_from_store()
95 expected
= OSDRemovalQueue(cephadm_module
)
96 expected
.osds
.add(OSD(osd_id
=35, remove_util
=rm_util
, draining
=True))
97 assert cephadm_module
.to_remove_osds
== expected
102 def test_start(self
, osd_obj
):
103 assert osd_obj
.started
is False
105 assert osd_obj
.started
is True
106 assert osd_obj
.stopped
is False
108 def test_start_draining(self
, osd_obj
):
109 assert osd_obj
.draining
is False
110 assert osd_obj
.drain_started_at
is None
111 ret
= osd_obj
.start_draining()
112 osd_obj
.rm_util
.set_osd_flag
.assert_called_with([osd_obj
], 'out')
113 assert isinstance(osd_obj
.drain_started_at
, datetime
)
114 assert osd_obj
.draining
is True
117 def test_start_draining_stopped(self
, osd_obj
):
118 osd_obj
.stopped
= True
119 ret
= osd_obj
.start_draining()
120 assert osd_obj
.drain_started_at
is None
122 assert osd_obj
.draining
is False
124 def test_stop_draining(self
, osd_obj
):
125 ret
= osd_obj
.stop_draining()
126 osd_obj
.rm_util
.set_osd_flag
.assert_called_with([osd_obj
], 'in')
127 assert isinstance(osd_obj
.drain_stopped_at
, datetime
)
128 assert osd_obj
.draining
is False
131 @mock.patch('cephadm.services.osd.OSD.stop_draining')
132 def test_stop(self
, stop_draining_mock
, osd_obj
):
134 assert osd_obj
.started
is False
135 assert osd_obj
.stopped
is True
136 stop_draining_mock
.assert_called_once()
138 @pytest.mark
.parametrize(
139 "draining, empty, expected",
141 # must be !draining! and !not empty! to yield True
142 (True, not True, True),
143 # not draining and not empty
144 (False, not True, False),
145 # not draining and empty
146 (False, True, False),
151 def test_is_draining(self
, osd_obj
, draining
, empty
, expected
):
152 with mock
.patch("cephadm.services.osd.OSD.is_empty", new_callable
=mock
.PropertyMock(return_value
=empty
)):
153 osd_obj
.draining
= draining
154 assert osd_obj
.is_draining
is expected
156 @mock.patch("cephadm.services.osd.RemoveUtil.ok_to_stop")
157 def test_is_ok_to_stop(self
, _
, osd_obj
):
158 ret
= osd_obj
.is_ok_to_stop
159 osd_obj
.rm_util
.ok_to_stop
.assert_called_once()
161 @pytest.mark
.parametrize(
162 "pg_count, expected",
170 def test_is_empty(self
, osd_obj
, pg_count
, expected
):
171 with mock
.patch("cephadm.services.osd.OSD.get_pg_count", return_value
=pg_count
):
172 assert osd_obj
.is_empty
is expected
174 @mock.patch("cephadm.services.osd.RemoveUtil.safe_to_destroy")
175 def test_safe_to_destroy(self
, _
, osd_obj
):
176 ret
= osd_obj
.safe_to_destroy()
177 osd_obj
.rm_util
.safe_to_destroy
.assert_called_once()
179 @mock.patch("cephadm.services.osd.RemoveUtil.set_osd_flag")
180 def test_down(self
, _
, osd_obj
):
182 osd_obj
.rm_util
.set_osd_flag
.assert_called_with([osd_obj
], 'down')
184 @mock.patch("cephadm.services.osd.RemoveUtil.destroy_osd")
185 def test_destroy_osd(self
, _
, osd_obj
):
186 ret
= osd_obj
.destroy()
187 osd_obj
.rm_util
.destroy_osd
.assert_called_once()
189 @mock.patch("cephadm.services.osd.RemoveUtil.purge_osd")
190 def test_purge(self
, _
, osd_obj
):
191 ret
= osd_obj
.purge()
192 osd_obj
.rm_util
.purge_osd
.assert_called_once()
194 @mock.patch("cephadm.services.osd.RemoveUtil.get_pg_count")
195 def test_pg_count(self
, _
, osd_obj
):
196 ret
= osd_obj
.get_pg_count()
197 osd_obj
.rm_util
.get_pg_count
.assert_called_once()
199 def test_drain_status_human_not_started(self
, osd_obj
):
200 assert osd_obj
.drain_status_human() == 'not started'
202 def test_drain_status_human_started(self
, osd_obj
):
203 osd_obj
.started
= True
204 assert osd_obj
.drain_status_human() == 'started'
206 def test_drain_status_human_draining(self
, osd_obj
):
207 osd_obj
.started
= True
208 osd_obj
.draining
= True
209 assert osd_obj
.drain_status_human() == 'draining'
211 def test_drain_status_human_done(self
, osd_obj
):
212 osd_obj
.started
= True
213 osd_obj
.draining
= False
214 osd_obj
.drain_done_at
= datetime
.utcnow()
215 assert osd_obj
.drain_status_human() == 'done, waiting for purge'
218 class TestOSDRemovalQueue
:
220 def test_queue_size(self
, osd_obj
):
221 q
= OSDRemovalQueue(mock
.Mock())
222 assert q
.queue_size() == 0
224 assert q
.queue_size() == 1
226 @mock.patch("cephadm.services.osd.OSD.start")
227 @mock.patch("cephadm.services.osd.OSD.exists")
228 def test_enqueue(self
, exist
, start
, osd_obj
):
229 q
= OSDRemovalQueue(mock
.Mock())
231 osd_obj
.start
.assert_called_once()
233 @mock.patch("cephadm.services.osd.OSD.stop")
234 @mock.patch("cephadm.services.osd.OSD.exists")
235 def test_rm_raise(self
, exist
, stop
, osd_obj
):
236 q
= OSDRemovalQueue(mock
.Mock())
237 with pytest
.raises(KeyError):
239 osd_obj
.stop
.assert_called_once()
241 @mock.patch("cephadm.services.osd.OSD.stop")
242 @mock.patch("cephadm.services.osd.OSD.exists")
243 def test_rm(self
, exist
, stop
, osd_obj
):
244 q
= OSDRemovalQueue(mock
.Mock())
247 osd_obj
.stop
.assert_called_once()