On 5/1/21 2:55 AM, Ilya Maximets wrote: > New flag for ovsdb table schema 'copyForReplication'. It's needed to > enable replication of a _Server database in later commits. > > With this option ovsdb-server will create a new _synced_<table-name> > table where it will store data received from the replication source > while keeping the original table for data of the local server. > This way ovsdb-server will be able to keep state of local databases > while replicating state of databases from the active server. > > Signed-off-by: Ilya Maximets <[email protected]> > ---
One tiny nit, otherwise: Acked-by: Dumitru Ceara <[email protected]> Regards, Dumitru > Documentation/ref/ovsdb-server.7.rst | 7 +++++++ > ovsdb/ovsdb-doc | 3 ++- > ovsdb/ovsdb.c | 19 ++++++++++++++++++- > ovsdb/table.c | 20 ++++++++++++++++---- > ovsdb/table.h | 4 +++- > python/ovs/db/schema.py | 20 +++++++++++++++++--- > 6 files changed, 63 insertions(+), 10 deletions(-) > > diff --git a/Documentation/ref/ovsdb-server.7.rst > b/Documentation/ref/ovsdb-server.7.rst > index 04414350a..717f62d81 100644 > --- a/Documentation/ref/ovsdb-server.7.rst > +++ b/Documentation/ref/ovsdb-server.7.rst > @@ -104,6 +104,13 @@ configuration and the following columns: > The set of columns and column:key pairs for which authorized update and > mutate operations should be permitted. > > +Since version 2.16, database table could be copied for replication purposes > +by setting ``copyForReplication`` flag to ``true``. For each table marked > +with this flag, ``ovsdb-server`` will create one more table with the same > +name and ``_synced_`` prefix (e.g., ``_synced_<table-name>``). Server in a > +backup role will keep its own content in the original table and will put > +data, received from the active server, to this special table. > + > 4 Wire Protocol > --------------- > > diff --git a/ovsdb/ovsdb-doc b/ovsdb/ovsdb-doc > index 10d0c0c13..5513783c1 100755 > --- a/ovsdb/ovsdb-doc > +++ b/ovsdb/ovsdb-doc > @@ -213,7 +213,8 @@ def docsToNroff(schemaFile, xmlFile, erFile, > version=None): > introNodes += [dbNode] > > documented_tables = set((name for (name, title) in summary)) > - schema_tables = set(schema.tables.keys()) > + schema_tables = set([name for name in schema.tables.keys() > + if not name.startswith("_")]) > undocumented_tables = schema_tables - documented_tables > for table in undocumented_tables: > raise error.Error("undocumented table %s" % table) > diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c > index 9042658fa..f662a0238 100644 > --- a/ovsdb/ovsdb.c > +++ b/ovsdb/ovsdb.c > @@ -238,6 +238,21 @@ ovsdb_schema_from_json(const struct json *json, struct > ovsdb_schema **schemap) > } > > shash_add(&schema->tables, table->name, table); > + > + if (table->copy_for_replication) { > + /* Need to create a copy of the table for the case it will be > + * synced from another server. */ > + struct ovsdb_table_schema *synced_table; > + > + synced_table = ovsdb_table_schema_clone(table); > + free(synced_table->name); > + synced_table->name = xasprintf("_synced_%s", node->name); > + /* Clearing 'copy' flag to avoid accidental further copying. */ > + synced_table->copy_for_replication = false; > + > + shash_add(&schema->tables, synced_table->name, synced_table); > + } > + > } > > /* "isRoot" was not part of the original schema definition. Before it > was > @@ -308,8 +323,10 @@ ovsdb_schema_to_json(const struct ovsdb_schema *schema) > > SHASH_FOR_EACH (node, &schema->tables) { > struct ovsdb_table_schema *table = node->data; > - json_object_put(tables, table->name, > + if (node->name[0] != '_') { > + json_object_put(tables, table->name, > ovsdb_table_schema_to_json(table, default_is_root)); Nit: indentation. > + } > } > json_object_put(json, "tables", tables); > > diff --git a/ovsdb/table.c b/ovsdb/table.c > index 6cd2d886d..b46946072 100644 > --- a/ovsdb/table.c > +++ b/ovsdb/table.c > @@ -36,7 +36,8 @@ add_column(struct ovsdb_table_schema *ts, struct > ovsdb_column *column) > > struct ovsdb_table_schema * > ovsdb_table_schema_create(const char *name, bool mutable, > - unsigned int max_rows, bool is_root) > + unsigned int max_rows, bool is_root, > + bool copy_for_replication) > { > struct ovsdb_column *uuid, *version; > struct ovsdb_table_schema *ts; > @@ -47,6 +48,7 @@ ovsdb_table_schema_create(const char *name, bool mutable, > shash_init(&ts->columns); > ts->max_rows = max_rows; > ts->is_root = is_root; > + ts->copy_for_replication = copy_for_replication; > > uuid = ovsdb_column_create("_uuid", false, true, &ovsdb_type_uuid); > add_column(ts, uuid); > @@ -70,7 +72,8 @@ ovsdb_table_schema_clone(const struct ovsdb_table_schema > *old) > size_t i; > > new = ovsdb_table_schema_create(old->name, old->mutable, > - old->max_rows, old->is_root); > + old->max_rows, old->is_root, > + old->copy_for_replication); > SHASH_FOR_EACH (node, &old->columns) { > const struct ovsdb_column *column = node->data; > > @@ -126,7 +129,8 @@ ovsdb_table_schema_from_json(const struct json *json, > const char *name, > struct ovsdb_table_schema **tsp) > { > struct ovsdb_table_schema *ts; > - const struct json *columns, *mutable, *max_rows, *is_root, *indexes; > + const struct json *columns, *mutable, *max_rows; > + const struct json *is_root, *indexes, *copy_for_replication; > struct shash_node *node; > struct ovsdb_parser parser; > struct ovsdb_error *error; > @@ -141,6 +145,8 @@ ovsdb_table_schema_from_json(const struct json *json, > const char *name, > max_rows = ovsdb_parser_member(&parser, "maxRows", > OP_INTEGER | OP_OPTIONAL); > is_root = ovsdb_parser_member(&parser, "isRoot", OP_BOOLEAN | > OP_OPTIONAL); > + copy_for_replication = ovsdb_parser_member(&parser, "copyForReplication", > + OP_BOOLEAN | OP_OPTIONAL); > indexes = ovsdb_parser_member(&parser, "indexes", OP_ARRAY | > OP_OPTIONAL); > error = ovsdb_parser_finish(&parser); > if (error) { > @@ -165,7 +171,10 @@ ovsdb_table_schema_from_json(const struct json *json, > const char *name, > ts = ovsdb_table_schema_create(name, > mutable ? json_boolean(mutable) : true, > MIN(n_max_rows, UINT_MAX), > - is_root ? json_boolean(is_root) : false); > + is_root ? json_boolean(is_root) : false, > + copy_for_replication > + ? json_boolean(copy_for_replication) > + : false); > SHASH_FOR_EACH (node, json_object(columns)) { > struct ovsdb_column *column; > > @@ -249,6 +258,9 @@ ovsdb_table_schema_to_json(const struct > ovsdb_table_schema *ts, > if (default_is_root != ts->is_root) { > json_object_put(json, "isRoot", json_boolean_create(ts->is_root)); > } > + if (ts->copy_for_replication) { > + json_object_put(json, "copyForReplication", > json_boolean_create(true)); > + } > > columns = json_object_create(); > > diff --git a/ovsdb/table.h b/ovsdb/table.h > index 69dd649df..afd56f7a6 100644 > --- a/ovsdb/table.h > +++ b/ovsdb/table.h > @@ -29,6 +29,7 @@ struct ovsdb_table_schema { > char *name; > bool mutable; > bool is_root; /* Part of garbage collection root set? */ > + bool copy_for_replication; /* '_synced_' copy of the table needed? */ > unsigned int max_rows; /* Maximum number of rows. */ > struct shash columns; /* Contains "struct ovsdb_column *"s. */ > struct ovsdb_column_set *indexes; > @@ -36,7 +37,8 @@ struct ovsdb_table_schema { > }; > > struct ovsdb_table_schema *ovsdb_table_schema_create( > - const char *name, bool mutable, unsigned int max_rows, bool is_root); > + const char *name, bool mutable, unsigned int max_rows, > + bool is_root, bool copy_for_replication); > struct ovsdb_table_schema *ovsdb_table_schema_clone( > const struct ovsdb_table_schema *); > void ovsdb_table_schema_destroy(struct ovsdb_table_schema *); > diff --git a/python/ovs/db/schema.py b/python/ovs/db/schema.py > index 3ba844ae5..e58e81080 100644 > --- a/python/ovs/db/schema.py > +++ b/python/ovs/db/schema.py > @@ -80,6 +80,13 @@ class DbSchema(object): > _check_id(tableName, json) > tables[tableName] = TableSchema.from_json(tableJson, tableName, > allow_extensions) > + if tables[tableName].copy_for_replication: > + synced_table_name = "_synced_" + tableName > + synced_table = TableSchema.from_json(tableJson, > + synced_table_name, > + allow_extensions) > + synced_table.copy_for_replication = False > + tables[synced_table_name] = synced_table > > return DbSchema(name, version, tables) > > @@ -92,7 +99,8 @@ class DbSchema(object): > > tables = {} > for table in self.tables.values(): > - tables[table.name] = table.to_json(default_is_root) > + if not table.name.startswith("_"): > + tables[table.name] = table.to_json(default_is_root) > json = {"name": self.name, "tables": tables} > if self.version: > json["version"] = self.version > @@ -172,7 +180,8 @@ def column_set_from_json(json, columns): > > class TableSchema(object): > def __init__(self, name, columns, mutable=True, max_rows=sys.maxsize, > - is_root=True, indexes=[], extensions={}): > + is_root=True, indexes=[], extensions={}, > + copy_for_replication=False): > self.name = name > self.columns = columns > self.mutable = mutable > @@ -180,6 +189,7 @@ class TableSchema(object): > self.is_root = is_root > self.indexes = indexes > self.extensions = extensions > + self.copy_for_replication = copy_for_replication > > @staticmethod > def from_json(json, name, allow_extensions=False): > @@ -188,6 +198,8 @@ class TableSchema(object): > mutable = parser.get_optional("mutable", [bool], True) > max_rows = parser.get_optional("maxRows", [int]) > is_root = parser.get_optional("isRoot", [bool], False) > + copy_for_replication = parser.get_optional("copyForReplication", > + [bool], False) > indexes_json = parser.get_optional("indexes", [list], []) > if allow_extensions: > extensions = parser.get_optional("extensions", [dict], {}) > @@ -224,7 +236,7 @@ class TableSchema(object): > indexes.append(index) > > return TableSchema(name, columns, mutable, max_rows, is_root, > indexes, > - extensions) > + extensions, copy_for_replication) > > def to_json(self, default_is_root=False): > """Returns this table schema serialized into JSON. > @@ -243,6 +255,8 @@ class TableSchema(object): > json["mutable"] = False > if default_is_root != self.is_root: > json["isRoot"] = self.is_root > + if self.copy_for_replication: > + json["copyForReplication"] = True > > json["columns"] = columns = {} > for column in self.columns.values(): > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
