mirror of https://gitee.com/openkylin/libvirt.git
Extend the virDomainDeviceAddress struture to allow disk controller addresses
Introduce a new structure struct _virDomainDeviceDriveAddress { unsigned int controller; unsigned int bus; unsigned int unit; }; and plug that into virDomainDeviceAddress and generates XML that looks like <address type='drive' controller='1' bus='0' unit='5'/> This syntax will be used by the QEMU driver to explicitly control how drives are attached to the bus * src/conf/domain_conf.h, src/conf/domain_conf.c: Parsing and formatting of drive addresses * docs/schemas/domain.rng: Define new address format for drives
This commit is contained in:
parent
1b0cce7d3a
commit
d812e7aeb8
|
@ -1189,6 +1189,21 @@
|
||||||
<ref name="pciFunc"/>
|
<ref name="pciFunc"/>
|
||||||
</attribute>
|
</attribute>
|
||||||
</define>
|
</define>
|
||||||
|
<define name="driveaddress">
|
||||||
|
<optional>
|
||||||
|
<attribute name="controller">
|
||||||
|
<ref name="driveController"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="bus">
|
||||||
|
<ref name="driveBus"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<attribute name="unit">
|
||||||
|
<ref name="driveUnit"/>
|
||||||
|
</attribute>
|
||||||
|
</define>
|
||||||
<!--
|
<!--
|
||||||
Devices attached to a domain.
|
Devices attached to a domain.
|
||||||
-->
|
-->
|
||||||
|
@ -1305,6 +1320,12 @@
|
||||||
</attribute>
|
</attribute>
|
||||||
<ref name="pciaddress"/>
|
<ref name="pciaddress"/>
|
||||||
</group>
|
</group>
|
||||||
|
<group>
|
||||||
|
<attribute name="type">
|
||||||
|
<value>drive</value>
|
||||||
|
</attribute>
|
||||||
|
<ref name="driveaddress"/>
|
||||||
|
</group>
|
||||||
</choice>
|
</choice>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
@ -1434,6 +1455,21 @@
|
||||||
<param name="pattern">(0x)?[0-7]</param>
|
<param name="pattern">(0x)?[0-7]</param>
|
||||||
</data>
|
</data>
|
||||||
</define>
|
</define>
|
||||||
|
<define name="driveController">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">[0-9]{1,2}</param>
|
||||||
|
</data>
|
||||||
|
</define>
|
||||||
|
<define name="driveBus">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">[0-9]{1,2}</param>
|
||||||
|
</data>
|
||||||
|
</define>
|
||||||
|
<define name="driveUnit">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">[0-9]{1,2}</param>
|
||||||
|
</data>
|
||||||
|
</define>
|
||||||
<define name="featureName">
|
<define name="featureName">
|
||||||
<data type="string">
|
<data type="string">
|
||||||
<param name='pattern'>[a-zA-Z0-9\-_]+</param>
|
<param name='pattern'>[a-zA-Z0-9\-_]+</param>
|
||||||
|
|
|
@ -90,7 +90,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
|
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
|
||||||
"none",
|
"none",
|
||||||
"pci")
|
"pci",
|
||||||
|
"drive");
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
|
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
|
||||||
"block",
|
"block",
|
||||||
|
@ -748,6 +749,9 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
|
||||||
switch (info->type) {
|
switch (info->type) {
|
||||||
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
|
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
|
||||||
return virDomainDevicePCIAddressIsValid(&info->addr.pci);
|
return virDomainDevicePCIAddressIsValid(&info->addr.pci);
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
|
||||||
|
return virDomainDeviceDriveAddressIsValid(&info->addr.drive);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -760,6 +764,13 @@ int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
/*return addr->controller || addr->bus || addr->unit;*/
|
||||||
|
return 1; /* 0 is valid for all fields, so any successfully parsed addr is valid */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info)
|
int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info)
|
||||||
{
|
{
|
||||||
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
||||||
|
@ -803,6 +814,13 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf,
|
||||||
info->addr.pci.function);
|
info->addr.pci.function);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
|
||||||
|
virBufferVSprintf(buf, " controller='%d' bus='%d' unit='%d'",
|
||||||
|
info->addr.drive.controller,
|
||||||
|
info->addr.drive.bus,
|
||||||
|
info->addr.drive.unit);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
virDomainReportError(NULL, VIR_ERR_INTERNAL_ERROR,
|
virDomainReportError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("unknown address type '%d'"), info->type);
|
_("unknown address type '%d'"), info->type);
|
||||||
|
@ -828,6 +846,18 @@ int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a,
|
||||||
|
virDomainDeviceDriveAddressPtr b)
|
||||||
|
{
|
||||||
|
if (a->controller == b->controller &&
|
||||||
|
a->bus == b->bus &&
|
||||||
|
a->unit == b->unit)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainDevicePCIAddressParseXML(virConnectPtr conn,
|
virDomainDevicePCIAddressParseXML(virConnectPtr conn,
|
||||||
xmlNodePtr node,
|
xmlNodePtr node,
|
||||||
|
@ -888,6 +918,56 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainDeviceDriveAddressParseXML(virConnectPtr conn,
|
||||||
|
xmlNodePtr node,
|
||||||
|
virDomainDeviceDriveAddressPtr addr)
|
||||||
|
{
|
||||||
|
char *bus, *unit, *controller;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
memset(addr, 0, sizeof(*addr));
|
||||||
|
|
||||||
|
controller = virXMLPropString(node, "controller");
|
||||||
|
bus = virXMLPropString(node, "bus");
|
||||||
|
unit = virXMLPropString(node, "unit");
|
||||||
|
|
||||||
|
if (controller &&
|
||||||
|
virStrToLong_ui(controller, NULL, 10, &addr->controller) < 0) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Cannot parse <address> 'controller' attribute"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bus &&
|
||||||
|
virStrToLong_ui(bus, NULL, 10, &addr->bus) < 0) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Cannot parse <address> 'bus' attribute"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unit &&
|
||||||
|
virStrToLong_ui(unit, NULL, 10, &addr->unit) < 0) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Cannot parse <address> 'unit' attribute"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!virDomainDeviceDriveAddressIsValid(addr)) {
|
||||||
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Insufficient specification for drive address"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(controller);
|
||||||
|
VIR_FREE(bus);
|
||||||
|
VIR_FREE(unit);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the XML definition for a device address
|
/* Parse the XML definition for a device address
|
||||||
* @param node XML nodeset to parse for device address definition
|
* @param node XML nodeset to parse for device address definition
|
||||||
*/
|
*/
|
||||||
|
@ -938,6 +1018,11 @@ virDomainDeviceInfoParseXML(virConnectPtr conn,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
|
||||||
|
if (virDomainDeviceDriveAddressParseXML(conn, node, &info->addr.drive) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Should not happen */
|
/* Should not happen */
|
||||||
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
|
|
@ -67,6 +67,7 @@ enum virDomainVirtType {
|
||||||
enum virDomainDeviceAddressType {
|
enum virDomainDeviceAddressType {
|
||||||
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE,
|
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE,
|
||||||
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI,
|
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI,
|
||||||
|
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
|
||||||
|
|
||||||
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
|
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
|
||||||
};
|
};
|
||||||
|
@ -80,12 +81,21 @@ struct _virDomainDevicePCIAddress {
|
||||||
unsigned int function;
|
unsigned int function;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress;
|
||||||
|
typedef virDomainDeviceDriveAddress *virDomainDeviceDriveAddressPtr;
|
||||||
|
struct _virDomainDeviceDriveAddress {
|
||||||
|
unsigned int controller;
|
||||||
|
unsigned int bus;
|
||||||
|
unsigned int unit;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
|
typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
|
||||||
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
|
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
|
||||||
struct _virDomainDeviceInfo {
|
struct _virDomainDeviceInfo {
|
||||||
int type;
|
int type;
|
||||||
union {
|
union {
|
||||||
virDomainDevicePCIAddress pci;
|
virDomainDevicePCIAddress pci;
|
||||||
|
virDomainDeviceDriveAddress drive;
|
||||||
} addr;
|
} addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -690,9 +700,12 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
|
||||||
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
|
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
|
||||||
int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a,
|
int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a,
|
||||||
virDomainDevicePCIAddressPtr b);
|
virDomainDevicePCIAddressPtr b);
|
||||||
|
int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a,
|
||||||
|
virDomainDeviceDriveAddressPtr b);
|
||||||
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
|
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
|
||||||
int type);
|
int type);
|
||||||
int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr);
|
int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr);
|
||||||
|
int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr);
|
||||||
int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info);
|
int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info);
|
||||||
void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
|
void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
|
||||||
void virDomainDefFree(virDomainDefPtr vm);
|
void virDomainDefFree(virDomainDefPtr vm);
|
||||||
|
|
Loading…
Reference in New Issue