This patch contains additions to the internal API for host device enumeration.
diff --git a/src/hash.c b/src/hash.c index 0a5bdcd..424c4a7 100644 --- a/src/hash.c +++ b/src/hash.c @@ -687,6 +687,9 @@ virGetConnect(void) { ret->storageVols = virHashCreate(20); if (ret->storageVols == NULL) goto failed; + ret->nodeDevices = virHashCreate(256); + if (ret->nodeDevices == NULL) + goto failed; pthread_mutex_init(&ret->lock, NULL); @@ -703,6 +706,8 @@ failed: virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName); if (ret->storageVols != NULL) virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName); + if (ret->nodeDevices != NULL) + virHashFree(ret->nodeDevices, (virHashDeallocator) virNodeDeviceFree); pthread_mutex_destroy(&ret->lock); VIR_FREE(ret); @@ -730,6 +735,8 @@ virReleaseConnect(virConnectPtr conn) { virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName); if (conn->storageVols != NULL) virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName); + if (conn->nodeDevices != NULL) + virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree); virResetError(&conn->err); if (__lastErr.conn == conn) @@ -1318,3 +1325,126 @@ virUnrefStorageVol(virStorageVolPtr vol) { pthread_mutex_unlock(&vol->conn->lock); return (refs); } + + +/** + * virGetNodeDevice: + * @conn: the hypervisor connection + * @name: device name (unique on node) + * + * Lookup if the device is already registered for that connection, + * if yes return a new pointer to it, if no allocate a new structure, + * and register it in the table. In any case a corresponding call to + * virFreeNodeDevice() is needed to not leak data. + * + * Returns a pointer to the node device, or NULL in case of failure + */ +virNodeDevicePtr +__virGetNodeDevice(virConnectPtr conn, const char *name) +{ + virNodeDevicePtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL)) { + virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + pthread_mutex_lock(&conn->lock); + + ret = (virNodeDevicePtr) virHashLookup(conn->nodeDevices, name); + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virHashError(conn, VIR_ERR_NO_MEMORY, _("allocating node dev")); + goto error; + } + ret->magic = VIR_NODE_DEVICE_MAGIC; + ret->conn = conn; + ret->name = strdup(name); + if (ret->name == NULL) { + virHashError(conn, VIR_ERR_NO_MEMORY, _("copying node dev name")); + goto error; + } + + if (virHashAddEntry(conn->nodeDevices, name, ret) < 0) { + virHashError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to add node dev to conn hash table")); + goto error; + } + conn->refs++; + } + ret->refs++; + pthread_mutex_unlock(&conn->lock); + return(ret); + +error: + pthread_mutex_unlock(&conn->lock); + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret); + } + return(NULL); +} + + +/** + * virReleaseNodeDevice: + * @dev: the dev to release + * + * Unconditionally release all memory associated with a dev. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The dev obj must not + * be used once this method returns. + * + * It will also unreference the associated connection object, + * which may also be released if its ref count hits zero. + */ +static void +virReleaseNodeDevice(virNodeDevicePtr dev) { + virConnectPtr conn = dev->conn; + DEBUG("release dev %p %s", dev, dev->name); + + if (virHashRemoveEntry(conn->nodeDevices, dev->name, NULL) < 0) + virHashError(conn, VIR_ERR_INTERNAL_ERROR, + _("dev missing from connection hash table")); + + dev->magic = -1; + VIR_FREE(dev->name); + VIR_FREE(dev); + + DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + + pthread_mutex_unlock(&conn->lock); +} + + +/** + * virUnrefNodeDevice: + * @dev: the dev to unreference + * + * Unreference the dev. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefNodeDevice(virNodeDevicePtr dev) { + int refs; + + pthread_mutex_lock(&dev->conn->lock); + DEBUG("unref dev %p %s %d", dev, dev->name, dev->refs); + dev->refs--; + refs = dev->refs; + if (refs == 0) { + virReleaseNodeDevice(dev); + /* Already unlocked mutex */ + return (0); + } + + pthread_mutex_unlock(&dev->conn->lock); + return (refs); +} diff --git a/src/internal.h b/src/internal.h index 7ea1586..02aa343 100644 --- a/src/internal.h +++ b/src/internal.h @@ -37,6 +37,7 @@ #include "libvirt/libvirt.h" #include "libvirt/virterror.h" #include "driver.h" +#include "node_device.h" /* On architectures which lack these limits, define them (ie. Cygwin). * Note that the libvirt code should be robust enough to handle the @@ -191,6 +192,16 @@ extern int debugFlag; #define VIR_IS_STORAGE_VOL(obj) ((obj) && (obj)->magic==VIR_STORAGE_VOL_MAGIC) #define VIR_IS_CONNECTED_STORAGE_VOL(obj) (VIR_IS_STORAGE_VOL(obj) && VIR_IS_CONNECT((obj)->conn)) +/** + * VIR_NODE_DEVICE_MAGIC: + * + * magic value used to protect the API when pointers to storage vol structures + * are passed down by the users. + */ +#define VIR_NODE_DEVICE_MAGIC 0xDEAD5679 +#define VIR_IS_NODE_DEVICE(obj) ((obj) && (obj)->magic==VIR_NODE_DEVICE_MAGIC) +#define VIR_IS_CONNECTED_NODE_DEVICE(obj) (VIR_IS_NODE_DEVICE(obj) && VIR_IS_CONNECT((obj)->conn)) + /* * arbitrary limitations */ @@ -211,6 +222,7 @@ struct _virConnect { virDriverPtr driver; virNetworkDriverPtr networkDriver; virStorageDriverPtr storageDriver; + virNodeDriverPtr nodeDriver; /* Private data pointer which can be used by driver and * network driver as they wish. @@ -219,6 +231,7 @@ struct _virConnect { void * privateData; void * networkPrivateData; void * storagePrivateData; + void * nodePrivateData; /* Per-connection error. */ virError err; /* the last error */ @@ -236,6 +249,7 @@ struct _virConnect { virHashTablePtr networks; /* hash table for known domains */ virHashTablePtr storagePools;/* hash table for known storage pools */ virHashTablePtr storageVols;/* hash table for known storage vols */ + virHashTablePtr nodeDevices; /* hash table for known node devices */ int refs; /* reference count */ }; @@ -295,6 +309,19 @@ struct _virStorageVol { }; +/** + * _virNodeDevice: + * + * Internal structure associated with a node device + */ +struct _virNodeDevice { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *name; /* device name (unique on node) */ +}; + + /************************************************************************ * * * API for error handling * @@ -346,11 +373,15 @@ virStorageVolPtr __virGetStorageVol (virConnectPtr conn, const char *name, const char *key); int virUnrefStorageVol (virStorageVolPtr vol); +virNodeDevicePtr __virGetNodeDevice (virConnectPtr conn, + const char *name); +int virUnrefNodeDevice (virNodeDevicePtr dev); #define virGetDomain(c,n,u) __virGetDomain((c),(n),(u)) #define virGetNetwork(c,n,u) __virGetNetwork((c),(n),(u)) #define virGetStoragePool(c,n,u) __virGetStoragePool((c),(n),(u)) #define virGetStorageVol(c,p,n,u) __virGetStorageVol((c),(p),(n),(u)) +#define virGetNodeDevice(c,n) __virGetNodeDevice((c),(n)) #ifdef WITH_LIBVIRTD int __virStateInitialize(void); diff --git a/src/node_device_conf.c b/src/node_device_conf.c new file mode 100644 index 0000000..f27167c --- /dev/null +++ b/src/node_device_conf.c @@ -0,0 +1,443 @@ +/* + * node_device_conf.c: config handling for node devices + * + * Copyright (C) 2008 Virtual Iron Software, Inc. + * Copyright (C) 2008 David F. Lively + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: David F. Lively <dlively@xxxxxxxxxxxxxxx> + */ + +#include <config.h> + +#include <unistd.h> +#include <errno.h> + +#include "internal.h" +#include "memory.h" + +#include "node_device_conf.h" +#include "memory.h" +#include "xml.h" +#include "util.h" +#include "buf.h" +#include "uuid.h" + + +VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST, + "system", + "pci", + "usb_device", + "usb", + "net", + "block", + "scsi_host", + "scsi", + "storage"); + +VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST, + "80203", + "80211"); + + +#define virNodeDeviceLog(msg...) fprintf(stderr, msg) + +void +virNodeDeviceReportError(virConnectPtr conn, int code, const char *fmt, ...) { + va_list args; + char errorMessage[1024]; + + if (fmt) { + va_start(args, fmt); + vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args); + va_end(args); + } else { + errorMessage[0] = '\0'; + } + virNodeDeviceLog("%s", errorMessage); + __virRaiseError(conn, NULL, NULL, VIR_FROM_NODE, code, VIR_ERR_ERROR, + NULL, NULL, NULL, -1, -1, "%s", errorMessage); +} + + +virNodeDeviceObjPtr virNodeDeviceFindByName(const virNodeDeviceObjListPtr devs, + const char *name) +{ + unsigned int i; + + for (i = 0; i < devs->count; i++) + if (STREQ(devs->objs[i]->def->name, name)) + return devs->objs[i]; + + return NULL; +} + + +void virNodeDeviceDefFree(virNodeDeviceDefPtr def) +{ + virNodeDevCapsDefPtr caps; + + if (!def) + return; + + VIR_FREE(def->name); + VIR_FREE(def->parent); + + caps = def->caps; + while (caps) { + virNodeDevCapsDefPtr next = caps->next; + virNodeDevCapsDefFree(caps); + caps = next; + } + + VIR_FREE(def); +} + +void virNodeDeviceObjFree(virNodeDeviceObjPtr dev) +{ + if (!dev) + return; + + virNodeDeviceDefFree(dev->def); + if (dev->privateFree) + (*dev->privateFree)(dev->privateData); + + VIR_FREE(dev); +} + +void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs) +{ + unsigned int i; + for (i = 0 ; i < devs->count ; i++) + virNodeDeviceObjFree(devs->objs[i]); + VIR_FREE(devs->objs); + devs->count = 0; +} + +virNodeDeviceObjPtr virNodeDeviceAssignDef(virConnectPtr conn, + virNodeDeviceObjListPtr devs, + const virNodeDeviceDefPtr def) +{ + virNodeDeviceObjPtr device; + + if ((device = virNodeDeviceFindByName(devs, def->name))) { + virNodeDeviceDefFree(device->def); + device->def = def; + return device; + } + + if (VIR_ALLOC(device) < 0) { + virNodeDeviceReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + device->def = def; + + if (VIR_REALLOC_N(devs->objs, devs->count+1) < 0) { + device->def = NULL; + virNodeDeviceObjFree(device); + virNodeDeviceReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + devs->objs[devs->count++] = device; + + return device; + +} + +void virNodeDeviceObjRemove(virNodeDeviceObjListPtr devs, + const virNodeDeviceObjPtr dev) +{ + unsigned int i; + + for (i = 0; i < devs->count; i++) { + if (devs->objs[i] == dev) { + virNodeDeviceObjFree(devs->objs[i]); + + if (i < (devs->count - 1)) + memmove(devs->objs + i, devs->objs + i + 1, + sizeof(*(devs->objs)) * (devs->count - (i + 1))); + + if (VIR_REALLOC_N(devs->objs, devs->count - 1) < 0) { + ; /* Failure to reduce memory allocation isn't fatal */ + } + devs->count--; + + break; + } + } +} + +char *virNodeDeviceDefFormat(virConnectPtr conn, + const virNodeDeviceDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virNodeDevCapsDefPtr caps = def->caps; + char *tmp; + + virBufferAddLit(&buf, "<device>\n"); + virBufferEscapeString(&buf, " <name>%s</name>\n", def->name); + + if (def->parent) + virBufferEscapeString(&buf, " <parent>%s</parent>\n", def->parent); + + for (caps = def->caps; caps; caps = caps->next) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + union _virNodeDevCapData *data = &caps->data; + + virBufferVSprintf(&buf, " <capability type='%s'>\n", + virNodeDevCapTypeToString(caps->type)); + switch (caps->type) { + case VIR_NODE_DEV_CAP_SYSTEM: + if (data->system.product_name) + virBufferEscapeString(&buf, " <product>%s</product>\n", + data->system.product_name); + virBufferAddLit(&buf, " <hardware>\n"); + if (data->system.hardware.vendor_name) + virBufferEscapeString(&buf, " <vendor>%s</vendor>\n", + data->system.hardware.vendor_name); + if (data->system.hardware.version) + virBufferEscapeString(&buf, " <version>%s</version>\n", + data->system.hardware.version); + if (data->system.hardware.serial) + virBufferEscapeString(&buf, " <serial>%s</serial>\n", + data->system.hardware.serial); + virUUIDFormat(data->system.hardware.uuid, uuidstr); + virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); + virBufferAddLit(&buf, " </hardware>\n"); + virBufferAddLit(&buf, " <firmware>\n"); + if (data->system.firmware.vendor_name) + virBufferEscapeString(&buf, " <vendor>%s</vendor>\n", + data->system.firmware.vendor_name); + if (data->system.firmware.version) + virBufferEscapeString(&buf, " <version>%s</version>\n", + data->system.firmware.version); + if (data->system.firmware.release_date) + virBufferEscapeString(&buf, + " <release_date>%s</release_date>\n", + data->system.firmware.release_date); + virBufferAddLit(&buf, " </firmware>\n"); + break; + case VIR_NODE_DEV_CAP_PCI_DEV: + virBufferVSprintf(&buf, " <domain>%d</domain>\n", + data->pci_dev.domain); + virBufferVSprintf(&buf, " <bus>%d</bus>\n", data->pci_dev.bus); + virBufferVSprintf(&buf, " <slot>%d</slot>\n", + data->pci_dev.slot); + virBufferVSprintf(&buf, " <function>%d</function>\n", + data->pci_dev.function); + virBufferVSprintf(&buf, " <product id='%d'", + data->pci_dev.product); + if (data->pci_dev.product_name) + virBufferEscapeString(&buf, ">%s</product>\n", + data->pci_dev.product_name); + else + virBufferAddLit(&buf, " />\n"); + virBufferVSprintf(&buf, " <vendor id='%d'", + data->pci_dev.vendor); + if (data->pci_dev.vendor_name) + virBufferEscapeString(&buf, ">%s</vendor>\n", + data->pci_dev.vendor_name); + else + virBufferAddLit(&buf, " />\n"); + break; + case VIR_NODE_DEV_CAP_USB_DEV: + virBufferVSprintf(&buf, " <bus>%d</bus>\n", data->usb_dev.bus); + virBufferVSprintf(&buf, " <device>%d</device>\n", + data->usb_dev.device); + virBufferVSprintf(&buf, " <product id='%d'", + data->usb_dev.product); + if (data->usb_dev.product_name) + virBufferEscapeString(&buf, ">%s</product>\n", + data->usb_dev.product_name); + else + virBufferAddLit(&buf, " />\n"); + virBufferVSprintf(&buf, " <vendor id='%d'", + data->usb_dev.vendor); + if (data->usb_dev.vendor_name) + virBufferEscapeString(&buf, ">%s</vendor>\n", + data->usb_dev.vendor_name); + else + virBufferAddLit(&buf, " />\n"); + break; + case VIR_NODE_DEV_CAP_USB_INTERFACE: + virBufferVSprintf(&buf, " <number>%d</number>\n", + data->usb_if.number); + virBufferVSprintf(&buf, " <class>%d</class>\n", + data->usb_if._class); + virBufferVSprintf(&buf, " <subclass>%d</subclass>\n", + data->usb_if.subclass); + virBufferVSprintf(&buf, " <protocol>%d</protocol>\n", + data->usb_if.protocol); + if (data->usb_if.description) + virBufferVSprintf(&buf, " <description>%s</description>\n", + data->usb_if.description); + break; + case VIR_NODE_DEV_CAP_NET: + virBufferVSprintf(&buf, " <interface>%s</interface>\n", + data->net.interface); + if (data->net.address) + virBufferVSprintf(&buf, " <address>%s</address>\n", + data->net.address); + if (data->net.subtype != VIR_NODE_DEV_CAP_NET_LAST) { + const char *subtyp = + virNodeDevNetCapTypeToString(data->net.subtype); + virBufferVSprintf(&buf, " <capability type='%s'>\n", subtyp); + switch (data->net.subtype) { + case VIR_NODE_DEV_CAP_NET_80203: + virBufferVSprintf(&buf, + " <mac_address>%012llx</address>\n", + data->net.data.ieee80203.mac_address); + break; + case VIR_NODE_DEV_CAP_NET_80211: + virBufferVSprintf(&buf, + " <mac_address>%012llx</address>\n", + data->net.data.ieee80211.mac_address); + break; + case VIR_NODE_DEV_CAP_NET_LAST: + /* Keep dumb compiler happy */ + break; + } + virBufferAddLit(&buf, " </capability>\n"); + } + break; + case VIR_NODE_DEV_CAP_BLOCK: + virBufferVSprintf(&buf, " <device>%s</device>\n", + data->block.device); + break; + case VIR_NODE_DEV_CAP_SCSI_HOST: + virBufferVSprintf(&buf, " <host>%d</host>\n", + data->scsi_host.host); + break; + case VIR_NODE_DEV_CAP_SCSI: + virBufferVSprintf(&buf, " <host>%d</host>\n", data->scsi.host); + virBufferVSprintf(&buf, " <bus>%d</bus>\n", data->scsi.bus); + virBufferVSprintf(&buf, " <target>%d</target>\n", + data->scsi.target); + virBufferVSprintf(&buf, " <lun>%d</lun>\n", data->scsi.lun); + if (data->scsi.type) + virBufferVSprintf(&buf, " <type>%s</type>\n", + data->scsi.type); + break; + case VIR_NODE_DEV_CAP_STORAGE: + if (data->storage.bus) + virBufferVSprintf(&buf, " <bus>%s</bus>\n", + data->storage.bus); + if (data->storage.drive_type) + virBufferVSprintf(&buf, " <drive_type>%s</drive_type>\n", + data->storage.drive_type); + if (data->storage.originating_device) + virBufferVSprintf(&buf, + " <originating_device>%s" + "</originating_device>\n", + data->storage.originating_device); + if (data->storage.model) + virBufferVSprintf(&buf, " <model>%s</model>\n", + data->storage.model); + if (data->storage.vendor) + virBufferVSprintf(&buf, " <vendor>%s</vendor>\n", + data->storage.vendor); + if (data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_REMOVABLE) { + int avl = data->storage.flags & + VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE; + virBufferAddLit(&buf, " <capability type='removable'>\n"); + virBufferVSprintf(&buf, + " <media_available>%d" + "</media_available>\n", avl ? 1 : 0); + virBufferVSprintf(&buf, " <media_size>%llu</media_size>\n", + data->storage.removable_media_size); + virBufferAddLit(&buf, " </capability>\n"); + } else { + virBufferVSprintf(&buf, " <size>%llu</size>\n", + data->storage.size); + } + if (data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_HOTPLUGGABLE) + virBufferAddLit(&buf, + " <capability type='hotpluggable' />\n"); + break; + case VIR_NODE_DEV_CAP_LAST: + /* ignore special LAST value */ + break; + } + + virBufferAddLit(&buf, " </capability>\n"); + } + + virBufferAddLit(&buf, "</device>\n"); + + if (virBufferError(&buf)) + goto no_memory; + + return virBufferContentAndReset(&buf); + + no_memory: + virNodeDeviceReportError(conn, VIR_ERR_NO_MEMORY, NULL); + tmp = virBufferContentAndReset(&buf); + VIR_FREE(tmp); + return NULL; +} + +void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) +{ + union _virNodeDevCapData *data = &caps->data; + + switch (caps->type) { + case VIR_NODE_DEV_CAP_SYSTEM: + VIR_FREE(data->system.product_name); + VIR_FREE(data->system.hardware.vendor_name); + VIR_FREE(data->system.hardware.version); + VIR_FREE(data->system.hardware.serial); + VIR_FREE(data->system.firmware.vendor_name); + VIR_FREE(data->system.firmware.version); + VIR_FREE(data->system.firmware.release_date); + break; + case VIR_NODE_DEV_CAP_PCI_DEV: + VIR_FREE(data->pci_dev.product_name); + VIR_FREE(data->pci_dev.vendor_name); + break; + case VIR_NODE_DEV_CAP_USB_DEV: + VIR_FREE(data->usb_dev.product_name); + VIR_FREE(data->usb_dev.vendor_name); + break; + case VIR_NODE_DEV_CAP_USB_INTERFACE: + VIR_FREE(data->usb_if.description); + break; + case VIR_NODE_DEV_CAP_NET: + VIR_FREE(data->net.interface); + VIR_FREE(data->net.address); + break; + case VIR_NODE_DEV_CAP_BLOCK: + VIR_FREE(data->block.device); + break; + case VIR_NODE_DEV_CAP_SCSI_HOST: + break; + case VIR_NODE_DEV_CAP_SCSI: + VIR_FREE(data->scsi.type); + break; + case VIR_NODE_DEV_CAP_STORAGE: + VIR_FREE(data->storage.bus); + VIR_FREE(data->storage.drive_type); + VIR_FREE(data->storage.model); + VIR_FREE(data->storage.vendor); + break; + case VIR_NODE_DEV_CAP_LAST: + /* This case is here to shutup the compiler */ + break; + } + + VIR_FREE(caps); +} + diff --git a/src/node_device_conf.h b/src/node_device_conf.h new file mode 100644 index 0000000..8c29973 --- /dev/null +++ b/src/node_device_conf.h @@ -0,0 +1,205 @@ +/* + * node_device_conf.h: config handling for node devices + * + * Copyright (C) 2008 Virtual Iron Software, Inc. + * Copyright (C) 2008 David F. Lively + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: David F. Lively <dlively@xxxxxxxxxxxxxxx> + */ + +#ifndef __VIR_NODE_DEVICE_CONF_H__ +#define __VIR_NODE_DEVICE_CONF_H__ + +#include "internal.h" +#include "util.h" + +enum virNodeDevCapType { + /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */ + VIR_NODE_DEV_CAP_SYSTEM, /* System capability */ + VIR_NODE_DEV_CAP_PCI_DEV, /* PCI device */ + VIR_NODE_DEV_CAP_USB_DEV, /* USB device */ + VIR_NODE_DEV_CAP_USB_INTERFACE, /* USB interface */ + VIR_NODE_DEV_CAP_NET, /* Network device */ + VIR_NODE_DEV_CAP_BLOCK, /* Block device */ + VIR_NODE_DEV_CAP_SCSI_HOST, /* SCSI Host Bus Adapter */ + VIR_NODE_DEV_CAP_SCSI, /* SCSI device */ + VIR_NODE_DEV_CAP_STORAGE, /* Storage device */ + VIR_NODE_DEV_CAP_LAST +}; + +enum virNodeDevNetCapType { + /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */ + VIR_NODE_DEV_CAP_NET_80203, /* 802.03 network device */ + VIR_NODE_DEV_CAP_NET_80211, /* 802.11 network device */ + VIR_NODE_DEV_CAP_NET_LAST +}; + +VIR_ENUM_DECL(virNodeDevCap); +VIR_ENUM_DECL(virNodeDevNetCap); + +enum virNodeDevStorageCapFlags { + VIR_NODE_DEV_CAP_STORAGE_REMOVABLE = (1 << 0), + VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE = (1 << 1), + VIR_NODE_DEV_CAP_STORAGE_HOTPLUGGABLE = (1 << 2), +}; + +typedef struct _virNodeDevCapsDef virNodeDevCapsDef; +typedef virNodeDevCapsDef *virNodeDevCapsDefPtr; +struct _virNodeDevCapsDef { + enum virNodeDevCapType type; + union _virNodeDevCapData { + struct { + char *product_name; + struct { + char *vendor_name; + char *version; + char *serial; + unsigned char uuid[VIR_UUID_BUFLEN]; + } hardware; + struct { + char *vendor_name; + char *version; + char *release_date; + } firmware; + } system; + struct { + unsigned domain; + unsigned bus; + unsigned slot; + unsigned function; + unsigned product; + unsigned vendor; + char *product_name; + char *vendor_name; + } pci_dev; + struct { + unsigned bus; + unsigned device; + unsigned product; + unsigned vendor; + char *product_name; + char *vendor_name; + } usb_dev; + struct { + unsigned number; + unsigned _class; /* "class" is reserved in C */ + unsigned subclass; + unsigned protocol; + char *description; + } usb_if; + struct { + char *address; + char *interface; + enum virNodeDevNetCapType subtype; /* LAST -> no subtype */ + union { + struct { + unsigned long long mac_address; + } ieee80203; + struct { + unsigned long long mac_address; + } ieee80211; + } data; + } net; + struct { + char *device; + } block; + struct { + unsigned host; + } scsi_host; + struct { + unsigned host; + unsigned bus; + unsigned target; + unsigned lun; + char *type; + } scsi; + struct { + unsigned long long size; + unsigned long long removable_media_size; + char *bus; + char *drive_type; + char *originating_device; + char *model; + char *vendor; + unsigned flags; /* virNodeDevStorageCapFlags bits */ + } storage; + } data; + virNodeDevCapsDefPtr next; /* next capability */ +}; + + +typedef struct _virNodeDeviceDef virNodeDeviceDef; +typedef virNodeDeviceDef *virNodeDeviceDefPtr; +struct _virNodeDeviceDef { + char *name; /* device name (unique on node) */ + char *parent; /* optional parent device name */ + virNodeDevCapsDefPtr caps; /* optional device capabilities */ +}; + + +typedef struct _virNodeDeviceObj virNodeDeviceObj; +typedef virNodeDeviceObj *virNodeDeviceObjPtr; +struct _virNodeDeviceObj { + virNodeDeviceDefPtr def; /* device definition */ + void *privateData; /* driver-specific private data */ + void (*privateFree)(void *data); /* destructor for private data */ + +}; + +typedef struct _virNodeDeviceObjList virNodeDeviceObjList; +typedef virNodeDeviceObjList *virNodeDeviceObjListPtr; +struct _virNodeDeviceObjList { + unsigned int count; + virNodeDeviceObjPtr *objs; +}; + +typedef struct _virNodeDriverState virNodeDriverState; +typedef virNodeDriverState *virNodeDriverStatePtr; +struct _virNodeDriverState { + virNodeDeviceObjList devs; /* currently-known devices */ + void *privateData; /* driver-specific private data */ +}; + +void virNodeDeviceReportError(virConnectPtr conn, + int code, + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); + +virNodeDeviceObjPtr virNodeDeviceFindByName(const virNodeDeviceObjListPtr devs, + const char *name); + +virNodeDeviceObjPtr virNodeDeviceAssignDef(virConnectPtr conn, + virNodeDeviceObjListPtr devs, + const virNodeDeviceDefPtr def); + +void virNodeDeviceObjRemove(virNodeDeviceObjListPtr devs, + const virNodeDeviceObjPtr dev); + +char *virNodeDeviceDefFormat(virConnectPtr conn, + const virNodeDeviceDefPtr def); + +// TODO: virNodeDeviceDefParseString/File/Node for virNodeDeviceCreate + +void virNodeDeviceDefFree(virNodeDeviceDefPtr def); + +void virNodeDeviceObjFree(virNodeDeviceObjPtr dev); + +void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs); + +void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps); + +#endif /* __VIR_NODE_DEVICE_CONF_H__ */
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list