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

Michal Privoznik mprivozn at redhat.com
Wed Jan 18 16:20:03 UTC 2012


On 04.01.2012 00:47, Peter Krempa wrote:
> 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);

I wonder if we can reuse the code from virNetSocketNewConnectSSH().
> +
> +    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);

Otherwise looking good.




More information about the libvir-list mailing list