From: Adam King Date: Mon, 5 Jun 2023 19:05:55 +0000 (-0400) Subject: mgr/cephadm: add ability to zap OSDs' devices while draining host X-Git-Tag: v17.2.8~458^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=686a44841fec9db387ab5b4c4e479b8fe8d538cd;p=ceph.git mgr/cephadm: add ability to zap OSDs' devices while draining host Currently, when cephadm drains a host, it will remove all OSDs on the host, but provides no option to zap the OSD's devices afterwards. Given users are draining the host likely to remove it from the cluster, it makes sense some users would want to clean up the devices on the host that were being used for OSDs. Cephadm already supports zapping devices outside of host draining, so it makes shouldn't take much to add that functionality to the host drain as well. Fixes: https://tracker.ceph.com/issues/61593 Signed-off-by: Adam King (cherry picked from commit 85043ff4cee108c152f5aa8af267c85e353c475a) --- diff --git a/doc/cephadm/host-management.rst b/doc/cephadm/host-management.rst index 5a5c838a9451..eb83efb24b95 100644 --- a/doc/cephadm/host-management.rst +++ b/doc/cephadm/host-management.rst @@ -132,6 +132,14 @@ progress of the OSD removal operation with the following command: See :ref:`cephadm-osd-removal` for more details about OSD removal. +The ``orch host drain`` command also supports a ``--zap-osd-devices`` +flag. Setting this flag while draining a host will cause cephadm to zap +the devices of the OSDs it is removing as part of the drain process + +.. prompt:: bash # + + ceph orch host drain ** --zap-osd-devices + Use the following command to determine whether any daemons are still on the host: diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index b8fdeba593fe..d3349235894f 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -3189,7 +3189,7 @@ Then run the following: return self.to_remove_osds.all_osds() @handle_orch_error - def drain_host(self, hostname: str, force: bool = False, keep_conf_keyring: bool = False) -> str: + def drain_host(self, hostname: str, force: bool = False, keep_conf_keyring: bool = False, zap_osd_devices: bool = False) -> str: """ Drain all daemons from a host. :param host: host name @@ -3215,7 +3215,7 @@ Then run the following: daemons: List[orchestrator.DaemonDescription] = self.cache.get_daemons_by_host(hostname) osds_to_remove = [d.daemon_id for d in daemons if d.daemon_type == 'osd'] - self.remove_osds(osds_to_remove) + self.remove_osds(osds_to_remove, zap=zap_osd_devices) daemons_table = "" daemons_table += "{:<20} {:<15}\n".format("type", "id") diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index 55a0dd02a36e..b7f074790100 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -2437,3 +2437,14 @@ Traceback (most recent call last): with pytest.raises(OrchestratorError, match=r'Command "very slow" timed out on host hostC \(non-default 999 second timeout\)'): with cephadm_module.async_timeout_handler('hostC', 'very slow', 999): cephadm_module.wait_async(_timeout()) + + @mock.patch("cephadm.CephadmOrchestrator.remove_osds") + @mock.patch("cephadm.CephadmOrchestrator.add_host_label", lambda *a, **kw: None) + @mock.patch("cephadm.inventory.HostCache.get_daemons_by_host", lambda *a, **kw: []) + def test_host_drain_zap(self, _rm_osds, cephadm_module): + # pass force=true in these tests to bypass _admin label check + cephadm_module.drain_host('host1', force=True, zap_osd_devices=False) + assert _rm_osds.called_with([], zap=False) + + cephadm_module.drain_host('host1', force=True, zap_osd_devices=True) + assert _rm_osds.called_with([], zap=True) diff --git a/src/pybind/mgr/orchestrator/_interface.py b/src/pybind/mgr/orchestrator/_interface.py index 02618d60db7a..f3ce2953e4e9 100644 --- a/src/pybind/mgr/orchestrator/_interface.py +++ b/src/pybind/mgr/orchestrator/_interface.py @@ -355,7 +355,7 @@ class Orchestrator(object): """ raise NotImplementedError() - def drain_host(self, hostname: str, force: bool = False, keep_conf_keyring: bool = False) -> OrchResult[str]: + def drain_host(self, hostname: str, force: bool = False, keep_conf_keyring: bool = False, zap_osd_devices: bool = False) -> OrchResult[str]: """ drain all daemons from a host diff --git a/src/pybind/mgr/orchestrator/module.py b/src/pybind/mgr/orchestrator/module.py index 3206827f4506..e6e09ca04f25 100644 --- a/src/pybind/mgr/orchestrator/module.py +++ b/src/pybind/mgr/orchestrator/module.py @@ -451,9 +451,9 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule, return HandleCommandResult(stdout=completion.result_str()) @_cli_write_command('orch host drain') - def _drain_host(self, hostname: str, force: bool = False, keep_conf_keyring: bool = False) -> HandleCommandResult: + def _drain_host(self, hostname: str, force: bool = False, keep_conf_keyring: bool = False, zap_osd_devices: bool = False) -> HandleCommandResult: """drain all daemons from a host""" - completion = self.drain_host(hostname, force, keep_conf_keyring) + completion = self.drain_host(hostname, force, keep_conf_keyring, zap_osd_devices) raise_if_exception(completion) return HandleCommandResult(stdout=completion.result_str())