REST API for obj-nextids
Change-Id: Ibad03de0a6ffa8a478037120c84edfe6722f4d9b
(cherry picked from commit 0acb326963dda08a5eef16134eca5cba84b8e75d)
diff --git a/apps/virtual/app/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java b/apps/virtual/app/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java
index c4e2031..0a5a509 100644
--- a/apps/virtual/app/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java
+++ b/apps/virtual/app/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java
@@ -22,6 +22,8 @@
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.lang3.tuple.Pair;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.util.KryoNamespace;
import org.onosproject.incubator.net.virtual.AbstractVnetService;
@@ -172,6 +174,11 @@
}
@Override
+ public Map<Pair<Integer, DeviceId>, List<String>> getNextMappingsChain() {
+ return ImmutableMap.of();
+ }
+
+ @Override
public List<String> getNextMappings() {
List<String> mappings = new ArrayList<>();
Map<Integer, NextGroup> allnexts = flowObjectiveStore.getAllGroups();
diff --git a/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java b/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java
index 103691c..11a7f5f 100644
--- a/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java
+++ b/core/api/src/main/java/org/onosproject/net/flowobjective/FlowObjectiveService.java
@@ -24,6 +24,7 @@
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import org.apache.commons.lang.NotImplementedException;
+import org.apache.commons.lang3.tuple.Pair;
import org.onosproject.net.DeviceId;
/**
@@ -93,6 +94,18 @@
/**
* Retrieve all nextObjective to group mappings known to this onos instance,
+ * in a format meant for display via REST API, to help with debugging. Applications
+ * are only aware of next-Ids, while the group sub-system is only aware of group-ids.
+ * This method fills in the gap by providing information on the mapping
+ * between next-ids and group-ids done by device-drivers.
+ *
+ * @return a map of key as a pair of next-id and Device id to group-id mapping.
+ * Consumed by the REST API.
+ */
+ Map<Pair<Integer, DeviceId>, List<String>> getNextMappingsChain();
+
+ /**
+ * Retrieve all nextObjective to group mappings known to this onos instance,
* in a format meant for display on the CLI, to help with debugging. Applications
* are only aware of next-Ids, while the group sub-system is only aware of group-ids.
* This method fills in the gap by providing information on the mapping
diff --git a/core/api/src/test/java/org/onosproject/net/flowobjective/FlowObjectiveServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/flowobjective/FlowObjectiveServiceAdapter.java
index 360c1f2..0b17ce8 100644
--- a/core/api/src/test/java/org/onosproject/net/flowobjective/FlowObjectiveServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/flowobjective/FlowObjectiveServiceAdapter.java
@@ -17,7 +17,10 @@
package org.onosproject.net.flowobjective;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import org.onosproject.net.DeviceId;
+import org.apache.commons.lang3.tuple.Pair;
+import java.util.Map;
import java.util.List;
@@ -65,4 +68,10 @@
public List<String> getPendingFlowObjectives() {
return ImmutableList.of();
}
+
+ @Override
+ public Map<Pair<Integer, DeviceId>, List<String>> getNextMappingsChain() {
+ return ImmutableMap.of();
+ }
+
}
diff --git a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
index d0bd1c5..de7d785 100644
--- a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
@@ -16,9 +16,11 @@
package org.onosproject.net.flowobjective.impl;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import org.apache.commons.lang3.tuple.Pair;
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.util.ItemNotFoundException;
@@ -65,6 +67,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -738,6 +741,38 @@
}
@Override
+ public Map<Pair<Integer, DeviceId>, List<String>> getNextMappingsChain() {
+ Map<Pair<Integer, DeviceId>, List<String>> nextObjGroupMap = new HashMap<>();
+ Map<Integer, NextGroup> allnexts = flowObjectiveStore.getAllGroups();
+
+ // XXX if the NextGroup after de-serialization actually stored info of the deviceId
+ // then info on any nextObj could be retrieved from one controller instance.
+ // Right now the drivers on one instance can only fetch for next-ids that came
+ // to them.
+ // Also, we still need to send the right next-id to the right driver as potentially
+ // there can be different drivers for different devices. But on that account,
+ // no instance should be decoding for another instance's nextIds.
+
+ for (Map.Entry<Integer, NextGroup> e : allnexts.entrySet()) {
+ // get the device this next Objective was sent to
+ DeviceId deviceId = nextToDevice.get(e.getKey());
+ if (deviceId != null) {
+ // this instance of the controller sent the nextObj to a driver
+ Pipeliner pipeliner = getDevicePipeliner(deviceId);
+ List<String> nextMappings = pipeliner.getNextMappings(e.getValue());
+ if (nextMappings != null) {
+ //mappings.addAll(nextMappings);
+ nextObjGroupMap.put(Pair.of(e.getKey(), deviceId), nextMappings);
+ }
+ } else {
+ nextObjGroupMap.put(Pair.of(e.getKey(), deviceId), ImmutableList.of("nextId not in this onos instance"));
+ }
+ }
+ return nextObjGroupMap;
+ }
+
+
+ @Override
public List<String> getPendingFlowObjectives() {
List<String> pendingFlowObjectives = new ArrayList<>();
diff --git a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java
index e09f8a1..dc5ef05 100644
--- a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java
@@ -16,6 +16,7 @@
package org.onosproject.net.flowobjective.impl.composition;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.osgi.DefaultServiceDirectory;
@@ -25,7 +26,6 @@
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.behaviour.PipelinerContext;
import org.onosproject.net.device.DeviceEvent;
@@ -57,6 +57,8 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.net.DeviceId;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newFixedThreadPool;
@@ -430,6 +432,11 @@
}
@Override
+ public Map<Pair<Integer, DeviceId>, List<String>> getNextMappingsChain() {
+ return ImmutableMap.of();
+ }
+
+ @Override
public List<String> getPendingFlowObjectives() {
// TODO Implementation deferred as this is an experimental component.
return ImmutableList.of();
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java b/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java
index a6227bc..906e27c 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java
@@ -38,6 +38,7 @@
HostsWebResource.class,
IntentsWebResource.class,
FlowsWebResource.class,
+ FlowObjectiveNextListWebResource.class,
GroupsWebResource.class,
MetersWebResource.class,
TopologyWebResource.class,
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/FlowObjectiveNextListWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/FlowObjectiveNextListWebResource.java
new file mode 100644
index 0000000..4e9b427
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/rest/resources/FlowObjectiveNextListWebResource.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.resources;
+
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.List;
+import java.util.Map;
+import static org.slf4j.LoggerFactory.getLogger;
+
+
+/**
+ * Get Flow objective next list.
+ */
+@Path("nextobjectives")
+public class FlowObjectiveNextListWebResource extends AbstractWebResource {
+
+ private final Logger log = getLogger(getClass());
+
+ /**
+ * To get all obj-next-Ids.
+ * @return 200 OK with flow objective Next ids.
+ * @onos.rsModel NextObjectives
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getObjNextids() {
+ ObjectNode node = getGroupChainByIdJsonOutput(null, null);
+ return Response.status(200).entity(node).build();
+ }
+
+ /**
+ * Returns all group-chains associated with the given nextId.
+ *
+ * @param nextId nextid mapping
+ * @return 200 OK with array of all the group chain.
+ *
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("nextobjective/{nextId}")
+ public Response getGroupChainByNextid(@PathParam("nextId") String nextId) {
+ ObjectNode node = getGroupChainByIdJsonOutput(Integer.parseInt(nextId), null);
+ return Response.status(200).entity(node).build();
+ }
+
+
+ /**
+ * Returns all group-chains associated with the given deviceId.
+ *
+ * @param deviceId deviceId mapping
+ * @return 200 OK with array of all the group chain.
+ *
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{deviceId}")
+ public Response getGroupChainByDeviceId(@PathParam("deviceId") String deviceId) {
+ ObjectNode node = getGroupChainByIdJsonOutput(null, DeviceId.deviceId(deviceId));
+ return Response.status(200).entity(node).build();
+ }
+
+ private ObjectNode getGroupChainByIdJsonOutput(Integer nextId, DeviceId deviceId) {
+ ObjectNode root = mapper().createObjectNode();
+ ArrayNode connectionArray = mapper().createArrayNode();
+ FlowObjectiveService service = get(FlowObjectiveService.class);
+ Map<Pair<Integer, DeviceId>, List<String>> nextObjGroupMap = service.getNextMappingsChain();
+
+ if (nextId == null && deviceId == null) {
+ nextObjGroupMap.forEach((key, value) -> {
+ ObjectNode mappingNode = mapper().createObjectNode();
+ String keyString = String.format("NextId %s: %s", key.getLeft(), key.getRight());
+ mappingNode.put(keyString, value.toString());
+ connectionArray.add(mappingNode);
+ });
+ } else {
+ nextObjGroupMap.forEach((key, value) -> {
+ ObjectNode mappingNode = mapper().createObjectNode();
+ if ((key.getLeft().equals(nextId)) || (key.getRight().equals(deviceId))) {
+ List groupchain = value;
+ if (deviceId != null && groupchain != null) {
+ String keyString = String.format("NextId %s:", key.getLeft());
+ mappingNode.put(keyString, groupchain.toString());
+ } else if (groupchain != null) {
+ mappingNode.put("groupChain", groupchain.toString());
+ }
+ connectionArray.add(mappingNode);
+ }
+ });
+ }
+ root.put("obj-next-ids", connectionArray);
+
+ return root;
+ }
+
+
+}
diff --git a/web/api/src/main/resources/definitions/NextObjectives.json b/web/api/src/main/resources/definitions/NextObjectives.json
new file mode 100644
index 0000000..686e452
--- /dev/null
+++ b/web/api/src/main/resources/definitions/NextObjectives.json
@@ -0,0 +1,25 @@
+{
+ "type": "object",
+ "title": "obj-next-ids",
+ "required": [
+ "obj-next-ids"
+ ],
+ "properties": {
+ "devices": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "title": "nextId",
+ "required": [
+ "groupChain"
+ ],
+ "properties": {
+ "groupChain": {
+ "type": "array",
+ "example": "[0x1234 --> 0x1246 --> port :1, 0x1234 --> 0x12786 --> port :2] "
+ }
+ }
+ }
+ }
+ }
+}