You need to sign in or sign up before continuing.
提交 627f489e 编写于 作者: P Peter Krempa

qemu: command: Separate validation from command line building for -drive

Remove validation code into a separate function so that it's not
interleaved with actual building of the command line.
上级 57b17c8d
...@@ -1481,24 +1481,16 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk, ...@@ -1481,24 +1481,16 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk,
} }
char * static int
qemuBuildDriveStr(virDomainDiskDefPtr disk, qemuBuildDriveStrValidate(virDomainDiskDefPtr disk,
virQEMUDriverConfigPtr cfg, virQEMUCapsPtr qemuCaps,
bool bootable, const char *bus,
virQEMUCapsPtr qemuCaps) int idx)
{ {
virBuffer opt = VIR_BUFFER_INITIALIZER;
const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
const char *trans =
virDomainDiskGeometryTransTypeToString(disk->geometry.trans);
int idx = virDiskNameToIndex(disk->dst);
int busid = -1, unitid = -1;
bool emitDeviceSyntax = qemuDiskBusNeedsDeviceArg(disk->bus);
if (idx < 0) { if (idx < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("unsupported disk type '%s'"), disk->dst); _("unsupported disk type '%s'"), disk->dst);
goto error; return -1;
} }
switch (disk->bus) { switch (disk->bus) {
...@@ -1506,7 +1498,7 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, ...@@ -1506,7 +1498,7 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) { if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unexpected address type for scsi disk")); _("unexpected address type for scsi disk"));
goto error; return -1;
} }
/* Setting bus= attr for SCSI drives, causes a controller /* Setting bus= attr for SCSI drives, causes a controller
...@@ -1515,53 +1507,173 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, ...@@ -1515,53 +1507,173 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
if (disk->info.addr.drive.bus != 0) { if (disk->info.addr.drive.bus != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("SCSI controller only supports 1 bus")); "%s", _("SCSI controller only supports 1 bus"));
goto error; return -1;
} }
busid = disk->info.addr.drive.controller;
unitid = disk->info.addr.drive.unit;
break; break;
case VIR_DOMAIN_DISK_BUS_IDE: case VIR_DOMAIN_DISK_BUS_IDE:
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) { if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unexpected address type for ide disk")); _("unexpected address type for ide disk"));
goto error; return -1;
} }
/* We can only have 1 IDE controller (currently) */ /* We can only have 1 IDE controller (currently) */
if (disk->info.addr.drive.controller != 0) { if (disk->info.addr.drive.controller != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Only 1 %s controller is supported"), bus); _("Only 1 %s controller is supported"), bus);
goto error; return -1;
} }
busid = disk->info.addr.drive.bus;
unitid = disk->info.addr.drive.unit;
break; break;
case VIR_DOMAIN_DISK_BUS_FDC: case VIR_DOMAIN_DISK_BUS_FDC:
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) { if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unexpected address type for fdc disk")); _("unexpected address type for fdc disk"));
goto error; return -1;
} }
/* We can only have 1 FDC controller (currently) */ /* We can only have 1 FDC controller (currently) */
if (disk->info.addr.drive.controller != 0) { if (disk->info.addr.drive.controller != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Only 1 %s controller is supported"), bus); _("Only 1 %s controller is supported"), bus);
goto error; return -1;
} }
/* We can only have 1 FDC bus (currently) */ /* We can only have 1 FDC bus (currently) */
if (disk->info.addr.drive.bus != 0) { if (disk->info.addr.drive.bus != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Only 1 %s bus is supported"), bus); _("Only 1 %s bus is supported"), bus);
goto error; return -1;
} }
if (disk->info.addr.drive.target != 0) { if (disk->info.addr.drive.target != 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("target must be 0 for controller fdc")); _("target must be 0 for controller fdc"));
goto error; return -1;
} }
break;
case VIR_DOMAIN_DISK_BUS_VIRTIO:
case VIR_DOMAIN_DISK_BUS_XEN:
case VIR_DOMAIN_DISK_BUS_SD:
break;
}
if (disk->src->readonly &&
disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
if (disk->bus == VIR_DOMAIN_DISK_BUS_IDE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("readonly ide disks are not supported"));
return -1;
}
if (disk->bus == VIR_DOMAIN_DISK_BUS_SATA) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("readonly sata disks are not supported"));
return -1;
}
}
if (disk->transient) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("transient disks not supported yet"));
return -1;
}
if (disk->serial &&
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_SERIAL)) {
if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("scsi-block 'lun' devices do not support the "
"serial property"));
return -1;
}
}
if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_DIRECTSYNC &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("disk cache mode 'directsync' is not supported by this QEMU"));
return -1;
}
if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_UNSAFE &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_CACHE_UNSAFE)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("disk cache mode 'unsafe' is not supported by this QEMU"));
return -1;
}
if (disk->iomode == VIR_DOMAIN_DISK_IO_NATIVE &&
disk->cachemode != VIR_DOMAIN_DISK_CACHE_DIRECTSYNC &&
disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("native I/O needs either no disk cache "
"or directsync cache mode, QEMU will fallback "
"to aio=threads"));
return -1;
}
if (disk->copy_on_read &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_COPY_ON_READ)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("copy_on_read is not supported by this QEMU binary"));
return -1;
}
if (disk->discard &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DISCARD)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("discard is not supported by this QEMU binary"));
return -1;
}
if (disk->detect_zeroes &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DETECT_ZEROES)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("detect_zeroes is not supported by this QEMU binary"));
return -1;
}
if (disk->iomode &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_AIO)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("disk aio mode not supported with this QEMU binary"));
return -1;
}
return 0;
}
char *
qemuBuildDriveStr(virDomainDiskDefPtr disk,
virQEMUDriverConfigPtr cfg,
bool bootable,
virQEMUCapsPtr qemuCaps)
{
virBuffer opt = VIR_BUFFER_INITIALIZER;
const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
const char *trans =
virDomainDiskGeometryTransTypeToString(disk->geometry.trans);
int idx = virDiskNameToIndex(disk->dst);
int busid = -1, unitid = -1;
bool emitDeviceSyntax = qemuDiskBusNeedsDeviceArg(disk->bus);
if (qemuBuildDriveStrValidate(disk, qemuCaps, bus, idx) < 0)
goto error;
switch (disk->bus) {
case VIR_DOMAIN_DISK_BUS_SCSI:
busid = disk->info.addr.drive.controller;
unitid = disk->info.addr.drive.unit; unitid = disk->info.addr.drive.unit;
break;
case VIR_DOMAIN_DISK_BUS_IDE:
busid = disk->info.addr.drive.bus;
unitid = disk->info.addr.drive.unit;
break;
case VIR_DOMAIN_DISK_BUS_FDC:
unitid = disk->info.addr.drive.unit;
break; break;
case VIR_DOMAIN_DISK_BUS_VIRTIO: case VIR_DOMAIN_DISK_BUS_VIRTIO:
...@@ -1618,26 +1730,8 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, ...@@ -1618,26 +1730,8 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) && disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) &&
disk->bus != VIR_DOMAIN_DISK_BUS_IDE) disk->bus != VIR_DOMAIN_DISK_BUS_IDE)
virBufferAddLit(&opt, ",boot=on"); virBufferAddLit(&opt, ",boot=on");
if (disk->src->readonly) { if (disk->src->readonly)
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
if (disk->bus == VIR_DOMAIN_DISK_BUS_IDE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("readonly ide disks are not supported"));
goto error;
}
if (disk->bus == VIR_DOMAIN_DISK_BUS_SATA) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("readonly sata disks are not supported"));
goto error;
}
}
virBufferAddLit(&opt, ",readonly=on"); virBufferAddLit(&opt, ",readonly=on");
}
if (disk->transient) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("transient disks not supported yet"));
goto error;
}
/* generate geometry command string */ /* generate geometry command string */
if (disk->geometry.cylinders > 0 && if (disk->geometry.cylinders > 0 &&
...@@ -1657,95 +1751,43 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, ...@@ -1657,95 +1751,43 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_SERIAL)) { virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_SERIAL)) {
if (qemuSafeSerialParamValue(disk->serial) < 0) if (qemuSafeSerialParamValue(disk->serial) < 0)
goto error; goto error;
if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("scsi-block 'lun' devices do not support the "
"serial property"));
goto error;
}
virBufferAddLit(&opt, ",serial="); virBufferAddLit(&opt, ",serial=");
virBufferEscape(&opt, '\\', " ", "%s", disk->serial); virBufferEscape(&opt, '\\', " ", "%s", disk->serial);
} }
if (disk->cachemode) { if (disk->cachemode) {
const char *mode = NULL; virBufferAsprintf(&opt, ",cache=%s",
qemuDiskCacheV2TypeToString(disk->cachemode));
mode = qemuDiskCacheV2TypeToString(disk->cachemode);
if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_DIRECTSYNC &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("disk cache mode 'directsync' is not "
"supported by this QEMU"));
goto error;
} else if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_UNSAFE &&
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_CACHE_UNSAFE)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("disk cache mode 'unsafe' is not "
"supported by this QEMU"));
goto error;
}
if (disk->iomode == VIR_DOMAIN_DISK_IO_NATIVE &&
disk->cachemode != VIR_DOMAIN_DISK_CACHE_DIRECTSYNC &&
disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("native I/O needs either no disk cache "
"or directsync cache mode, QEMU will fallback "
"to aio=threads"));
goto error;
}
virBufferAsprintf(&opt, ",cache=%s", mode);
} else if (disk->src->shared && !disk->src->readonly) { } else if (disk->src->shared && !disk->src->readonly) {
virBufferAddLit(&opt, ",cache=none"); virBufferAddLit(&opt, ",cache=none");
} }
if (disk->copy_on_read) { if (disk->copy_on_read) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_COPY_ON_READ)) { virBufferAsprintf(&opt, ",copy-on-read=%s",
virBufferAsprintf(&opt, ",copy-on-read=%s", virTristateSwitchTypeToString(disk->copy_on_read));
virTristateSwitchTypeToString(disk->copy_on_read));
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("copy_on_read is not supported by this QEMU binary"));
goto error;
}
} }
if (disk->discard) { if (disk->discard) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DISCARD)) { virBufferAsprintf(&opt, ",discard=%s",
virBufferAsprintf(&opt, ",discard=%s", virDomainDiskDiscardTypeToString(disk->discard));
virDomainDiskDiscardTypeToString(disk->discard));
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("discard is not supported by this QEMU binary"));
goto error;
}
} }
if (disk->detect_zeroes) { if (disk->detect_zeroes) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DETECT_ZEROES)) { int detect_zeroes = disk->detect_zeroes;
int detect_zeroes = disk->detect_zeroes;
/*
* As a convenience syntax, if discards are ignored and
* zero detection is set to 'unmap', then simply behave
* like zero detection is set to 'on'. But don't change
* it in the XML for easier adjustments. This behaviour
* is documented.
*/
if (disk->discard != VIR_DOMAIN_DISK_DISCARD_UNMAP &&
detect_zeroes == VIR_DOMAIN_DISK_DETECT_ZEROES_UNMAP)
detect_zeroes = VIR_DOMAIN_DISK_DETECT_ZEROES_ON;
virBufferAsprintf(&opt, ",detect-zeroes=%s", /*
virDomainDiskDetectZeroesTypeToString(detect_zeroes)); * As a convenience syntax, if discards are ignored and
} else { * zero detection is set to 'unmap', then simply behave
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", * like zero detection is set to 'on'. But don't change
_("detect_zeroes is not supported by this QEMU binary")); * it in the XML for easier adjustments. This behaviour
goto error; * is documented.
} */
if (disk->discard != VIR_DOMAIN_DISK_DISCARD_UNMAP &&
detect_zeroes == VIR_DOMAIN_DISK_DETECT_ZEROES_UNMAP)
detect_zeroes = VIR_DOMAIN_DISK_DETECT_ZEROES_ON;
virBufferAsprintf(&opt, ",detect-zeroes=%s",
virDomainDiskDetectZeroesTypeToString(detect_zeroes));
} }
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MONITOR_JSON)) { if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
...@@ -1774,15 +1816,8 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, ...@@ -1774,15 +1816,8 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
} }
if (disk->iomode) { if (disk->iomode) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_AIO)) { virBufferAsprintf(&opt, ",aio=%s",
virBufferAsprintf(&opt, ",aio=%s", virDomainDiskIoTypeToString(disk->iomode));
virDomainDiskIoTypeToString(disk->iomode));
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("disk aio mode not supported with this "
"QEMU binary"));
goto error;
}
} }
if (qemuCheckDiskConfigBlkdeviotune(disk, qemuCaps) < 0) if (qemuCheckDiskConfigBlkdeviotune(disk, qemuCaps) < 0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册