From 64926f3da07b821ef394abb36321917327c82806 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 20 Apr 2021 18:18:46 -0400 Subject: [PATCH] mgr/cephadm: _write_remote_file helper This is careful is ownership, mode, and fsyncs before renaming into position. Signed-off-by: Sage Weil --- src/pybind/mgr/cephadm/remotes.py | 19 +++++++++++++++++++ src/pybind/mgr/cephadm/serve.py | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/pybind/mgr/cephadm/remotes.py b/src/pybind/mgr/cephadm/remotes.py index 0ad7006831d62..e1ecf2dcbe93b 100644 --- a/src/pybind/mgr/cephadm/remotes.py +++ b/src/pybind/mgr/cephadm/remotes.py @@ -26,6 +26,25 @@ def choose_python(): return None +def write_file(path: str, content: bytes, mode: int, uid: int, gid: int, + mkdir_p: bool = True) -> Optional[str]: + try: + if mkdir_p: + dirname = os.path.dirname(path) + if not os.path.exists(dirname): + os.makedirs(dirname) + tmp_path = path + '.new' + with open(tmp_path, 'wb') as f: + os.fchown(f.fileno(), uid, gid) + os.fchmod(f.fileno(), mode) + f.write(content) + os.fsync(f.fileno()) + os.rename(tmp_path, path) + except Exception as e: + return str(e) + return None + + if __name__ == '__channelexec__': for item in channel: # type: ignore # noqa: F821 channel.send(eval(item)) # type: ignore # noqa: F821 diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 69fbaff40601b..c1b9feca457be 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -1139,6 +1139,24 @@ class CephadmServe: self.log.warning(msg) raise OrchestratorError(msg) + def _write_remote_file(self, + host: str, + path: str, + content: bytes, + mode: int, + uid: int, + gid: int) -> None: + with self._remote_connection(host) as tpl: + conn, connr = tpl + try: + errmsg = connr.write_file(path, content, mode, uid, gid) + if errmsg is not None: + raise OrchestratorError(errmsg) + except Exception as e: + msg = f"Unable to write {host}:{path}: {e}" + self.log.warning(msg) + raise OrchestratorError(msg) + @contextmanager def _remote_connection(self, host: str, -- 2.39.5