9219d1
From 536d6aa32497ab17e12767446f294fc8467cfc7c Mon Sep 17 00:00:00 2001
9219d1
From: Dumitru Ceara <dceara@redhat.com>
9219d1
Date: Thu, 3 Sep 2020 17:03:45 +0200
9219d1
Subject: [PATCH 1/2] chassis: Fix the way encaps are updated for a chassis
9219d1
 record.
9219d1
9219d1
ovn-controller always stores the last configured system-id/chassis-id in
9219d1
memory regardless if the connection to the SB is up or down. This is OK
9219d1
as long as the change can be committed successfully when the SB DB
9219d1
connection comes back up.
9219d1
9219d1
Without this change, if the chassis-id changes while the SB connection is
9219d1
down, ovn-controller will fail to create the new record but nevertheless
9219d1
update its in-memory chassis-id. When the SB connection is restored
9219d1
ovn-controller tries to find the record corresponding to the chassis-id
9219d1
it stored in memory. This fails causing ovn-controller to try to insert
9219d1
a new record. But at this point a constraint violation is hit in the SB
9219d1
because the Encap records of the "stale" chassis still exist in the DB,
9219d1
along with the old chassis record.
9219d1
9219d1
This commit changes the way we search for a "stale" chassis record in the
9219d1
SB to cover the above mentioned case. Also, in such cases there's no need
9219d1
to recreate the Encaps, it's sufficient to update the chassis_name field.
9219d1
9219d1
Fixes: 5344f24ecb1a ("ovn-controller: Refactor chassis.c to abstract the string parsing")
9219d1
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
9219d1
Signed-off-by: Numan Siddique <numans@ovn.org>
9219d1
9219d1
(cherry-picked from master commit 94a32fca2d2b825fece0ef5b1873459bd9857dd3)
9219d1
9219d1
(cherry picked from upstream commit 0716c4f4cf2d97f03c1f2e5099fece92f3183d43)
9219d1
9219d1
Change-Id: I20f0c61fddffba599b16f43d15b110414a6a6e6b
9219d1
---
9219d1
 controller/chassis.c    | 60 +++++++++++++++++++++++++++++++------------------
9219d1
 tests/ovn-controller.at | 17 ++++++++++++++
9219d1
 2 files changed, 55 insertions(+), 22 deletions(-)
9219d1
9219d1
diff --git a/controller/chassis.c b/controller/chassis.c
9219d1
index 6ac591e..773d966 100644
9219d1
--- a/controller/chassis.c
9219d1
+++ b/controller/chassis.c
9219d1
@@ -397,10 +397,7 @@ chassis_tunnels_changed(const struct sset *encap_type_set,
9219d1
 {
9219d1
     size_t encap_type_count = 0;
9219d1
 
9219d1
-    for (int i = 0; i < chassis_rec->n_encaps; i++) {
9219d1
-        if (strcmp(chassis_rec->name, chassis_rec->encaps[i]->chassis_name)) {
9219d1
-            return true;
9219d1
-        }
9219d1
+    for (size_t i = 0; i < chassis_rec->n_encaps; i++) {
9219d1
 
9219d1
         if (!sset_contains(encap_type_set, chassis_rec->encaps[i]->type)) {
9219d1
             return true;
9219d1
@@ -473,6 +470,19 @@ chassis_build_encaps(struct ovsdb_idl_txn *ovnsb_idl_txn,
9219d1
 }
9219d1
 
9219d1
 /*
9219d1
+ * Updates encaps for a given chassis. This can happen when the chassis
9219d1
+ * name has changed. Also, the only thing we support updating is the
9219d1
+ * chassis_name. For other changes the encaps will be recreated.
9219d1
+ */
9219d1
+static void
9219d1
+chassis_update_encaps(const struct sbrec_chassis *chassis)
9219d1
+{
9219d1
+    for (size_t i = 0; i < chassis->n_encaps; i++) {
9219d1
+        sbrec_encap_set_chassis_name(chassis->encaps[i], chassis->name);
9219d1
+    }
9219d1
+}
9219d1
+
9219d1
+/*
9219d1
  * Returns a pointer to a chassis record from 'chassis_table' that
9219d1
  * matches at least one tunnel config.
9219d1
  */
9219d1
@@ -503,9 +513,10 @@ chassis_get_stale_record(const struct sbrec_chassis_table *chassis_table,
9219d1
 /* If this is a chassis config update after we initialized the record once
9219d1
  * then we should always be able to find it with the ID we saved in
9219d1
  * chassis_state.
9219d1
- * Otherwise (i.e., first time we create the record) then we check if there's
9219d1
- * a stale record from a previous controller run that didn't end gracefully
9219d1
- * and reuse it. If not then we create a new record.
9219d1
+ * Otherwise (i.e., first time we create the record or if the system-id
9219d1
+ * changed) then we check if there's a stale record from a previous
9219d1
+ * controller run that didn't end gracefully and reuse it. If not then we
9219d1
+ * create a new record.
9219d1
  *
9219d1
  * Sets '*chassis_rec' to point to the local chassis record.
9219d1
  * Returns true if this record was already in the database, false if it was
9219d1
@@ -519,28 +530,32 @@ chassis_get_record(struct ovsdb_idl_txn *ovnsb_idl_txn,
9219d1
                    const char *chassis_id,
9219d1
                    const struct sbrec_chassis **chassis_rec)
9219d1
 {
9219d1
+    const struct sbrec_chassis *chassis = NULL;
9219d1
+
9219d1
     if (chassis_info_id_inited(&chassis_state)) {
9219d1
-        *chassis_rec = chassis_lookup_by_name(sbrec_chassis_by_name,
9219d1
-                                              chassis_info_id(&chassis_state));
9219d1
-        if (!(*chassis_rec)) {
9219d1
-            VLOG_DBG("Could not find Chassis, will create it"
9219d1
-                     ": stored (%s) ovs (%s)",
9219d1
+        chassis = chassis_lookup_by_name(sbrec_chassis_by_name,
9219d1
+                                         chassis_info_id(&chassis_state));
9219d1
+        if (!chassis) {
9219d1
+            VLOG_DBG("Could not find Chassis, will check if the id changed: "
9219d1
+                     "stored (%s) ovs (%s)",
9219d1
                      chassis_info_id(&chassis_state), chassis_id);
9219d1
-            if (ovnsb_idl_txn) {
9219d1
-                /* Recreate the chassis record.  */
9219d1
-                *chassis_rec = sbrec_chassis_insert(ovnsb_idl_txn);
9219d1
-                return false;
9219d1
-            }
9219d1
         }
9219d1
-    } else {
9219d1
-        *chassis_rec =
9219d1
-            chassis_get_stale_record(chassis_table, ovs_cfg, chassis_id);
9219d1
+    }
9219d1
 
9219d1
-        if (!(*chassis_rec) && ovnsb_idl_txn) {
9219d1
+    if (!chassis) {
9219d1
+        chassis = chassis_get_stale_record(chassis_table, ovs_cfg, chassis_id);
9219d1
+    }
9219d1
+
9219d1
+    if (!chassis) {
9219d1
+        /* Recreate the chassis record. */
9219d1
+        VLOG_DBG("Could not find Chassis, will create it: %s", chassis_id);
9219d1
+        if (ovnsb_idl_txn) {
9219d1
             *chassis_rec = sbrec_chassis_insert(ovnsb_idl_txn);
9219d1
-            return false;
9219d1
         }
9219d1
+        return false;
9219d1
     }
9219d1
+
9219d1
+    *chassis_rec = chassis;
9219d1
     return true;
9219d1
 }
9219d1
 
9219d1
@@ -602,6 +617,7 @@ chassis_update(const struct sbrec_chassis *chassis_rec,
9219d1
                                 &ovs_cfg->encap_ip_set, ovs_cfg->encap_csum,
9219d1
                                 chassis_rec);
9219d1
     if (!tunnels_changed) {
9219d1
+        chassis_update_encaps(chassis_rec);
9219d1
         return updated;
9219d1
     }
9219d1
 
9219d1
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
9219d1
index 1b96934..f2faf1f 100644
9219d1
--- a/tests/ovn-controller.at
9219d1
+++ b/tests/ovn-controller.at
9219d1
@@ -196,6 +196,23 @@ OVS_WAIT_UNTIL([
9219d1
     test "${sysid}" = "${chassis_id}"
9219d1
 ])
9219d1
 
9219d1
+# Simulate system-id changing while ovn-controller is disconnected from the
9219d1
+# SB.
9219d1
+valid_remote=$(ovs-vsctl get Open_vSwitch . external_ids:ovn-remote)
9219d1
+invalid_remote=tcp:0.0.0.0:4242
9219d1
+ovs-vsctl set Open_vSwitch . external_ids:ovn-remote=${invalid_remote}
9219d1
+expected_state="not connected"
9219d1
+OVS_WAIT_UNTIL([
9219d1
+    test "${expected_state}" = "$(ovn-appctl -t ovn-controller connection-status)"
9219d1
+])
9219d1
+sysid=${sysid}-bar
9219d1
+ovs-vsctl set Open_vSwitch . external-ids:system-id="${sysid}"
9219d1
+ovs-vsctl set Open_vSwitch . external_ids:ovn-remote=${valid_remote}
9219d1
+OVS_WAIT_UNTIL([
9219d1
+    chassis_id=$(ovn-sbctl get Chassis "${sysid}" name)
9219d1
+    test "${sysid}" = "${chassis_id}"
9219d1
+])
9219d1
+
9219d1
 # Gracefully terminate daemons
9219d1
 OVN_CLEANUP_SBOX([hv])
9219d1
 OVN_CLEANUP_VSWITCH([main])
9219d1
-- 
9219d1
1.8.3.1
9219d1