This patch upgrades the send_fd_scm function to use it in way if not provide socket_scm_helper. It uses new provided functions _send_fds and _recv_fds that depend on FD's and data that allow us to send a file/socket descriptor (with access and permissions) from one process to another. The parameter data include qmp message like getfd or add-fd.
Signed-off-by: Oksana Vohchana <ovosh...@redhat.com> --- python/qemu/machine.py | 64 ++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 976316e5f5..906ca118db 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -179,20 +179,27 @@ class QEMUMachine(object): return sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", fds))]) - def send_fd_scm(self, fd=None, file_path=None): + def send_fd_scm(self, fd=None, file_path=None, data=None): """ - Send an fd or file_path to socket_scm_helper. + Can be used in two different cases. + Send an fd or file_path to socket_scm_helper or + provide data and fd to send it to the socket. - Exactly one of fd and file_path must be given. - If it is file_path, the helper will open that file and pass its own fd. + Exactly one of fd and file_path must be given to the case of + socket_scm_helper. If it is file_path, the helper will open that file + and pass its own fd. + + To second case need adds data that include a QMP request and fd """ # In iotest.py, the qmp should always use unix socket. assert self._qmp.is_scm_available() - if self._socket_scm_helper is None: - raise QEMUMachineError("No path to socket_scm_helper set") - if not os.path.exists(self._socket_scm_helper): - raise QEMUMachineError("%s does not exist" % - self._socket_scm_helper) + if data is None: + if self._socket_scm_helper is None: + raise QEMUMachineError( + "No path to socket_scm_helper set or data provided") + if not os.path.exists(self._socket_scm_helper): + raise QEMUMachineError("%s does not exist" % + self._socket_scm_helper) # This did not exist before 3.4, but since then it is # mandatory for our purpose @@ -201,24 +208,33 @@ class QEMUMachine(object): if fd is not None: os.set_inheritable(fd, True) - fd_param = ["%s" % self._socket_scm_helper, - "%d" % self._qmp.get_sock_fd()] + if data is None: + fd_param = ["%s" % self._socket_scm_helper, + "%d" % self._qmp.get_sock_fd()] + if file_path is not None: + assert fd is None + fd_param.append(file_path) + else: + assert fd is not None + fd_param.append(str(fd)) - if file_path is not None: - assert fd is None - fd_param.append(file_path) - else: - assert fd is not None - fd_param.append(str(fd)) + devnull = open(os.path.devnull, 'rb') + proc = subprocess.Popen(fd_param, stdin=devnull, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, close_fds=False) + output = proc.communicate()[0] + if output: + LOG.debug(output) - devnull = open(os.path.devnull, 'rb') - proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, close_fds=False) - output = proc.communicate()[0] - if output: - LOG.debug(output) + return proc.returncode - return proc.returncode + else: + sock_fd = socket.fromfd(self._qmp.get_sock_fd(), socket.AF_UNIX, + socket.SOCK_STREAM) + fds_param = [fd, self._qmp.get_sock_fd()] + self._send_fds(sock_fd, data, fds_param) + self._recv_fds(sock_fd) + return self @staticmethod def _remove_if_exists(path): -- 2.21.1