Renamed datagrid and datastore packages
net.onrc.onos.datagrid.* => net.onrc.onos.core.datagrid.*
net.onrc.onos.datastore.* => net.onrc.onos.core.datastore.*
Change-Id: Ibe1894a6fabae08ea7cfcbf6595f0c91b05ef497
diff --git a/src/main/java/net/onrc/onos/core/datagrid/web/DatagridWebRoutable.java b/src/main/java/net/onrc/onos/core/datagrid/web/DatagridWebRoutable.java
new file mode 100755
index 0000000..672f66d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datagrid/web/DatagridWebRoutable.java
@@ -0,0 +1,37 @@
+package net.onrc.onos.core.datagrid.web;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+/**
+ * REST API implementation for the Datagrid.
+ */
+public class DatagridWebRoutable implements RestletRoutable {
+ /**
+ * Create the Restlet router and bind to the proper resources.
+ */
+ @Override
+ public Restlet getRestlet(Context context) {
+ Router router = new Router(context);
+ router.attach("/add/intents/json", IntentResource.class);
+ router.attach("/get/intents/json", IntentResource.class);
+ router.attach("/get/intent/{intent_id}/json", IntentResource.class);
+ router.attach("/get/ng-events/json", GetNGEventsResource.class);
+ router.attach("/get/ng-flows/summary/json", GetNGFlowsSummaryResource.class);
+ router.attach("/get/intents/{category}/json", IntentResource.class);
+ router.attach("/get/intent/{category}/{intent_id}/json", IntentResource.class);
+ router.attach("/delete/intents/json", IntentResource.class);
+ return router;
+ }
+
+ /**
+ * Set the base path for the Topology
+ */
+ @Override
+ public String basePath() {
+ return "/wm/onos/datagrid";
+ }
+}
diff --git a/src/main/java/net/onrc/onos/core/datagrid/web/GetNGEventsResource.java b/src/main/java/net/onrc/onos/core/datagrid/web/GetNGEventsResource.java
new file mode 100644
index 0000000..f319d23
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datagrid/web/GetNGEventsResource.java
@@ -0,0 +1,41 @@
+package net.onrc.onos.core.datagrid.web;
+
+import java.util.Collection;
+
+import net.onrc.onos.core.datagrid.IDatagridService;
+import net.onrc.onos.core.datagrid.IEventChannel;
+import net.onrc.onos.ofcontroller.networkgraph.TopologyEvent;
+import net.onrc.onos.ofcontroller.networkgraph.TopologyManager;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GetNGEventsResource extends ServerResource {
+
+ public static final Logger log = LoggerFactory.getLogger(GetNGEventsResource.class);
+
+ @Get("json")
+ public String retrieve() {
+ IDatagridService datagridService =
+ (IDatagridService) getContext().getAttributes().
+ get(IDatagridService.class.getCanonicalName());
+
+
+ log.debug("Get network graph events");
+
+ IEventChannel<byte[], TopologyEvent> channel = datagridService.createChannel(TopologyManager.EVENT_CHANNEL_NAME,
+ byte[].class, TopologyEvent.class);
+
+ Collection<TopologyEvent> entries = channel.getAllEntries();
+
+ String result = "";
+ for (TopologyEvent event : entries) {
+ result += event.toString() + "\n";
+ }
+
+ return result;
+ }
+
+}
diff --git a/src/main/java/net/onrc/onos/core/datagrid/web/GetNGFlowsSummaryResource.java b/src/main/java/net/onrc/onos/core/datagrid/web/GetNGFlowsSummaryResource.java
new file mode 100644
index 0000000..0ebeec9
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datagrid/web/GetNGFlowsSummaryResource.java
@@ -0,0 +1,114 @@
+package net.onrc.onos.core.datagrid.web;
+
+import java.util.ArrayList;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import net.onrc.onos.intent.Intent;
+import net.onrc.onos.intent.PathIntent;
+import net.onrc.onos.intent.ShortestPathIntent;
+import net.onrc.onos.intent.Intent.IntentState;
+import net.onrc.onos.intent.IntentMap;
+import net.onrc.onos.intent.runtime.IPathCalcRuntimeService;
+
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.util.CallerId;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.util.FlowPathType;
+import net.onrc.onos.ofcontroller.util.FlowPathUserState;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * REST API call to get a summary of Flow Paths.
+ *
+ * NOTE: This REST API call is needed for the ONOS GUI.
+ *
+ * GET /wm/onos/datagrid/get/ng-flows/summary/json
+ */
+public class GetNGFlowsSummaryResource extends ServerResource {
+ public static final Logger log = LoggerFactory.getLogger(GetNGFlowsSummaryResource.class);
+
+ @Get("json")
+ public ArrayList<FlowPath> retrieve() {
+ ArrayList<FlowPath> result = new ArrayList<>();
+ SortedMap<Long, FlowPath> sortedFlowPaths = new TreeMap<>();
+
+ IPathCalcRuntimeService pathRuntime =
+ (IPathCalcRuntimeService) getContext().
+ getAttributes().get(IPathCalcRuntimeService.class.getCanonicalName());
+ log.debug("Get NG Flows Summary");
+
+
+ IntentMap parentIntentMap = pathRuntime.getHighLevelIntents();
+ IntentMap intentMap = pathRuntime.getPathIntents();
+ for (Intent parentIntent : parentIntentMap.getAllIntents()) {
+ // Get only installed Shortest Paths
+ if (parentIntent.getState() != IntentState.INST_ACK)
+ continue;
+ if (!(parentIntent instanceof ShortestPathIntent))
+ continue;
+ ShortestPathIntent spIntent = (ShortestPathIntent) parentIntent;
+
+ // Get the Path Intent
+ Intent intent = intentMap.getIntent(spIntent.getPathIntentId());
+ if (!(intent instanceof PathIntent))
+ continue;
+ PathIntent pathIntent = (PathIntent) intent;
+
+ // Decode the Shortest Path ID
+ String applnIntentId = parentIntent.getId();
+ String intentId = applnIntentId.split(":")[1];
+
+ // Create the Flow Path
+ FlowId flowId = new FlowId(intentId);
+ FlowPath flowPath = new FlowPath();
+ flowPath.setFlowId(flowId);
+ sortedFlowPaths.put(flowPath.flowId().value(), flowPath);
+
+ flowPath.setInstallerId(new CallerId("E"));
+ flowPath.setFlowEntryActions(null);
+ flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
+ flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
+
+ // Setup the Source and Destination DPID and Port
+ SwitchPort srcPort = flowPath.dataPath().srcPort();
+ SwitchPort dstPort = flowPath.dataPath().dstPort();
+ srcPort.setDpid(new Dpid(spIntent.getSrcSwitchDpid()));
+ srcPort.setPort(new Port((short) spIntent.getSrcPortNumber()));
+ dstPort.setDpid(new Dpid(spIntent.getDstSwitchDpid()));
+ dstPort.setPort(new Port((short) spIntent.getDstPortNumber()));
+
+ // Extract the Flow Entries
+ Path path = pathIntent.getPath();
+ FlowEntry flowEntry;
+ ArrayList<FlowEntry> flowEntries = new ArrayList<>();
+ for (LinkEvent linkEvent : path) {
+ Dpid dpid = new Dpid(linkEvent.getSrc().getDpid());
+ flowEntry = new FlowEntry();
+ flowEntry.setDpid(dpid);
+ flowEntries.add(flowEntry);
+ }
+ // Add the final Flow Entry
+ flowEntry = new FlowEntry();
+ flowEntry.setDpid(new Dpid(spIntent.getDstSwitchDpid()));
+ flowEntries.add(flowEntry);
+ flowPath.dataPath().setFlowEntries(flowEntries);
+ }
+
+ // Prepare the return result
+ for (FlowPath flowPath : sortedFlowPaths.values())
+ result.add(flowPath);
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/core/datagrid/web/IntentResource.java b/src/main/java/net/onrc/onos/core/datagrid/web/IntentResource.java
new file mode 100755
index 0000000..7d338b5
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/datagrid/web/IntentResource.java
@@ -0,0 +1,230 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package net.onrc.onos.core.datagrid.web;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+
+import net.onrc.onos.intent.ConstrainedShortestPathIntent;
+import net.onrc.onos.intent.ShortestPathIntent;
+import net.onrc.onos.intent.IntentOperation;
+import net.onrc.onos.intent.IntentMap;
+import net.onrc.onos.intent.Intent;
+import net.onrc.onos.intent.runtime.IPathCalcRuntimeService;
+import net.onrc.onos.intent.IntentOperationList;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.restlet.resource.Post;
+import org.restlet.resource.ServerResource;
+import org.codehaus.jackson.map.ObjectMapper;
+import net.floodlightcontroller.util.MACAddress;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import org.codehaus.jackson.node.ArrayNode;
+import org.codehaus.jackson.node.ObjectNode;
+import org.restlet.resource.Delete;
+import org.restlet.resource.Get;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author nickkaranatsios
+ */
+public class IntentResource extends ServerResource {
+ private final static Logger log = LoggerFactory.getLogger(IntentResource.class);
+ // TODO need to assign proper application id.
+ private final String APPLN_ID = "1";
+
+ @Post("json")
+ public String store(String jsonIntent) throws IOException {
+ IPathCalcRuntimeService pathRuntime = (IPathCalcRuntimeService) getContext()
+ .getAttributes().get(IPathCalcRuntimeService.class.getCanonicalName());
+ if (pathRuntime == null) {
+ log.warn("Failed to get path calc runtime");
+ return "";
+ }
+ String reply = "";
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode jNode = null;
+ try {
+ jNode = mapper.readValue(jsonIntent, JsonNode.class);
+ } catch (JsonGenerationException ex) {
+ log.error("JsonGeneration exception ", ex);
+ } catch (JsonMappingException ex) {
+ log.error("JsonMappingException occurred", ex);
+ } catch (IOException ex) {
+ log.error("IOException occurred", ex);
+ }
+
+ if (jNode != null) {
+ reply = parseJsonNode(jNode.getElements(), pathRuntime);
+ }
+ return reply;
+ }
+
+ @Delete("json")
+ public String store() {
+ IPathCalcRuntimeService pathRuntime = (IPathCalcRuntimeService) getContext().
+ getAttributes().get(IPathCalcRuntimeService.class.getCanonicalName());
+ pathRuntime.purgeIntents();
+ // TODO no reply yet from the purge intents call
+ return "";
+
+ }
+
+ @Get("json")
+ public String retrieve() throws IOException {
+ IPathCalcRuntimeService pathRuntime = (IPathCalcRuntimeService) getContext().
+ getAttributes().get(IPathCalcRuntimeService.class.getCanonicalName());
+
+ String intentCategory = (String) getRequestAttributes().get("category");
+ IntentMap intentMap = null;
+ if (intentCategory.equals("high")) {
+ intentMap = pathRuntime.getHighLevelIntents();
+ } else {
+ intentMap = pathRuntime.getPathIntents();
+ }
+ ObjectMapper mapper = new ObjectMapper();
+ String restStr = "";
+
+ String intentId = (String) getRequestAttributes().get("intent_id");
+ ArrayNode arrayNode = mapper.createArrayNode();
+ Collection<Intent> intents = intentMap.getAllIntents();
+ if (!intents.isEmpty()) {
+ if ((intentId != null)) {
+ String applnIntentId = APPLN_ID + ":" + intentId;
+ Intent intent = intentMap.getIntent(applnIntentId);
+ if (intent != null) {
+ ObjectNode node = mapper.createObjectNode();
+ // TODO refactor/remove duplicate code.
+ node.put("intent_id", intentId);
+ node.put("status", intent.getState().toString());
+ LinkedList<String> logs = intent.getLogs();
+ ArrayNode logNode = mapper.createArrayNode();
+ for (String intentLog : logs) {
+ logNode.add(intentLog);
+ }
+ node.put("log", logNode);
+ arrayNode.add(node);
+ }
+ } else {
+ for (Intent intent : intents) {
+ ObjectNode node = mapper.createObjectNode();
+ String applnIntentId = intent.getId();
+ intentId = applnIntentId.split(":")[1];
+ node.put("intent_id", intentId);
+ node.put("status", intent.getState().toString());
+ LinkedList<String> logs = intent.getLogs();
+ ArrayNode logNode = mapper.createArrayNode();
+ for (String intentLog : logs) {
+ logNode.add(intentLog);
+ }
+ node.put("log", logNode);
+ arrayNode.add(node);
+ }
+ }
+ restStr = mapper.writeValueAsString(arrayNode);
+ }
+ return restStr;
+ }
+
+ private String parseJsonNode(Iterator<JsonNode> nodes,
+ IPathCalcRuntimeService pathRuntime) throws IOException {
+ IntentOperationList operations = new IntentOperationList();
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode arrayNode = mapper.createArrayNode();
+ while (nodes.hasNext()) {
+ JsonNode node = nodes.next();
+ if (node.isObject()) {
+ JsonNode data;
+ Iterator<String> fieldNames = node.getFieldNames();
+ Map<String, Object> fields = new HashMap<>();
+ while (fieldNames.hasNext()) {
+ String fieldName = fieldNames.next();
+ data = node.get(fieldName);
+ parseFields(data, fieldName, fields);
+ }
+ Intent intent = processIntent(fields, operations);
+ appendIntentStatus(intent, (String) fields.get("intent_id"), mapper, arrayNode);
+ }
+ }
+ pathRuntime.executeIntentOperations(operations);
+ return mapper.writeValueAsString(arrayNode);
+ }
+
+ private void appendIntentStatus(Intent intent, final String intentId,
+ ObjectMapper mapper, ArrayNode arrayNode) throws IOException {
+ ObjectNode node = mapper.createObjectNode();
+ node.put("intent_id", intentId);
+ node.put("status", intent.getState().toString());
+ LinkedList<String> logs = intent.getLogs();
+ ArrayNode logNode = mapper.createArrayNode();
+ for (String intentLog : logs) {
+ logNode.add(intentLog);
+ }
+ node.put("log", logNode);
+ arrayNode.add(node);
+ }
+
+ private Intent processIntent(Map<String, Object> fields, IntentOperationList operations) {
+ String intentType = (String) fields.get("intent_type");
+ String intentOp = (String) fields.get("intent_op");
+ Intent intent;
+ String intentId = (String) fields.get("intent_id");
+ boolean pathFrozen = false;
+ if (intentId.startsWith("F")) { // TODO define REST API for frozen intents
+ pathFrozen = true;
+ intentId = intentId.substring(1);
+ }
+ String applnIntentId = APPLN_ID + ":" + intentId;
+
+ IntentOperation.Operator operation = IntentOperation.Operator.ADD;
+ if ((intentOp.equals("remove"))) {
+ operation = IntentOperation.Operator.REMOVE;
+ }
+ if (intentType.equals("shortest_intent_type")) {
+ ShortestPathIntent spi = new ShortestPathIntent(applnIntentId,
+ Long.decode((String) fields.get("srcSwitch")),
+ (long) fields.get("srcPort"),
+ MACAddress.valueOf((String) fields.get("srcMac")).toLong(),
+ Long.decode((String) fields.get("dstSwitch")),
+ (long) fields.get("dstPort"),
+ MACAddress.valueOf((String) fields.get("dstMac")).toLong());
+ spi.setPathFrozen(pathFrozen);
+ operations.add(operation, spi);
+ intent = spi;
+ } else {
+ ConstrainedShortestPathIntent cspi = new ConstrainedShortestPathIntent(applnIntentId,
+ Long.decode((String) fields.get("srcSwitch")),
+ (long) fields.get("srcPort"),
+ MACAddress.valueOf((String) fields.get("srcMac")).toLong(),
+ Long.decode((String) fields.get("dstSwitch")),
+ (long) fields.get("dstPort"),
+ MACAddress.valueOf((String) fields.get("dstMac")).toLong(),
+ (double) fields.get("bandwidth"));
+ cspi.setPathFrozen(pathFrozen);
+ operations.add(operation, cspi);
+ intent = cspi;
+ }
+ return intent;
+ }
+
+ private void parseFields(JsonNode node, String fieldName, Map<String, Object> fields) {
+ if ((node.isTextual())) {
+ fields.put(fieldName, node.getTextValue());
+ } else if ((node.isInt())) {
+ fields.put(fieldName, (long) node.getIntValue());
+ } else if (node.isDouble()) {
+ fields.put(fieldName, node.getDoubleValue());
+ } else if ((node.isLong())) {
+ fields.put(fieldName, node.getLongValue());
+ }
+ }
+}