mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-16 18:02:05 +02:00
Implement REST API for Hosts objects
Change-Id: Ie1d4f7c19c47d2d357dedf81016e4d4d197e4052
This commit is contained in:
parent
fcf9162409
commit
1f95bd3f84
@ -38,6 +38,10 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
@ -25,6 +25,8 @@ import org.onosproject.codec.JsonCodec;
|
||||
import org.onosproject.net.Annotations;
|
||||
import org.onosproject.net.ConnectPoint;
|
||||
import org.onosproject.net.Device;
|
||||
import org.onosproject.net.Host;
|
||||
import org.onosproject.net.HostLocation;
|
||||
import org.onosproject.net.Link;
|
||||
import org.onosproject.net.Port;
|
||||
import org.slf4j.Logger;
|
||||
@ -53,11 +55,13 @@ public class CodecManager implements CodecService {
|
||||
registerCodec(Port.class, new PortCodec());
|
||||
registerCodec(ConnectPoint.class, new ConnectPointCodec());
|
||||
registerCodec(Link.class, new LinkCodec());
|
||||
registerCodec(Host.class, new HostCodec());
|
||||
registerCodec(HostLocation.class, new HostLocationCodec());
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deativate() {
|
||||
public void deactivate() {
|
||||
codecs.clear();
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2014 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.codec.impl;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onosproject.codec.CodecContext;
|
||||
import org.onosproject.codec.JsonCodec;
|
||||
import org.onosproject.net.Host;
|
||||
import org.onosproject.net.HostLocation;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Host JSON codec.
|
||||
*/
|
||||
public class HostCodec extends AnnotatedCodec<Host> {
|
||||
|
||||
@Override
|
||||
public ObjectNode encode(Host host, CodecContext context) {
|
||||
checkNotNull(host, "Host cannot be null");
|
||||
final JsonCodec<HostLocation> locationCodec = new HostLocationCodec();
|
||||
final ObjectNode result = context.mapper().createObjectNode()
|
||||
.put("id", host.id().toString())
|
||||
.put("mac", host.mac().toString())
|
||||
.put("vlan", host.vlan().toString());
|
||||
|
||||
final ArrayNode jsonIpAddresses = result.putArray("ipAddresses");
|
||||
for (final IpAddress ipAddress : host.ipAddresses()) {
|
||||
jsonIpAddresses.add(ipAddress.toString());
|
||||
}
|
||||
result.set("ipAddresses", jsonIpAddresses);
|
||||
result.set("location", locationCodec.encode(host.location(), context));
|
||||
|
||||
return annotate(result, host, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2014 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.codec.impl;
|
||||
|
||||
import org.onosproject.codec.CodecContext;
|
||||
import org.onosproject.codec.JsonCodec;
|
||||
import org.onosproject.net.HostLocation;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Host JSON codec.
|
||||
*/
|
||||
public class HostLocationCodec extends JsonCodec<HostLocation> {
|
||||
|
||||
@Override
|
||||
public ObjectNode encode(HostLocation hostLocation, CodecContext context) {
|
||||
checkNotNull(hostLocation, "Host location cannot be null");
|
||||
return context.mapper().createObjectNode()
|
||||
.put("elementId", hostLocation.elementId().toString())
|
||||
.put("port", hostLocation.port().toString());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2014 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.rest;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.onosproject.net.Host;
|
||||
import org.onosproject.net.host.HostService;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import static org.onosproject.net.HostId.hostId;
|
||||
|
||||
/**
|
||||
* REST resource for interacting with the inventory of hosts.
|
||||
*/
|
||||
@Path("hosts")
|
||||
public class HostsWebResource extends AbstractWebResource {
|
||||
|
||||
public static final String HOST_NOT_FOUND = "Host is not found";
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getHosts() {
|
||||
final Iterable<Host> hosts = get(HostService.class).getHosts();
|
||||
final ObjectNode root = encodeArray(Host.class, "hosts", hosts);
|
||||
return ok(root.toString()).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{id}")
|
||||
public Response getHostById(@PathParam("id") String id) {
|
||||
final Host host = nullIsNotFound(get(HostService.class).getHost(hostId(id)),
|
||||
HOST_NOT_FOUND);
|
||||
final ObjectNode root = codec(Host.class).encode(host, this);
|
||||
return ok(root.toString()).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{mac}/{vlan}")
|
||||
public Response getHostByMacAndVlan(@PathParam("mac") String mac,
|
||||
@PathParam("vlan") String vlan) {
|
||||
final Host host = nullIsNotFound(get(HostService.class).getHost(hostId(mac + "/" + vlan)),
|
||||
HOST_NOT_FOUND);
|
||||
final ObjectNode root = codec(Host.class).encode(host, this);
|
||||
return ok(root.toString()).build();
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
org.onosproject.rest.DevicesWebResource,
|
||||
org.onosproject.rest.LinksWebResource,
|
||||
org.onosproject.rest.HostsWebResource,
|
||||
org.onosproject.rest.ConfigResource
|
||||
</param-value>
|
||||
</init-param>
|
||||
|
@ -45,7 +45,7 @@ public class GreetResourceTest extends JerseyTest {
|
||||
public void basics() {
|
||||
WebResource rs = resource();
|
||||
String response = rs.path("greet").get(String.class);
|
||||
assertTrue("incorrect response", response.contains("Whazup "));
|
||||
assertTrue("incorrect response", response.contains("greeting"));
|
||||
}
|
||||
|
||||
}
|
||||
|
333
web/api/src/test/java/org/onosproject/rest/HostResourceTest.java
Normal file
333
web/api/src/test/java/org/onosproject/rest/HostResourceTest.java
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright 2014 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.rest;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
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.MacAddress;
|
||||
import org.onlab.rest.BaseResource;
|
||||
import org.onosproject.codec.CodecService;
|
||||
import org.onosproject.codec.impl.CodecManager;
|
||||
import org.onosproject.net.DefaultHost;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.Host;
|
||||
import org.onosproject.net.HostId;
|
||||
import org.onosproject.net.HostLocation;
|
||||
import org.onosproject.net.host.HostService;
|
||||
import org.onosproject.net.provider.ProviderId;
|
||||
|
||||
import com.eclipsesource.json.JsonArray;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sun.jersey.api.client.WebResource;
|
||||
import com.sun.jersey.test.framework.JerseyTest;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.onlab.packet.MacAddress.valueOf;
|
||||
import static org.onlab.packet.VlanId.vlanId;
|
||||
import static org.onosproject.net.PortNumber.portNumber;
|
||||
|
||||
/**
|
||||
* Simple example on how to write a JAX-RS unit test using Jersey test framework.
|
||||
* A base class should/will be created to provide further assistance for testing.
|
||||
*/
|
||||
public class HostResourceTest extends JerseyTest {
|
||||
final HostService mockHostService = createMock(HostService.class);
|
||||
final HashSet<Host> hosts = new HashSet<>();
|
||||
|
||||
public HostResourceTest() {
|
||||
super("org.onosproject.rest");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
expect(mockHostService.getHosts()).andReturn(hosts).anyTimes();
|
||||
|
||||
// Register the services needed for the test
|
||||
final CodecManager codecService = new CodecManager();
|
||||
codecService.activate();
|
||||
ServiceDirectory testDirectory =
|
||||
new TestServiceDirectory()
|
||||
.add(HostService.class, mockHostService)
|
||||
.add(CodecService.class, codecService);
|
||||
|
||||
BaseResource.setServiceDirectory(testDirectory);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
verify(mockHostService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hamcrest matcher to check that a host representation in JSON matches
|
||||
* the actual host.
|
||||
*/
|
||||
public static class HostJsonMatcher extends TypeSafeMatcher<JsonObject> {
|
||||
private final Host host;
|
||||
private String reason = "";
|
||||
|
||||
public HostJsonMatcher(Host hostValue) {
|
||||
host = hostValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesSafely(JsonObject jsonHost) {
|
||||
// Check id
|
||||
final String jsonId = jsonHost.get("id").asString();
|
||||
if (!jsonId.equals(host.id().toString())) {
|
||||
reason = "id " + host.id().toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check vlan id
|
||||
final String jsonVlanId = jsonHost.get("vlan").asString();
|
||||
if (!jsonVlanId.equals(host.vlan().toString())) {
|
||||
reason = "vlan id " + host.vlan().toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check mac address
|
||||
final String jsonMacAddress = jsonHost.get("mac").asString();
|
||||
if (!jsonMacAddress.equals(host.mac().toString())) {
|
||||
reason = "mac address " + host.mac().toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check location element id
|
||||
final JsonObject jsonLocation = jsonHost.get("location").asObject();
|
||||
final String jsonLocationElementId = jsonLocation.get("elementId").asString();
|
||||
if (!jsonLocationElementId.equals(host.location().elementId().toString())) {
|
||||
reason = "location element id " + host.location().elementId().toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check location port number
|
||||
final String jsonLocationPortNumber = jsonLocation.get("port").asString();
|
||||
if (!jsonLocationPortNumber.equals(host.location().port().toString())) {
|
||||
reason = "location portNumber " + host.location().port().toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check Ip Addresses
|
||||
final JsonArray jsonHostIps = jsonHost.get("ipAddresses").asArray();
|
||||
final Set<IpAddress> expectedHostIps = host.ipAddresses();
|
||||
if (jsonHostIps.size() != expectedHostIps.size()) {
|
||||
reason = "IP address arrays differ in size";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to allocate a host array matcher.
|
||||
*
|
||||
* @param host host object we are looking for
|
||||
* @return matcher
|
||||
*/
|
||||
private static HostJsonMatcher matchesHost(Host host) {
|
||||
return new HostJsonMatcher(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hamcrest matcher to check that a host is represented properly in a JSON
|
||||
* array of hosts.
|
||||
*/
|
||||
public static class HostJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
|
||||
private final Host host;
|
||||
private String reason = "";
|
||||
|
||||
public HostJsonArrayMatcher(Host hostValue) {
|
||||
host = hostValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesSafely(JsonArray json) {
|
||||
boolean hostFound = false;
|
||||
final int expectedAttributes = 5;
|
||||
for (int jsonHostIndex = 0; jsonHostIndex < json.size();
|
||||
jsonHostIndex++) {
|
||||
|
||||
final JsonObject jsonHost = json.get(jsonHostIndex).asObject();
|
||||
|
||||
if (jsonHost.names().size() != expectedAttributes) {
|
||||
reason = "Found a host with the wrong number of attributes";
|
||||
return false;
|
||||
}
|
||||
|
||||
final String jsonHostId = jsonHost.get("id").asString();
|
||||
if (jsonHostId.equals(host.id().toString())) {
|
||||
hostFound = true;
|
||||
|
||||
// We found the correct host, check attribute values
|
||||
assertThat(jsonHost, matchesHost(host));
|
||||
}
|
||||
}
|
||||
if (!hostFound) {
|
||||
reason = "Host with id " + host.id().toString() + " not found";
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to allocate a host array matcher.
|
||||
*
|
||||
* @param host host object we are looking for
|
||||
* @return matcher
|
||||
*/
|
||||
private static HostJsonArrayMatcher hasHost(Host host) {
|
||||
return new HostJsonArrayMatcher(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the result of the rest api GET when there are no hosts.
|
||||
*/
|
||||
@Test
|
||||
public void testHostsEmptyArray() {
|
||||
replay(mockHostService);
|
||||
WebResource rs = resource();
|
||||
String response = rs.path("hosts").get(String.class);
|
||||
assertThat(response, is("{\"hosts\":[]}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the result of the rest api GET when hosts are defined.
|
||||
*/
|
||||
@Test
|
||||
public void testHostsArray() {
|
||||
replay(mockHostService);
|
||||
final ProviderId pid = new ProviderId("of", "foo");
|
||||
final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
|
||||
final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
|
||||
final Host host1 =
|
||||
new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
|
||||
new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
|
||||
ips1);
|
||||
final MacAddress mac2 = MacAddress.valueOf("00:00:11:00:00:02");
|
||||
final Set<IpAddress> ips2 = ImmutableSet.of(
|
||||
IpAddress.valueOf("2222:2222:2222:1::"),
|
||||
IpAddress.valueOf("2222:2222:2222:2::"));
|
||||
final Host host2 =
|
||||
new DefaultHost(pid, HostId.hostId(mac2), valueOf(2), vlanId((short) 2),
|
||||
new HostLocation(DeviceId.deviceId("2"), portNumber(22), 2),
|
||||
ips2);
|
||||
hosts.add(host1);
|
||||
hosts.add(host2);
|
||||
WebResource rs = resource();
|
||||
String response = rs.path("hosts").get(String.class);
|
||||
assertThat(response, containsString("{\"hosts\":["));
|
||||
|
||||
final JsonObject result = JsonObject.readFrom(response);
|
||||
assertThat(result, notNullValue());
|
||||
|
||||
assertThat(result.names(), hasSize(1));
|
||||
assertThat(result.names().get(0), is("hosts"));
|
||||
|
||||
final JsonArray hosts = result.get("hosts").asArray();
|
||||
assertThat(hosts, notNullValue());
|
||||
|
||||
assertThat(hosts, hasHost(host1));
|
||||
assertThat(hosts, hasHost(host2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests fetch of one host by Id.
|
||||
*/
|
||||
@Test
|
||||
public void testSingleHostByIdFetch() {
|
||||
final ProviderId pid = new ProviderId("of", "foo");
|
||||
final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
|
||||
final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
|
||||
final Host host1 =
|
||||
new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
|
||||
new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
|
||||
ips1);
|
||||
|
||||
hosts.add(host1);
|
||||
|
||||
expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
|
||||
.andReturn(host1)
|
||||
.anyTimes();
|
||||
replay(mockHostService);
|
||||
|
||||
WebResource rs = resource();
|
||||
String response = rs.path("hosts/00:00:11:00:00:01%2F1").get(String.class);
|
||||
final JsonObject result = JsonObject.readFrom(response);
|
||||
assertThat(result, matchesHost(host1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests fetch of one host by mac and vlan.
|
||||
*/
|
||||
@Test
|
||||
public void testSingleHostByMacAndVlanFetch() {
|
||||
final ProviderId pid = new ProviderId("of", "foo");
|
||||
final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
|
||||
final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
|
||||
final Host host1 =
|
||||
new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
|
||||
new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
|
||||
ips1);
|
||||
|
||||
hosts.add(host1);
|
||||
|
||||
expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
|
||||
.andReturn(host1)
|
||||
.anyTimes();
|
||||
replay(mockHostService);
|
||||
|
||||
WebResource rs = resource();
|
||||
String response = rs.path("hosts/00:00:11:00:00:01/1").get(String.class);
|
||||
final JsonObject result = JsonObject.readFrom(response);
|
||||
assertThat(result, matchesHost(host1));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user