mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 03:12:22 +00:00
qemu: Move disk config validation to qemuValidateDomainDeviceDefDiskFrontend
Previously we've validated it in qemuCheckDiskConfig which was directly called from the command line generator. Move the checks to the validator where they belong. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
ca03369c99
commit
8b5cf013ef
@ -651,23 +651,6 @@ qemuBuildIoEventFdStr(virBufferPtr buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ .+"
|
||||
|
||||
static int
|
||||
qemuSafeSerialParamValue(const char *value)
|
||||
{
|
||||
if (strspn(value, QEMU_SERIAL_PARAM_ACCEPTED_CHARS) != strlen(value)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("driver serial '%s' contains unsafe characters"),
|
||||
value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qemuBuildSecretInfoProps:
|
||||
* @secinfo: pointer to the secret info object
|
||||
@ -1140,191 +1123,10 @@ qemuDiskConfigBlkdeviotuneEnabled(virDomainDiskDefPtr disk)
|
||||
* error reported.
|
||||
*/
|
||||
int
|
||||
qemuCheckDiskConfig(virDomainDiskDefPtr disk,
|
||||
qemuCheckDiskConfig(virDomainDiskDefPtr disk G_GNUC_UNUSED,
|
||||
const virDomainDef *def G_GNUC_UNUSED,
|
||||
virQEMUCapsPtr qemuCaps)
|
||||
virQEMUCapsPtr qemuCaps G_GNUC_UNUSED)
|
||||
{
|
||||
if (disk->wwn) {
|
||||
if ((disk->bus != VIR_DOMAIN_DISK_BUS_IDE) &&
|
||||
(disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only ide and scsi disk support wwn"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((disk->vendor || disk->product) &&
|
||||
disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only scsi disk supports vendor and product"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
||||
/* make sure that both the bus supports type='lun' (SG_IO). */
|
||||
if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO &&
|
||||
disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("disk device='lun' is not supported for bus='%s'"),
|
||||
virDomainDiskBusTypeToString(disk->bus));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
|
||||
disk->src->format != VIR_STORAGE_FILE_RAW) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("disk device 'lun' using target 'scsi' must use "
|
||||
"'raw' format"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qemuDomainDefValidateDiskLunSource(disk->src) < 0)
|
||||
return -1;
|
||||
|
||||
if (disk->wwn) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Setting wwn is not supported for lun device"));
|
||||
return -1;
|
||||
}
|
||||
if (disk->vendor || disk->product) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Setting vendor or product is not supported "
|
||||
"for lun device"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (disk->bus) {
|
||||
case VIR_DOMAIN_DISK_BUS_SCSI:
|
||||
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unexpected address type for scsi disk"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setting bus= attr for SCSI drives, causes a controller
|
||||
* to be created. Yes this is slightly odd. It is not possible
|
||||
* to have > 1 bus on a SCSI controller (yet). */
|
||||
if (disk->info.addr.drive.bus != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("SCSI controller only supports 1 bus"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DISK_BUS_IDE:
|
||||
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unexpected address type for ide disk"));
|
||||
return -1;
|
||||
}
|
||||
/* We can only have 1 IDE controller (currently) */
|
||||
if (disk->info.addr.drive.controller != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Only 1 IDE controller is supported"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DISK_BUS_FDC:
|
||||
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unexpected address type for fdc disk"));
|
||||
return -1;
|
||||
}
|
||||
/* We can only have 1 FDC controller (currently) */
|
||||
if (disk->info.addr.drive.controller != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Only 1 fdc controller is supported"));
|
||||
return -1;
|
||||
}
|
||||
/* We can only have 1 FDC bus (currently) */
|
||||
if (disk->info.addr.drive.bus != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Only 1 fdc bus is supported"));
|
||||
return -1;
|
||||
}
|
||||
if (disk->info.addr.drive.target != 0) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("target must be 0 for controller fdc"));
|
||||
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->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 (qemuCaps) {
|
||||
if (disk->serial &&
|
||||
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->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 == VIR_DOMAIN_DISK_IO_URING) {
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_AIO_IO_URING)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("io uring is not supported by this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disk->serial &&
|
||||
qemuSafeSerialParamValue(disk->serial) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1897,8 +1897,26 @@ qemuValidateDomainDeviceDefVideo(const virDomainVideoDef *video,
|
||||
}
|
||||
|
||||
|
||||
#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ .+"
|
||||
|
||||
static int
|
||||
qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk)
|
||||
qemuValidateDomainDeviceDefDiskSerial(const char *value)
|
||||
{
|
||||
if (strspn(value, QEMU_SERIAL_PARAM_ACCEPTED_CHARS) != strlen(value)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("driver serial '%s' contains unsafe characters"),
|
||||
value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk,
|
||||
virQEMUCapsPtr qemuCaps)
|
||||
{
|
||||
if (disk->geometry.cylinders > 0 &&
|
||||
disk->geometry.heads > 0 &&
|
||||
@ -1952,6 +1970,188 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk)
|
||||
}
|
||||
}
|
||||
|
||||
if (disk->wwn) {
|
||||
if ((disk->bus != VIR_DOMAIN_DISK_BUS_IDE) &&
|
||||
(disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only ide and scsi disk support wwn"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((disk->vendor || disk->product) &&
|
||||
disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only scsi disk supports vendor and product"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
||||
/* make sure that both the bus supports type='lun' (SG_IO). */
|
||||
if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO &&
|
||||
disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("disk device='lun' is not supported for bus='%s'"),
|
||||
virDomainDiskBusTypeToString(disk->bus));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
|
||||
disk->src->format != VIR_STORAGE_FILE_RAW) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("disk device 'lun' using target 'scsi' must use "
|
||||
"'raw' format"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qemuDomainDefValidateDiskLunSource(disk->src) < 0)
|
||||
return -1;
|
||||
|
||||
if (disk->wwn) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Setting wwn is not supported for lun device"));
|
||||
return -1;
|
||||
}
|
||||
if (disk->vendor || disk->product) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Setting vendor or product is not supported "
|
||||
"for lun device"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (disk->bus) {
|
||||
case VIR_DOMAIN_DISK_BUS_SCSI:
|
||||
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unexpected address type for scsi disk"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setting bus= attr for SCSI drives, causes a controller
|
||||
* to be created. Yes this is slightly odd. It is not possible
|
||||
* to have > 1 bus on a SCSI controller (yet). */
|
||||
if (disk->info.addr.drive.bus != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("SCSI controller only supports 1 bus"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DISK_BUS_IDE:
|
||||
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unexpected address type for ide disk"));
|
||||
return -1;
|
||||
}
|
||||
/* We can only have 1 IDE controller (currently) */
|
||||
if (disk->info.addr.drive.controller != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Only 1 IDE controller is supported"));
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_DISK_BUS_FDC:
|
||||
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unexpected address type for fdc disk"));
|
||||
return -1;
|
||||
}
|
||||
/* We can only have 1 FDC controller (currently) */
|
||||
if (disk->info.addr.drive.controller != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Only 1 fdc controller is supported"));
|
||||
return -1;
|
||||
}
|
||||
/* We can only have 1 FDC bus (currently) */
|
||||
if (disk->info.addr.drive.bus != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Only 1 fdc bus is supported"));
|
||||
return -1;
|
||||
}
|
||||
if (disk->info.addr.drive.target != 0) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("target must be 0 for controller fdc"));
|
||||
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->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 (qemuCaps) {
|
||||
if (disk->serial &&
|
||||
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->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 == VIR_DOMAIN_DISK_IO_URING) {
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_AIO_IO_URING)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("io uring is not supported by this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disk->serial &&
|
||||
qemuValidateDomainDeviceDefDiskSerial(disk->serial) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2062,7 +2262,7 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk,
|
||||
int idx;
|
||||
int partition;
|
||||
|
||||
if (qemuValidateDomainDeviceDefDiskFrontend(disk) < 0)
|
||||
if (qemuValidateDomainDeviceDefDiskFrontend(disk, qemuCaps) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuValidateDomainDeviceDefDiskBlkdeviotune(disk, def, qemuCaps) < 0)
|
||||
|
@ -1115,7 +1115,7 @@ mymain(void)
|
||||
QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_DISK_WWN);
|
||||
DO_TEST("disk-scsi-disk-vpd",
|
||||
QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_DISK_WWN);
|
||||
DO_TEST_FAILURE("disk-scsi-disk-vpd-build-error",
|
||||
DO_TEST_PARSE_ERROR("disk-scsi-disk-vpd-build-error",
|
||||
QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_DISK_WWN);
|
||||
DO_TEST_CAPS_LATEST("controller-virtio-scsi");
|
||||
DO_TEST("disk-sata-device",
|
||||
|
Loading…
x
Reference in New Issue
Block a user