In the reverted commit d2e5538b1, the libxl driver was changed to copy interface names autogenerated by libxl to the corresponding network def in the domain's virDomainDef object. The copied name is freed when the domain transitions to the shutoff state. But when migrating a domain, the autogenerated name is included in the XML sent to the destination host. It is possible an interface with the same name already exists on the destination host, causing migration to fail. This patch defines a new capability for setting the network device prefix that will be used in the driver. This prefix will be then copied when domain is created as def->netprefix, which will be then used by virDomainNetDefFormat(). Valid prefixes are VIR_NET_GENERATED_PREFIX or the one announced by the driver. Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx> --- src/conf/capabilities.c | 21 +++++++++++++++++++++ src/conf/capabilities.h | 4 ++++ src/conf/domain_conf.c | 20 +++++++++++++++----- src/conf/domain_conf.h | 2 ++ src/libvirt_private.syms | 1 + src/network/bridge_driver.c | 2 +- 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index 86ea212..eafa7a9 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -269,6 +269,23 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps, return 0; } +/** + * virCapabilitiesSetNetPrefix: + * @caps: capabilities to extend + * @name: prefix for host generated network interfaces + * + * Registers the prefix that is used for generated network interfaces + */ +int +virCapabilitiesSetNetPrefix(virCapsPtr caps, + const char *prefix) +{ + if (VIR_STRDUP(caps->host.netprefix, prefix) < 0) + return -1; + + return 0; +} + /** * virCapabilitiesAddHostNUMACell: @@ -913,6 +930,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBufferAddLit(&buf, "</migration_features>\n"); } + if (caps->host.netprefix) + virBufferAsprintf(&buf, "<netprefix>%s</netprefix>\n", + caps->host.netprefix); + if (caps->host.nnumaCell && virCapabilitiesFormatNUMATopology(&buf, caps->host.nnumaCell, caps->host.numaCell) < 0) diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index 1754b13..2767f48 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -160,6 +160,7 @@ struct _virCapsHost { size_t nsecModels; virCapsHostSecModelPtr secModels; + char *netprefix; virCPUDefPtr cpu; int nPagesSize; /* size of pagesSize array */ unsigned int *pagesSize; /* page sizes support on the system */ @@ -219,6 +220,9 @@ extern int virCapabilitiesAddHostMigrateTransport(virCapsPtr caps, const char *name); +extern int +virCapabilitiesSetNetPrefix(virCapsPtr caps, + const char *prefix); extern int virCapabilitiesAddHostNUMACell(virCapsPtr caps, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a9706b0..70d5556 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8403,6 +8403,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, xmlNodePtr node, xmlXPathContextPtr ctxt, virHashTablePtr bootHash, + char *prefix, unsigned int flags) { virDomainNetDefPtr def; @@ -8569,7 +8570,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, ifname = virXMLPropString(cur, "dev"); if (ifname && (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) && - STRPREFIX(ifname, VIR_NET_GENERATED_PREFIX)) { + (STRPREFIX(ifname, VIR_NET_GENERATED_PREFIX) || + (prefix && STRPREFIX(ifname, prefix)))) { /* An auto-generated target name, blank it out */ VIR_FREE(ifname); } @@ -12525,6 +12527,7 @@ virDomainDeviceDefParse(const char *xmlStr, xmlNodePtr node; xmlXPathContextPtr ctxt = NULL; virDomainDeviceDefPtr dev = NULL; + char *prefix; if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"), &ctxt))) goto error; @@ -12567,8 +12570,9 @@ virDomainDeviceDefParse(const char *xmlStr, goto error; break; case VIR_DOMAIN_DEVICE_NET: + prefix = caps->host.netprefix; if (!(dev->data.net = virDomainNetDefParseXML(xmlopt, node, ctxt, - NULL, flags))) + NULL, prefix, flags))) goto error; break; case VIR_DOMAIN_DEVICE_INPUT: @@ -15885,11 +15889,15 @@ virDomainDefParseXML(xmlDocPtr xml, goto error; if (n && VIR_ALLOC_N(def->nets, n) < 0) goto error; + if (caps->host.netprefix && + VIR_STRDUP(def->netprefix, caps->host.netprefix) < 0) + goto error; for (i = 0; i < n; i++) { virDomainNetDefPtr net = virDomainNetDefParseXML(xmlopt, nodes[i], ctxt, bootHash, + def->netprefix, flags); if (!net) goto error; @@ -19880,6 +19888,7 @@ virDomainVirtioNetDriverFormat(char **outstr, int virDomainNetDefFormat(virBufferPtr buf, virDomainNetDefPtr def, + char *prefix, unsigned int flags) { unsigned int actualType = virDomainNetGetActualType(def); @@ -20057,7 +20066,8 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name); if (def->ifname && !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) && - (STRPREFIX(def->ifname, VIR_NET_GENERATED_PREFIX)))) { + (STRPREFIX(def->ifname, VIR_NET_GENERATED_PREFIX) || + (prefix && STRPREFIX(def->ifname, prefix))))) { /* Skip auto-generated target names for inactive config. */ virBufferEscapeString(buf, "<target dev='%s'/>\n", def->ifname); } @@ -22310,7 +22320,7 @@ virDomainDefFormatInternal(virDomainDefPtr def, goto error; for (n = 0; n < def->nnets; n++) - if (virDomainNetDefFormat(buf, def->nets[n], flags) < 0) + if (virDomainNetDefFormat(buf, def->nets[n], def->netprefix, flags) < 0) goto error; for (n = 0; n < def->nsmartcards; n++) @@ -23535,7 +23545,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, rc = virDomainFSDefFormat(&buf, src->data.fs, flags); break; case VIR_DOMAIN_DEVICE_NET: - rc = virDomainNetDefFormat(&buf, src->data.net, flags); + rc = virDomainNetDefFormat(&buf, src->data.net, def->netprefix, flags); break; case VIR_DOMAIN_DEVICE_INPUT: rc = virDomainInputDefFormat(&buf, src->data.input, flags); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 0141009..9e085a7 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2254,6 +2254,7 @@ struct _virDomainDef { virDomainOSDef os; char *emulator; + char *netprefix; /* These three options are of type virTristateSwitch, * except VIR_DOMAIN_FEATURE_CAPABILITIES that is of type * virDomainCapabilitiesPolicy */ @@ -2748,6 +2749,7 @@ int virDomainDiskSourceFormat(virBufferPtr buf, int virDomainNetDefFormat(virBufferPtr buf, virDomainNetDefPtr def, + char *prefix, unsigned int flags); typedef enum { diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 83f6e2c..80d6cc5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -59,6 +59,7 @@ virCapabilitiesGetCpusForNodemask; virCapabilitiesHostSecModelAddBaseLabel; virCapabilitiesNew; virCapabilitiesSetHostCPU; +virCapabilitiesSetNetPrefix; # conf/cpu_conf.h diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 362e294..5b0a7f1 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -200,7 +200,7 @@ networkRunHook(virNetworkObjPtr network, virBufferAddLit(&buf, "<hookData>\n"); virBufferAdjustIndent(&buf, 2); - if (iface && virDomainNetDefFormat(&buf, iface, 0) < 0) + if (iface && virDomainNetDefFormat(&buf, iface, NULL, 0) < 0) goto cleanup; if (virNetworkDefFormatBuf(&buf, network->def, 0) < 0) goto cleanup; -- 2.1.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list