[PATCH RFCv2 3/5] libssh2_transport: Add libssh2 session support to net client code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds a glue layer to enable using libssh2 code with the
network client code.

As in the original client implementation, shell code is sent to the
server to detect correct options for netcat.

*src/rpc/virnetclient.c:
*src/rpc/virnetclient.h: Add function to handle connection to a libvirt
                         daemon using the libssh2 transport.
---
 src/rpc/virnetclient.c |   91 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/rpc/virnetclient.h |   11 ++++++
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index 469c6a5..b0cb8d2 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -383,6 +383,72 @@ virNetClientPtr virNetClientNewSSH(const char *nodename,
     return virNetClientNew(sock, NULL);
 }

+virNetClientPtr virNetClientNewLibSSH(const char *host,
+                                      const char *port,
+                                      const char *username,
+                                      const char *password,
+                                      const char *netcat,
+                                      const char *socketPath,
+                                      const char *knownHostsFile,
+                                      const char *hostkeyVerify,
+                                      const char *privkey,
+                                      virConnectAuthPtr auth)
+{
+    virNetSocketPtr sock;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *nc = NULL;
+
+    if (!host)
+        host = "localhost";
+
+    if (!port)
+        port = "22";
+
+    if (!username)
+        username = "root";
+
+    if (netcat) {
+        virBufferEscapeShell(&buf, netcat);
+        nc = virBufferContentAndReset(&buf);
+    } else {
+        nc = strdup("nc");
+    }
+
+    if (!nc) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    virBufferAsprintf(&buf,
+         "sh -c "
+         "'if '%s' -q 2>&1 | grep \"requires an argument\" >/dev/null 2>&1; then "
+             "ARG=-q0;"
+         "else "
+             "ARG=;"
+         "fi;"
+         "'%s' $ARG -U %s'",
+         nc, nc, socketPath);
+
+    VIR_FREE(nc);
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    nc = virBufferContentAndReset(&buf);
+
+    if (virNetSocketNewConnectLibSSH(host, port, username, password, nc,
+                                     knownHostsFile, hostkeyVerify,
+                                     privkey, auth, &sock) != 0) {
+        VIR_FREE(nc);
+        return NULL;
+    }
+
+    VIR_FREE(nc);
+    return virNetClientNew(sock, NULL);
+}
+
 virNetClientPtr virNetClientNewExternal(const char **cmdargv)
 {
     virNetSocketPtr sock;
@@ -964,6 +1030,7 @@ virNetClientIOWriteMessage(virNetClientPtr client,
                            virNetClientCallPtr thecall)
 {
     ssize_t ret = 0;
+    virErrorPtr err;

     if (thecall->msg->bufferOffset < thecall->msg->bufferLength) {
         ret = virNetSocketWrite(client->sock,
@@ -971,8 +1038,18 @@ virNetClientIOWriteMessage(virNetClientPtr client,
                                 thecall->msg->bufferLength - thecall->msg->bufferOffset);
         if (ret > 0 || virNetSocketHasPendingData(client->sock))
             thecall->sentSomeData = true;
-        if (ret <= 0)
+        if (ret <= 0) {
+            if ((err = virGetLastError())) {
+                if (err->domain == VIR_FROM_LIBSSH &&
+                    err->code == VIR_ERR_LIBSSH_REMOTE_COMMAND) {
+                    virResetLastError();
+                    virNetError(VIR_ERR_LIBSSH_REMOTE_COMMAND,
+                                _("Remote daemon is not running or remote "
+                                  "command has failed"));
+                }
+            }
             return ret;
+        }

         thecall->msg->bufferOffset += ret;
     }
@@ -1637,6 +1714,7 @@ void virNetClientIncomingEvent(virNetSocketPtr sock,
                                void *opaque)
 {
     virNetClientPtr client = opaque;
+    virErrorPtr err;

     virNetClientLock(client);

@@ -1657,7 +1735,16 @@ void virNetClientIncomingEvent(virNetSocketPtr sock,
     }

     if (virNetClientIOHandleInput(client) < 0) {
-        VIR_WARN("Something went wrong during async message processing");
+        /* translate error message if we're using libssh transport */
+        if ((err = virGetLastError()) &&
+            (err->domain == VIR_FROM_LIBSSH &&
+             err->code == VIR_ERR_LIBSSH_REMOTE_COMMAND)) {
+                virNetError(VIR_ERR_NO_CONNECT, "%s",
+                            _("Remote daemon is not running or remote command "
+                              "has failed"));
+        } else {
+            VIR_WARN("Something went wrong during async message processing");
+        }
         virNetSocketRemoveIOCallback(sock);
     }

diff --git a/src/rpc/virnetclient.h b/src/rpc/virnetclient.h
index 61d51e1..9157852 100644
--- a/src/rpc/virnetclient.h
+++ b/src/rpc/virnetclient.h
@@ -49,6 +49,17 @@ virNetClientPtr virNetClientNewSSH(const char *nodename,
                                    const char *keyfile,
                                    const char *path);

+virNetClientPtr virNetClientNewLibSSH(const char *host,
+                                      const char *port,
+                                      const char *username,
+                                      const char *password,
+                                      const char *netcat,
+                                      const char *socketPath,
+                                      const char *knownHostsFile,
+                                      const char *hostkeyVerify,
+                                      const char *privkey,
+                                      virConnectAuthPtr auth);
+
 virNetClientPtr virNetClientNewExternal(const char **cmdargv);

 void virNetClientRef(virNetClientPtr client);
-- 
1.7.3.4

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]