On Thu, 2008-11-13 at 17:31 +0000, Daniel P. Berrange wrote:
This is the basic internal driver support code for the node device
APIs.
The actual registration of the drivers was pushed to a later patch to
allow this to compile on its own & thus be fully bisectable.
Daniel
diff -r 6812c3044043 src/Makefile.am
--- a/src/Makefile.am Wed Nov 12 21:11:46 2008 +0000
+++ b/src/Makefile.am Wed Nov 12 21:11:51 2008 +0000
@@ -132,6 +132,10 @@
storage_driver.h storage_driver.c \
storage_backend.h storage_backend.c
+# Network driver generic impl APIs
Typo
+NODE_DEVICE_CONF_SOURCES = \
+ node_device_conf.c node_device_conf.h
+
...
diff -r 6812c3044043 src/node_device_conf.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node_device_conf.c Wed Nov 12 21:11:51 2008 +0000
...
+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_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");
This all seems a bit odd.
We've listed the mac address once already, so why do it again in a hex format?
And I wouldn't think of "802.3 vs 802.11" as a network device capability,
but more like it's "type" - they're mutually exclusive, right?
Also, we have:
<device>
...
<capability type='net'>
...
<capability type='80203'>
<mac_address>001320f74a06</address>
</capability>
</capability>
</device>
i.e. two different capability semantics?
+ }
+ break;
+ case VIR_NODE_DEV_CAP_BLOCK:
+ virBufferVSprintf(&buf, "
<device>%s</device>\n",
+ data->block.device);
Two nested <device> nodes:
<device>
...
<capability type='block'>
<device>/dev/sda1</device>
</capability>
</device>
How about <path> or <device_path> ?
+ 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);
This originating_device thing sounds strange, and I don't think we
implement it yet. Leave it out for now?
+ 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");
Again, the nested capabilities doesn't seem right.
How about just:
<removable media_available="1"/>
<hotpluggable/>
+ 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);
originating_device not freed.
+ break;
+ case VIR_NODE_DEV_CAP_LAST:
+ /* This case is here to shutup the compiler */
+ break;
+ }
+
+ VIR_FREE(caps);
+}
+
diff -r 6812c3044043 src/node_device_conf.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node_device_conf.h Wed Nov 12 21:11:51 2008 +0000
...
+char *virNodeDeviceDefFormat(virConnectPtr conn,
+ const virNodeDeviceDefPtr def);
+
+// TODO: virNodeDeviceDefParseString/File/Node for virNodeDeviceCreate
Kinda superflous comment - if we implement DeviceCreate(), the need for
those functions will be obvious.
Cheers,
Mark.