From: Sage Weil Date: Tue, 20 Apr 2021 22:18:46 +0000 (-0400) Subject: mgr/cephadm: _write_remote_file helper X-Git-Tag: v16.2.5~39^2~4^2^2~15 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f663c418d73e8ce40a0975f7b1d409820335c363;p=ceph.git mgr/cephadm: _write_remote_file helper This is careful is ownership, mode, and fsyncs before renaming into position. Signed-off-by: Sage Weil (cherry picked from commit 64926f3da07b821ef394abb36321917327c82806) --- diff --git a/src/pybind/mgr/cephadm/remotes.py b/src/pybind/mgr/cephadm/remotes.py index 0ad7006831d6..e1ecf2dcbe93 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 b04877dd0ecf..cf722a8fc54d 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -1144,6 +1144,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,