<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>
--- /dev/null
+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;
+ }
+
+
+
+}
--- /dev/null
+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;
+ }
+
+
+}
--- /dev/null
+package org.opendaylight.ovsdb.lib.database;
+
+/**
+ * @author araveendrann
+ */
+public class Column<E extends Table> {
+ ColumnSchema schema;
+}
-/*
- * [[ 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
-/*
- * [[ 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
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
--- /dev/null
+package org.opendaylight.ovsdb.lib.database;
+
+/**
+ * @author araveendrann
+ */
+public class Table<E extends Table> {
+ TableSchema schema;
+
+
+}
-/*
- * [[ 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
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
--- /dev/null
+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);
+ }
+ }
+}
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();
--- /dev/null
+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);
+}
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
* 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;
}
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 + "]";
}
+
}
--- /dev/null
+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;
+ }
+ }
+}
--- /dev/null
+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)
+ }
+}
--- /dev/null
+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);
+ }
+ }
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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>{}
+}
--- /dev/null
+package org.opendaylight.ovsdb.lib.meta.temp;
+
+/**
+ * @author araveendrann
+ */
+public class Reference {
+
+}
--- /dev/null
+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
+
+ }
+}
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;
}
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);
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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;
+ }
+
+}
//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());
--- /dev/null
+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);
+
+ }
+}
--- /dev/null
+{
+ "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
+}
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,
--- /dev/null
+<?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
-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
--- /dev/null
+{
+ "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
+}