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:
Daniel P. Berrange 2009-12-01 16:56:24 +00:00
parent 1b0cce7d3a
commit d812e7aeb8
3 changed files with 135 additions and 1 deletions

View File

@ -1189,6 +1189,21 @@
<ref name="pciFunc"/>
</attribute>
</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.
-->
@ -1305,6 +1320,12 @@
</attribute>
<ref name="pciaddress"/>
</group>
<group>
<attribute name="type">
<value>drive</value>
</attribute>
<ref name="driveaddress"/>
</group>
</choice>
</element>
</define>
@ -1434,6 +1455,21 @@
<param name="pattern">(0x)?[0-7]</param>
</data>
</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">
<data type="string">
<param name='pattern'>[a-zA-Z0-9\-_]+</param>

View File

@ -90,7 +90,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
"none",
"pci")
"pci",
"drive");
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
"block",
@ -748,6 +749,9 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
switch (info->type) {
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
return virDomainDevicePCIAddressIsValid(&info->addr.pci);
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
return virDomainDeviceDriveAddressIsValid(&info->addr.drive);
}
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)
{
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
@ -803,6 +814,13 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf,
info->addr.pci.function);
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:
virDomainReportError(NULL, VIR_ERR_INTERNAL_ERROR,
_("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
virDomainDevicePCIAddressParseXML(virConnectPtr conn,
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
* @param node XML nodeset to parse for device address definition
*/
@ -938,6 +1018,11 @@ virDomainDeviceInfoParseXML(virConnectPtr conn,
goto cleanup;
break;
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
if (virDomainDeviceDriveAddressParseXML(conn, node, &info->addr.drive) < 0)
goto cleanup;
break;
default:
/* Should not happen */
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,

View File

@ -67,6 +67,7 @@ enum virDomainVirtType {
enum virDomainDeviceAddressType {
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
};
@ -80,12 +81,21 @@ struct _virDomainDevicePCIAddress {
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 virDomainDeviceInfo *virDomainDeviceInfoPtr;
struct _virDomainDeviceInfo {
int type;
union {
virDomainDevicePCIAddress pci;
virDomainDeviceDriveAddress drive;
} addr;
};
@ -690,9 +700,12 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a,
virDomainDevicePCIAddressPtr b);
int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a,
virDomainDeviceDriveAddressPtr b);
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
int type);
int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr);
int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr);
int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info);
void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
void virDomainDefFree(virDomainDefPtr vm);