[ovs-dev] [PATCH] ovs-vsctl: Allow modifying "immutable" columns if we just created the row.

Ben Pfaff blp at nicira.com
Fri Sep 26 23:01:13 UTC 2014


OVSDB has the concept of "immutable" columns, which are columns whose
values are fixed once a row is inserted.  Until now, ovs-vsctl has not
allowed these columns to be modified at all.  However, this is a little too
strict, because these columns can be set to any value at the time that the
row is inserted.  This commit relaxes the ovs-vsctl requirement, then, to
allow an immutable column's value to be modified if its row has been
inserted within this transaction.

Requested-by: Mukesh Hira <mhira at vmware.com>
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 NEWS                  |    2 ++
 lib/ovsdb-idl.c       |   17 ++++++++++++++++-
 lib/ovsdb-idl.h       |    4 +++-
 tests/ovs-vsctl.at    |    8 +++++---
 utilities/ovs-vsctl.c |   18 ++++++++----------
 5 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/NEWS b/NEWS
index a8bd45b..8f83dbe 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,8 @@ Post-v2.3.0
      it in OpenSSL.
    - ovsdb-server: New OVSDB protocol extension allows inequality tests on
      "optional scalar" columns.  See ovsdb-server(1) for details.
+   - ovs-vsctl now permits immutable columns in a new row to be modified in
+     the same transaction that creates the row.
    - test-controller has been renamed ovs-testcontroller at request of users
      who find it useful for testing basic OpenFlow setups.  It is still not
      a necessary or desirable part of most Open vSwitch deployments.
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index 5c4d93b..4f6a2ed 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1196,6 +1196,21 @@ ovsdb_idl_get(const struct ovsdb_idl_row *row,
     return ovsdb_idl_read(row, column);
 }
 
+/* Returns true if the field represented by 'column' in 'row' may be modified,
+ * false if it is immutable.
+ *
+ * Normally, whether a field is mutable is controlled by its column's schema.
+ * However, an immutable column can be set to any initial value at the time of
+ * insertion, so if 'row' is a new row (one that is being added as part of the
+ * current transaction, supposing that a transaction is in progress) then even
+ * its "immutable" fields are actually mutable. */
+bool
+ovsdb_idl_is_mutable(const struct ovsdb_idl_row *row,
+                     const struct ovsdb_idl_column *column)
+{
+    return column->mutable || (row->new && !row->old);
+}
+
 /* Returns false if 'row' was obtained from the IDL, true if it was initialized
  * to all-zero-bits by some other entity.  If 'row' was set up some other way
  * then the return value is indeterminate. */
diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
index cb0ad11..26aa2a3 100644
--- a/lib/ovsdb-idl.h
+++ b/lib/ovsdb-idl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -115,6 +115,8 @@ const struct ovsdb_datum *ovsdb_idl_get(const struct ovsdb_idl_row *,
                                         const struct ovsdb_idl_column *,
                                         enum ovsdb_atomic_type key_type,
                                         enum ovsdb_atomic_type value_type);
+bool ovsdb_idl_is_mutable(const struct ovsdb_idl_row *,
+                          const struct ovsdb_idl_column *);
 
 bool ovsdb_idl_row_is_synthetic(const struct ovsdb_idl_row *);
 
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index 864c382..2f83566 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -632,7 +632,8 @@ AT_SETUP([database commands -- positive checks])
 AT_KEYWORDS([ovs-vsctl])
 OVS_VSCTL_SETUP
 AT_CHECK(
-  [RUN_OVS_VSCTL_TOGETHER([--id=@br0 create bridge name=br0],
+  [RUN_OVS_VSCTL_TOGETHER([--id=@br0 create bridge name=br123],
+                          [set b br123 name=br0],
                           [set o . bridges=@br0])],
   [0], [stdout], [], [OVS_VSCTL_CLEANUP])
 cp stdout out1
@@ -642,6 +643,7 @@ cp stdout out2
 AT_CHECK([${PERL} $srcdir/uuidfilt.pl out1 out2], [0],
   [[<0>
 
+
 _uuid               : <0>
 controller          : []
 datapath_id         : []
@@ -847,10 +849,10 @@ AT_CHECK([RUN_OVS_VSCTL([destroy bridge br2])],
 AT_CHECK([RUN_OVS_VSCTL([add in 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])],
+AT_CHECK([RUN_OVS_VSCTL([set port br0 name=br2])],
   [1], [], [ovs-vsctl: cannot modify read-only column name in table Port
 ], [OVS_VSCTL_CLEANUP])
-AT_CHECK([RUN_OVS_VSCTL([remove bridge br1 name br1])],
+AT_CHECK([RUN_OVS_VSCTL([remove bridge br0 name br1])],
   [1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge
 ], [OVS_VSCTL_CLEANUP])
 AT_CHECK([RUN_OVS_VSCTL([remove bridge br1 flood-vlans true])],
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index 818184a..270d9bf 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -2987,12 +2987,12 @@ pre_parse_column_key_value(struct vsctl_context *ctx,
 }
 
 static void
-check_mutable(const struct vsctl_table_class *table,
+check_mutable(const struct ovsdb_idl_row *row,
               const struct ovsdb_idl_column *column)
 {
-    if (!column->mutable) {
+    if (!ovsdb_idl_is_mutable(row, column)) {
         vsctl_fatal("cannot modify read-only column %s in table %s",
-                    column->name, table->class->name);
+                    column->name, row->table->class->name);
     }
 }
 
@@ -3339,10 +3339,7 @@ pre_cmd_set(struct vsctl_context *ctx)
 
     table = pre_get_table(ctx, table_name);
     for (i = 3; i < ctx->argc; i++) {
-        const struct ovsdb_idl_column *column;
-
-        column = pre_parse_column_key_value(ctx, ctx->argv[i], table);
-        check_mutable(table, column);
+        pre_parse_column_key_value(ctx, ctx->argv[i], table);
     }
 }
 
@@ -3361,6 +3358,7 @@ set_column(const struct vsctl_table_class *table,
     if (!value_string) {
         vsctl_fatal("%s: missing value", arg);
     }
+    check_mutable(row, column);
 
     if (key_string) {
         union ovsdb_atom key, value;
@@ -3431,7 +3429,6 @@ pre_cmd_add(struct vsctl_context *ctx)
 
     table = pre_get_table(ctx, table_name);
     pre_get_column(ctx, table, column_name, &column);
-    check_mutable(table, column);
 }
 
 static void
@@ -3454,6 +3451,7 @@ cmd_add(struct vsctl_context *ctx)
     if (!row) {
         return;
     }
+    check_mutable(row, column);
 
     type = &column->type;
     ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
@@ -3492,7 +3490,6 @@ pre_cmd_remove(struct vsctl_context *ctx)
 
     table = pre_get_table(ctx, table_name);
     pre_get_column(ctx, table, column_name, &column);
-    check_mutable(table, column);
 }
 
 static void
@@ -3515,6 +3512,7 @@ cmd_remove(struct vsctl_context *ctx)
     if (!row) {
         return;
     }
+    check_mutable(row, column);
 
     type = &column->type;
     ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
@@ -3566,7 +3564,6 @@ pre_cmd_clear(struct vsctl_context *ctx)
         const struct ovsdb_idl_column *column;
 
         pre_get_column(ctx, table, ctx->argv[i], &column);
-        check_mutable(table, column);
     }
 }
 
@@ -3592,6 +3589,7 @@ cmd_clear(struct vsctl_context *ctx)
         struct ovsdb_datum datum;
 
         die_if_error(get_column(table, ctx->argv[i], &column));
+        check_mutable(row, column);
 
         type = &column->type;
         if (type->n_min > 0) {
-- 
1.7.10.4




More information about the dev mailing list