mirror of
https://github.com/openvswitch/ovs
synced 2025-08-30 22:05:19 +00:00
ovsdb: Implement garbage collection.
This commit is contained in:
12
debian/openvswitch-switch.init
vendored
12
debian/openvswitch-switch.init
vendored
@@ -232,6 +232,18 @@ case "$1" in
|
||||
cksum=`ovsdb-tool db-cksum "$conf_file" | awk '{print $1}'`
|
||||
cp "$conf_file" "$conf_file.backup$version-$cksum"
|
||||
|
||||
# Compact database. This is important if the old schema did not
|
||||
# enable garbage collection (i.e. if it did not have any tables
|
||||
# with "isRoot": true) but the new schema does. In that situation
|
||||
# the old database may contain a transaction that creates a record
|
||||
# followed by a transaction that creates the first use of the
|
||||
# record. Replaying that series of transactions against the new
|
||||
# database schema (as "convert" does) would cause the record to be
|
||||
# dropped by the first transaction, then the second transaction
|
||||
# would cause a referential integrity failure (for a strong
|
||||
# reference).
|
||||
ovsdb-tool -vANY:console:emer compact $conf_file
|
||||
|
||||
# Upgrade or downgrade schema and compact database.
|
||||
ovsdb-tool -vANY:console:emer convert $conf_file $schema_file
|
||||
fi
|
||||
|
@@ -285,9 +285,28 @@ parse_json_pair(const struct json *json,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ovsdb_symbol_referenced(struct ovsdb_symbol *symbol,
|
||||
const struct ovsdb_base_type *base)
|
||||
{
|
||||
assert(base->type == OVSDB_TYPE_UUID);
|
||||
|
||||
if (base->u.uuid.refTableName) {
|
||||
switch (base->u.uuid.refType) {
|
||||
case OVSDB_REF_STRONG:
|
||||
symbol->strong_ref = true;
|
||||
break;
|
||||
case OVSDB_REF_WEAK:
|
||||
symbol->weak_ref = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json,
|
||||
struct ovsdb_symbol_table *symtab)
|
||||
struct ovsdb_symbol_table *symtab,
|
||||
const struct ovsdb_base_type *base)
|
||||
{
|
||||
struct ovsdb_error *error0;
|
||||
const struct json *value;
|
||||
@@ -304,14 +323,17 @@ ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json,
|
||||
|
||||
error1 = unwrap_json(json, "named-uuid", JSON_STRING, &value);
|
||||
if (!error1) {
|
||||
const char *name = json_string(value);
|
||||
struct ovsdb_symbol *symbol;
|
||||
|
||||
ovsdb_error_destroy(error0);
|
||||
*uuid = ovsdb_symbol_table_insert(symtab, name)->uuid;
|
||||
if (!ovsdb_parser_is_id(json_string(value))) {
|
||||
return ovsdb_syntax_error(json, NULL, "named-uuid string is "
|
||||
"not a valid <id>");
|
||||
}
|
||||
|
||||
symbol = ovsdb_symbol_table_insert(symtab, json_string(value));
|
||||
*uuid = symbol->uuid;
|
||||
ovsdb_symbol_referenced(symbol, base);
|
||||
return NULL;
|
||||
}
|
||||
ovsdb_error_destroy(error1);
|
||||
@@ -321,10 +343,13 @@ ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json,
|
||||
}
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
ovsdb_atom_from_json__(union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
||||
ovsdb_atom_from_json__(union ovsdb_atom *atom,
|
||||
const struct ovsdb_base_type *base,
|
||||
const struct json *json,
|
||||
struct ovsdb_symbol_table *symtab)
|
||||
{
|
||||
enum ovsdb_atomic_type type = base->type;
|
||||
|
||||
switch (type) {
|
||||
case OVSDB_TYPE_VOID:
|
||||
NOT_REACHED();
|
||||
@@ -364,7 +389,7 @@ ovsdb_atom_from_json__(union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
||||
break;
|
||||
|
||||
case OVSDB_TYPE_UUID:
|
||||
return ovsdb_atom_parse_uuid(&atom->uuid, json, symtab);
|
||||
return ovsdb_atom_parse_uuid(&atom->uuid, json, symtab, base);
|
||||
|
||||
case OVSDB_N_TYPES:
|
||||
default:
|
||||
@@ -384,7 +409,9 @@ ovsdb_atom_from_json__(union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
||||
*
|
||||
* If 'symtab' is nonnull, then named UUIDs in 'symtab' are accepted. Refer to
|
||||
* ovsdb/SPECS for information about this, and for the syntax that this
|
||||
* function accepts. */
|
||||
* function accepts. If 'base' is a reference and a symbol is parsed, then the
|
||||
* symbol's 'strong_ref' or 'weak_ref' member is set to true, as
|
||||
* appropriate. */
|
||||
struct ovsdb_error *
|
||||
ovsdb_atom_from_json(union ovsdb_atom *atom,
|
||||
const struct ovsdb_base_type *base,
|
||||
@@ -393,7 +420,7 @@ ovsdb_atom_from_json(union ovsdb_atom *atom,
|
||||
{
|
||||
struct ovsdb_error *error;
|
||||
|
||||
error = ovsdb_atom_from_json__(atom, base->type, json, symtab);
|
||||
error = ovsdb_atom_from_json__(atom, base, json, symtab);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -440,9 +467,12 @@ ovsdb_atom_to_json(const union ovsdb_atom *atom, enum ovsdb_atomic_type type)
|
||||
}
|
||||
|
||||
static char *
|
||||
ovsdb_atom_from_string__(union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
||||
const char *s, struct ovsdb_symbol_table *symtab)
|
||||
ovsdb_atom_from_string__(union ovsdb_atom *atom,
|
||||
const struct ovsdb_base_type *base, const char *s,
|
||||
struct ovsdb_symbol_table *symtab)
|
||||
{
|
||||
enum ovsdb_atomic_type type = base->type;
|
||||
|
||||
switch (type) {
|
||||
case OVSDB_TYPE_VOID:
|
||||
NOT_REACHED();
|
||||
@@ -503,7 +533,9 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
||||
|
||||
case OVSDB_TYPE_UUID:
|
||||
if (*s == '@') {
|
||||
atom->uuid = ovsdb_symbol_table_insert(symtab, s)->uuid;
|
||||
struct ovsdb_symbol *symbol = ovsdb_symbol_table_insert(symtab, s);
|
||||
atom->uuid = symbol->uuid;
|
||||
ovsdb_symbol_referenced(symbol, base);
|
||||
} else if (!uuid_from_string(&atom->uuid, s)) {
|
||||
return xasprintf("\"%s\" is not a valid UUID", s);
|
||||
}
|
||||
@@ -535,7 +567,9 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom, enum ovsdb_atomic_type type,
|
||||
* then an identifier beginning with '@' is also acceptable. If the
|
||||
* named identifier is already in 'symtab', then the associated UUID is
|
||||
* used; otherwise, a new, random UUID is used and added to the symbol
|
||||
* table.
|
||||
* table. If 'base' is a reference and a symbol is parsed, then the
|
||||
* symbol's 'strong_ref' or 'weak_ref' member is set to true, as
|
||||
* appropriate.
|
||||
*
|
||||
* Returns a null pointer if successful, otherwise an error message describing
|
||||
* the problem. On failure, the contents of 'atom' are indeterminate. The
|
||||
@@ -549,7 +583,7 @@ ovsdb_atom_from_string(union ovsdb_atom *atom,
|
||||
struct ovsdb_error *error;
|
||||
char *msg;
|
||||
|
||||
msg = ovsdb_atom_from_string__(atom, base->type, s, symtab);
|
||||
msg = ovsdb_atom_from_string__(atom, base, s, symtab);
|
||||
if (msg) {
|
||||
return msg;
|
||||
}
|
||||
@@ -1829,6 +1863,8 @@ ovsdb_symbol_table_put(struct ovsdb_symbol_table *symtab, const char *name,
|
||||
symbol = xmalloc(sizeof *symbol);
|
||||
symbol->uuid = *uuid;
|
||||
symbol->created = created;
|
||||
symbol->strong_ref = false;
|
||||
symbol->weak_ref = false;
|
||||
shash_add(&symtab->sh, name, symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
@@ -236,6 +236,8 @@ struct ovsdb_symbol_table {
|
||||
struct ovsdb_symbol {
|
||||
struct uuid uuid; /* The UUID that the symbol represents. */
|
||||
bool created; /* Already used to create row? */
|
||||
bool strong_ref; /* Parsed a strong reference to this row? */
|
||||
bool weak_ref; /* Parsed a weak reference to this row? */
|
||||
};
|
||||
|
||||
struct ovsdb_symbol_table *ovsdb_symbol_table_create(void);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2009, 2010 Nicira Networks.
|
||||
/* Copyright (c) 2009, 2010, 2011 Nicira Networks.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,6 +47,7 @@ struct ovsdb_idl_column {
|
||||
|
||||
struct ovsdb_idl_table_class {
|
||||
char *name;
|
||||
bool is_root;
|
||||
const struct ovsdb_idl_column *columns;
|
||||
size_t n_columns;
|
||||
size_t allocation_size;
|
||||
|
19
ovsdb/SPECS
19
ovsdb/SPECS
@@ -131,6 +131,7 @@ is represented by <database-schema>, as described below.
|
||||
|
||||
"columns": {<id>: <column-schema>, ...} required
|
||||
"maxRows": <integer> optional
|
||||
"isRoot": <boolean> optional
|
||||
|
||||
The value of "columns" is a JSON object whose names are column
|
||||
names and whose values are <column-schema>s.
|
||||
@@ -152,12 +153,28 @@ is represented by <database-schema>, as described below.
|
||||
the database process is stopped and then started again, each
|
||||
"_version" also changes to a new random value.
|
||||
|
||||
If "isRoot" is omitted or specified as false, then any given row
|
||||
in the table may exist only when there is at least one reference
|
||||
to it, with refType "strong", from a different row (in the same
|
||||
table or a different table). This is a "deferred" action:
|
||||
unreferenced rows in the table are deleted just before transaction
|
||||
commit. If "isRoot" is specified as true, then rows in the table
|
||||
exist independent of any references (they can be thought of as
|
||||
part of the "root set" in a garbage collector).
|
||||
|
||||
For compatibility with schemas created before "isRoot" was
|
||||
introduced, if "isRoot" is omitted or false in every
|
||||
<table-schema> in a given <database-schema>, then every table is
|
||||
part of the root set.
|
||||
|
||||
If "maxRows" is specified, as a positive integer, it limits the
|
||||
maximum number of rows that may be present in the table. This is
|
||||
a "deferred" constraint, enforced only at transaction commit time
|
||||
(see the "transact" request below). If "maxRows" is not
|
||||
specified, the size of the table is limited only by the resources
|
||||
available to the database server.
|
||||
available to the database server. "maxRows" constraints are
|
||||
enforced after unreferenced rows are deleted from tables with a
|
||||
false "isRoot".
|
||||
|
||||
<column-schema>
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
# Copyright (c) 2009, 2010 Nicira Networks
|
||||
# Copyright (c) 2009, 2010, 2011 Nicira Networks
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,14 @@ while (<>) {
|
||||
$y *= $scale;
|
||||
$width *= $scale;
|
||||
$height *= $scale;
|
||||
print "linethick = ", ($style eq 'bold' ? 0.5 : 1.0), ";\n";
|
||||
print "box at $x,$y wid $width height $height \"$name\"\n";
|
||||
if ($style eq 'bold') {
|
||||
my $inset = 2.0 / 72.0;
|
||||
$width -= $inset * 2;
|
||||
$height -= $inset * 2;
|
||||
print "box at $x,$y wid $width height $height\n";
|
||||
}
|
||||
} elsif (/edge/) {
|
||||
my (undef, $tail, $head, $n, $rest) = split(' ', $_, 5);
|
||||
my @xy;
|
||||
@@ -51,6 +58,8 @@ while (<>) {
|
||||
}
|
||||
my ($style, $color) = split(' ', $rest);
|
||||
|
||||
print "linethick = ", ($style eq 'dotted' ? 0.5 : 1), ";\n";
|
||||
|
||||
print "spline -> from $xy[0][0],$xy[0][1]";
|
||||
for (my ($i) = 0; $i <= $#xy; $i++) {
|
||||
print " to $xy[$i][0],$xy[$i][1]";
|
||||
|
@@ -290,9 +290,11 @@ Table Purpose
|
||||
.SH "TABLE RELATIONSHIPS"
|
||||
.PP
|
||||
The following diagram shows the relationship among tables in the
|
||||
database. Each node represents a table. Each edge leads from the
|
||||
database. Each node represents a table. Tables that are part of the
|
||||
``root set'' are shown with double borders. Each edge leads from the
|
||||
table that contains it and points to the table that its value
|
||||
represents. Edges are labeled with their column names.
|
||||
represents. Edges are labeled with their column names. Thick lines
|
||||
represent strong references; thin lines represent weak references.
|
||||
.RS -1in
|
||||
"""
|
||||
erStream = open(erFile, "r")
|
||||
|
@@ -16,6 +16,7 @@ def printEdge(tableName, baseType, label):
|
||||
options['label'] = '"%s"' % label
|
||||
if baseType.ref_type == 'weak':
|
||||
options['constraint'] = 'false'
|
||||
options['style'] = 'dotted'
|
||||
print "\t%s -> %s [%s];" % (
|
||||
tableName,
|
||||
baseType.ref_table,
|
||||
@@ -25,12 +26,17 @@ def schemaToDot(schemaFile):
|
||||
schema = ovs.db.schema.DbSchema.from_json(ovs.json.from_file(schemaFile))
|
||||
|
||||
print "digraph %s {" % schema.name
|
||||
print '\tsize="6.5,4";'
|
||||
print '\tmargin="0";'
|
||||
print "\tnode [shape=box];"
|
||||
print "\tedge [dir=none, arrowhead=none, arrowtail=none];"
|
||||
for tableName, table in schema.tables.iteritems():
|
||||
print '\tsize="6.5,4";'
|
||||
print '\tmargin="0";'
|
||||
print "\tnode [shape=box];"
|
||||
print "\tedge [dir=none, arrowhead=none, arrowtail=none];"
|
||||
print "\t%s;" % tableName
|
||||
options = {}
|
||||
if table.is_root:
|
||||
options['style'] = 'bold'
|
||||
print "\t%s [%s];" % (
|
||||
tableName,
|
||||
', '.join(['%s=%s' % (k,v) for k,v in options.items()]))
|
||||
for columnName, column in table.columns.iteritems():
|
||||
if column.type.value:
|
||||
printEdge(tableName, column.type.key, "%s key" % columnName)
|
||||
|
@@ -487,7 +487,11 @@ static void\n%s_columns_init(void)
|
||||
print "struct ovsdb_idl_table_class %stable_classes[%sN_TABLES] = {" % (prefix, prefix.upper())
|
||||
for tableName, table in sorted(schema.tables.iteritems()):
|
||||
structName = "%s%s" % (prefix, tableName.lower())
|
||||
print " {\"%s\"," % tableName
|
||||
if table.is_root:
|
||||
is_root = "true"
|
||||
else:
|
||||
is_root = "false"
|
||||
print " {\"%s\", %s," % (tableName, is_root)
|
||||
print " %s_columns, ARRAY_SIZE(%s_columns)," % (
|
||||
structName, structName)
|
||||
print " sizeof(struct %s)}," % structName
|
||||
|
@@ -127,6 +127,21 @@ is_valid_version(const char *s)
|
||||
return n != -1 && s[n] == '\0';
|
||||
}
|
||||
|
||||
/* Returns the number of tables in 'schema''s root set. */
|
||||
static size_t
|
||||
root_set_size(const struct ovsdb_schema *schema)
|
||||
{
|
||||
struct shash_node *node;
|
||||
size_t n_root;
|
||||
|
||||
SHASH_FOR_EACH (node, &schema->tables) {
|
||||
struct ovsdb_table_schema *table = node->data;
|
||||
|
||||
n_root += table->is_root;
|
||||
}
|
||||
return n_root;
|
||||
}
|
||||
|
||||
struct ovsdb_error *
|
||||
ovsdb_schema_from_json(struct json *json, struct ovsdb_schema **schemap)
|
||||
{
|
||||
@@ -205,6 +220,18 @@ ovsdb_schema_from_json(struct json *json, struct ovsdb_schema **schemap)
|
||||
}
|
||||
}
|
||||
|
||||
/* "isRoot" was not part of the original schema definition. Before it was
|
||||
* added, there was no support for garbage collection. So, for backward
|
||||
* compatibility, if the root set is empty then assume that every table is
|
||||
* in the root set. */
|
||||
if (root_set_size(schema) == 0) {
|
||||
SHASH_FOR_EACH (node, &schema->tables) {
|
||||
struct ovsdb_table_schema *table = node->data;
|
||||
|
||||
table->is_root = true;
|
||||
}
|
||||
}
|
||||
|
||||
*schemap = schema;
|
||||
return 0;
|
||||
}
|
||||
@@ -214,6 +241,7 @@ ovsdb_schema_to_json(const struct ovsdb_schema *schema)
|
||||
{
|
||||
struct json *json, *tables;
|
||||
struct shash_node *node;
|
||||
bool default_is_root;
|
||||
|
||||
json = json_object_create();
|
||||
json_object_put_string(json, "name", schema->name);
|
||||
@@ -224,12 +252,18 @@ ovsdb_schema_to_json(const struct ovsdb_schema *schema)
|
||||
json_object_put_string(json, "cksum", schema->cksum);
|
||||
}
|
||||
|
||||
/* "isRoot" was not part of the original schema definition. Before it was
|
||||
* added, there was no support for garbage collection. So, for backward
|
||||
* compatibility, if every table is in the root set then do not output
|
||||
* "isRoot" in table schemas. */
|
||||
default_is_root = root_set_size(schema) == shash_count(&schema->tables);
|
||||
|
||||
tables = json_object_create();
|
||||
|
||||
SHASH_FOR_EACH (node, &schema->tables) {
|
||||
struct ovsdb_table_schema *table = node->data;
|
||||
json_object_put(tables, table->name,
|
||||
ovsdb_table_schema_to_json(table));
|
||||
ovsdb_table_schema_to_json(table, default_is_root));
|
||||
}
|
||||
json_object_put(json, "tables", tables);
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2009, 2010 Nicira Networks
|
||||
/* Copyright (c) 2009, 2010, 2011 Nicira Networks
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,7 @@ 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)
|
||||
unsigned int max_rows, bool is_root)
|
||||
{
|
||||
struct ovsdb_column *uuid, *version;
|
||||
struct ovsdb_table_schema *ts;
|
||||
@@ -47,6 +47,7 @@ ovsdb_table_schema_create(const char *name, bool mutable,
|
||||
ts->mutable = mutable;
|
||||
shash_init(&ts->columns);
|
||||
ts->max_rows = max_rows;
|
||||
ts->is_root = is_root;
|
||||
|
||||
uuid = ovsdb_column_create("_uuid", false, true, &ovsdb_type_uuid);
|
||||
add_column(ts, uuid);
|
||||
@@ -65,7 +66,8 @@ ovsdb_table_schema_clone(const struct ovsdb_table_schema *old)
|
||||
struct ovsdb_table_schema *new;
|
||||
struct shash_node *node;
|
||||
|
||||
new = ovsdb_table_schema_create(old->name, old->mutable, old->max_rows);
|
||||
new = ovsdb_table_schema_create(old->name, old->mutable,
|
||||
old->max_rows, old->is_root);
|
||||
SHASH_FOR_EACH (node, &old->columns) {
|
||||
const struct ovsdb_column *column = node->data;
|
||||
|
||||
@@ -97,7 +99,7 @@ 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;
|
||||
const struct json *columns, *mutable, *max_rows, *is_root;
|
||||
struct shash_node *node;
|
||||
struct ovsdb_parser parser;
|
||||
struct ovsdb_error *error;
|
||||
@@ -111,6 +113,7 @@ ovsdb_table_schema_from_json(const struct json *json, const char *name,
|
||||
OP_TRUE | OP_FALSE | OP_OPTIONAL);
|
||||
max_rows = ovsdb_parser_member(&parser, "maxRows",
|
||||
OP_INTEGER | OP_OPTIONAL);
|
||||
is_root = ovsdb_parser_member(&parser, "isRoot", OP_BOOLEAN | OP_OPTIONAL);
|
||||
error = ovsdb_parser_finish(&parser);
|
||||
if (error) {
|
||||
return error;
|
||||
@@ -133,7 +136,8 @@ 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));
|
||||
MIN(n_max_rows, UINT_MAX),
|
||||
is_root ? json_boolean(is_root) : false);
|
||||
SHASH_FOR_EACH (node, json_object(columns)) {
|
||||
struct ovsdb_column *column;
|
||||
|
||||
@@ -156,8 +160,19 @@ ovsdb_table_schema_from_json(const struct json *json, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns table schema 'ts' serialized into JSON.
|
||||
*
|
||||
* The "isRoot" member is included in the JSON only if its value would differ
|
||||
* from 'default_is_root'. Ordinarily 'default_is_root' should be false,
|
||||
* because ordinarily a table would be not be part of the root set if its
|
||||
* "isRoot" member is omitted. However, garbage collection was not orginally
|
||||
* included in OVSDB, so in older schemas that do not include any "isRoot"
|
||||
* members, every table is implicitly part of the root set. To serialize such
|
||||
* a schema in a way that can be read by older OVSDB tools, specify
|
||||
* 'default_is_root' as true. */
|
||||
struct json *
|
||||
ovsdb_table_schema_to_json(const struct ovsdb_table_schema *ts)
|
||||
ovsdb_table_schema_to_json(const struct ovsdb_table_schema *ts,
|
||||
bool default_is_root)
|
||||
{
|
||||
struct json *json, *columns;
|
||||
struct shash_node *node;
|
||||
@@ -166,6 +181,9 @@ ovsdb_table_schema_to_json(const struct ovsdb_table_schema *ts)
|
||||
if (!ts->mutable) {
|
||||
json_object_put(json, "mutable", json_boolean_create(false));
|
||||
}
|
||||
if (default_is_root != ts->is_root) {
|
||||
json_object_put(json, "isRoot", json_boolean_create(ts->is_root));
|
||||
}
|
||||
|
||||
columns = json_object_create();
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2009, 2010 Nicira Networks
|
||||
/* Copyright (c) 2009, 2010, 2011 Nicira Networks
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,11 +30,11 @@ struct ovsdb_table_schema {
|
||||
bool mutable;
|
||||
struct shash columns; /* Contains "struct ovsdb_column *"s. */
|
||||
unsigned int max_rows; /* Maximum number of rows. */
|
||||
bool is_root; /* Part of garbage collection root set? */
|
||||
};
|
||||
|
||||
struct ovsdb_table_schema *ovsdb_table_schema_create(const char *name,
|
||||
bool mutable,
|
||||
unsigned int max_rows);
|
||||
struct ovsdb_table_schema *ovsdb_table_schema_create(
|
||||
const char *name, bool mutable, unsigned int max_rows, bool is_root);
|
||||
struct ovsdb_table_schema *ovsdb_table_schema_clone(
|
||||
const struct ovsdb_table_schema *);
|
||||
void ovsdb_table_schema_destroy(struct ovsdb_table_schema *);
|
||||
@@ -43,7 +43,8 @@ struct ovsdb_error *ovsdb_table_schema_from_json(const struct json *,
|
||||
const char *name,
|
||||
struct ovsdb_table_schema **)
|
||||
WARN_UNUSED_RESULT;
|
||||
struct json *ovsdb_table_schema_to_json(const struct ovsdb_table_schema *);
|
||||
struct json *ovsdb_table_schema_to_json(const struct ovsdb_table_schema *,
|
||||
bool default_is_root);
|
||||
|
||||
const struct ovsdb_column *ovsdb_table_schema_get_column(
|
||||
const struct ovsdb_table_schema *, const char *name);
|
||||
|
@@ -81,6 +81,8 @@ struct ovsdb_txn_row {
|
||||
unsigned long changed[]; /* Bits set to 1 for columns that changed. */
|
||||
};
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
delete_garbage_row(struct ovsdb_txn *txn, struct ovsdb_txn_row *r);
|
||||
static void ovsdb_txn_row_prefree(struct ovsdb_txn_row *);
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
for_each_txn_row(struct ovsdb_txn *txn,
|
||||
@@ -158,6 +160,20 @@ find_txn_row(const struct ovsdb_table *table, const struct uuid *uuid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ovsdb_txn_row *
|
||||
find_or_make_txn_row(struct ovsdb_txn *txn, const struct ovsdb_table *table,
|
||||
const struct uuid *uuid)
|
||||
{
|
||||
struct ovsdb_txn_row *txn_row = find_txn_row(table, uuid);
|
||||
if (!txn_row) {
|
||||
const struct ovsdb_row *row = ovsdb_table_get_row(table, uuid);
|
||||
if (row) {
|
||||
txn_row = ovsdb_txn_row_modify(txn, row)->txn_row;
|
||||
}
|
||||
}
|
||||
return txn_row;
|
||||
}
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
ovsdb_txn_adjust_atom_refs(struct ovsdb_txn *txn, const struct ovsdb_row *r,
|
||||
const struct ovsdb_column *c,
|
||||
@@ -175,24 +191,22 @@ ovsdb_txn_adjust_atom_refs(struct ovsdb_txn *txn, const struct ovsdb_row *r,
|
||||
table = base->u.uuid.refTable;
|
||||
for (i = 0; i < n; i++) {
|
||||
const struct uuid *uuid = &atoms[i].uuid;
|
||||
struct ovsdb_txn_row *txn_row = find_txn_row(table, uuid);
|
||||
struct ovsdb_txn_row *txn_row;
|
||||
|
||||
if (uuid_equals(uuid, ovsdb_row_get_uuid(r))) {
|
||||
/* Self-references don't count. */
|
||||
continue;
|
||||
}
|
||||
|
||||
txn_row = find_or_make_txn_row(txn, table, uuid);
|
||||
if (!txn_row) {
|
||||
const struct ovsdb_row *row = ovsdb_table_get_row(table, uuid);
|
||||
if (row) {
|
||||
txn_row = ovsdb_txn_row_modify(txn, row)->txn_row;
|
||||
} else {
|
||||
return ovsdb_error("referential integrity violation",
|
||||
"Table %s column %s row "UUID_FMT" "
|
||||
"references nonexistent row "UUID_FMT" in "
|
||||
"table %s.",
|
||||
r->table->schema->name, c->name,
|
||||
UUID_ARGS(ovsdb_row_get_uuid(r)),
|
||||
UUID_ARGS(uuid), table->schema->name);
|
||||
}
|
||||
return ovsdb_error("referential integrity violation",
|
||||
"Table %s column %s row "UUID_FMT" "
|
||||
"references nonexistent row "UUID_FMT" in "
|
||||
"table %s.",
|
||||
r->table->schema->name, c->name,
|
||||
UUID_ARGS(ovsdb_row_get_uuid(r)),
|
||||
UUID_ARGS(uuid), table->schema->name);
|
||||
}
|
||||
txn_row->n_refs += delta;
|
||||
}
|
||||
@@ -257,6 +271,92 @@ check_ref_count(struct ovsdb_txn *txn OVS_UNUSED, struct ovsdb_txn_row *r)
|
||||
}
|
||||
}
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
delete_row_refs(struct ovsdb_txn *txn, const struct ovsdb_row *row,
|
||||
const struct ovsdb_base_type *base,
|
||||
const union ovsdb_atom *atoms, unsigned int n)
|
||||
{
|
||||
const struct ovsdb_table *table;
|
||||
unsigned int i;
|
||||
|
||||
if (!ovsdb_base_type_is_strong_ref(base)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table = base->u.uuid.refTable;
|
||||
for (i = 0; i < n; i++) {
|
||||
const struct uuid *uuid = &atoms[i].uuid;
|
||||
struct ovsdb_txn_row *txn_row;
|
||||
|
||||
if (uuid_equals(uuid, ovsdb_row_get_uuid(row))) {
|
||||
/* Self-references don't count. */
|
||||
continue;
|
||||
}
|
||||
|
||||
txn_row = find_or_make_txn_row(txn, table, uuid);
|
||||
if (!txn_row) {
|
||||
return OVSDB_BUG("strong ref target missing");
|
||||
} else if (!txn_row->n_refs) {
|
||||
return OVSDB_BUG("strong ref target has zero n_refs");
|
||||
} else if (!txn_row->new) {
|
||||
return OVSDB_BUG("deleted strong ref target");
|
||||
}
|
||||
|
||||
if (--txn_row->n_refs == 0) {
|
||||
struct ovsdb_error *error = delete_garbage_row(txn, txn_row);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
delete_garbage_row(struct ovsdb_txn *txn, struct ovsdb_txn_row *txn_row)
|
||||
{
|
||||
struct shash_node *node;
|
||||
struct ovsdb_row *row;
|
||||
|
||||
if (txn_row->table->schema->is_root) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
row = txn_row->new;
|
||||
txn_row->new = NULL;
|
||||
hmap_remove(&txn_row->table->rows, &row->hmap_node);
|
||||
SHASH_FOR_EACH (node, &txn_row->table->schema->columns) {
|
||||
const struct ovsdb_column *column = node->data;
|
||||
const struct ovsdb_datum *field = &row->fields[column->index];
|
||||
struct ovsdb_error *error;
|
||||
|
||||
error = delete_row_refs(txn, row,
|
||||
&column->type.key, field->keys, field->n);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
error = delete_row_refs(txn, row,
|
||||
&column->type.value, field->values, field->n);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
ovsdb_row_destroy(row);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
collect_garbage(struct ovsdb_txn *txn, struct ovsdb_txn_row *txn_row)
|
||||
{
|
||||
if (txn_row->new && !txn_row->n_refs) {
|
||||
return delete_garbage_row(txn, txn_row);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ovsdb_error * WARN_UNUSED_RESULT
|
||||
update_ref_counts(struct ovsdb_txn *txn)
|
||||
{
|
||||
@@ -491,15 +591,22 @@ ovsdb_txn_commit(struct ovsdb_txn *txn, bool durable)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check maximum rows table constraints. */
|
||||
error = check_max_rows(txn);
|
||||
/* Update reference counts and check referential integrity. */
|
||||
error = update_ref_counts(txn);
|
||||
if (error) {
|
||||
ovsdb_txn_abort(txn);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Update reference counts and check referential integrity. */
|
||||
error = update_ref_counts(txn);
|
||||
/* Delete unreferenced, non-root rows. */
|
||||
error = for_each_txn_row(txn, collect_garbage);
|
||||
if (error) {
|
||||
ovsdb_txn_abort(txn);
|
||||
return OVSDB_WRAP_BUG("can't happen", error);
|
||||
}
|
||||
|
||||
/* Check maximum rows table constraints. */
|
||||
error = check_max_rows(txn);
|
||||
if (error) {
|
||||
ovsdb_txn_abort(txn);
|
||||
return error;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2009, 2010 Nicira Networks
|
||||
# Copyright (c) 2009, 2010, 2011 Nicira Networks
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -34,6 +34,22 @@ class DbSchema(object):
|
||||
self.__check_ref_table(column, column.type.key, "key")
|
||||
self.__check_ref_table(column, column.type.value, "value")
|
||||
|
||||
# "isRoot" was not part of the original schema definition. Before it
|
||||
# was added, there was no support for garbage collection. So, for
|
||||
# backward compatibility, if the root set is empty then assume that
|
||||
# every table is in the root set.
|
||||
if self.__root_set_size() == 0:
|
||||
for table in self.tables.itervalues():
|
||||
table.is_root = True
|
||||
|
||||
def __root_set_size(self):
|
||||
"""Returns the number of tables in the schema's root set."""
|
||||
n_root = 0
|
||||
for table in self.tables.itervalues():
|
||||
if table.is_root:
|
||||
n_root += 1
|
||||
return n_root
|
||||
|
||||
@staticmethod
|
||||
def from_json(json):
|
||||
parser = ovs.db.parser.Parser(json, "database schema")
|
||||
@@ -60,9 +76,15 @@ class DbSchema(object):
|
||||
return DbSchema(name, version, tables)
|
||||
|
||||
def to_json(self):
|
||||
# "isRoot" was not part of the original schema definition. Before it
|
||||
# was added, there was no support for garbage collection. So, for
|
||||
# backward compatibility, if every table is in the root set then do not
|
||||
# output "isRoot" in table schemas.
|
||||
default_is_root = self.__root_set_size() == len(self.tables)
|
||||
|
||||
tables = {}
|
||||
for table in self.tables.itervalues():
|
||||
tables[table.name] = table.to_json()
|
||||
tables[table.name] = table.to_json(default_is_root)
|
||||
json = {"name": self.name, "tables": tables}
|
||||
if self.version:
|
||||
json["version"] = self.version
|
||||
@@ -96,11 +118,13 @@ class IdlSchema(DbSchema):
|
||||
idlPrefix, idlHeader)
|
||||
|
||||
class TableSchema(object):
|
||||
def __init__(self, name, columns, mutable=True, max_rows=sys.maxint):
|
||||
def __init__(self, name, columns, mutable=True, max_rows=sys.maxint,
|
||||
is_root=True):
|
||||
self.name = name
|
||||
self.columns = columns
|
||||
self.mutable = mutable
|
||||
self.max_rows = max_rows
|
||||
self.max_rows = max_rows
|
||||
self.is_root = is_root
|
||||
|
||||
@staticmethod
|
||||
def from_json(json, name):
|
||||
@@ -108,6 +132,7 @@ class TableSchema(object):
|
||||
columnsJson = parser.get("columns", [dict])
|
||||
mutable = parser.get_optional("mutable", [bool], True)
|
||||
max_rows = parser.get_optional("maxRows", [int])
|
||||
is_root = parser.get_optional("isRoot", [bool], False)
|
||||
parser.finish()
|
||||
|
||||
if max_rows == None:
|
||||
@@ -128,12 +153,25 @@ class TableSchema(object):
|
||||
columns[columnName] = ColumnSchema.from_json(columnJson,
|
||||
columnName)
|
||||
|
||||
return TableSchema(name, columns, mutable, max_rows)
|
||||
return TableSchema(name, columns, mutable, max_rows, is_root)
|
||||
|
||||
def to_json(self):
|
||||
def to_json(self, default_is_root=False):
|
||||
"""Returns this table schema serialized into JSON.
|
||||
|
||||
The "isRoot" member is included in the JSON only if its value would
|
||||
differ from 'default_is_root'. Ordinarily 'default_is_root' should be
|
||||
false, because ordinarily a table would be not be part of the root set
|
||||
if its "isRoot" member is omitted. However, garbage collection was not
|
||||
orginally included in OVSDB, so in older schemas that do not include
|
||||
any "isRoot" members, every table is implicitly part of the root set.
|
||||
To serialize such a schema in a way that can be read by older OVSDB
|
||||
tools, specify 'default_is_root' as True.
|
||||
"""
|
||||
json = {}
|
||||
if not self.mutable:
|
||||
json["mutable"] = False
|
||||
if default_is_root != self.is_root:
|
||||
json["isRoot"] = self.is_root
|
||||
|
||||
json["columns"] = columns = {}
|
||||
for column in self.columns.itervalues():
|
||||
|
@@ -535,7 +535,9 @@ AT_BANNER([ovs-vsctl unit tests -- database commands])
|
||||
AT_SETUP([database commands -- positive checks])
|
||||
AT_KEYWORDS([ovs-vsctl])
|
||||
OVS_VSCTL_SETUP
|
||||
AT_CHECK([RUN_OVS_VSCTL([create b name=br0])],
|
||||
AT_CHECK(
|
||||
[RUN_OVS_VSCTL_TOGETHER([--id=@br0 create b name=br0],
|
||||
[set o . bridges=@br0])],
|
||||
[0], [stdout], [], [OVS_VSCTL_CLEANUP])
|
||||
cp stdout out1
|
||||
AT_CHECK([RUN_OVS_VSCTL([list b], [get b br0 _uuid])],
|
||||
@@ -543,6 +545,7 @@ AT_CHECK([RUN_OVS_VSCTL([list b], [get b br0 _uuid])],
|
||||
cp stdout out2
|
||||
AT_CHECK([perl $srcdir/uuidfilt.pl out1 out2], [0],
|
||||
[[<0>
|
||||
|
||||
_uuid : <0>
|
||||
controller : []
|
||||
datapath_id : []
|
||||
@@ -572,8 +575,10 @@ AT_CHECK(
|
||||
name : "br0"
|
||||
datapath_type : ""
|
||||
]], [ignore], [test ! -e pid || kill `cat pid`])
|
||||
AT_CHECK([RUN_OVS_VSCTL([create b name=br1 datapath_type="foo"],
|
||||
[create b name=br2 external-ids:bar=quux])],
|
||||
AT_CHECK([
|
||||
RUN_OVS_VSCTL_TOGETHER([--id=@br1 create b name=br1 datapath_type="foo"],
|
||||
[--id=@br2 create b name=br2 external-ids:bar=quux],
|
||||
[add o . bridges @br1 @br2])],
|
||||
[0], [stdout], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK(
|
||||
[RUN_OVS_VSCTL([--columns=name find b datapath_type!=foo])], [0], [stdout],
|
||||
@@ -608,7 +613,8 @@ AT_CHECK([RUN_OVS_VSCTL([clear br br0 external-ids -- get br br0 external_ids])]
|
||||
], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK([RUN_OVS_VSCTL_TOGETHER([destroy b br0],
|
||||
[destroy b br1],
|
||||
[destroy b br2])],
|
||||
[destroy b br2],
|
||||
[clear o . bridges])],
|
||||
[0], [stdout], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK([RUN_OVS_VSCTL([list b])],
|
||||
[0], [], [], [OVS_VSCTL_CLEANUP])
|
||||
@@ -618,19 +624,22 @@ AT_CLEANUP
|
||||
AT_SETUP([database commands -- negative checks])
|
||||
AT_KEYWORDS([ovs-vsctl])
|
||||
OVS_VSCTL_SETUP
|
||||
AT_CHECK([RUN_OVS_VSCTL([create b name=br0])],
|
||||
AT_CHECK([RUN_OVS_VSCTL([add-br br0])],
|
||||
[0], [ignore], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK([RUN_OVS_VSCTL([add-br br1])],
|
||||
[0], [ignore], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK([RUN_OVS_VSCTL([set-controller br1 tcp:127.0.0.1])],
|
||||
[0], [ignore], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK([RUN_OVS_VSCTL([create n targets='"1.2.3.4:567"'])],
|
||||
AT_CHECK([
|
||||
RUN_OVS_VSCTL_TOGETHER([--id=@n create n targets='"1.2.3.4:567"'],
|
||||
[set bridge br0 netflow=@n])],
|
||||
[0], [stdout], [], [OVS_VSCTL_CLEANUP])
|
||||
cp stdout netflow-uuid
|
||||
AT_CHECK([RUN_OVS_VSCTL([list n `cat netflow-uuid`])],
|
||||
[0], [stdout], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK([perl $srcdir/uuidfilt.pl netflow-uuid stdout], [0],
|
||||
[[<0>
|
||||
|
||||
_uuid : <0>
|
||||
active_timeout : 0
|
||||
add_id_to_interface : false
|
||||
@@ -806,13 +815,44 @@ name : "br0"
|
||||
OVS_VSCTL_CLEANUP
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([unreferenced record warnings])
|
||||
AT_KEYWORDS([ovs-vsctl])
|
||||
OVS_VSCTL_SETUP
|
||||
AT_CHECK(
|
||||
[ovs-vsctl -vPATTERN:console:'%c|%p|%m' --timeout=5 --no-wait -vreconnect:ANY:emer --db=unix:socket \
|
||||
-- create Bridge name=br0 | $srcdir/uuidfilt.pl],
|
||||
[0], [<0>
|
||||
], [vsctl|WARN|applying "create" command to table Bridge without --id option will have no effect
|
||||
], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK(
|
||||
[ovs-vsctl -vPATTERN:console:'%c|%p|%m' --timeout=5 --no-wait -vreconnect:ANY:emer --db=unix:socket \
|
||||
-- --id=@br0 create Bridge name=br0 | $srcdir/uuidfilt.pl],
|
||||
[0], [<0>
|
||||
], [vsctl|WARN|row id "@br0" was created but no reference to it was inserted, so it will not actually appear in the database
|
||||
], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK(
|
||||
[ovs-vsctl -vPATTERN:console:'%c|%p|%m' --timeout=5 --no-wait -vreconnect:ANY:emer --db=unix:socket \
|
||||
-- --id=@eth0_iface create Interface name=eth0 \
|
||||
-- --id=@eth0 create Port name=eth0 interfaces=@eth0_iface \
|
||||
-- --id=@m0 create Mirror name=m0 output_port=@eth0 \
|
||||
-- --id=@br0 create Bridge name=br0 mirrors=@m0 \
|
||||
-- set Open_vSwitch . bridges=@br0 | $srcdir/uuidfilt.pl],
|
||||
[0], [<0>
|
||||
<1>
|
||||
<2>
|
||||
<3>
|
||||
], [vsctl|WARN|row id "@eth0" was created but only a weak reference to it was inserted, so it will not actually appear in the database
|
||||
], [OVS_VSCTL_CLEANUP])
|
||||
OVS_VSCTL_CLEANUP
|
||||
AT_CLEANUP
|
||||
|
||||
dnl This test really shows a bug -- "create" followed by "list" in
|
||||
dnl the same execution shows the wrong UUID on the "list" command.
|
||||
dnl The bug is documented in ovs-vsctl.8.
|
||||
AT_SETUP([created row UUID is wrong in same execution])
|
||||
AT_KEYWORDS([ovs-vsctl])
|
||||
OVS_VSCTL_SETUP
|
||||
AT_CHECK([RUN_OVS_VSCTL([create Bridge name=br0 -- list b])],
|
||||
AT_CHECK([RUN_OVS_VSCTL([--id=@br0 create Bridge name=br0 -- add Open_vSwitch . bridges @br0 -- list b])],
|
||||
[0], [stdout], [], [OVS_VSCTL_CLEANUP])
|
||||
AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0],
|
||||
[[<0>
|
||||
|
@@ -57,6 +57,44 @@ m4_define([WEAK_SCHEMA],
|
||||
"refType": "weak"},
|
||||
"min": 0, "max": "unlimited"}}}}}}]])
|
||||
|
||||
m4_define([GC_SCHEMA],
|
||||
[[{"name": "gc",
|
||||
"tables": {
|
||||
"root": {
|
||||
"columns": {
|
||||
"a": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "a"},
|
||||
"min": 0, "max": "unlimited"}}},
|
||||
"isRoot": true},
|
||||
"a": {
|
||||
"columns": {
|
||||
"a": {"type": "integer"},
|
||||
"a2a": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "a"},
|
||||
"min": 0, "max": "unlimited"}},
|
||||
"a2b": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "b"},
|
||||
"min": 0, "max": "unlimited"}},
|
||||
"wa2a": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "a",
|
||||
"refType": "weak"},
|
||||
"min": 0, "max": "unlimited"}},
|
||||
"wa2b": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "b",
|
||||
"refType": "weak"},
|
||||
"min": 0, "max": "unlimited"}}}},
|
||||
"b": {
|
||||
"columns": {
|
||||
"b": {"type": "integer"},
|
||||
"b2a": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "a"},
|
||||
"min": 0, "max": "unlimited"}},
|
||||
"wb2a": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "a",
|
||||
"refType": "weak"},
|
||||
"min": 0, "max": "unlimited"}}},
|
||||
"isRoot": false}}}]])
|
||||
|
||||
# OVSDB_CHECK_EXECUTION(TITLE, SCHEMA, TRANSACTIONS, OUTPUT, [KEYWORDS])
|
||||
#
|
||||
# Runs "test-ovsdb execute" with the given SCHEMA and each of the
|
||||
@@ -760,6 +798,150 @@ OVSDB_CHECK_EXECUTION([weak references],
|
||||
[{"count":1}]
|
||||
[{"rows":[]}]
|
||||
[{"rows":[{"_uuid":["uuid","<3>"],"b":2,"b2a":["set",[]]},{"_uuid":["uuid","<4>"],"b":3,"b2a":["set",[]]}]}]
|
||||
]])
|
||||
|
||||
OVSDB_CHECK_EXECUTION([garbage collection],
|
||||
[GC_SCHEMA],
|
||||
[dnl Check that inserting a row without any references is a no-op.
|
||||
[[["gc",
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 0}}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"]}]]],
|
||||
dnl Check that inserting a chain of rows that reference each other
|
||||
dnl in turn is also a no-op.
|
||||
[[["gc",
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 0, "a2a": ["named-uuid", "row1"]},
|
||||
"uuid-name": "row0"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 1, "a2a": ["named-uuid", "row2"]},
|
||||
"uuid-name": "row1"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 2, "a2a": ["named-uuid", "row3"]},
|
||||
"uuid-name": "row2"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 3},
|
||||
"uuid-name": "row3"}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"]}]]],
|
||||
dnl Check that inserting a pair of rows that mutually reference each
|
||||
dnl other causes the rows to be retained.
|
||||
[[["gc",
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 4, "a2a": ["named-uuid", "row5"]},
|
||||
"uuid-name": "row4"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 5, "a2a": ["named-uuid", "row4"]},
|
||||
"uuid-name": "row5"}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"],
|
||||
"sort": ["a"]}]]],
|
||||
dnl Check that unreferencing one of the rows causes the other to be deleted.
|
||||
[[["gc",
|
||||
{"op": "update",
|
||||
"table": "a",
|
||||
"where": [["a", "==", 4]],
|
||||
"row": {"a2a": ["set", []]}}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"]}]]],
|
||||
dnl Check that inserting a pair of rows that mutually weak reference each
|
||||
dnl other is a no-op.
|
||||
[[["gc",
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 6, "wa2a": ["named-uuid", "row7"]},
|
||||
"uuid-name": "row6"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 7, "wa2a": ["named-uuid", "row6"]},
|
||||
"uuid-name": "row7"}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"]}]]],
|
||||
dnl Check that a circular chain of rows is retained.
|
||||
[[["gc",
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 8, "a2a": ["named-uuid", "row9"]},
|
||||
"uuid-name": "row8"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 9, "a2a": ["named-uuid", "row10"]},
|
||||
"uuid-name": "row9"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 10, "a2a": ["named-uuid", "row11"]},
|
||||
"uuid-name": "row10"},
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 11, "a2a": ["named-uuid", "row8"]},
|
||||
"uuid-name": "row11"}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"],
|
||||
"sort": ["a"]}]]],
|
||||
dnl Check that breaking the chain causes all of the rows to be deleted.
|
||||
[[["gc",
|
||||
{"op": "update",
|
||||
"table": "a",
|
||||
"where": [["a", "==", 9]],
|
||||
"row": {"a2a": ["set", []]}}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"]}]]],
|
||||
dnl Check that inserting a row only referenced by itself is a no-op.
|
||||
[[["gc",
|
||||
{"op": "insert",
|
||||
"table": "a",
|
||||
"row": {"a": 12, "a2a": ["named-uuid", "self"]},
|
||||
"uuid-name": "self"}]]],
|
||||
[[["gc",
|
||||
{"op": "select",
|
||||
"table": "a",
|
||||
"where": [],
|
||||
"columns": ["a"]}]]]],
|
||||
[[[{"uuid":["uuid","<0>"]}]
|
||||
[{"rows":[]}]
|
||||
[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]},{"uuid":["uuid","<4>"]}]
|
||||
[{"rows":[]}]
|
||||
[{"uuid":["uuid","<5>"]},{"uuid":["uuid","<6>"]}]
|
||||
[{"rows":[{"a":4},{"a":5}]}]
|
||||
[{"count":1}]
|
||||
[{"rows":[]}]
|
||||
[{"uuid":["uuid","<7>"]},{"uuid":["uuid","<8>"]}]
|
||||
[{"rows":[]}]
|
||||
[{"uuid":["uuid","<9>"]},{"uuid":["uuid","<10>"]},{"uuid":["uuid","<11>"]},{"uuid":["uuid","<12>"]}]
|
||||
[{"rows":[{"a":8},{"a":9},{"a":10},{"a":11}]}]
|
||||
[{"count":1}]
|
||||
[{"rows":[]}]
|
||||
[{"uuid":["uuid","<13>"]}]
|
||||
[{"rows":[]}]
|
||||
]])])
|
||||
|
||||
EXECUTION_EXAMPLES
|
||||
|
@@ -1,6 +1,6 @@
|
||||
AT_BANNER([OVSDB -- tables])
|
||||
|
||||
OVSDB_CHECK_POSITIVE_CPY([table with one column],
|
||||
OVSDB_CHECK_POSITIVE_CPY([non-root table with one column],
|
||||
[[parse-table mytable '{"columns": {"name": {"type": "string"}}}']],
|
||||
[[{"columns":{"name":{"type":"string"}}}]])
|
||||
|
||||
@@ -10,6 +10,22 @@ OVSDB_CHECK_POSITIVE_CPY([immutable table with one column],
|
||||
"mutable": false}']],
|
||||
[[{"columns":{"name":{"type":"string"}},"mutable":false}]])
|
||||
|
||||
OVSDB_CHECK_POSITIVE_CPY([root table with one column],
|
||||
[[parse-table mytable \
|
||||
'{"columns": {"name": {"type": "string"}},
|
||||
"isRoot": true}']],
|
||||
[[{"columns":{"name":{"type":"string"}},"isRoot":true}]])
|
||||
|
||||
OVSDB_CHECK_POSITIVE_CPY([non-root table with default_is_root=true],
|
||||
[[parse-table mytable '{"columns": {"name": {"type": "string"}}}' true]],
|
||||
[[{"columns":{"name":{"type":"string"}},"isRoot":false}]])
|
||||
|
||||
OVSDB_CHECK_POSITIVE_CPY([root table with default_is_root=true],
|
||||
[[parse-table mytable \
|
||||
'{"columns": {"name": {"type": "string"}},
|
||||
"isRoot": true}' true]],
|
||||
[[{"columns":{"name":{"type":"string"}}}]])
|
||||
|
||||
OVSDB_CHECK_POSITIVE_CPY([table with maxRows of 2],
|
||||
[[parse-table mytable '{"columns": {"name": {"type": "string"}},
|
||||
"maxRows": 2}']],
|
||||
|
@@ -141,7 +141,7 @@ usage(void)
|
||||
" parse string DATUMs as data of given TYPE, and re-serialize\n"
|
||||
" parse-column NAME OBJECT\n"
|
||||
" parse column NAME with info OBJECT, and re-serialize\n"
|
||||
" parse-table NAME OBJECT\n"
|
||||
" parse-table NAME OBJECT [DEFAULT-IS-ROOT]\n"
|
||||
" parse table NAME with info OBJECT\n"
|
||||
" parse-row TABLE ROW..., and re-serialize\n"
|
||||
" parse each ROW of defined TABLE\n"
|
||||
@@ -608,12 +608,15 @@ static void
|
||||
do_parse_table(int argc OVS_UNUSED, char *argv[])
|
||||
{
|
||||
struct ovsdb_table_schema *ts;
|
||||
bool default_is_root;
|
||||
struct json *json;
|
||||
|
||||
default_is_root = argc > 3 && !strcmp(argv[3], "true");
|
||||
|
||||
json = parse_json(argv[2]);
|
||||
check_ovsdb_error(ovsdb_table_schema_from_json(json, argv[1], &ts));
|
||||
json_destroy(json);
|
||||
print_and_free_json(ovsdb_table_schema_to_json(ts));
|
||||
print_and_free_json(ovsdb_table_schema_to_json(ts, default_is_root));
|
||||
ovsdb_table_schema_destroy(ts);
|
||||
}
|
||||
|
||||
@@ -1932,7 +1935,7 @@ static struct command all_commands[] = {
|
||||
{ "parse-data-strings", 2, INT_MAX, do_parse_data_strings },
|
||||
{ "sort-atoms", 2, 2, do_sort_atoms },
|
||||
{ "parse-column", 2, 2, do_parse_column },
|
||||
{ "parse-table", 2, 2, do_parse_table },
|
||||
{ "parse-table", 2, 3, do_parse_table },
|
||||
{ "parse-rows", 2, INT_MAX, do_parse_rows },
|
||||
{ "compare-rows", 2, INT_MAX, do_compare_rows },
|
||||
{ "parse-conditions", 2, INT_MAX, do_parse_conditions },
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2009, 2010 Nicira Networks
|
||||
# Copyright (c) 2009, 2010, 2011 Nicira Networks
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -121,10 +121,11 @@ def do_parse_column(name, column_string):
|
||||
column = ovs.db.schema.ColumnSchema.from_json(column_json, name)
|
||||
print ovs.json.to_string(column.to_json(), sort_keys=True)
|
||||
|
||||
def do_parse_table(name, table_string):
|
||||
def do_parse_table(name, table_string, default_is_root_string='false'):
|
||||
default_is_root = default_is_root_string == 'true'
|
||||
table_json = unbox_json(ovs.json.from_string(table_string))
|
||||
table = ovs.db.schema.TableSchema.from_json(table_json, name)
|
||||
print ovs.json.to_string(table.to_json(), sort_keys=True)
|
||||
print ovs.json.to_string(table.to_json(default_is_root), sort_keys=True)
|
||||
|
||||
def do_parse_rows(table_string, *rows):
|
||||
table_json = unbox_json(ovs.json.from_string(table_string))
|
||||
@@ -272,7 +273,7 @@ parse-data TYPE DATUM...
|
||||
parse JSON DATUMs as data of given TYPE, and re-serialize
|
||||
parse-column NAME OBJECT
|
||||
parse column NAME with info OBJECT, and re-serialize
|
||||
parse-table NAME OBJECT
|
||||
parse-table NAME OBJECT [DEFAULT-IS-ROOT]
|
||||
parse table NAME with info OBJECT
|
||||
parse-schema JSON
|
||||
parse JSON as an OVSDB schema, and re-serialize
|
||||
@@ -332,7 +333,7 @@ def main(argv):
|
||||
"parse-data": (do_parse_data, (2,)),
|
||||
"sort-atoms": (do_sort_atoms, 2),
|
||||
"parse-column": (do_parse_column, 2),
|
||||
"parse-table": (do_parse_table, 2),
|
||||
"parse-table": (do_parse_table, (2, 3)),
|
||||
"parse-schema": (do_parse_schema, 1),
|
||||
"idl": (do_idl, (1,))}
|
||||
|
||||
|
@@ -478,9 +478,11 @@ A bridge port. Records may be identified by port name.
|
||||
A network device attached to a port. Records may be identified by
|
||||
name.
|
||||
.IP "\fBQoS\fR"
|
||||
Quality-of-service configuration for an \fBInterface\fR.
|
||||
Quality-of-service configuration for a \fBPort\fR. Records may be
|
||||
identified by port name.
|
||||
.IP "\fBQueue\fR"
|
||||
Configuration for one queue within a \fBQoS\fR configuration.
|
||||
Configuration for one queue within a \fBQoS\fR configuration. Records
|
||||
may only be identified by UUID.
|
||||
.IP "\fBMonitor\fR"
|
||||
Connectivity Monitoring attached to an \fBInterface\fR. Records may be
|
||||
identified by \fBInterface\fR name.
|
||||
@@ -637,10 +639,30 @@ If \fB@\fIname\fR is specified, then the UUID for the new row may be
|
||||
referred to by that name elsewhere in the same \fBovs\-vsctl\fR
|
||||
invocation in contexts where a UUID is expected. Such references may
|
||||
precede or follow the \fBcreate\fR command.
|
||||
.IP
|
||||
Records in the Open vSwitch database are significant only when they
|
||||
can be reached directly or indirectly from the \fBOpen_vSwitch\fR
|
||||
table. Except for records in the \fBQoS\fR or \fBQueue\fR tables,
|
||||
records that are not reachable from the \fBOpen_vSwitch\fR table are
|
||||
automatically deleted from the database. This deletion happens
|
||||
immediately, without waiting for additional \fBovs\-vsctl\fR commands
|
||||
or other database activity. Thus, a \fBcreate\fR command must
|
||||
generally be accompanied by additional commands \fIwithin the same
|
||||
\fBovs\-vsctl\fI invocation\fR to add a chain of references to the
|
||||
newly created record from the top-level \fBOpen_vSwitch\fR record.
|
||||
The \fBEXAMPLES\fR section gives some examples that show how to do
|
||||
this.
|
||||
.
|
||||
.IP "\fR[\fB\-\-if\-exists\fR] \fBdestroy \fItable record\fR..."
|
||||
Deletes each specified \fIrecord\fR from \fItable\fR. Unless
|
||||
\fB\-\-if\-exists\fR is specified, each \fIrecord\fRs must exist.
|
||||
.IP
|
||||
It is often unnecessary to specify explicit \fBdestroy\fR commands,
|
||||
because (except for records in the \fBQoS\fR or \fBQueue\fR tables)
|
||||
records that are not reachable from the \fBOpen_vSwitch\fR table are
|
||||
automatically deleted from the database. This means that deleting the
|
||||
last reference to a record is sufficient for deleting the record
|
||||
itself. See the \fBEXAMPLES\fR section below for more information.
|
||||
.
|
||||
.IP "\fBwait\-until \fItable record \fR[\fIcolumn\fR[\fB:\fIkey\fR]\fB=\fIvalue\fR]..."
|
||||
Waits until \fItable\fR contains a record named \fIrecord\fR whose
|
||||
@@ -720,10 +742,10 @@ ignored):
|
||||
.IP
|
||||
.B "\-\- \-\-id=@m create Mirror name=mymirror select-dst-port=@eth0,@eth1 select-src-port=@eth0,@eth1 output-port=@eth2"
|
||||
.PP
|
||||
Remove the mirror created above from \fBbr0\fR and destroy the Mirror
|
||||
record (to avoid having an unreferenced record in the database):
|
||||
Remove the mirror created above from \fBbr0\fR, which also destroys
|
||||
the Mirror record (since it is now unreferenced):
|
||||
.IP
|
||||
.B "ovs\-vsctl destroy Mirror mymirror \-\- clear Bridge br0 mirrors"
|
||||
.B "remove Bridge br0 mirrors mymirror"
|
||||
.SS "Quality of Service (QoS)"
|
||||
.PP
|
||||
Create a \fBlinux\-htb\fR QoS record that points to a few queues and
|
||||
@@ -744,7 +766,8 @@ Deconfigure the QoS record above from \fBeth1\fR only:
|
||||
.B "ovs\-vsctl clear Port eth1 qos"
|
||||
.PP
|
||||
To deconfigure the QoS record from both \fBeth0\fR and \fBeth1\fR and
|
||||
then delete the QoS record:
|
||||
then delete the QoS record (which must be done explicitly because
|
||||
unreferenced QoS records are not automatically destroyed):
|
||||
.IP
|
||||
.B "ovs\-vsctl \-\- destroy QoS eth0 \-\- clear Port eth0 qos \-\- clear Port eth1 qos"
|
||||
.PP
|
||||
@@ -781,10 +804,10 @@ instead use an active timeout of 60 seconds:
|
||||
.IP
|
||||
.B "ovs\-vsctl set NetFlow br0 active_timeout=60"
|
||||
.PP
|
||||
Deconfigure the NetFlow settings from \fBbr0\fR and delete the NetFlow
|
||||
record (to avoid having an unreferenced record in the database):
|
||||
Deconfigure the NetFlow settings from \fBbr0\fR, which also destroys
|
||||
the NetFlow record (since it is now unreferenced):
|
||||
.IP
|
||||
.B "ovs\-vsctl destroy NetFlow br0 \-\- clear Bridge br0 netflow"
|
||||
.B "ovs\-vsctl clear Bridge br0 netflow"
|
||||
.SS "sFlow"
|
||||
.PP
|
||||
Configure bridge \fBbr0\fR to send sFlow records to a collector on
|
||||
@@ -795,10 +818,10 @@ with specific sampling parameters:
|
||||
.IP
|
||||
.B "\-\- set Bridge br0 sflow=@s"
|
||||
.PP
|
||||
Deconfigure sFlow from br0 and destroy the sFlow record (to avoid
|
||||
having an unreferenced record in the database):
|
||||
Deconfigure sFlow from br0, which also destroys the sFlow record
|
||||
(since it is now unreferenced):
|
||||
.IP
|
||||
.B "ovs\-vsctl \-\- destroy sFlow br0 \-\- clear Bridge br0 sflow"
|
||||
.B "ovs\-vsctl \-\- clear Bridge br0 sflow"
|
||||
.SH "EXIT STATUS"
|
||||
.IP "0"
|
||||
Successful program execution.
|
||||
|
@@ -1035,12 +1035,6 @@ cmd_emer_reset(struct vsctl_context *ctx)
|
||||
const struct ovsrec_bridge *br;
|
||||
const struct ovsrec_port *port;
|
||||
const struct ovsrec_interface *iface;
|
||||
const struct ovsrec_mirror *mirror, *next_mirror;
|
||||
const struct ovsrec_controller *ctrl, *next_ctrl;
|
||||
const struct ovsrec_manager *mgr, *next_mgr;
|
||||
const struct ovsrec_netflow *nf, *next_nf;
|
||||
const struct ovsrec_ssl *ssl, *next_ssl;
|
||||
const struct ovsrec_sflow *sflow, *next_sflow;
|
||||
|
||||
/* Reset the Open_vSwitch table. */
|
||||
ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
|
||||
@@ -1084,30 +1078,6 @@ cmd_emer_reset(struct vsctl_context *ctx)
|
||||
ovsrec_interface_set_ingress_policing_rate(iface, 0);
|
||||
ovsrec_interface_set_ingress_policing_burst(iface, 0);
|
||||
}
|
||||
|
||||
OVSREC_MIRROR_FOR_EACH_SAFE (mirror, next_mirror, idl) {
|
||||
ovsrec_mirror_delete(mirror);
|
||||
}
|
||||
|
||||
OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, next_ctrl, idl) {
|
||||
ovsrec_controller_delete(ctrl);
|
||||
}
|
||||
|
||||
OVSREC_MANAGER_FOR_EACH_SAFE (mgr, next_mgr, idl) {
|
||||
ovsrec_manager_delete(mgr);
|
||||
}
|
||||
|
||||
OVSREC_NETFLOW_FOR_EACH_SAFE (nf, next_nf, idl) {
|
||||
ovsrec_netflow_delete(nf);
|
||||
}
|
||||
|
||||
OVSREC_SSL_FOR_EACH_SAFE (ssl, next_ssl, idl) {
|
||||
ovsrec_ssl_delete(ssl);
|
||||
}
|
||||
|
||||
OVSREC_SFLOW_FOR_EACH_SAFE (sflow, next_sflow, idl) {
|
||||
ovsrec_sflow_delete(sflow);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1218,18 +1188,8 @@ cmd_add_br(struct vsctl_context *ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
del_port(struct vsctl_info *info, struct vsctl_port *port)
|
||||
del_port(struct vsctl_port *port)
|
||||
{
|
||||
struct shash_node *node;
|
||||
|
||||
SHASH_FOR_EACH (node, &info->ifaces) {
|
||||
struct vsctl_iface *iface = node->data;
|
||||
if (iface->port == port) {
|
||||
ovsrec_interface_delete(iface->iface_cfg);
|
||||
}
|
||||
}
|
||||
ovsrec_port_delete(port->port_cfg);
|
||||
|
||||
bridge_delete_port((port->bridge->parent
|
||||
? port->bridge->parent->br_cfg
|
||||
: port->bridge->br_cfg), port->port_cfg);
|
||||
@@ -1245,18 +1205,18 @@ cmd_del_br(struct vsctl_context *ctx)
|
||||
get_info(ctx, &info);
|
||||
bridge = find_bridge(&info, ctx->argv[1], must_exist);
|
||||
if (bridge) {
|
||||
struct shash_node *node;
|
||||
|
||||
SHASH_FOR_EACH (node, &info.ports) {
|
||||
struct vsctl_port *port = node->data;
|
||||
if (port->bridge == bridge || port->bridge->parent == bridge
|
||||
|| !strcmp(port->port_cfg->name, bridge->name)) {
|
||||
del_port(&info, port);
|
||||
}
|
||||
}
|
||||
if (bridge->br_cfg) {
|
||||
ovsrec_bridge_delete(bridge->br_cfg);
|
||||
ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
|
||||
} else {
|
||||
struct shash_node *node;
|
||||
|
||||
SHASH_FOR_EACH (node, &info.ports) {
|
||||
struct vsctl_port *port = node->data;
|
||||
if (port->bridge == bridge || port->bridge->parent == bridge
|
||||
|| !strcmp(port->port_cfg->name, bridge->name)) {
|
||||
del_port(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free_info(&info);
|
||||
@@ -1641,7 +1601,7 @@ cmd_del_port(struct vsctl_context *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
del_port(&info, port);
|
||||
del_port(port);
|
||||
}
|
||||
|
||||
free_info(&info);
|
||||
@@ -1773,17 +1733,6 @@ cmd_get_controller(struct vsctl_context *ctx)
|
||||
free_info(&info);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_controllers(struct ovsrec_controller **controllers,
|
||||
size_t n_controllers)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n_controllers; i++) {
|
||||
ovsrec_controller_delete(controllers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_del_controller(struct vsctl_context *ctx)
|
||||
{
|
||||
@@ -1791,13 +1740,9 @@ cmd_del_controller(struct vsctl_context *ctx)
|
||||
struct vsctl_bridge *br;
|
||||
|
||||
get_info(ctx, &info);
|
||||
br = find_real_bridge(&info, ctx->argv[1], true);
|
||||
verify_controllers(br->br_cfg);
|
||||
|
||||
if (br->ctrl) {
|
||||
delete_controllers(br->ctrl, br->n_ctrl);
|
||||
ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
|
||||
}
|
||||
br = find_real_bridge(&info, ctx->argv[1], true);
|
||||
ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
|
||||
|
||||
free_info(&info);
|
||||
}
|
||||
@@ -1827,9 +1772,6 @@ cmd_set_controller(struct vsctl_context *ctx)
|
||||
|
||||
get_info(ctx, &info);
|
||||
br = find_real_bridge(&info, ctx->argv[1], true);
|
||||
verify_controllers(br->br_cfg);
|
||||
|
||||
delete_controllers(br->ctrl, br->n_ctrl);
|
||||
|
||||
n = ctx->argc - 2;
|
||||
controllers = insert_controllers(ctx->txn, &ctx->argv[2], n);
|
||||
@@ -1935,28 +1877,12 @@ cmd_get_manager(struct vsctl_context *ctx)
|
||||
svec_destroy(&targets);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_managers(const struct vsctl_context *ctx)
|
||||
{
|
||||
const struct ovsrec_open_vswitch *ovs = ctx->ovs;
|
||||
size_t i;
|
||||
|
||||
/* Delete Manager rows pointed to by 'manager_options' column. */
|
||||
for (i = 0; i < ovs->n_manager_options; i++) {
|
||||
ovsrec_manager_delete(ovs->manager_options[i]);
|
||||
}
|
||||
|
||||
/* Delete 'Manager' row refs in 'manager_options' column. */
|
||||
ovsrec_open_vswitch_set_manager_options(ovs, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_del_manager(struct vsctl_context *ctx)
|
||||
{
|
||||
const struct ovsrec_open_vswitch *ovs = ctx->ovs;
|
||||
|
||||
verify_managers(ovs);
|
||||
delete_managers(ctx);
|
||||
ovsrec_open_vswitch_set_manager_options(ovs, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1982,8 +1908,6 @@ cmd_set_manager(struct vsctl_context *ctx)
|
||||
{
|
||||
const size_t n = ctx->argc - 1;
|
||||
|
||||
verify_managers(ctx->ovs);
|
||||
delete_managers(ctx);
|
||||
insert_managers(ctx, &ctx->argv[1], n);
|
||||
}
|
||||
|
||||
@@ -2027,13 +1951,7 @@ pre_cmd_del_ssl(struct vsctl_context *ctx)
|
||||
static void
|
||||
cmd_del_ssl(struct vsctl_context *ctx)
|
||||
{
|
||||
struct ovsrec_ssl *ssl = ctx->ovs->ssl;
|
||||
|
||||
if (ssl) {
|
||||
ovsrec_open_vswitch_verify_ssl(ctx->ovs);
|
||||
ovsrec_ssl_delete(ssl);
|
||||
ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
|
||||
}
|
||||
ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2046,12 +1964,8 @@ static void
|
||||
cmd_set_ssl(struct vsctl_context *ctx)
|
||||
{
|
||||
bool bootstrap = shash_find(&ctx->options, "--bootstrap");
|
||||
struct ovsrec_ssl *ssl = ctx->ovs->ssl;
|
||||
struct ovsrec_ssl *ssl;
|
||||
|
||||
ovsrec_open_vswitch_verify_ssl(ctx->ovs);
|
||||
if (ssl) {
|
||||
ovsrec_ssl_delete(ssl);
|
||||
}
|
||||
ssl = ovsrec_ssl_insert(ctx->txn);
|
||||
|
||||
ovsrec_ssl_set_private_key(ssl, ctx->argv[1]);
|
||||
@@ -2351,7 +2265,7 @@ get_column(const struct vsctl_table_class *table, const char *column_name,
|
||||
}
|
||||
}
|
||||
|
||||
static struct uuid *
|
||||
static struct ovsdb_symbol *
|
||||
create_symbol(struct ovsdb_symbol_table *symtab, const char *id, bool *newp)
|
||||
{
|
||||
struct ovsdb_symbol *symbol;
|
||||
@@ -2370,7 +2284,7 @@ create_symbol(struct ovsdb_symbol_table *symtab, const char *id, bool *newp)
|
||||
id);
|
||||
}
|
||||
symbol->created = true;
|
||||
return &symbol->uuid;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2578,13 +2492,19 @@ cmd_get(struct vsctl_context *ctx)
|
||||
table = get_table(table_name);
|
||||
row = must_get_row(ctx, table, record_id);
|
||||
if (id) {
|
||||
struct ovsdb_symbol *symbol;
|
||||
bool new;
|
||||
|
||||
*create_symbol(ctx->symtab, id, &new) = row->uuid;
|
||||
symbol = create_symbol(ctx->symtab, id, &new);
|
||||
if (!new) {
|
||||
vsctl_fatal("row id \"%s\" specified on \"get\" command was used "
|
||||
"before it was defined", id);
|
||||
}
|
||||
symbol->uuid = row->uuid;
|
||||
|
||||
/* This symbol refers to a row that already exists, so disable warnings
|
||||
* about it being unreferenced. */
|
||||
symbol->strong_ref = true;
|
||||
}
|
||||
for (i = 3; i < ctx->argc; i++) {
|
||||
const struct ovsdb_idl_column *column;
|
||||
@@ -3093,18 +3013,42 @@ cmd_clear(struct vsctl_context *ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_create(struct vsctl_context *ctx)
|
||||
pre_create(struct vsctl_context *ctx)
|
||||
{
|
||||
const char *id = shash_find_data(&ctx->options, "--id");
|
||||
const char *table_name = ctx->argv[1];
|
||||
const struct vsctl_table_class *table;
|
||||
|
||||
table = get_table(table_name);
|
||||
if (!id && !table->class->is_root) {
|
||||
VLOG_WARN("applying \"create\" command to table %s without --id "
|
||||
"option will have no effect", table->class->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_create(struct vsctl_context *ctx)
|
||||
{
|
||||
const char *id = shash_find_data(&ctx->options, "--id");
|
||||
const char *table_name = ctx->argv[1];
|
||||
const struct vsctl_table_class *table = get_table(table_name);
|
||||
const struct ovsdb_idl_row *row;
|
||||
const struct uuid *uuid;
|
||||
int i;
|
||||
|
||||
uuid = id ? create_symbol(ctx->symtab, id, NULL) : NULL;
|
||||
if (id) {
|
||||
struct ovsdb_symbol *symbol = create_symbol(ctx->symtab, id, NULL);
|
||||
if (table->class->is_root) {
|
||||
/* This table is in the root set, meaning that rows created in it
|
||||
* won't disappear even if they are unreferenced, so disable
|
||||
* warnings about that by pretending that there is a reference. */
|
||||
symbol->strong_ref = true;
|
||||
}
|
||||
uuid = &symbol->uuid;
|
||||
} else {
|
||||
uuid = NULL;
|
||||
}
|
||||
|
||||
table = get_table(table_name);
|
||||
row = ovsdb_idl_txn_insert(ctx->txn, table->class, uuid);
|
||||
for (i = 2; i < ctx->argc; i++) {
|
||||
set_column(table, row, ctx->argv[i], ctx->symtab);
|
||||
@@ -3402,6 +3346,17 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
|
||||
"with \"-- --id=%s create ...\")",
|
||||
node->name, node->name);
|
||||
}
|
||||
if (!symbol->strong_ref) {
|
||||
if (!symbol->weak_ref) {
|
||||
VLOG_WARN("row id \"%s\" was created but no reference to it "
|
||||
"was inserted, so it will not actually appear in "
|
||||
"the database", node->name);
|
||||
} else {
|
||||
VLOG_WARN("row id \"%s\" was created but only a weak "
|
||||
"reference to it was inserted, so it will not "
|
||||
"actually appear in the database", node->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = ovsdb_idl_txn_commit_block(txn);
|
||||
@@ -3577,7 +3532,7 @@ static const struct vsctl_command_syntax all_commands[] = {
|
||||
{"add", 4, INT_MAX, pre_cmd_add, cmd_add, NULL, "", RW},
|
||||
{"remove", 4, INT_MAX, pre_cmd_remove, cmd_remove, NULL, "", RW},
|
||||
{"clear", 3, INT_MAX, pre_cmd_clear, cmd_clear, NULL, "", RW},
|
||||
{"create", 2, INT_MAX, NULL, cmd_create, post_create, "--id=", RW},
|
||||
{"create", 2, INT_MAX, pre_create, cmd_create, post_create, "--id=", RW},
|
||||
{"destroy", 1, INT_MAX, pre_cmd_destroy, cmd_destroy, NULL, "--if-exists",
|
||||
RW},
|
||||
{"wait-until", 2, INT_MAX, pre_cmd_wait_until, cmd_wait_until, NULL, "",
|
||||
|
@@ -497,14 +497,6 @@ del_port(const struct ovsrec_bridge *br, const struct ovsrec_port *port)
|
||||
}
|
||||
ovsrec_bridge_set_ports(br, ports, n);
|
||||
free(ports);
|
||||
|
||||
/* Delete all of the port's interfaces. */
|
||||
for (i = 0; i < port->n_interfaces; i++) {
|
||||
ovsrec_interface_delete(port->interfaces[i]);
|
||||
}
|
||||
|
||||
/* Delete the port itself. */
|
||||
ovsrec_port_delete(port);
|
||||
}
|
||||
|
||||
/* Delete 'iface' from 'port' (which must be within 'br'). If 'iface' was
|
||||
@@ -530,7 +522,6 @@ del_interface(const struct ovsrec_bridge *br,
|
||||
}
|
||||
ovsrec_port_set_interfaces(port, ifaces, n);
|
||||
free(ifaces);
|
||||
ovsrec_interface_delete(iface);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,24 +582,6 @@ del_bridge(struct ovsdb_idl *idl,
|
||||
|
||||
ovsdb_idl_txn_add_comment(txn, "ovs-brcompatd: delbr %s", br_name);
|
||||
|
||||
/* Delete everything that the bridge points to, then delete the bridge
|
||||
* itself. */
|
||||
while (br->n_ports > 0) {
|
||||
del_port(br, br->ports[0]);
|
||||
}
|
||||
for (i = 0; i < br->n_mirrors; i++) {
|
||||
ovsrec_mirror_delete(br->mirrors[i]);
|
||||
}
|
||||
if (br->netflow) {
|
||||
ovsrec_netflow_delete(br->netflow);
|
||||
}
|
||||
if (br->sflow) {
|
||||
ovsrec_sflow_delete(br->sflow);
|
||||
}
|
||||
for (i = 0; i < br->n_controller; i++) {
|
||||
ovsrec_controller_delete(br->controller[i]);
|
||||
}
|
||||
|
||||
/* Remove 'br' from the vswitch's list of bridges. */
|
||||
bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
|
||||
for (i = n = 0; i < ovs->n_bridges; i++) {
|
||||
@@ -619,9 +592,6 @@ del_bridge(struct ovsdb_idl *idl,
|
||||
ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
|
||||
free(bridges);
|
||||
|
||||
/* Delete the bridge itself. */
|
||||
ovsrec_bridge_delete(br);
|
||||
|
||||
return commit_txn(txn, true);
|
||||
}
|
||||
|
||||
|
@@ -3,92 +3,36 @@ digraph Open_vSwitch {
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Bridge;
|
||||
Bridge [style=bold];
|
||||
Bridge -> sFlow [label="sflow"];
|
||||
Bridge -> Mirror [label="mirrors"];
|
||||
Bridge -> Port [label="ports"];
|
||||
Bridge -> Controller [label="controller"];
|
||||
Bridge -> NetFlow [label="netflow"];
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
QoS;
|
||||
QoS [style=bold];
|
||||
QoS -> Queue [label="queues value"];
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Monitor;
|
||||
Monitor [style=bold];
|
||||
Monitor -> Maintenance_Point [label="remote_mps"];
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
sFlow;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Open_vSwitch;
|
||||
sFlow [style=bold];
|
||||
Open_vSwitch [style=bold];
|
||||
Open_vSwitch -> Bridge [label="bridges"];
|
||||
Open_vSwitch -> Capability [label="capabilities value"];
|
||||
Open_vSwitch -> SSL [label="ssl"];
|
||||
Open_vSwitch -> Manager [label="manager_options"];
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Controller;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Queue;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
SSL;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Manager;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Capability;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Mirror;
|
||||
Mirror -> Port [constraint=false, label="select_src_port"];
|
||||
Mirror -> Port [constraint=false, label="output_port"];
|
||||
Mirror -> Port [constraint=false, label="select_dst_port"];
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Interface;
|
||||
Controller [style=bold];
|
||||
Queue [style=bold];
|
||||
SSL [style=bold];
|
||||
Manager [style=bold];
|
||||
Capability [style=bold];
|
||||
Mirror [style=bold];
|
||||
Mirror -> Port [style=dotted, constraint=false, label="select_src_port"];
|
||||
Mirror -> Port [style=dotted, constraint=false, label="output_port"];
|
||||
Mirror -> Port [style=dotted, constraint=false, label="select_dst_port"];
|
||||
Interface [style=bold];
|
||||
Interface -> Monitor [label="monitor"];
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
NetFlow;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Maintenance_Point;
|
||||
size="6.5,4";
|
||||
margin="0";
|
||||
node [shape=box];
|
||||
edge [dir=none, arrowhead=none, arrowtail=none];
|
||||
Port;
|
||||
NetFlow [style=bold];
|
||||
Maintenance_Point [style=bold];
|
||||
Port [style=bold];
|
||||
Port -> QoS [label="qos"];
|
||||
Port -> Interface [label="interfaces"];
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{"name": "Open_vSwitch",
|
||||
"version": "2.0.0",
|
||||
"cksum": "4107852581 15651",
|
||||
"version": "2.1.0",
|
||||
"cksum": "1990266641 15714",
|
||||
"tables": {
|
||||
"Open_vSwitch": {
|
||||
"columns": {
|
||||
@@ -43,6 +43,7 @@
|
||||
"system_version": {
|
||||
"type": {"key": {"type": "string"},
|
||||
"min": 0, "max": 1}}},
|
||||
"isRoot": true,
|
||||
"maxRows": 1},
|
||||
"Capability": {
|
||||
"columns": {
|
||||
@@ -267,7 +268,8 @@
|
||||
"min": 0, "max": "unlimited"}},
|
||||
"external_ids": {
|
||||
"type": {"key": "string", "value": "string",
|
||||
"min": 0, "max": "unlimited"}}}},
|
||||
"min": 0, "max": "unlimited"}}},
|
||||
"isRoot": true},
|
||||
"Queue": {
|
||||
"columns": {
|
||||
"other_config": {
|
||||
@@ -275,7 +277,8 @@
|
||||
"min": 0, "max": "unlimited"}},
|
||||
"external_ids": {
|
||||
"type": {"key": "string", "value": "string",
|
||||
"min": 0, "max": "unlimited"}}}},
|
||||
"min": 0, "max": "unlimited"}}},
|
||||
"isRoot": true},
|
||||
"Mirror": {
|
||||
"columns": {
|
||||
"name": {
|
||||
|
@@ -1,53 +1,100 @@
|
||||
.\" Generated from vswitch.gv with cksum "3734436941 2390"
|
||||
.\" Generated from vswitch.gv with cksum "1122829786 1269"
|
||||
.PS
|
||||
linethick = 1;
|
||||
linethick = 0.5;
|
||||
box at 2.320997253,3.1110975 wid 0.5020540998 height 0.296295 "Bridge"
|
||||
box at 2.320997253,3.1110975 wid 0.446498544244444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 0.2304523251,2.37036 wid 0.4609046502 height 0.296295 "sFlow"
|
||||
box at 0.2304523251,2.37036 wid 0.405349094644444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 0.847759254,2.37036 wid 0.4855919496 height 0.296295 "Mirror"
|
||||
box at 0.847759254,2.37036 wid 0.430036394044444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 2.320997253,2.37036 wid 0.4444425 height 0.296295 "Port"
|
||||
box at 2.320997253,2.37036 wid 0.388886944444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 3.045260751,2.37036 wid 0.707789496 height 0.296295 "Controller"
|
||||
box at 3.045260751,2.37036 wid 0.652233940444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 3.851835,2.37036 wid 0.609064002 height 0.296295 "NetFlow"
|
||||
box at 3.851835,2.37036 wid 0.553508446444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 2.057590998,1.6296225 wid 0.4444425 height 0.296295 "QoS"
|
||||
box at 2.057590998,1.6296225 wid 0.388886944444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 1.991754249,0.888885 wid 0.5102851749 height 0.296295 "Queue"
|
||||
box at 1.991754249,0.888885 wid 0.454729619344444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 2.938238997,0.888885 wid 0.5761278498 height 0.296295 "Monitor"
|
||||
box at 2.938238997,0.888885 wid 0.520572294244444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 2.938238997,0.1481475 wid 1.218128004 height 0.296295 "Maintenance_Point"
|
||||
box at 2.938238997,0.1481475 wid 1.16257244844444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 3.637850751,3.851835 wid 0.954721749 height 0.296295 "Open_vSwitch"
|
||||
box at 3.637850751,3.851835 wid 0.899166193444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 3.061734753,3.1110975 wid 0.699611754 height 0.296295 "Capability"
|
||||
box at 3.061734753,3.1110975 wid 0.644056198444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 4.22220375,3.1110975 wid 0.4444425 height 0.296295 "SSL"
|
||||
box at 4.22220375,3.1110975 wid 0.388886944444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 4.905341502,3.1110975 wid 0.633715746 height 0.296295 "Manager"
|
||||
box at 4.905341502,3.1110975 wid 0.578160190444444 height 0.240739444444444
|
||||
linethick = 0.5;
|
||||
box at 2.872402248,1.6296225 wid 0.641952747 height 0.296295 "Interface"
|
||||
box at 2.872402248,1.6296225 wid 0.586397191444444 height 0.240739444444444
|
||||
linethick = 1;
|
||||
spline -> from 2.072227971,3.066534732 to 2.072227971,3.066534732 to 1.825829049,3.018534942 to 1.439934441,2.932787169 to 1.119343251,2.8148025 to 0.887818338,2.729588058 to 0.637567581,2.60087751 to 0.4617876093,2.503870527
|
||||
"sflow" at 1.271579622,2.74072875
|
||||
linethick = 1;
|
||||
spline -> from 2.071042791,2.98546842 to 2.071042791,2.98546842 to 1.796021772,2.847157914 to 1.357208877,2.626536657 to 1.086632283,2.490477993
|
||||
"mirrors" at 1.9259175,2.74072875
|
||||
linethick = 1;
|
||||
spline -> from 2.320997253,2.96117223 to 2.320997253,2.96117223 to 2.320997253,2.832698718 to 2.320997253,2.648462487 to 2.320997253,2.520048234
|
||||
"ports" at 2.469144753,2.74072875
|
||||
linethick = 1;
|
||||
spline -> from 2.495218713,2.960816676 to 2.495218713,2.960816676 to 2.546240712,2.915068728 to 2.601410841,2.863868952 to 2.650180998,2.8148025 to 2.743336146,2.721054762 to 2.842120899,2.609944137 to 2.917557606,2.522300076
|
||||
"controller" at 3.065823624,2.74072875
|
||||
linethick = 1;
|
||||
spline -> from 2.571070233,2.988964701 to 2.571070233,2.988964701 to 2.594773833,2.979424002 to 2.61865521,2.970594411 to 2.641943997,2.96295 to 2.957675949,2.859720822 to 3.079038381,2.966624058 to 3.374444496,2.8148025 to 3.514473513,2.742862074 to 3.643184061,2.618003361 to 3.731598489,2.518922313
|
||||
"netflow" at 3.802472253,2.74072875
|
||||
linethick = 0.5;
|
||||
spline -> from 1.091017449,2.37036 to 1.091017449,2.37036 to 1.370542152,2.37036 to 1.825414236,2.37036 to 2.096701938,2.37036
|
||||
"select_src_port" at 1.588496754,2.44443375
|
||||
linethick = 0.5;
|
||||
spline -> from 1.067787921,2.221501392 to 1.067787921,2.221501392 to 1.095284097,2.208345894 to 1.123787676,2.197086684 to 1.152231996,2.189264496 to 1.526156286,2.08650939 to 1.651429812,2.084257548 to 2.024702253,2.189264496 to 2.052553983,2.197145943 to 2.080346454,2.208405153 to 2.107190781,2.221501392
|
||||
"output_port" at 1.588496754,2.263338246
|
||||
linethick = 0.5;
|
||||
spline -> from 0.905240484,2.221264356 to 0.905240484,2.221264356 to 0.953892123,2.117798142 to 1.034780658,1.987843155 to 1.152231996,1.9259175 to 1.495282347,1.745118291 to 1.682837082,1.742984967 to 2.024702253,1.9259175 to 2.140790634,1.988080191 to 2.21924955,2.117975919 to 2.266123419,2.221442133
|
||||
"select_dst_port" at 1.588496754,1.99999125
|
||||
linethick = 1;
|
||||
spline -> from 2.267664153,2.22043473 to 2.267664153,2.22043473 to 2.221975464,2.091961218 to 2.156494269,1.907724987 to 2.11080558,1.779310734
|
||||
"qos" at 2.312760252,1.99999125
|
||||
linethick = 1;
|
||||
spline -> from 2.43258195,2.22043473 to 2.43258195,2.22043473 to 2.528225976,2.091961218 to 2.665351302,1.907724987 to 2.760995328,1.779310734
|
||||
"interfaces" at 2.930001996,1.99999125
|
||||
linethick = 1;
|
||||
spline -> from 2.023220778,1.479637971 to 2.023220778,1.479637971 to 2.013917115,1.433001138 to 2.005028265,1.381268031 to 1.99999125,1.3333275 to 1.989620925,1.235076078 to 1.98754686,1.123965453 to 1.988080191,1.037447313
|
||||
"queues value" at 2.378597001,1.25925375
|
||||
linethick = 1;
|
||||
spline -> from 2.938238997,0.73895973 to 2.938238997,0.73895973 to 2.938238997,0.610486218 to 2.938238997,0.4262736906 to 2.938238997,0.2978238822
|
||||
"remote_mps" at 3.288044874,0.51851625
|
||||
linethick = 1;
|
||||
spline -> from 3.159808398,3.796309317 to 3.159808398,3.796309317 to 2.96591295,3.754828017 to 2.749321305,3.682295001 to 2.584344249,3.55554 to 2.486211345,3.480162552 to 2.417352387,3.356903832 to 2.374685907,3.259245
|
||||
"bridges" at 2.790091497,3.48146625
|
||||
linethick = 1;
|
||||
spline -> from 3.219067398,3.702146766 to 3.219067398,3.702146766 to 3.159926916,3.663332121 to 3.106830852,3.615095295 to 3.069971754,3.55554 to 3.015927546,3.468251493 to 3.015809028,3.35168904 to 3.028194159,3.25983759
|
||||
"capabilities value" at 3.55554,3.48146625
|
||||
linethick = 1;
|
||||
spline -> from 3.884901522,3.703568982 to 3.884901522,3.703568982 to 3.941612385,3.661080279 to 3.997849176,3.611065683 to 4.041108246,3.55554 to 4.109256096,3.468132975 to 4.155478116,3.351570522 to 4.184159472,3.259778331
|
||||
"ssl" at 4.205729748,3.48146625
|
||||
linethick = 1;
|
||||
spline -> from 4.020249078,3.702146766 to 4.020249078,3.702146766 to 4.117848651,3.659065473 to 4.22101857,3.609110136 to 4.312751502,3.55554 to 4.46042493,3.469258896 to 4.614616848,3.352696443 to 4.728690423,3.260548698
|
||||
"manager_options" at 5.024689128,3.48146625
|
||||
linethick = 1;
|
||||
spline -> from 2.885735523,1.47969723 to 2.885735523,1.47969723 to 2.89717251,1.351223718 to 2.913527994,1.166987487 to 2.924964981,1.038573234
|
||||
"monitor" at 3.139897374,1.25925375
|
||||
.PE
|
||||
|
@@ -1,15 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<database title="Open vSwitch Configuration Database">
|
||||
<p>A database with this schema holds the configuration for one Open
|
||||
vSwitch daemon. The root of the configuration for the daemon is
|
||||
the <ref table="Open_vSwitch"/> table, which must have exactly one
|
||||
<p>
|
||||
A database with this schema holds the configuration for one Open
|
||||
vSwitch daemon. The top-level configuration for the daemon is the
|
||||
<ref table="Open_vSwitch"/> table, which must have exactly one
|
||||
record. Records in other tables are significant only when they
|
||||
can be reached directly or indirectly from the
|
||||
<ref table="Open_vSwitch"/> table.</p>
|
||||
can be reached directly or indirectly from the <ref
|
||||
table="Open_vSwitch"/> table. Records that are not reachable from
|
||||
the <ref table="Open_vSwitch"/> table are automatically deleted
|
||||
from the database, except for records in a few distinguished
|
||||
``root set'' tables noted below.
|
||||
</p>
|
||||
|
||||
<table name="Open_vSwitch" title="Open vSwitch configuration.">
|
||||
Configuration for an Open vSwitch daemon. There must be exactly one record
|
||||
in the <ref table="Open_vSwitch"/> table.
|
||||
Configuration for an Open vSwitch daemon. There must be exactly
|
||||
one record in the <ref table="Open_vSwitch"/> table.
|
||||
|
||||
<group title="Configuration">
|
||||
<column name="bridges">
|
||||
|
@@ -341,7 +341,18 @@ function start {
|
||||
cksum=`$ovsdb_tool db-cksum "$OVSDB_SERVER_DB" | awk '{print $1}'`
|
||||
cp "$OVSDB_SERVER_DB" "$OVSDB_SERVER_DB.backup$version-$cksum"
|
||||
|
||||
# Upgrade or downgrade schema and compact database.
|
||||
# Compact database. This is important if the old schema did not enable
|
||||
# garbage collection (i.e. if it did not have any tables with "isRoot":
|
||||
# true) but the new schema does. In that situation the old database
|
||||
# may contain a transaction that creates a record followed by a
|
||||
# transaction that creates the first use of the record. Replaying that
|
||||
# series of transactions against the new database schema (as "convert"
|
||||
# does) would cause the record to be dropped by the first transaction,
|
||||
# then the second transaction would cause a referential integrity
|
||||
# failure (for a strong reference).
|
||||
$ovsdb_tool -vANY:console:emer compact "$OVSDB_SERVER_DB"
|
||||
|
||||
# Upgrade or downgrade schema.
|
||||
$ovsdb_tool -vANY:console:emer convert "$OVSDB_SERVER_DB" "$VSWITCHD_OVSDB_SCHEMA"
|
||||
fi
|
||||
|
||||
|
Reference in New Issue
Block a user