[libvirt] [PATCHv2 1/5] api: Add API to tunnel a guest channel via stream

John Eckersberg jeckersb at redhat.com
Wed Jan 2 15:38:50 UTC 2013


This patch adds a new API, virDomainOpenChannel, that uses streams to
connect to a virtio channel on a guest.  This creates a secure
communication channel between a guest and a libvirt client.

This behaves the same as virDomainOpenConsole, except on channels
instead of console/serial/parallel devices.
---
 include/libvirt/libvirt.h.in | 16 ++++++++++++
 src/driver.h                 |  7 +++++
 src/libvirt.c                | 61 ++++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms      |  5 ++++
 src/remote/remote_driver.c   |  1 +
 src/remote/remote_protocol.x |  9 ++++++-
 src/remote_protocol-structs  |  6 +++++
 7 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 2de6835..78262a2 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4547,6 +4547,22 @@ int virDomainOpenConsole(virDomainPtr dom,
                          virStreamPtr st,
                          unsigned int flags);
 
+/**
+ * virDomainChannelFlags
+ *
+ * Since 1.0.2
+ */
+typedef enum {
+    VIR_DOMAIN_CHANNEL_FORCE = (1 << 0), /* abort a (possibly) active channel
+                                            connection to force a new
+                                            connection */
+} virDomainChannelFlags;
+
+int virDomainOpenChannel(virDomainPtr dom,
+                         const char *name,
+                         virStreamPtr st,
+                         unsigned int flags);
+
 typedef enum {
     VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH = (1 << 0),
 } virDomainOpenGraphicsFlags;
diff --git a/src/driver.h b/src/driver.h
index 64d652f..01c95cf 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -717,6 +717,12 @@ typedef int
                                virStreamPtr st,
                                unsigned int flags);
 typedef int
+    (*virDrvDomainOpenChannel)(virDomainPtr dom,
+                               const char *name,
+                               virStreamPtr st,
+                               unsigned int flags);
+
+typedef int
     (*virDrvDomainOpenGraphics)(virDomainPtr dom,
                                 unsigned int idx,
                                 int fd,
@@ -1078,6 +1084,7 @@ struct _virDriver {
     virDrvDomainQemuAttach              qemuDomainAttach;
     virDrvDomainQemuAgentCommand        qemuDomainArbitraryAgentCommand;
     virDrvDomainOpenConsole             domainOpenConsole;
+    virDrvDomainOpenChannel             domainOpenChannel;
     virDrvDomainOpenGraphics            domainOpenGraphics;
     virDrvDomainInjectNMI               domainInjectNMI;
     virDrvDomainMigrateBegin3           domainMigrateBegin3;
diff --git a/src/libvirt.c b/src/libvirt.c
index bf674d1..6d1da12 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -19118,6 +19118,67 @@ error:
 }
 
 /**
+ * virDomainOpenChannel:
+ * @dom: a domain object
+ * @name: the channel name, or NULL
+ * @st: a stream to associate with the channel
+ * @flags: bitwise-OR of virDomainChannelFlags
+ *
+ * This opens the host interface associated with a channel device on a
+ * guest, if the host interface is supported.  If @name is given, it
+ * can match either the device alias (e.g. "channel0"), or the virtio
+ * target name (e.g. "org.qemu.guest_agent.0").  If @name is omitted,
+ * then the first channel is opened. The channel is associated with
+ * the passed in @st stream, which should have been opened in
+ * non-blocking mode for bi-directional I/O.
+ *
+ * By default, when @flags is 0, the open will fail if libvirt detects
+ * that the channel is already in use by another client; passing
+ * VIR_DOMAIN_CHANNEL_FORCE will cause libvirt to forcefully remove the
+ * other client prior to opening this channel.
+ *
+ * Returns 0 if the channel was opened, -1 on error
+ */
+int virDomainOpenChannel(virDomainPtr dom,
+                         const char *name,
+                         virStreamPtr st,
+                         unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(dom, "name=%s, st=%p, flags=%x",
+                     NULLSTR(name), st, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_DOMAIN(dom)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    conn = dom->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainOpenChannel) {
+        int ret;
+        ret = conn->driver->domainOpenChannel(dom, name, st, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(conn);
+    return -1;
+}
+
+/**
  * virDomainBlockJobAbort:
  * @dom: pointer to domain object
  * @disk: path to the block device, or device shorthand
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index e3d63d3..2107519 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -580,4 +580,9 @@ LIBVIRT_1.0.1 {
         virDomainSendProcessSignal;
 } LIBVIRT_1.0.0;
 
+LIBVIRT_1.0.2 {
+    global:
+        virDomainOpenChannel;
+} LIBVIRT_1.0.1;
+
 # .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index ae861cc..c078cb5 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6121,6 +6121,7 @@ static virDriver remote_driver = {
     .qemuDomainAttach = qemuDomainAttach, /* 0.9.4 */
     .qemuDomainArbitraryAgentCommand = qemuDomainAgentCommand, /* 0.10.0 */
     .domainOpenConsole = remoteDomainOpenConsole, /* 0.8.6 */
+    .domainOpenChannel = remoteDomainOpenChannel, /* 1.0.2 */
     .domainOpenGraphics = remoteDomainOpenGraphics, /* 0.9.7 */
     .domainInjectNMI = remoteDomainInjectNMI, /* 0.9.2 */
     .domainMigrateBegin3 = remoteDomainMigrateBegin3, /* 0.9.2 */
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index bdad9f0..9035776 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2439,6 +2439,12 @@ struct remote_domain_open_console_args {
     unsigned int flags;
 };
 
+struct remote_domain_open_channel_args {
+    remote_nonnull_domain dom;
+    remote_string name;
+    unsigned int flags;
+};
+
 struct remote_storage_vol_upload_args {
     remote_nonnull_storage_vol vol;
     unsigned hyper offset;
@@ -3042,7 +3048,8 @@ enum remote_procedure {
     REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK = 292, /* autogen autogen */
     REMOTE_PROC_NODE_GET_CPU_MAP = 293, /* skipgen skipgen */
     REMOTE_PROC_DOMAIN_FSTRIM = 294, /* autogen autogen */
-    REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL = 295 /* autogen autogen */
+    REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL = 295, /* autogen autogen */
+    REMOTE_PROC_DOMAIN_OPEN_CHANNEL = 296 /* autogen autogen | readstream at 2 */
 
     /*
      * Notice how the entries are grouped in sets of 10 ?
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index e7d05b8..91414d4 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -1873,6 +1873,11 @@ struct remote_domain_open_console_args {
         remote_string              dev_name;
         u_int                      flags;
 };
+struct remote_domain_open_channel_args {
+        remote_nonnull_domain      dom;
+        remote_string              name;
+        u_int                      flags;
+};
 struct remote_storage_vol_upload_args {
         remote_nonnull_storage_vol vol;
         uint64_t                   offset;
@@ -2447,4 +2452,5 @@ enum remote_procedure {
         REMOTE_PROC_NODE_GET_CPU_MAP = 293,
         REMOTE_PROC_DOMAIN_FSTRIM = 294,
         REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL = 295,
+        REMOTE_PROC_DOMAIN_OPEN_CHANNEL = 296,
 };
-- 
1.7.11.7




More information about the libvir-list mailing list