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

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]>

---
v2:
 - Back up database before deleting it
 - Use the db-name command to check for validity of file
 - Added test to verify that valid clustered databases are detected as
v3:
 - Removed sourcing of lsb functions
 - Corrected comment formatting.
 - Restored test instead of valdidate_db check

---
 tests/ovsdb-server.at | 56 +++++++++++++++++++++++++++++++++++++++++++
 utilities/ovs-lib.in  | 32 ++++++++++++++++++++++---
 2 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
index b71947511..69f3d41fc 100644
--- a/tests/ovsdb-server.at
+++ b/tests/ovsdb-server.at
@@ -105,6 +105,62 @@ AT_CHECK([uuidfilt output], [0],
 ]], [])
 AT_CLEANUP
 
+AT_SETUP([database without valid schema is recreated])
+AT_KEYWORDS([ovsdb unix])
+AT_SKIP_IF([test "$IS_WIN32" = "yes"])
+ordinal_schema > schema
+
+dnl Loading ovs-lib resets our PATH, save a copy and then restore.
+. 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_CHECK([validate_db db], [0])
+
+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
+dnl previous test but 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 -q 'syntax error: db: parse error.* in header line "xxx"' 
stderr])
+AT_CHECK([uuidfilt stdout], [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 -Ec 'Backing up database|Creating cluster database db' stdout], 
[0], [2
+])
+AT_CHECK([validate_db db])
+
+dnl Join a cluster with a corrupted db.
+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 -Ec 'Backing up database|Joining db to cluster' stdout], [0], [2
+])
+AT_CHECK([validate_db db])
+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 582fdd0df..74805e47e 100644
--- a/utilities/ovs-lib.in
+++ b/utilities/ovs-lib.in
@@ -428,16 +428,40 @@ create_db () {
 
 backup_db () {
     # Back up the old version.
-    version=`ovsdb_tool db-version "$DB_FILE"`
-    cksum=`ovsdb_tool db-cksum "$DB_FILE" | awk '{print $1}'`
-    backup=$DB_FILE.backup$version-$cksum
+    if test ! -e "$DB_FILE"; then
+        return 0
+    elif ovsdb_tool db-is-standalone "$DB_FILE" 2>/dev/null; then
+        version=`ovsdb_tool db-version "$DB_FILE"`
+        cksum=`ovsdb_tool db-cksum "$DB_FILE" | awk '{print $1}'`
+        backup=$DB_FILE.backup$version-$cksum
+    else
+        # Support for clsutered databases.
+        backup=`mktemp -q $DB_FILE.XXXXXXXXXX`
+    fi
     action "Backing up database to $backup" cp "$DB_FILE" "$backup" || return 1
 }
 
+validate_db () {
+    # Returns 0 if $DB_FILE is present and at least has a db name.
+    # Returns 1 if $DB_FILE is not present.
+    DB_FILE="$1"
+
+    if test ! -e "$DB_FILE"; then
+        return 1
+    elif ! ovsdb_tool db-name "$DB_FILE" >/dev/null 2>&1; then
+        backup_db "$DB_FILE"
+        action "Removing invalid database file $DB_FILE" rm -f "$DB_FILE"
+        return 1
+    fi
+
+    return 0
+}
+
 upgrade_db () {
     DB_FILE="$1"
     DB_SCHEMA="$2"
 
+    validate_db "$DB_FILE"
     schemaver=`ovsdb_tool schema-version "$DB_SCHEMA"`
     if test ! -e "$DB_FILE"; then
         log_warning_msg "$DB_FILE does not exist"
@@ -500,6 +524,7 @@ create_cluster () {
       election_timer_arg="--election-timer=$ELECTION_TIMER_MS"
     fi
 
+    validate_db "$DB_FILE"
     if test ! -e "$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
@@ -517,6 +542,7 @@ join_cluster() {
     LOCAL_ADDR="$3"
     REMOTE_ADDR="$4"
 
+    validate_db "$DB_FILE"
     if test -e "$DB_FILE" && ovsdb_tool db-is-standalone "$DB_FILE"; then
         backup_db || return 1
         rm $DB_FILE
-- 
2.43.5

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

Reply via email to