diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 9827320ec37..d803a3d1b1d 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -534,7 +534,8 @@ parse_txn(struct server_config *config, struct db *db, struct ovsdb_schema *schema, const struct json *txn_json, const struct uuid *txnid) { - if (schema) { + if (schema && (!db->db->schema || strcmp(schema->version, + db->db->schema->version))) { /* We're replacing the schema (and the data). Destroy the database * (first grabbing its storage), then replace it with the new schema. * The transaction must also include the replacement data. diff --git a/tests/ovsdb-cluster.at b/tests/ovsdb-cluster.at index 15f821be6db..f5dd4a805b3 100644 --- a/tests/ovsdb-cluster.at +++ b/tests/ovsdb-cluster.at @@ -273,6 +273,62 @@ OVS_WAIT_UNTIL([ovs-appctl -t "`pwd`"/s4 cluster/status $schema_name | grep "Ele AT_CLEANUP + +AT_BANNER([OVSDB cluster install snapshot RPC]) + +AT_SETUP([OVSDB cluster - install snapshot RPC]) +AT_KEYWORDS([ovsdb server positive unix cluster snapshot]) + +n=3 +schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema` +ordinal_schema > schema +AT_CHECK([ovsdb-tool '-vPATTERN:console:%c|%p|%m' create-cluster s1.db $abs_srcdir/idltest.ovsschema unix:s1.raft], [0], [], [stderr]) +cid=`ovsdb-tool db-cid s1.db` +schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema` +for i in `seq 2 $n`; do + AT_CHECK([ovsdb-tool join-cluster s$i.db $schema_name unix:s$i.raft unix:s1.raft]) +done + +on_exit 'kill `cat *.pid`' +for i in `seq $n`; do + AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb s$i.db]) +done +for i in `seq $n`; do + AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected]) +done + +# Kill one follower (s2) and write some data to cluster, so that the follower is falling behind +printf "\ns2: stopping\n" +OVS_APP_EXIT_AND_WAIT_BY_TARGET([`pwd`/s2], [s2.pid]) + +AT_CHECK([ovsdb-client transact unix:s1.ovsdb '[["idltest", + {"op": "insert", + "table": "simple", + "row": {"i": 1}}]]'], [0], [ignore], [ignore]) + +# Compact leader online to generate snapshot +AT_CHECK([ovs-appctl -t "`pwd`"/s1 ovsdb-server/compact]) + +# Start the follower s2 again. +AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s2.log --pidfile=s2.pid --unixctl=s2 --remote=punix:s2.ovsdb s2.db]) +AT_CHECK([ovsdb_client_wait unix:s2.ovsdb $schema_name connected]) + +# A client transaction through s2. During this transaction, there will be a +# install_snapshot RPC because s2 detects it is behind and s1 doesn't have the +# pre_log_index requested by s2 because it is already compacted. +# After the install_snapshot RPC process, the transaction through s2 should +# succeed. +AT_CHECK([ovsdb-client transact unix:s2.ovsdb '[["idltest", + {"op": "insert", + "table": "simple", + "row": {"i": 1}}]]'], [0], [ignore], [ignore]) + +for i in `seq $n`; do + OVS_APP_EXIT_AND_WAIT_BY_TARGET([`pwd`/s$i], [s$i.pid]) +done + +AT_CLEANUP + OVS_START_SHELL_HELPERS