Following the Plugin Migration, this commit brings in the Northbound migration.
Due to the nature of the Library rearchiteture, the northbound APIs should not assume any schema.
But unfortunately, that is not the case with the existing APIs and hence we have split the APIs as V2 (older version)
and the newer V3.
This commit just migrates the V2 APIs to the newer Infra. V3 will be added soon.
Also, the GET serailization is still pending and will be addressed in subsequent commit.
But, all the IT tests are passing in this version.
Change-Id: I7c0e59f41499dadb2215fef3d597f98b2efa3c13
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
<artifactId>ovsdb_plugin</artifactId>
<version>${ovsdb.plugin.version}</version>
</dependency>
-<!--
- TODO : Remove this comment once the Northbound migration is complete.
-
<dependency>
<groupId>org.opendaylight.ovsdb</groupId>
<artifactId>ovsdb_northbound</artifactId>
<version>${ovsdb.northbound.version}</version>
</dependency>
--->
<dependency>
<groupId>org.opendaylight.ovsdb</groupId>
<artifactId>ovsdb_schema.Open_vSwitch</artifactId>
<includes>
<include>**/*LibraryIT*</include>
<include>**/*PluginIT*</include>
+ <include>**/*NorthboundIT*</include>
</includes>
</configuration>
</execution>
package org.opendaylight.ovsdb.integrationtest;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.opendaylight.controller.sal.connection.ConnectionConstants;
+import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.ovsdb.lib.OvsdbClient;
import org.opendaylight.ovsdb.lib.OvsdbConnection;
import org.opendaylight.ovsdb.lib.OvsdbConnectionListener;
+import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
public abstract class OvsdbIntegrationTestBase {
protected final static String IDENTIFIER = "TEST";
return props;
}
+ public Node getPluginTestConnection() throws IOException, InterruptedException, ExecutionException, TimeoutException {
+ Properties props = loadProperties();
+ String addressStr = props.getProperty(SERVER_IPADDRESS);
+ String portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
+ String connectionType = props.getProperty(CONNECTION_TYPE, "active");
+
+ IConnectionServiceInternal connection = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+ // If the connection type is active, controller connects to the ovsdb-server
+ if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
+ if (addressStr == null) {
+ fail(usage());
+ }
+
+ Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
+ params.put(ConnectionConstants.ADDRESS, addressStr);
+ params.put(ConnectionConstants.PORT, portStr);
+ return connection.connect(IDENTIFIER, params);
+ } else if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_PASSIVE)) {
+ // Wait for 10 seconds for the Passive connection to be initiated by the ovsdb-server.
+ Thread.sleep(10000);
+ List<Node> nodes = connection.getNodes();
+ assertNotNull(nodes);
+ assertTrue(nodes.size() > 0);
+ return nodes.get(0);
+ }
+ fail("Connection parameter ("+CONNECTION_TYPE+") must be active or passive");
+ return null;
+ }
+
public OvsdbClient getTestConnection() throws IOException, InterruptedException, ExecutionException, TimeoutException {
Properties props = loadProperties();
String addressStr = props.getProperty(SERVER_IPADDRESS);
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeNotNull;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import org.opendaylight.controller.usermanager.IUserManager;
import org.opendaylight.ovsdb.integrationtest.ConfigurationBundles;
import org.opendaylight.ovsdb.integrationtest.OvsdbIntegrationTestBase;
-import org.opendaylight.ovsdb.lib.OvsdbClient;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExamParameterized;
@Inject
private BundleContext bc;
private Node node = null;
- private OvsdbClient client = null;
private IUserManager userManager;
@Parameterized.Parameters(name = "ApiTest{index}:{0}")
@Test
public void testApi() {
System.out.println("Running " + fTestCase + "...\n");
- /*
- * TODO : Remove this assumeNotNull once the new library migration is completed.
- */
- assumeNotNull(node);
+
Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter(USERNAME , PASSWORD));
String uri = BASE_URI + fPath;
fail("Unsupported operation");
}
assertEquals(fExpectedStatusCode, response.getStatus());
-
}
private String expand(String content){
assertTrue(this.userManager != null);
try {
- client = getTestConnection();
+ node = getPluginTestConnection();
} catch (Exception e) {
fail("Exception : "+e.getMessage());
}
ConfigurationBundles.controllerBundles(),
ConfigurationBundles.controllerNorthboundBundles(),
ConfigurationBundles.ovsdbLibraryBundles(),
+ ConfigurationBundles.ovsdbDefaultSchemaBundles(),
mavenBundle("org.opendaylight.ovsdb", "ovsdb_plugin").versionAsInProject(),
mavenBundle("org.opendaylight.ovsdb", "ovsdb_northbound").versionAsInProject(),
junitBundles()
import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperty;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-import java.io.IOException;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Properties;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.opendaylight.controller.sal.connection.ConnectionConstants;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.sal.utils.Status;
}
}
- public Node getPluginTestConnection() throws IOException, InterruptedException, ExecutionException, TimeoutException {
- Properties props = loadProperties();
- String addressStr = props.getProperty(SERVER_IPADDRESS);
- String portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
- String connectionType = props.getProperty(CONNECTION_TYPE, "active");
-
- IConnectionServiceInternal connection = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
- // If the connection type is active, controller connects to the ovsdb-server
- if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
- if (addressStr == null) {
- fail(usage());
- }
-
- Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
- params.put(ConnectionConstants.ADDRESS, addressStr);
- params.put(ConnectionConstants.PORT, portStr);
- return connection.connect(IDENTIFIER, params);
- } else if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_PASSIVE)) {
- // Wait for 10 seconds for the Passive connection to be initiated by the ovsdb-server.
- Thread.sleep(10000);
- List<Node> nodes = connection.getNodes();
- assertNotNull(nodes);
- assertTrue(nodes.size() > 0);
- return nodes.get(0);
- }
- fail("Connection parameter ("+CONNECTION_TYPE+") must be active or passive");
- return null;
- }
-
@Before
public void areWeReady() throws InterruptedException {
assertNotNull(bc);
import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
import org.opendaylight.ovsdb.lib.schema.TableSchema;
+import com.fasterxml.jackson.annotation.JsonIgnore;
-public class Column<E extends TableSchema<E>, D> {
+public class Column<E extends TableSchema<E>, D> {
+ @JsonIgnore
private ColumnSchema<E, D> schema;
private D data;
<artifactId>ovsdb_plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.1</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
</dependencies>
<build>
com.sun.jersey.spi.container.servlet,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.authorization,
+ org.opendaylight.ovsdb.plugin,
+ org.opendaylight.ovsdb.lib,
org.opendaylight.ovsdb.lib.table,
+ org.opendaylight.ovsdb.lib.jsonrpc,
org.opendaylight.ovsdb.lib.notation,
- org.opendaylight.ovsdb.plugin,
+ org.opendaylight.ovsdb.lib.database,
+ org.opendaylight.ovsdb.lib.operations,
+ org.opendaylight.ovsdb.lib.message,
+ org.opendaylight.ovsdb.lib.schema,
+ org.opendaylight.ovsdb.lib.schema.typed,
javax.ws.rs,
javax.ws.rs.core,
javax.xml.bind,
javax.xml.bind.annotation,
org.slf4j,
org.apache.catalina.filters,
- com.fasterxml.jackson.databind.annotation,
- com.fasterxml.jackson.annotation,
- !org.codehaus.enunciate.jaxrs</Import-Package>
+ !org.codehaus.enunciate.jaxrs,*</Import-Package>
<Export-Package></Export-Package>
- <Web-ContextPath>/ovsdb/nb/v2</Web-ContextPath>
+ <Web-ContextPath>/ovsdb/nb</Web-ContextPath>
<Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+++ /dev/null
-/*
- * Copyright (C) 2013 Red Hat, Inc.
- *
- * 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 : Madhu Venugopal, Brent Salisbury
- */
-package org.opendaylight.ovsdb.northbound;
-
-import org.opendaylight.ovsdb.lib.table.Bridge;
-import org.opendaylight.ovsdb.lib.table.Capability;
-import org.opendaylight.ovsdb.lib.table.Controller;
-import org.opendaylight.ovsdb.lib.table.IPFIX;
-import org.opendaylight.ovsdb.lib.table.Interface;
-import org.opendaylight.ovsdb.lib.table.Manager;
-import org.opendaylight.ovsdb.lib.table.Mirror;
-import org.opendaylight.ovsdb.lib.table.NetFlow;
-import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
-import org.opendaylight.ovsdb.lib.table.Port;
-import org.opendaylight.ovsdb.lib.table.Qos;
-import org.opendaylight.ovsdb.lib.table.Queue;
-import org.opendaylight.ovsdb.lib.table.SFlow;
-import org.opendaylight.ovsdb.lib.table.SSL;
-import org.opendaylight.ovsdb.lib.table.Table;
-
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-
-@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
-public class OVSDBRow {
- String parent_uuid;
- /*
- * MINIMAL_CLASS Directive expects a leading "." character on the class name and is lame.
- * Hence going with NAME directive even though it calls for SubTypes.
- * Since we are using fixed table types for the Hydrogen release, this is acceptable.
- * When we move towards Schema driven table definition, this is anyways not required.
-
- @JsonTypeInfo(
- use = JsonTypeInfo.Id.MINIMAL_CLASS,
- include = JsonTypeInfo.As.PROPERTY,
- property = "@class")
- */
-
- @JsonTypeInfo(
- use = JsonTypeInfo.Id.NAME,
- include = JsonTypeInfo.As.WRAPPER_OBJECT)
- @JsonSubTypes({
- @JsonSubTypes.Type(value=Bridge.class, name="Bridge"),
- @JsonSubTypes.Type(value=Capability.class, name="Capbility"),
- @JsonSubTypes.Type(value=Controller.class, name="Controller"),
- @JsonSubTypes.Type(value=Interface.class, name="Interface"),
- @JsonSubTypes.Type(value=Manager.class, name="Manager"),
- @JsonSubTypes.Type(value=Mirror.class, name="Mirror"),
- @JsonSubTypes.Type(value=NetFlow.class, name="NetFlow"),
- @JsonSubTypes.Type(value=Open_vSwitch.class, name="Open_vSwitch"),
- @JsonSubTypes.Type(value=Port.class, name="Port"),
- @JsonSubTypes.Type(value=Qos.class, name="QoS"),
- @JsonSubTypes.Type(value=Queue.class, name="Queue"),
- @JsonSubTypes.Type(value=SFlow.class, name="sFlow"),
- @JsonSubTypes.Type(value=SSL.class, name="SSL"),
- @JsonSubTypes.Type(value=IPFIX.class, name="IPFIX")
- })
- Table row;
-
- public OVSDBRow() {
- }
-
- public OVSDBRow(String parent_uuid, Table row) {
- this.parent_uuid = parent_uuid;
- this.row = row;
- }
-
- public String getParent_uuid() {
- return parent_uuid;
- }
- public void setParent_uuid(String parent_uuid) {
- this.parent_uuid = parent_uuid;
- }
- public Table getRow() {
- return row;
- }
- public void setRow(Table row) {
- this.row = row;
- }
-}
*/
package org.opendaylight.ovsdb.northbound;
-import java.util.List;
+import java.io.IOException;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.notation.Row;
import org.opendaylight.ovsdb.lib.notation.UUID;
-import org.opendaylight.ovsdb.lib.table.Table;
-import org.opendaylight.ovsdb.lib.table.Tables;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.plugin.Connection;
+import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+import org.opendaylight.ovsdb.plugin.OvsVswitchdSchemaConstants;
import org.opendaylight.ovsdb.plugin.StatusWithUuid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.JsonNode;
+
/**
* OVSDB Northbound REST API.<br>
* This class provides REST APIs to Create, Read, Update and Delete OVSDB Row in any of the ovsdb table
* HTTPS Authentication is disabled by default.
*/
-@Path("/")
-public class OVSDBNorthbound {
- protected static final Logger logger = LoggerFactory.getLogger(OVSDBNorthbound.class);
+@Path("/v2/")
+public class OvsdbNorthboundV2 {
+ protected static final Logger logger = LoggerFactory.getLogger(OvsdbNorthboundV2.class);
@Context
private UriInfo _uriInfo;
+ " : Table Name in URL does not match the row name in request body");
}
- private String getOVSTableName(String tableName) {
- List<Table> tables = Tables.getTables();
- for (Table table : tables) {
- if (table.getTableName().getName().equalsIgnoreCase(tableName)) {
- return table.getTableName().getName();
- }
- }
- // TODO Auto-generated method stub
- return null;
- }
-
/**
- * Create a Row
+ * Create a Row for Open_vSwitch schema
*
* @param nodeType type of node e.g OVS
* @param nodeId ID of the node
* @param tableName name of the OVSDB table
- * @param row the {@link OVSDBRow} Row that is being inserted
+ * @param row the {@link OvsdbRow} Row that is being inserted
*
* @return Response as dictated by the HTTP Response Status code
*
* }
* }
* </pre>
+ * @throws IOException
+ * @throws ExecutionException
+ * @throws InterruptedException
*/
@Path("/node/{nodeType}/{nodeId}/tables/{tableName}/rows")
@ResponseCode(code = 401, condition = "User not authorized to perform this operation")})
@Consumes({ MediaType.APPLICATION_JSON})
public Response addRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
- @PathParam("tableName") String tableName, @TypeHint(OVSDBRow.class) OVSDBRow row) {
+ @PathParam("tableName") String tableName, JsonNode rowJson) throws IOException, InterruptedException, ExecutionException {
if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation");
}
- String ovsTableName = getOVSTableName(tableName);
- if (ovsTableName == null) {
- Status status = new Status(StatusCode.NOTFOUND, "Table "+tableName+" is not currently supported");
- return NorthboundUtils.getResponse(status);
- }
-
OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
this);
if (ovsdbTable == null) {
throw new ServiceUnavailableException("OVS Configuration Service " + RestMessages.SERVICEUNAVAILABLE.toString());
}
- if (row != null && row.getRow() != null) {
- handleNameMismatch(tableName, row.getRow().getTableName().getName());
- Node node = Node.fromString(nodeType, nodeId);
- StatusWithUuid statusWithUUID = ovsdbTable.insertRow(node, ovsTableName, row.getParent_uuid(), row.getRow());
-
- if (statusWithUUID.isSuccess()) {
- UUID uuid = statusWithUUID.getUuid();
- return Response.status(Response.Status.CREATED)
- .header("Location", String.format("%s/%s", _uriInfo.getAbsolutePath().toString(),
- uuid.toString()))
- .entity(uuid.toString())
- .build();
- } else {
- return NorthboundUtils.getResponse(statusWithUUID);
- }
+ Node node = Node.fromString(nodeType, nodeId);
+ IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+ Connection connection = connectionService.getConnection(node);
+ OvsdbClient client = connection.getClient();
+ OvsdbRow localRow = OvsdbRow.fromJsonNode(client, OvsVswitchdSchemaConstants.DATABASE_NAME, rowJson);
+ String bckCompatibleTableName = this.getBackwardCompatibleTableName(client, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
+
+ if (localRow == null) {
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+
+ StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, bckCompatibleTableName, localRow.getParentUuid(), localRow.getRow());
+
+ if (statusWithUuid.isSuccess()) {
+ UUID uuid = statusWithUuid.getUuid();
+ return Response.status(Response.Status.CREATED)
+ .header("Location", String.format("%s/%s", _uriInfo.getAbsolutePath().toString(),
+ uuid.toString()))
+ .entity(uuid.toString())
+ .build();
}
- return Response.status(Response.Status.BAD_REQUEST).build();
+ return NorthboundUtils.getResponse(statusWithUuid);
}
/**
@ResponseCode(code = 400, condition = "Invalid data passed"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation")})
@Consumes({ MediaType.APPLICATION_JSON})
- @TypeHint(OVSDBRow.class)
- public OVSDBRow getRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
+ @TypeHint(Row.class)
+ public Row getRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
@PathParam("tableName") String tableName, @PathParam("rowUuid") String rowUuid) {
if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation");
}
- String ovsTableName = getOVSTableName(tableName);
- if (ovsTableName == null) return null;
-
OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
this);
if (ovsdbTable == null) {
}
Node node = Node.fromString(nodeType, nodeId);
- Table<?> row = null;
+ IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+ Connection connection = connectionService.getConnection(node);
+ OvsdbClient client = connection.getClient();
+ String bckCompatibleTableName = this.getBackwardCompatibleTableName(client, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
+
+ Row row = null;
try {
- row = ovsdbTable.getRow(node, ovsTableName, rowUuid);
+ row = ovsdbTable.getRow(node, bckCompatibleTableName, rowUuid);
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
- return new OVSDBRow(null, row);
+ return row;
}
/**
@ResponseCode(code = 400, condition = "Invalid data passed"),
@ResponseCode(code = 401, condition = "User not authorized to perform this operation")})
@Consumes({ MediaType.APPLICATION_JSON})
- @TypeHint(OVSDBRows.class)
- public OVSDBRows getAllRows(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
+ @TypeHint(OvsdbRows.class)
+ public OvsdbRows getAllRows(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
@PathParam("tableName") String tableName) {
if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation");
}
- String ovsTableName = getOVSTableName(tableName);
- if (ovsTableName == null) return null;
-
OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
this);
if (ovsdbTable == null) {
}
Node node = Node.fromString(nodeType, nodeId);
- Map<String, Table<?>> rows = null;
+ IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+ Connection connection = connectionService.getConnection(node);
+ OvsdbClient client = connection.getClient();
+ String bckCompatibleTableName = this.getBackwardCompatibleTableName(client, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
+ Map<String, Row> rows = null;
try {
- rows = ovsdbTable.getRows(node, ovsTableName);
+ rows = ovsdbTable.getRows(node, bckCompatibleTableName);
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
- return new OVSDBRows(rows);
+ return new OvsdbRows(rows);
}
+ /*
/**
* Update a Row
*
@Consumes({ MediaType.APPLICATION_JSON})
public Response updateRow(@PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
@PathParam("tableName") String tableName, @PathParam("rowUuid") String rowUuid,
- @TypeHint(OVSDBRow.class) OVSDBRow row) {
+ JsonNode rowJson) {
if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
throw new UnauthorizedException("User is not authorized to perform this operation");
}
- String ovsTableName = getOVSTableName(tableName);
- if (ovsTableName == null) {
- Status status = new Status(StatusCode.NOTFOUND, "Table "+tableName+" is not currently supported");
- return NorthboundUtils.getResponse(status);
- }
-
OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
this);
if (ovsdbTable == null) {
- throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+ throw new ServiceUnavailableException("OVS Configuration Service " + RestMessages.SERVICEUNAVAILABLE.toString());
}
- if (row != null && row.getRow() != null) {
- handleNameMismatch(tableName, row.getRow().getTableName().getName());
- Node node = Node.fromString(nodeType, nodeId);
- Status status = ovsdbTable.updateRow(node, ovsTableName, row.getParent_uuid(), rowUuid, row.getRow());
- return NorthboundUtils.getResponse(status);
+ Node node = Node.fromString(nodeType, nodeId);
+ IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+ Connection connection = connectionService.getConnection(node);
+ OvsdbClient client = connection.getClient();
+ String bckCompatibleTableName = this.getBackwardCompatibleTableName(client, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
+ OvsdbRow localRow = OvsdbRow.fromJsonNode(client, OvsVswitchdSchemaConstants.DATABASE_NAME, rowJson);
+
+ if (localRow == null) {
+ return Response.status(Response.Status.BAD_REQUEST).build();
}
- return Response.status(Response.Status.BAD_REQUEST).build();
+
+ Status status = ovsdbTable.updateRow(node, bckCompatibleTableName, localRow.getParentUuid(), rowUuid, localRow.getRow());
+ return NorthboundUtils.getResponse(status);
}
/**
* DELETE http://localhost:8080/ovsdb/nb/v2/node/OVS/HOST1/tables/manager/rows/6f4c602c-026f-4390-beea-d50d6d448100
* </pre>
*/
+
@Path("/node/{nodeType}/{nodeId}/tables/{tableName}/rows/{uuid}")
@DELETE
@StatusCodes({ @ResponseCode(code = 204, condition = "User Deleted Successfully"),
throw new UnauthorizedException("User is not authorized to perform this operation");
}
- String ovsTableName = getOVSTableName(tableName);
- if (ovsTableName == null) {
- Status status = new Status(StatusCode.NOTFOUND, "Table "+tableName+" is not currently supported");
- return NorthboundUtils.getResponse(status);
- }
-
- OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+ OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class,
+ this);
if (ovsdbTable == null) {
- throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+ throw new ServiceUnavailableException("OVS Configuration Service " + RestMessages.SERVICEUNAVAILABLE.toString());
}
+
Node node = Node.fromString(nodeType, nodeId);
- Status status = ovsdbTable.deleteRow(node, ovsTableName, uuid);
+ IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+ Connection connection = connectionService.getConnection(node);
+ OvsdbClient client = connection.getClient();
+ String bckCompatibleTableName = this.getBackwardCompatibleTableName(client, OvsVswitchdSchemaConstants.DATABASE_NAME, tableName);
+
+ Status status = ovsdbTable.deleteRow(node, bckCompatibleTableName, uuid);
if (status.isSuccess()) {
return Response.noContent().build();
}
return NorthboundUtils.getResponse(status);
}
+
+ private String getBackwardCompatibleTableName(OvsdbClient client, String databaseName, String tableName) {
+ DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
+ if (dbSchema == null || tableName == null) return tableName;
+ for (String dbTableName : dbSchema.getTables()) {
+ if (dbTableName.equalsIgnoreCase(tableName)) return dbTableName;
+ }
+ return tableName;
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc. and others
+ *
+ * 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 : Madhu Venugopal
+ */
+package org.opendaylight.ovsdb.northbound;
+
+import javax.ws.rs.Path;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+* OVSDB Northbound V3 REST API.<br>
+*/
+
+@Path("/v3/")
+public class OvsdbNorthboundV3 {
+ protected static final Logger logger = LoggerFactory.getLogger(OvsdbNorthboundV3.class);
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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 : Madhu Venugopal, Brent Salisbury
+ */
+package org.opendaylight.ovsdb.northbound;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.concurrent.ExecutionException;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.notation.Row;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class OvsdbRow {
+ private static final String PARENTUUID = "parent_uuid";
+ private static final String ROW = "row";
+
+ @XmlElement(name=PARENTUUID)
+ String parentUuid;
+
+ String tableName;
+
+ @XmlElement(name=ROW)
+ Row<GenericTableSchema> row;
+
+ public OvsdbRow() {
+ }
+
+ public OvsdbRow(String parentUuid, String tableName, Row<GenericTableSchema> row) {
+ this.parentUuid = parentUuid;
+ this.tableName = tableName;
+ this.row = row;
+ }
+
+ public static OvsdbRow fromJsonNode(OvsdbClient client, String dbName, JsonNode json) {
+ JsonNode parentUuidNode = json.get(PARENTUUID);
+ String parentUuid = null;
+ if (parentUuidNode != null) parentUuid = parentUuidNode.asText();
+
+ JsonNode rowNode = json.get(ROW);
+ if (rowNode == null) return null;
+ for(Iterator<String> fieldNames = rowNode.fieldNames(); fieldNames.hasNext();) {
+ String tableName = fieldNames.next();
+ Row<GenericTableSchema> row = null;
+ try {
+ row = getRow(client, dbName, tableName, rowNode.get(tableName));
+ } catch (InterruptedException | ExecutionException | IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ return new OvsdbRow(parentUuid, tableName, row);
+ }
+ return null;
+ }
+
+ public static Row<GenericTableSchema> getRow(OvsdbClient client, String dbName, String tableName, JsonNode rowJson) throws InterruptedException, ExecutionException, JsonParseException, IOException {
+ DatabaseSchema dbSchema = client.getSchema(dbName).get();
+ GenericTableSchema schema = dbSchema.table(tableName, GenericTableSchema.class);
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.setSerializationInclusion(Include.NON_NULL);
+ Row<GenericTableSchema> row = schema.createRow((ObjectNode)rowJson);
+ return row;
+ }
+
+ public String getParentUuid() {
+ return parentUuid;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public Row<GenericTableSchema> getRow() {
+ return row;
+ }
+
+ @Override
+ public String toString() {
+ return "OVSDBRow [parentUuid=" + parentUuid + ", tableName="
+ + tableName + ", row=" + row + "]";
+ }
+}
import java.util.Map;
-import org.opendaylight.ovsdb.lib.table.Table;
+import org.opendaylight.ovsdb.lib.notation.Row;
-public class OVSDBRows {
- Map<String, Table<?>> rows;
+public class OvsdbRows {
+ Map<String, Row> rows;
- public OVSDBRows(Map<String, Table<?>> rows) {
+ public OvsdbRows(Map<String, Row> rows) {
super();
this.rows = rows;
}
- public Map<String, Table<?>> getRows() {
+ public Map<String, Row> getRows() {
return rows;
}
- public void setRows(Map<String, Table<?>> rows) {
+ public void setRows(Map<String, Row> rows) {
this.rows = rows;
}
}
* plugin layer.
*/
public String getSpecialCaseParentUUID(Node node, String databaseName, String childTableName) {
- if (databaseName.equals(OvsVswitchdSchemaConstants.DATABASE_NAME) && childTableName.equals("Bridge")) {
+ if (!databaseName.equals(OvsVswitchdSchemaConstants.DATABASE_NAME)) return null;
+ String[] parentColumn = OvsVswitchdSchemaConstants.getParentColumnToMutate(childTableName);
+ if (parentColumn != null && parentColumn[0].equals(OvsVswitchdSchemaConstants.DATABASE_NAME)) {
Connection connection = connectionService.getConnection(node);
OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
ConcurrentMap<String, Row> row = this.getRows(node, openVSwitch.getSchema().getName());
String parentTable, String parentColumn, String uuid, TransactionBuilder transactionBuilder) {
DatabaseSchema dbSchema = client.getDatabaseSchema(databaseName);
TableSchema<GenericTableSchema> childTableSchema = dbSchema.table(childTable, GenericTableSchema.class);
- TableSchema<GenericTableSchema> parentTableSchema = dbSchema.table(parentTable, GenericTableSchema.class);
- ColumnSchema<GenericTableSchema, UUID> parentColumnSchema = parentTableSchema.column(parentColumn, UUID.class);
if (parentColumn != null) {
+ TableSchema<GenericTableSchema> parentTableSchema = dbSchema.table(parentTable, GenericTableSchema.class);
+ ColumnSchema<GenericTableSchema, UUID> parentColumnSchema = parentTableSchema.column(parentColumn, UUID.class);
transactionBuilder
.add(op.mutate(parentTableSchema)
.addMutation(parentColumnSchema, Mutator.DELETE, new UUID(uuid))
ConcurrentMap<String, ConcurrentMap<String,Row>> retMap = Maps.newConcurrentMap();
for (String tableName : tdbMap.keySet()) {
TableDB tdb = tdbMap.get(tableName);
- retMap.put(tableName, tdb.getTableCache(tableName));
+ if (tdb != null && tdb.getTableCache(tableName) != null) retMap.put(tableName, tdb.getTableCache(tableName));
}
return retMap;
}
addParentColumnToMutate("Interface", "Port", "interfaces");
addParentColumnToMutate("SSL", "Open_vSwitch", "ssl");
addParentColumnToMutate("IPFIX", "Bridge", "ipfix");
- addParentColumnToMutate("SFlow", "Bridge", "sflow");
- addParentColumnToMutate("Qos", "Port", "qos");
- addParentColumnToMutate("Netflow", "Bridge", "netflow");
+ addParentColumnToMutate("sFlow", "Bridge", "sflow");
+ addParentColumnToMutate("Flow_Table", "Bridge", "flow_tables");
+ addParentColumnToMutate("QoS", "Port", "qos");
+ addParentColumnToMutate("NetFlow", "Bridge", "netflow");
addParentColumnToMutate("Mirror", "Bridge", "mirrors");
addParentColumnToMutate("Manager", "Open_vSwitch", "manager_options");
addParentColumnToMutate("Controller", "Bridge", "controller");
<module>plugin</module>
<module>commons/parent</module>
<module>commons/integrationtest</module>
+ <module>northbound</module>
<!--
TODO : remove this comment & let these modules build once the Library migraion is complete.
- <module>northbound</module>
<module>neutron</module>
<module>distribution/opendaylight</module>
-->