Support QEMU's virtual FAT block device driver

Introduce a new type="dir"  mode for <disks> that allows use of
QEMU's  virtual FAT block device driver. eg

    <disk type='dir' device='floppy'>
      <source dir='/tmp/test'/>
      <target dev='fda' bus='fdc'/>
      <readonly/>
    </disk>

gets turned into

  -drive file=fat:floppy:/tmp/test,if=floppy,index=0

Only read-only disks are supported with virtual FAT mode

* src/conf/domain_conf.c, src/conf/domain_conf.h: Add type="dir"
* docs/schemas/domain.rng: Document new disk type
* src/xen/xend_internal.c, src/xen/xm_internal.c: Raise error for
  unsupported disk types
* tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-empty.args: Fix
  empty disk file handling
* tests/qemuxml2argvdata/qemuxml2argv-disk-drive-fat.args,
  tests/qemuxml2argvdata/qemuxml2argv-disk-drive-fat.xml,
  tests/qemuxml2argvdata/qemuxml2argv-floppy-drive-fat.args,
  tests/qemuxml2argvdata/qemuxml2argv-floppy-drive-fat.xml
  tests/qemuxml2argvtest.c: Test QEMU vitual FAT driver
* src/qemu/qemu_conf.c: Support generating fat:/some/dir type
  disk args
* src/security/security_selinux.c: Temporarily skip labelling
  of directory based disks
This commit is contained in:
Daniel P. Berrange 2009-11-16 18:08:29 +00:00
parent a73cd93b24
commit e7c78b0a94
14 changed files with 173 additions and 13 deletions

View File

@ -434,6 +434,22 @@
<ref name="diskspec"/> <ref name="diskspec"/>
</interleave> </interleave>
</group> </group>
<group>
<attribute name="type">
<value>dir</value>
</attribute>
<interleave>
<optional>
<element name="source">
<attribute name="dir">
<ref name="absFilePath"/>
</attribute>
<empty/>
</element>
</optional>
<ref name="diskspec"/>
</interleave>
</group>
<ref name="diskspec"/> <ref name="diskspec"/>
</choice> </choice>
</element> </element>

View File

@ -90,7 +90,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
"block", "block",
"file") "file",
"dir")
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST, VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
"disk", "disk",
@ -777,10 +778,22 @@ virDomainDiskDefParseXML(virConnectPtr conn,
if ((source == NULL) && if ((source == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "source"))) { (xmlStrEqual(cur->name, BAD_CAST "source"))) {
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) switch (def->type) {
case VIR_DOMAIN_DISK_TYPE_FILE:
source = virXMLPropString(cur, "file"); source = virXMLPropString(cur, "file");
else break;
case VIR_DOMAIN_DISK_TYPE_BLOCK:
source = virXMLPropString(cur, "dev"); source = virXMLPropString(cur, "dev");
break;
case VIR_DOMAIN_DISK_TYPE_DIR:
source = virXMLPropString(cur, "dir");
break;
default:
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"),
virDomainDiskTypeToString(def->type));
goto error;
}
/* People sometimes pass a bogus '' source path /* People sometimes pass a bogus '' source path
when they mean to omit the source element when they mean to omit the source element
@ -3951,12 +3964,25 @@ virDomainDiskDefFormat(virConnectPtr conn,
} }
if (def->src) { if (def->src) {
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) switch (def->type) {
case VIR_DOMAIN_DISK_TYPE_FILE:
virBufferEscapeString(buf, " <source file='%s'/>\n", virBufferEscapeString(buf, " <source file='%s'/>\n",
def->src); def->src);
else break;
case VIR_DOMAIN_DISK_TYPE_BLOCK:
virBufferEscapeString(buf, " <source dev='%s'/>\n", virBufferEscapeString(buf, " <source dev='%s'/>\n",
def->src); def->src);
break;
case VIR_DOMAIN_DISK_TYPE_DIR:
virBufferEscapeString(buf, " <source dir='%s'/>\n",
def->src);
break;
default:
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"),
virDomainDiskTypeToString(def->type));
return -1;
}
} }
virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n", virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n",

View File

@ -67,6 +67,7 @@ enum virDomainVirtType {
enum virDomainDiskType { enum virDomainDiskType {
VIR_DOMAIN_DISK_TYPE_BLOCK, VIR_DOMAIN_DISK_TYPE_BLOCK,
VIR_DOMAIN_DISK_TYPE_FILE, VIR_DOMAIN_DISK_TYPE_FILE,
VIR_DOMAIN_DISK_TYPE_DIR,
VIR_DOMAIN_DISK_TYPE_LAST VIR_DOMAIN_DISK_TYPE_LAST
}; };

View File

@ -1994,8 +1994,30 @@ int qemudBuildCommandLine(virConnectPtr conn,
break; break;
} }
virBufferVSprintf(&opt, "file=%s", disk->src ? disk->src : ""); if (disk->src) {
virBufferVSprintf(&opt, ",if=%s", bus); if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
/* QEMU only supports magic FAT format for now */
if (disk->driverType &&
STRNEQ(disk->driverType, "fat")) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("unsupported disk driver type for '%s'"),
disk->driverType);
goto error;
}
if (!disk->readonly) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot create virtual FAT disks in read-write mode"));
goto error;
}
if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
virBufferVSprintf(&opt, "file=fat:floppy:%s,", disk->src);
else
virBufferVSprintf(&opt, "file=fat:%s,", disk->src);
} else {
virBufferVSprintf(&opt, "file=%s,", disk->src);
}
}
virBufferVSprintf(&opt, "if=%s", bus);
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
virBufferAddLit(&opt, ",media=cdrom"); virBufferAddLit(&opt, ",media=cdrom");
virBufferVSprintf(&opt, ",index=%d", idx); virBufferVSprintf(&opt, ",index=%d", idx);
@ -2003,6 +2025,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
virBufferAddLit(&opt, ",boot=on"); virBufferAddLit(&opt, ",boot=on");
if (disk->driverType && if (disk->driverType &&
disk->type != VIR_DOMAIN_DISK_TYPE_DIR &&
qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_FORMAT) qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE_FORMAT)
virBufferVSprintf(&opt, ",format=%s", disk->driverType); virBufferVSprintf(&opt, ",format=%s", disk->driverType);
if (disk->serial && if (disk->serial &&
@ -2071,7 +2094,27 @@ int qemudBuildCommandLine(virConnectPtr conn,
} }
} }
snprintf(file, PATH_MAX, "%s", disk->src); if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
/* QEMU only supports magic FAT format for now */
if (disk->driverType &&
STRNEQ(disk->driverType, "fat")) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("unsupported disk driver type for '%s'"),
disk->driverType);
goto error;
}
if (!disk->readonly) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot create virtual FAT disks in read-write mode"));
goto error;
}
if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src);
else
snprintf(file, PATH_MAX, "fat:%s", disk->src);
} else {
snprintf(file, PATH_MAX, "%s", disk->src);
}
ADD_ARG_LIT(dev); ADD_ARG_LIT(dev);
ADD_ARG_LIT(file); ADD_ARG_LIT(file);

View File

@ -687,6 +687,9 @@ SELinuxSetSecurityLabel(virConnectPtr conn,
if (secdef->imagelabel) { if (secdef->imagelabel) {
for (i = 0 ; i < vm->def->ndisks ; i++) { for (i = 0 ; i < vm->def->ndisks ; i++) {
/* XXX fixme - we need to recursively label the entriy tree :-( */
if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR)
continue;
if (SELinuxSetSecurityImageLabel(conn, vm, vm->def->disks[i]) < 0) if (SELinuxSetSecurityImageLabel(conn, vm, vm->def->disks[i]) < 0)
return -1; return -1;
} }

View File

@ -5375,11 +5375,16 @@ xenDaemonFormatSxprDisk(virConnectPtr conn ATTRIBUTE_UNUSED,
} else { } else {
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) { if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
virBufferVSprintf(buf, "(uname 'file:%s')", def->src); virBufferVSprintf(buf, "(uname 'file:%s')", def->src);
} else { } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
if (def->src[0] == '/') if (def->src[0] == '/')
virBufferVSprintf(buf, "(uname 'phy:%s')", def->src); virBufferVSprintf(buf, "(uname 'phy:%s')", def->src);
else else
virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", def->src); virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", def->src);
} else {
virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED,
_("unsupported disk type %s"),
virDomainDiskTypeToString(def->type));
return -1;
} }
} }
} }

View File

@ -1973,9 +1973,19 @@ static int xenXMDomainConfigFormatDisk(virConnectPtr conn,
if (STREQ(disk->driverName, "tap")) if (STREQ(disk->driverName, "tap"))
virBufferVSprintf(&buf, "%s:", disk->driverType ? disk->driverType : "aio"); virBufferVSprintf(&buf, "%s:", disk->driverType ? disk->driverType : "aio");
} else { } else {
virBufferVSprintf(&buf, "%s:", switch (disk->type) {
disk->type == VIR_DOMAIN_DISK_TYPE_FILE ? case VIR_DOMAIN_DISK_TYPE_FILE:
"file" : "phy"); virBufferAddLit(&buf, "file:");
break;
case VIR_DOMAIN_DISK_TYPE_BLOCK:
virBufferAddLit(&buf, "phy:");
break;
default:
xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
_("unsupported disk type %s"),
virDomainDiskTypeToString(disk->type));
goto cleanup;
}
} }
virBufferVSprintf(&buf, "%s", disk->src); virBufferVSprintf(&buf, "%s", disk->src);
} }

View File

@ -1 +1 @@
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -drive file=/dev/HostVG/QEMUGuest1,if=ide,index=0 -drive file=,if=ide,media=cdrom,index=2 -net none -serial none -parallel none -usb LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -drive file=/dev/HostVG/QEMUGuest1,if=ide,index=0 -drive if=ide,media=cdrom,index=2 -net none -serial none -parallel none -usb

View File

@ -0,0 +1 @@
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -drive file=fat:/var/somefiles,if=ide,index=0,boot=on -net none -serial none -parallel none -usb

View File

@ -0,0 +1,24 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory>219200</memory>
<currentMemory>219200</currentMemory>
<vcpu>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='dir' device='disk'>
<driver name='qemu' type='fat'/>
<source dir='/var/somefiles'/>
<target dev='hda' bus='ide'/>
<readonly/>
</disk>
</devices>
</domain>

View File

@ -0,0 +1 @@
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot a -drive file=fat:floppy:/var/somefiles,if=floppy,index=0 -net none -serial none -parallel none -usb

View File

@ -0,0 +1,24 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory>219200</memory>
<currentMemory>219200</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='fd'/>
</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='dir' device='floppy'>
<driver name='qemu' type='fat'/>
<source dir='/var/somefiles'/>
<target dev='fda' bus='fdc'/>
<readonly/>
</disk>
</devices>
</domain>

View File

@ -211,6 +211,10 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_DRIVE_BOOT); QEMUD_CMD_FLAG_DRIVE_BOOT);
DO_TEST("disk-drive-boot-cdrom", QEMUD_CMD_FLAG_DRIVE | DO_TEST("disk-drive-boot-cdrom", QEMUD_CMD_FLAG_DRIVE |
QEMUD_CMD_FLAG_DRIVE_BOOT); QEMUD_CMD_FLAG_DRIVE_BOOT);
DO_TEST("floppy-drive-fat", QEMUD_CMD_FLAG_DRIVE |
QEMUD_CMD_FLAG_DRIVE_BOOT | QEMUD_CMD_FLAG_DRIVE_FORMAT);
DO_TEST("disk-drive-fat", QEMUD_CMD_FLAG_DRIVE |
QEMUD_CMD_FLAG_DRIVE_BOOT | QEMUD_CMD_FLAG_DRIVE_FORMAT);
DO_TEST("disk-drive-fmt-qcow", QEMUD_CMD_FLAG_DRIVE | DO_TEST("disk-drive-fmt-qcow", QEMUD_CMD_FLAG_DRIVE |
QEMUD_CMD_FLAG_DRIVE_BOOT | QEMUD_CMD_FLAG_DRIVE_FORMAT); QEMUD_CMD_FLAG_DRIVE_BOOT | QEMUD_CMD_FLAG_DRIVE_FORMAT);
DO_TEST("disk-drive-shared", QEMUD_CMD_FLAG_DRIVE | DO_TEST("disk-drive-shared", QEMUD_CMD_FLAG_DRIVE |

View File

@ -98,6 +98,8 @@ mymain(int argc, char **argv)
DO_TEST("disk-many"); DO_TEST("disk-many");
DO_TEST("disk-xenvbd"); DO_TEST("disk-xenvbd");
DO_TEST("disk-usb"); DO_TEST("disk-usb");
DO_TEST("floppy-drive-fat");
DO_TEST("disk-drive-fat");
DO_TEST("disk-drive-fmt-qcow"); DO_TEST("disk-drive-fmt-qcow");
DO_TEST("disk-drive-cache-v1-wt"); DO_TEST("disk-drive-cache-v1-wt");
DO_TEST("disk-drive-cache-v1-wb"); DO_TEST("disk-drive-cache-v1-wb");