Implementation of REST POST API for creating intents
- codec for constraint decode
- codec for intent decode
- POST method for intents
- unit tests for codecs and POST method
Change-Id: Ibc0ef8f99a0c0664710a733985424c77010c49b5
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/ConstraintCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/ConstraintCodecTest.java
new file mode 100644
index 0000000..2a47d11
--- /dev/null
+++ b/core/common/src/test/java/org/onosproject/codec/impl/ConstraintCodecTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2015 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 java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.constraint.AnnotationConstraint;
+import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.LambdaConstraint;
+import org.onosproject.net.intent.constraint.LatencyConstraint;
+import org.onosproject.net.intent.constraint.LinkTypeConstraint;
+import org.onosproject.net.intent.constraint.ObstacleConstraint;
+import org.onosproject.net.intent.constraint.WaypointConstraint;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.did;
+
+/**
+ * Unit tests for Constraint codec.
+ */
+public class ConstraintCodecTest {
+
+ MockCodecContext context;
+ JsonCodec<Constraint> constraintCodec;
+ final CoreService mockCoreService = createMock(CoreService.class);
+
+ /**
+ * Sets up for each test. Creates a context and fetches the flow rule
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new MockCodecContext();
+ constraintCodec = context.codec(Constraint.class);
+ assertThat(constraintCodec, notNullValue());
+
+ expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID))
+ .andReturn(APP_ID).anyTimes();
+ replay(mockCoreService);
+ context.registerService(CoreService.class, mockCoreService);
+ }
+
+ /**
+ * Reads in a constraint from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the constraint
+ * @return decoded constraint
+ */
+ private Constraint getConstraint(String resourceName) {
+ InputStream jsonStream = ConstraintCodecTest.class
+ .getResourceAsStream(resourceName);
+ try {
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ Constraint constraint = constraintCodec.decode((ObjectNode) json, context);
+ assertThat(constraint, notNullValue());
+ return checkNotNull(constraint);
+ } catch (IOException ioe) {
+ Assert.fail(ioe.getMessage());
+ throw new IllegalStateException("cannot happen");
+ }
+ }
+
+
+ /**
+ * Tests link type constraint.
+ */
+ @Test
+ public void linkTypeConstraint() {
+ Constraint constraint = getConstraint("LinkTypeConstraint.json");
+ assertThat(constraint, instanceOf(LinkTypeConstraint.class));
+
+ LinkTypeConstraint linkTypeConstraint = (LinkTypeConstraint) constraint;
+ assertThat(linkTypeConstraint.isInclusive(), is(false));
+ assertThat(linkTypeConstraint.types(), hasSize(2));
+ assertThat(linkTypeConstraint.types(), hasItem(Link.Type.OPTICAL));
+ assertThat(linkTypeConstraint.types(), hasItem(Link.Type.DIRECT));
+ }
+
+ /**
+ * Tests annotation constraint.
+ */
+ @Test
+ public void annotationConstraint() {
+ Constraint constraint = getConstraint("AnnotationConstraint.json");
+ assertThat(constraint, instanceOf(AnnotationConstraint.class));
+
+ AnnotationConstraint annotationConstraint = (AnnotationConstraint) constraint;
+ assertThat(annotationConstraint.key(), is("key"));
+ assertThat(annotationConstraint.threshold(), is(123.0D));
+ }
+
+ /**
+ * Tests bandwidth constraint.
+ */
+ @Test
+ public void bandwidthConstraint() {
+ Constraint constraint = getConstraint("BandwidthConstraint.json");
+ assertThat(constraint, instanceOf(BandwidthConstraint.class));
+
+ BandwidthConstraint bandwidthConstraint = (BandwidthConstraint) constraint;
+ assertThat(bandwidthConstraint.bandwidth().toDouble(), is(345.678D));
+ }
+
+ /**
+ * Tests lambda constraint.
+ */
+ @Test
+ public void lambdaConstraint() {
+ Constraint constraint = getConstraint("LambdaConstraint.json");
+ assertThat(constraint, instanceOf(LambdaConstraint.class));
+
+ LambdaConstraint lambdaConstraint = (LambdaConstraint) constraint;
+ assertThat(lambdaConstraint.lambda().toInt(), is(444));
+ }
+
+ /**
+ * Tests latency constraint.
+ */
+ @Test
+ public void latencyConstraint() {
+ Constraint constraint = getConstraint("LatencyConstraint.json");
+ assertThat(constraint, instanceOf(LatencyConstraint.class));
+
+ LatencyConstraint latencyConstraint = (LatencyConstraint) constraint;
+ assertThat(latencyConstraint.latency().toMillis(), is(111L));
+ }
+
+ /**
+ * Tests obstacle constraint.
+ */
+ @Test
+ public void obstacleConstraint() {
+ Constraint constraint = getConstraint("ObstacleConstraint.json");
+ assertThat(constraint, instanceOf(ObstacleConstraint.class));
+
+ ObstacleConstraint obstacleConstraint = (ObstacleConstraint) constraint;
+
+ assertThat(obstacleConstraint.obstacles(), hasItem(did("dev1")));
+ assertThat(obstacleConstraint.obstacles(), hasItem(did("dev2")));
+ assertThat(obstacleConstraint.obstacles(), hasItem(did("dev3")));
+ }
+
+ /**
+ * Tests waypoint constaint.
+ */
+ @Test
+ public void waypointConstraint() {
+ Constraint constraint = getConstraint("WaypointConstraint.json");
+ assertThat(constraint, instanceOf(WaypointConstraint.class));
+
+ WaypointConstraint waypointConstraint = (WaypointConstraint) constraint;
+
+ assertThat(waypointConstraint.waypoints(), hasItem(did("devA")));
+ assertThat(waypointConstraint.waypoints(), hasItem(did("devB")));
+ assertThat(waypointConstraint.waypoints(), hasItem(did("devC")));
+ }
+
+ /**
+ * Tests asymmetric path constraint.
+ */
+ @Test
+ public void asymmetricPathConstraint() {
+ Constraint constraint = getConstraint("AsymmetricPathConstraint.json");
+ assertThat(constraint, instanceOf(AsymmetricPathConstraint.class));
+ }
+}
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
index cdbd533..0824bd5 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.codec.impl;
+import java.io.IOException;
+import java.io.InputStream;
import java.time.Duration;
import java.util.List;
@@ -26,6 +28,7 @@
import org.onlab.util.Bandwidth;
import org.onosproject.codec.JsonCodec;
import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
@@ -43,9 +46,13 @@
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentServiceAdapter;
import org.onosproject.net.intent.PointToPointIntent;
@@ -59,14 +66,22 @@
import org.onosproject.net.resource.link.BandwidthResource;
import org.onosproject.net.resource.link.LambdaResource;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableList;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.onosproject.codec.impl.IntentJsonMatcher.matchesIntent;
import static org.onosproject.net.NetTestTools.did;
import static org.onosproject.net.NetTestTools.hid;
+import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
/**
* Unit tests for the host to host intent class codec.
@@ -81,11 +96,16 @@
final TrafficTreatment emptyTreatment =
DefaultTrafficTreatment.emptyTreatment();
private final MockCodecContext context = new MockCodecContext();
+ final CoreService mockCoreService = createMock(CoreService.class);
@Before
public void setUpIntentService() {
final IntentService mockIntentService = new IntentServiceAdapter();
context.registerService(IntentService.class, mockIntentService);
+ context.registerService(CoreService.class, mockCoreService);
+ expect(mockCoreService.getAppId((short) 2))
+ .andReturn(new DefaultApplicationId(2, "app"));
+ replay(mockCoreService);
}
/**
@@ -161,13 +181,13 @@
final List<Constraint> constraints =
ImmutableList.of(
- new BandwidthConstraint(new BandwidthResource(Bandwidth.bps(1.0))),
- new LambdaConstraint(LambdaResource.valueOf(3)),
- new AnnotationConstraint("key", 33.0),
- new AsymmetricPathConstraint(),
- new LatencyConstraint(Duration.ofSeconds(2)),
- new ObstacleConstraint(did1, did2),
- new WaypointConstraint(did3));
+ new BandwidthConstraint(new BandwidthResource(Bandwidth.bps(1.0))),
+ new LambdaConstraint(LambdaResource.valueOf(3)),
+ new AnnotationConstraint("key", 33.0),
+ new AsymmetricPathConstraint(),
+ new LatencyConstraint(Duration.ofSeconds(2)),
+ new ObstacleConstraint(did1, did2),
+ new WaypointConstraint(did3));
final PointToPointIntent intent =
PointToPointIntent.builder()
@@ -188,4 +208,81 @@
assertThat(intentJson, matchesIntent(intent));
}
+
+ /**
+ * Reads in a rule from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded flow rule
+ * @throws IOException if processing the resource fails
+ */
+ private Intent getIntent(String resourceName, JsonCodec intentCodec) throws IOException {
+ InputStream jsonStream = FlowRuleCodecTest.class
+ .getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ Intent intent = (Intent) intentCodec.decode((ObjectNode) json, context);
+ assertThat(intent, notNullValue());
+ return intent;
+ }
+
+ /**
+ * Tests the point to point intent JSON codec.
+ *
+ * @throws IOException if JSON processing fails
+ */
+ @Test
+ public void decodePointToPointIntent() throws IOException {
+ JsonCodec<Intent> intentCodec = context.codec(Intent.class);
+ assertThat(intentCodec, notNullValue());
+
+ Intent intent = getIntent("PointToPointIntent.json", intentCodec);
+ assertThat(intent, notNullValue());
+ assertThat(intent, instanceOf(PointToPointIntent.class));
+
+ PointToPointIntent pointIntent = (PointToPointIntent) intent;
+ assertThat(pointIntent.priority(), is(55));
+ assertThat(pointIntent.ingressPoint().deviceId(), is(did("0000000000000001")));
+ assertThat(pointIntent.ingressPoint().port(), is(PortNumber.portNumber(1)));
+ assertThat(pointIntent.egressPoint().deviceId(), is(did("0000000000000007")));
+ assertThat(pointIntent.egressPoint().port(), is(PortNumber.portNumber(2)));
+
+ assertThat(pointIntent.constraints(), hasSize(1));
+
+ assertThat(pointIntent.selector(), notNullValue());
+ assertThat(pointIntent.selector().criteria(), hasSize(1));
+ Criterion criterion1 = pointIntent.selector().criteria().iterator().next();
+ assertThat(criterion1, instanceOf(EthCriterion.class));
+ EthCriterion ethCriterion = (EthCriterion) criterion1;
+ assertThat(ethCriterion.mac().toString(), is("11:22:33:44:55:66"));
+ assertThat(ethCriterion.type().name(), is("ETH_DST"));
+
+ assertThat(pointIntent.treatment(), notNullValue());
+ assertThat(pointIntent.treatment().allInstructions(), hasSize(1));
+ Instruction instruction1 = pointIntent.treatment().allInstructions().iterator().next();
+ assertThat(instruction1, instanceOf(ModEtherInstruction.class));
+ ModEtherInstruction ethInstruction = (ModEtherInstruction) instruction1;
+ assertThat(ethInstruction.mac().toString(), is("22:33:44:55:66:77"));
+ assertThat(ethInstruction.type().toString(), is("L2MODIFICATION"));
+ assertThat(ethInstruction.subtype().toString(), is("ETH_SRC"));
+ }
+
+ /**
+ * Tests the host to host intent JSON codec.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void decodeHostToHostIntent() throws IOException {
+ JsonCodec<Intent> intentCodec = context.codec(Intent.class);
+ assertThat(intentCodec, notNullValue());
+
+ Intent intent = getIntent("HostToHostIntent.json", intentCodec);
+ assertThat(intent, notNullValue());
+ assertThat(intent, instanceOf(HostToHostIntent.class));
+
+ HostToHostIntent hostIntent = (HostToHostIntent) intent;
+ assertThat(hostIntent.priority(), is(7));
+ assertThat(hostIntent.constraints(), hasSize(1));
+ }
}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/AnnotationConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/AnnotationConstraint.json
new file mode 100644
index 0000000..aaa72a7
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/AnnotationConstraint.json
@@ -0,0 +1,5 @@
+{
+ "type":"AnnotationConstraint",
+ "key":"key",
+ "threshold":123.0
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/AsymmetricPathConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/AsymmetricPathConstraint.json
new file mode 100644
index 0000000..340bdba
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/AsymmetricPathConstraint.json
@@ -0,0 +1,3 @@
+{
+ "type":"AsymmetricPathConstraint"
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/BandwidthConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/BandwidthConstraint.json
new file mode 100644
index 0000000..3475006
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/BandwidthConstraint.json
@@ -0,0 +1,4 @@
+{
+ "type":"BandwidthConstraint",
+ "bandwidth":345.678
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/HostToHostIntent.json b/core/common/src/test/resources/org/onosproject/codec/impl/HostToHostIntent.json
new file mode 100644
index 0000000..5010c48
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/HostToHostIntent.json
@@ -0,0 +1,19 @@
+{
+ "type": "HostToHostIntent",
+ "appId": 2,
+ "selector": {"criteria": []},
+ "treatment": {
+ "instructions": [],
+ "deferred": []
+ },
+ "priority": 7,
+ "constraints": [
+ {
+ "inclusive": false,
+ "types": ["OPTICAL"],
+ "type": "LinkTypeConstraint"
+ }
+ ],
+ "one": "00:00:00:00:00:02/-1",
+ "two": "00:00:00:00:00:05/-1"
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/LambdaConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/LambdaConstraint.json
new file mode 100644
index 0000000..4ac3763
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/LambdaConstraint.json
@@ -0,0 +1,4 @@
+{
+ "type":"LambdaConstraint",
+ "lambda":444
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/LatencyConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/LatencyConstraint.json
new file mode 100644
index 0000000..1c46e5e
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/LatencyConstraint.json
@@ -0,0 +1,4 @@
+{
+ "type":"LatencyConstraint",
+ "latencyMillis":111
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/LinkTypeConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/LinkTypeConstraint.json
new file mode 100644
index 0000000..8b766da
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/LinkTypeConstraint.json
@@ -0,0 +1,5 @@
+{
+ "inclusive":false,
+ "types":["DIRECT","OPTICAL"],
+ "type":"LinkTypeConstraint"
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/ObstacleConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/ObstacleConstraint.json
new file mode 100644
index 0000000..35dcb0f
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/ObstacleConstraint.json
@@ -0,0 +1,4 @@
+{
+ "type":"ObstacleConstraint",
+ "obstacles":["of:dev1","of:dev2","of:dev3"]
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/PointToPointIntent.json b/core/common/src/test/resources/org/onosproject/codec/impl/PointToPointIntent.json
new file mode 100644
index 0000000..4c6c4b8
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/PointToPointIntent.json
@@ -0,0 +1,38 @@
+{
+ "type": "PointToPointIntent",
+ "appId": 2,
+ "selector": {
+ "criteria": [
+ {
+ "type": "ETH_DST",
+ "mac": "11:22:33:44:55:66"
+ }
+ ]
+ },
+ "treatment": {
+ "instructions": [
+ {
+ "type": "L2MODIFICATION",
+ "subtype": "ETH_SRC",
+ "mac": "22:33:44:55:66:77"
+ }
+ ],
+ "deferred": []
+ },
+ "priority": 55,
+ "constraints": [
+ {
+ "inclusive": false,
+ "types": ["OPTICAL"],
+ "type": "LinkTypeConstraint"
+ }
+ ],
+ "ingressPoint": {
+ "port": "1",
+ "device": "of:0000000000000001"
+ },
+ "egressPoint": {
+ "port": "2",
+ "device": "of:0000000000000007"
+ }
+}
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/WaypointConstraint.json b/core/common/src/test/resources/org/onosproject/codec/impl/WaypointConstraint.json
new file mode 100644
index 0000000..7009cf9
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/WaypointConstraint.json
@@ -0,0 +1,4 @@
+{
+ "type":"WaypointConstraint",
+ "waypoints":["of:devA","of:devB","of:devC"]
+}