Previously ovs-lib would assume a database is valid if the file exists,
however, it is possible for the database file to exist but be unopenable
by ovsdb.

Now existence checks are augmented with schema checksum validation.
Databases with an invalid schema are removed.

Reported-at: https://issues.redhat.com/browse/FDP-689
Reported-by: Ihar Hrachyshka
Signed-off-by: Mike Pattrick <[email protected]>
---
 tests/ovsdb-server.at | 50 +++++++++++++++++++++++++++++++++++++++++++
 utilities/ovs-lib.in  | 23 ++++++++++++++++----
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
index ce6d32aee..54c1cda97 100644
--- a/tests/ovsdb-server.at
+++ b/tests/ovsdb-server.at
@@ -105,6 +105,56 @@ AT_CHECK([uuidfilt output], [0],
 ]], [])
 AT_CLEANUP
 
+AT_SETUP([truncated database recreated])
+AT_KEYWORDS([ovsdb unix])
+AT_SKIP_IF([test "$IS_WIN32" = "yes"])
+ordinal_schema > schema
+. ovs-lib
+
+dnl Check that DB is recreated when schema corrupted.
+echo 'x' > db
+AT_CHECK([upgrade_db db schema], [0], [stdout], [ignore])
+AT_CHECK([grep -c "db does not exist\|Creating empty database db" stdout], 
[0], [2
+])
+
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+  {"op": "insert",
+   "table": "ordinals",
+   "row": {"number": 1, "name": "one"}}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket db --run="sh txnfile"], [0], 
[stdout], [stderr])
+
+dnl Check that DB is not recreated on corrupted log. This is similar to the 
previous test but
+dnl includes a mid-operation upgrade.
+echo 'xxx' >> db
+AT_CHECK([upgrade_db db schema], [0], [], [ignore])
+
+dnl Validate that the db can now be used.
+AT_DATA([txnfile], [[ovsdb-client transact unix:socket \
+'["ordinals",
+  {"op": "select",
+   "table": "ordinals",
+   "where": []}]'
+]])
+AT_CHECK([ovsdb-server --remote=punix:socket db --run="sh txnfile"], [0], 
[stdout], [stderr])
+AT_CHECK([grep 'syntax error: db: parse error.* in header line "xxx"' stderr], 
[0], [ignore])
+cat stdout >> output
+AT_CHECK([uuidfilt output], [0],
+  
[[[{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<1>"],"name":"one","number":1}]}]
+]], [])
+
+dnl Validate then create and join cluster.
+echo 'x' > db
+AT_CHECK([create_cluster db schema tcp:1.1.1.1:1111 1000], [0], [stdout], [])
+AT_CHECK([grep -c 'Creating cluster database db' stdout], [0], [1
+])
+echo 'x' > db
+AT_CHECK([join_cluster db schema tcp:1.1.1.1:1111 tcp:2.2.2.2:2222], [0], 
[stdout], [])
+AT_CHECK([grep -c 'Joining db to cluster' stdout], [0], [1
+])
+AT_CLEANUP
+
 AT_SETUP([truncating database log with bad transaction])
 AT_KEYWORDS([ovsdb server positive unix])
 AT_SKIP_IF([test "$IS_WIN32" = "yes"])
diff --git a/utilities/ovs-lib.in b/utilities/ovs-lib.in
index 7812a94ee..7e580d730 100644
--- a/utilities/ovs-lib.in
+++ b/utilities/ovs-lib.in
@@ -447,12 +447,27 @@ backup_db () {
     action "Backing up database to $backup" cp "$DB_FILE" "$backup" || return 1
 }
 
+validate_db () {
+    # Returns 0 if $DB_FILE is present and has a valid schema.
+    # Returns 1 if $DB_FILE is not present.
+    DB_FILE="$1"
+
+    if test ! -e "$DB_FILE"; then
+        return 1
+    elif ! ovsdb_tool db-cksum "$DB_FILE" >/dev/null 2>&1; then
+        rm -f "$DB_FILE"
+        return 1
+    fi
+
+    return 0
+}
+
 upgrade_db () {
     DB_FILE="$1"
     DB_SCHEMA="$2"
 
     schemaver=`ovsdb_tool schema-version "$DB_SCHEMA"`
-    if test ! -e "$DB_FILE"; then
+    if ! validate_db "$DB_FILE"; then
         log_warning_msg "$DB_FILE does not exist"
         install_dir `dirname $DB_FILE`
         create_db "$DB_FILE" "$DB_SCHEMA"
@@ -513,7 +528,7 @@ create_cluster () {
       election_timer_arg="--election-timer=$ELECTION_TIMER_MS"
     fi
 
-    if test ! -e "$DB_FILE"; then
+    if ! validate_db "$DB_FILE"; then
         action "Creating cluster database $DB_FILE" ovsdb_tool 
$election_timer_arg create-cluster "$DB_FILE" "$DB_SCHEMA" "$LOCAL_ADDR"
     elif ovsdb_tool db-is-standalone "$DB_FILE"; then
         # Convert standalone database to clustered.
@@ -530,11 +545,11 @@ join_cluster() {
     LOCAL_ADDR="$3"
     REMOTE_ADDR="$4"
 
-    if test -e "$DB_FILE" && ovsdb_tool db-is-standalone "$DB_FILE"; then
+    if validate_db "$DB_FILE" && ovsdb_tool db-is-standalone "$DB_FILE"; then
         backup_db || return 1
         rm $DB_FILE
     fi
-    if test ! -e "$DB_FILE"; then
+    if ! validate_db "$DB_FILE"; then
         action "Joining $DB_FILE to cluster" \
                ovsdb_tool join-cluster "$DB_FILE" "$SCHEMA_NAME" "$LOCAL_ADDR" 
"$REMOTE_ADDR"
     fi
-- 
2.39.3

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

Reply via email to