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
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list