[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