mirror of https://gitee.com/openkylin/libvirt.git
Add new domain device: "controller"
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 * docs/schemas/domain.rng: Define syntax for <controller> XML element * src/conf/domain_conf.c, src/conf/domain_conf.h: Define virDomainControllerDef struct, and routines for parsing and formatting XML * src/libvirt_private.syms: Add virDomainControllerInsert and virDomainControllerDefFree
This commit is contained in:
parent
776e37e1eb
commit
74ec5e65ce
|
@ -521,6 +521,25 @@
|
|||
</choice>
|
||||
</attribute>
|
||||
</define>
|
||||
<define name="controller">
|
||||
<element name="controller">
|
||||
<optional>
|
||||
<attribute name="type">
|
||||
<choice>
|
||||
<value>fdc</value>
|
||||
<value>ide</value>
|
||||
<value>scsi</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</optional>
|
||||
<attribute name="index">
|
||||
<ref name="unsignedInt"/>
|
||||
</attribute>
|
||||
<optional>
|
||||
<ref name="address"/>
|
||||
</optional>
|
||||
</element>
|
||||
</define>
|
||||
<define name="filesystem">
|
||||
<element name="filesystem">
|
||||
<choice>
|
||||
|
@ -1225,6 +1244,7 @@
|
|||
<zeroOrMore>
|
||||
<choice>
|
||||
<ref name="disk"/>
|
||||
<ref name="controller"/>
|
||||
<ref name="filesystem"/>
|
||||
<ref name="interface"/>
|
||||
<ref name="input"/>
|
||||
|
|
|
@ -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",
|
||||
|
@ -119,6 +120,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",
|
||||
|
@ -367,6 +374,16 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
|
|||
VIR_FREE(def);
|
||||
}
|
||||
|
||||
void virDomainControllerDefFree(virDomainControllerDefPtr def)
|
||||
{
|
||||
if (!def)
|
||||
return;
|
||||
|
||||
virDomainDeviceInfoClear(&def->info);
|
||||
|
||||
VIR_FREE(def);
|
||||
}
|
||||
|
||||
void virDomainFSDefFree(virDomainFSDefPtr def)
|
||||
{
|
||||
if (!def)
|
||||
|
@ -528,6 +545,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);
|
||||
|
@ -561,6 +581,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);
|
||||
|
@ -1335,6 +1359,63 @@ 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;
|
||||
char *type = NULL;
|
||||
char *idx = 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (virDomainDeviceInfoParseXML(conn, node, &def->info, flags) < 0)
|
||||
goto error;
|
||||
|
||||
if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
|
||||
def->info.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
|
||||
*/
|
||||
|
@ -2995,6 +3076,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"));
|
||||
|
@ -3067,6 +3152,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,
|
||||
|
@ -3382,6 +3520,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,
|
||||
|
@ -4298,6 +4455,35 @@ virDomainDiskDefFormat(virConnectPtr conn,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virDomainControllerDefFormat(virConnectPtr conn,
|
||||
virBufferPtr buf,
|
||||
virDomainControllerDefPtr def)
|
||||
{
|
||||
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 (virDomainDeviceInfoIsSet(&def->info)) {
|
||||
virBufferAddLit(buf, ">\n");
|
||||
if (virDomainDeviceInfoFormat(buf, &def->info) < 0)
|
||||
return -1;
|
||||
virBufferAddLit(buf, " </controller>\n");
|
||||
} else {
|
||||
virBufferAddLit(buf, "/>\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virDomainFSDefFormat(virConnectPtr conn,
|
||||
virBufferPtr buf,
|
||||
|
@ -5045,6 +5231,10 @@ char *virDomainDefFormat(virConnectPtr conn,
|
|||
if (virDomainDiskDefFormat(conn, &buf, def->disks[n]) < 0)
|
||||
goto cleanup;
|
||||
|
||||
for (n = 0 ; n < def->ncontrollers ; n++)
|
||||
if (virDomainControllerDefFormat(conn, &buf, def->controllers[n]) < 0)
|
||||
goto cleanup;
|
||||
|
||||
for (n = 0 ; n < def->nfss ; n++)
|
||||
if (virDomainFSDefFormat(conn, &buf, def->fss[n]) < 0)
|
||||
goto cleanup;
|
||||
|
|
|
@ -160,6 +160,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;
|
||||
virDomainDeviceInfo info;
|
||||
};
|
||||
|
||||
|
||||
/* Two types of disk backends */
|
||||
enum virDomainFSType {
|
||||
VIR_DOMAIN_FS_TYPE_MOUNT, /* Better named 'bind' */
|
||||
|
@ -488,6 +507,7 @@ enum virDomainDeviceType {
|
|||
VIR_DOMAIN_DEVICE_VIDEO,
|
||||
VIR_DOMAIN_DEVICE_HOSTDEV,
|
||||
VIR_DOMAIN_DEVICE_WATCHDOG,
|
||||
VIR_DOMAIN_DEVICE_CONTROLLER,
|
||||
|
||||
VIR_DOMAIN_DEVICE_LAST,
|
||||
};
|
||||
|
@ -498,6 +518,7 @@ struct _virDomainDeviceDef {
|
|||
int type;
|
||||
union {
|
||||
virDomainDiskDefPtr disk;
|
||||
virDomainControllerDefPtr controller;
|
||||
virDomainFSDefPtr fs;
|
||||
virDomainNetDefPtr net;
|
||||
virDomainInputDefPtr input;
|
||||
|
@ -610,6 +631,9 @@ struct _virDomainDef {
|
|||
int ndisks;
|
||||
virDomainDiskDefPtr *disks;
|
||||
|
||||
int ncontrollers;
|
||||
virDomainControllerDefPtr *controllers;
|
||||
|
||||
int nfss;
|
||||
virDomainFSDefPtr *fss;
|
||||
|
||||
|
@ -693,6 +717,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);
|
||||
|
@ -775,6 +800,11 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def,
|
|||
virDomainDiskDefPtr disk);
|
||||
void virDomainDiskDefAssignAddress(virDomainDiskDefPtr def);
|
||||
|
||||
int virDomainControllerInsert(virDomainDefPtr def,
|
||||
virDomainControllerDefPtr controller);
|
||||
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
|
||||
virDomainControllerDefPtr controller);
|
||||
|
||||
int virDomainSaveXML(virConnectPtr conn,
|
||||
const char *configDir,
|
||||
virDomainDefPtr def,
|
||||
|
@ -855,6 +885,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)
|
||||
|
|
|
@ -130,6 +130,8 @@ virDomainDiskDeviceTypeToString;
|
|||
virDomainDiskInsert;
|
||||
virDomainDiskInsertPreAlloced;
|
||||
virDomainDiskDefAssignAddress;
|
||||
virDomainControllerInsert;
|
||||
virDomainControllerInsertPreAlloced;
|
||||
virDomainFindByID;
|
||||
virDomainFindByName;
|
||||
virDomainFindByUUID;
|
||||
|
|
Loading…
Reference in New Issue