This change makes it so that if a chassis has no encaps configured, the
entire Chassis record is deleted.

If a chassis hv1 has encap A, and then encap A is removed from hv1,
chassis hv2 should be able to use encap A. But this is not possible if
the Encap record is still present in the sb db.

The reasoning for deleting the entire Chassis record rather than just
its Encap is that a chassis is already considered misconfigured if it
has no encaps set. We could allow encap-less chassis, but we already
have the behavior established of deleting chassis with no valid encaps
(if there are duplicates) in chassis_update(), and allowing 0 encaps
would also require a schema change and checking for n_encaps>0 in many
places.

So the easiest solution is just to remove the chassis record altogether.
When encaps are readded, the chassis record will be recreated.

Reported-at: https://redhat.atlassian.net/browse/FDP-1945
Signed-off-by: Rosemarie O'Riorden <[email protected]>
---
 controller/chassis.c    | 46 +++++++++++++++++++++++++++++++------
 tests/ovn-controller.at | 51 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 7 deletions(-)

diff --git a/controller/chassis.c b/controller/chassis.c
index b82683064..ed3d0e878 100644
--- a/controller/chassis.c
+++ b/controller/chassis.c
@@ -82,6 +82,12 @@ enum chassis_update_status {
     CHASSIS_NEED_DELETE
 };
 
+enum chassis_parse_status {
+    CHASSIS_PARSED,
+    CHASSIS_NO_CFG,
+    CHASSIS_DELETE_NO_ENCAPS,
+};
+
 static void
 ovs_chassis_cfg_init(struct ovs_chassis_cfg *cfg)
 {
@@ -303,9 +309,12 @@ chassis_parse_ovs_iface_types(char **iface_types, size_t 
n_iface_types,
 }
 
 /*
- * Parse the 'ovs_table' entry and populate 'ovs_cfg'.
+ * Parse the 'ovs_table' entry and populate 'ovs_cfg'.  If successful,
+ * returns CHASSIS_PARSED.
+ * Otherwise, returns CHASSIS_NO_CFG if 'ovs_table' is NULL, or
+ * CHASSIS_DELETE_NO_ENCAPS if encap type or ip is NULL.
  */
-static bool
+static enum chassis_parse_status
 chassis_parse_ovs_config(const struct ovsrec_open_vswitch_table *ovs_table,
                          const struct ovsrec_bridge *br_int,
                          struct ovs_chassis_cfg *ovs_cfg)
@@ -316,7 +325,7 @@ chassis_parse_ovs_config(const struct 
ovsrec_open_vswitch_table *ovs_table,
 
     if (!cfg) {
         VLOG_INFO("No Open_vSwitch row defined.");
-        return false;
+        return CHASSIS_NO_CFG;
     }
 
     const char *chassis_id = get_ovs_chassis_id(ovs_table);
@@ -328,8 +337,9 @@ chassis_parse_ovs_config(const struct 
ovsrec_open_vswitch_table *ovs_table,
         get_chassis_external_id_value(&cfg->external_ids, chassis_id,
                                       "ovn-encap-ip", NULL);
     if (!encap_type || !encap_ips) {
-        VLOG_INFO_RL(&rl, "Need to specify an encap type and ip");
-        return false;
+        VLOG_WARN_RL(&rl, "No encap type and/or ip on chassis '%s'. Deleting "
+                     "chassis.", chassis_id);
+        return CHASSIS_DELETE_NO_ENCAPS;
     }
 
     ovs_cfg->hostname = get_hostname(&cfg->external_ids, chassis_id);
@@ -386,7 +396,7 @@ chassis_parse_ovs_config(const struct 
ovsrec_open_vswitch_table *ovs_table,
     ovs_cfg->ct_label_flush =
         ovs_feature_is_supported(OVS_CT_LABEL_FLUSH_SUPPORT);
 
-    return true;
+    return CHASSIS_PARSED;
 }
 
 static void
@@ -958,7 +968,29 @@ chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
 
     /* Get the chassis config from the ovs table. */
     ovs_chassis_cfg_init(&ovs_cfg);
-    if (!chassis_parse_ovs_config(ovs_table, br_int, &ovs_cfg)) {
+    enum chassis_parse_status parse_status =
+        chassis_parse_ovs_config(ovs_table, br_int, &ovs_cfg);
+
+    if (parse_status == CHASSIS_NO_CFG) {
+        ovs_chassis_cfg_destroy(&ovs_cfg);
+        return NULL;
+    }
+
+    /* If no encaps are configured, delete the Chassis record. */
+    if (parse_status == CHASSIS_DELETE_NO_ENCAPS) {
+        const struct sbrec_chassis *chassis_rec =
+            chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
+        if (chassis_rec && ovnsb_idl_txn) {
+            sbrec_chassis_delete(chassis_rec);
+        }
+        *chassis_private =
+            chassis_private_lookup_by_name(sbrec_chassis_private_by_name,
+                                           chassis_id);
+        if (*chassis_private && ovnsb_idl_txn) {
+            sbrec_chassis_private_delete(*chassis_private);
+        }
+
+        ovs_chassis_cfg_destroy(&ovs_cfg);
         return NULL;
     }
 
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
index d600ba2cd..4d1860136 100644
--- a/tests/ovn-controller.at
+++ b/tests/ovn-controller.at
@@ -4520,3 +4520,54 @@ done
 OVN_CLEANUP([gw1],[gw3],[hv2])
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn-controller - remove encap from chassis add to other chassis])
+AT_KEYWORDS([ovn])
+ovn_start
+net_add n1
+
+sim_add hv1
+as hv1 check ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.11
+
+sim_add hv2
+as hv2 check ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.12
+
+as hv2
+OVS_WAIT_FOR_OUTPUT([ovs-vsctl find Interface type=geneve | grep -c _uuid], 
[0], [1
+])
+
+as hv1
+OVS_WAIT_FOR_OUTPUT([ovs-vsctl find Interface type=geneve | grep -c _uuid], 
[0], [1
+])
+wait_row_count Encap 4
+wait_row_count Chassis 2
+
+# Remove hv1's encap.
+as hv1 check ovs-vsctl remove Open_vSwitch . external-ids 
ovn-encap-ip="192.168.0.11"
+check ovn-nbctl --wait=sb sync
+
+# Make sure that hv1's chassis rec was deleted from sb.  And of course with
+# that its encaps too.
+OVS_WAIT_UNTIL([test $(ovn-sbctl --bare find Encap chassis_name=hv1 
ip="192.168.0.11" | wc -l) -eq 0])
+wait_row_count Encap 0 chassis_name="hv1" ip="192.168.0.11"
+wait_row_count Chassis 0 name="hv1"
+OVS_WAIT_UNTIL([grep -q "No encap type and/or ip on chassis 'hv1'. Deleting 
chassis."  hv1/ovn-controller.log
+])
+
+# Assign hv1's old encap ip to hv2.  Verify it worked.
+as hv2 check ovs-vsctl set Open_vSwitch . 
external-ids:ovn-encap-ip="192.168.0.11"
+wait_row_count Encap 0 chassis_name="hv2" ip="192.168.0.12"
+wait_row_count Encap 2 chassis_name="hv2" ip="192.168.0.11"
+
+# Now give hv1 a new different encap ip.  Verify the chassis is back.
+as hv1 check ovs-vsctl set Open_vSwitch . 
external-ids:ovn-encap-ip="192.168.0.13"
+check ovn-nbctl --wait=hv sync
+wait_row_count Encap 2 chassis_name="hv1" ip="192.168.0.13"
+wait_row_count Chassis 1 name="hv1"
+
+OVN_CLEANUP([hv1],[hv2])
+AT_CLEANUP
+])
-- 
2.56.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to