Introduce new XMLs to specify disk source using libvirt storage

With this patch, one can specify the disk source using libvirt
storage like:

  <disk type='volume' device='disk'>
    <driver name='qemu' type='raw' cache='none'/>
    <source pool='default' volume='fc18.img'/>
    <target dev='vdb' bus='virtio'/>
  </disk>

"seclabels" and "startupPolicy" are not supported for this new
disk type ("volume"). They will be supported in later patches.

docs/formatdomain.html.in:
  * Add documents for new XMLs
docs/schemas/domaincommon.rng:
  * Add rng for new XMLs;
src/conf/domain_conf.h:
  * New struct for 'volume' type disk source (virDomainDiskSourcePoolDef)
  * Add VIR_DOMAIN_DISK_TYPE_VOLUME for enum virDomainDiskType
src/conf/domain_conf.c:
  * New helper virDomainDiskSourcePoolDefParse to parse the 'volume'
    type disk source.
  * New helper virDomainDiskSourcePoolDefFree to free the source def
    if 'volume' type disk.
tests/qemuxml2argvdata/qemuxml2argv-disk-source-pool.xml:
tests/qemuxml2xmltest.c:
  * New test
This commit is contained in:
Osier Yang 2013-04-05 03:37:56 +08:00
parent a05b0fc1ab
commit 4bc331c894
6 changed files with 157 additions and 8 deletions

View File

@ -1372,6 +1372,11 @@
&lt;blockio logical_block_size='512' physical_block_size='4096'/&gt; &lt;blockio logical_block_size='512' physical_block_size='4096'/&gt;
&lt;target dev='hda' bus='ide'/&gt; &lt;target dev='hda' bus='ide'/&gt;
&lt;/disk&gt; &lt;/disk&gt;
&lt;disk type='volume' device='disk'&gt;
&lt;driver name='qemu' type='raw'/&gt;
&lt;source pool='blk-pool0' volume='blk-pool0-vol0'/&gt;
&lt;target dev='hda' bus='ide'/&gt;
&lt;/disk&gt;
&lt;/devices&gt; &lt;/devices&gt;
...</pre> ...</pre>
@ -1452,10 +1457,16 @@
<code>iqn.1992-01.com.example/1</code>); the default LUN is zero. <code>iqn.1992-01.com.example/1</code>); the default LUN is zero.
When the disk <code>type</code> is "network", the <code>source</code> When the disk <code>type</code> is "network", the <code>source</code>
may have zero or more <code>host</code> sub-elements used to may have zero or more <code>host</code> sub-elements used to
specify the hosts to connect. specify the hosts to connect. If the disk <code>type</code> is
"volume", the underlying disk source is represented by attributes
<code>pool</code> and <code>volume</code>. Attribute <code>pool</code>
specifies the name of storage pool (managed by libvirt) where the disk
source resides, and attribute <code>volume</code> specifies the name of
storage volume (managed by libvirt) used as the disk source.
<span class="since">Since 0.0.3; <code>type='dir'</code> since <span class="since">Since 0.0.3; <code>type='dir'</code> since
0.7.5; <code>type='network'</code> since 0.7.5; <code>type='network'</code> since
0.8.7; <code>protocol='iscsi'</code> since 1.0.4</span><br/> 0.8.7; <code>protocol='iscsi'</code> since 1.0.4;
<code>type='volume'</code> since 1.0.5;</span><br/>
For a "file" disk type which represents a cdrom or floppy For a "file" disk type which represents a cdrom or floppy
(the <code>device</code> attribute), it is possible to define (the <code>device</code> attribute), it is possible to define
policy what to do with the disk if the source file is not accessible. policy what to do with the disk if the source file is not accessible.

View File

@ -1107,6 +1107,24 @@
<ref name="diskspec"/> <ref name="diskspec"/>
</interleave> </interleave>
</group> </group>
<group>
<attribute name="type">
<value>volume</value>
</attribute>
<interleave>
<optional>
<element name="source">
<attribute name="pool">
<ref name="genericName"/>
</attribute>
<attribute name="volume">
<ref name="volName"/>
</attribute>
</element>
</optional>
<ref name="diskspec"/>
</interleave>
</group>
<ref name="diskspec"/> <ref name="diskspec"/>
</choice> </choice>
</element> </element>

View File

@ -210,7 +210,8 @@ VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
"block", "block",
"file", "file",
"dir", "dir",
"network") "network",
"volume")
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST, VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
"disk", "disk",
@ -1116,6 +1117,18 @@ void virDomainLeaseDefFree(virDomainLeaseDefPtr def)
VIR_FREE(def); VIR_FREE(def);
} }
static void
virDomainDiskSourcePoolDefFree(virDomainDiskSourcePoolDefPtr def)
{
if (!def)
return;
VIR_FREE(def->pool);
VIR_FREE(def->volume);
VIR_FREE(def);
}
void virDomainDiskDefFree(virDomainDiskDefPtr def) void virDomainDiskDefFree(virDomainDiskDefPtr def)
{ {
unsigned int i; unsigned int i;
@ -1125,6 +1138,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->serial); VIR_FREE(def->serial);
VIR_FREE(def->src); VIR_FREE(def->src);
virDomainDiskSourcePoolDefFree(def->srcpool);
VIR_FREE(def->dst); VIR_FREE(def->dst);
VIR_FREE(def->driverName); VIR_FREE(def->driverName);
virStorageFileFreeMetadata(def->backingChain); virStorageFileFreeMetadata(def->backingChain);
@ -4157,6 +4171,46 @@ cleanup:
goto cleanup; goto cleanup;
} }
static int
virDomainDiskSourcePoolDefParse(xmlNodePtr node,
virDomainDiskDefPtr def)
{
char *pool = NULL;
char *volume = NULL;
int ret = -1;
pool = virXMLPropString(node, "pool");
volume = virXMLPropString(node, "volume");
/* CD-ROM and Floppy allows no source */
if (!pool && !volume)
return 0;
if (!pool || !volume) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("'pool' and 'volume' must be specified together "
"for 'pool' type source"));
goto cleanup;
}
if (VIR_ALLOC(def->srcpool) < 0) {
virReportOOMError();
goto cleanup;
}
def->srcpool->pool = pool;
pool = NULL;
def->srcpool->volume = volume;
volume = NULL;
ret = 0;
cleanup:
VIR_FREE(pool);
VIR_FREE(volume);
return ret;
}
#define VENDOR_LEN 8 #define VENDOR_LEN 8
#define PRODUCT_LEN 16 #define PRODUCT_LEN 16
@ -4252,7 +4306,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
cur = node->children; cur = node->children;
while (cur != NULL) { while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE) { if (cur->type == XML_ELEMENT_NODE) {
if (!source && !hosts && if (!source && !hosts && !def->srcpool &&
xmlStrEqual(cur->name, BAD_CAST "source")) { xmlStrEqual(cur->name, BAD_CAST "source")) {
sourceNode = cur; sourceNode = cur;
@ -4345,6 +4399,10 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
child = child->next; child = child->next;
} }
break; break;
case VIR_DOMAIN_DISK_TYPE_VOLUME:
if (virDomainDiskSourcePoolDefParse(cur, def) < 0)
goto error;
break;
default: default:
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"), _("unexpected disk type %s"),
@ -4643,7 +4701,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
/* Only CDROM and Floppy devices are allowed missing source path /* Only CDROM and Floppy devices are allowed missing source path
* to indicate no media present */ * to indicate no media present */
if (source == NULL && hosts == NULL && if (source == NULL && hosts == NULL && !def->srcpool &&
def->device != VIR_DOMAIN_DISK_DEVICE_CDROM && def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) { def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
virReportError(VIR_ERR_NO_SOURCE, virReportError(VIR_ERR_NO_SOURCE,
@ -4665,8 +4723,19 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
} }
if (target == NULL) { if (target == NULL) {
virReportError(VIR_ERR_NO_TARGET, if (def->srcpool) {
source ? "%s" : NULL, source); char *tmp;
if (virAsprintf(&tmp, "pool = '%s', volume = '%s'",
def->srcpool->pool, def->srcpool->volume) < 0) {
virReportOOMError();
goto error;
}
virReportError(VIR_ERR_NO_TARGET, "%s", tmp);
VIR_FREE(tmp);
} else {
virReportError(VIR_ERR_NO_TARGET, source ? "%s" : NULL, source);
}
goto error; goto error;
} }
@ -12877,7 +12946,7 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
int n; int n;
const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy); const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy);
if (def->src || def->nhosts > 0 || if (def->src || def->nhosts > 0 || def->srcpool ||
def->startupPolicy) { def->startupPolicy) {
switch (def->type) { switch (def->type) {
case VIR_DOMAIN_DISK_TYPE_FILE: case VIR_DOMAIN_DISK_TYPE_FILE:
@ -12949,6 +13018,14 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
virBufferAddLit(buf, " </source>\n"); virBufferAddLit(buf, " </source>\n");
} }
break; break;
case VIR_DOMAIN_DISK_TYPE_VOLUME:
/* Parsing guarantees the def->srcpool->volume cannot be NULL
* if def->srcpool->pool is not NULL.
*/
if (def->srcpool->pool)
virBufferAsprintf(buf, " <source pool='%s' volume='%s'/>\n",
def->srcpool->pool, def->srcpool->volume);
break;
default: default:
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"), _("unexpected disk type %s"),

View File

@ -447,6 +447,7 @@ enum virDomainDiskType {
VIR_DOMAIN_DISK_TYPE_FILE, VIR_DOMAIN_DISK_TYPE_FILE,
VIR_DOMAIN_DISK_TYPE_DIR, VIR_DOMAIN_DISK_TYPE_DIR,
VIR_DOMAIN_DISK_TYPE_NETWORK, VIR_DOMAIN_DISK_TYPE_NETWORK,
VIR_DOMAIN_DISK_TYPE_VOLUME,
VIR_DOMAIN_DISK_TYPE_LAST VIR_DOMAIN_DISK_TYPE_LAST
}; };
@ -606,6 +607,13 @@ struct _virDomainBlockIoTuneInfo {
}; };
typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr; typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
typedef struct _virDomainDiskSourcePoolDef virDomainDiskSourcePoolDef;
struct _virDomainDiskSourcePoolDef {
char *pool; /* pool name */
char *volume; /* volume name */
};
typedef virDomainDiskSourcePoolDef *virDomainDiskSourcePoolDefPtr;
/* Stores the virtual disk configuration */ /* Stores the virtual disk configuration */
struct _virDomainDiskDef { struct _virDomainDiskDef {
int type; int type;
@ -617,6 +625,7 @@ struct _virDomainDiskDef {
int protocol; int protocol;
size_t nhosts; size_t nhosts;
virDomainDiskHostDefPtr hosts; virDomainDiskHostDefPtr hosts;
virDomainDiskSourcePoolDefPtr srcpool;
struct { struct {
char *username; char *username;
int secretType; /* enum virDomainDiskSecretType */ int secretType; /* enum virDomainDiskSecretType */

View File

@ -0,0 +1,33 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='volume' device='cdrom'>
<source pool='blk-pool0' volume='blk-pool0-vol0'/>
<target dev='hda' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<disk type='file' device='disk'>
<source file='/tmp/idedisk.img'/>
<target dev='hdc' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='ide' index='1'/>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -253,6 +253,7 @@ mymain(void)
DO_TEST("disk-scsi-lun-passthrough-sgio"); DO_TEST("disk-scsi-lun-passthrough-sgio");
DO_TEST("disk-scsi-disk-vpd"); DO_TEST("disk-scsi-disk-vpd");
DO_TEST("disk-source-pool");
DO_TEST("virtio-rng-random"); DO_TEST("virtio-rng-random");
DO_TEST("virtio-rng-egd"); DO_TEST("virtio-rng-egd");