mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
ovsdb: Enforce immutability of immutable columns.
OVSDB has always had the ability to mark a column as "immutable", so that its value cannot be changed in a given row after that row is initially inserted. However, we discovered recently that ovsdb-server has never enforced this constraint. This commit implements enforcement. Reported-by: Paul Ingram <paul@nicira.com> Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Kyle Mestery <kmestery@cisco.com>
This commit is contained in:
parent
c22c56bd74
commit
341c4e59f5
2
NEWS
2
NEWS
@ -18,6 +18,8 @@ post-v1.8.0
|
|||||||
are true, but because we do not know of any users for this
|
are true, but because we do not know of any users for this
|
||||||
feature it seems better on balance to remove it. (The ovs-pki-cgi
|
feature it seems better on balance to remove it. (The ovs-pki-cgi
|
||||||
program was not included in distribution packaging.)
|
program was not included in distribution packaging.)
|
||||||
|
- ovsdb-server now enforces the immutability of immutable columns. This
|
||||||
|
was not enforced in earlier versions due to an oversight.
|
||||||
- Stable bond mode is deprecated and will be removed no earlier than
|
- Stable bond mode is deprecated and will be removed no earlier than
|
||||||
February 2013. Please email dev@openvswitch.org with concerns.
|
February 2013. Please email dev@openvswitch.org with concerns.
|
||||||
- The autopath action is deprecated and will be removed no earlier than
|
- The autopath action is deprecated and will be removed no earlier than
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2009, 2010, 2011 Nicira, Inc.
|
/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -41,6 +41,7 @@ struct ovsdb_idl_row {
|
|||||||
struct ovsdb_idl_column {
|
struct ovsdb_idl_column {
|
||||||
char *name;
|
char *name;
|
||||||
struct ovsdb_type type;
|
struct ovsdb_type type;
|
||||||
|
bool mutable;
|
||||||
void (*parse)(struct ovsdb_idl_row *, const struct ovsdb_datum *);
|
void (*parse)(struct ovsdb_idl_row *, const struct ovsdb_datum *);
|
||||||
void (*unparse)(struct ovsdb_idl_row *);
|
void (*unparse)(struct ovsdb_idl_row *);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2009, 2010, 2011 Nicira, Inc.
|
/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -434,6 +434,22 @@ ovsdb_execute_update(struct ovsdb_execution *x, struct ovsdb_parser *parser,
|
|||||||
if (!error) {
|
if (!error) {
|
||||||
error = parse_row(row_json, table, x->symtab, &row, &columns);
|
error = parse_row(row_json, table, x->symtab, &row, &columns);
|
||||||
}
|
}
|
||||||
|
if (!error) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < columns.n_columns; i++) {
|
||||||
|
const struct ovsdb_column *column = columns.columns[i];
|
||||||
|
|
||||||
|
if (!column->mutable) {
|
||||||
|
error = ovsdb_syntax_error(parser->json,
|
||||||
|
"constraint violation",
|
||||||
|
"Cannot update immutable column %s "
|
||||||
|
"in table %s.",
|
||||||
|
column->name, table->schema->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!error) {
|
if (!error) {
|
||||||
error = ovsdb_condition_from_json(table->schema, where, x->symtab,
|
error = ovsdb_condition_from_json(table->schema, where, x->symtab,
|
||||||
&condition);
|
&condition);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2009, 2010, 2011 Nicira, Inc.
|
/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -95,6 +95,12 @@ ovsdb_mutation_from_json(const struct ovsdb_table_schema *ts,
|
|||||||
"No column %s in table %s.",
|
"No column %s in table %s.",
|
||||||
column_name, ts->name);
|
column_name, ts->name);
|
||||||
}
|
}
|
||||||
|
if (!m->column->mutable) {
|
||||||
|
return ovsdb_syntax_error(json, "constraint violation",
|
||||||
|
"Cannot mutate immutable column %s in "
|
||||||
|
"table %s.", column_name, ts->name);
|
||||||
|
}
|
||||||
|
|
||||||
ovsdb_type_clone(&m->type, &m->column->type);
|
ovsdb_type_clone(&m->type, &m->column->type);
|
||||||
|
|
||||||
mutator_name = json_string(array->elems[1]);
|
mutator_name = json_string(array->elems[1]);
|
||||||
|
@ -577,11 +577,16 @@ static void\n%s_columns_init(void)
|
|||||||
for columnName, column in sorted(table.columns.iteritems()):
|
for columnName, column in sorted(table.columns.iteritems()):
|
||||||
cs = "%s_col_%s" % (structName, columnName)
|
cs = "%s_col_%s" % (structName, columnName)
|
||||||
d = {'cs': cs, 'c': columnName, 's': structName}
|
d = {'cs': cs, 'c': columnName, 's': structName}
|
||||||
|
if column.mutable:
|
||||||
|
mutable = "true"
|
||||||
|
else:
|
||||||
|
mutable = "false"
|
||||||
print
|
print
|
||||||
print " /* Initialize %(cs)s. */" % d
|
print " /* Initialize %(cs)s. */" % d
|
||||||
print " c = &%(cs)s;" % d
|
print " c = &%(cs)s;" % d
|
||||||
print " c->name = \"%(c)s\";" % d
|
print " c->name = \"%(c)s\";" % d
|
||||||
print column.type.cInitType(" ", "c->type")
|
print column.type.cInitType(" ", "c->type")
|
||||||
|
print " c->mutable = %s;" % mutable
|
||||||
print " c->parse = %(s)s_parse_%(c)s;" % d
|
print " c->parse = %(s)s_parse_%(c)s;" % d
|
||||||
print " c->unparse = %(s)s_unparse_%(c)s;" % d
|
print " c->unparse = %(s)s_unparse_%(c)s;" % d
|
||||||
print "}"
|
print "}"
|
||||||
|
@ -736,6 +736,18 @@ AT_CHECK([RUN_OVS_VSCTL([clear netflow `cat netflow-uuid` targets])],
|
|||||||
AT_CHECK([RUN_OVS_VSCTL([destroy b br2])],
|
AT_CHECK([RUN_OVS_VSCTL([destroy b br2])],
|
||||||
[1], [], [ovs-vsctl: no row "br2" in table Bridge
|
[1], [], [ovs-vsctl: no row "br2" in table Bridge
|
||||||
], [OVS_VSCTL_CLEANUP])
|
], [OVS_VSCTL_CLEANUP])
|
||||||
|
AT_CHECK([RUN_OVS_VSCTL([add i br1 name x])],
|
||||||
|
[1], [], [ovs-vsctl: cannot modify read-only column name in table Interface
|
||||||
|
], [OVS_VSCTL_CLEANUP])
|
||||||
|
AT_CHECK([RUN_OVS_VSCTL([set port br1 name br2])],
|
||||||
|
[1], [], [ovs-vsctl: cannot modify read-only column name in table Port
|
||||||
|
], [OVS_VSCTL_CLEANUP])
|
||||||
|
AT_CHECK([RUN_OVS_VSCTL([remove b br1 name br1])],
|
||||||
|
[1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge
|
||||||
|
], [OVS_VSCTL_CLEANUP])
|
||||||
|
AT_CHECK([RUN_OVS_VSCTL([clear b br1 name])],
|
||||||
|
[1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge
|
||||||
|
], [OVS_VSCTL_CLEANUP])
|
||||||
OVS_VSCTL_CLEANUP
|
OVS_VSCTL_CLEANUP
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
@ -111,6 +111,15 @@ gc_schema () {
|
|||||||
"isRoot": false}}}
|
"isRoot": false}}}
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
immutable_schema () {
|
||||||
|
cat <<'EOF'
|
||||||
|
{"name": "immutable",
|
||||||
|
"tables": {
|
||||||
|
"a": {
|
||||||
|
"columns": {"i": {"type": "integer", "mutable": false}}}}}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
]
|
]
|
||||||
m4_divert_pop([PREPARE_TESTS])
|
m4_divert_pop([PREPARE_TESTS])
|
||||||
|
|
||||||
@ -908,6 +917,40 @@ OVSDB_CHECK_EXECUTION([weak references],
|
|||||||
[{"rows":[{"_uuid":["uuid","<3>"],"b":2,"b2a":["set",[]]},{"_uuid":["uuid","<4>"],"b":3,"b2a":["set",[]]}]}]
|
[{"rows":[{"_uuid":["uuid","<3>"],"b":2,"b2a":["set",[]]},{"_uuid":["uuid","<4>"],"b":3,"b2a":["set",[]]}]}]
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
OVSDB_CHECK_EXECUTION([immutable columns],
|
||||||
|
[immutable_schema],
|
||||||
|
[[[["immutable",
|
||||||
|
{"op": "insert",
|
||||||
|
"table": "a",
|
||||||
|
"row": {"i": 5},
|
||||||
|
"uuid-name": "row1"}]]],
|
||||||
|
[[["immutable",
|
||||||
|
{"op": "update",
|
||||||
|
"table": "a",
|
||||||
|
"row": {"i": 10},
|
||||||
|
"where": []}]]],
|
||||||
|
[[["immutable",
|
||||||
|
{"op": "update",
|
||||||
|
"table": "a",
|
||||||
|
"row": {"i": 5},
|
||||||
|
"where": []}]]],
|
||||||
|
[[["immutable",
|
||||||
|
{"op": "mutate",
|
||||||
|
"table": "a",
|
||||||
|
"where": [],
|
||||||
|
"mutations": [["i", "-=", 5]]}]]],
|
||||||
|
[[["immutable",
|
||||||
|
{"op": "mutate",
|
||||||
|
"table": "a",
|
||||||
|
"where": [],
|
||||||
|
"mutations": [["i", "*=", 1]]}]]]],
|
||||||
|
[[[{"uuid":["uuid","<0>"]}]
|
||||||
|
[{"details":"Cannot update immutable column i in table a.","error":"constraint violation","syntax":"{\"op\":\"update\",\"row\":{\"i\":10},\"table\":\"a\",\"where\":[]}"}]
|
||||||
|
[{"details":"Cannot update immutable column i in table a.","error":"constraint violation","syntax":"{\"op\":\"update\",\"row\":{\"i\":5},\"table\":\"a\",\"where\":[]}"}]
|
||||||
|
[{"details":"Cannot mutate immutable column i in table a.","error":"constraint violation","syntax":"[\"i\",\"-=\",5]"}]
|
||||||
|
[{"details":"Cannot mutate immutable column i in table a.","error":"constraint violation","syntax":"[\"i\",\"*=\",1]"}]
|
||||||
|
]])
|
||||||
|
|
||||||
OVSDB_CHECK_EXECUTION([garbage collection],
|
OVSDB_CHECK_EXECUTION([garbage collection],
|
||||||
[gc_schema],
|
[gc_schema],
|
||||||
[dnl Check that inserting a row without any references is a no-op.
|
[dnl Check that inserting a row without any references is a no-op.
|
||||||
|
@ -99,6 +99,18 @@ test-ovsdb: syntax "["u","delete",["uuid","9179ca6d-6d65-400a-b455-3ad92783a099"
|
|||||||
]])
|
]])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
AT_SETUP([disallowed mutations on immutable columns])
|
||||||
|
AT_KEYWORDS([ovsdb negative mutation])
|
||||||
|
AT_CHECK([[test-ovsdb parse-mutations \
|
||||||
|
'{"columns":
|
||||||
|
{"i": {"type": "integer", "mutable": false}}}' \
|
||||||
|
'[["i", "+=", 1]]'
|
||||||
|
]],
|
||||||
|
[1], [],
|
||||||
|
[[test-ovsdb: syntax "["i","+=",1]": constraint violation: Cannot mutate immutable column i in table mytable.
|
||||||
|
]])
|
||||||
|
AT_CLEANUP
|
||||||
|
|
||||||
OVSDB_CHECK_POSITIVE([mutations on sets],
|
OVSDB_CHECK_POSITIVE([mutations on sets],
|
||||||
[[parse-mutations \
|
[[parse-mutations \
|
||||||
'{"columns":
|
'{"columns":
|
||||||
|
@ -2763,7 +2763,7 @@ error:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static const struct ovsdb_idl_column *
|
||||||
pre_parse_column_key_value(struct vsctl_context *ctx,
|
pre_parse_column_key_value(struct vsctl_context *ctx,
|
||||||
const char *arg,
|
const char *arg,
|
||||||
const struct vsctl_table_class *table)
|
const struct vsctl_table_class *table)
|
||||||
@ -2780,6 +2780,18 @@ pre_parse_column_key_value(struct vsctl_context *ctx,
|
|||||||
|
|
||||||
pre_get_column(ctx, table, column_name, &column);
|
pre_get_column(ctx, table, column_name, &column);
|
||||||
free(column_name);
|
free(column_name);
|
||||||
|
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_mutable(const struct vsctl_table_class *table,
|
||||||
|
const struct ovsdb_idl_column *column)
|
||||||
|
{
|
||||||
|
if (!column->mutable) {
|
||||||
|
vsctl_fatal("cannot modify read-only column %s in table %s",
|
||||||
|
column->name, table->class->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3112,7 +3124,10 @@ pre_cmd_set(struct vsctl_context *ctx)
|
|||||||
|
|
||||||
table = pre_get_table(ctx, table_name);
|
table = pre_get_table(ctx, table_name);
|
||||||
for (i = 3; i < ctx->argc; i++) {
|
for (i = 3; i < ctx->argc; i++) {
|
||||||
pre_parse_column_key_value(ctx, ctx->argv[i], table);
|
const struct ovsdb_idl_column *column;
|
||||||
|
|
||||||
|
column = pre_parse_column_key_value(ctx, ctx->argv[i], table);
|
||||||
|
check_mutable(table, column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3195,6 +3210,7 @@ pre_cmd_add(struct vsctl_context *ctx)
|
|||||||
|
|
||||||
table = pre_get_table(ctx, table_name);
|
table = pre_get_table(ctx, table_name);
|
||||||
pre_get_column(ctx, table, column_name, &column);
|
pre_get_column(ctx, table, column_name, &column);
|
||||||
|
check_mutable(table, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3251,6 +3267,7 @@ pre_cmd_remove(struct vsctl_context *ctx)
|
|||||||
|
|
||||||
table = pre_get_table(ctx, table_name);
|
table = pre_get_table(ctx, table_name);
|
||||||
pre_get_column(ctx, table, column_name, &column);
|
pre_get_column(ctx, table, column_name, &column);
|
||||||
|
check_mutable(table, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3316,6 +3333,7 @@ pre_cmd_clear(struct vsctl_context *ctx)
|
|||||||
const struct ovsdb_idl_column *column;
|
const struct ovsdb_idl_column *column;
|
||||||
|
|
||||||
pre_get_column(ctx, table, ctx->argv[i], &column);
|
pre_get_column(ctx, table, ctx->argv[i], &column);
|
||||||
|
check_mutable(table, column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user