https://bugzilla.redhat.com/show_bug.cgi?id=1607202

It's stated that if the admin wants to shoot themselves in
the foot by removing the nwfilter binding while the domain
is running we will certainly allow that.  However, in doing
so we also run the risk that a libvirtd restart will cause
the domain to be shutdown, which isn't a good thing.

So add another boolean to virDomainConfNWFilterInstantiate
which allows us to recover somewhat gracefully in the event
the virNWFilterBindingCreateXML fails when we come from
qemuProcessReconnect and we determine that the filter has
been deleted. It was there at some point (it had to be), but
if it's missing, then we don't want to cause the guest to
stop running, so issue a warning and continue on.

Signed-off-by: John Ferlan <jfer...@redhat.com>
---
 src/conf/domain_nwfilter.c | 33 ++++++++++++++++++++++++++++-----
 src/conf/domain_nwfilter.h |  3 ++-
 src/lxc/lxc_process.c      |  3 ++-
 src/qemu/qemu_hotplug.c    |  7 ++++---
 src/qemu/qemu_interface.c  |  6 ++++--
 src/qemu/qemu_process.c    | 10 +++++++---
 src/uml/uml_conf.c         |  3 ++-
 7 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/src/conf/domain_nwfilter.c b/src/conf/domain_nwfilter.c
index f39c8a1f9b..3e6e462def 100644
--- a/src/conf/domain_nwfilter.c
+++ b/src/conf/domain_nwfilter.c
@@ -85,16 +85,19 @@ int
 virDomainConfNWFilterInstantiate(const char *vmname,
                                  const unsigned char *vmuuid,
                                  virDomainNetDefPtr net,
-                                 bool ignoreExists)
+                                 bool ignoreExists,
+                                 bool ignoreDeleted)
 {
     virConnectPtr conn = virGetConnectNWFilter();
     virNWFilterBindingDefPtr def = NULL;
     virNWFilterBindingPtr binding = NULL;
+    virNWFilterPtr nwfilter = NULL;
     char *xml = NULL;
     int ret = -1;
 
-    VIR_DEBUG("vmname=%s portdev=%s filter=%s ignoreExists=%d",
-              vmname, NULLSTR(net->ifname), NULLSTR(net->filter), 
ignoreExists);
+    VIR_DEBUG("vmname=%s portdev=%s filter=%s ignoreExists=%d 
ignoreDeleted=%d",
+              vmname, NULLSTR(net->ifname), NULLSTR(net->filter),
+              ignoreExists, ignoreDeleted);
 
     if (!conn)
         goto cleanup;
@@ -113,14 +116,34 @@ virDomainConfNWFilterInstantiate(const char *vmname,
     if (!(xml = virNWFilterBindingDefFormat(def)))
         goto cleanup;
 
-    if (!(binding = virNWFilterBindingCreateXML(conn, xml, 0)))
-        goto cleanup;
+    if (!(binding = virNWFilterBindingCreateXML(conn, xml, 0))) {
+        virErrorPtr orig_err;
+
+        if (!ignoreDeleted)
+            goto cleanup;
+
+        /* Let's determine if the error was because the filter was deleted.
+         * Save the orig_err just in case it's not a failure to find the
+         * filter by name. */
+        orig_err = virSaveLastError();
+        nwfilter = virNWFilterLookupByName(conn, def->filter);
+        virSetError(orig_err);
+        virFreeError(orig_err);
+        if (nwfilter)
+            goto cleanup;
+
+        VIR_WARN("filter '%s' for binding '%s' has been deleted while the "
+                 "guest was running, ignoring for restart processing",
+                 def->filter, def->portdevname);
+        virResetLastError();
+    }
 
     ret = 0;
 
  cleanup:
     VIR_FREE(xml);
     virNWFilterBindingDefFree(def);
+    virObjectUnref(nwfilter);
     virObjectUnref(binding);
     virObjectUnref(conn);
     return ret;
diff --git a/src/conf/domain_nwfilter.h b/src/conf/domain_nwfilter.h
index 6bda228fc8..e3a2f7a7f2 100644
--- a/src/conf/domain_nwfilter.h
+++ b/src/conf/domain_nwfilter.h
@@ -26,7 +26,8 @@
 int virDomainConfNWFilterInstantiate(const char *vmname,
                                      const unsigned char *vmuuid,
                                      virDomainNetDefPtr net,
-                                     bool ignoreExists);
+                                     bool ignoreExists,
+                                     bool ignoreDeleted);
 void virDomainConfNWFilterTeardown(virDomainNetDefPtr net);
 void virDomainConfVMNWFilterTeardown(virDomainObjPtr vm);
 
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 33c806630b..b8b014ca72 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -303,7 +303,8 @@ virLXCProcessSetupInterfaceTap(virDomainDefPtr vm,
     }
 
     if (net->filter &&
-        virDomainConfNWFilterInstantiate(vm->name, vm->uuid, net, false) < 0)
+        virDomainConfNWFilterInstantiate(vm->name, vm->uuid, net,
+                                         false, false) < 0)
         goto cleanup;
 
     ret = containerVeth;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 0b84a503bb..11b10cbe14 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3434,8 +3434,8 @@ qemuDomainChangeNetFilter(virDomainObjPtr vm,
     virDomainConfNWFilterTeardown(olddev);
 
     if (newdev->filter &&
-        virDomainConfNWFilterInstantiate(vm->def->name,
-                                         vm->def->uuid, newdev, false) < 0) {
+        virDomainConfNWFilterInstantiate(vm->def->name, vm->def->uuid, newdev,
+                                        false, false) < 0) {
         virErrorPtr errobj;
 
         virReportError(VIR_ERR_OPERATION_FAILED,
@@ -3444,7 +3444,8 @@ qemuDomainChangeNetFilter(virDomainObjPtr vm,
                        olddev->ifname);
         virErrorPreserveLast(&errobj);
         ignore_value(virDomainConfNWFilterInstantiate(vm->def->name,
-                                                      vm->def->uuid, olddev, 
false));
+                                                      vm->def->uuid, olddev,
+                                                      false, false));
         virErrorRestore(&errobj);
         return -1;
     }
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index a3f13093f5..fc5f39b76d 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -467,7 +467,8 @@ qemuInterfaceEthernetConnect(virDomainDefPtr def,
         goto cleanup;
 
     if (net->filter &&
-        virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 
0) {
+        virDomainConfNWFilterInstantiate(def->name, def->uuid, net,
+                                         false, false) < 0) {
         goto cleanup;
     }
 
@@ -586,7 +587,8 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def,
         goto cleanup;
 
     if (net->filter &&
-        virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 
0) {
+        virDomainConfNWFilterInstantiate(def->name, def->uuid, net,
+                                         false, false) < 0) {
         goto cleanup;
     }
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ab749389ee..4d8b3017b4 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3161,14 +3161,18 @@ qemuProcessNotifyNets(virDomainDefPtr def)
 }
 
 static int
-qemuProcessFiltersInstantiate(virDomainDefPtr def, bool ignoreExists)
+qemuProcessFiltersInstantiate(virDomainDefPtr def,
+                              bool ignoreExists,
+                              bool ignoreDeleted)
 {
     size_t i;
 
     for (i = 0; i < def->nnets; i++) {
         virDomainNetDefPtr net = def->nets[i];
         if ((net->filter) && (net->ifname)) {
-            if (virDomainConfNWFilterInstantiate(def->name, def->uuid, net, 
ignoreExists) < 0)
+            if (virDomainConfNWFilterInstantiate(def->name, def->uuid, net,
+                                                 ignoreExists,
+                                                 ignoreDeleted) < 0)
                 return 1;
         }
     }
@@ -7892,7 +7896,7 @@ qemuProcessReconnect(void *opaque)
 
     qemuProcessNotifyNets(obj->def);
 
-    if (qemuProcessFiltersInstantiate(obj->def, true))
+    if (qemuProcessFiltersInstantiate(obj->def, true, true))
         goto error;
 
     if (qemuProcessRefreshDisks(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index f116e619ef..29d26848f3 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -137,7 +137,8 @@ umlConnectTapDevice(virDomainDefPtr vm,
     }
 
     if (net->filter) {
-        if (virDomainConfNWFilterInstantiate(vm->name, vm->uuid, net, false) < 
0) {
+        if (virDomainConfNWFilterInstantiate(vm->name, vm->uuid, net,
+                                             false, false) < 0) {
             if (template_ifname)
                 VIR_FREE(net->ifname);
             goto error;
-- 
2.17.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to