The combination of explicit firmware paths, which we now produce in all cases, and firmware autoselection knobs is explicitly rejected by libvirt 8.6.0 and newer. Right now we produce inherently migratable XML in all cases, since we always strip those bits, but that's going to change soon. To prepare for that, make sure that we always skip the problematic elements and attributes when preparing a migratable XML. The destination will simply receive a fully specified firmware configuration, which is indistinguishable from one that was manually provided by the user and is thus accepted by any old version of libvirt, regardless of whether or not firmware autoselection was used on the source host. Signed-off-by: Andrea Bolognani <abologna@xxxxxxxxxx> --- src/conf/domain_conf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 9ef50c818b..9f49c6e62d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -27382,6 +27382,7 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, const char *type = NULL; int n; size_t i; + bool migratable = !!(flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE); virCheckFlags(VIR_DOMAIN_DEF_FORMAT_COMMON_FLAGS | VIR_DOMAIN_DEF_FORMAT_STATUS | @@ -27476,7 +27477,7 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, } virBufferAddLit(buf, "<os"); - if (def->os.firmware) + if (def->os.firmware && !migratable) virBufferAsprintf(buf, " firmware='%s'", virDomainOsDefFirmwareTypeToString(def->os.firmware)); virBufferAddLit(buf, ">\n"); @@ -27499,7 +27500,7 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, virBufferAsprintf(buf, ">%s</type>\n", virDomainOSTypeToString(def->os.type)); - if (def->os.firmwareFeatures) { + if (def->os.firmwareFeatures && !migratable) { virBufferAddLit(buf, "<firmware>\n"); virBufferAdjustIndent(buf, 2); -- 2.39.2