mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 02:51:16 +00:00
qemuBuildDiskCommandLine: Generate via JSON
The types for the special fields of the 'virtio-blk-pci' according to QEMU are: iothread=<link<iothread>> ioeventfd=<bool> - on/off (default: true) event_idx=<bool> - on/off (default: true) scsi=<bool> - on/off (default: false) num-queues=<uint16> - (default: 65535) queue-size=<uint16> - (default: 256) For all disks we also use the following properties (based on 'scsi-hd'): device_id=<str> share-rw=<bool> - (default: false) drive=<str> - Node name or ID of a block device to use as a backend chardev=<str> - ID of a chardev to use as a backend <- vhost-user-blk-pci bootindex=<int32> logical_block_size=<size> - A power of two between 512 B and 2 MiB (default: 0) physical_block_size=<size> - A power of two between 512 B and 2 MiB (default: 0) wwn=<uint64> - (default: 0) rotation_rate=<uint16> - (default: 0) vendor=<str> product=<str> removable=<bool> - on/off (default: false) write-cache=<OnOffAuto> - on/off/auto (default: "auto") cyls=<uint32> - (default: 0) heads=<uint32> - (default: 0) secs=<uint32> - (default: 0) bios-chs-trans=<BiosAtaTranslation> - Logical CHS translation algorithm, auto/none/lba/large/rechs (default: "auto") <- ide-hd serial=<str> werror=<BlockdevOnError> - Error handling policy, report/ignore/enospc/stop/auto (default: "auto") rerror=<BlockdevOnError> - Error handling policy, report/ignore/enospc/stop/auto (default: "auto") The 'wwn' field is changed from a hex string to a number since qemu actually treats it as a number. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
d06e3000c4
commit
dc481f11a6
@ -2002,31 +2002,6 @@ qemuBuildDiskFrontendAttributeErrorPolicy(virDomainDiskDef *disk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
qemuBuildDiskFrontendAttributes(virDomainDiskDef *disk,
|
|
||||||
virBuffer *buf)
|
|
||||||
{
|
|
||||||
/* generate geometry command string */
|
|
||||||
if (disk->geometry.cylinders > 0 &&
|
|
||||||
disk->geometry.heads > 0 &&
|
|
||||||
disk->geometry.sectors > 0) {
|
|
||||||
virBufferAsprintf(buf, ",cyls=%u,heads=%u,secs=%u",
|
|
||||||
disk->geometry.cylinders,
|
|
||||||
disk->geometry.heads,
|
|
||||||
disk->geometry.sectors);
|
|
||||||
|
|
||||||
if (disk->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT)
|
|
||||||
virBufferAsprintf(buf, ",bios-chs-trans=%s",
|
|
||||||
virDomainDiskGeometryTransTypeToString(disk->geometry.trans));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disk->serial) {
|
|
||||||
virBufferAddLit(buf, ",serial=");
|
|
||||||
virBufferEscape(buf, '\\', " ", "%s", disk->serial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
qemuBuildDriveStr(virDomainDiskDef *disk,
|
qemuBuildDriveStr(virDomainDiskDef *disk,
|
||||||
virQEMUCaps *qemuCaps)
|
virQEMUCaps *qemuCaps)
|
||||||
@ -2099,82 +2074,46 @@ qemuBuildDriveStr(virDomainDiskDef *disk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
virJSONValue *
|
||||||
qemuBuildDriveDevCacheStr(virDomainDiskDef *disk,
|
qemuBuildDiskDeviceProps(const virDomainDef *def,
|
||||||
virBuffer *buf,
|
|
||||||
virQEMUCaps *qemuCaps)
|
|
||||||
{
|
|
||||||
bool wb;
|
|
||||||
|
|
||||||
if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_DEFAULT)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* VIR_DOMAIN_DISK_DEVICE_LUN translates into 'scsi-block'
|
|
||||||
* where any caching setting makes no sense. */
|
|
||||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_WRITE_CACHE))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (qemuDomainDiskCachemodeFlags(disk->cachemode, &wb, NULL, NULL) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
virBufferStrcat(buf, ",write-cache=",
|
|
||||||
virTristateSwitchTypeToString(virTristateSwitchFromBool(wb)),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
qemuBuildDiskDeviceStr(const virDomainDef *def,
|
|
||||||
virDomainDiskDef *disk,
|
virDomainDiskDef *disk,
|
||||||
virQEMUCaps *qemuCaps)
|
virQEMUCaps *qemuCaps)
|
||||||
{
|
{
|
||||||
g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
|
g_autoptr(virJSONValue) props = NULL;
|
||||||
const char *contAlias;
|
const char *driver = NULL;
|
||||||
g_autofree char *backendAlias = NULL;
|
|
||||||
g_autofree char *scsiVPDDeviceId = NULL;
|
g_autofree char *scsiVPDDeviceId = NULL;
|
||||||
int controllerModel;
|
virTristateSwitch shareRW = VIR_TRISTATE_SWITCH_ABSENT;
|
||||||
|
g_autofree char *chardev = NULL;
|
||||||
|
g_autofree char *drive = NULL;
|
||||||
|
unsigned int bootindex = 0;
|
||||||
|
unsigned int logical_block_size = 0;
|
||||||
|
unsigned int physical_block_size = 0;
|
||||||
|
g_autoptr(virJSONValue) wwn = NULL;
|
||||||
|
g_autofree char *serial = NULL;
|
||||||
|
virTristateSwitch removable = VIR_TRISTATE_SWITCH_ABSENT;
|
||||||
|
virTristateSwitch writeCache = VIR_TRISTATE_SWITCH_ABSENT;
|
||||||
|
const char *biosCHSTrans = NULL;
|
||||||
|
const char *wpolicy = NULL;
|
||||||
|
const char *rpolicy = NULL;
|
||||||
|
|
||||||
switch ((virDomainDiskBus) disk->bus) {
|
switch ((virDomainDiskBus) disk->bus) {
|
||||||
case VIR_DOMAIN_DISK_BUS_IDE:
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_SATA:
|
||||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
|
||||||
virBufferAddLit(&opt, "ide-cd");
|
driver = "ide-cd";
|
||||||
else
|
else
|
||||||
virBufferAddLit(&opt, "ide-hd");
|
driver = "ide-hd";
|
||||||
|
|
||||||
/* When domain has builtin IDE controller we don't put it onto cmd
|
|
||||||
* line. Therefore we can't set its alias. In that case, use the
|
|
||||||
* default one. */
|
|
||||||
if (qemuDomainHasBuiltinIDE(def)) {
|
|
||||||
contAlias = "ide";
|
|
||||||
} else {
|
|
||||||
if (!(contAlias = virDomainControllerAliasFind(def,
|
|
||||||
VIR_DOMAIN_CONTROLLER_TYPE_IDE,
|
|
||||||
disk->info.addr.drive.controller)))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
virBufferAsprintf(&opt, ",bus=%s.%d,unit=%d",
|
|
||||||
contAlias,
|
|
||||||
disk->info.addr.drive.bus,
|
|
||||||
disk->info.addr.drive.unit);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_DISK_BUS_SCSI:
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
||||||
controllerModel = qemuDomainFindSCSIControllerModel(def, &disk->info);
|
|
||||||
if (controllerModel < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
||||||
virBufferAddLit(&opt, "scsi-block");
|
driver = "scsi-block";
|
||||||
} else {
|
} else {
|
||||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
|
||||||
virBufferAddLit(&opt, "scsi-cd");
|
driver = "scsi-cd";
|
||||||
else
|
else
|
||||||
virBufferAddLit(&opt, "scsi-hd");
|
driver = "scsi-hd";
|
||||||
|
|
||||||
/* qemu historically used the name of -drive as one of the device
|
/* qemu historically used the name of -drive as one of the device
|
||||||
* ids in the Vital Product Data Device Identification page if
|
* ids in the Vital Product Data Device Identification page if
|
||||||
@ -2191,116 +2130,56 @@ qemuBuildDiskDeviceStr(const virDomainDef *def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(contAlias = virDomainControllerAliasFind(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
|
|
||||||
disk->info.addr.drive.controller)))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
switch ((virDomainControllerModelSCSI)controllerModel) {
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_NCR53C90:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DC390:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AM53C974:
|
|
||||||
virBufferAsprintf(&opt, ",bus=%s.%d,scsi-id=%d",
|
|
||||||
contAlias,
|
|
||||||
disk->info.addr.drive.bus,
|
|
||||||
disk->info.addr.drive.unit);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO:
|
case VIR_DOMAIN_DISK_BUS_VIRTIO: {
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC:
|
virTristateSwitch scsi = VIR_TRISTATE_SWITCH_ABSENT;
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068:
|
g_autofree char *iothread = NULL;
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL:
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL:
|
|
||||||
virBufferAsprintf(&opt, ",bus=%s.0,channel=%d,scsi-id=%d,lun=%d",
|
|
||||||
contAlias,
|
|
||||||
disk->info.addr.drive.bus,
|
|
||||||
disk->info.addr.drive.target,
|
|
||||||
disk->info.addr.drive.unit);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT:
|
if (disk->iothread > 0)
|
||||||
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST:
|
iothread = g_strdup_printf("iothread%u", disk->iothread);
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Unexpected SCSI controller model %d"),
|
|
||||||
controllerModel);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scsiVPDDeviceId)
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI)) {
|
||||||
virBufferStrcat(&opt, ",device_id=", scsiVPDDeviceId, NULL);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_DISK_BUS_SATA:
|
|
||||||
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
|
|
||||||
virBufferAddLit(&opt, "ide-cd");
|
|
||||||
else
|
|
||||||
virBufferAddLit(&opt, "ide-hd");
|
|
||||||
|
|
||||||
/* When domain has builtin SATA controller we don't put it onto cmd
|
|
||||||
* line. Therefore we can't set its alias. In that case, use the
|
|
||||||
* default one. */
|
|
||||||
if (qemuDomainIsQ35(def) &&
|
|
||||||
disk->info.addr.drive.controller == 0) {
|
|
||||||
contAlias = "ide";
|
|
||||||
} else {
|
|
||||||
if (!(contAlias = virDomainControllerAliasFind(def,
|
|
||||||
VIR_DOMAIN_CONTROLLER_TYPE_SATA,
|
|
||||||
disk->info.addr.drive.controller)))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
virBufferAsprintf(&opt, ",bus=%s.%d",
|
|
||||||
contAlias,
|
|
||||||
disk->info.addr.drive.unit);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_DISK_BUS_VIRTIO:
|
|
||||||
if (qemuBuildVirtioDevStr(&opt, qemuCaps, VIR_DOMAIN_DEVICE_DISK, disk) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (disk->iothread)
|
|
||||||
virBufferAsprintf(&opt, ",iothread=iothread%u", disk->iothread);
|
|
||||||
|
|
||||||
qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps);
|
|
||||||
if (disk->event_idx) {
|
|
||||||
virBufferAsprintf(&opt, ",event_idx=%s",
|
|
||||||
virTristateSwitchTypeToString(disk->event_idx));
|
|
||||||
}
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI) &&
|
|
||||||
!(virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI_DEFAULT_DISABLED) &&
|
|
||||||
disk->device != VIR_DOMAIN_DISK_DEVICE_LUN)) {
|
|
||||||
/* if sg_io is true but the scsi option isn't supported,
|
/* if sg_io is true but the scsi option isn't supported,
|
||||||
* that means it's just always on in this version of qemu.
|
* that means it's just always on in this version of qemu.
|
||||||
*/
|
*/
|
||||||
virBufferAsprintf(&opt, ",scsi=%s",
|
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
|
||||||
(disk->device == VIR_DOMAIN_DISK_DEVICE_LUN)
|
scsi = VIR_TRISTATE_SWITCH_ON;
|
||||||
? "on" : "off");
|
} else {
|
||||||
|
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI_DEFAULT_DISABLED))
|
||||||
|
scsi = VIR_TRISTATE_SWITCH_OFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk->queues) {
|
if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_DISK, disk, qemuCaps)))
|
||||||
virBufferAsprintf(&opt, ",num-queues=%u", disk->queues);
|
|
||||||
}
|
|
||||||
if (disk->queue_size > 0) {
|
|
||||||
virBufferAsprintf(&opt, ",queue-size=%u", disk->queue_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qemuBuildDeviceAddressStr(&opt, def, &disk->info) < 0)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (virJSONValueObjectAdd(props,
|
||||||
|
"S:iothread", iothread,
|
||||||
|
"T:ioeventfd", disk->ioeventfd,
|
||||||
|
"T:event_idx", disk->event_idx,
|
||||||
|
"T:scsi", scsi,
|
||||||
|
"p:num-queues", disk->queues,
|
||||||
|
"p:queue-size", disk->queue_size,
|
||||||
|
NULL) < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_DISK_BUS_USB:
|
case VIR_DOMAIN_DISK_BUS_USB:
|
||||||
virBufferAddLit(&opt, "usb-storage");
|
driver = "usb-storage";
|
||||||
|
|
||||||
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_REMOVABLE)) {
|
||||||
|
if (disk->removable == VIR_TRISTATE_SWITCH_ABSENT)
|
||||||
|
removable = VIR_TRISTATE_SWITCH_OFF;
|
||||||
|
else
|
||||||
|
removable = disk->removable;
|
||||||
|
}
|
||||||
|
|
||||||
if (qemuBuildDeviceAddressStr(&opt, def, &disk->info) < 0)
|
|
||||||
return NULL;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_DISK_BUS_FDC:
|
case VIR_DOMAIN_DISK_BUS_FDC:
|
||||||
virBufferAsprintf(&opt, "floppy,unit=%d", disk->info.addr.drive.unit);
|
driver = "floppy";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_DISK_BUS_XEN:
|
case VIR_DOMAIN_DISK_BUS_XEN:
|
||||||
@ -2315,74 +2194,105 @@ qemuBuildDiskDeviceStr(const virDomainDef *def,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk->src->shared &&
|
if (driver) {
|
||||||
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
|
if (virJSONValueObjectCreate(&props,
|
||||||
virBufferAddLit(&opt, ",share-rw=on");
|
"s:driver", driver,
|
||||||
|
NULL) < 0)
|
||||||
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
return NULL;
|
||||||
backendAlias = qemuDomainGetVhostUserChrAlias(disk->info.alias);
|
}
|
||||||
|
|
||||||
virBufferAsprintf(&opt, ",chardev=%s", backendAlias);
|
if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
|
||||||
} else {
|
disk->info.addr.drive.diskbus = disk->bus;
|
||||||
if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &backendAlias) < 0)
|
|
||||||
|
if (qemuBuildDeviceAddressProps(props, def, &disk->info) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (disk->src->shared &&
|
||||||
|
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
|
||||||
|
shareRW = VIR_TRISTATE_SWITCH_ON;
|
||||||
|
|
||||||
|
if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
|
||||||
|
chardev = qemuDomainGetVhostUserChrAlias(disk->info.alias);
|
||||||
|
} else {
|
||||||
|
if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &drive) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (backendAlias)
|
|
||||||
virBufferAsprintf(&opt, ",drive=%s", backendAlias);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virBufferAsprintf(&opt, ",id=%s", disk->info.alias);
|
|
||||||
/* bootindex for floppies is configured via the fdc controller */
|
/* bootindex for floppies is configured via the fdc controller */
|
||||||
if (disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
|
if (disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY)
|
||||||
disk->info.effectiveBootIndex > 0)
|
bootindex = disk->info.effectiveBootIndex;
|
||||||
virBufferAsprintf(&opt, ",bootindex=%u", disk->info.effectiveBootIndex);
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKIO)) {
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKIO)) {
|
||||||
if (disk->blockio.logical_block_size > 0)
|
logical_block_size = disk->blockio.logical_block_size;
|
||||||
virBufferAsprintf(&opt, ",logical_block_size=%u",
|
physical_block_size = disk->blockio.physical_block_size;
|
||||||
disk->blockio.logical_block_size);
|
|
||||||
if (disk->blockio.physical_block_size > 0)
|
|
||||||
virBufferAsprintf(&opt, ",physical_block_size=%u",
|
|
||||||
disk->blockio.physical_block_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk->wwn) {
|
if (disk->wwn) {
|
||||||
if (STRPREFIX(disk->wwn, "0x"))
|
unsigned long long w = 0;
|
||||||
virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
|
|
||||||
else
|
if (virStrToLong_ull(disk->wwn, NULL, 16, &w) < 0) {
|
||||||
virBufferAsprintf(&opt, ",wwn=0x%s", disk->wwn);
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("Failed to parse wwn '%s' as number"), disk->wwn);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk->rotation_rate)
|
wwn = virJSONValueNewNumberUlong(w);
|
||||||
virBufferAsprintf(&opt, ",rotation_rate=%u", disk->rotation_rate);
|
|
||||||
|
|
||||||
if (disk->vendor) {
|
|
||||||
virBufferAddLit(&opt, ",vendor=");
|
|
||||||
virQEMUBuildBufferEscapeComma(&opt, disk->vendor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk->product) {
|
if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
|
||||||
virBufferAddLit(&opt, ",product=");
|
/* VIR_DOMAIN_DISK_DEVICE_LUN translates into 'scsi-block'
|
||||||
virQEMUBuildBufferEscapeComma(&opt, disk->product);
|
* where any caching setting makes no sense. */
|
||||||
}
|
if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN &&
|
||||||
|
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_WRITE_CACHE)) {
|
||||||
|
bool wb;
|
||||||
|
|
||||||
if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
|
if (qemuDomainDiskCachemodeFlags(disk->cachemode, &wb, NULL,
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_REMOVABLE)) {
|
NULL) < 0)
|
||||||
if (disk->removable == VIR_TRISTATE_SWITCH_ON)
|
|
||||||
virBufferAddLit(&opt, ",removable=on");
|
|
||||||
else
|
|
||||||
virBufferAddLit(&opt, ",removable=off");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qemuBuildDriveDevCacheStr(disk, &opt, qemuCaps) < 0)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
qemuBuildDiskFrontendAttributes(disk, &opt);
|
writeCache = virTristateSwitchFromBool(wb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disk->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT)
|
||||||
|
biosCHSTrans = virDomainDiskGeometryTransTypeToString(disk->geometry.trans);
|
||||||
|
|
||||||
|
if (disk->serial) {
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
|
virBufferEscape(&buf, '\\', " ", "%s", disk->serial);
|
||||||
|
serial = virBufferContentAndReset(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_STORAGE_WERROR))
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_STORAGE_WERROR))
|
||||||
qemuBuildDiskFrontendAttributeErrorPolicy(disk, &opt);
|
qemuBuildDiskGetErrorPolicy(disk, &wpolicy, &rpolicy);
|
||||||
|
|
||||||
return virBufferContentAndReset(&opt);
|
if (virJSONValueObjectAdd(props,
|
||||||
|
"S:device_id", scsiVPDDeviceId,
|
||||||
|
"T:share-rw", shareRW,
|
||||||
|
"S:drive", drive,
|
||||||
|
"S:chardev", chardev,
|
||||||
|
"s:id", disk->info.alias,
|
||||||
|
"p:bootindex", bootindex,
|
||||||
|
"p:logical_block_size", logical_block_size,
|
||||||
|
"p:physical_block_size", physical_block_size,
|
||||||
|
"A:wwn", &wwn,
|
||||||
|
"p:rotation_rate", disk->rotation_rate,
|
||||||
|
"S:vendor", disk->vendor,
|
||||||
|
"S:product", disk->product,
|
||||||
|
"T:removable", removable,
|
||||||
|
"S:write-cache", qemuOnOffAuto(writeCache),
|
||||||
|
"p:cyls", disk->geometry.cylinders,
|
||||||
|
"p:heads", disk->geometry.heads,
|
||||||
|
"p:secs", disk->geometry.sectors,
|
||||||
|
"S:bios-chs-trans", biosCHSTrans,
|
||||||
|
"S:serial", serial,
|
||||||
|
"S:werror", wpolicy,
|
||||||
|
"S:rerror", rpolicy,
|
||||||
|
NULL) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_steal_pointer(&props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2613,7 +2523,7 @@ qemuBuildDiskCommandLine(virCommand *cmd,
|
|||||||
virDomainDiskDef *disk,
|
virDomainDiskDef *disk,
|
||||||
virQEMUCaps *qemuCaps)
|
virQEMUCaps *qemuCaps)
|
||||||
{
|
{
|
||||||
g_autofree char *optstr = NULL;
|
g_autoptr(virJSONValue) devprops = NULL;
|
||||||
|
|
||||||
if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0)
|
if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -2632,11 +2542,11 @@ qemuBuildDiskCommandLine(virCommand *cmd,
|
|||||||
if (qemuCommandAddExtDevice(cmd, &disk->info, qemuCaps) < 0)
|
if (qemuCommandAddExtDevice(cmd, &disk->info, qemuCaps) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
virCommandAddArg(cmd, "-device");
|
if (!(devprops = qemuBuildDiskDeviceProps(def, disk, qemuCaps)))
|
||||||
|
return -1;
|
||||||
if (!(optstr = qemuBuildDiskDeviceStr(def, disk, qemuCaps)))
|
|
||||||
|
if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
virCommandAddArg(cmd, optstr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -134,8 +134,8 @@ qemuBlockStorageSourceChainData *
|
|||||||
qemuBuildStorageSourceChainAttachPrepareBlockdevTop(virStorageSource *top,
|
qemuBuildStorageSourceChainAttachPrepareBlockdevTop(virStorageSource *top,
|
||||||
virStorageSource *backingStore);
|
virStorageSource *backingStore);
|
||||||
|
|
||||||
char
|
virJSONValue *
|
||||||
*qemuBuildDiskDeviceStr(const virDomainDef *def,
|
qemuBuildDiskDeviceProps(const virDomainDef *def,
|
||||||
virDomainDiskDef *disk,
|
virDomainDiskDef *disk,
|
||||||
virQEMUCaps *qemuCaps);
|
virQEMUCaps *qemuCaps);
|
||||||
|
|
||||||
|
@ -710,7 +710,7 @@ qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
|
|||||||
{
|
{
|
||||||
g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
|
g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
|
||||||
qemuDomainObjPrivate *priv = vm->privateData;
|
qemuDomainObjPrivate *priv = vm->privateData;
|
||||||
g_autofree char *devstr = NULL;
|
g_autoptr(virJSONValue) devprops = NULL;
|
||||||
bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
|
bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
|
||||||
bool extensionDeviceAttached = false;
|
bool extensionDeviceAttached = false;
|
||||||
int rc;
|
int rc;
|
||||||
@ -772,7 +772,7 @@ qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
|
|||||||
ignore_value(VIR_INSERT_ELEMENT(data->srcdata, 0, data->nsrcdata, backend));
|
ignore_value(VIR_INSERT_ELEMENT(data->srcdata, 0, data->nsrcdata, backend));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(devstr = qemuBuildDiskDeviceStr(vm->def, disk, priv->qemuCaps)))
|
if (!(devprops = qemuBuildDiskDeviceProps(vm->def, disk, priv->qemuCaps)))
|
||||||
goto rollback;
|
goto rollback;
|
||||||
|
|
||||||
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
||||||
@ -782,7 +782,7 @@ qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
|
|||||||
extensionDeviceAttached = true;
|
extensionDeviceAttached = true;
|
||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = qemuMonitorAddDevice(priv->mon, devstr);
|
rc = qemuMonitorAddDeviceProps(priv->mon, &devprops);
|
||||||
|
|
||||||
/* Setup throttling of disk via block_set_io_throttle QMP command. This
|
/* Setup throttling of disk via block_set_io_throttle QMP command. This
|
||||||
* is a hack until the 'throttle' blockdev driver will support modification
|
* is a hack until the 'throttle' blockdev driver will support modification
|
||||||
|
@ -29,7 +29,7 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
|
|||||||
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
|
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
|
||||||
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
|
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
|
||||||
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
|
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
|
||||||
-device ide-hd,bus=ide.0,unit=1,drive=libvirt-1-format,id=ide0-0-1,bootindex=1,wwn=0x5000c50015ea71ad,serial=WD-WMAP9A966149 \
|
-device ide-hd,bus=ide.0,unit=1,drive=libvirt-1-format,id=ide0-0-1,bootindex=1,wwn=5764824127192592813,serial=WD-WMAP9A966149 \
|
||||||
-audiodev id=audio1,driver=none \
|
-audiodev id=audio1,driver=none \
|
||||||
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
|
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
|
||||||
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
||||||
|
@ -31,10 +31,10 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
|
|||||||
-device lsi,id=scsi1,bus=pci.0,addr=0x3 \
|
-device lsi,id=scsi1,bus=pci.0,addr=0x3 \
|
||||||
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
|
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
|
||||||
-blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"raw","file":"libvirt-2-storage"}' \
|
-blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"raw","file":"libvirt-2-storage"}' \
|
||||||
-device scsi-cd,bus=scsi0.0,channel=0,scsi-id=1,lun=0,device_id=WD-WMAP9A966149,drive=libvirt-2-format,id=scsi0-0-1-0,wwn=0x5000c50015ea71ac,serial=WD-WMAP9A966149 \
|
-device scsi-cd,bus=scsi0.0,channel=0,scsi-id=1,lun=0,device_id=WD-WMAP9A966149,drive=libvirt-2-format,id=scsi0-0-1-0,wwn=5764824127192592812,serial=WD-WMAP9A966149 \
|
||||||
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest2","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
|
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest2","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
|
||||||
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
|
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
|
||||||
-device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,device_id=drive-scsi0-0-0-0,drive=libvirt-1-format,id=scsi0-0-0-0,bootindex=1,wwn=0x5000c50015ea71ad \
|
-device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,device_id=drive-scsi0-0-0-0,drive=libvirt-1-format,id=scsi0-0-0-0,bootindex=1,wwn=5764824127192592813 \
|
||||||
-audiodev id=audio1,driver=none \
|
-audiodev id=audio1,driver=none \
|
||||||
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 \
|
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 \
|
||||||
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
||||||
|
@ -43,7 +43,7 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
|
|||||||
-device scsi-hd,bus=scsi1.0,channel=0,scsi-id=0,lun=0,device_id=abcdefghijklmn,drive=libvirt-4-format,id=scsi1-0-0-0,serial=abcdefghijklmn \
|
-device scsi-hd,bus=scsi1.0,channel=0,scsi-id=0,lun=0,device_id=abcdefghijklmn,drive=libvirt-4-format,id=scsi1-0-0-0,serial=abcdefghijklmn \
|
||||||
-blockdev '{"driver":"file","filename":"/tmp/scsidisk3.img","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
|
-blockdev '{"driver":"file","filename":"/tmp/scsidisk3.img","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
|
||||||
-blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"raw","file":"libvirt-3-storage"}' \
|
-blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"raw","file":"libvirt-3-storage"}' \
|
||||||
-device scsi-hd,bus=scsi2.0,channel=0,scsi-id=0,lun=0,device_id=drive-scsi2-0-0-0,drive=libvirt-3-format,id=scsi2-0-0-0,wwn=0x5000c50015ea71ac \
|
-device scsi-hd,bus=scsi2.0,channel=0,scsi-id=0,lun=0,device_id=drive-scsi2-0-0-0,drive=libvirt-3-format,id=scsi2-0-0-0,wwn=5764824127192592812 \
|
||||||
-blockdev '{"driver":"file","filename":"/tmp/scsidisk4.img","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
|
-blockdev '{"driver":"file","filename":"/tmp/scsidisk4.img","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
|
||||||
-blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"raw","file":"libvirt-2-storage"}' \
|
-blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"raw","file":"libvirt-2-storage"}' \
|
||||||
-device scsi-hd,bus=scsi3.0,channel=0,scsi-id=0,lun=0,device_id=drive-scsi3-0-0-0,drive=libvirt-2-format,id=scsi3-0-0-0 \
|
-device scsi-hd,bus=scsi3.0,channel=0,scsi-id=0,lun=0,device_id=drive-scsi3-0-0-0,drive=libvirt-2-format,id=scsi3-0-0-0 \
|
||||||
|
Loading…
Reference in New Issue
Block a user