File 6c17606b-qemu-normalize-mac-addr.patch of Package libvirt.22292

commit 6c17606b7cce7bf77baef956bde8a0b056666011
Author: Laine Stump <laine@redhat.com>
Date:   Tue Dec 17 10:24:00 2019 -0500

    qemu: homogenize MAC address in live & config when hotplugging a netdev
    
    Prior to commit 55ce6564634 (first in libvirt 4.6.0), the XML sent to
    virDomainAttachDeviceFlags() was parsed only once, and the results of
    that parse were inserted into both the live object of the running
    domain and into the persistent config. Thus, if MAC address was
    omitted from in XML for a network device (<interface>), both the live
    and config object would have the same MAC address.
    
    Commit 55ce6564634 changed the code to parse the incoming XML twice -
    once for live and once for config. This does eliminate the problem of
    PCI (/scsi/sata) address conflicts caused by allocating an address
    based on existing devices in live object, but then inserting the
    result into the config (which may already have a device using that
    address), BUT it also means that when the MAC address of a network
    device hasn't been specified in the XML, each copy will get a
    different auto-generated MAC address.
    
    This results in the MAC address of the device changing the next time
    the domain is shutdown and restarted, which creates havoc with the
    guest OS's network config.
    
    There have been several discussions about this in the last > 1 year,
    attempting to find the ideal solution to this problem that makes MAC
    addresses consistent and accounts for all sorts of corner cases with
    PCI/scsi/sata addresses. All of these discussions fizzled out because
    every proposal was either too difficult to implement or failed to fix
    some esoteric case someone thought up.
    
    So, in the interest of solving the MAC address problem while not
    making the "other address" situation any worse than before, this patch
    simply adds a qemuDomainAttachDeviceLiveAndConfigHomogenize() function
    that (for now) copies the MAC address from the config object to the
    live object (if the original xml had <mac address='blah'/> then this
    will be an effective NOP (as the macs already match)).
    
    Any downstream libvirt containing upstream commit
    55ce6564634 should have this patch as well.
    
    https://bugzilla.redhat.com/1783411
    
    Signed-off-by: Laine Stump <laine@redhat.com>
    Reviewed-by: Michal Privoznik <mprivozn@redhat.com>

Index: libvirt-5.1.0/src/qemu/qemu_driver.c
===================================================================
--- libvirt-5.1.0.orig/src/qemu/qemu_driver.c
+++ libvirt-5.1.0/src/qemu/qemu_driver.c
@@ -8748,6 +8748,35 @@ qemuDomainUpdateDeviceConfig(virDomainDe
     return 0;
 }
 
+
+static void
+qemuDomainAttachDeviceLiveAndConfigHomogenize(const virDomainDeviceDef *devConf,
+                                              virDomainDeviceDefPtr devLive)
+{
+    /*
+     * Fixup anything that needs to be identical in the live and
+     * config versions of DeviceDef, but might not be. Do this by
+     * changing the contents of devLive. This is done after all
+     * post-parse tweaks and validation, so be very careful about what
+     * changes are made. (For example, it would be a very bad idea to
+     * change assigned PCI, scsi, or sata addresses, as it could lead
+     * to a conflict and there would be nothing to catch it except
+     * qemu itself!)
+     */
+
+    /* MAC address should be identical in both DeviceDefs, but if it
+     * wasn't specified in the XML, and was instead autogenerated, it
+     * will be different for the two since they are each the result of
+     * a separate parser call. If it *was* specified, it will already
+     * be the same, so copying does no harm.
+     */
+
+    if (devConf->type == VIR_DOMAIN_DEVICE_NET)
+        virMacAddrSet(&devLive->data.net->mac, &devConf->data.net->mac);
+
+}
+
+
 static int
 qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
                                     virQEMUDriverPtr driver,
@@ -8757,6 +8786,7 @@ qemuDomainAttachDeviceLiveAndConfig(virD
     virDomainDefPtr vmdef = NULL;
     virQEMUDriverConfigPtr cfg = NULL;
     virDomainDeviceDefPtr devConf = NULL;
+    virDomainDeviceDef devConfSave = { 0 };
     virDomainDeviceDefPtr devLive = NULL;
     int ret = -1;
     virCapsPtr caps = NULL;
@@ -8783,7 +8813,14 @@ qemuDomainAttachDeviceLiveAndConfig(virD
                                                 driver->xmlopt, parse_flags)))
             goto cleanup;
 
-        if (virDomainDefCompatibleDevice(vmdef, devConf, NULL,
+        /*
+         * devConf will be NULLed out by
+         * qemuDomainAttachDeviceConfig(), so save it for later use by
+         * qemuDomainAttachDeviceLiveAndConfigHomogenize()
+         */
+        devConfSave = *devConf;
+
+    if (virDomainDefCompatibleDevice(vmdef, devConf, NULL,
                                          VIR_DOMAIN_DEVICE_ACTION_ATTACH,
                                          false) < 0)
             goto cleanup;
@@ -8799,6 +8836,9 @@ qemuDomainAttachDeviceLiveAndConfig(virD
                                                 driver->xmlopt, parse_flags)))
             goto cleanup;
 
+        if (flags & VIR_DOMAIN_AFFECT_CONFIG)
+            qemuDomainAttachDeviceLiveAndConfigHomogenize(&devConfSave, devLive);
+
         if (virDomainDeviceValidateAliasForHotplug(vm, devLive, flags) < 0)
             goto cleanup;
 
openSUSE Build Service is sponsored by