On Mon, Oct 03, 2011 at 04:07:23PM +0200, Michal Privoznik wrote: > This element says what to do with cdrom (or floppy) on migration. > Currently, only one attribute is supported: 'optional'. It accepts > 'require', 'optional' and 'drop' values. Setting a cdrom to be > required means migration will fail if destination cannot access > source under the same path. Setting to optional means, if destination > cannot access disk source, it simply gets free()'d/ejected. > Finally, setting to drop will simply cause cdrom to be dropped > regardless of path being accessible or not. > > This functionality is important for users, whose machines get buggy. > So they decide to save as much as possible and migrate the machine > even they won't be able to access (readonly) cdrom on destination. Migration will also be disallowed when the vm uses host devices or has snapshots (qemuMigrationIsAllowed)[1]. Would it make sense to introduce a VIR_MIGRATE_FORCE similar to VIR_REVERT_FORCE here? We could then introduce error codes similar to the snapshot case (VIR_ERR_MIGRATE_RISKY). The attached patch shows how this could look like, it's not meant to be applied yet. Cheers, -- Guido (sorry for hijacking this thread a bit) [1] Hopefully we can make migration with snapshots safe in the future by transfering the metadata. A current hack around is to put this onto shared storage and reread it on the destination side after migration. > --- > docs/formatdomain.html.in | 23 ++++++ > docs/schemas/domaincommon.rng | 17 ++++ > src/conf/domain_conf.c | 78 +++++++++++++++++++- > src/conf/domain_conf.h | 17 ++++ > src/libvirt_private.syms | 2 + > .../domain-qemu-complex-migration.xml | 68 +++++++++++++++++ > 6 files changed, 204 insertions(+), 1 deletions(-) > create mode 100644 tests/domainschemadata/domain-qemu-complex-migration.xml > > diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in > index 593adcb..c72967f 100644 > --- a/docs/formatdomain.html.in > +++ b/docs/formatdomain.html.in > @@ -917,6 +917,7 @@ > <driver name='qemu' type='raw'/> > <target def='hdc' bus='ide'/> > <readonly/> > + <migration optional='require'> > </disk> > </devices> > ...</pre> > @@ -1109,6 +1110,28 @@ > </tr> > </table> > </dd> > + <dt><code>migration</code></dt> > + <dd>This element says what to do with disk during migration. Currently, > + only <code>optional</code> attribute is supported. This attribute > + specify policy for CD ROM and floppy in cases when source has or not > + access to source. Accepted values: > + <table class="top_table"> > + <tr> > + <td> require </td> > + <td> destination must see the same medium as source </td> > + </tr> > + <tr> > + <td> optional </td> > + <td> if destination has same medium, use it. If not, > + eject medium regardless drive being locked or not. </td> > + </tr> > + <tr> > + <td> drop </td> > + <td> on migration, destination will eject, even if it > + has same medium. Again, regardless drive lock status. </td> > + </tr> > + </table> > + </dd> > <dt><code>address</code></dt> > <dd>If present, the <code>address</code> element ties the disk > to a given slot of a controller (the > diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng > index cffaac2..16a76e0 100644 > --- a/docs/schemas/domaincommon.rng > +++ b/docs/schemas/domaincommon.rng > @@ -630,6 +630,9 @@ > <ref name="encryption"/> > </optional> > <optional> > + <ref name="migration"/> > + </optional> > + <optional> > <ref name="address"/> > </optional> > </define> > @@ -642,6 +645,20 @@ > </choice> > </attribute> > </define> > + <define name="migration"> > + <optional> > + <element name="migration"> > + <attribute name="optional"> > + <choice> > + <value>require</value> > + <value>optional</value> > + <value>drop</value> > + </choice> > + </attribute> > + <empty/> > + </element> > + </optional> > + </define> > > <define name="lease"> > <element name="lease"> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 6fb1888..e1f43b6 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -572,6 +572,13 @@ VIR_ENUM_IMPL(virDomainNumatuneMemMode, VIR_DOMAIN_NUMATUNE_MEM_LAST, > "preferred", > "interleave"); > > +VIR_ENUM_IMPL(virDomainDeviceMigrationOptional, > + VIR_DOMAIN_DEVICE_MIGRATION_OPT_LAST, > + "default", > + "require", > + "optional", > + "drop"); > + > #define virDomainReportError(code, ...) \ > virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \ > __FUNCTION__, __LINE__, __VA_ARGS__) > @@ -2273,6 +2280,50 @@ cleanup: > } > > > +static int > +virDomainDeviceMigrationParseXML(xmlNodePtr node, > + virDomainDiskDefPtr def) > +{ > + int ret = -1; > + char *optional = NULL; > + int i; > + > + if (!node || !def) { > + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("invalid argument supplied")); > + return -1; > + } > + > + if ((optional = virXMLPropString(node, "optional")) != NULL) { > + i = virDomainDeviceMigrationOptionalTypeFromString(optional); > + if (i <= 0) { > + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, > + _("unknown migration optional value '%s'"), > + optional); > + goto cleanup; > + } > + > + if (i != VIR_DOMAIN_DEVICE_MIGRATION_OPT_REQ && > + def->device != VIR_DOMAIN_DISK_DEVICE_CDROM && > + def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) { > + virDomainReportError(VIR_ERR_INVALID_ARG, > + _("Setting disk %s is allowed only for " > + "cdrom or floppy"), > + optional); > + goto cleanup; > + } > + > + def->migration.optional = i; > + } > + > + ret = 0; > + > +cleanup: > + VIR_FREE(optional); > + return ret; > +} > + > + > /* Parse the XML definition for a disk > * @param node XML nodeset to parse for disk definition > */ > @@ -2283,7 +2334,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, > unsigned int flags) > { > virDomainDiskDefPtr def; > - xmlNodePtr cur, host; > + xmlNodePtr cur, host, migration = NULL; > char *type = NULL; > char *device = NULL; > char *snapshot = NULL; > @@ -2442,6 +2493,8 @@ virDomainDiskDefParseXML(virCapsPtr caps, > if (virDomainDeviceBootParseXML(cur, &def->bootIndex, > bootMap)) > goto error; > + } else if (xmlStrEqual(cur->name, BAD_CAST "migration")) { > + migration = cur; > } > } > cur = cur->next; > @@ -2605,6 +2658,11 @@ virDomainDiskDefParseXML(virCapsPtr caps, > def->event_idx = idx; > } > > + if (migration) { > + if (virDomainDeviceMigrationParseXML(migration, def) < 0) > + goto error; > + } > + > if (devaddr) { > if (virDomainParseLegacyDeviceAddress(devaddr, > &def->info.addr.pci) < 0) { > @@ -9116,6 +9174,21 @@ virDomainLeaseDefFormat(virBufferPtr buf, > } > > static int > +virDomainDeviceMigrationFormat(virBufferPtr buf, > + virDomainDeviceMigrationInfoPtr mig) > +{ > + if (!buf || !mig) > + return -1; > + > + if (mig->optional == VIR_DOMAIN_DEVICE_MIGRATION_OPT_DEFAULT) > + return 0; > + > + virBufferAsprintf(buf, " <migration optional='%s'/>\n", > + virDomainDeviceMigrationOptionalTypeToString(mig->optional)); > + return 0; > +} > + > +static int > virDomainDiskDefFormat(virBufferPtr buf, > virDomainDiskDefPtr def, > unsigned int flags) > @@ -9245,6 +9318,9 @@ virDomainDiskDefFormat(virBufferPtr buf, > virStorageEncryptionFormat(buf, def->encryption, 6) < 0) > return -1; > > + if (virDomainDeviceMigrationFormat(buf, &def->migration) < 0) > + return -1; > + > if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) > return -1; > > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index bc41d34..e0db892 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -268,6 +268,21 @@ enum virDomainSnapshotState { > VIR_DOMAIN_DISK_SNAPSHOT = VIR_DOMAIN_LAST, > }; > > +enum virDomainDeviceMigrationOptional { > + VIR_DOMAIN_DEVICE_MIGRATION_OPT_DEFAULT = 0, > + VIR_DOMAIN_DEVICE_MIGRATION_OPT_REQ, > + VIR_DOMAIN_DEVICE_MIGRATION_OPT_OPT, > + VIR_DOMAIN_DEVICE_MIGRATION_OPT_DROP, > + > + VIR_DOMAIN_DEVICE_MIGRATION_OPT_LAST > +}; > + > +typedef struct _virDomainDeviceMigrationInfo virDomainDeviceMigrationInfo; > +typedef virDomainDeviceMigrationInfo *virDomainDeviceMigrationInfoPtr; > +struct _virDomainDeviceMigrationInfo { > + int optional; > +}; > + > /* Stores the virtual disk configuration */ > typedef struct _virDomainDiskDef virDomainDiskDef; > typedef virDomainDiskDef *virDomainDiskDefPtr; > @@ -295,6 +310,7 @@ struct _virDomainDiskDef { > unsigned int transient : 1; > virDomainDeviceInfo info; > virStorageEncryptionPtr encryption; > + virDomainDeviceMigrationInfo migration; > }; > > > @@ -1912,5 +1928,6 @@ VIR_ENUM_DECL(virDomainTimerName) > VIR_ENUM_DECL(virDomainTimerTrack) > VIR_ENUM_DECL(virDomainTimerTickpolicy) > VIR_ENUM_DECL(virDomainTimerMode) > +VIR_ENUM_DECL(virDomainDeviceMigrationOptional) > > #endif /* __DOMAIN_CONF_H */ > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 1ac486f..881d535 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -275,6 +275,8 @@ virDomainDeviceAddressTypeToString; > virDomainDeviceDefFree; > virDomainDeviceDefParse; > virDomainDeviceInfoIterate; > +virDomainDeviceMigrationOptionalTypeFromString; > +virDomainDeviceMigrationOptionalTypeToString; > virDomainDevicePCIAddressIsValid; > virDomainDeviceTypeToString; > virDomainDiskBusTypeToString; > diff --git a/tests/domainschemadata/domain-qemu-complex-migration.xml b/tests/domainschemadata/domain-qemu-complex-migration.xml > new file mode 100644 > index 0000000..7071b3d > --- /dev/null > +++ b/tests/domainschemadata/domain-qemu-complex-migration.xml > @@ -0,0 +1,68 @@ > +<domain type='kvm'> > + <name>pxe</name> > + <uuid>ee74a5f1-71c1-4a46-84a9-05ac9199fe8f</uuid> > + <memory>1048576</memory> > + <currentMemory>1048576</currentMemory> > + <vcpu>4</vcpu> > + <os> > + <type arch='x86_64' machine='pc-0.14'>hvm</type> > + <boot dev='network'/> > + </os> > + <features> > + <acpi/> > + <apic/> > + <pae/> > + </features> > + <clock offset='utc'/> > + <on_poweroff>destroy</on_poweroff> > + <on_reboot>restart</on_reboot> > + <on_crash>restart</on_crash> > + <devices> > + <emulator>/usr/bin/qemu-kvm</emulator> > + <disk type='file' device='cdrom'> > + <driver name='qemu' type='raw'/> > + <source file='/tmp/cdrom.iso'/> > + <target dev='hdc' bus='ide'/> > + <readonly/> > + <migration optional='optional'/> > + <address type='drive' controller='0' bus='1' unit='0'/> > + </disk> > + <disk type='block' device='disk'> > + <driver name='qemu' type='raw'/> > + <source dev='/tmp/disk.img'/> > + <target dev='hdd' bus='ide'/> > + <migration optional='require'/> > + <address type='drive' controller='0' bus='1' unit='1'/> > + </disk> > + <controller type='virtio-serial' index='0'> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> > + </controller> > + <controller type='ide' index='0'> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> > + </controller> > + <interface type='network'> > + <mac address='52:54:00:75:71:fe'/> > + <source network='default'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> > + </interface> > + <serial type='pty'> > + <target port='0'/> > + </serial> > + <console type='pty'> > + <target type='serial' port='0'/> > + </console> > + <channel type='spicevmc'> > + <target type='virtio' name='com.redhat.spice.0'/> > + <address type='virtio-serial' controller='0' bus='0' port='1'/> > + </channel> > + <input type='mouse' bus='ps2'/> > + <graphics type='spice' port='5999' autoport='no' keymap='en-us'/> > + <video> > + <model type='cirrus' vram='9216' heads='1'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> > + </video> > + <memballoon model='virtio'> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> > + </memballoon> > + </devices> > +</domain> > -- > 1.7.3.4 > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list >
>From 36bdfd44f099c1ce5e249581c9d1ebe974a5352b Mon Sep 17 00:00:00 2001 From: Guido Guenther <agx@xxxxxxxxxxx> Date: Thu, 13 Oct 2011 12:05:08 +0200 Subject: [PATCH] Introducte VIR_MIGRATE_FORCE flag to allow for risky migrations Change errors inidicating risky migration to VIR_ERR_MIGRATE_RISKY. --- include/libvirt/libvirt.h.in | 3 ++- include/libvirt/virterror.h | 2 ++ src/qemu/qemu_driver.c | 10 +++++----- src/qemu/qemu_migration.c | 38 ++++++++++++++++++++++++-------------- src/qemu/qemu_migration.h | 13 +++++++++---- src/util/virterror.c | 6 ++++++ 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index c991dfc..abf08a3 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -766,7 +766,8 @@ typedef enum { VIR_MIGRATE_CHANGE_PROTECTION = (1 << 8), /* protect for changing domain configuration through the * whole migration process; this will be used automatically * when supported */ - + VIR_MIGRATE_FORCE = (1 << 9), /* Force migration even when we have host devices in use + or have snapshotes */ } virDomainMigrateFlags; /* Domain migration. */ diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index dfbe2bc..17e8fdd 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -240,6 +240,8 @@ typedef enum { VIR_ERR_STORAGE_POOL_BUILT = 76, /* storage pool already built */ VIR_ERR_SNAPSHOT_REVERT_RISKY = 77, /* force was not requested for a risky domain snapshot revert */ + VIR_ERR_MIGRATE_RISKY = 78, /* force was not requested for a + risky domain migration */ } virErrorNumber; /** diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ec01cd5..95396e8 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7838,7 +7838,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn, ret = qemuMigrationPrepareTunnel(driver, dconn, NULL, 0, NULL, NULL, /* No cookies in v2 */ - st, dname, dom_xml); + st, dname, dom_xml, flags); cleanup: qemuDriverUnlock(driver); @@ -7898,7 +7898,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ret = qemuMigrationPrepareDirect(driver, dconn, NULL, 0, NULL, NULL, /* No cookies */ uri_in, uri_out, - dname, dom_xml); + dname, dom_xml, flags); cleanup: qemuDriverUnlock(driver); @@ -8051,7 +8051,7 @@ qemuDomainMigrateBegin3(virDomainPtr domain, goto endjob; if (!(xml = qemuMigrationBegin(driver, vm, xmlin, - cookieout, cookieoutlen))) + cookieout, cookieoutlen, flags))) goto endjob; if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { @@ -8128,7 +8128,7 @@ qemuDomainMigratePrepare3(virConnectPtr dconn, cookiein, cookieinlen, cookieout, cookieoutlen, uri_in, uri_out, - dname, dom_xml); + dname, dom_xml, flags); cleanup: qemuDriverUnlock(driver); @@ -8173,7 +8173,7 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, ret = qemuMigrationPrepareTunnel(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, - st, dname, dom_xml); + st, dname, dom_xml, flags); qemuDriverUnlock(driver); cleanup: diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 4516231..91000ad 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -780,18 +780,24 @@ error: * the fact that older servers did not do checks on the source. */ static bool qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm, - virDomainDefPtr def) + virDomainDefPtr def, int flags) { int nsnapshots; + /* FIXME: there are different kinds of risk (a missing host device + might break the vm entirely while missing snapshots will not */ + if (flags & VIR_MIGRATE_FORCE) { + return true; + } + if (vm) { if (qemuProcessAutoDestroyActive(driver, vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, + qemuReportError(VIR_ERR_MIGRATE_RISKY, "%s", _("domain is marked for auto destroy")); return false; } if ((nsnapshots = virDomainSnapshotObjListNum(&vm->snapshots, 0))) { - qemuReportError(VIR_ERR_OPERATION_INVALID, + qemuReportError(VIR_ERR_MIGRATE_RISKY, _("cannot migrate domain with %d snapshots"), nsnapshots); return false; @@ -800,7 +806,7 @@ qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm, def = vm->def; } if (def->nhostdevs > 0) { - qemuReportError(VIR_ERR_OPERATION_INVALID, + qemuReportError(VIR_ERR_MIGRATE_RISKY, "%s", _("Domain with assigned host devices cannot be migrated")); return false; } @@ -993,7 +999,8 @@ char *qemuMigrationBegin(struct qemud_driver *driver, virDomainObjPtr vm, const char *xmlin, char **cookieout, - int *cookieoutlen) + int *cookieoutlen, + unsigned long flags) { char *rv = NULL; qemuMigrationCookiePtr mig = NULL; @@ -1010,7 +1017,7 @@ char *qemuMigrationBegin(struct qemud_driver *driver, if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_BEGIN3); - if (!qemuMigrationIsAllowed(driver, vm, NULL)) + if (!qemuMigrationIsAllowed(driver, vm, NULL, flags)) goto cleanup; if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0))) @@ -1059,7 +1066,8 @@ qemuMigrationPrepareAny(struct qemud_driver *driver, const char *dname, const char *dom_xml, const char *migrateFrom, - virStreamPtr st) + virStreamPtr st, + int flags) { virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; @@ -1080,7 +1088,7 @@ qemuMigrationPrepareAny(struct qemud_driver *driver, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; - if (!qemuMigrationIsAllowed(driver, NULL, def)) + if (!qemuMigrationIsAllowed(driver, NULL, def, flags)) goto cleanup; /* Target domain name, maybe renamed. */ @@ -1220,7 +1228,8 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, int *cookieoutlen, virStreamPtr st, const char *dname, - const char *dom_xml) + const char *dom_xml, + unsigned long flags) { int ret; @@ -1234,7 +1243,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, */ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, dname, dom_xml, - "stdio", st); + "stdio", st, flags); return ret; } @@ -1249,7 +1258,8 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, const char *uri_in, char **uri_out, const char *dname, - const char *dom_xml) + const char *dom_xml, + unsigned long flags) { static int port = 0; int this_port; @@ -1345,7 +1355,7 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, dname, dom_xml, - migrateFrom, NULL); + migrateFrom, NULL, flags); cleanup: VIR_FREE(hostname); if (ret != 0) @@ -2012,7 +2022,7 @@ static int doPeer2PeerMigrate3(struct qemud_driver *driver, * a single job. */ dom_xml = qemuMigrationBegin(driver, vm, xmlin, - &cookieout, &cookieoutlen); + &cookieout, &cookieoutlen, flags); if (!dom_xml) goto cleanup; @@ -2289,7 +2299,7 @@ qemuMigrationPerformJob(struct qemud_driver *driver, goto endjob; } - if (!qemuMigrationIsAllowed(driver, vm, NULL)) + if (!qemuMigrationIsAllowed(driver, vm, NULL, flags)) goto cleanup; resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING; diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index ec70422..5adc1cf 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -35,7 +35,9 @@ VIR_MIGRATE_PAUSED | \ VIR_MIGRATE_NON_SHARED_DISK | \ VIR_MIGRATE_NON_SHARED_INC | \ - VIR_MIGRATE_CHANGE_PROTECTION) + VIR_MIGRATE_CHANGE_PROTECTION | \ + VIR_MIGRATE_FORCE) + enum qemuMigrationJobPhase { QEMU_MIGRATION_PHASE_NONE = 0, @@ -80,7 +82,8 @@ char *qemuMigrationBegin(struct qemud_driver *driver, virDomainObjPtr vm, const char *xmlin, char **cookieout, - int *cookieoutlen); + int *cookieoutlen, + unsigned long flags); int qemuMigrationPrepareTunnel(struct qemud_driver *driver, virConnectPtr dconn, @@ -90,7 +93,8 @@ int qemuMigrationPrepareTunnel(struct qemud_driver *driver, int *cookieoutlen, virStreamPtr st, const char *dname, - const char *dom_xml); + const char *dom_xml, + unsigned long flags); int qemuMigrationPrepareDirect(struct qemud_driver *driver, virConnectPtr dconn, @@ -101,7 +105,8 @@ int qemuMigrationPrepareDirect(struct qemud_driver *driver, const char *uri_in, char **uri_out, const char *dname, - const char *dom_xml); + const char *dom_xml, + unsigned long flags); int qemuMigrationPerform(struct qemud_driver *driver, virConnectPtr conn, diff --git a/src/util/virterror.c b/src/util/virterror.c index 5006fa2..3544208 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1210,6 +1210,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("revert requires force: %s"); break; + case VIR_ERR_MIGRATE_RISKY: + if (info == NULL) + errmsg = _("migration requires force"); + else + errmsg = _("migration requires force: %s"); + break; } return (errmsg); } -- 1.7.6.3
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list