From 8159b984dced44851670bd48e204b4e854941a24 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 27 Dec 2010 14:26:47 -0800 Subject: [PATCH] Implement database schema versioning. As the database schema evolves, it might be useful to have an identifier for the particular version in use. This commit adds that feature. --- ovsdb/SPECS | 12 +++++++++++ ovsdb/ovsdb-client.1.in | 15 +++++++++++++ ovsdb/ovsdb-client.c | 12 +++++++++++ ovsdb/ovsdb-tool.1.in | 29 +++++++++++++++++++++++++ ovsdb/ovsdb-tool.c | 26 ++++++++++++++++++++++ ovsdb/ovsdb.c | 37 +++++++++++++++++++++++++++----- ovsdb/ovsdb.h | 4 +++- python/ovs/db/schema.py | 25 +++++++++++++++------ tests/idltest.ovsschema | 3 ++- tests/ovsdb-execution.at | 3 ++- tests/ovsdb-schema.at | 26 +++++++++++++++++++++- tests/ovsdb-server.at | 13 ++++++++++- tests/ovsdb-tool.at | 20 ++++++++++++++++- vswitchd/automake.mk | 12 +++++++++++ vswitchd/vswitch.ovsschema | 5 +++++ vswitchd/vswitch.xml | 20 +++++++++++++++++ xenserver/etc_init.d_openvswitch | 11 +++++++++- 17 files changed, 255 insertions(+), 18 deletions(-) diff --git a/ovsdb/SPECS b/ovsdb/SPECS index 326293c71..97f988265 100644 --- a/ovsdb/SPECS +++ b/ovsdb/SPECS @@ -33,6 +33,11 @@ values. Additional notation is presented later. s that begin with _ are reserved to the implementation and may not be used by the user. + + + A JSON string that contains a version number that matches + [0-9]+\.[0-9]+\.[0-9]+ + A JSON true or false value. @@ -102,6 +107,7 @@ is represented by , as described below. A JSON object with the following members: "name": required + "version": required "tables": {: , ...} required The "name" identifies the database as a whole. It must be @@ -109,6 +115,12 @@ is represented by , as described below. operated on. The value of "tables" is a JSON object whose names are table names and whose values are s. + The "version" reports the version of the database schema. Because + this is a recent addition to the schema format, OVSDB permits it + to be omitted, but future versions of OVSDB will require it to be + present. Open vSwitch semantics for "version" are described in + ovs-vswitchd.conf.db(5). + A JSON object with the following members: diff --git a/ovsdb/ovsdb-client.1.in b/ovsdb/ovsdb-client.1.in index 22b4e2322..725211d70 100644 --- a/ovsdb/ovsdb-client.1.in +++ b/ovsdb/ovsdb-client.1.in @@ -19,6 +19,8 @@ ovsdb\-client \- command-line interface to \fBovsdb-server\fR(1) .br \fBovsdb\-client \fR[\fIoptions\fR] \fBget\-schema\fI server database\fR .br +\fBovsdb\-client \fR[\fIoptions\fR] \fBget\-schema\-version\fI server database\fR +.br \fBovsdb\-client \fR[\fIoptions\fR] \fBlist\-tables\fI server database\fR .br \fBovsdb\-client \fR[\fIoptions\fR] \fBlist\-columns\fI server database \fR[\fItable\fR] @@ -61,6 +63,19 @@ be used for \fIdatabase\fR in the following commands. Connects to \fIserver\fR, retrieves the schema for \fIdatabase\fR, and prints it in JSON format. . +.IP "\fBget\-schema\-version\fI server database\fR" +Connects to \fIserver\fR, retrieves the schema for \fIdatabase\fR, and +prints its version number on stdout. A schema version number has the form +\fIx\fB.\fIy\fB.\fIz\fR. See \fBovs\-vswitchd.conf.db\fR(5) for +details. +.IP +Schema version numbers and Open vSwitch version numbers are +independent. +.IP +If \fIdatabase\fR was created before schema versioning was introduced, +then it will not have a version number and this command will print a +blank line. +. .IP "\fBlist\-tables\fI server database\fR" Connects to \fIserver\fR, retrieves the schema for \fIdatabase\fR, and prints a table listing the name of each table diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 6d19e5df2..da6a6d6d7 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -182,6 +182,9 @@ usage(void) " list databases available on SERVER\n" "\n get-schema SERVER DATABASE\n" " retrieve schema for DATABASE from SERVER\n" + "\n get-schema-version SERVER DATABASE\n" + " retrieve schema for DATABASE from SERVER and report only its\n" + " version number on stdout\n" "\n list-tables SERVER DATABASE\n" " list tables for DATABASE on SERVER\n" "\n list-columns SERVER DATABASE [TABLE]\n" @@ -781,6 +784,14 @@ do_get_schema(int argc OVS_UNUSED, char *argv[]) ovsdb_schema_destroy(schema); } +static void +do_get_schema_version(int argc OVS_UNUSED, char *argv[]) +{ + struct ovsdb_schema *schema = fetch_schema(argv[1], argv[2]); + puts(schema->version); + ovsdb_schema_destroy(schema); +} + static void do_list_tables(int argc OVS_UNUSED, char *argv[]) { @@ -1344,6 +1355,7 @@ do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) static const struct command all_commands[] = { { "list-dbs", 1, 1, do_list_dbs }, { "get-schema", 2, 2, do_get_schema }, + { "get-schema-version", 2, 2, do_get_schema_version }, { "list-tables", 2, 2, do_list_tables }, { "list-columns", 2, 3, do_list_columns }, { "transact", 2, 2, do_transact }, diff --git a/ovsdb/ovsdb-tool.1.in b/ovsdb/ovsdb-tool.1.in index b073f6d57..069ab1a4d 100644 --- a/ovsdb/ovsdb-tool.1.in +++ b/ovsdb/ovsdb-tool.1.in @@ -14,6 +14,15 @@ ovsdb\-tool \- Open vSwitch database management utility .SH SYNOPSIS \fBovsdb\-tool \fR[\fIoptions\fR] \fBcreate\fI db schema\fR .br +\fBovsdb\-tool \fR[\fIoptions\fR] \fBcompact \fIdb \fR[\fItarget\fR] +.br +\fBovsdb\-tool \fR[\fIoptions\fR] \fBconvert\fI db schema +\fR[\fItarget\fR] +.br +\fBovsdb\-tool \fR[\fIoptions\fR] \fBdb\-version\fI db\fR +.br +\fBovsdb\-tool \fR[\fIoptions\fR] \fBschema\-version\fI schema\fR +.br \fBovsdb\-tool \fR[\fIoptions\fR] \fBquery\fI db transaction\fR .br \fBovsdb\-tool \fR[\fIoptions\fR] \fBtransact\fI db transaction\fR @@ -63,6 +72,26 @@ ignored. Columns that exist in \fIschema\fR but not in \fIdb\fR are set to their default values. All of \fIschema\fR's constraints apply in full. . +.IP "\fBdb\-version\fI db\fR" +Reads \fIdb\fR and prints the version number of the schema embedded +within the database on stdout. A schema version number has the form +\fIx\fB.\fIy\fB.\fIz\fR. See \fBovs\-vswitchd.conf.db\fR(5) for +details. +.IP +Schema version numbers and Open vSwitch version numbers are +independent. +.IP +If \fIdb\fR was created before schema versioning was introduced, then +it will not have a version number and this command will print a blank +line. +. +.IP "\fBschema\-version\fI schema\fR" +Reads \fIschema\fR and prints the schema's version number on stdout. +.IP +If \fIschema\fR was created before versioning was introduced, then it +does not have a version number and this command will print a blank +line. +. .IP "\fBquery\fI db transaction\fR" Opens \fIdb\fR, executes \fItransaction\fR on it, and prints the results. The \fItransaction\fR must be a JSON array in the format of diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c index 5eeb28fa4..130e73779 100644 --- a/ovsdb/ovsdb-tool.c +++ b/ovsdb/ovsdb-tool.c @@ -110,6 +110,8 @@ usage(void) " create DB SCHEMA create DB with the given SCHEMA\n" " compact DB [DST] compact DB in-place (or to DST)\n" " convert DB SCHEMA [DST] convert DB to SCHEMA (to DST)\n" + " db-version DB report version of schema used by DB\n" + " schema-version SCHEMA report SCHEMA's schema version\n" " query DB TRNS execute read-only transaction on DB\n" " transact DB TRNS execute read/write transaction on DB\n" " show-log DB prints information about DB's log entries\n", @@ -239,6 +241,28 @@ do_convert(int argc OVS_UNUSED, char *argv[]) ovsdb_schema_destroy(new_schema); } +static void +do_db_version(int argc OVS_UNUSED, char *argv[]) +{ + const char *db_file_name = argv[1]; + struct ovsdb *db; + + check_ovsdb_error(ovsdb_file_open(db_file_name, true, &db, NULL)); + puts(db->schema->version); + ovsdb_destroy(db); +} + +static void +do_schema_version(int argc OVS_UNUSED, char *argv[]) +{ + const char *schema_file_name = argv[1]; + struct ovsdb_schema *schema; + + check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema)); + puts(schema->version); + ovsdb_schema_destroy(schema); +} + static void transact(bool read_only, const char *db_file_name, const char *transaction) { @@ -410,6 +434,8 @@ static const struct command all_commands[] = { { "create", 2, 2, do_create }, { "compact", 1, 2, do_compact }, { "convert", 2, 3, do_convert }, + { "db-version", 1, 1, do_db_version }, + { "schema-version", 1, 1, do_schema_version }, { "query", 2, 2, do_query }, { "transact", 2, 2, do_transact }, { "show-log", 1, 1, do_show_log }, diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c index 45683766c..b767d3867 100644 --- a/ovsdb/ovsdb.c +++ b/ovsdb/ovsdb.c @@ -26,12 +26,13 @@ #include "transaction.h" struct ovsdb_schema * -ovsdb_schema_create(const char *name) +ovsdb_schema_create(const char *name, const char *version) { struct ovsdb_schema *schema; schema = xzalloc(sizeof *schema); schema->name = xstrdup(name); + schema->version = xstrdup(version); shash_init(&schema->tables); return schema; @@ -43,7 +44,7 @@ ovsdb_schema_clone(const struct ovsdb_schema *old) struct ovsdb_schema *new; struct shash_node *node; - new = ovsdb_schema_create(old->name); + new = ovsdb_schema_create(old->name, old->version); SHASH_FOR_EACH (node, &old->tables) { const struct ovsdb_table_schema *ts = node->data; @@ -52,7 +53,6 @@ ovsdb_schema_clone(const struct ovsdb_schema *old) return new; } - void ovsdb_schema_destroy(struct ovsdb_schema *schema) { @@ -67,6 +67,7 @@ ovsdb_schema_destroy(struct ovsdb_schema *schema) } shash_destroy(&schema->tables); free(schema->name); + free(schema->version); free(schema); } @@ -116,26 +117,49 @@ ovsdb_schema_check_ref_table(const struct ovsdb_column *column, } } +static bool +is_valid_version(const char *s) +{ + int n = -1; + sscanf(s, "%*[0-9].%*[0-9].%*[0-9]%n", &n); + return n != -1 && s[n] == '\0'; +} + struct ovsdb_error * ovsdb_schema_from_json(struct json *json, struct ovsdb_schema **schemap) { struct ovsdb_schema *schema; - const struct json *name, *tables; + const struct json *name, *tables, *version_json; struct ovsdb_error *error; struct shash_node *node; struct ovsdb_parser parser; + const char *version; *schemap = NULL; ovsdb_parser_init(&parser, json, "database schema"); name = ovsdb_parser_member(&parser, "name", OP_ID); + version_json = ovsdb_parser_member(&parser, "version", + OP_STRING | OP_OPTIONAL); + ovsdb_parser_member(&parser, "cksum", OP_STRING | OP_OPTIONAL); tables = ovsdb_parser_member(&parser, "tables", OP_OBJECT); error = ovsdb_parser_finish(&parser); if (error) { return error; } - schema = ovsdb_schema_create(json_string(name)); + if (version_json) { + version = json_string(version_json); + if (!is_valid_version(version)) { + return ovsdb_syntax_error(json, NULL, "schema version \"%s\" not " + "in format x.y.z", version); + } + } else { + /* Backward compatibility with old databases. */ + version = ""; + } + + schema = ovsdb_schema_create(json_string(name), version); SHASH_FOR_EACH (node, json_object(tables)) { struct ovsdb_table_schema *table; @@ -190,6 +214,9 @@ ovsdb_schema_to_json(const struct ovsdb_schema *schema) json = json_object_create(); json_object_put_string(json, "name", schema->name); + if (schema->version[0]) { + json_object_put_string(json, "version", schema->version); + } tables = json_object_create(); diff --git a/ovsdb/ovsdb.h b/ovsdb/ovsdb.h index a83412dcd..642f686f0 100644 --- a/ovsdb/ovsdb.h +++ b/ovsdb/ovsdb.h @@ -29,10 +29,12 @@ struct uuid; /* Database schema. */ struct ovsdb_schema { char *name; + char *version; struct shash tables; /* Contains "struct ovsdb_table_schema *"s. */ }; -struct ovsdb_schema *ovsdb_schema_create(const char *name); +struct ovsdb_schema *ovsdb_schema_create(const char *name, + const char *version); struct ovsdb_schema *ovsdb_schema_clone(const struct ovsdb_schema *); void ovsdb_schema_destroy(struct ovsdb_schema *); diff --git a/python/ovs/db/schema.py b/python/ovs/db/schema.py index 189b137c7..c12eda2e2 100644 --- a/python/ovs/db/schema.py +++ b/python/ovs/db/schema.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import re import sys from ovs.db import error @@ -21,8 +22,9 @@ from ovs.db import types class DbSchema(object): """Schema for an OVSDB database.""" - def __init__(self, name, tables): + def __init__(self, name, version, tables): self.name = name + self.version = version self.tables = tables # Validate that all ref_tables refer to the names of tables @@ -36,9 +38,16 @@ class DbSchema(object): def from_json(json): parser = ovs.db.parser.Parser(json, "database schema") name = parser.get("name", ['id']) + version = parser.get_optional("version", [unicode]) + parser.get_optional("cksum", [unicode]) tablesJson = parser.get("tables", [dict]) parser.finish() + if (version is not None and + not re.match('[0-9]+\.[0-9]+\.[0-9]+$', version)): + raise error.Error("schema version \"%s\" not in format x.y.z" + % version) + tables = {} for tableName, tableJson in tablesJson.iteritems(): if tableName.startswith('_'): @@ -48,13 +57,16 @@ class DbSchema(object): raise error.Error("name must be a valid id", json) tables[tableName] = TableSchema.from_json(tableJson, tableName) - return DbSchema(name, tables) + return DbSchema(name, version, tables) def to_json(self): tables = {} for table in self.tables.itervalues(): tables[table.name] = table.to_json() - return {"name": self.name, "tables": tables} + json = {"name": self.name, "tables": tables} + if self.version: + json["version"] = self.version + return json def __check_ref_table(self, column, base, base_name): if (base and base.type == types.UuidType and base.ref_table and @@ -64,8 +76,8 @@ class DbSchema(object): tag="syntax error") class IdlSchema(DbSchema): - def __init__(self, name, tables, idlPrefix, idlHeader): - DbSchema.__init__(self, name, tables) + def __init__(self, name, version, tables, idlPrefix, idlHeader): + DbSchema.__init__(self, name, version, tables) self.idlPrefix = idlPrefix self.idlHeader = idlHeader @@ -80,7 +92,8 @@ class IdlSchema(DbSchema): del subjson["idlHeader"] schema = DbSchema.from_json(subjson) - return IdlSchema(schema.name, schema.tables, idlPrefix, idlHeader) + return IdlSchema(schema.name, schema.version, schema.tables, + idlPrefix, idlHeader) class TableSchema(object): def __init__(self, name, columns, mutable=True, max_rows=sys.maxint): diff --git a/tests/idltest.ovsschema b/tests/idltest.ovsschema index 545242bea..275a49e4f 100644 --- a/tests/idltest.ovsschema +++ b/tests/idltest.ovsschema @@ -1,5 +1,6 @@ { - "name": "idltest", + "name": "idltest", + "version": "1.2.3", "tables": { "link1": { "columns": { diff --git a/tests/ovsdb-execution.at b/tests/ovsdb-execution.at index 394fcba72..a457b2a8d 100644 --- a/tests/ovsdb-execution.at +++ b/tests/ovsdb-execution.at @@ -6,7 +6,8 @@ m4_define([ORDINAL_SCHEMA], "ordinals": { "columns": { "number": {"type": "integer"}, - "name": {"type": "string"}}}}}]]) + "name": {"type": "string"}}}}, + "version": "5.1.3"}]]) m4_define([CONSTRAINT_SCHEMA], [[{"name": "constraints", diff --git a/tests/ovsdb-schema.at b/tests/ovsdb-schema.at index 008cc4316..d129093a2 100644 --- a/tests/ovsdb-schema.at +++ b/tests/ovsdb-schema.at @@ -3,6 +3,7 @@ AT_BANNER([OVSDB -- schemas]) OVSDB_CHECK_POSITIVE_CPY([schema with valid refTables], [[parse-schema \ '{"name": "mydb", + "version": "4.2.1", "tables": { "a": { "columns": { @@ -21,7 +22,19 @@ OVSDB_CHECK_POSITIVE_CPY([schema with valid refTables], "key": { "type": "uuid", "refTable": "a"}}}}}}}']], - [[{"name":"mydb","tables":{"a":{"columns":{"map":{"type":{"key":{"refTable":"b","type":"uuid"},"value":{"refTable":"a","type":"uuid"}}}}},"b":{"columns":{"aRef":{"type":{"key":{"refTable":"a","type":"uuid"}}}}}}}]]) + [[{"name":"mydb","tables":{"a":{"columns":{"map":{"type":{"key":{"refTable":"b","type":"uuid"},"value":{"refTable":"a","type":"uuid"}}}}},"b":{"columns":{"aRef":{"type":{"key":{"refTable":"a","type":"uuid"}}}}}},"version":"4.2.1"}]]) + +dnl Schemas without version numbers are accepted for backward +dnl compatibility, but this is a deprecated feature. +OVSDB_CHECK_POSITIVE_CPY([schema without version number], + [[parse-schema \ + '{"name": "mydb", + "tables": { + "x": { + "columns": { + "y": { + "type": "integer"}}}}}']], + [{"name":"mydb","tables":{"x":{"columns":{"y":{"type":"integer"}}}}}]) OVSDB_CHECK_NEGATIVE_CPY([schema with invalid refTables], [[parse-schema \ @@ -45,3 +58,14 @@ OVSDB_CHECK_NEGATIVE_CPY([schema with invalid refTables], "type": "uuid", "refTable": "a"}}}}}}}']], [[syntax error: column map key refers to undefined table c]]) + +OVSDB_CHECK_NEGATIVE_CPY([schema with invalid version number], + [[parse-schema \ + '{"name": "mydb", + "tables": { + "x": { + "columns": { + "y": { + "type": "integer"}}}}, + "version": "xxx"}']], + [[schema version "xxx" not in format x.y.z]]) diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at index 52c196922..23125ab46 100644 --- a/tests/ovsdb-server.at +++ b/tests/ovsdb-server.at @@ -38,6 +38,17 @@ cat stdout >> output EXECUTION_EXAMPLES +AT_SETUP([ovsdb-client get-schema-version]) +AT_KEYWORDS([ovsdb server positive]) +AT_DATA([schema], [ORDINAL_SCHEMA +]) +AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-server --detach --pidfile=$PWD/pid --unixctl=$PWD/unixctl --remote=punix:socket db], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client get-schema-version unix:socket ordinals], [0], [5.1.3 +]) +OVSDB_SERVER_SHUTDOWN +AT_CLEANUP + AT_SETUP([database multiplexing implementation]) AT_KEYWORDS([ovsdb server positive]) AT_DATA([schema], [ORDINAL_SCHEMA @@ -181,7 +192,7 @@ AT_CHECK( [0], [stdout], [ignore], [test ! -e pid || kill `cat pid`]) dnl Check that all the crap is in fact in the database log. AT_CHECK([[perl $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/"_date":0/' | test-json --multiple -]], [0], - [[{"name":"ordinals","tables":{"ordinals":{"columns":{"name":{"type":"string"},"number":{"type":"integer"}}}}} + [[{"name":"ordinals","tables":{"ordinals":{"columns":{"name":{"type":"string"},"number":{"type":"integer"}}}},"version":"5.1.3"} {"_comment":"add row for zero 0","_date":0,"ordinals":{"<0>":{"name":"zero"}}} {"_comment":"delete row for 0","_date":0,"ordinals":{"<0>":null}} {"_comment":"add back row for zero 0","_date":0,"ordinals":{"<1>":{"name":"zero"}}} diff --git a/tests/ovsdb-tool.at b/tests/ovsdb-tool.at index c2ec88103..664e616d7 100644 --- a/tests/ovsdb-tool.at +++ b/tests/ovsdb-tool.at @@ -83,7 +83,7 @@ AT_CHECK( [0], [stdout], [ignore]) dnl Check that all the crap is in fact in the database log. AT_CHECK([[perl $srcdir/uuidfilt.pl db | grep -v ^OVSDB | sed 's/"_date":[0-9]*/"_date":0/' | test-json --multiple -]], [0], - [[{"name":"ordinals","tables":{"ordinals":{"columns":{"name":{"type":"string"},"number":{"type":"integer"}}}}} + [[{"name":"ordinals","tables":{"ordinals":{"columns":{"name":{"type":"string"},"number":{"type":"integer"}}}},"version":"5.1.3"} {"_comment":"add row for zero 0","_date":0,"ordinals":{"<0>":{"name":"zero"}}} {"_comment":"delete row for 0","_date":0,"ordinals":{"<0>":null}} {"_comment":"add back row for zero 0","_date":0,"ordinals":{"<1>":{"name":"zero"}}} @@ -270,3 +270,21 @@ _uuid name number <5> "" 5 @&t@ ]) AT_CLEANUP + +AT_SETUP([ovsdb-tool schema-version]) +AT_KEYWORDS([ovsdb file positive]) +AT_DATA([schema], [ORDINAL_SCHEMA +]) +AT_CHECK([ovsdb-tool schema-version schema], [0], [5.1.3 +]) +AT_CLEANUP + +AT_SETUP([ovsdb-tool db-version]) +AT_KEYWORDS([ovsdb file positive]) +AT_DATA([schema], [ORDINAL_SCHEMA +]) +touch .db.~lock~ +AT_CHECK([ovsdb-tool create db schema], [0], [], [ignore]) +AT_CHECK([ovsdb-tool db-version db], [0], [5.1.3 +]) +AT_CLEANUP diff --git a/vswitchd/automake.mk b/vswitchd/automake.mk index 4c3c07622..abcf76280 100644 --- a/vswitchd/automake.mk +++ b/vswitchd/automake.mk @@ -92,3 +92,15 @@ vswitchd/ovs-vswitchd.conf.db.5: \ $(srcdir)/vswitchd/vswitch.ovsschema \ $(srcdir)/vswitchd/vswitch.xml > $@.tmp mv $@.tmp $@ + +# Version checking for vswitch.ovsschema. +ALL_LOCAL += vswitchd/vswitch.ovsschema.stamp +vswitchd/vswitch.ovsschema.stamp: vswitchd/vswitch.ovsschema + @sum=`sed '/cksum/d' $? | cksum`; \ + expected=`sed -n 's/.*"cksum": "\(.*\)".*/\1/p' $?`; \ + if test "X$$sum" = "X$$expected"; then \ + touch $@; \ + else \ + ln=`sed -n '/"cksum":/=' $?`; \ + echo "$?:$$ln: checksum \"$$sum\" does not match (you should probably update the version number and fix the checksum)"; \ + fi diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 04b691a53..a1917ee5c 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,4 +1,6 @@ {"name": "Open_vSwitch", + "version": "1.0.0", + "cksum": "514853437 13985", "tables": { "Open_vSwitch": { "columns": { @@ -34,6 +36,9 @@ "ovs_version": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, + "db_version": { + "type": {"key": {"type": "string"}, + "min": 0, "max": 1}}, "system_type": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 9f079e869..b3f00752a 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -210,6 +210,26 @@ also included, e.g. 1.1.0pre2+build4948. + +

+ The database schema version number in the form + major.minor.tweak, + e.g. 1.2.3. Whenever the database schema is changed in + a non-backward compatible way (e.g. deleting a column or a table), + major is incremented. When the database schema is changed + in a backward compatible way (e.g. adding a new column), + minor is incremented. When the database schema is changed + cosmetically (e.g. reindenting its syntax), tweak is + incremented. +

+ +

+ The schema version is part of the database schema, so it can also be + retrieved by fetching the schema using the Open vSwitch database + protocol. +

+
+

An identifier for the type of system on top of which Open vSwitch diff --git a/xenserver/etc_init.d_openvswitch b/xenserver/etc_init.d_openvswitch index 0a2fc780b..9d7ad2d80 100755 --- a/xenserver/etc_init.d_openvswitch +++ b/xenserver/etc_init.d_openvswitch @@ -325,6 +325,7 @@ function start { # Allow GRE traffic. iptables -I INPUT -p gre -j ACCEPT + schemaver=`$ovsdb_tool schema-version "$VSWITCHD_OVSDB_SCHEMA"` if [ ! -e "$OVSDB_SERVER_DB" ]; then warning "$OVSDB_SERVER_DB does not exist" install -d -m 755 -o root -g root `dirname $OVSDB_SERVER_DB` @@ -332,12 +333,20 @@ function start { action "Creating empty database $OVSDB_SERVER_DB" true $ovsdb_tool -vANY:console:emer create "$OVSDB_SERVER_DB" "$VSWITCHD_OVSDB_SCHEMA" else + # If schema version changed, then back up the old version. + oldver=`$ovsdb_tool db-version "$OVSDB_SERVER_DB"` + if test "X$oldver" != "X$schemaver"; then + backup=$OVSDB_SERVER_DB.backup$oldver + action "Backing up $OVSDB_SERVER_DB in $backup before converting from schema version \"$oldver\" to \"$schemaver\"" true + cp "$OVSDB_SERVER_DB" "$backup" + fi + # Upgrade or downgrade schema and compact database. $ovsdb_tool -vANY:console:emer convert "$OVSDB_SERVER_DB" "$VSWITCHD_OVSDB_SCHEMA" fi start_ovsdb_server - $vsctl --no-wait --timeout=5 init + $vsctl --no-wait --timeout=5 init -- set Open_vSwitch . db-version="$schemaver" if [ ! -e /var/run/openvswitch.booted ]; then touch /var/run/openvswitch.booted for bridge in $($vsctl list-br); do -- 2.43.0