From: Wolfgang Mauerer <wolfgang.mauerer(a)siemens.com>
This augments virDomainDevice with a <controller> element
that is used to represent disk controllers (e.g., scsi
controllers). The XML format is given by
<controller type="scsi" index="<num>">
<address type="pci" domain="0xNUM" bus="0xNUM"
slot="0xNUM"/>
</controller>
where type denotes the disk interface (scsi, ide,...), index
is an integer that identifies the controller for association
with disks, and the <address> element specifies the controller
address on the PCI bus as described in previous commits
The address element can be omitted; in this case, an address
will be assigned automatically.
Most of the code in this patch is from Wolfgang Mauerer's
previous disk controller series
---
src/conf/domain_conf.c | 207 +++++++++++++++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 30 +++++++
src/libvirt_private.syms | 2 +
3 files changed, 238 insertions(+), 1 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 533a1b0..95a9d52 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -86,7 +86,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
"sound",
"video",
"hostdev",
- "watchdog")
+ "watchdog",
+ "controller")
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
"none",
@@ -124,6 +125,12 @@ VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
"writethrough",
"writeback")
+VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
+ "ide",
+ "fdc",
+ "scsi",
+ "sata")
+
VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
"mount",
"block",
@@ -371,6 +378,14 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def);
}
+void virDomainControllerDefFree(virDomainControllerDefPtr def)
+{
+ if (!def)
+ return;
+
+ VIR_FREE(def);
+}
+
void virDomainFSDefFree(virDomainFSDefPtr def)
{
if (!def)
@@ -523,6 +538,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
case VIR_DOMAIN_DEVICE_WATCHDOG:
virDomainWatchdogDefFree(def->data.watchdog);
break;
+ case VIR_DOMAIN_DEVICE_CONTROLLER:
+ virDomainControllerDefFree(def->data.controller);
+ break;
}
VIR_FREE(def);
@@ -556,6 +574,10 @@ void virDomainDefFree(virDomainDefPtr def)
virDomainDiskDefFree(def->disks[i]);
VIR_FREE(def->disks);
+ for (i = 0 ; i < def->ncontrollers ; i++)
+ virDomainControllerDefFree(def->controllers[i]);
+ VIR_FREE(def->controllers);
+
for (i = 0 ; i < def->nfss ; i++)
virDomainFSDefFree(def->fss[i]);
VIR_FREE(def->fss);
@@ -1390,6 +1412,76 @@ cleanup:
}
+/* Parse the XML definition for a controller
+ * @param node XML nodeset to parse for controller definition
+ */
+static virDomainControllerDefPtr
+virDomainControllerDefParseXML(virConnectPtr conn,
+ xmlNodePtr node,
+ int flags) {
+ virDomainControllerDefPtr def;
+ xmlNodePtr cur;
+ char *type = NULL;
+ char *idx = NULL;
+ xmlNodePtr addr = NULL;
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+
+ type = virXMLPropString(node, "type");
+ if (type) {
+ if ((def->type = virDomainDiskBusTypeFromString(type)) < 0) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unknown disk controller type
'%s'"), type);
+ goto error;
+ }
+ }
+
+ idx = virXMLPropString(node, "index");
+ if (idx) {
+ if (virStrToLong_i(idx, NULL, 10, &def->idx) < 0) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse disk controller index %s"),
idx);
+ goto error;
+ }
+ }
+
+ cur = node->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE &&
+ addr == NULL) {
+ addr = cur;
+ }
+
+ cur = cur->next;
+ }
+
+ if (addr) {
+ if (virDomainDeviceAddressParseXML(conn, addr, &def->addr,flags) < 0)
+ goto error;
+ }
+
+ if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+ def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Disk controllers must use the 'pci' address
type"));
+ goto error;
+ }
+
+cleanup:
+ VIR_FREE(type);
+ VIR_FREE(idx);
+
+ return def;
+
+ error:
+ virDomainControllerDefFree(def);
+ def = NULL;
+ goto cleanup;
+}
+
/* Parse the XML definition for a disk
* @param node XML nodeset to parse for disk definition
*/
@@ -3092,6 +3184,10 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn,
dev->type = VIR_DOMAIN_DEVICE_HOSTDEV;
if (!(dev->data.hostdev = virDomainHostdevDefParseXML(conn, node, flags)))
goto error;
+ } else if (xmlStrEqual(node->name, BAD_CAST "controller")) {
+ dev->type = VIR_DOMAIN_DEVICE_CONTROLLER;
+ if (!(dev->data.controller = virDomainControllerDefParseXML(conn, node,
flags)))
+ goto error;
} else {
virDomainReportError(conn, VIR_ERR_XML_ERROR,
"%s", _("unknown device type"));
@@ -3164,6 +3260,59 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def,
}
+int virDomainControllerInsert(virDomainDefPtr def,
+ virDomainControllerDefPtr controller)
+{
+
+ if (VIR_REALLOC_N(def->controllers, def->ncontrollers+1) < 0)
+ return -1;
+
+ virDomainControllerInsertPreAlloced(def, controller);
+
+ return 0;
+}
+
+void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
+ virDomainControllerDefPtr controller)
+{
+ int i;
+ /* Tenatively plan to insert controller at the end. */
+ int insertAt = -1;
+
+ /* Then work backwards looking for controllers of
+ * the same type. If we find a controller with a
+ * index greater than the new one, insert at
+ * that position
+ */
+ for (i = (def->ncontrollers - 1) ; i >= 0 ; i--) {
+ /* If bus matches and current controller is after
+ * new controller, then new controller should go here */
+ if ((def->controllers[i]->type == controller->type) &&
+ (def->controllers[i]->idx > controller->idx)) {
+ insertAt = i;
+ } else if (def->controllers[i]->type == controller->type &&
+ insertAt == -1) {
+ /* Last controller with match bus is before the
+ * new controller, then put new controller just after
+ */
+ insertAt = i + 1;
+ }
+ }
+
+ /* No controllers with this bus yet, so put at end of list */
+ if (insertAt == -1)
+ insertAt = def->ncontrollers;
+
+ if (insertAt < def->ncontrollers)
+ memmove(def->controllers + insertAt + 1,
+ def->controllers + insertAt,
+ (sizeof(def->controllers[0]) * (def->ncontrollers-insertAt)));
+
+ def->controllers[insertAt] = controller;
+ def->ncontrollers++;
+}
+
+
#ifndef PROXY
static char *virDomainDefDefaultEmulator(virConnectPtr conn,
virDomainDefPtr def,
@@ -3479,6 +3628,25 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
}
VIR_FREE(nodes);
+ /* analysis of the controller devices */
+ if ((n = virXPathNodeSet(conn, "./devices/controller", ctxt, &nodes))
< 0) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("cannot extract controller
devices"));
+ goto error;
+ }
+ if (n && VIR_ALLOC_N(def->controllers, n) < 0)
+ goto no_memory;
+ for (i = 0 ; i < n ; i++) {
+ virDomainControllerDefPtr controller = virDomainControllerDefParseXML(conn,
+ nodes[i],
+ flags);
+ if (!controller)
+ goto error;
+
+ def->controllers[def->ncontrollers++] = controller;
+ }
+ VIR_FREE(nodes);
+
/* analysis of the filesystems */
if ((n = virXPathNodeSet(conn, "./devices/filesystem", ctxt, &nodes))
< 0) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
@@ -4387,6 +4555,36 @@ virDomainDiskDefFormat(virConnectPtr conn,
}
static int
+virDomainControllerDefFormat(virConnectPtr conn,
+ virBufferPtr buf,
+ virDomainControllerDefPtr def,
+ int flags)
+{
+ const char *type = virDomainControllerTypeToString(def->type);
+
+ if (!type) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected controller type %d"),
def->type);
+ return -1;
+ }
+
+ virBufferVSprintf(buf,
+ " <controller type='%s'
index='%d'",
+ type, def->idx);
+
+ if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ virBufferAddLit(buf, ">\n");
+ if (virDomainDeviceAddressFormat(buf, &def->addr, flags) < 0)
+ return -1;
+ virBufferAddLit(buf, " </controller>\n");
+ } else {
+ virBufferAddLit(buf, "/>\n");
+ }
+
+ return 0;
+}
+
+static int
virDomainFSDefFormat(virConnectPtr conn,
virBufferPtr buf,
virDomainFSDefPtr def)
@@ -5138,6 +5336,10 @@ char *virDomainDefFormat(virConnectPtr conn,
if (virDomainDiskDefFormat(conn, &buf, def->disks[n], flags) < 0)
goto cleanup;
+ for (n = 0 ; n < def->ncontrollers ; n++)
+ if (virDomainControllerDefFormat(conn, &buf, def->controllers[n], flags)
< 0)
+ goto cleanup;
+
for (n = 0 ; n < def->nfss ; n++)
if (virDomainFSDefFormat(conn, &buf, def->fss[n]) < 0)
goto cleanup;
@@ -5316,6 +5518,9 @@ void virDomainDefClearDynamicValues(virDomainDefPtr def)
for (i = 0 ; i < def->nnets ; i++) {
virDomainDeviceAddressClearDynamicValues(&def->nets[i]->addr);
}
+ for (i = 0 ; i < def->ncontrollers ; i++) {
+ virDomainDeviceAddressClearDynamicValues(&def->controllers[i]->addr);
+ }
if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
VIR_FREE(def->seclabel.label);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c93aed6..413647b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -176,6 +176,25 @@ struct _virDomainDiskDef {
};
+enum virDomainControllerType {
+ VIR_DOMAIN_CONTROLLER_TYPE_IDE,
+ VIR_DOMAIN_CONTROLLER_TYPE_FDC,
+ VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
+ VIR_DOMAIN_CONTROLLER_TYPE_SATA,
+
+ VIR_DOMAIN_CONTROLLER_TYPE_LAST
+};
+
+/* Stores the virtual disk controller configuration */
+typedef struct _virDomainControllerDef virDomainControllerDef;
+typedef virDomainControllerDef *virDomainControllerDefPtr;
+struct _virDomainControllerDef {
+ int type;
+ int idx;
+ virDomainDeviceAddress addr;
+};
+
+
/* Two types of disk backends */
enum virDomainFSType {
VIR_DOMAIN_FS_TYPE_MOUNT, /* Better named 'bind' */
@@ -500,6 +519,7 @@ enum virDomainDeviceType {
VIR_DOMAIN_DEVICE_VIDEO,
VIR_DOMAIN_DEVICE_HOSTDEV,
VIR_DOMAIN_DEVICE_WATCHDOG,
+ VIR_DOMAIN_DEVICE_CONTROLLER,
VIR_DOMAIN_DEVICE_LAST,
};
@@ -510,6 +530,7 @@ struct _virDomainDeviceDef {
int type;
union {
virDomainDiskDefPtr disk;
+ virDomainControllerDefPtr controller;
virDomainFSDefPtr fs;
virDomainNetDefPtr net;
virDomainInputDefPtr input;
@@ -622,6 +643,9 @@ struct _virDomainDef {
int ndisks;
virDomainDiskDefPtr *disks;
+ int ncontrollers;
+ virDomainControllerDefPtr *controllers;
+
int nfss;
virDomainFSDefPtr *fss;
@@ -704,6 +728,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def);
void virDomainInputDefFree(virDomainInputDefPtr def);
void virDomainDiskDefFree(virDomainDiskDefPtr def);
+void virDomainControllerDefFree(virDomainControllerDefPtr def);
void virDomainFSDefFree(virDomainFSDefPtr def);
void virDomainNetDefFree(virDomainNetDefPtr def);
void virDomainChrDefFree(virDomainChrDefPtr def);
@@ -790,6 +815,10 @@ int virDomainDiskInsert(virDomainDefPtr def,
virDomainDiskDefPtr disk);
void virDomainDiskInsertPreAlloced(virDomainDefPtr def,
virDomainDiskDefPtr disk);
+int virDomainControllerInsert(virDomainDefPtr def,
+ virDomainControllerDefPtr controller);
+void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
+ virDomainControllerDefPtr controller);
int virDomainSaveXML(virConnectPtr conn,
const char *configDir,
@@ -871,6 +900,7 @@ VIR_ENUM_DECL(virDomainDisk)
VIR_ENUM_DECL(virDomainDiskDevice)
VIR_ENUM_DECL(virDomainDiskBus)
VIR_ENUM_DECL(virDomainDiskCache)
+VIR_ENUM_DECL(virDomainController)
VIR_ENUM_DECL(virDomainFS)
VIR_ENUM_DECL(virDomainNet)
VIR_ENUM_DECL(virDomainChrTarget)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 285715d..8622e5b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -109,6 +109,8 @@ virDomainDiskDefFree;
virDomainDiskDeviceTypeToString;
virDomainDiskInsert;
virDomainDiskInsertPreAlloced;
+virDomainControllerInsert;
+virDomainControllerInsertPreAlloced;
virDomainFindByID;
virDomainFindByName;
virDomainFindByUUID;
--
1.6.5.2