Fixing checkstyle issues on Ashwin's initial POC code for the new Schema design. 17/5817/2
authorMadhu Venugopal <mavenugo@gmail.com>
Mon, 31 Mar 2014 23:53:27 +0000 (16:53 -0700)
committerMadhu Venugopal <mavenugo@gmail.com>
Mon, 31 Mar 2014 23:53:27 +0000 (16:53 -0700)
Change-Id: I1c97d60c272e47be165f6f562db7ea2122e2d438
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
31 files changed:
ovsdb/pom.xml
ovsdb/src/main/java/org/opendaylight/ovsdb/Insert.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/OpenVswitch.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/Column.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/ColumnSchema.java
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/DatabaseSchema.java
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/Table.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/TableSchema.java
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/jsonrpc/JsonUtils.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/message/OvsdbRPC.java
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/message/operations/ConditionalOperation.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/message/operations/MutateOperation.java
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/message/operations/Operation.java
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/BaseType.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/ColumnSchema.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/ColumnType.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/DatabaseSchema.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/TableSchema.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/temp/Reference.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/temp/SchemaObjs.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/lib/notation/Condition.java
ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/ConnectionService.java
ovsdb/src/test/java/org/opendaylight/ovsdb/OpenVswitchTestIT.java [new file with mode: 0644]
ovsdb/src/test/java/org/opendaylight/ovsdb/OpenVswitchTestITTyped.java [new file with mode: 0644]
ovsdb/src/test/java/org/opendaylight/ovsdb/lib/message/OVSDBNettyFactoryIT.java
ovsdb/src/test/java/org/opendaylight/ovsdb/lib/meta/OvsDBSchemaTest.java [new file with mode: 0644]
ovsdb/src/test/java/org/opendaylight/ovsdb/lib/meta/test_schema.json [new file with mode: 0644]
ovsdb/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestBase.java
ovsdb/src/test/resources/logback.xml [new file with mode: 0644]
ovsdb/src/test/resources/org/opendaylight/ovsdb/lib/message/integration-test.properties
ovsdb/src/test/resources/org/opendaylight/ovsdb/lib/meta/test_schema.json [new file with mode: 0644]

index 5539b3845d25f89db59803d1ae73d123c2bee679..c62f4327cf5ddbe5b1ca930e5405761fbccb6f73 100755 (executable)
           <version>2.1</version>
           <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+        </dependency>
     </dependencies>
 
     <profiles>
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/Insert.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/Insert.java
new file mode 100644 (file)
index 0000000..e9770d8
--- /dev/null
@@ -0,0 +1,72 @@
+package org.opendaylight.ovsdb;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.Maps;
+import org.opendaylight.ovsdb.lib.message.operations.Operation;
+import org.opendaylight.ovsdb.lib.meta.ColumnSchema;
+import org.opendaylight.ovsdb.lib.meta.TableSchema;
+
+import java.util.Map;
+
+/**
+ * @author Ashwin Raveendran
+ */
+public class Insert<E extends TableSchema<E>> extends Operation<E> {
+
+    public static final String INSERT = "insert";
+
+    String uuid;
+
+    @JsonProperty("uuid-name")
+    private String uuidName;
+
+    private Map<String, Object> row = Maps.newHashMap();
+
+    public Insert on(TableSchema schema){
+        this.setTableSchema(schema);
+        return this;
+    }
+
+    public Insert withId(String name) {
+        this.uuidName = name;
+        this.setOp(INSERT);
+        return this;
+    }
+
+
+    public Insert(TableSchema<E> schema) {
+        super(schema, INSERT);
+    }
+
+    public <D, C extends TableSchema<C>> Insert<E> value(ColumnSchema<C, D> columnSchema, D value) {
+        row.put(columnSchema.getName(), value);
+        return this;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    public String getUuidName() {
+        return uuidName;
+    }
+
+    public void setUuidName(String uuidName) {
+        this.uuidName = uuidName;
+    }
+
+    public Map<String, Object> getRow() {
+        return row;
+    }
+
+    public void setRow(Map<String, Object> row) {
+        this.row = row;
+    }
+
+
+
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/OpenVswitch.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/OpenVswitch.java
new file mode 100644 (file)
index 0000000..b38efc4
--- /dev/null
@@ -0,0 +1,270 @@
+package org.opendaylight.ovsdb;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.ovsdb.lib.message.OvsdbRPC;
+import org.opendaylight.ovsdb.lib.message.TransactBuilder;
+import org.opendaylight.ovsdb.lib.message.operations.ConditionalOperation;
+import org.opendaylight.ovsdb.lib.message.operations.Operation;
+import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
+import org.opendaylight.ovsdb.lib.meta.ColumnSchema;
+import org.opendaylight.ovsdb.lib.meta.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.meta.TableSchema;
+import org.opendaylight.ovsdb.lib.notation.Condition;
+import org.opendaylight.ovsdb.lib.notation.Function;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * @author araveendrann
+ */
+public class OpenVswitch {
+
+    ExecutorService executorService;
+    String schemaName;
+    OvsdbRPC rpc;
+    volatile DatabaseSchema schema;
+    Queue<Throwable> exceptions;
+
+    public OpenVswitch(OvsdbRPC rpc, ExecutorService executorService) {
+        this.rpc = rpc;
+        this.executorService = executorService;
+    }
+
+    public OpenVswitch() {
+    }
+
+
+    public void populateSchemaFromDevice() {
+        final ListenableFuture<JsonNode> fOfSchema = rpc.get_schema(Lists.newArrayList(DatabaseSchema.OPEN_VSWITCH_SCHEMA_NAME));
+        fOfSchema.addListener(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    JsonNode jsonNode = fOfSchema.get();
+                    schema =  DatabaseSchema.fromJson(jsonNode);
+
+                } catch (Exception e) {
+                    exceptions.add(e);
+                }
+            }
+        }, executorService);
+    }
+
+    public Transaction transact(){
+        return new Transaction(this);
+    }
+
+    public ListenableFuture<List<OperationResult>> transact(List<Operation> operations) {
+
+        //todo, we may not need transactionbuilder if we can have JSON objects
+        TransactBuilder builder = new TransactBuilder();
+        for (Operation o : operations) {
+           builder.addOperation(o);
+        }
+
+        ListenableFuture<List<OperationResult>> transact = rpc.transact(builder);
+        return transact;
+    }
+
+    public boolean isReady(long timeout) {
+        //todo implement timeout
+        return null != schema;
+    }
+
+    public DatabaseSchema schema() {
+        return schema;
+    }
+
+
+    public static class Transaction {
+
+        private  DatabaseSchema eDatabaseSchema;
+        OpenVswitch ovs;
+        ArrayList<Operation> operations = Lists.newArrayList();
+
+        public Transaction(OpenVswitch ovs) {
+            this.ovs = ovs;
+        }
+
+        public Transaction(DatabaseSchema eDatabaseSchema) {
+            this.eDatabaseSchema = eDatabaseSchema;
+        }
+
+        public Transaction add(Operation operation) {
+            operations.add(operation);
+            return this;
+        }
+
+        public List<Operation> build() {
+            return operations;
+        }
+
+        public ListenableFuture<List<OperationResult>> execute() {
+            return ovs.transact(operations);
+        }
+    }
+
+    public static class Update<E extends TableSchema<E>> extends Operation<E> implements ConditionalOperation {
+
+        Map<String, Object> row = Maps.newHashMap();
+        String uuid;
+        //Where where;
+        List<Condition> where = Lists.newArrayList();
+
+        private String uuidName;
+
+        public Update(TableSchema<E> schema) {
+            super(schema, "update");
+        }
+
+        public Update<E> on(TableSchema schema){
+            return this;
+        }
+
+        public <T extends TableSchema<T>, D> Update<E> set(ColumnSchema<T, D> columnSchema, D value) {
+            columnSchema.validate(value);
+            this.row.put(columnSchema.getName(), value);
+            return this;
+        }
+
+        public Where where(Condition condition) {
+            return new Where(this);
+        }
+
+        public String getUuid() {
+            return uuid;
+        }
+
+        public void setUuid(String uuid) {
+            this.uuid = uuid;
+        }
+
+        public String getUuidName() {
+            return uuidName;
+        }
+
+        public void setUuidName(String uuidName) {
+            this.uuidName = uuidName;
+        }
+
+        public Map<String, Object> getRow() {
+            return row;
+        }
+
+        public void setRow(Map<String, Object> row) {
+            this.row = row;
+        }
+
+        @Override
+        public void addCondition(Condition condition) {
+            this.where.add(condition);
+        }
+
+        public List<Condition> getWhere() {
+            return where;
+        }
+
+        public void setWhere(List<Condition> where) {
+            this.where = where;
+        }
+    }
+
+
+    public static class Where {
+
+        @JsonIgnore
+        ConditionalOperation operation;
+
+        public Where() { }  public Where(ConditionalOperation operation) {
+            this.operation = operation;
+        }
+
+        public Where condition(Condition condition) {
+            operation.addCondition(condition);
+            return this;
+        }
+
+        public Where condition(ColumnSchema column, Function function, Object value) {
+            this.condition(new Condition(column.getName(), function, value));
+            return this;
+        }
+
+        public Where and(ColumnSchema column, Function function, Object value) {
+            condition(column, function, value);
+            return this;
+        }
+
+        public Where and(Condition condition) {
+           condition(condition);
+            return this;
+        }
+
+        public Operation operation() {
+            return (Operation) this.operation;
+        }
+
+    }
+
+
+    public static class Operations {
+        public static Operations op = new Operations();
+
+        public <E extends TableSchema<E>> Insert<E> insert(TableSchema<E> schema) {
+            return new Insert<>(schema);
+        }
+
+        public  <E extends TableSchema<E>> Update<E> update(TableSchema<E> schema) {
+            return new Update<>(schema);
+        }
+    }
+
+    public ExecutorService getExecutorService() {
+        return executorService;
+    }
+
+    public void setExecutorService(ExecutorService executorService) {
+        this.executorService = executorService;
+    }
+
+    public String getSchemaName() {
+        return schemaName;
+    }
+
+    public void setSchemaName(String schemaName) {
+        this.schemaName = schemaName;
+    }
+
+    public OvsdbRPC getRpc() {
+        return rpc;
+    }
+
+    public void setRpc(OvsdbRPC rpc) {
+        this.rpc = rpc;
+    }
+
+    public DatabaseSchema getSchema() {
+        return schema;
+    }
+
+    public void setSchema(DatabaseSchema schema) {
+        this.schema = schema;
+    }
+
+    public Queue<Throwable> getExceptions() {
+        return exceptions;
+    }
+
+    public void setExceptions(Queue<Throwable> exceptions) {
+        this.exceptions = exceptions;
+    }
+
+
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/Column.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/Column.java
new file mode 100644 (file)
index 0000000..cd910d0
--- /dev/null
@@ -0,0 +1,8 @@
+package org.opendaylight.ovsdb.lib.database;
+
+/**
+ * @author araveendrann
+ */
+public class Column<E extends Table> {
+    ColumnSchema schema;
+}
index 2067eab074dd7e5bcf812853432cc44d86c82fee..5684675b64b599e4022f51a17bc7e37a579961a1 100644 (file)
@@ -1,35 +1,71 @@
-/*
- * [[ Authors will Fill in the Copyright header ]]
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Authors : Brent Salisbury, Evan Zeller
- */
+/*\r
+ * [[ Authors will Fill in the Copyright header ]]\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Authors : Brent Salisbury, Evan Zeller\r
+ */\r
 package org.opendaylight.ovsdb.lib.database;\r
 \r
 import com.fasterxml.jackson.annotation.JsonProperty;\r
+import org.opendaylight.ovsdb.lib.notation.Condition;\r
+import org.opendaylight.ovsdb.lib.notation.Function;\r
 \r
 public class ColumnSchema {\r
+\r
+    String name;\r
+\r
     @JsonProperty("type")\r
     private OvsdbType type;\r
+\r
     @JsonProperty("ephemeral")\r
     private Boolean ephemeral;\r
+\r
     @JsonProperty("mutable")\r
     private Boolean mutable;\r
+\r
     public OvsdbType getType() {\r
         return type;\r
     }\r
+\r
     public Boolean getEphemeral() {\r
         return ephemeral;\r
     }\r
+\r
     public Boolean getMutable() {\r
         return mutable;\r
     }\r
+\r
+    public String getName() {\r
+        return name;\r
+    }\r
+\r
+    public void setName(String name) {\r
+        this.name = name;\r
+    }\r
+\r
+    public Condition opEqual(String some) {\r
+        return new Condition(this.getName(), Function.EQUALS, some);\r
+    }\r
+\r
+    public Condition opGreaterThan(Object val) {\r
+        return new Condition(this.getName(), Function.GREATER_THAN, val);\r
+    }\r
+\r
+    public Condition opLesserThan(int val) {\r
+        return new Condition(this.getName(), Function.GREATER_THAN, val);\r
+    }\r
+\r
+    public Condition opLesserThanOrEquals(Object val) {\r
+        return new Condition(this.getName(), Function.LESS_THAN_OR_EQUALS, val);\r
+    }\r
+\r
     @Override\r
     public String toString() {\r
-        return "ColumnSchema [type=" + type + ", ephemeral=" + ephemeral\r
+        return "ColumnType [type=" + type + ", ephemeral=" + ephemeral\r
                 + ", mutable=" + mutable + "]";\r
     }\r
+\r
 }\r
index 5ddd41affba2cd3cb4c8bc1e303a7582a74f8640..ce2620ea08599dc160397f134e8a7adf09b6bca9 100644 (file)
@@ -1,12 +1,12 @@
-/*
- * [[ Authors will Fill in the Copyright header ]]
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Authors : Brent Salisbury, Evan Zeller
- */
+/*\r
+ * [[ Authors will Fill in the Copyright header ]]\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Authors : Brent Salisbury, Evan Zeller\r
+ */\r
 package org.opendaylight.ovsdb.lib.database;\r
 \r
 import java.util.Map;\r
@@ -16,24 +16,36 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class DatabaseSchema {\r
     @JsonProperty("name")\r
     private String name;\r
+\r
     @JsonProperty("version")\r
     private String version;\r
+\r
     @JsonProperty("cksum")\r
     private String cksum;\r
+\r
     @JsonProperty("tables")\r
     private Map<String, TableSchema> tables;\r
+\r
     public String getName() {\r
         return name;\r
     }\r
+\r
     public String getVersion() {\r
         return version;\r
     }\r
+\r
     public String getCksum() {\r
         return cksum;\r
     }\r
+\r
     public Map<String, TableSchema> getTables() {\r
         return tables;\r
     }\r
+\r
+    public TableSchema getTable(String tableName) {\r
+       return tables.get(tableName);\r
+    }\r
+\r
     @Override\r
     public String toString() {\r
         return "DatabaseSchema [name=" + name + ", version=" + version\r
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/Table.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/database/Table.java
new file mode 100644 (file)
index 0000000..b085568
--- /dev/null
@@ -0,0 +1,10 @@
+package org.opendaylight.ovsdb.lib.database;
+
+/**
+ * @author araveendrann
+ */
+public class Table<E extends Table> {
+    TableSchema schema;
+
+
+}
index 7efc02a07ed9918e2857ea7d5ef95008b99bc981..cc6a735be37d29acc2eaef5bdd7f18e268924a8a 100644 (file)
@@ -1,12 +1,12 @@
-/*
- * [[ Authors will Fill in the Copyright header ]]
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- *
- * Authors : Brent Salisbury, Evan Zeller
- */
+/*\r
+ * [[ Authors will Fill in the Copyright header ]]\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Authors : Brent Salisbury, Evan Zeller\r
+ */\r
 package org.opendaylight.ovsdb.lib.database;\r
 \r
 import java.util.Map;\r
@@ -14,19 +14,27 @@ import java.util.Map;
 import com.fasterxml.jackson.annotation.JsonProperty;\r
 \r
 public class TableSchema {\r
+\r
     @JsonProperty("columns")\r
     private Map<String, ColumnSchema> columns;\r
+\r
     @JsonProperty("maxRows")\r
     private Integer maxRows;\r
+\r
     @JsonProperty("isRoot")\r
     private Boolean isRoot;\r
+\r
     @JsonProperty("indexes")\r
     private Object indexes;\r
 \r
-    public Map<String, ColumnSchema> getColumns(){\r
+    public Map<String, ColumnSchema> getColumns() {\r
         return this.columns;\r
     }\r
 \r
+    public ColumnSchema getColumn(String columnName) {\r
+        return this.columns.get(columnName);\r
+    }\r
+\r
     public Integer getMaxRows() {\r
         return maxRows;\r
     }\r
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/jsonrpc/JsonUtils.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/jsonrpc/JsonUtils.java
new file mode 100644 (file)
index 0000000..9fa0f38
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.ovsdb.lib.jsonrpc;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+/**
+ * @author araveendrann
+ */
+public class JsonUtils {
+
+    static ObjectMapper mapper = new ObjectMapper();
+
+    static ObjectWriter prettyWriter = mapper.writerWithDefaultPrettyPrinter();
+
+    public static String prettyString(Object jsonNode){
+        try {
+            return prettyWriter.writeValueAsString(jsonNode);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
index 3e2ac3250cfca1f9ef306a3f4d6e9b8e13a8c7eb..68475e9715f76dc2c7c561d2f03175d06103b8ba 100644 (file)
@@ -11,16 +11,17 @@ package org.opendaylight.ovsdb.lib.message;
 
 import java.util.List;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.util.concurrent.ListenableFuture;
 
 import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.ovsdb.lib.database.DatabaseSchema;
 import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
 
 public interface OvsdbRPC {
     public static final String REGISTER_CALLBACK_METHOD = "registerCallback";
 
-    public ListenableFuture<DatabaseSchema> get_schema(List<String> db_names);
+    //public ListenableFuture<DatabaseSchema> get_schema(List<String> db_names);
+    public ListenableFuture<JsonNode> get_schema(List<String> db_names);
 
     public ListenableFuture<List<String>> echo();
 
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/message/operations/ConditionalOperation.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/message/operations/ConditionalOperation.java
new file mode 100644 (file)
index 0000000..feabe28
--- /dev/null
@@ -0,0 +1,12 @@
+package org.opendaylight.ovsdb.lib.message.operations;
+
+import org.opendaylight.ovsdb.lib.notation.Condition;
+
+/**
+ * Represents an Operation type that accepts acondition, for e.g Update, Select etc
+ * @author araveendrann
+ */
+public interface ConditionalOperation {
+
+    public void addCondition(Condition condition);
+}
index 72ab481da2dffe8c86f129f661d31f81de79a897..31b7c3c0358214140c43180cdf801f156a216cb4 100644 (file)
@@ -20,31 +20,38 @@ public class MutateOperation extends Operation {
     List<Mutation> mutations;
 
     public MutateOperation(String table, List<Condition> where,
-            List<Mutation> mutations) {
+                           List<Mutation> mutations) {
         super();
         super.setOp("mutate");
         this.table = table;
         this.where = where;
         this.mutations = mutations;
     }
+
     public String getTable() {
         return table;
     }
+
     public void setTable(String table) {
         this.table = table;
     }
+
     public List<Condition> getWhere() {
         return where;
     }
+
     public void setWhere(List<Condition> where) {
         this.where = where;
     }
+
     public List<Mutation> getMutations() {
         return mutations;
     }
+
     public void setMutations(List<Mutation> mutations) {
         this.mutations = mutations;
     }
+
     @Override
     public String toString() {
         return "MutateOperation [table=" + table + ", where=" + where
index 856e74f94cd1a1f46e7853c2d59f668a674fbd9c..1330bb94c4d77ce0d7d1fa96c3102163e98b3597 100644 (file)
@@ -5,18 +5,39 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  *
- * Authors : Madhu Venugopal
+ * Authors : Madhu Venugopal, Ashwin Raveendran
  */
 package org.opendaylight.ovsdb.lib.message.operations;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.opendaylight.ovsdb.lib.meta.TableSchema;
+
+public abstract class Operation<E extends TableSchema<E>> {
+
+    @JsonIgnore
+    private TableSchema<E> tableSchema;
 
-public abstract class Operation {
     private String op;
+
     @JsonIgnore
+    //todo(Ashwin): remove this
     // Just a simple way to retain the result of a transact operation which the client can refer to.
     private OperationResult result;
 
+
+    protected Operation() {
+    }
+
+    protected Operation(TableSchema<E> tableSchema) {
+        this.tableSchema = tableSchema;
+    }
+
+    public Operation(TableSchema<E> schema, String operation) {
+        this.tableSchema = schema;
+        this.op = operation;
+    }
+
     public String getOp() {
         return op;
     }
@@ -33,8 +54,22 @@ public abstract class Operation {
         this.result = result;
     }
 
+    public TableSchema<E> getTableSchema() {
+        return tableSchema;
+    }
+
+    public void setTableSchema(TableSchema<E> tableSchema) {
+        this.tableSchema = tableSchema;
+    }
+
+    @JsonProperty
+    public String getTable() {
+        return tableSchema.getName();
+    }
+
     @Override
     public String toString() {
         return "Operation [op=" + op + ", result=" + result + "]";
     }
+
 }
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/BaseType.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/BaseType.java
new file mode 100644 (file)
index 0000000..b4e036f
--- /dev/null
@@ -0,0 +1,309 @@
+package org.opendaylight.ovsdb.lib.meta;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Sets;
+
+import java.util.Set;
+
+/**
+ * @author araveendrann
+ */
+public abstract class BaseType<E extends BaseType<E>> {
+
+    private static BaseType[] types = new BaseType[]{
+            new StringBaseType(),
+            new IntegerBaseType(),
+            new RealBaseType(),
+            new BooleanBaseType(),
+            new UuidBaseType(),
+    };
+
+    public static BaseType fromJson(JsonNode json, String keyorval) {
+        BaseType baseType = null;
+        if (json.isValueNode()) {
+            for (BaseType baseTypeFactory : types) {
+                String type = json.asText().trim();
+                baseType = baseTypeFactory.fromString(type);
+                if (baseType != null) {
+                    break;
+                }
+            }
+        } else {
+            if (!json.has(keyorval)) {
+                throw new RuntimeException("Not a type");
+            }
+
+            for (BaseType baseTypeFactory : types) {
+                baseType = baseTypeFactory.fromJsonNode(json.get(keyorval), keyorval);
+                if (baseType != null) {
+                    break;
+                }
+            }
+        }
+        return baseType;
+    }
+
+    protected abstract E fromString(String type);
+
+    protected abstract void getConstraints(E baseType, JsonNode type);
+
+    protected E fromJsonNode(JsonNode type, String keyorval) {
+
+        E baseType = null;
+
+        //json like  "string"
+        if (type.isTextual()) {
+            baseType = fromString(type.asText());
+            if (baseType != null) {
+                return baseType;
+            }
+        }
+
+        //json like  {"type" : "string", "enum": ["set", ["access", "native-tagged"]]}" for key or value
+        if (type.isObject() && type.has("type")) {
+            baseType = fromString(type.get("type").asText());
+            if (baseType != null) {
+                getConstraints(baseType, type);
+            }
+        }
+
+        return baseType;
+    }
+
+    public static class IntegerBaseType extends BaseType<IntegerBaseType> {
+        long min = Long.MIN_VALUE;
+        long max = Long.MAX_VALUE;
+        Set<Integer> enums;
+
+        public IntegerBaseType fromString(String typeString) {
+            return "integer".equals(typeString) ? new IntegerBaseType() : null;
+        }
+
+        @Override
+        protected void getConstraints(IntegerBaseType baseType, JsonNode type) {
+
+            JsonNode node = null;
+
+            if ((node = type.get("maxInteger")) != null) {
+                baseType.setMax(node.asLong());
+            }
+
+            if ((node = type.get("minInteger")) != null) {
+                baseType.setMin(node.asLong());
+            }
+
+            populateEnum(type);
+        }
+
+        private void populateEnum(JsonNode node) {
+            if (node.has("enum")) {
+                Set<Long> s = Sets.newHashSet();
+                JsonNode anEnum = node.get("enum").get(1);
+                for (JsonNode n : anEnum) {
+                    s.add(n.asLong());
+                }
+            }
+        }
+
+
+        public long getMin() {
+            return min;
+        }
+
+        public void setMin(long min) {
+            this.min = min;
+        }
+
+        public long getMax() {
+            return max;
+        }
+
+        public void setMax(long max) {
+            this.max = max;
+        }
+
+        public Set<Integer> getEnums() {
+            return enums;
+        }
+
+        public void setEnums(Set<Integer> enums) {
+            this.enums = enums;
+        }
+    }
+
+    public static class RealBaseType extends BaseType<RealBaseType> {
+        double min = Double.MIN_VALUE;
+        double max = Double.MAX_VALUE;
+        Set<Double> enums;
+
+        public RealBaseType fromString(String typeString) {
+            return "real".equals(typeString) ? new RealBaseType() : null;
+        }
+
+        @Override
+        protected void getConstraints(RealBaseType baseType, JsonNode type) {
+
+            JsonNode node = null;
+
+            if ((node = type.get("maxReal")) != null) {
+                baseType.setMax(node.asLong());
+            }
+
+            if ((node = type.get("minReal")) != null) {
+                baseType.setMin(node.asLong());
+            }
+
+            populateEnum(type);
+        }
+
+        private void populateEnum(JsonNode node) {
+            if (node.has("enum")) {
+                Set<Double> s = Sets.newHashSet();
+                JsonNode anEnum = node.get("enum").get(1);
+                for (JsonNode n : anEnum) {
+                    s.add(n.asDouble());
+                }
+            }
+        }
+
+        public double getMin() {
+            return min;
+        }
+
+        public void setMin(double min) {
+            this.min = min;
+        }
+
+        public double getMax() {
+            return max;
+        }
+
+        public void setMax(double max) {
+            this.max = max;
+        }
+
+        public Set<Double> getEnums() {
+            return enums;
+        }
+
+        public void setEnums(Set<Double> enums) {
+            this.enums = enums;
+        }
+
+
+    }
+
+
+    public static class BooleanBaseType extends BaseType {
+
+        public BooleanBaseType fromString(String typeString) {
+            return "boolean".equals(typeString) ? new BooleanBaseType() : null;
+        }
+
+        @Override
+        protected void getConstraints(BaseType baseType, JsonNode node) {
+            //no op
+        }
+    }
+
+    public static class StringBaseType extends BaseType<StringBaseType> {
+        int minLength = Integer.MIN_VALUE;
+        int maxLength = Integer.MAX_VALUE;
+        Set<String> enums;
+
+        public StringBaseType fromString(String typeString) {
+            return "string".equals(typeString) ? new StringBaseType() : null;
+        }
+
+        @Override
+        protected void getConstraints(StringBaseType baseType, JsonNode type) {
+
+            JsonNode node = null;
+
+            if ((node = type.get("maxLength")) != null) {
+                baseType.setMaxLength(node.asInt());
+            }
+
+            if ((node = type.get("minLength")) != null) {
+                baseType.setMinLength(node.asInt());
+            }
+
+            populateEnum(baseType, type);
+        }
+
+        private void populateEnum(StringBaseType baseType, JsonNode node) {
+            if (node.has("enum")) {
+                Set<String> s = Sets.newHashSet();
+                JsonNode anEnum = node.get("enum").get(1);
+                for (JsonNode n : anEnum) {
+                    s.add(n.asText());
+                }
+                baseType.setEnums(s);
+            }
+        }
+
+        public int getMinLength() {
+            return minLength;
+        }
+
+        public void setMinLength(int minLength) {
+            this.minLength = minLength;
+        }
+
+        public int getMaxLength() {
+            return maxLength;
+        }
+
+        public void setMaxLength(int maxLength) {
+            this.maxLength = maxLength;
+        }
+
+        public Set<String> getEnums() {
+            return enums;
+        }
+
+        public void setEnums(Set<String> enums) {
+            this.enums = enums;
+        }
+    }
+
+
+    public static class UuidBaseType extends BaseType<UuidBaseType> {
+        public static enum RefType {strong, weak}
+
+        String refTable;
+        RefType refType;
+
+
+        public UuidBaseType fromString(String typeString) {
+            return "uuid".equals(typeString) ? new UuidBaseType() : null;
+        }
+
+        @Override
+        protected void getConstraints(UuidBaseType baseType, JsonNode node) {
+
+            JsonNode refTable = node.get("refTable");
+            baseType.setRefTable(refTable != null ? refTable.asText() : null);
+
+            JsonNode refTypeJson = node.get("refType");
+            baseType.setRefType(refTypeJson != null ? RefType.valueOf(refTypeJson.asText()) : RefType.strong);
+
+        }
+
+        public String getRefTable() {
+            return refTable;
+        }
+
+        public void setRefTable(String refTable) {
+            this.refTable = refTable;
+        }
+
+        public RefType getRefType() {
+            return refType;
+        }
+
+        public void setRefType(RefType refType) {
+            this.refType = refType;
+        }
+    }
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/ColumnSchema.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/ColumnSchema.java
new file mode 100644 (file)
index 0000000..683dbea
--- /dev/null
@@ -0,0 +1,65 @@
+package org.opendaylight.ovsdb.lib.meta;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.opendaylight.ovsdb.lib.notation.Condition;
+import org.opendaylight.ovsdb.lib.notation.Function;
+
+/**
+ * @author ashw7n
+ */
+
+public class ColumnSchema<E extends TableSchema<E>, D> {
+    String name;
+    ColumnType type;
+    boolean ephemeral;
+    boolean mutable;
+
+    public ColumnSchema(String name, ColumnType columnType) {
+        this.name = name;
+        this.type = columnType;
+    }
+
+    public static ColumnSchema fromJson(String name, JsonNode json) {
+        if (!json.isObject() || !json.has("type")) {
+            //todo specific types of exception
+            throw new RuntimeException("bad column schema root, expected \"type\" as child");
+        }
+
+        return new ColumnSchema(name, ColumnType.fromJson(json.get("type")));
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Condition opEqual(D data) {
+        return new Condition(this.getName(), Function.EQUALS, data);
+    }
+
+    public Condition opGreaterThan(D data) {
+        return new Condition(this.getName(), Function.GREATER_THAN, data);
+    }
+
+    public Condition opLesserThan(D data) {
+        return new Condition(this.getName(), Function.GREATER_THAN, data);
+    }
+
+    public Condition opLesserThanOrEquals(D data) {
+        return new Condition(this.getName(), Function.LESS_THAN_OR_EQUALS, data);
+    }
+
+    @Override
+    public String toString() {
+        return "ColumnType [type=" + type + ", ephemeral=" + ephemeral
+                + ", mutable=" + mutable + "]";
+    }
+
+    /**
+     * Validates the passed in value against the constraints set for this ColumnSchema
+     * @param value
+     * @throws java.lang.RuntimeException (validation exception)
+     */
+    public void validate(Object value)throws RuntimeException {
+        //todo(type check and validate based on constraints set)
+    }
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/ColumnType.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/ColumnType.java
new file mode 100644 (file)
index 0000000..aa4eeeb
--- /dev/null
@@ -0,0 +1,109 @@
+package org.opendaylight.ovsdb.lib.meta;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.opendaylight.ovsdb.lib.jsonrpc.JsonUtils;
+
+/**
+ * @author araveendrann
+ */
+public abstract class ColumnType {
+    BaseType baseType;
+    int min = 0;
+    int max = 0;
+
+    private static ColumnType columns[] = new ColumnType[]{
+            new AtomicColumnType(),
+            new KeyValuedColumnType()
+    };
+
+
+    public ColumnType() {
+
+    }
+
+    public ColumnType(BaseType baseType) {
+        this.baseType = baseType;
+    }
+
+    /**
+            "type": {
+                "key": {
+                     "maxInteger": 4294967295,
+                     "minInteger": 0,
+                     "type": "integer"
+                },
+                "min": 0,
+                "value": {
+                    "type": "uuid",
+                    "refTable": "Queue"
+                 },
+                 "max": "unlimited"
+            }
+     * @param json
+     * @return
+     */
+    public static ColumnType fromJson(JsonNode json) {
+        for (ColumnType colType : columns) {
+            ColumnType columnType = colType.fromJsonNode(json);
+            if (null != columnType) {
+                return columnType;
+            }
+        }
+        //todo mode to speicfic typed exception
+        throw new RuntimeException(String.format("could not find the right column type %s",
+                JsonUtils.prettyString(json)));
+    }
+
+
+    /**
+     * Creates a ColumnType from the JsonNode if the type knows how to,
+     * returns null otherwise
+     *
+     * @param json the JSONNode object that needs to converted
+     * @return a valid SubType or Null (if the JsonNode does not represent
+     * the subtype)
+     */
+    protected abstract ColumnType fromJsonNode(JsonNode json);
+
+    public static class AtomicColumnType extends ColumnType {
+
+        public AtomicColumnType() {
+        }
+
+        public AtomicColumnType(BaseType baseType1) {
+            super(baseType1);
+        }
+
+        public AtomicColumnType fromJsonNode(JsonNode json) {
+            if (json.isObject() && json.has("value")) {
+                return null;
+            }
+            BaseType baseType = BaseType.fromJson(json, "key");
+
+            return baseType != null ? new AtomicColumnType(baseType) : null;
+        }
+
+    }
+
+    public static class KeyValuedColumnType extends ColumnType {
+
+        BaseType valueType;
+
+        public KeyValuedColumnType() {
+        }
+
+        public KeyValuedColumnType(BaseType baseType, BaseType valueType) {
+            super(baseType);
+        }
+
+        public KeyValuedColumnType fromJsonNode(JsonNode json) {
+            if (json.isValueNode() || !json.has("value")) {
+                return null;
+            }
+            BaseType keyType = BaseType.fromJson(json, "key");
+            BaseType valueType = BaseType.fromJson(json, "value");
+
+            return new KeyValuedColumnType(keyType, valueType);
+        }
+    }
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/DatabaseSchema.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/DatabaseSchema.java
new file mode 100644 (file)
index 0000000..e082b09
--- /dev/null
@@ -0,0 +1,58 @@
+package org.opendaylight.ovsdb.lib.meta;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.opendaylight.ovsdb.OpenVswitch;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author araveendrann
+ */
+public class DatabaseSchema {
+    public static Logger logger = LoggerFactory.getLogger(DatabaseSchema.class);
+
+    public static String OPEN_VSWITCH_SCHEMA_NAME = "Open_vSwitch";
+
+    public Map<String, TableSchema> tables;
+
+    public DatabaseSchema(Map<String, TableSchema> tables) {
+        this.tables = tables;
+    }
+
+
+    public static DatabaseSchema fromJson(JsonNode json) {
+        if (!json.isObject() || !json.has("tables")) {
+            //todo specific types of exception
+            throw new RuntimeException("bad databaseschema root, expected \"tables\" as child");
+        }
+
+        Map<String, TableSchema> tables = new HashMap<>();
+        //Iterator<Map.Entry<String,JsonNode>> fields = json.fields();
+        for(Iterator<Map.Entry<String,JsonNode>> iter = json.get("tables").fields(); iter.hasNext();) {
+            Map.Entry<String, JsonNode> table = iter.next();
+            logger.debug("Read schema for table[{}]:{}" , table.getKey(), table.getValue());
+
+            tables.put(table.getKey(), TableSchema.fromJson(table.getKey(), table.getValue()));
+        }
+
+        return new DatabaseSchema(tables);
+    }
+
+    public OpenVswitch.Transaction beginTransaction() {
+        return new OpenVswitch.Transaction(this);
+    }
+
+    public <E extends TableSchema<E>> TableSchema<E> table(String tableName) {
+        //todo : error handling
+        return tables.get(tableName);
+    }
+
+    public <E extends TableSchema<E>> E table(String tableName, Class<E> clazz) {
+        TableSchema<E> table = table(tableName);
+        return table.as(clazz);
+    }
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/TableSchema.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/TableSchema.java
new file mode 100644 (file)
index 0000000..2547ac0
--- /dev/null
@@ -0,0 +1,76 @@
+package org.opendaylight.ovsdb.lib.meta;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.opendaylight.ovsdb.Insert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author araveendrann
+ */
+public class TableSchema<E extends TableSchema<E>> {
+    protected static final Logger logger = LoggerFactory.getLogger(TableSchema.class);
+    private String name;
+    private Map<String, ColumnSchema> columns;
+
+    public TableSchema() {
+    }
+
+    public TableSchema(String name, Map<String, ColumnSchema> columns) {
+        this.name = name;
+        this.columns = columns;
+    }
+
+    public static TableSchema fromJson(String tableName, JsonNode json) {
+
+        if (!json.isObject() || !json.has("columns")) {
+            //todo specific types of exception
+            throw new RuntimeException("bad tableschema root, expected \"columns\" as child");
+        }
+
+        Map<String, ColumnSchema> columns = new HashMap<>();
+        for (Iterator<Map.Entry<String, JsonNode>> iter = json.get("columns").fields(); iter.hasNext(); ) {
+            Map.Entry<String, JsonNode> column = iter.next();
+            logger.debug("%s:%s", tableName, column.getKey());
+            columns.put(column.getKey(), ColumnSchema.fromJson(column.getKey(), column.getValue()));
+        }
+
+       TableSchema tableSchema = new TableSchema(tableName, columns);
+       return tableSchema;
+    }
+
+    public <E extends TableSchema<E>> E as(Class<E> clazz) {
+        try {
+            Constructor<E> e = clazz.getConstructor(TableSchema.class);
+            return e.newInstance(this);
+        } catch (Exception e) {
+            throw new RuntimeException("exception constructing instance of clazz " + clazz, e);
+        }
+    }
+
+    public Insert<E> insert() {
+        return new Insert<>(this);
+    }
+
+
+
+    public <D> ColumnSchema<E, D> column(String column) {
+        //todo exception handling
+        return columns.get(column);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public static class AnyTableSchema extends TableSchema<AnyTableSchema>{}
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/temp/Reference.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/temp/Reference.java
new file mode 100644 (file)
index 0000000..85a175d
--- /dev/null
@@ -0,0 +1,8 @@
+package org.opendaylight.ovsdb.lib.meta.temp;
+
+/**
+ * @author araveendrann
+ */
+public class Reference {
+
+}
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/temp/SchemaObjs.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/lib/meta/temp/SchemaObjs.java
new file mode 100644 (file)
index 0000000..29b3f31
--- /dev/null
@@ -0,0 +1,65 @@
+package org.opendaylight.ovsdb.lib.meta.temp;
+
+import org.opendaylight.ovsdb.OpenVswitch;
+import org.opendaylight.ovsdb.lib.meta.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.meta.ColumnSchema;
+import org.opendaylight.ovsdb.lib.meta.TableSchema;
+
+/**
+ * @author araveendrann
+ */
+public class SchemaObjs {
+
+    public static class Bridge extends TableSchema<Bridge> {
+        public static String NAME = "Bridge";
+        TableSchema target;
+
+        ColumnSchema<Bridge, String> name;
+        ColumnSchema<Bridge, Boolean> flood_vlans;
+
+
+        public Bridge(TableSchema<Bridge> target) {
+            this.target = target;
+            name = target.column("name");
+            flood_vlans = target.column("statistics");
+        }
+
+    }
+
+    public static class Port extends TableSchema<Port> {
+        public static String NAME = "Port";
+        TableSchema target;
+
+        ColumnSchema<Port, String> name;
+        ColumnSchema<Port, String> statistics;
+
+        public Port(TableSchema<Port> target) {
+            this.target = target;
+            name = target.column("name");
+            statistics = target.column("statistics");
+        }
+
+    }
+
+    public static void main(String[] args) {
+
+        OpenVswitch ovs = new OpenVswitch(null, null);
+        DatabaseSchema db = ovs.getSchema();
+        Bridge bridge = db.table(Bridge.NAME, Bridge.class);
+        Port port = db.table(Port.NAME, Port.class);
+
+        db.beginTransaction()
+                .add(bridge.insert()
+                        .value(bridge.flood_vlans, true)
+                        .value(bridge.name, "br-int"))
+                .add(port.insert()
+                        .value(port.statistics, "stats")
+                        //.value(port.statistics, 2) ## will not type check as stats is a string
+                        .value(port.name, "newport")
+                )
+                .execute();
+
+        //todo untyped version
+
+    }
+}
index 199d67d4dc429a2f2ee5c953e452bf4e6c841824..839efe602d285332246dad4b31f39c5544c5bb8f 100644 (file)
@@ -18,27 +18,34 @@ public class Condition {
     String column;
     Function function;
     Object value;
+
     public Condition(String column, Function function, Object value) {
         super();
         this.column = column;
         this.function = function;
         this.value = value;
     }
+
     public String getColumn() {
         return column;
     }
+
     public void setColumn(String column) {
         this.column = column;
     }
+
     public Function getFunction() {
         return function;
     }
+
     public void setFunction(Function function) {
         this.function = function;
     }
+
     public Object getValue() {
         return value;
     }
+
     public void setValue(Object value) {
         this.value = value;
     }
index ad7f71a5a24009099a9fc5830c03156a37ed04fa..124d10b4a035aa21fe7234d9cda24f3695e6dc03 100644 (file)
@@ -310,7 +310,7 @@ public class ConnectionService implements IPluginInConnectionService, IConnectio
         inventoryServiceInternal.addNode(connection.getNode(), props);
 
         List<String> dbNames = Arrays.asList(Open_vSwitch.NAME.getName());
-        ListenableFuture<DatabaseSchema> dbSchemaF = connection.getRpc().get_schema(dbNames);
+        ListenableFuture<DatabaseSchema> dbSchemaF = null;//todo : fix it up to new structue : connection.getRpc().get_schema(dbNames);
         DatabaseSchema databaseSchema = dbSchemaF.get();
         inventoryServiceInternal.updateDatabaseSchema(connection.getNode(), databaseSchema);
 
diff --git a/ovsdb/src/test/java/org/opendaylight/ovsdb/OpenVswitchTestIT.java b/ovsdb/src/test/java/org/opendaylight/ovsdb/OpenVswitchTestIT.java
new file mode 100644 (file)
index 0000000..711814b
--- /dev/null
@@ -0,0 +1,66 @@
+package org.opendaylight.ovsdb;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.ovsdb.lib.message.OvsdbRPC;
+import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
+import org.opendaylight.ovsdb.lib.meta.ColumnSchema;
+import org.opendaylight.ovsdb.lib.meta.TableSchema;
+import org.opendaylight.ovsdb.plugin.OvsdbTestBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.opendaylight.ovsdb.OpenVswitch.Operations.op;
+
+/**
+ * @author Ashwin Raveendran
+ */
+public class OpenVswitchTestIT extends OvsdbTestBase {
+    Logger logger = LoggerFactory.getLogger(OpenVswitchTestIT.class);
+
+    @Test
+    public void test() throws IOException, InterruptedException, ExecutionException {
+        OpenVswitch ovs = getVswitch();
+
+        TableSchema<TableSchema.AnyTableSchema> bridge = ovs.schema().table("Bridge");
+        ColumnSchema<TableSchema.AnyTableSchema, String> name = bridge.column("name");
+
+        ListenableFuture<List<OperationResult>> results = ovs.transact()
+                .add(op.insert(bridge).value(name, "br-int"))
+                .add(op.update(bridge)
+                        .set(name, "br-int")
+                        .where(name.opEqual("br-int"))
+                        .and(name.opEqual("br-int")).operation())
+                .execute();
+
+        List<OperationResult> operationResults = results.get();
+        Assert.assertFalse(operationResults.isEmpty());
+        System.out.println("operationResults = " + operationResults);
+    }
+
+
+    private OpenVswitch getVswitch() throws IOException, InterruptedException {
+        TestObjects testConnection = getTestConnection();
+        OvsdbRPC rpc = testConnection.connectionService.getConnection(testConnection.node).getRpc();
+
+        ExecutorService executorService = Executors.newFixedThreadPool(3);
+        OpenVswitch ovs = new OpenVswitch(rpc, executorService);
+        ovs.populateSchemaFromDevice();
+
+        for (int i = 0; i < 100; i++) {
+           if (ovs.isReady(0)) {
+              break;
+           }
+           Thread.sleep(1000);
+        }
+        return ovs;
+    }
+
+}
diff --git a/ovsdb/src/test/java/org/opendaylight/ovsdb/OpenVswitchTestITTyped.java b/ovsdb/src/test/java/org/opendaylight/ovsdb/OpenVswitchTestITTyped.java
new file mode 100644 (file)
index 0000000..91d3c5d
--- /dev/null
@@ -0,0 +1,96 @@
+package org.opendaylight.ovsdb;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.ovsdb.lib.message.OvsdbRPC;
+import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
+import org.opendaylight.ovsdb.lib.meta.ColumnSchema;
+import org.opendaylight.ovsdb.lib.meta.TableSchema;
+import org.opendaylight.ovsdb.lib.meta.temp.Reference;
+import org.opendaylight.ovsdb.plugin.OvsdbTestBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.opendaylight.ovsdb.OpenVswitch.Operations.op;
+
+/**
+ * @author Ashwin Raveendran
+ */
+public class OpenVswitchTestITTyped extends OvsdbTestBase {
+
+    Logger logger = LoggerFactory.getLogger(OpenVswitchTestITTyped.class);
+
+
+    static class Bridge extends TableSchema<Bridge> {
+
+        Bridge(String name, Map<String, ColumnSchema> columns) {
+            super(name, columns);
+        }
+
+        public ColumnSchema<Bridge, String> name() {
+            return column("name");
+        }
+
+        public ColumnSchema<Bridge, Integer> floodVlans() {
+            return column("flood_vlans");
+        }
+
+        public ColumnSchema<Bridge, String> status() {
+            return column("status");
+        }
+
+        public ColumnSchema<Bridge, Reference> netflow() {
+            return column("netflow");
+        }
+    }
+
+
+    @Test
+    public void test() throws IOException, InterruptedException, ExecutionException {
+        OpenVswitch ovs = getVswitch();
+
+        Bridge bridge = ovs.schema().table("Bridge", Bridge.class);
+
+        ListenableFuture<List<OperationResult>> results = ovs.transact()
+                .add(op.insert(bridge).value(bridge.name(), "br-int"))
+                .add(op.update(bridge)
+                        .set(bridge.status(), "br-blah")
+                        .set(bridge.floodVlans(), 34)
+                        .where(bridge.name().opEqual("br-int"))
+                        .and(bridge.name().opEqual("br-int")).operation())
+                .execute();
+
+        List<OperationResult> operationResults = results.get();
+        Assert.assertFalse(operationResults.isEmpty());
+        System.out.println("operationResults = " + operationResults);
+    }
+
+
+
+
+    private OpenVswitch getVswitch() throws IOException, InterruptedException {
+        TestObjects testConnection = getTestConnection();
+        OvsdbRPC rpc = testConnection.connectionService.getConnection(testConnection.node).getRpc();
+
+        ExecutorService executorService = Executors.newFixedThreadPool(3);
+        OpenVswitch ovs = new OpenVswitch(rpc, executorService);
+        ovs.populateSchemaFromDevice();
+
+        for (int i = 0; i < 100; i++) {
+           if (ovs.isReady(0)) {
+              break;
+           }
+           Thread.sleep(1000);
+        }
+        return ovs;
+    }
+
+}
index a8442fdf9299aab475230c4fc317d97222ee9a25..35d79b5c77fa989ffbdb2337502d6b25ddf04539 100644 (file)
@@ -96,7 +96,7 @@ public class OVSDBNettyFactoryIT {
 
         //GET DB-SCHEMA
         List<String> dbNames = Arrays.asList(Open_vSwitch.NAME.getName());
-        ListenableFuture<DatabaseSchema> dbSchemaF = ovsdb.get_schema(dbNames);
+        ListenableFuture<DatabaseSchema> dbSchemaF = null; //ovsdb.get_schema(dbNames);
         DatabaseSchema databaseSchema = dbSchemaF.get();
         MapUtils.debugPrint(System.out, null, databaseSchema.getTables());
 
diff --git a/ovsdb/src/test/java/org/opendaylight/ovsdb/lib/meta/OvsDBSchemaTest.java b/ovsdb/src/test/java/org/opendaylight/ovsdb/lib/meta/OvsDBSchemaTest.java
new file mode 100644 (file)
index 0000000..91be86a
--- /dev/null
@@ -0,0 +1,26 @@
+package org.opendaylight.ovsdb.lib.meta;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+import static org.junit.Assert.assertNotNull;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author araveendrann
+ */
+public class OvsDBSchemaTest {
+
+    @Test
+    public void testSchema() throws IOException {
+        InputStream resourceAsStream = OvsDBSchemaTest.class.getResourceAsStream("test_schema.json");
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode jsonNode = mapper.readTree(resourceAsStream);
+        System.out.println("jsonNode = " + jsonNode.get("id"));
+
+        DatabaseSchema schema = DatabaseSchema.fromJson(jsonNode.get("result"));
+        assertNotNull(schema);
+
+    }
+}
diff --git a/ovsdb/src/test/java/org/opendaylight/ovsdb/lib/meta/test_schema.json b/ovsdb/src/test/java/org/opendaylight/ovsdb/lib/meta/test_schema.json
new file mode 100644 (file)
index 0000000..f7f8405
--- /dev/null
@@ -0,0 +1,1150 @@
+{
+  "id": 0,
+  "result": {
+    "tables": {
+      "Port": {
+        "columns": {
+          "name": {
+            "mutable": false,
+            "type": "string"
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "integer",
+              "max": "unlimited"
+            }
+          },
+          "vlan_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "access",
+                    "native-tagged",
+                    "native-untagged",
+                    "trunk"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "qos": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "QoS"
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "trunks": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "max": 4096
+            }
+          },
+          "mac": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "interfaces": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Interface"
+              },
+              "max": "unlimited"
+            }
+          },
+          "bond_downdelay": {
+            "type": "integer"
+          },
+          "bond_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "active-backup",
+                    "balance-slb",
+                    "balance-tcp",
+                    "stable"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "bond_updelay": {
+            "type": "integer"
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "tag": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "bond_fake_iface": {
+            "type": "boolean"
+          },
+          "fake_bridge": {
+            "type": "boolean"
+          },
+          "lacp": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "active",
+                    "off",
+                    "passive"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          }
+        },
+        "indexes": [
+          [
+            "name"
+          ]
+        ]
+      },
+      "Manager": {
+        "columns": {
+          "is_connected": {
+            "ephemeral": true,
+            "type": "boolean"
+          },
+          "target": {
+            "type": "string"
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "max_backoff": {
+            "type": {
+              "key": {
+                "minInteger": 1000,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "connection_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "in-band",
+                    "out-of-band"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "inactivity_probe": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          }
+        },
+        "indexes": [
+          [
+            "target"
+          ]
+        ]
+      },
+      "Bridge": {
+        "columns": {
+          "name": {
+            "mutable": false,
+            "type": "string"
+          },
+          "flood_vlans": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "max": 4096
+            }
+          },
+          "netflow": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "NetFlow"
+              },
+              "min": 0
+            }
+          },
+          "mirrors": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Mirror"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "datapath_id": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "controller": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Controller"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "protocols": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "OpenFlow10",
+                    "OpenFlow12",
+                    "OpenFlow13"
+                  ]
+                ]
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "fail_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "secure",
+                    "standalone"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "ports": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "flow_tables": {
+            "type": {
+              "key": {
+                "maxInteger": 254,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "value": {
+                "type": "uuid",
+                "refTable": "Flow_Table"
+              },
+              "max": "unlimited"
+            }
+          },
+          "sflow": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "sFlow"
+              },
+              "min": 0
+            }
+          },
+          "datapath_type": {
+            "type": "string"
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "stp_enable": {
+            "type": "boolean"
+          }
+        },
+        "indexes": [
+          [
+            "name"
+          ]
+        ]
+      },
+      "Interface": {
+        "columns": {
+          "options": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "name": {
+            "mutable": false,
+            "type": "string"
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "integer",
+              "max": "unlimited"
+            }
+          },
+          "link_speed": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "mtu": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "mac_in_use": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "type": {
+            "type": "string"
+          },
+          "ingress_policing_rate": {
+            "type": {
+              "key": {
+                "minInteger": 0,
+                "type": "integer"
+              }
+            }
+          },
+          "cfm_remote_opstate": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "down",
+                    "up"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "mac": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "ofport": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "cfm_fault_status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "duplex": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "full",
+                    "half"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "lacp_current": {
+            "ephemeral": true,
+            "type": {
+              "key": "boolean",
+              "min": 0
+            }
+          },
+          "cfm_fault": {
+            "ephemeral": true,
+            "type": {
+              "key": "boolean",
+              "min": 0
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "admin_state": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "down",
+                    "up"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "link_state": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "down",
+                    "up"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "cfm_remote_mpids": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "cfm_mpid": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "ofport_request": {
+            "type": {
+              "key": {
+                "maxInteger": 65279,
+                "minInteger": 1,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "ingress_policing_burst": {
+            "type": {
+              "key": {
+                "minInteger": 0,
+                "type": "integer"
+              }
+            }
+          },
+          "cfm_health": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "maxInteger": 100,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "link_resets": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          }
+        },
+        "indexes": [
+          [
+            "name"
+          ]
+        ]
+      },
+      "SSL": {
+        "columns": {
+          "ca_cert": {
+            "type": "string"
+          },
+          "private_key": {
+            "type": "string"
+          },
+          "bootstrap_ca_cert": {
+            "type": "boolean"
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "certificate": {
+            "type": "string"
+          }
+        },
+        "maxRows": 1
+      },
+      "Open_vSwitch": {
+        "columns": {
+          "ovs_version": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "system_version": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "bridges": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Bridge"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "next_cfg": {
+            "type": "integer"
+          },
+          "manager_options": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Manager"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "system_type": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "ssl": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "SSL"
+              },
+              "min": 0
+            }
+          },
+          "db_version": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "cur_cfg": {
+            "type": "integer"
+          }
+        },
+        "maxRows": 1,
+        "isRoot": true
+      },
+      "Queue": {
+        "columns": {
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "dscp": {
+            "type": {
+              "key": {
+                "maxInteger": 63,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        },
+        "isRoot": true
+      },
+      "NetFlow": {
+        "columns": {
+          "engine_type": {
+            "type": {
+              "key": {
+                "maxInteger": 255,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "targets": {
+            "type": {
+              "key": "string",
+              "max": "unlimited"
+            }
+          },
+          "add_id_to_interface": {
+            "type": "boolean"
+          },
+          "active_timeout": {
+            "type": {
+              "key": {
+                "minInteger": -1,
+                "type": "integer"
+              }
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "engine_id": {
+            "type": {
+              "key": {
+                "maxInteger": 255,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        }
+      },
+      "Mirror": {
+        "columns": {
+          "name": {
+            "type": "string"
+          },
+          "output_port": {
+            "type": {
+              "key": {
+                "refType": "weak",
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0
+            }
+          },
+          "output_vlan": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 1,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "integer",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "select_dst_port": {
+            "type": {
+              "key": {
+                "refType": "weak",
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "select_all": {
+            "type": "boolean"
+          },
+          "select_vlan": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "max": 4096
+            }
+          },
+          "select_src_port": {
+            "type": {
+              "key": {
+                "refType": "weak",
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          }
+        }
+      },
+      "QoS": {
+        "columns": {
+          "queues": {
+            "type": {
+              "key": {
+                "maxInteger": 4294967295,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "value": {
+                "type": "uuid",
+                "refTable": "Queue"
+              },
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "type": {
+            "type": "string"
+          }
+        },
+        "isRoot": true
+      },
+      "Controller": {
+        "columns": {
+          "is_connected": {
+            "ephemeral": true,
+            "type": "boolean"
+          },
+          "enable_async_messages": {
+            "type": {
+              "key": "boolean",
+              "min": 0
+            }
+          },
+          "controller_rate_limit": {
+            "type": {
+              "key": {
+                "minInteger": 100,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "target": {
+            "type": "string"
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "local_netmask": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "local_gateway": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "max_backoff": {
+            "type": {
+              "key": {
+                "minInteger": 1000,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "local_ip": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "connection_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "in-band",
+                    "out-of-band"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "role": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "master",
+                    "other",
+                    "slave"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "inactivity_probe": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "controller_burst_limit": {
+            "type": {
+              "key": {
+                "minInteger": 25,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        }
+      },
+      "Flow_Table": {
+        "columns": {
+          "groups": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "name": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "overflow_policy": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "evict",
+                    "refuse"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "flow_limit": {
+            "type": {
+              "key": {
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        }
+      },
+      "sFlow": {
+        "columns": {
+          "polling": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "targets": {
+            "type": {
+              "key": "string",
+              "max": "unlimited"
+            }
+          },
+          "header": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "agent": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "sampling": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          }
+        }
+      }
+    },
+    "cksum": "2180939265 17455",
+    "name": "Open_vSwitch",
+    "version": "6.12.0"
+  },
+  "error": null
+}
index f6929b335759323a3f69c915ab4405d16f80ce10..9629ce593eca67f90ac34c7aec7dd5d12116f9e1 100644 (file)
@@ -51,9 +51,13 @@ public abstract class OvsdbTestBase {
         Node.NodeIDType.registerIDType("OVS", String.class);
         NodeConnector.NodeConnectorIDType.registerIDType("OVS", String.class,
                 "OVS");
+        InventoryService inventoryService = new InventoryService();
+        inventoryService.init();
 
         ConnectionService connectionService = new ConnectionService();
         connectionService.init();
+
+        connectionService.setInventoryServiceInternal(inventoryService);
         Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
         Properties props = loadProperties();
         params.put(ConnectionConstants.ADDRESS,
diff --git a/ovsdb/src/test/resources/logback.xml b/ovsdb/src/test/resources/logback.xml
new file mode 100644 (file)
index 0000000..70118ce
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- encoders are assigned the type
+             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcEndpoint" level="TRACE" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <!--<logger name="com.lordofthejars.foo" level="INFO" additivity="false">-->
+        <!--<appender-ref ref="STDOUT" />-->
+    <!--</logger>-->
+
+    <root level="INFO">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+</configuration>
\ No newline at end of file
index 7d6453a59e00c0b3b51f62ab79b4974603dd9e54..16978d18070d6e3ffe68e6e094fdc8bc83b742f5 100644 (file)
@@ -1,2 +1,2 @@
-ovsdbserver.ipaddress=${ovsdbserver.ipaddress}
-ovsdbserver.port=${ovsdbserver.port}
\ No newline at end of file
+ovsdbserver.ipaddress=192.168.111.135
+ovsdbserver.port=5000
\ No newline at end of file
diff --git a/ovsdb/src/test/resources/org/opendaylight/ovsdb/lib/meta/test_schema.json b/ovsdb/src/test/resources/org/opendaylight/ovsdb/lib/meta/test_schema.json
new file mode 100644 (file)
index 0000000..f7f8405
--- /dev/null
@@ -0,0 +1,1150 @@
+{
+  "id": 0,
+  "result": {
+    "tables": {
+      "Port": {
+        "columns": {
+          "name": {
+            "mutable": false,
+            "type": "string"
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "integer",
+              "max": "unlimited"
+            }
+          },
+          "vlan_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "access",
+                    "native-tagged",
+                    "native-untagged",
+                    "trunk"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "qos": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "QoS"
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "trunks": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "max": 4096
+            }
+          },
+          "mac": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "interfaces": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Interface"
+              },
+              "max": "unlimited"
+            }
+          },
+          "bond_downdelay": {
+            "type": "integer"
+          },
+          "bond_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "active-backup",
+                    "balance-slb",
+                    "balance-tcp",
+                    "stable"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "bond_updelay": {
+            "type": "integer"
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "tag": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "bond_fake_iface": {
+            "type": "boolean"
+          },
+          "fake_bridge": {
+            "type": "boolean"
+          },
+          "lacp": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "active",
+                    "off",
+                    "passive"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          }
+        },
+        "indexes": [
+          [
+            "name"
+          ]
+        ]
+      },
+      "Manager": {
+        "columns": {
+          "is_connected": {
+            "ephemeral": true,
+            "type": "boolean"
+          },
+          "target": {
+            "type": "string"
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "max_backoff": {
+            "type": {
+              "key": {
+                "minInteger": 1000,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "connection_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "in-band",
+                    "out-of-band"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "inactivity_probe": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          }
+        },
+        "indexes": [
+          [
+            "target"
+          ]
+        ]
+      },
+      "Bridge": {
+        "columns": {
+          "name": {
+            "mutable": false,
+            "type": "string"
+          },
+          "flood_vlans": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "max": 4096
+            }
+          },
+          "netflow": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "NetFlow"
+              },
+              "min": 0
+            }
+          },
+          "mirrors": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Mirror"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "datapath_id": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "controller": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Controller"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "protocols": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "OpenFlow10",
+                    "OpenFlow12",
+                    "OpenFlow13"
+                  ]
+                ]
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "fail_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "secure",
+                    "standalone"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "ports": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "flow_tables": {
+            "type": {
+              "key": {
+                "maxInteger": 254,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "value": {
+                "type": "uuid",
+                "refTable": "Flow_Table"
+              },
+              "max": "unlimited"
+            }
+          },
+          "sflow": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "sFlow"
+              },
+              "min": 0
+            }
+          },
+          "datapath_type": {
+            "type": "string"
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "stp_enable": {
+            "type": "boolean"
+          }
+        },
+        "indexes": [
+          [
+            "name"
+          ]
+        ]
+      },
+      "Interface": {
+        "columns": {
+          "options": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "name": {
+            "mutable": false,
+            "type": "string"
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "integer",
+              "max": "unlimited"
+            }
+          },
+          "link_speed": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "mtu": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "mac_in_use": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "type": {
+            "type": "string"
+          },
+          "ingress_policing_rate": {
+            "type": {
+              "key": {
+                "minInteger": 0,
+                "type": "integer"
+              }
+            }
+          },
+          "cfm_remote_opstate": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "down",
+                    "up"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "mac": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "ofport": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "cfm_fault_status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "duplex": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "full",
+                    "half"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "lacp_current": {
+            "ephemeral": true,
+            "type": {
+              "key": "boolean",
+              "min": 0
+            }
+          },
+          "cfm_fault": {
+            "ephemeral": true,
+            "type": {
+              "key": "boolean",
+              "min": 0
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "admin_state": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "down",
+                    "up"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "link_state": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "down",
+                    "up"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "cfm_remote_mpids": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "cfm_mpid": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "ofport_request": {
+            "type": {
+              "key": {
+                "maxInteger": 65279,
+                "minInteger": 1,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "ingress_policing_burst": {
+            "type": {
+              "key": {
+                "minInteger": 0,
+                "type": "integer"
+              }
+            }
+          },
+          "cfm_health": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "maxInteger": 100,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "link_resets": {
+            "ephemeral": true,
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          }
+        },
+        "indexes": [
+          [
+            "name"
+          ]
+        ]
+      },
+      "SSL": {
+        "columns": {
+          "ca_cert": {
+            "type": "string"
+          },
+          "private_key": {
+            "type": "string"
+          },
+          "bootstrap_ca_cert": {
+            "type": "boolean"
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "certificate": {
+            "type": "string"
+          }
+        },
+        "maxRows": 1
+      },
+      "Open_vSwitch": {
+        "columns": {
+          "ovs_version": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "system_version": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "bridges": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Bridge"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "next_cfg": {
+            "type": "integer"
+          },
+          "manager_options": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "Manager"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "system_type": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "ssl": {
+            "type": {
+              "key": {
+                "type": "uuid",
+                "refTable": "SSL"
+              },
+              "min": 0
+            }
+          },
+          "db_version": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "cur_cfg": {
+            "type": "integer"
+          }
+        },
+        "maxRows": 1,
+        "isRoot": true
+      },
+      "Queue": {
+        "columns": {
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "dscp": {
+            "type": {
+              "key": {
+                "maxInteger": 63,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        },
+        "isRoot": true
+      },
+      "NetFlow": {
+        "columns": {
+          "engine_type": {
+            "type": {
+              "key": {
+                "maxInteger": 255,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "targets": {
+            "type": {
+              "key": "string",
+              "max": "unlimited"
+            }
+          },
+          "add_id_to_interface": {
+            "type": "boolean"
+          },
+          "active_timeout": {
+            "type": {
+              "key": {
+                "minInteger": -1,
+                "type": "integer"
+              }
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "engine_id": {
+            "type": {
+              "key": {
+                "maxInteger": 255,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        }
+      },
+      "Mirror": {
+        "columns": {
+          "name": {
+            "type": "string"
+          },
+          "output_port": {
+            "type": {
+              "key": {
+                "refType": "weak",
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0
+            }
+          },
+          "output_vlan": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 1,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "statistics": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "integer",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "select_dst_port": {
+            "type": {
+              "key": {
+                "refType": "weak",
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "select_all": {
+            "type": "boolean"
+          },
+          "select_vlan": {
+            "type": {
+              "key": {
+                "maxInteger": 4095,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "max": 4096
+            }
+          },
+          "select_src_port": {
+            "type": {
+              "key": {
+                "refType": "weak",
+                "type": "uuid",
+                "refTable": "Port"
+              },
+              "min": 0,
+              "max": "unlimited"
+            }
+          }
+        }
+      },
+      "QoS": {
+        "columns": {
+          "queues": {
+            "type": {
+              "key": {
+                "maxInteger": 4294967295,
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0,
+              "value": {
+                "type": "uuid",
+                "refTable": "Queue"
+              },
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "type": {
+            "type": "string"
+          }
+        },
+        "isRoot": true
+      },
+      "Controller": {
+        "columns": {
+          "is_connected": {
+            "ephemeral": true,
+            "type": "boolean"
+          },
+          "enable_async_messages": {
+            "type": {
+              "key": "boolean",
+              "min": 0
+            }
+          },
+          "controller_rate_limit": {
+            "type": {
+              "key": {
+                "minInteger": 100,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "target": {
+            "type": "string"
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "other_config": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "local_netmask": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "local_gateway": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "max_backoff": {
+            "type": {
+              "key": {
+                "minInteger": 1000,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          },
+          "local_ip": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "connection_mode": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "in-band",
+                    "out-of-band"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "status": {
+            "ephemeral": true,
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "role": {
+            "ephemeral": true,
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "master",
+                    "other",
+                    "slave"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "inactivity_probe": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "controller_burst_limit": {
+            "type": {
+              "key": {
+                "minInteger": 25,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        }
+      },
+      "Flow_Table": {
+        "columns": {
+          "groups": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "max": "unlimited"
+            }
+          },
+          "name": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "overflow_policy": {
+            "type": {
+              "key": {
+                "type": "string",
+                "enum": [
+                  "set",
+                  [
+                    "evict",
+                    "refuse"
+                  ]
+                ]
+              },
+              "min": 0
+            }
+          },
+          "flow_limit": {
+            "type": {
+              "key": {
+                "minInteger": 0,
+                "type": "integer"
+              },
+              "min": 0
+            }
+          }
+        }
+      },
+      "sFlow": {
+        "columns": {
+          "polling": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "targets": {
+            "type": {
+              "key": "string",
+              "max": "unlimited"
+            }
+          },
+          "header": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          },
+          "agent": {
+            "type": {
+              "key": "string",
+              "min": 0
+            }
+          },
+          "external_ids": {
+            "type": {
+              "key": "string",
+              "min": 0,
+              "value": "string",
+              "max": "unlimited"
+            }
+          },
+          "sampling": {
+            "type": {
+              "key": "integer",
+              "min": 0
+            }
+          }
+        }
+      }
+    },
+    "cksum": "2180939265 17455",
+    "name": "Open_vSwitch",
+    "version": "6.12.0"
+  },
+  "error": null
+}