ONOS-5504: Added REST API for administering OFAgent.

Change-Id: Idc9a18fc82ec23fbb8348fe213f8007e362253ac
This commit is contained in:
Jovana Vuleta 2017-05-01 12:18:00 +02:00 committed by Yoonseon Han
parent 18ffcc738e
commit fe32db7d4c
18 changed files with 1134 additions and 0 deletions

View File

@ -10,12 +10,16 @@ COMPILE_DEPS = [
'//lib:netty-codec',
'//lib:netty-handler',
'//lib:openflowj-3.0',
'//lib:javax.ws.rs-api',
'//utils/rest:onlab-rest',
]
TEST_DEPS = [
'//lib:TEST_ADAPTERS',
'//core/api:onos-api-tests',
'//core/common:onos-core-common-tests',
'//lib:TEST_REST',
'//lib:jersey-server',
]
EXCLUDED_BUNDLES = [
@ -25,6 +29,7 @@ EXCLUDED_BUNDLES = [
osgi_jar_with_tests (
deps = COMPILE_DEPS,
test_deps = TEST_DEPS,
web_context = '/onos/v1/ofagent',
)
onos_app (

View File

@ -73,6 +73,8 @@
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
@ -126,6 +128,49 @@
<artifactId>netty-all</artifactId>
<version>${netty4.version}</version>
</dependency>
<!-- REST api dependencies -->
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-rest</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@ -136,9 +181,18 @@
<extensions>true</extensions>
<configuration>
<instructions>
<_wab>src/main/webapp/</_wab>
<Include-Resource>
WEB-INF/classes/apidoc/swagger.json=target/swagger.json,
{maven-resources}
</Include-Resource>
<Embed-Dependency>
openflowj
</Embed-Dependency>
<Import-Package>
*,org.glassfish.jersey.servlet
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>

View File

@ -0,0 +1,75 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ofagent.rest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Sets;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.ofagent.api.OFAgent;
import org.onosproject.ofagent.api.OFController;
import org.onosproject.ofagent.impl.DefaultOFAgent;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* OpenFlow agent JSON codec.
*/
public final class OFAgentCodec extends JsonCodec<OFAgent> {
@Override
public ObjectNode encode(OFAgent ofAgent, CodecContext context) {
checkNotNull(ofAgent, "OFAgent cannot be null");
ObjectMapper mapper = context.mapper();
ObjectNode ofAgentNode = mapper.createObjectNode();
ofAgentNode
.put("networkId", ofAgent.networkId().toString())
.put("state", ofAgent.state().toString());
ArrayNode controllers = mapper.createArrayNode();
ofAgent.controllers().forEach(ofController -> controllers.add((new OFControllerCodec()).encode(ofController,
context)));
ofAgentNode.set("controllers", controllers);
return ofAgentNode;
}
public OFAgent decode(ObjectNode json, CodecContext context) {
JsonNode networkId = json.get("networkId");
checkNotNull(networkId);
checkNotNull(json.get("controllers"));
checkState(json.get("controllers").isArray());
Set<OFController> controllers = Sets.newHashSet();
json.get("controllers").forEach(jsonController -> controllers.add((new
OFControllerCodec()).decode((ObjectNode) jsonController, context)));
return DefaultOFAgent.builder()
.networkId(NetworkId.networkId(networkId.asLong()))
.controllers(controllers)
.state(OFAgent.State.STOPPED)
.build();
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ofagent.rest;
import org.onlab.rest.AbstractWebApplication;
import java.util.Set;
/**
* OFAgent Web application.
*/
public class OFAgentWebApplication extends AbstractWebApplication {
@Override
public Set<Class<?>> getClasses() {
return getClasses(OFAgentWebResource.class);
}
}

View File

@ -0,0 +1,241 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ofagent.rest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.ofagent.api.OFAgent;
import org.onosproject.ofagent.api.OFAgentAdminService;
import org.onosproject.ofagent.api.OFAgentService;
import org.onosproject.rest.AbstractWebResource;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import static javax.ws.rs.core.Response.Status.*;
/**
* Manage virtual switch and controller mapping.
*/
@Path("service")
public class OFAgentWebResource extends AbstractWebResource {
private static final String OFAGENT_NOT_FOUND = "OFAgent not found";
private static final String OFAGENTS_NOT_FOUND = "OFAgent set not found";
private static final String OFAGENT_CREATED = "OFAgent created";
private static final String OFAGENT_NOT_CREATED = "OFAgent not created";
private static final String OFAGENT_STARTED = "OFAgent started";
private static final String OFAGENT_NOT_STARTED = "OFAgent not started";
private static final String OFAGENT_UPDATED = "OFAgent updated";
private static final String OFAGENT_NOT_UPDATED = "OFAgent not updated";
/**
* Lists OpenFlow agents.
* Shows OpenFlow agents for all virtual networks.
*
* @return 200 OK if set exists, 500 INTERNAL SERVER ERROR otherwise
*/
@GET
@Path("ofagents")
public Response listOFAgents() {
OFAgentService service = get(OFAgentService.class);
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = mapper.createObjectNode();
ArrayNode ofAgentsArray = mapper.createArrayNode();
if (service.agents() == null) {
return Response.status(INTERNAL_SERVER_ERROR)
.entity(OFAGENTS_NOT_FOUND).build();
} else {
service.agents().forEach(ofAgent -> ofAgentsArray.add((new OFAgentCodec()).encode(ofAgent, this)));
root.set("ofAgents", ofAgentsArray);
return Response.ok(root, MediaType.APPLICATION_JSON_TYPE).build();
}
}
/**
* Lists OpenFlow agent.
* Shows OpenFlow agent for given network.
*
* @param networkId OFAgent networkId
* @return 200 OK if OFAgent exists, 404 NOT FOUND otherwise
*/
@GET
@Path("ofagent/{networkId}")
public Response listOFAgent(@PathParam("networkId") long networkId) {
OFAgentService service = get(OFAgentService.class);
OFAgent ofAgent = service.agent(NetworkId.networkId(networkId));
if (ofAgent == null) {
return Response.status(NOT_FOUND)
.entity(OFAGENT_NOT_FOUND).build();
} else {
return Response.ok((new OFAgentCodec()).encode(ofAgent, this), MediaType
.APPLICATION_JSON_TYPE)
.build();
}
}
/**
* Adds a new OpenFlow agent.
* Creates a new OpenFlow agent and adds it to OpenFlow agent store.
*
* @param stream JSON stream
* @return 201 CREATED , 400 BAD REQUEST if stream cannot be decoded to OFAgent
* @throws IOException if request cannot be parsed
*/
@POST
@Path("ofagent-create")
@Consumes(MediaType.APPLICATION_JSON)
public Response createOFAgent(InputStream stream) throws IOException {
OFAgentAdminService adminService = get(OFAgentAdminService.class);
OFAgent ofAgent = (new OFAgentCodec()).decode((ObjectNode) mapper().readTree(stream), this);
if (ofAgent == null) {
return Response.status(BAD_REQUEST)
.entity(OFAGENT_NOT_CREATED).build();
} else {
adminService.createAgent(ofAgent);
return Response.status(CREATED).entity(OFAGENT_CREATED).build();
}
}
/**
* Starts OpenFlow agent.
* Starts OpenFlow agent for the given network.
*
* @param stream JSON stream
* @return 200 OK if OFAgent was started, 404 NOT FOUND when OF agent does not exist, 400 BAD REQUEST otherwise
* @throws IOException if request cannot be parsed
*/
@POST
@Path("ofagent-start")
@Consumes(MediaType.APPLICATION_JSON)
public Response startOFAgent(InputStream stream) throws IOException {
OFAgentAdminService adminService = get(OFAgentAdminService.class);
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
JsonNode networkId = jsonTree.get("networkId");
if (networkId == null) {
return Response.status(BAD_REQUEST)
.entity(OFAGENT_NOT_STARTED).build();
} else if (get(OFAgentService.class).agent(NetworkId.networkId(networkId.asLong())) == null) {
return Response.status(NOT_FOUND)
.entity(OFAGENT_NOT_STARTED).build();
} else {
adminService.startAgent(NetworkId.networkId(networkId.asLong()));
return Response.status(OK).entity(OFAGENT_STARTED).build();
}
}
/**
* Updates OpenFlow agent.
* Updates existing OpenFlow agent for the given network.
*
* @param stream JSON stream
* @return 200 OK if OFAgent was updated, 404 NOT FOUND when OF agent does not exist, 400 BAD REQUEST otherwise
* @throws IOException if request cannot be parsed
*/
@PUT
@Path("ofagent-update")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateOFAgent(InputStream stream) throws IOException {
OFAgentAdminService adminService = get(OFAgentAdminService.class);
OFAgent ofAgent = (new OFAgentCodec()).decode((ObjectNode) mapper().readTree(stream), this);
if (ofAgent == null) {
return Response.status(NOT_FOUND)
.entity(OFAGENT_NOT_UPDATED).build();
} else if (get(OFAgentService.class).agent(ofAgent.networkId()) == null) {
return Response.status(NOT_FOUND)
.entity(OFAGENT_NOT_UPDATED).build();
}
adminService.updateAgent(ofAgent);
return Response.status(OK).entity(OFAGENT_UPDATED).build();
}
/**
* Stops OFAgent.
* Stops OFAgent for the given virtual network.
*
* @param stream JSON stream
* @return 204 NO CONTENT if OpenFlow agent was stopped, 404 NOT FOUND otherwise
* @throws IOException if request cannot be parsed
*/
@POST
@Path("ofagent-stop")
@Consumes(MediaType.APPLICATION_JSON)
public Response stopOFAgent(InputStream stream) throws IOException {
OFAgentAdminService adminService = get(OFAgentAdminService.class);
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
JsonNode networkId = jsonTree.get("networkId");
if (get(OFAgentService.class).agent(NetworkId.networkId(networkId.asLong())) == null) {
return Response.status(NOT_FOUND)
.entity(OFAGENT_NOT_FOUND).build();
}
adminService.stopAgent(NetworkId.networkId(networkId.asLong()));
return Response.noContent().build();
}
/**
* Deletes OFAgent.
* Removes OFAgent for the given virtual network from repository.
*
* @param networkId OFAgent networkId
* @return 200 OK if OFAgent was removed, 404 NOT FOUND when OF agent does not exist, 400 BAD REQUEST otherwise
*/
@DELETE
@Path("ofagent-remove/{networkId}")
public Response removeOFAgent(@PathParam("networkId") long networkId) {
if (get(OFAgentService.class).agent(NetworkId.networkId(networkId)) == null) {
return Response.status(BAD_REQUEST)
.entity(OFAGENT_NOT_FOUND).build();
}
OFAgentAdminService adminService = get(OFAgentAdminService.class);
OFAgent removed = adminService.removeAgent(NetworkId.networkId(networkId));
if (removed != null) {
return Response.ok((new OFAgentCodec()).encode(removed, this), MediaType
.APPLICATION_JSON_TYPE)
.build();
} else {
return Response.status(NOT_FOUND)
.entity(OFAGENT_NOT_FOUND).build();
}
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ofagent.rest;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.ofagent.api.OFController;
import org.onosproject.ofagent.impl.DefaultOFController;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* OFController JSON codec.
*/
public final class OFControllerCodec extends JsonCodec<OFController> {
private static final String IP = "ip";
private static final String PORT = "port";
private static final String MISSING_MEMBER_MESSAGE = " member is required in OFController";
@Override
public ObjectNode encode(OFController ofController, CodecContext context) {
checkNotNull(ofController, "OFController cannot be null");
return context.mapper().createObjectNode()
.put(IP, String.valueOf(ofController.ip()))
.put(PORT, String.valueOf(ofController.port()));
}
@Override
public OFController decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
return null;
}
// parse ip address
int id = nullIsIllegal(json.get(IP), IP + MISSING_MEMBER_MESSAGE).asInt();
// parse port
String name = nullIsIllegal(json.get(PORT), PORT + MISSING_MEMBER_MESSAGE).asText();
return DefaultOFController.of(IpAddress.valueOf(id),
TpPort.tpPort(Integer.valueOf(name)));
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* REST API for OFAgent.
*/
package org.onosproject.ofagent.rest;

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2017-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>OFAgent REST API v1.0</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.onosproject.ofagent.rest.OFAgentWebApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

View File

@ -0,0 +1,525 @@
/*
* Copyright 2017-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ofagent.rest;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.Sets;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onlab.rest.BaseResource;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.ofagent.api.OFAgent;
import org.onosproject.ofagent.api.OFAgentAdminService;
import org.onosproject.ofagent.api.OFAgentService;
import org.onosproject.ofagent.api.OFController;
import org.onosproject.ofagent.impl.DefaultOFAgent;
import org.onosproject.ofagent.impl.DefaultOFController;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.Set;
import static org.easymock.EasyMock.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.onosproject.ofagent.api.OFAgent.State.STOPPED;
/**
* Test class for OFAgent application REST resource.
*/
public class OFAgentWebResourceTest extends JerseyTest {
private static final Set<OFController> CONTROLLER_SET_1 = Sets.newHashSet(
DefaultOFController.of(
IpAddress.valueOf("147.91.1.4"),
TpPort.tpPort(6633)));
private static final Set<OFController> CONTROLLER_SET_2 = Sets.newHashSet(
DefaultOFController.of(
IpAddress.valueOf("147.91.4.25"),
TpPort.tpPort(6633)),
DefaultOFController.of(
IpAddress.valueOf("147.91.4.27"),
TpPort.tpPort(6653)));
private static final Set<OFController> CONTROLLER_SET = Sets.newHashSet(
DefaultOFController.of(
IpAddress.valueOf("147.91.2.11"),
TpPort.tpPort(6633)),
DefaultOFController.of(
IpAddress.valueOf("147.91.2.9"),
TpPort.tpPort(6633)),
DefaultOFController.of(
IpAddress.valueOf("147.91.2.17"),
TpPort.tpPort(6653)));
private static final NetworkId NETWORK_1 = NetworkId.networkId(1);
private static final NetworkId NETWORK_2 = NetworkId.networkId(2);
private static final NetworkId NETWORK = NetworkId.networkId(3);
private static final OFAgent OF_AGENT = DefaultOFAgent.builder()
.networkId(NETWORK)
.controllers(CONTROLLER_SET)
.state(STOPPED)
.build();
private Set<OFAgent> agents = Sets.newHashSet(DefaultOFAgent.builder()
.networkId(NETWORK_1)
.controllers(CONTROLLER_SET_1)
.state(STOPPED)
.build(),
DefaultOFAgent.builder()
.networkId(NETWORK_2)
.controllers(CONTROLLER_SET_2)
.state(STOPPED)
.build(),
OF_AGENT);
private Set<OFAgent> empty = Sets.newHashSet();
private final OFAgentAdminService mockOFAgentAdminService = createMock(OFAgentAdminService.class);
private final OFAgentService mockOFAgentService = createMock(OFAgentService.class);
/**
* Constructs OFAgent Web application test instance.
*/
public OFAgentWebResourceTest() {
super(ResourceConfig.forApplicationClass(OFAgentWebApplication.class));
}
/**
* Sets up the global values for all the tests.
*/
@Before
public void setUpMocks() {
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(OFAgentAdminService.class, mockOFAgentAdminService)
.add(OFAgentService.class, mockOFAgentService);
BaseResource.setServiceDirectory(testDirectory);
}
/**
* Cleans up.
*/
@After
public void tearDownMocks() {
}
/**
* Tests the result of the rest api GET when there are OFAgents.
*
* @throws IOException
*/
@Test
public void testNonEmptyOFAgentSet() throws IOException {
expect(mockOFAgentService.agents()).andReturn(agents).anyTimes();
replay(mockOFAgentService);
final WebTarget wt = target();
assertNotNull("WebTarget is null", wt);
assertNotNull("WebTarget request is null", wt.request());
final String response = wt.path("service/ofagents").request().get(String.class);
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("ofAgents"));
mockOFAgentService.agents().forEach(ofAgent -> {
String expectedJsonStringNetworkId = "\"networkId\":\"" + ofAgent.networkId().id() + "\"";
assertThat(response, containsString(expectedJsonStringNetworkId));
String expectedJsonStringState = "\"state\":\"" + ofAgent.state() + "\"";
assertThat(response, containsString(expectedJsonStringState));
ofAgent.controllers().forEach(ofController -> {
String expectedJsonStringIP = "\"ip\":\"" + ofController.ip() + "\"";
assertThat(response, containsString(expectedJsonStringIP));
String expectedJsonStringPort = "\"port\":\"" + ofController.port() + "\"";
assertThat(response, containsString(expectedJsonStringPort));
});
});
verify(mockOFAgentService);
}
/**
* Tests the result of the rest api GET when there are no OFAgents.
*
* @throws IOException
*/
@Test
public void testEmptyOFAgentSet() throws IOException {
expect(mockOFAgentService.agents()).andReturn(empty).anyTimes();
replay(mockOFAgentService);
final WebTarget wt = target();
assertNotNull("WebTarget is null", wt);
assertNotNull("WebTarget request is null", wt.request());
final String response = wt.path("service/ofagents").request().get(String.class);
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(response, is("{\"ofAgents\":[]}"));
verify(mockOFAgentService);
}
/**
* Tests the result of the rest api GET for OFAgent.
*
* @throws IOException
*/
@Test
public void testOFAgent() throws IOException {
expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
replay(mockOFAgentService);
final WebTarget wt = target();
assertNotNull("WebTarget is null", wt);
assertNotNull("WebTarget request is null", wt.request());
final Response response = wt.path("service/ofagent/" + NETWORK).request().get();
final JsonObject result = Json.parse(response.readEntity(String.class)).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(3));
assertThat(result.get("networkId").asString(), is(NETWORK.id().toString()));
assertThat(result.get("state").asString(), is(STOPPED.toString()));
verify(mockOFAgentService);
}
/**
* Tests the result of the rest api GET for non-existent OFAgent.
*
* @throws IOException
*/
@Test
public void testNonExistentOFAgent() throws IOException {
expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
replay(mockOFAgentService);
final WebTarget wt = target();
assertNotNull("WebTarget is null", wt);
assertNotNull("WebTarget request is null", wt.request());
final Response response = wt.path("service/ofagent/" + NETWORK_1).request().get();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
verify(mockOFAgentService);
}
/**
* Tests creating an OFAgent with POST.
*/
@Test
public void testOFAgentCreate() {
mockOFAgentAdminService.createAgent(anyObject());
expectLastCall().anyTimes();
replay(mockOFAgentAdminService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-ofagent-create.json");
assertNotNull("post-ofagent-create.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-create")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
verify(mockOFAgentAdminService);
}
/**
* Tests creating an OFAgent with bad POST request.
*/
@Test
public void testOFAgentCreateBadRequest() {
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-bad-request.json");
assertNotNull("post-bad-request.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-create")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
}
/**
* Tests updating an OFAgent with PUT.
*/
@Test
public void testOFAgentUpdate() {
expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
replay(mockOFAgentService);
mockOFAgentAdminService.updateAgent(anyObject());
expectLastCall().anyTimes();
replay(mockOFAgentAdminService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("put-ofagent-update.json");
assertNotNull("put-ofagent-update.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-update")
.request(MediaType.APPLICATION_JSON_TYPE)
.put(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
assertThat(response.readEntity(String.class), containsString("OFAgent updated"));
verify(mockOFAgentService);
verify(mockOFAgentAdminService);
}
/**
* Tests non-existent OFAgent updating with PUT.
*/
@Test
public void testNonExistentOFAgentUpdate() {
expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
replay(mockOFAgentService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("put-non-existent-ofagent-update.json");
assertNotNull("put-non-existent-ofagent-update.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-update")
.request(MediaType.APPLICATION_JSON_TYPE)
.put(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
verify(mockOFAgentService);
}
/**
* Tests OFAgent updating with bad PUT request.
*/
@Test
public void testOFAgentUpdateBadRequest() {
expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
replay(mockOFAgentService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("put-bad-request.json");
assertNotNull("put-bad-request.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-update")
.request(MediaType.APPLICATION_JSON_TYPE)
.put(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
verify(mockOFAgentService);
}
/**
* Tests starting an OFAgent with POST.
*/
@Test
public void testOFAgentStart() {
expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
replay(mockOFAgentService);
mockOFAgentAdminService.startAgent(anyObject());
expectLastCall().anyTimes();
replay(mockOFAgentAdminService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-ofagent-start.json");
assertNotNull("post-ofagent-create.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-start")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
// assertThat(response.readEntity(String.class), containsString("OFAgent started"));
assertThat(response.readEntity(String.class), is("OFAgent started"));
verify(mockOFAgentService);
verify(mockOFAgentAdminService);
}
/**
* Tests non-existent OFAgent starting with POST.
*/
@Test
public void testNonExistentOFAgentStart() {
expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(null).anyTimes();
replay(mockOFAgentService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-non-existent-ofagent-start.json");
assertNotNull("post-non-existent-ofagent-start.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-start")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
verify(mockOFAgentService);
}
/**
* Tests OFAgent starting with bad POST request.
*/
@Test
public void testOFAgentStartBadRequest() {
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-bad-request.json");
assertNotNull("post-bad-request.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-start")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
}
/**
* Tests stopping an OFAgent with POST.
*/
@Test
public void testOFAgentStop() {
expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
replay(mockOFAgentService);
mockOFAgentAdminService.stopAgent(anyObject());
expectLastCall().anyTimes();
replay(mockOFAgentAdminService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-ofagent-stop.json");
assertNotNull("post-ofagent-stop.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-stop")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
verify(mockOFAgentService);
verify(mockOFAgentAdminService);
}
/**
* Tests stopping non-existent OFAgent with POST.
*/
@Test
public void testNonExistentOFAgentStop() {
expect(mockOFAgentService.agent(NETWORK)).andReturn(null).anyTimes();
replay(mockOFAgentService);
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-non-existent-ofagent-stop.json");
assertNotNull("post-non-existent-ofagent-stop.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-stop")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
verify(mockOFAgentService);
}
/**
* Tests stopping FAgent with bad POST request.
*/
@Test
public void testOFAgentStopBadRequest() {
InputStream jsonStream = OFAgentWebResourceTest.class
.getResourceAsStream("post-bad-request.json");
assertNotNull("post-bad-request.json is null", jsonStream);
WebTarget wt = target();
Response response = wt.path("service/ofagent-stop")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
}
/**
* Tests deleting an OFAgent with DELETE.
*/
@Test
public void testOFAgentRemove() {
expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
replay(mockOFAgentService);
expect(mockOFAgentAdminService.removeAgent(NETWORK)).andReturn(OF_AGENT).anyTimes();
replay(mockOFAgentAdminService);
WebTarget wt = target();
Response response = wt.path("service/ofagent-remove/" + NETWORK.toString())
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
final JsonObject result = Json.parse(response.readEntity(String.class)).asObject();
assertThat(result.get("networkId").asString(), is(NETWORK.id().toString()));
assertThat(result.get("state").asString(), is(STOPPED.toString()));
verify(mockOFAgentService);
verify(mockOFAgentAdminService);
}
/**
* Tests deleting a non-existent OFAgent with DELETE.
*/
@Test
public void testNonExistentOFAgentRemove() {
expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(null).anyTimes();
replay(mockOFAgentService);
expect(mockOFAgentAdminService.removeAgent(NETWORK)).andReturn(null).anyTimes();
replay(mockOFAgentAdminService);
WebTarget wt = target();
Response response = wt.path("service/ofagent-remove/" + NETWORK.toString())
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
assertThat(response.readEntity(String.class), containsString("OFAgent not found"));
verify(mockOFAgentService);
verify(mockOFAgentAdminService);
}
}

View File

@ -0,0 +1,9 @@
{
"networkId": "3",
"controllers": [
{
"ip": "147.91.1.27",
"port": "63"
}
]
}

View File

@ -0,0 +1,3 @@
{
"networkId": "3"
}

View File

@ -0,0 +1,3 @@
{
"networkId": "3"
}

View File

@ -0,0 +1,12 @@
{
"controllers": [
{
"ip": "147.91.1.27",
"port": "6633"
},
{
"ip": "147.91.1.25",
"port": "6633"
}
]
}

View File

@ -0,0 +1,13 @@
{
"networkId": "3",
"controllers": [
{
"ip": "147.91.1.27",
"port": "6653"
},
{
"ip": "147.91.1.4",
"port": "6633"
}
]
}

View File

@ -0,0 +1,13 @@
{
"networkId": "3",
"controllers": [
{
"ip": "147.91.1.27",
"port": "6633"
},
{
"ip": "147.91.1.25",
"port": "6633"
}
]
}