the socket, and finally ``mode`` which accepts one value ``client``
specifying the role of hypervisor. It's recommended to allow libvirt
manage the persistent reservations.
+ :since:`Since 12.1.0` the ``migration`` (values ``yes``, ``no``) controls
+ whether the hypervisor should attempt to migrate persistent reservations
+ during migration.
``initiator``
:since:`Since 4.7.0`, the ``initiator`` element is supported for
a disk ``type`` "network" that is using a ``source`` element with the
return false;
}
+ /* While not guest visible it influences the qemu migration stream so
+ * we need to keep it identical */
+ if (src->src->pr || dst->src->pr) {
+ virTristateBool srcmig = VIR_TRISTATE_BOOL_ABSENT;
+ virTristateBool dstmig = VIR_TRISTATE_BOOL_ABSENT;
+
+ if (src->src->pr)
+ srcmig = src->src->pr->migration;
+
+ if (dst->src->pr)
+ dstmig = dst->src->pr->migration;
+
+ if (srcmig != dstmig) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target disk reservations 'migration' property %1$s does not match source %2$s"),
+ virTristateBoolTypeToString(dstmig),
+ virTristateBoolTypeToString(srcmig));
+ return false;
+ }
+ }
+
if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
return false;
<ref name="virYesNo"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="migration">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<optional>
<ref name="unixSocketSource"/>
</optional>
&prd->managed) < 0)
goto cleanup;
+ if (virXMLPropTristateBool(ctxt->node, "migration",
+ VIR_XML_PROP_NONZERO,
+ &prd->migration) < 0)
+ goto cleanup;
+
type = virXPathString("string(./source[1]/@type)", ctxt);
path = virXPathString("string(./source[1]/@path)", ctxt);
mode = virXPathString("string(./source[1]/@mode)", ctxt);
{
virBufferAsprintf(buf, "<reservations managed='%s'",
virTristateBoolTypeToString(prd->managed));
+
+ if (prd->migration != VIR_TRISTATE_BOOL_ABSENT)
+ virBufferAsprintf(buf, " migration='%s'",
+ virTristateBoolTypeToString(prd->migration));
+
if (prd->path &&
(prd->managed == VIR_TRISTATE_BOOL_NO || !migratable)) {
virBufferAddLit(buf, ">\n");
virTristateBool managed;
char *path;
+ virTristateBool migration;
+
/* manager object alias */
char *mgralias;
};
g_autofree char *usbdiskalias = NULL;
const virDomainDeviceInfo *deviceinfo = &disk->info;
g_autoptr(virJSONValue) statistics = NULL;
+ virTristateBool migrate_pr = VIR_TRISTATE_BOOL_ABSENT;
virDomainDeviceInfo usbSCSIinfo = {
.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
.addr.drive = { .diskbus = VIR_DOMAIN_DISK_BUS_USB },
case VIR_DOMAIN_DISK_BUS_SCSI:
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
driver = "scsi-block";
+ if (disk->src->pr)
+ migrate_pr = disk->src->pr->migration;
} else {
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
driver = "scsi-cd";
"S:rerror", rpolicy,
"A:stats-intervals", &statistics,
"T:dpofua", disk->dpofua, /* SCSI-only, ensured by validation */
+ "T:migrate-pr", migrate_pr, /* 'scsi-block' only, ensured by validation */
NULL) < 0)
return NULL;
}
}
+ if (disk->src->pr &&
+ disk->src->pr->migration != VIR_TRISTATE_BOOL_ABSENT) {
+ if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN ||
+ disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("persistent reservation migration supported only with 'lun' disks on 'scsi' bus"));
+ return -1;
+ }
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("persistent reservation migration not supported by this qemu"));
+ return -1;
+ }
+ }
+
if (disk->rotation_rate) {
if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI &&
disk->bus != VIR_DOMAIN_DISK_BUS_IDE &&
-device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":0,"drive":"libvirt-2-storage","id":"scsi0-0-0-0","bootindex":1}' \
-object '{"qom-type":"pr-manager-helper","id":"pr-helper-libvirt-1-storage","path":"/path/to/qemu-pr-helper.sock"}' \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest2","pr-manager":"pr-helper-libvirt-1-storage","node-name":"libvirt-1-storage","read-only":false}' \
--device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1"}' \
+-device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1","migrate-pr":true}' \
-audiodev '{"id":"audio1","driver":"none"}' \
-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
<disk type='block' device='lun'>
<driver name='qemu' type='raw'/>
<source dev='/dev/HostVG/QEMUGuest2'>
- <reservations managed='no'>
+ <reservations managed='no' migration='yes'>
<source type='unix' path='/path/to/qemu-pr-helper.sock' mode='client'/>
</reservations>
</source>