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

[libvirt] Re: [PATCH] 4/7 host ("node") device enumeration - remote driver



This patch contains the remote implementation of node device
enumeration.

diff --git a/qemud/remote.c b/qemud/remote.c
index a623494..56d88a7 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -66,6 +66,7 @@ static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr do
 static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
 static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src);
 static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
+static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src);
 
 #include "remote_dispatch_prototypes.h"
 
@@ -3640,6 +3641,303 @@ remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUS
 }
 
 
+/***************************************************************
+ *     NODE INFO APIS
+ **************************************************************/
+
+static int
+remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                struct qemud_client *client,
+                                remote_message_header *req,
+                                remote_node_num_of_devices_args *args,
+                                remote_node_num_of_devices_ret *ret)
+{
+    CHECK_CONN(client);
+
+    ret->num = virNodeNumOfDevices (client->conn, args->flags);
+    if (ret->num == -1) return -1;
+
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeListDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
+                               struct qemud_client *client,
+                               remote_message_header *req,
+                               remote_node_list_devices_args *args,
+                               remote_node_list_devices_ret *ret)
+{
+    CHECK_CONN(client);
+
+    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
+        remoteDispatchError (client, req,
+                             "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
+        return -2;
+    }
+
+    /* Allocate return buffer. */
+    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
+        remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL);
+        return -2;
+    }
+
+    ret->names.names_len =
+        virNodeListDevices (client->conn,
+                            ret->names.names_val, args->maxnames, args->flags);
+    if (ret->names.names_len == -1) {
+        VIR_FREE(ret->names.names_val);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeNumOfDevicesByCap (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                     struct qemud_client *client,
+                                     remote_message_header *req,
+                                     remote_node_num_of_devices_by_cap_args *args,
+                                     remote_node_num_of_devices_by_cap_ret *ret)
+{
+    CHECK_CONN(client);
+
+    ret->num = virNodeNumOfDevicesByCap (client->conn, args->cap, args->flags);
+    if (ret->num == -1) return -1;
+
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeListDevicesByCap (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                    struct qemud_client *client,
+                                    remote_message_header *req,
+                                    remote_node_list_devices_by_cap_args *args,
+                                    remote_node_list_devices_by_cap_ret *ret)
+{
+    CHECK_CONN(client);
+
+    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
+        remoteDispatchError (client, req,
+                             "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
+        return -2;
+    }
+
+    /* Allocate return buffer. */
+    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
+        remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL);
+        return -2;
+    }
+
+    ret->names.names_len =
+        virNodeListDevicesByCap (client->conn, args->cap,
+                                 ret->names.names_val, args->maxnames,
+                                 args->flags);
+    if (ret->names.names_len == -1) {
+        VIR_FREE(ret->names.names_val);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                      struct qemud_client *client,
+                                      remote_message_header *req,
+                                      remote_node_device_lookup_by_name_args *args,
+                                      remote_node_device_lookup_by_name_ret *ret)
+{
+    virNodeDevicePtr dev;
+
+    CHECK_CONN(client);
+
+    dev = virNodeDeviceLookupByName (client->conn, args->name);
+    if (dev == NULL) return -1;
+
+    make_nonnull_node_device (&ret->dev, dev);
+    virNodeDeviceFree(dev);
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                 struct qemud_client *client,
+                                 remote_message_header *req,
+                                 remote_node_device_dump_xml_args *args,
+                                 remote_node_device_dump_xml_ret *ret)
+{
+    virNodeDevicePtr dev;
+    CHECK_CONN(client);
+
+    dev = virNodeDeviceLookupByName(client->conn, args->name);
+    if (dev == NULL) {
+        remoteDispatchError (client, req, "%s", _("node_device not found"));
+        return -2;
+    }
+
+    /* remoteDispatchClientRequest will free this. */
+    ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags);
+    if (!ret->xml) {
+        virNodeDeviceFree(dev);
+        return -1;
+    }
+    virNodeDeviceFree(dev);
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                   struct qemud_client *client,
+                                   remote_message_header *req,
+                                   remote_node_device_get_parent_args *args,
+                                   remote_node_device_get_parent_ret *ret)
+{
+    virNodeDevicePtr dev;
+    const char *parent;
+    CHECK_CONN(client);
+
+    dev = virNodeDeviceLookupByName(client->conn, args->name);
+    if (dev == NULL) {
+        remoteDispatchError (client, req, "%s", _("node_device not found"));
+        return -2;
+    }
+
+    parent = virNodeDeviceGetParent(dev);
+
+    if (parent == NULL) {
+        ret->parent = NULL;
+    } else {
+        /* remoteDispatchClientRequest will free this. */
+        char **parent_p;
+        if (VIR_ALLOC(parent_p) < 0) {
+            remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL);
+            return -2;
+        }
+        *parent_p = strdup(parent);
+        if (*parent_p == NULL) {
+            remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL);
+            return -2;
+        }
+        ret->parent = parent_p;
+    }
+
+    virNodeDeviceFree(dev);
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                   struct qemud_client *client,
+                                   remote_message_header *req,
+                                   remote_node_device_num_of_caps_args *args,
+                                   remote_node_device_num_of_caps_ret *ret)
+{
+    virNodeDevicePtr dev;
+    CHECK_CONN(client);
+
+    dev = virNodeDeviceLookupByName(client->conn, args->name);
+    if (dev == NULL) {
+        remoteDispatchError (client, req, "%s", _("node_device not found"));
+        return -2;
+    }
+
+    ret->num = virNodeDeviceNumOfCaps(dev);
+
+    virNodeDeviceFree(dev);
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                  struct qemud_client *client,
+                                  remote_message_header *req,
+                                  remote_node_device_list_caps_args *args,
+                                  remote_node_device_list_caps_ret *ret)
+{
+    virNodeDevicePtr dev;
+    CHECK_CONN(client);
+
+    dev = virNodeDeviceLookupByName(client->conn, args->name);
+    if (dev == NULL) {
+        remoteDispatchError (client, req, "%s", _("node_device not found"));
+        return -2;
+    }
+
+    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
+        remoteDispatchError (client, req,
+                             "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
+        return -2;
+    }
+
+    /* Allocate return buffer. */
+    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
+        remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL);
+        return -2;
+    }
+
+    ret->names.names_len =
+        virNodeDeviceListCaps (dev, ret->names.names_val,
+                               args->maxnames);
+    if (ret->names.names_len == -1) {
+        VIR_FREE(ret->names.names_val);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                struct qemud_client *client,
+                                remote_message_header *req,
+                                remote_node_device_create_args *args,
+                                remote_node_device_create_ret *ret)
+{
+    virNodeDevicePtr dev;
+
+    CHECK_CONN(client);
+
+    dev = virNodeDeviceCreate (client->conn, args->xml, args->flags);
+    if (dev == NULL) return -1;
+
+    make_nonnull_node_device (&ret->dev, dev);
+    virNodeDeviceFree(dev);
+    return 0;
+}
+
+
+static int
+remoteDispatchNodeDeviceDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                struct qemud_client *client,
+                                remote_message_header *req,
+                                remote_node_device_destroy_args *args,
+                                void *ret ATTRIBUTE_UNUSED)
+{
+    virNodeDevicePtr dev;
+    CHECK_CONN(client);
+
+    dev = virNodeDeviceLookupByName(client->conn, args->name);
+    if (dev == NULL) {
+        remoteDispatchError (client, req, "%s", _("node_device not found"));
+        return -2;
+    }
+
+    if (virNodeDeviceDestroy (dev, args->flags) < 0) {
+        virNodeDeviceFree(dev);
+        return -1;
+    }
+    virNodeDeviceFree(dev);
+    return 0;
+}
 /**************************
  * Async Events
  **************************/
@@ -3763,6 +4061,7 @@ remoteDispatchDomainEventSend (struct qemud_client *client,
     client->bufferLength = len;
     client->bufferOffset = 0;
 }
+
 /*----- Helpers. -----*/
 
 /* get_nonnull_domain and get_nonnull_network turn an on-wire
@@ -3833,3 +4132,9 @@ make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr
     vol_dst->name = strdup (vol_src->name);
     vol_dst->key = strdup (vol_src->key);
 }
+
+static void
+make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src)
+{
+    dev_dst->name = strdup(dev_src->name);
+}
diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x
index b7e41aa..f7fb4c2 100644
--- a/qemud/remote_protocol.x
+++ b/qemud/remote_protocol.x
@@ -86,6 +86,12 @@ const REMOTE_STORAGE_POOL_NAME_LIST_MAX = 256;
 /* Upper limit on lists of storage vol names. */
 const REMOTE_STORAGE_VOL_NAME_LIST_MAX = 1024;
 
+/* Upper limit on lists of node device names. */
+const REMOTE_NODE_DEVICE_NAME_LIST_MAX = 16384;
+
+/* Upper limit on lists of node device capabilities. */
+const REMOTE_NODE_DEVICE_CAPS_LIST_MAX = 16384;
+
 /* Upper limit on list of scheduler parameters. */
 const REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX = 16;
 
@@ -139,11 +145,17 @@ struct remote_nonnull_storage_vol {
     remote_nonnull_string key;
 };
 
+/* A node device which may not be NULL. */
+struct remote_nonnull_node_device {
+    remote_nonnull_string name;
+};
+
 /* A domain or network which may be NULL. */
 typedef remote_nonnull_domain *remote_domain;
 typedef remote_nonnull_network *remote_network;
 typedef remote_nonnull_storage_pool *remote_storage_pool;
 typedef remote_nonnull_storage_vol *remote_storage_vol;
+typedef remote_nonnull_node_device *remote_node_device;
 
 /* Error message. See <virterror.h> for explanation of fields. */
 
@@ -965,6 +977,100 @@ struct remote_storage_vol_get_path_ret {
     remote_nonnull_string name;
 };
 
+/* Node driver calls: */
+
+struct remote_node_num_of_devices_args {
+    unsigned flags;
+};
+
+struct remote_node_num_of_devices_ret {
+    int num;
+};
+
+struct remote_node_list_devices_args {
+    int maxnames;
+    unsigned flags;
+};
+
+struct remote_node_list_devices_ret {
+    remote_nonnull_string names<REMOTE_NODE_DEVICE_NAME_LIST_MAX>;
+};
+
+struct remote_node_num_of_devices_by_cap_args {
+    remote_nonnull_string cap;
+    unsigned flags;
+};
+
+struct remote_node_num_of_devices_by_cap_ret {
+    int num;
+};
+
+struct remote_node_list_devices_by_cap_args {
+    int maxnames;
+    remote_nonnull_string cap;
+    unsigned flags;
+};
+
+struct remote_node_list_devices_by_cap_ret {
+    remote_nonnull_string names<REMOTE_NODE_DEVICE_NAME_LIST_MAX>;
+};
+
+struct remote_node_device_lookup_by_name_args {
+    remote_nonnull_string name;
+};
+
+struct remote_node_device_lookup_by_name_ret {
+    remote_nonnull_node_device dev;
+};
+
+struct remote_node_device_dump_xml_args {
+    remote_nonnull_string name;
+    unsigned flags;
+};
+
+struct remote_node_device_dump_xml_ret {
+    remote_nonnull_string xml;
+};
+
+struct remote_node_device_get_parent_args {
+    remote_nonnull_string name;
+};
+
+struct remote_node_device_get_parent_ret {
+    remote_string parent;
+};
+
+struct remote_node_device_num_of_caps_args {
+    remote_nonnull_string name;
+};
+
+struct remote_node_device_num_of_caps_ret {
+    int num;
+};
+
+struct remote_node_device_list_caps_args {
+    remote_nonnull_string name;
+    int maxnames;
+};
+
+struct remote_node_device_list_caps_ret {
+    remote_nonnull_string names<REMOTE_NODE_DEVICE_CAPS_LIST_MAX>;
+};
+
+struct remote_node_device_create_args {
+    remote_nonnull_string xml;
+    unsigned flags;
+};
+
+struct remote_node_device_create_ret {
+    remote_nonnull_node_device dev;
+};
+
+struct remote_node_device_destroy_args {
+    remote_nonnull_string name;
+    unsigned flags;
+};
+
 /**
  * Events Register/Deregister:
  * It would seem rpcgen does not like both args, and ret
@@ -1109,7 +1215,19 @@ enum remote_procedure {
 
     REMOTE_PROC_DOMAIN_EVENTS_REGISTER = 105,
     REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER = 106,
-    REMOTE_PROC_DOMAIN_EVENT = 107
+    REMOTE_PROC_DOMAIN_EVENT = 107,
+    
+    REMOTE_PROC_NODE_NUM_OF_DEVICES = 108,
+    REMOTE_PROC_NODE_LIST_DEVICES = 109,
+    REMOTE_PROC_NODE_NUM_OF_DEVICES_BY_CAP = 110,
+    REMOTE_PROC_NODE_LIST_DEVICES_BY_CAP = 111,
+    REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME = 112,
+    REMOTE_PROC_NODE_DEVICE_DUMP_XML = 113,
+    REMOTE_PROC_NODE_DEVICE_CREATE = 114,
+    REMOTE_PROC_NODE_DEVICE_DESTROY = 115,
+    REMOTE_PROC_NODE_DEVICE_GET_PARENT = 116,
+    REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS = 117,
+    REMOTE_PROC_NODE_DEVICE_LIST_CAPS = 118
 };
 
 /* Custom RPC structure. */
diff --git a/src/remote_internal.c b/src/remote_internal.c
index a182de3..d2d3e53 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -132,6 +132,14 @@ struct private_data {
         return (retcode);                                               \
     }
 
+#define GET_NODE_PRIVATE(conn,retcode)                               \
+    struct private_data *priv = (struct private_data *) (conn)->nodePrivateData; \
+    if (!priv || priv->magic != MAGIC) {                                \
+        error (conn, VIR_ERR_INVALID_ARG,                               \
+               _("tried to use a closed or uninitialised handle"));     \
+        return (retcode);                                               \
+    }
+
 
 enum {
     REMOTE_CALL_IN_OPEN = 1,
@@ -161,6 +169,7 @@ static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domai
 static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
 static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool);
 static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol);
+static virNodeDevicePtr get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev);
 static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
 static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
 static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src);
@@ -3633,6 +3642,331 @@ remoteStorageVolGetPath (virStorageVolPtr vol)
 
 /*----------------------------------------------------------------------*/
 
+static virDrvOpenStatus remoteNodeDrvOpen(virConnectPtr conn,
+                                          xmlURIPtr uri ATTRIBUTE_UNUSED,
+                                          virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                                          int flags ATTRIBUTE_UNUSED)
+{
+    if (conn &&
+        conn->driver &&
+        STREQ (conn->driver->name, "remote")) {
+        /* If we're here, the remote driver is already
+         * in use due to a) a QEMU uri, or b) a remote
+         * URI. So we can re-use existing connection
+         */
+        conn->nodePrivateData = conn->privateData;
+        return VIR_DRV_OPEN_SUCCESS;
+    }
+
+    /* Decline open.  Will fallback to appropriate local node driver. */
+    return VIR_DRV_OPEN_DECLINED;
+}
+
+static int remoteNodeDrvClose(virConnectPtr conn)
+{
+    int ret = 0;
+    GET_NODE_PRIVATE (conn, -1);
+    if (priv->localUses) {
+        priv->localUses--;
+        if (!priv->localUses) {
+            ret = doRemoteClose(conn, priv);
+            VIR_FREE(priv);
+            conn->nodePrivateData = NULL;
+        }
+    }
+    return ret;
+}
+
+static int remoteNodeNumOfDevices(virConnectPtr conn,
+                                  unsigned int flags)
+{
+    remote_node_num_of_devices_args args;
+    remote_node_num_of_devices_ret ret;
+    GET_STORAGE_PRIVATE (conn, -1);
+
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NODE_NUM_OF_DEVICES,
+              (xdrproc_t) xdr_remote_node_num_of_devices_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_num_of_devices_ret, (char *) &ret) == -1)
+        return -1;
+
+    return ret.num;
+}
+
+
+static int remoteNodeListDevices(virConnectPtr conn,
+                                 char **const names,
+                                 int maxnames,
+                                 unsigned int flags)
+{
+    int i;
+    remote_node_list_devices_args args;
+    remote_node_list_devices_ret ret;
+    GET_STORAGE_PRIVATE (conn, -1);
+
+    if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
+        error (conn, VIR_ERR_RPC, _("too many device names requested"));
+        return -1;
+    }
+    args.maxnames = maxnames;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NODE_LIST_DEVICES,
+              (xdrproc_t) xdr_remote_node_list_devices_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret) == -1)
+        return -1;
+
+    if (ret.names.names_len > maxnames) {
+        error (conn, VIR_ERR_RPC, _("too many device names received"));
+        xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret);
+        return -1;
+    }
+
+    /* This call is caller-frees (although that isn't clear from
+     * the documentation).  However xdr_free will free up both the
+     * names and the list of pointers, so we have to strdup the
+     * names here.
+     */
+    for (i = 0; i < ret.names.names_len; ++i)
+        names[i] = strdup (ret.names.names_val[i]);
+
+    xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret);
+
+    return ret.names.names_len;
+}
+
+
+static int remoteNodeNumOfDevicesByCap(virConnectPtr conn,
+                                       const char *cap,
+                                       unsigned int flags)
+{
+    remote_node_num_of_devices_by_cap_args args;
+    remote_node_num_of_devices_by_cap_ret ret;
+    GET_STORAGE_PRIVATE (conn, -1);
+
+    args.cap = (char *)cap;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NODE_NUM_OF_DEVICES_BY_CAP,
+              (xdrproc_t) xdr_remote_node_num_of_devices_by_cap_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_num_of_devices_by_cap_ret, (char *) &ret) == -1)
+        return -1;
+
+    return ret.num;
+}
+
+static int remoteNodeListDevicesByCap(virConnectPtr conn,
+                                      const char *cap,
+                                      char **const names,
+                                      int maxnames,
+                                      unsigned int flags)
+{
+    int i;
+    remote_node_list_devices_by_cap_args args;
+    remote_node_list_devices_by_cap_ret ret;
+    GET_STORAGE_PRIVATE (conn, -1);
+
+    if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
+        error (conn, VIR_ERR_RPC, _("too many device names requested"));
+        return -1;
+    }
+    args.maxnames = maxnames;
+    args.cap = (char *)cap;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NODE_LIST_DEVICES_BY_CAP,
+              (xdrproc_t) xdr_remote_node_list_devices_by_cap_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_list_devices_by_cap_ret, (char *) &ret) == -1)
+        return -1;
+
+    if (ret.names.names_len > maxnames) {
+        error (conn, VIR_ERR_RPC, _("too many device names received"));
+        xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret);
+        return -1;
+    }
+
+    /* This call is caller-frees (although that isn't clear from
+     * the documentation).  However xdr_free will free up both the
+     * names and the list of pointers, so we have to strdup the
+     * names here.
+     */
+    for (i = 0; i < ret.names.names_len; ++i)
+        names[i] = strdup (ret.names.names_val[i]);
+
+    xdr_free ((xdrproc_t) xdr_remote_node_list_devices_by_cap_ret, (char *) &ret);
+
+    return ret.names.names_len;
+}
+
+static virNodeDevicePtr remoteNodeDeviceLookupByName(virConnectPtr conn,
+                                                     const char *name)
+{
+    remote_node_device_lookup_by_name_args args;
+    remote_node_device_lookup_by_name_ret ret;
+    virNodeDevicePtr dev;
+    GET_STORAGE_PRIVATE (conn, NULL);
+
+    args.name = (char *)name;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME,
+              (xdrproc_t) xdr_remote_node_device_lookup_by_name_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret) == -1)
+        return NULL;
+
+    dev = get_nonnull_node_device(conn, ret.dev);
+
+    xdr_free ((xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret);
+
+    return dev;
+}
+
+static char *remoteNodeDeviceDumpXML(virNodeDevicePtr dev,
+                                     unsigned int flags)
+{
+    remote_node_device_dump_xml_args args;
+    remote_node_device_dump_xml_ret ret;
+    GET_STORAGE_PRIVATE (dev->conn, NULL);
+
+    args.name = dev->name;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DUMP_XML,
+              (xdrproc_t) xdr_remote_node_device_dump_xml_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_device_dump_xml_ret, (char *) &ret) == -1)
+        return NULL;
+
+    /* Caller frees. */
+    return ret.xml;
+}
+
+static char *remoteNodeDeviceGetParent(virNodeDevicePtr dev)
+{
+    remote_node_device_get_parent_args args;
+    remote_node_device_get_parent_ret ret;
+    GET_STORAGE_PRIVATE (dev->conn, NULL);
+
+    args.name = dev->name;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_GET_PARENT,
+              (xdrproc_t) xdr_remote_node_device_get_parent_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_device_get_parent_ret, (char *) &ret) == -1)
+        return NULL;
+
+    /* Caller frees. */
+    return ret.parent ? *ret.parent : NULL;
+}
+
+static int remoteNodeDeviceNumOfCaps(virNodeDevicePtr dev)
+{
+    remote_node_device_num_of_caps_args args;
+    remote_node_device_num_of_caps_ret ret;
+    GET_STORAGE_PRIVATE (dev->conn, -1);
+
+    args.name = dev->name;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS,
+              (xdrproc_t) xdr_remote_node_device_num_of_caps_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_device_num_of_caps_ret, (char *) &ret) == -1)
+        return -1;
+
+    return ret.num;
+}
+
+static int remoteNodeDeviceListCaps(virNodeDevicePtr dev,
+                                    char **const names,
+                                    int maxnames)
+{
+    int i;
+    remote_node_device_list_caps_args args;
+    remote_node_device_list_caps_ret ret;
+    GET_STORAGE_PRIVATE (dev->conn, -1);
+
+    if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) {
+        error (dev->conn, VIR_ERR_RPC, _("too many capability names requested"));
+        return -1;
+    }
+    args.maxnames = maxnames;
+    args.name = dev->name;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LIST_CAPS,
+              (xdrproc_t) xdr_remote_node_device_list_caps_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret) == -1)
+        return -1;
+
+    if (ret.names.names_len > maxnames) {
+        error (dev->conn, VIR_ERR_RPC, _("too many capability names received"));
+        xdr_free ((xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret);
+        return -1;
+    }
+
+    /* This call is caller-frees (although that isn't clear from
+     * the documentation).  However xdr_free will free up both the
+     * names and the list of pointers, so we have to strdup the
+     * names here.
+     */
+    for (i = 0; i < ret.names.names_len; ++i)
+        names[i] = strdup (ret.names.names_val[i]);
+
+    xdr_free ((xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret);
+
+    return ret.names.names_len;
+}
+
+static virNodeDevicePtr remoteNodeDeviceCreate(virConnectPtr conn,
+                                               const char *xml,
+                                               unsigned int flags)
+{
+    remote_node_device_create_args args;
+    remote_node_device_create_ret ret;
+    virNodeDevicePtr dev;
+    GET_STORAGE_PRIVATE (conn, NULL);
+
+    args.xml = (char *)xml;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NODE_DEVICE_CREATE,
+              (xdrproc_t) xdr_remote_node_device_create_args, (char *) &args,
+              (xdrproc_t) xdr_remote_node_device_create_ret, (char *) &ret) == -1)
+        return NULL;
+
+    dev = get_nonnull_node_device(conn, ret.dev);
+
+    xdr_free ((xdrproc_t) xdr_remote_node_device_create_ret, (char *) &ret);
+
+    return dev;
+}
+
+static int remoteNodeDeviceDestroy(virNodeDevicePtr dev,
+                                   unsigned int flags)
+{
+    remote_node_device_destroy_args args;
+    GET_STORAGE_PRIVATE (dev->conn, -1);
+
+    args.name = dev->name;
+    args.flags = flags;
+
+    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DESTROY,
+              (xdrproc_t) xdr_remote_node_device_destroy_args, (char *) &args,
+              (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        return -1;
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+
 static int
 remoteAuthenticate (virConnectPtr conn, struct private_data *priv, int in_open,
                     virConnectAuthPtr auth
@@ -4890,6 +5224,12 @@ get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol)
     return virGetStorageVol (conn, vol.pool, vol.name, vol.key);
 }
 
+static virNodeDevicePtr
+get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev)
+{
+    return virGetNodeDevice(conn, dev.name);
+}
+
 /* Make remote_nonnull_domain and remote_nonnull_network. */
 static void
 make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
@@ -5044,6 +5384,24 @@ static virStorageDriver storage_driver = {
     .volGetPath = remoteStorageVolGetPath,
 };
 
+static virNodeDriver node_driver = {
+    .name = "remote",
+    .open = remoteNodeDrvOpen,
+    .close = remoteNodeDrvClose,
+    .numOfDevices = remoteNodeNumOfDevices,
+    .listDevices = remoteNodeListDevices,
+    .numOfDevicesByCap = remoteNodeNumOfDevicesByCap,
+    .listDevicesByCap = remoteNodeListDevicesByCap,
+    .deviceLookupByName = remoteNodeDeviceLookupByName,
+    .deviceDumpXML = remoteNodeDeviceDumpXML,
+    .deviceCreate = remoteNodeDeviceCreate,
+    .deviceDestroy = remoteNodeDeviceDestroy,
+    .deviceGetParent = remoteNodeDeviceGetParent,
+    .deviceNumOfCaps = remoteNodeDeviceNumOfCaps,
+    .deviceListCaps = remoteNodeDeviceListCaps,
+};
+
+
 #ifdef WITH_LIBVIRTD
 static virStateDriver state_driver = {
     .initialize = remoteStartup,
@@ -5063,6 +5421,7 @@ remoteRegister (void)
     if (virRegisterDriver (&driver) == -1) return -1;
     if (virRegisterNetworkDriver (&network_driver) == -1) return -1;
     if (virRegisterStorageDriver (&storage_driver) == -1) return -1;
+    if (virRegisterNodeDriver (&node_driver) == -1) return -1;
 #ifdef WITH_LIBVIRTD
     if (virRegisterStateDriver (&state_driver) == -1) return -1;
 #endif

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