Merge "Fix missing rest script" into dev/ramcloud-new-datamodel
diff --git a/src/main/java/net/onrc/onos/intent/Intent.java b/src/main/java/net/onrc/onos/intent/Intent.java
index b6a51cb..c6a960f 100644
--- a/src/main/java/net/onrc/onos/intent/Intent.java
+++ b/src/main/java/net/onrc/onos/intent/Intent.java
@@ -54,6 +54,9 @@
public IntentState setState(IntentState newState) {
logs.add(String.format("setState, oldState:%s, newState:%s, time:%d",
state, newState, System.nanoTime())); // for measurement
+ if (logs.size() > 20) { // TODO this size should be configurable
+ logs.removeFirst();
+ }
IntentState oldState = state;
state = newState;
return oldState;
diff --git a/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java b/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java
index 515b0bf..380a0f2 100755
--- a/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java
+++ b/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java
@@ -9,6 +9,8 @@
import edu.stanford.ramcloud.JRamCloud;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong;
import net.onrc.onos.datagrid.web.IntentResource;
import net.onrc.onos.datastore.RCTable;
@@ -29,7 +31,8 @@
private long range = 10000L;
private final IControllerRegistryService controllerRegistry;
NetworkGraph graph = null;
- private final String intentJournal = "G:IntentJournal";
+ private final static String intentJournal = "G:IntentJournal";
+ private final static int valueStoreLimit = 1024 * 1024;
private RCTable table;
private Kryo kryo = new Kryo();
private ByteArrayOutputStream stream;
@@ -61,6 +64,7 @@
}
private long getNextBlock() {
+ // XXX This method is not thread safe, may lose allocated IdBlock
idBlock = controllerRegistry.allocateUniqueIdBlock(range);
nextId = new AtomicLong(idBlock.getStart());
rangeEnd = idBlock.getEnd();
@@ -73,15 +77,40 @@
// TODO call controllerRegistry.isClusterLeader()
if (leader) {
try {
+ // reserve key 10 entries for multi-write if size over 1MB
+ key *= 10;
kryo.writeObject(output, operations);
output.close();
+ ByteBuffer keyBytes = ByteBuffer.allocate(8).putLong(key);
byte[] buffer = stream.toByteArray();
- table.create(String.valueOf(key).getBytes(), buffer);
+ int total = buffer.length;
+ if ((total >= valueStoreLimit )) {
+ int writeCount = total / valueStoreLimit;
+ int remainder = total % valueStoreLimit;
+ int upperIndex = 0;
+ for (int i = 0; i < writeCount; i++, key++) {
+ keyBytes.clear();
+ keyBytes.putLong(key);
+ keyBytes.flip();
+ upperIndex = (i * valueStoreLimit + valueStoreLimit) - 1;
+ log.debug("writing using indexes {}:{}", (i*valueStoreLimit) ,upperIndex);
+ table.create(keyBytes.array(), Arrays.copyOfRange(buffer, i * valueStoreLimit, upperIndex));
+ }
+ if (remainder > 0) {
+ keyBytes.clear();
+ keyBytes.putLong(key);
+ keyBytes.flip();
+ log.debug("writing using indexes {}:{}" ,upperIndex ,total);
+ table.create(keyBytes.array(), Arrays.copyOfRange(buffer, upperIndex + 1, total - 1));
+ }
+ } else {
+ keyBytes.flip();
+ table.create(keyBytes.array(), buffer);
+ }
log.debug("key is {} value length is {}", key, buffer.length);
stream.reset();
stream.close();
log.debug("persist operations to ramcloud size of operations: {}", operations.size());
- if (buffer.length > 921600 ) log.error("oversize key {} value length is {}", key, buffer.length);
ret = true;
} catch (JRamCloud.ObjectExistsException ex) {
log.warn("Failed to store intent journal with key " + key);
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
index abd68d1..6ff92db 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
@@ -107,19 +107,6 @@
pathIntentOpList.add(Operator.REMOVE, new Intent(oldPathIntentId));
}
- // remove old path-intent if exists
- Intent oldIntent = appIntents.getIntent(spIntent.getId());
- if (oldIntent != null) {
- ShortestPathIntent oldSpIntent = (ShortestPathIntent)oldIntent;
- String pathIntentId = oldSpIntent.getPathIntentId();
- if (pathIntentId != null) {
- Intent targetPathIntent = pathIntents.getIntent(pathIntentId);
- if (targetPathIntent != null) {
- pathIntentOpList.add(Operator.REMOVE, targetPathIntent);
- }
- }
- }
-
// create new path-intent
PathIntent pathIntent = new PathIntent(newPathIntentId, path, bandwidth, spIntent);
pathIntent.setState(IntentState.INST_REQ);
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
index b12711a..5691c53 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
@@ -5,13 +5,11 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.intent.FlowEntry;
import net.onrc.onos.intent.Intent;
@@ -23,6 +21,9 @@
import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
//import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
*
* @author Brian O'Connor <bocon@onlab.us>
@@ -40,7 +41,7 @@
public List<Set<FlowEntry>> computePlan(IntentOperationList intentOps) {
long start = System.nanoTime();
- Set<Collection<FlowEntry>> flowEntries = computeFlowEntries(intentOps);
+ List<Collection<FlowEntry>> flowEntries = computeFlowEntries(intentOps);
long step1 = System.nanoTime();
List<Set<FlowEntry>> plan = buildPhases(flowEntries);
long step2 = System.nanoTime();
@@ -49,8 +50,8 @@
return plan;
}
- private Set<Collection<FlowEntry>> computeFlowEntries(IntentOperationList intentOps) {
- Set<Collection<FlowEntry>> flowEntries = new HashSet<>();
+ private List<Collection<FlowEntry>> computeFlowEntries(IntentOperationList intentOps) {
+ List<Collection<FlowEntry>> flowEntries = new LinkedList<>();
for(IntentOperation i : intentOps) {
if(!(i.intent instanceof PathIntent)) {
log.warn("Not a path intent: {}", i);
@@ -106,7 +107,7 @@
return flowEntries;
}
- private List<Set<FlowEntry>> buildPhases(Set<Collection<FlowEntry>> flowEntries) {
+ private List<Set<FlowEntry>> buildPhases(List<Collection<FlowEntry>> flowEntries) {
Map<FlowEntry, Integer> map = new HashMap<>();
List<Set<FlowEntry>> plan = new ArrayList<>();
for(Collection<FlowEntry> c : flowEntries) {
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
index d9f1b0f..b8bed85 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
@@ -81,12 +81,20 @@
}
private void processIntents(IntentOperationList intents) {
+ log("start_processIntents");
log.debug("Processing OperationList {}", intents);
+ log("begin_computePlan");
List<Set<FlowEntry>> plan = planCalc.computePlan(intents);
+ log("end_computePlan");
log.debug("Plan: {}", plan);
+ log("begin_installPlan");
boolean success = planInstall.installPlan(plan);
+ log("end_installPlan");
+ log("begin_sendInstallNotif");
sendNotifications(intents, true, success);
+ log("end_sendInstallNotif");
+ log("finish");
}
private void sendNotifications(IntentOperationList intents, boolean installed, boolean success) {
@@ -120,8 +128,12 @@
@Override
public void entryAdded(IntentOperationList value) {
+ log("start_intentNotifRecv");
+ log("begin_sendReceivedNotif");
sendNotifications(value, false, false);
-
+ log("end_sendReceivedNotif");
+ log("finish");
+
log.debug("Added OperationList {}", value);
try {
intentQueue.put(value);
@@ -140,6 +152,11 @@
// This channel is a queue, so this method is not needed
}
}
+
+ public static void log(String step) {
+ log.error("Time:{}, Step:{}", System.nanoTime(), step);
+ }
+
@Override
public void startUp(FloodlightModuleContext context) {
// start subscriber
diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphLinksResource.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphLinksResource.java
index a244dc1..16da940 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphLinksResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphLinksResource.java
@@ -31,10 +31,13 @@
mapper.registerModule(module);
try {
+ graph.acquireReadLock();
return mapper.writeValueAsString(graph.getLinks());
} catch (IOException e) {
log.error("Error writing link list to JSON", e);
return "";
+ } finally {
+ graph.releaseReadLock();
}
}
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphSwitchesResource.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphSwitchesResource.java
index 92e94f6..3e2a57c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphSwitchesResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphSwitchesResource.java
@@ -33,11 +33,13 @@
mapper.registerModule(module);
try {
+ graph.acquireReadLock();
return mapper.writeValueAsString(graph.getSwitches());
} catch (IOException e) {
log.error("Error writing switch list to JSON", e);
return "";
+ } finally {
+ graph.releaseReadLock();
}
}
-
}
diff --git a/web/get_network_graph.py b/web/get_network_graph.py
new file mode 100755
index 0000000..ed3292b
--- /dev/null
+++ b/web/get_network_graph.py
@@ -0,0 +1,114 @@
+#! /usr/bin/env python
+# -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
+
+#
+# Get Network Graph Elements
+#
+
+import pprint
+import os
+import sys
+import subprocess
+import json
+import argparse
+import io
+import time
+
+from flask import Flask, json, Response, render_template, make_response, request
+
+## Global Var ##
+ControllerIP="127.0.0.1"
+ControllerPort=8080
+
+DEBUG=0
+pp = pprint.PrettyPrinter(indent=4)
+
+app = Flask(__name__)
+
+## Worker Functions ##
+def log_error(txt):
+ print '%s' % (txt)
+
+def debug(txt):
+ if DEBUG:
+ print '%s' % (txt)
+
+# @app.route("/wm/onos/ng/links/json ")
+# @app.route("/wm/onos/ng/switches/json ")
+# Sample output:
+
+def print_parsed_result(parsedResult):
+ print '%s' % (parsedResult),
+
+def get_network_switches():
+ try:
+ command = "curl -s \"http://%s:%s/wm/onos/ng/switches/json\"" % (ControllerIP, ControllerPort)
+ debug("get_network_switches %s" % command)
+
+ result = os.popen(command).read()
+ debug("result %s" % result)
+ if len(result) == 0:
+ print "No Switches found"
+ return;
+
+ # parsedResult = result
+ # parsedResult = json.loads(result)
+ parsedResult = json.dumps(json.loads(result), indent=4)
+ debug("parsed %s" % parsedResult)
+ except:
+ log_error("Controller IF has issue")
+ exit(1)
+
+ print_parsed_result(parsedResult)
+
+def get_network_links():
+ try:
+ command = "curl -s \"http://%s:%s/wm/onos/ng/links/json\"" % (ControllerIP, ControllerPort)
+ debug("get_network_links %s" % command)
+
+ result = os.popen(command).read()
+ debug("result %s" % result)
+ if len(result) == 0:
+ print "No Links found"
+ return;
+
+ # parsedResult = result
+ # parsedResult = json.loads(result)
+ parsedResult = json.dumps(json.loads(result), indent=4)
+ debug("parsed %s" % parsedResult)
+ except:
+ log_error("Controller IF has issue")
+ exit(1)
+
+ print_parsed_result(parsedResult)
+
+
+if __name__ == "__main__":
+ usage_msg1 = "Usage:\n"
+ usage_msg2 = "%s <elements_name> : Print network elements with name of <elements_name>\n" % (sys.argv[0])
+ usage_msg3 = " Valid element names:\n"
+ usage_msg4 = " all : Print all network elements\n"
+ usage_msg5 = " switches : Print all switches and ports\n"
+ usage_msg6 = " links : Print all links\n"
+ usage_msg = usage_msg1 + usage_msg2 + usage_msg3 + usage_msg4 + usage_msg5
+ usage_msg = usage_msg + usage_msg6
+
+ # Usage info
+ if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
+ print(usage_msg)
+ exit(0)
+
+ # Check arguments
+ if len(sys.argv) < 2:
+ log_error(usage_msg)
+ exit(1)
+
+ if (sys.argv[1] != "all" and sys.argv[1] != "switches" and sys.argv[1] != "links"):
+ log_error(usage_msg)
+ exit(1)
+
+ # Do the work
+ if (sys.argv[1] == "all" or sys.argv[1] == "switches"):
+ get_network_switches()
+ if (sys.argv[1] == "all" or sys.argv[1] == "links"):
+ get_network_links()
diff --git a/web/topology_rest_napi.py b/web/topology_rest_napi.py
index 45fc814..e16c197 100755
--- a/web/topology_rest_napi.py
+++ b/web/topology_rest_napi.py
@@ -5,6 +5,7 @@
from flask import Flask, json, Response, render_template, make_response, request
## Global Var for ON.Lab local REST ##
+# The GUI can be accessed at <this_host>:9000/onos-topology.html
RestIP="localhost"
RestPort=8080
ONOS_DEFAULT_HOST="localhost" ;# Has to set if LB=False