aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/tools/test
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
commit13d05bc8458758ee39cb829098241e89616717ee (patch)
tree22a4d1ce65f15952f07a3df5af4b462b4697cb3a /framework/src/onos/tools/test
parent6139282e1e93c2322076de4b91b1c85d0bc4a8b3 (diff)
ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60
Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd
Diffstat (limited to 'framework/src/onos/tools/test')
-rw-r--r--framework/src/onos/tools/test/README1
-rw-r--r--framework/src/onos/tools/test/bin/find-node.sh32
-rw-r--r--framework/src/onos/tools/test/bin/flow-tester.py45
-rw-r--r--framework/src/onos/tools/test/bin/ogroup-opts58
-rw-r--r--framework/src/onos/tools/test/bin/old.json387
-rwxr-xr-xframework/src/onos/tools/test/bin/onos21
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-archetypes-test21
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-batch17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-apps34
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-bits9
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-components17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-flows15
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-intent24
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-logs60
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-nodes20
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-summary20
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-check-views17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-config57
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-create-intent22
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-die9
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-fetch-logs43
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-fetch-vms11
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-form-cluster32
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-gen-partitions52
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-group90
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-gui9
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-install67
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-intentperf-scrape17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-iterm-cli42
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-iterm-logs42
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-jpenable19
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-kill18
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-list-cells18
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-local7
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-log38
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-log-kill16
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-log-write37
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-mininet69
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-oecfg12
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-patch-vm22
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-push-bits19
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-push-bits-through-proxy22
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-push-keys19
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-push-test-bits16
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-push-topos11
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-push-update-bundle27
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-remove-raft-logs14
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-rsdocs9
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-secure-ssh31
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-service55
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-set-controllers17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-show-cell57
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-ssh11
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-stage-apps29
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-start-network17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-topo-cfg14
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-topo-cfg-all15
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-uninstall14
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-untar-and-run24
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-upload-sprites18
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-user-key13
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-verify-cell11
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-wait-for-start28
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-watch17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-wipe-out9
-rwxr-xr-xframework/src/onos/tools/test/bin/stc23
-rwxr-xr-xframework/src/onos/tools/test/bin/stc-launcher25
-rwxr-xr-xframework/src/onos/tools/test/bin/stl7
-rw-r--r--framework/src/onos/tools/test/cells/beast18
-rw-r--r--framework/src/onos/tools/test/cells/beast-112
-rw-r--r--framework/src/onos/tools/test/cells/beast-314
-rw-r--r--framework/src/onos/tools/test/cells/beast-518
-rw-r--r--framework/src/onos/tools/test/cells/bramble8
-rw-r--r--framework/src/onos/tools/test/cells/ec218
-rw-r--r--framework/src/onos/tools/test/cells/local8
-rw-r--r--framework/src/onos/tools/test/cells/madan37
-rw-r--r--framework/src/onos/tools/test/cells/office7
-rw-r--r--framework/src/onos/tools/test/cells/prox6
-rw-r--r--framework/src/onos/tools/test/cells/sdnip-pmox8
-rw-r--r--framework/src/onos/tools/test/cells/single7
-rw-r--r--framework/src/onos/tools/test/cells/single_optical7
-rw-r--r--framework/src/onos/tools/test/cells/tom7
-rw-r--r--framework/src/onos/tools/test/cells/tomx10
-rw-r--r--framework/src/onos/tools/test/cells/triple9
-rw-r--r--framework/src/onos/tools/test/configs/l2-flow.json28
-rw-r--r--framework/src/onos/tools/test/configs/override-basic.json38
-rw-r--r--framework/src/onos/tools/test/configs/sample-basic.json54
-rw-r--r--framework/src/onos/tools/test/scenarios/archetypes.xml50
-rwxr-xr-xframework/src/onos/tools/test/scenarios/bin/create-flow.py56
-rwxr-xr-xframework/src/onos/tools/test/scenarios/bin/create-intent.py49
-rwxr-xr-xframework/src/onos/tools/test/scenarios/bin/find-device.py39
-rwxr-xr-xframework/src/onos/tools/test/scenarios/bin/find-flow.py40
-rwxr-xr-xframework/src/onos/tools/test/scenarios/bin/find-host.py36
-rwxr-xr-xframework/src/onos/tools/test/scenarios/bin/find-link.py45
-rw-r--r--framework/src/onos/tools/test/scenarios/example.xml19
-rw-r--r--framework/src/onos/tools/test/scenarios/net-create-flows.xml93
-rw-r--r--framework/src/onos/tools/test/scenarios/net-host-intent.xml59
-rw-r--r--framework/src/onos/tools/test/scenarios/net-link-down-up.xml38
-rw-r--r--framework/src/onos/tools/test/scenarios/net-pingall.xml37
-rw-r--r--framework/src/onos/tools/test/scenarios/net-point-intent.xml77
-rw-r--r--framework/src/onos/tools/test/scenarios/net-rest.xml160
-rw-r--r--framework/src/onos/tools/test/scenarios/net-setup.xml46
-rw-r--r--framework/src/onos/tools/test/scenarios/net-smoke.xml44
-rw-r--r--framework/src/onos/tools/test/scenarios/net-teardown.xml21
-rw-r--r--framework/src/onos/tools/test/scenarios/prerequisites.xml26
-rw-r--r--framework/src/onos/tools/test/scenarios/setup.xml47
-rw-r--r--framework/src/onos/tools/test/scenarios/shutdown.xml24
-rw-r--r--framework/src/onos/tools/test/scenarios/smoke.xml30
-rw-r--r--framework/src/onos/tools/test/scenarios/startup.xml26
-rw-r--r--framework/src/onos/tools/test/scenarios/tar-setup.xml64
-rw-r--r--framework/src/onos/tools/test/scenarios/wrapup.xml24
-rwxr-xr-xframework/src/onos/tools/test/topos/att-onos10
-rw-r--r--framework/src/onos/tools/test/topos/att-onos-ext.py31
-rw-r--r--framework/src/onos/tools/test/topos/att-onos.py41
-rw-r--r--framework/src/onos/tools/test/topos/attcli.py138
-rwxr-xr-xframework/src/onos/tools/test/topos/attmpls-intents8
-rw-r--r--framework/src/onos/tools/test/topos/attmpls.json58
-rw-r--r--framework/src/onos/tools/test/topos/attmpls.py177
-rw-r--r--framework/src/onos/tools/test/topos/attmplsfast.py174
-rw-r--r--framework/src/onos/tools/test/topos/chordal.py402
-rw-r--r--framework/src/onos/tools/test/topos/cord.json24
-rwxr-xr-xframework/src/onos/tools/test/topos/fractal.py56
-rw-r--r--framework/src/onos/tools/test/topos/linear-2.json6
-rw-r--r--framework/src/onos/tools/test/topos/newFuncTopo.py148
-rwxr-xr-xframework/src/onos/tools/test/topos/obelisk.py70
-rwxr-xr-xframework/src/onos/tools/test/topos/obeliskHostCheck.py91
-rw-r--r--framework/src/onos/tools/test/topos/oe-linear-3.json48
-rw-r--r--framework/src/onos/tools/test/topos/oe-nonlinear-10.json149
-rw-r--r--framework/src/onos/tools/test/topos/oe-nonlinear-4.json52
-rwxr-xr-xframework/src/onos/tools/test/topos/onos.py225
-rwxr-xr-xframework/src/onos/tools/test/topos/optical.py79
-rw-r--r--framework/src/onos/tools/test/topos/optical2.py84
-rw-r--r--framework/src/onos/tools/test/topos/opticalTest.py98
-rw-r--r--framework/src/onos/tools/test/topos/opticalTestBig.py391
-rw-r--r--framework/src/onos/tools/test/topos/opticalUtils.py771
-rw-r--r--framework/src/onos/tools/test/topos/rftest.py40
-rw-r--r--framework/src/onos/tools/test/topos/rftesttopo.py59
-rw-r--r--framework/src/onos/tools/test/topos/sdn-ip.json26
-rwxr-xr-xframework/src/onos/tools/test/topos/sol.py4
-rw-r--r--framework/src/onos/tools/test/topos/solar.py97
-rw-r--r--framework/src/onos/tools/test/topos/sys-nonlinear-10.config183
-rw-r--r--framework/src/onos/tools/test/topos/sys-nonlinear-4.config79
-rw-r--r--framework/src/onos/tools/test/topos/sys.config183
-rwxr-xr-xframework/src/onos/tools/test/topos/topo10
-rw-r--r--framework/src/onos/tools/test/topos/topo-200sw-linkalarm.py20
-rwxr-xr-xframework/src/onos/tools/test/topos/tower2
-rwxr-xr-xframework/src/onos/tools/test/topos/tower.py55
147 files changed, 7642 insertions, 0 deletions
diff --git a/framework/src/onos/tools/test/README b/framework/src/onos/tools/test/README
new file mode 100644
index 00000000..3d6b1eb7
--- /dev/null
+++ b/framework/src/onos/tools/test/README
@@ -0,0 +1 @@
+Artifacts for system testing onos.
diff --git a/framework/src/onos/tools/test/bin/find-node.sh b/framework/src/onos/tools/test/bin/find-node.sh
new file mode 100644
index 00000000..e76a84a6
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/find-node.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+validate_number () {
+ local re="^[0-9]+$"
+ if [[ ! $1 =~ $re ]] ; then
+ return 1
+ fi
+
+ return 0
+}
+
+find_node () {
+ if validate_number $1 ; then
+ # input is a number, try to find if an OC node is defined
+
+ oc_try="OC$1"
+ node=${!oc_try}
+
+ if [ -n "$node" ]; then
+ # node lookup succeeded, return node
+ echo $node
+ else
+ # node lookup failed, return original input
+ echo $1
+ fi
+
+ else
+ echo $1
+ fi
+
+ return 0
+}
diff --git a/framework/src/onos/tools/test/bin/flow-tester.py b/framework/src/onos/tools/test/bin/flow-tester.py
new file mode 100644
index 00000000..d77a861b
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/flow-tester.py
@@ -0,0 +1,45 @@
+import concurrent.futures
+import requests, json
+from optparse import OptionParser
+
+def run(url, request):
+ data = json.dumps(request)
+ r = requests.post(url, data)
+ return r
+
+def runTasks(flowPerDevice, neighbours, url, servers, doJson, remove):
+ # We can use a with statement to ensure threads are cleaned up promptly
+ with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
+ # Start the load operations and mark each future with its URL
+ request = { "flowsPerDevice" : flowPerDevice, "neighbours" : neighbours, "remove" : remove }
+ future_to_url = {executor.submit(run, url % (server), request) for server in servers}
+ for f in concurrent.futures.as_completed(future_to_url):
+ try:
+ response = f.result()
+ server = response.url.split('//')[1].split(':')[0]
+ if (doJson):
+ print (json.dumps({ "server" : server, "elapsed" : response.json()['elapsed'] }))
+ else:
+ print ("%s -> %sms" % (server, response.json()['elapsed']))
+ except Exception as exc:
+ print("Execution failed -> %s" % exc)
+
+if __name__ == "__main__":
+ parser = OptionParser()
+ parser.add_option("-u", "--url", dest="url", help="set the url for the request",
+ default="http://%s:8181/onos/demo/intents/flowTest")
+ parser.add_option("-f", "--flows", dest="flows", help="Number of flows to install per device",
+ default=100, type="int")
+ parser.add_option("-n", "--neighbours", dest="neighs", help="Number of neighbours to communicate to",
+ default=0, type="int")
+ parser.add_option("-s", "--servers", dest="servers", help="List of servers to hit",
+ default=[], action="append")
+ parser.add_option("-r", "--remove", dest="remove", help="Do not remove flows after installation",
+ default=True, action="store_false")
+ parser.add_option("-j", "--json", dest="doJson", help="Print results in json",
+ default=False, action="store_true")
+
+ (options, args) = parser.parse_args()
+ if (len(options.servers) == 0):
+ options.servers.append("localhost")
+ runTasks(options.flows, options.neighs, options.url, options.servers, options.doJson, options.remove)
diff --git a/framework/src/onos/tools/test/bin/ogroup-opts b/framework/src/onos/tools/test/bin/ogroup-opts
new file mode 100644
index 00000000..41842bdd
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/ogroup-opts
@@ -0,0 +1,58 @@
+# Options read by onos-group for help message formatting and sanity checks.
+GOPTS='install kill patch-vm push-keys uninstall'
+
+# Tab completion settings for onos-group.
+function _ogroup-opts () {
+ local cur=${COMP_WORDS[COMP_CWORD]}
+ if [ $COMP_CWORD -eq 1 ]; then
+ COMPREPLY=( $( compgen -W "${GOPTS} help" -- $cur ) )
+ fi
+}
+
+complete -F _ogroup-opts onos-group
+
+
+# Tab completion settings for stc
+function _stc-opts () {
+ local cur=${COMP_WORDS[COMP_CWORD]}
+ if [ $COMP_CWORD -eq 1 ]; then
+ COMPREPLY=( $( compgen -W "$(cd $ONOS_ROOT/tools/test/scenarios && ls -1 | sed 's/.xml//g')" -- $cur ) )
+ fi
+}
+
+complete -F _stc-opts stc
+
+
+# Tab completion settings for stl
+function _stl-opts () {
+ local cur=${COMP_WORDS[COMP_CWORD]}
+ if [ $COMP_CWORD -eq 1 ]; then
+ COMPREPLY=( $( compgen -W "$(cd /tmp/stc && ls -1)" -- $cur ) )
+ elif [ $COMP_CWORD -eq 2 ]; then
+ COMPREPLY=( $( compgen -W "$(cd /tmp/stc/$3 && ls -1)" -- $cur ) )
+ fi
+}
+
+complete -F _stl-opts stl
+
+
+# Tab completion settings for cell
+function _cell-opts () {
+ local cur=${COMP_WORDS[COMP_CWORD]}
+ if [ $COMP_CWORD -eq 1 ]; then
+ COMPREPLY=( $( compgen -W "$(cd $ONOS_ROOT/tools/test/cells && ls -1)" -- $cur ) )
+ fi
+}
+
+complete -F _cell-opts cell
+
+
+# Tab completion settings for onos-create-app.
+function _ocapp-opts () {
+ local cur=${COMP_WORDS[COMP_CWORD]}
+ if [ $COMP_CWORD -eq 1 ]; then
+ COMPREPLY=( $( compgen -W "bundle ui cli" -- $cur ) )
+ fi
+}
+
+complete -F _ocapp-opts onos-create-app
diff --git a/framework/src/onos/tools/test/bin/old.json b/framework/src/onos/tools/test/bin/old.json
new file mode 100644
index 00000000..713efbf6
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/old.json
@@ -0,0 +1,387 @@
+{
+ "linkConfig": [
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:02",
+ "params": {
+ "nodeName1": "SFO-W10",
+ "nodeName2": "SJC-W10",
+ "numWaves": 80,
+ "port1": 50,
+ "port2": 30
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:03",
+ "params": {
+ "nodeName1": "SJC-W10",
+ "nodeName2": "LAX-W10",
+ "numWaves": 80,
+ "port1": 50,
+ "port2": 30
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:04",
+ "params": {
+ "nodeName1": "LAX-W10",
+ "nodeName2": "SDG-W10",
+ "numWaves": 80,
+ "port1": 50,
+ "port2": 50
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:05",
+ "params": {
+ "nodeName1": "SFO-W10",
+ "nodeName2": "MSP-M10",
+ "numWaves": 80,
+ "port1": 20,
+ "port2": 50
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:05",
+ "params": {
+ "nodeName1": "SJC-W10",
+ "nodeName2": "MSP-M10",
+ "numWaves": 80,
+ "port1": 20,
+ "port2": 20
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+ "params": {
+ "nodeName1": "LAX-W10",
+ "nodeName2": "DFW-M10",
+ "numWaves": 80,
+ "port1": 20,
+ "port2": 50
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:04",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+ "params": {
+ "nodeName1": "SDG-W10",
+ "nodeName2": "DFW-M10",
+ "numWaves": 80,
+ "port1": 20,
+ "port2": 20
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:05",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+ "params": {
+ "nodeName1": "MSP-M10",
+ "nodeName2": "DFW-M10",
+ "numWaves": 80,
+ "port1": 30,
+ "port2": 40
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:05",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:07",
+ "params": {
+ "nodeName1": "MSP-M10",
+ "nodeName2": "CHG-N10",
+ "numWaves": 80,
+ "port1": 40,
+ "port2": 50
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:06",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:08",
+ "params": {
+ "nodeName1": "DFW-M10",
+ "nodeName2": "IAD-M10",
+ "numWaves": 80,
+ "port1": 30,
+ "port2": 50
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:07",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:08",
+ "params": {
+ "nodeName1": "CHG-N10",
+ "nodeName2": "IAD-M10",
+ "numWaves": 80,
+ "port1": 20,
+ "port2": 30
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:07",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:09",
+ "params": {
+ "nodeName1": "CHG-N10",
+ "nodeName2": "JFK-M10",
+ "numWaves": 80,
+ "port1": 30,
+ "port2": 50
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:08",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
+ "params": {
+ "nodeName1": "IAD-M10",
+ "nodeName2": "ATL-S10",
+ "numWaves": 80,
+ "port1": 20,
+ "port2": 50
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:ff:09",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
+ "params": {
+ "nodeName1": "JFK-M10",
+ "nodeName2": "ATL-S10",
+ "numWaves": 80,
+ "port1": 20,
+ "port2": 20
+ },
+ "type": "wdmLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:00:01",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:01",
+ "params": {
+ "bandwidth": 100000,
+ "nodeName1": "SFO-R10",
+ "nodeName2": "SFO-W10",
+ "port1": 2,
+ "port2": 10
+ },
+ "type": "pktOptLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:00:02",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:04",
+ "params": {
+ "bandwidth": 100000,
+ "nodeName1": null,
+ "nodeName2": "SDG-W10",
+ "port1": 2,
+ "port2": 10
+ },
+ "type": "pktOptLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:00:03",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+ "params": {
+ "bandwidth": 100000,
+ "nodeName1": "LAX-R10",
+ "nodeName2": "DFW-M10",
+ "port1": 2,
+ "port2": 10
+ },
+ "type": "pktOptLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:00:04",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:07",
+ "params": {
+ "bandwidth": 100000,
+ "nodeName1": "SDG-R10",
+ "nodeName2": "CHG-N10",
+ "port1": 2,
+ "port2": 10
+ },
+ "type": "pktOptLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:00:05",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:09",
+ "params": {
+ "bandwidth": 100000,
+ "nodeName1": null,
+ "nodeName2": "JFK-M10",
+ "port1": 2,
+ "port2": 10
+ },
+ "type": "pktOptLink"
+ },
+ {
+ "allowed": true,
+ "nodeDpid1": "00:00:ff:ff:ff:ff:00:06",
+ "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
+ "params": {
+ "bandwidth": 100000,
+ "nodeName1": null,
+ "nodeName2": "ATL-S10",
+ "port1": 2,
+ "port2": 10
+ },
+ "type": "pktOptLink"
+ }
+ ],
+ "switchConfig": [
+ {
+ "allowed": true,
+ "latitude": 37.6,
+ "longitude": 122.3,
+ "name": "SFO-W10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:01",
+ "params": {
+ "numRegen": 0
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 37.3,
+ "longitude": 121.9,
+ "name": "SJC-W10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:02",
+ "params": {
+ "numRegen": 0
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 33.9,
+ "longitude": 118.4,
+ "name": "LAX-W10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:03",
+ "params": {
+ "numRegen": 0
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 32.8,
+ "longitude": 117.1,
+ "name": "SDG-W10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:04",
+ "params": {
+ "numRegen": 3
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 44.8,
+ "longitude": 93.1,
+ "name": "MSP-M10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:05",
+ "params": {
+ "numRegen": 3
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 32.8,
+ "longitude": 97.1,
+ "name": "DFW-M10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:06",
+ "params": {
+ "numRegen": 3
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 41.8,
+ "longitude": 120.1,
+ "name": "CHG-N10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:07",
+ "params": {
+ "numRegen": 3
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 38.8,
+ "longitude": 77.1,
+ "name": "IAD-M10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:08",
+ "params": {
+ "numRegen": 3
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 40.8,
+ "longitude": 73.1,
+ "name": "JFK-M10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:09",
+ "params": {
+ "numRegen": 0
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 33.8,
+ "longitude": 84.1,
+ "name": "ATL-S10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:0A",
+ "params": {
+ "numRegen": 0
+ },
+ "type": "Roadm"
+ },
+ {
+ "allowed": true,
+ "latitude": 32.8,
+ "longitude": 97.1,
+ "name": "DFW-M10",
+ "nodeDpid": "00:00:ff:ff:ff:ff:ff:06",
+ "params": {
+ "numRegen": 3
+ },
+ "type": "Roadm"
+ }
+ ]
+}
diff --git a/framework/src/onos/tools/test/bin/onos b/framework/src/onos/tools/test/bin/onos
new file mode 100755
index 00000000..89197db5
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos
@@ -0,0 +1,21 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# ONOS remote command-line client.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
+
+[ "$1" = "-w" ] && shift && onos-wait-for-start $1
+
+[ -n "$1" ] && OCI=$(find_node $1) && shift
+
+if which client 1>/dev/null 2>&1 && [ -z "$ONOS_USE_SSH" ]; then
+ # Use Karaf client only if we can and are allowed to
+ unset KARAF_HOME
+ client -h $OCI -u karaf "$@" 2>/dev/null
+else
+ # Otherwise use raw ssh; strict checking is off for dev environments only
+ ssh -p 8101 -o StrictHostKeyChecking=no $OCI "$@"
+fi
diff --git a/framework/src/onos/tools/test/bin/onos-archetypes-test b/framework/src/onos/tools/test/bin/onos-archetypes-test
new file mode 100755
index 00000000..55f40e76
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-archetypes-test
@@ -0,0 +1,21 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Builds a set of projects using ONOS archetypes.
+# -----------------------------------------------------------------------------
+
+set -e
+
+export AROOT=/tmp/foo
+export ARCHETYPE_OPTS="-DarchetypeGroupId=org.onosproject -DarchetypeVersion=1.3.0-SNAPSHOT"
+
+mkdir -p $AROOT
+for an in api bundle cli ui; do
+ cd $AROOT
+ rm -fr $AROOT/foo-$an
+ mvn archetype:generate $ARCHETYPE_OPTS \
+ -DarchetypeArtifactId=onos-$an-archetype \
+ -DgroupId=org.foo -DartifactId=foo-$an -Dversion=1.0 \
+ -Dpackage=org.foo.$an -DinteractiveMode=false
+ cd $AROOT/foo-$an
+ mvn clean install
+done
diff --git a/framework/src/onos/tools/test/bin/onos-batch b/framework/src/onos/tools/test/bin/onos-batch
new file mode 100755
index 00000000..67864a22
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-batch
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Executes selected set of ONOS commands using the batch mode.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCI}
+
+commands="${2:-summary,intents,flows,hosts}"
+
+aux=/tmp/onos-batch.$$
+trap "rm -f $aux" EXIT
+
+echo "$commands" | tr ',' '\n' > $aux
+onos $node -b <$aux
diff --git a/framework/src/onos/tools/test/bin/onos-check-apps b/framework/src/onos/tools/test/bin/onos-check-apps
new file mode 100755
index 00000000..dfd6b4ef
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-apps
@@ -0,0 +1,34 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks whether all and only the ONOS apps configured in ONOS_APPS are active.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux $aux.1 $aux.2 2>/dev/null" EXIT
+
+for attempt in {1..3}; do
+ onos ${1:-$OCI} "onos:apps -s -a" | grep -v /bin/client > $aux
+ cat $aux
+
+ # Normalize the installed apps
+ cut -c7- $aux | grep -v '/bin/client' | cut -d\ -f1 | sort > $aux.1
+
+ # Normalize the expected apps
+ apps=${2:-$ONOS_APPS}
+ apps=${apps:-drivers,openflow}
+ (for app in ${apps//,/ }; do echo org.onosproject.$app; done) | sort > $aux.2
+
+ # Check for differences
+ case ${3:-equals} in
+ equals) diff $aux.1 $aux.2;;
+ includes) [ $(egrep -c -f $aux.2 $aux.1) -eq $(wc -l $aux.2 | sed "s|$aux.2||g") ];;
+ excludes) ! egrep -f $aux.2 $aux.1;;
+ esac
+
+ [ $? -eq 0 ] && exit 0 || sleep 1
+done
+
+exit 1;
diff --git a/framework/src/onos/tools/test/bin/onos-check-bits b/framework/src/onos/tools/test/bin/onos-check-bits
new file mode 100755
index 00000000..0423c342
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-bits
@@ -0,0 +1,9 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks if ONOS bits are available in preparation for install.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+ls -l $ONOS_TAR && cksum $ONOS_TAR
diff --git a/framework/src/onos/tools/test/bin/onos-check-components b/framework/src/onos/tools/test/bin/onos-check-components
new file mode 100755
index 00000000..f4c2df2c
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-components
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks whether all ONOS components are either ACTIVE or DISABLED.
+# -----------------------------------------------------------------------------
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux 2>/dev/null" EXIT
+
+onos ${1:-$OCI} scr:list > $aux
+cat $aux
+grep -q UNSATISFIED $aux && exit 1
+
+if [ -n "$2" ]; then
+ echo "Searching for ACTIVE $2"
+ egrep "ACTIVE.*$2" $aux || exit 1
+fi
+exit 0 \ No newline at end of file
diff --git a/framework/src/onos/tools/test/bin/onos-check-flows b/framework/src/onos/tools/test/bin/onos-check-flows
new file mode 100755
index 00000000..6debebcd
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-flows
@@ -0,0 +1,15 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks ONOS summary data
+# -----------------------------------------------------------------------------
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux 2>/dev/null" EXIT
+
+onos ${1:-$OCI} "onos:flows" > $aux
+cat $aux
+
+let status=0
+grep "PENDING_" $aux && let status=status+1
+
+exit $status \ No newline at end of file
diff --git a/framework/src/onos/tools/test/bin/onos-check-intent b/framework/src/onos/tools/test/bin/onos-check-intent
new file mode 100755
index 00000000..e332dc5b
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-intent
@@ -0,0 +1,24 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks that all intents in the system have a given state.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux 2>/dev/null" EXIT
+target=${1:-$OCI}
+
+echo onos-check-intent: $*
+
+set -x
+for i in {1..10}; do
+ onos $target "onos:intents" | tee $aux
+ ( cat $aux | grep "key=$2" | grep "state=$3" ) && cat $aux && exit 0
+ sleep 1
+done
+
+cat $aux
+exit 1
+
diff --git a/framework/src/onos/tools/test/bin/onos-check-logs b/framework/src/onos/tools/test/bin/onos-check-logs
new file mode 100755
index 00000000..ec1013ab
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-logs
@@ -0,0 +1,60 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks the logs of the remote ONOS instance and makes sure they are clean.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+remote=$ONOS_USER@${1:-$OCI}
+
+LOG=$ONOS_INSTALL_DIR/log/karaf.log*
+
+aux=/tmp/log.$$
+
+if [ "$2" = "old" ]; then
+ ssh $remote "egrep 'ERROR|Exception|Error' $LOG"
+
+else
+ ssh $remote "
+ tac $LOG | awk '
+ BEGIN { off = 0; fail = 0; }
+ / org.apache.karaf.main.lock.SimpleFileLock lock/ {
+ off = 1;
+ exit fail;
+ }
+
+ / ERROR / {
+ if (!off) {
+ print \$0;
+ exc = 0;
+ fail = 1;
+ }
+ }
+ / WARN / {
+ if (!off && exc) {
+ print \$0;
+ exc = 0;
+ }
+ }
+
+ /^[a-zA-Z0-9.]*(Exception|Error)/ {
+ if (!off) {
+ print \$0;
+ exc = 1;
+ fail = 1;
+ }
+ }
+
+ / at / {
+ if (!off) {
+ print \$0;
+ }
+ }
+ END { exit fail; }
+ ' > $aux
+ status=\$?
+ tac $aux && rm $aux
+ exit \$status
+ "
+fi
diff --git a/framework/src/onos/tools/test/bin/onos-check-nodes b/framework/src/onos/tools/test/bin/onos-check-nodes
new file mode 100755
index 00000000..69187b6a
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-nodes
@@ -0,0 +1,20 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks whether all and only the ONOS instances configured active.
+# -----------------------------------------------------------------------------
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux $aux.1 $aux.2 2>/dev/null" EXIT
+
+onos ${1:-$OCI} "onos:nodes" | grep -v /bin/client > $aux
+cat $aux
+
+# Normalize the nodes
+cut -d= -f3 $aux | cut -d: -f1 | sort > $aux.1
+
+# Normalize the expected nodes
+nodes=${2:-$ONOS_INSTANCES}
+(for node in $nodes; do echo $node; done) | sort > $aux.2
+
+# Check for differences
+diff $aux.1 $aux.2
diff --git a/framework/src/onos/tools/test/bin/onos-check-summary b/framework/src/onos/tools/test/bin/onos-check-summary
new file mode 100755
index 00000000..ab7c22dd
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-summary
@@ -0,0 +1,20 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks ONOS summary data
+# -----------------------------------------------------------------------------
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux 2>/dev/null" EXIT
+
+onos ${1:-$OCI} "onos:summary" > $aux
+cat $aux
+
+let status=0
+grep -q "nodes=${2:-.*}" $aux || let status=status+1
+grep -q "devices=${3:-.*}" $aux || let status=status+1
+grep -q "links=${4:-.*}" $aux || let status=status+1
+grep -q "hosts=${5:-.*}" $aux || let status=status+1
+grep -q "flows=${6:-.*}" $aux || let status=status+1
+grep -q "intents=${7:-.*}" $aux || let status=status+1
+
+exit $status \ No newline at end of file
diff --git a/framework/src/onos/tools/test/bin/onos-check-views b/framework/src/onos/tools/test/bin/onos-check-views
new file mode 100755
index 00000000..421de907
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-check-views
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Checks whether all and only the ONOS apps configured in ONOS_APPS are active.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux 2>/dev/null" EXIT
+
+onos ${1:-$OCI} "onos:ui-views" > $aux
+cat $aux
+
+[ $# -gt 0 ] && shift
+
+grep "${@:-topo}" $aux \ No newline at end of file
diff --git a/framework/src/onos/tools/test/bin/onos-config b/framework/src/onos/tools/test/bin/onos-config
new file mode 100755
index 00000000..5c3ab024
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-config
@@ -0,0 +1,57 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely configures & starts ONOS for the first time.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCI}
+remote=$ONOS_USER@$node
+
+# ONOS boot features
+export ONOS_BOOT_FEATURES="${ONOS_BOOT_FEATURES:-webconsole,onos-api,onos-core,onos-incubator,onos-cli,onos-rest,onos-gui}"
+
+# ONOS builtin apps and providers ignited by default
+export ONOS_APPS="${ONOS_APPS:-drivers,openflow}"
+
+# Generate a cluster.json from the ON* environment variables
+CDEF_FILE=/tmp/${remote}.cluster.json
+echo "{ \"ipPrefix\": \"$ONOS_NIC\"," > $CDEF_FILE
+echo " \"nodes\":[" >> $CDEF_FILE
+for node in $(env | sort | egrep "OC[2-9]+" | cut -d= -f2); do
+ echo " { \"id\": \"$node\", \"ip\": \"$node\", \"tcpPort\": 9876 }," >> $CDEF_FILE
+done
+echo " { \"id\": \"$OC1\", \"ip\": \"$OC1\", \"tcpPort\": 9876 }" >> $CDEF_FILE
+echo "]}" >> $CDEF_FILE
+scp -q $CDEF_FILE $remote:$ONOS_INSTALL_DIR/config/cluster.json
+
+ssh $remote "
+ echo \"onos.ip = \$(sudo ifconfig | grep $ONOS_NIC | cut -d: -f2 | cut -d\\ -f1)\" \
+ >> $ONOS_INSTALL_DIR/$KARAF_DIST/etc/system.properties
+
+ # Drop copycat related log level for the console
+ echo "log4j.logger.net.kuujo.copycat= INFO" \
+ >> $ONOS_INSTALL_DIR/$KARAF_DIST/etc/org.ops4j.pax.logging.cfg
+
+ # Patch the Apache Karaf distribution file to load ONOS boot features
+ perl -pi.old -e \"s|^(featuresBoot=.*,management)(,webconsole,.*)|\1,$ONOS_BOOT_FEATURES|\" \
+ $ONOS_INSTALL_DIR/$KARAF_DIST/etc/org.apache.karaf.features.cfg
+
+ # Customize which builtin apps should be ignited
+ for app in $(echo $ONOS_APPS | tr ',' ' '); do
+ touch $ONOS_INSTALL_DIR/apps/org.onosproject.\$app/active
+ done
+"
+
+# Generate a default tablets.json from the ON* environment variables
+TDEF_FILE=/tmp/${remote}.tablets.json
+onos-gen-partitions $TDEF_FILE
+scp -q $TDEF_FILE $remote:$ONOS_INSTALL_DIR/config/tablets.json
+
+# Copy tools/package/config/ to remote
+scp -qr ${ONOS_ROOT}/tools/package/config/ $remote:$ONOS_INSTALL_DIR/
+
+# Copy the desired initial network configuration to remote if needed
+[ -n "$ONOS_CFG" -a -f "$ONOS_CFG" -a "${1:-$OCI}" = "$OC1" ] && \
+ scp $ONOS_CFG $remote:$ONOS_INSTALL_DIR/config/network-cfg.json
diff --git a/framework/src/onos/tools/test/bin/onos-create-intent b/framework/src/onos/tools/test/bin/onos-create-intent
new file mode 100755
index 00000000..d1c0b93d
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-create-intent
@@ -0,0 +1,22 @@
+#!/bin/bash
+#! usage: onos-create-intent target-onos-instance name point deviceId1 deviceId2
+#! onos-create-intent target-onos-instance name host hostId1 hostId2
+# -----------------------------------------------------------------------------
+# Installs a new intent using the ONOS CLI
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux 2>/dev/null" EXIT
+target=$1
+name=$2
+type=$3
+arg1=$4
+arg2=$5
+
+set -x
+
+onos $target "onos:add-${type}-intent" --key $name "${arg1}" "${arg2}"
+
diff --git a/framework/src/onos/tools/test/bin/onos-die b/framework/src/onos/tools/test/bin/onos-die
new file mode 100755
index 00000000..9da768e8
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-die
@@ -0,0 +1,9 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely kills and stops the ONOS service on the specified node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+onos-kill "${1:-$OCI}" && onos-service "${1:-$OCI}" stop
diff --git a/framework/src/onos/tools/test/bin/onos-fetch-logs b/framework/src/onos/tools/test/bin/onos-fetch-logs
new file mode 100755
index 00000000..a4d7ffee
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-fetch-logs
@@ -0,0 +1,43 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Collect ONOS logs from a single node or the current ONOS cell.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+function print_usage {
+ command_name=`basename $0`
+ echo "Collect ONOS logs from a single node or the current ONOS cell."
+ echo
+ echo "Usage: $command_name <TARGET> "
+ echo " $command_name [-h | --help]"
+ echo "Options:"
+ echo " TARGET The target of the command"
+ echo " [-h | --help] Print this help"
+ echo ""
+ echo "TARGET: <hostname | --cell>"
+ echo " hostname Execute on the specified host name"
+ echo " --cell Execute on the current ONOS cell"
+ echo ""
+}
+
+# Print usage
+if [ "${1}" = "-h" -o "${1}" = "--help" ]; then
+ print_usage
+ exit 0
+fi
+
+# Select the target
+if [ "${1}" = "--cell" ]; then
+ nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
+else
+ nodes=${1:-$OCI}
+fi
+
+# Execute the remote commands
+for node in $nodes; do
+ echo "fetching from ${node}..."
+ mkdir -p ${node}
+ scp -p $ONOS_USER@${node}:$ONOS_INSTALL_DIR/log/karaf.log* ./${node}/
+done
diff --git a/framework/src/onos/tools/test/bin/onos-fetch-vms b/framework/src/onos/tools/test/bin/onos-fetch-vms
new file mode 100755
index 00000000..567f7f5b
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-fetch-vms
@@ -0,0 +1,11 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely fetches the ONOS test VMs from a local share into ~/Downloads.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+mkdir -p /tmp/onos
+mount -t smbfs smb://guest:@10.254.1.15/onos /tmp/onos
+cp /tmp/onos/onos*.ova ~/Downloads
diff --git a/framework/src/onos/tools/test/bin/onos-form-cluster b/framework/src/onos/tools/test/bin/onos-form-cluster
new file mode 100755
index 00000000..daca34cc
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-form-cluster
@@ -0,0 +1,32 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Forms ONOS cluster using REST API.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+# Scan arguments for user/password or other options...
+while getopts u:p: o; do
+ case "$o" in
+ u) user=$OPTARG;;
+ p) password=$OPTARG;;
+ esac
+done
+user=${user:-onos} # user defaults to 'onos'
+password=${password:-$user} # password defaults to user name if not specified
+let OPC=$OPTIND-1
+shift $OPC
+
+node=${1:-$OCI}
+
+if [ $node = "cell" ]; then
+ nodes=${ONOS_INSTANCES}
+ node=${OCI}
+else
+ nodes="$@"
+fi
+
+set -x
+
+ssh $ONOS_USER@$node $ONOS_INSTALL_DIR/bin/onos-form-cluster -u $user -p $password $nodes
diff --git a/framework/src/onos/tools/test/bin/onos-gen-partitions b/framework/src/onos/tools/test/bin/onos-gen-partitions
new file mode 100755
index 00000000..a2558392
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-gen-partitions
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+'''
+ Generate the partitions json file from the $OC* environment variables
+
+ Usage: onos-gen-partitions [output file]
+ If output file is not provided, the json is written to stdout.
+'''
+
+from os import environ
+from collections import deque, OrderedDict
+import re
+import json
+import sys
+
+convert = lambda text: int(text) if text.isdigit() else text.lower()
+alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
+
+def get_OC_vars():
+ vars = []
+ for var in environ:
+ if re.match(r"OC[0-9]+", var):
+ vars.append(var)
+ return sorted(vars, key=alphanum_key)
+
+def get_nodes(vars, port=9876):
+ node = lambda k: { 'id': k, 'ip': k, 'tcpPort': port }
+ return [ node(environ[v]) for v in vars ]
+
+def generate_permutations(nodes, k):
+ l = deque(nodes)
+ perms = {}
+ for i in range(1, len(nodes)+1):
+ perms['p%d' % i] = list(l)[:k]
+ l.rotate(-1)
+ return OrderedDict(sorted(perms.iteritems(), key=lambda (k, v): alphanum_key(k)))
+
+if __name__ == '__main__':
+ vars = get_OC_vars()
+ nodes = get_nodes(vars)
+ partitions = generate_permutations(nodes, 3)
+ data = {
+ 'nodes': nodes,
+ 'partitions': partitions
+ }
+ output = json.dumps(data, indent=4)
+
+ if len(sys.argv) == 2:
+ filename = sys.argv[1]
+ with open(filename, 'w') as f:
+ f.write(output)
+ else:
+ print output
diff --git a/framework/src/onos/tools/test/bin/onos-group b/framework/src/onos/tools/test/bin/onos-group
new file mode 100755
index 00000000..150f9470
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-group
@@ -0,0 +1,90 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Allows a select group of commands to be sent to all ONOS instances in a cell.
+# -----------------------------------------------------------------------------
+
+set -o pipefail
+IFS=$'\n'
+
+source ogroup-opts
+
+function err() {
+ printf '%s: %s: %s\n' "$(basename $0)" "$1" "$2" >&2
+ usage >&2
+ exit 1
+}
+
+function usage() {
+cat << EOF
+
+usage: $(basename $0) <help|[command]>
+
+Sends a command to all ONOS instances in the current cell. Currently supported
+commands are: $GOPTS
+
+options:
+ [command] : A command to send to the instances.
+ help : Displays this message and exits.
+
+notes:
+ Hitting <TAB> will display the options for $(basename $0).
+
+EOF
+}
+
+# gets the utility name
+function getcmd() {
+ # check that utility can be run in "batch-mode"
+ local isgopt=false
+ for c in $(printf '%s' "$GOPTS" | tr ' ' $'\n'); do
+ [ "$c" = "$1" ] && isgopt=true && break
+ done
+ if $isgopt ; then
+ printf 'onos-%s' "$1"
+ else
+ err 'unsupported command' "$1"
+ fi
+}
+
+# early sanity check for instances/arguments
+[ -z "$1" ] && usage && exit 0
+
+OCIS=( $(env | sed -ne 's:OC[0-9]\{1,\}=\(.*\):\1 :g p' | sort -k1) )
+if [ -z "$OCIS" ]; then
+ printf "no controller instances, quitting early" >&2 && exit 0
+fi
+
+CMD_HELP=false
+while [ $# -gt 0 ]; do
+ case "$1" in
+ 'help')
+ usage && exit 0
+ ;;
+ '-'?)
+ err 'invalid flag' "$1" && exit 1
+ ;;
+ *)
+ cmd=$(getcmd $1) || exit 1
+ shift
+ # grab flags aimed at the utility being called.
+ argv=( $@ )
+ args=()
+ for i in "${!argv[@]}"; do
+ # 'help' is a parameter for us; '-h' is for the command
+ [ "${argv[$i]}" = 'help' ] && break
+ [ "${argv[$i]}" = '-h' ] && CMD_HELP=true
+ args[$i]="${argv[$i]}"
+ shift
+ done
+ continue
+ ;;
+ esac
+ shift
+done
+
+( $CMD_HELP ) && $cmd '-h' && exit 0
+
+# TODO: verbose-mode and cleanup
+for i in ${OCIS[@]}; do
+ ${cmd} $(echo ${args[@]}) "$i" 2>/dev/null &
+done
diff --git a/framework/src/onos/tools/test/bin/onos-gui b/framework/src/onos/tools/test/bin/onos-gui
new file mode 100755
index 00000000..517ed11b
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-gui
@@ -0,0 +1,9 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Launches ONOS GUI on the specified node.
+# -----------------------------------------------------------------------------
+
+host=${1:-$OCI}
+host=${host:-localhost}
+
+open http://$host:8181/onos/ui
diff --git a/framework/src/onos/tools/test/bin/onos-install b/framework/src/onos/tools/test/bin/onos-install
new file mode 100755
index 00000000..0f4cc9dd
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-install
@@ -0,0 +1,67 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely pushes bits to a remote node and installs ONOS on it.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+while getopts fnm: o; do
+ case "$o" in
+ f) uninstall=true;;
+ n) nostart=true;;
+ m) mvn_settings=$OPTARG;;
+ esac
+done
+let OPC=$OPTIND-1
+shift $OPC
+
+# If the -f was given, attempt uninstall first.
+[ -n "$uninstall" ] && onos-uninstall ${1:-$OCI}
+
+node=${1:-$OCI}
+remote=$ONOS_USER@$node
+
+$(dirname $0)/onos-push-bits $node
+
+[ ! -z "$mvn_settings" ] && scp -q $mvn_settings $remote:/tmp/settings.xml
+
+ssh $remote "
+ [ -d $ONOS_INSTALL_DIR/bin ] && echo \"ONOS is already installed\" && exit 1
+
+ # Prepare a landing zone and unroll the bits
+ sudo mkdir -p $ONOS_INSTALL_DIR && sudo chown ${ONOS_USER}:${ONOS_GROUP} $ONOS_INSTALL_DIR
+ tar zxmf /tmp/$ONOS_BITS.tar.gz -C $ONOS_INSTALL_DIR --strip-components=1
+
+ # Make a link to the log file directory and make a home for auxiliaries
+ ln -s $ONOS_INSTALL_DIR/$KARAF_DIST/data/log /opt/onos/log
+ mkdir $ONOS_INSTALL_DIR/var
+ mkdir $ONOS_INSTALL_DIR/config
+
+ # create dir for Raft log
+ # TODO: use $KARAF_DATA
+ mkdir -p -- $ONOS_INSTALL_DIR/$KARAF_DIST/data/raft
+
+ # Install the upstart configuration file and setup options for debugging
+ [ -z "$nostart" ] && sudo cp $ONOS_INSTALL_DIR/debian/onos.conf /etc/init/onos.conf
+ echo 'export ONOS_OPTS=debug' > $ONOS_INSTALL_DIR/options
+
+ # Setup correct user to run onos-service
+ echo 'export ONOS_USER="${ONOS_USER:-sdn}"' >> $ONOS_INSTALL_DIR/options
+
+ # Remove any previous ON.Lab bits from ~/.m2 repo.
+ rm -fr ~/.m2/repository/org/onosproject
+
+ [ ! -z "$mvn_settings" ] && cp /tmp/settings.xml ~/.m2/settings.xml
+
+ # Drop log level for the console
+ echo "log4j.logger.org.apache.sshd = WARN" \
+ >> $ONOS_INSTALL_DIR/$KARAF_DIST/etc/org.ops4j.pax.logging.cfg
+
+"
+
+# Configure the ONOS installation
+onos-config $node
+
+# Unless -n option was given, attempt to ignite the ONOS service.
+[ -z "$nostart" ] && onos-service $node start
diff --git a/framework/src/onos/tools/test/bin/onos-intentperf-scrape b/framework/src/onos/tools/test/bin/onos-intentperf-scrape
new file mode 100755
index 00000000..8d698b1a
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-intentperf-scrape
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Scrapes intent performance numbers from the remote ONOS log file.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
+
+for node in $nodes; do
+ echo "fetching from ${node}..."
+ ssh $ONOS_USER@${node} "
+ grep 'Throughput: OVERALL=' $ONOS_INSTALL_DIR/log/karaf.log \
+ | sed 's/ | INFO .*\: OVERALL=/|/;s/\; INSTALL_REQ=.*//;s/\; CURRENT=/|/' | cut -c12-
+ " > ${node}.perf.log
+done
diff --git a/framework/src/onos/tools/test/bin/onos-iterm-cli b/framework/src/onos/tools/test/bin/onos-iterm-cli
new file mode 100755
index 00000000..85cee831
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-iterm-cli
@@ -0,0 +1,42 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# Test utility to spawn an iTerm window for testing against current cell.
+#-------------------------------------------------------------------------------
+
+cellName=$ONOS_CELL
+nodeCount=$(env | egrep "OC[0-9]+" | wc -l | tr -d ' ')
+
+osascript -e "
+tell application \"iTerm\"
+
+ set cellName to \"$cellName\"
+ set paneCount to $nodeCount
+
+ set theTerm to (make new terminal)
+
+ tell theTerm
+ set number of columns to 292
+ set number of rows to 24
+ launch session \"Default\"
+ tell the current session
+ set name to \"ONOS Shell 1\"
+ write text \"cell \" & cellName
+ write text \"oi 1 && clear && echo Node \$OCI\"
+ end tell
+ end tell
+
+ tell theTerm
+ repeat with thePane from 2 to paneCount
+ tell the current session
+ tell application \"System Events\" to keystroke \"d\" using command down
+ set name to \"ONOS Shell \" & thePane
+ write text \"cell \" & cellName
+ write text \"oi \" & thePane & \" && clear && echo Node \$OCI\"
+ end tell
+ end repeat
+ end tell
+
+ tell application \"System Events\" to keystroke \"I\" using command down
+
+end tell
+"
diff --git a/framework/src/onos/tools/test/bin/onos-iterm-logs b/framework/src/onos/tools/test/bin/onos-iterm-logs
new file mode 100755
index 00000000..b160c6e0
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-iterm-logs
@@ -0,0 +1,42 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# Test utility to spawn an iTerm window for monitoring logs of current cell.
+#-------------------------------------------------------------------------------
+
+cellName=$ONOS_CELL
+nodeCount=$(env | egrep "OC[0-9]+" | wc -l | tr -d ' ')
+
+osascript -e "
+tell application \"iTerm\"
+
+ set cellName to \"$cellName\"
+ set paneCount to $nodeCount
+
+ set theTerm to (make new terminal)
+
+ tell theTerm
+ set number of columns to 292
+ set number of rows to 64
+ launch session \"Default\"
+ tell the current session
+ set name to \"ONOS Log 1\"
+ write text \"cell \" & cellName
+ write text \"oi 1 && clear && echo Node \$OCI && ol\"
+ end tell
+ end tell
+
+ tell theTerm
+ repeat with thePane from 2 to paneCount
+ tell the current session
+ tell application \"System Events\" to keystroke \"D\" using command down
+ set name to \"ONOS Log \" & thePane
+ write text \"cell \" & cellName
+ write text \"oi \" & thePane & \" && clear && echo Node \$OCI && ol\"
+ end tell
+ end repeat
+ end tell
+
+ tell application \"System Events\" to keystroke \"I\" using command down
+
+end tell
+"
diff --git a/framework/src/onos/tools/test/bin/onos-jpenable b/framework/src/onos/tools/test/bin/onos-jpenable
new file mode 100755
index 00000000..ba3492ae
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-jpenable
@@ -0,0 +1,19 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely instruments the ONOS JVM for profiling with jprofiler.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+export JPROFILER_ROOT=${JPROFILER_ROOT:-/opt/jprofiler8}
+
+ssh $ONOS_USER@${1:-$OCI} "
+ pid=\$(ps -ef | grep karaf.jar | grep -v grep | cut -c10-15 | tr -d ' ')
+ if [ -n \"\$pid\" ]; then
+ echo \"Enabling profiling for ONOS process \$pid on \$(hostname)...\"
+ $JPROFILER_ROOT/bin/jpenable --gui --pid=\$pid --port=8849
+ else
+ echo \"ONOS process is not running...\"
+ exit 1
+ fi
+"
diff --git a/framework/src/onos/tools/test/bin/onos-kill b/framework/src/onos/tools/test/bin/onos-kill
new file mode 100755
index 00000000..47e5360b
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-kill
@@ -0,0 +1,18 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely kills the ONOS service on the specified node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+ssh $ONOS_USER@${1:-$OCI} "
+ pid=\$(ps -ef | grep karaf.jar | grep -v grep | cut -c10-15 | tr -d ' ')
+ if [ -n \"\$pid\" ]; then
+ echo \"Killing ONOS process \$pid on \$(hostname)...\"
+ kill -9 \$pid
+ else
+ echo \"ONOS process is not running...\"
+ exit 1
+ fi
+"
diff --git a/framework/src/onos/tools/test/bin/onos-list-cells b/framework/src/onos/tools/test/bin/onos-list-cells
new file mode 100755
index 00000000..39a70ee9
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-list-cells
@@ -0,0 +1,18 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# List available ONOS cells configuration.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+# Lists available cells
+for cell in $(ls -1 $ONOS_ROOT/tools/test/cells); do
+ if [ ${cell} = "${ONOS_CELL}" ]; then
+ cell_id="${cell} *"
+ else
+ cell_id="${cell}"
+ fi
+ cell_descr="$(grep '^#' $ONOS_ROOT/tools/test/cells/$cell | head -n 1)"
+ printf "%-12s %s\n" "${cell_id}" "${cell_descr}"
+done
diff --git a/framework/src/onos/tools/test/bin/onos-local b/framework/src/onos/tools/test/bin/onos-local
new file mode 100755
index 00000000..acf090c8
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-local
@@ -0,0 +1,7 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# ONOS local karaf server start.
+# -----------------------------------------------------------------------------
+
+unset KARAF_HOME
+karaf "$@" \ No newline at end of file
diff --git a/framework/src/onos/tools/test/bin/onos-log b/framework/src/onos/tools/test/bin/onos-log
new file mode 100755
index 00000000..fe89f6dd
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-log
@@ -0,0 +1,38 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Monitors remote ONOS log file on the specified node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
+
+less=0
+[ "$1" = "-l" ] && shift && less=1
+
+remote=$(find_node $1)
+
+remote=$ONOS_USER@${remote:-$OCI}
+instance=$2
+
+pattern=$3
+
+[ -n "$instance" -a "$instance" != "-" ] && \
+ LOG=$ONOS_INSTALL_DIR/$KARAF_DIST/instances/$instance/data/log/karaf.log || \
+ LOG=$ONOS_INSTALL_DIR/log/karaf.log
+
+
+if [ $less -eq 1 ]; then
+ ssh -t $remote "less $LOG"
+elif [ -n "$pattern" ]; then
+ ssh $remote "grep $LOG -Ee \"$pattern\""
+else
+ ssh -t $remote "
+ while true; do
+ echo ==================================================================
+ [ ! -f $LOG ] && sleep 2 && continue
+ [ \$(uname) = "Darwin" ] && tail -n 512 -f -F $LOG ||
+ tail -n 512 --follow=name $LOG --pid \$$ --sleep-interval 2
+ done
+ "
+fi
diff --git a/framework/src/onos/tools/test/bin/onos-log-kill b/framework/src/onos/tools/test/bin/onos-log-kill
new file mode 100755
index 00000000..c18d9231
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-log-kill
@@ -0,0 +1,16 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Kills all remote ONOS log file monitors on the specified node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
+
+less=0
+[ "$1" = "-l" ] && shift && less=1
+
+remote=$(find_node $1)
+remote=$ONOS_USER@${remote:-$OCI}
+
+ssh $remote "ps -ef | grep \"tail -n 512\" | grep -v grep | cut -c10-15 | xargs kill"
diff --git a/framework/src/onos/tools/test/bin/onos-log-write b/framework/src/onos/tools/test/bin/onos-log-write
new file mode 100755
index 00000000..840c43f5
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-log-write
@@ -0,0 +1,37 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Writes block text into the remote ONOS log file on the specified node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
+
+remote=$(find_node $1)
+remote=$ONOS_USER@${remote:-$OCI}
+message=$2
+
+if [ -z "$message" ]; then
+ echo "Usage: onos-log-write <instance> <message>"
+ exit
+fi
+if [ -z $(which figlet) ]; then
+ echo "Install figlet; example: brew install figlet"
+ exit
+fi
+
+#text=$(figlet $message)
+#echo "Writing to $remote:"
+#echo $text
+#echo
+
+[ -n "$instance" ] && \
+ LOG=$ONOS_INSTALL_DIR/$KARAF_DIST/instances/$instance/data/log/karaf.log || \
+ LOG=$ONOS_INSTALL_DIR/log/karaf.log
+
+#broken by special chars like `
+#ssh -t $remote "sudo mkdir -p $(dirname $LOG) && echo $text | sudo tee -a $LOG"
+
+figlet $message > /tmp/message.txt
+scp /tmp/message.txt $remote:/tmp
+ssh -t $remote "sudo mkdir -p $(dirname $LOG) && cat /tmp/message.txt | sudo tee -a $LOG; rm /tmp/message.txt"
diff --git a/framework/src/onos/tools/test/bin/onos-mininet b/framework/src/onos/tools/test/bin/onos-mininet
new file mode 100755
index 00000000..ef2c8ea5
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-mininet
@@ -0,0 +1,69 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Starts or interacts with mininet in a remote screen session.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+export MAX_WAIT=60
+
+cmd="$1" && shift
+log="screenlog.0"
+remote="$ONOS_USER@$OCN"
+mininet="ssh -t -t $remote screen -L -S mininet"
+
+case $cmd in
+send)
+ $mininet -X "stuff \"$@\\n\"" 2>/dev/null
+ ;;
+
+sendAndExpect)
+ cmd=""
+ for a in $*; do shift; if [ "$a" = "--expect" ]; then break; fi; cmd="$cmd $a"; done
+ $mininet -X "stuff \"$cmd\\n\"" 2>/dev/null
+ onos-mininet expect "$@"
+ ;;
+
+wait)
+ ssh $remote "
+ let count=0
+ sleep 1 && while test ! -f $log; do if test \$count -ge $MAX_WAIT; then exit 1; fi; sleep 1; let count=count+1; done
+ while ! (tail -n1 $log | egrep -q '^mininet>'); do if [ \$count -ge $MAX_WAIT ]; then exit 1; fi; sleep 1; done
+ sleep ${1-:1}
+ "
+ ;;
+
+expect)
+ aux=/tmp/mininet.$$.log
+ ssh $remote "
+ sleep 1
+ if [ ! -f $log ]; then exit 1; fi;
+ let count=0
+ while ! (tail -n1 $log | egrep -q '^mininet>'); do if test \$count -ge $MAX_WAIT; then exit 1; fi; sleep 1; let count=count+1; done
+ tac $log | awk '{ print \$0; } /^mininet>/ { if (on) { exit 0; } on=1; }' | tac > $aux
+ cat $aux
+ set -x
+ egrep \"$@\" $aux
+ "
+ ;;
+
+attach)
+ $mininet -x
+ ;;
+
+start)
+ ssh $remote "rm -f $log; echo logfile flush 1 > ~/.screenrc"
+ (
+ $mininet "$@"
+ scp $remote:$log /tmp/mininet.log
+ ssh $remote rm -f $log
+ ) &
+ ;;
+
+stop)
+ $mininet -X "stuff \"^C\\n\"" 2>/dev/null && \
+ $mininet -X "stuff \"^C\\n\"" 2>/dev/null && \
+ $mininet -X "stuff \"exit\\n\"" 2>/dev/null
+ ;;
+esac
diff --git a/framework/src/onos/tools/test/bin/onos-oecfg b/framework/src/onos/tools/test/bin/onos-oecfg
new file mode 100755
index 00000000..e709ce31
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-oecfg
@@ -0,0 +1,12 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# ONOS OE-Linc config generator.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+APP=onos-app-oecfg
+JAR=$M2_REPO/org/onosproject/$APP/$ONOS_POM_VERSION/$APP-$ONOS_POM_VERSION.jar
+
+java -jar $JAR < $1 | python -mjson.tool
diff --git a/framework/src/onos/tools/test/bin/onos-patch-vm b/framework/src/onos/tools/test/bin/onos-patch-vm
new file mode 100755
index 00000000..39f1c603
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-patch-vm
@@ -0,0 +1,22 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely patches the ONOS VM to tailor its hostname.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+address=${1:-$OCI}
+remote=$ONOS_USER@$address
+name=${2:-onos-1}
+
+[ -z "$address" ] && echo "Null address not allowed" >&2 && exit 1
+[ -z "$name" ] && echo "Null name not allowed" >&2 && exit 1
+
+ssh $remote "
+ sudo perl -pi.bak -e \"s/127.0.1.1.*/127.0.1.1 $name/g\" /etc/hosts
+ sudo bash -c \"echo $name >/etc/hostname\"
+ sudo hostname $name
+" 2>/dev/null
+
+echo "$address: $(ssh $remote hostname)"
diff --git a/framework/src/onos/tools/test/bin/onos-push-bits b/framework/src/onos/tools/test/bin/onos-push-bits
new file mode 100755
index 00000000..8c9276fc
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-push-bits
@@ -0,0 +1,19 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely pushes bits to a remote node in preparation for install.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCI}
+remote=$ONOS_USER@$node
+
+locHash=$(cksum $ONOS_TAR | cut -d' ' -f1,2)
+remHash=$(ssh $remote cksum $ONOS_TAR 2>/dev/null | cut -d' ' -f1,2)
+
+if [ "$locHash" = "$remHash" ]; then
+ echo "ONOS bits $ONOS_TAR already up-to-date on $node..."
+else
+ scp -q $ONOS_TAR $remote:/tmp
+fi
diff --git a/framework/src/onos/tools/test/bin/onos-push-bits-through-proxy b/framework/src/onos/tools/test/bin/onos-push-bits-through-proxy
new file mode 100755
index 00000000..1ec7107c
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-push-bits-through-proxy
@@ -0,0 +1,22 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely pushes bits to all remote nodes in preparation for install.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+OCT=${OCT:-$OCI}
+node=${1:-$OCT}
+remote=$ONOS_USER@$node
+shift
+
+echo "Pushing to proxy $node..."
+onos-push-bits $node
+
+others=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2 | grep -v $OCT)
+
+for other in $others; do
+ echo "Pushing to $other..."
+ ssh $remote "scp $ONOS_TAR $ONOS_USER@$other:$ONOS_TAR"
+done
diff --git a/framework/src/onos/tools/test/bin/onos-push-keys b/framework/src/onos/tools/test/bin/onos-push-keys
new file mode 100755
index 00000000..94da6998
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-push-keys
@@ -0,0 +1,19 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Pushes the local id_rsa.pub to the authorized_keys on a remote ONOS node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+remote=$ONOS_USER@${1:-$OCI}
+
+cat ~/.ssh/id_rsa.pub | ssh $remote "
+ mkdir -p ~/.ssh
+ chmod 700 ~/.ssh
+ cat >> ~/.ssh/authorized_keys
+ sort -u ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.bak
+ mv ~/.ssh/authorized_keys.bak ~/.ssh/authorized_keys
+ chmod 600 ~/.ssh/authorized_keys
+"
+ssh -n -o PasswordAuthentication=no $remote true
diff --git a/framework/src/onos/tools/test/bin/onos-push-test-bits b/framework/src/onos/tools/test/bin/onos-push-test-bits
new file mode 100755
index 00000000..927d157f
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-push-test-bits
@@ -0,0 +1,16 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely pushes test bits to a remote test machine and unrolls them in /tmp
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCI}
+remote=$ONOS_USER@$node
+
+scp -q $ONOS_TEST_TAR $remote:/tmp
+ssh $remote "
+ rm -f /tmp/onos $ONOS_TEST_BITS
+ cd /tmp && tar zxf $ONOS_TEST_BITS.tar.gz && ln -s $ONOS_TEST_BITS onos
+"
diff --git a/framework/src/onos/tools/test/bin/onos-push-topos b/framework/src/onos/tools/test/bin/onos-push-topos
new file mode 100755
index 00000000..a09d7440
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-push-topos
@@ -0,0 +1,11 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely pushes test topologies a remote mininet test machine.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCN}
+
+scp -qr $ONOS_ROOT/tools/test/topos $ONOS_USER@$node:
diff --git a/framework/src/onos/tools/test/bin/onos-push-update-bundle b/framework/src/onos/tools/test/bin/onos-push-update-bundle
new file mode 100755
index 00000000..85fa27bc
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-push-update-bundle
@@ -0,0 +1,27 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Pushes the specified bundle to the remote ONOS cell machines and updates it.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+cd ~/.m2/repository
+jar=$(find org/onosproject -type f -name '*.jar' | grep -e $1 | grep -v -e -tests | head -n 1)
+
+[ -z "$jar" ] && echo "No bundle $1 found for" && exit 1
+
+bundle=$(echo $(basename $jar .jar) | sed 's/-[0-9].*//g')
+
+echo "pushing bundle: $bundle"
+
+nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
+for node in $nodes; do
+ scp -q $jar $ONOS_USER@$node:.m2/repository/$jar
+ scp -q $jar $ONOS_USER@$node:$ONOS_INSTALL_DIR/$KARAF_DIST/system/$jar
+ ssh $ONOS_USER@$node "
+ $ONOS_INSTALL_DIR/bin/onos \"bundle:stop -f $bundle\"
+ $ONOS_INSTALL_DIR/bin/onos \"bundle:update -f $bundle\"
+ $ONOS_INSTALL_DIR/bin/onos \"bundle:start -f $bundle\"
+ " 2>/dev/null
+done
diff --git a/framework/src/onos/tools/test/bin/onos-remove-raft-logs b/framework/src/onos/tools/test/bin/onos-remove-raft-logs
new file mode 100755
index 00000000..1f1e5c68
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-remove-raft-logs
@@ -0,0 +1,14 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Removes Raft logs on all instances
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
+
+onos-service --cell stop
+
+# TODO: use $KARAF_DATA
+for node in $nodes; do onos-ssh $node "rm -v -- $ONOS_INSTALL_DIR/$KARAF_DIST/data/raft/onos-copy-cat-log_*"; done
diff --git a/framework/src/onos/tools/test/bin/onos-rsdocs b/framework/src/onos/tools/test/bin/onos-rsdocs
new file mode 100755
index 00000000..bc0127cf
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-rsdocs
@@ -0,0 +1,9 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Launches ONOS REST API docs GUI on the specified node.
+# -----------------------------------------------------------------------------
+
+host=${1:-$OCI}
+host=${host:-localhost}
+
+open http://$host:8181/onos/v1/docs
diff --git a/framework/src/onos/tools/test/bin/onos-secure-ssh b/framework/src/onos/tools/test/bin/onos-secure-ssh
new file mode 100755
index 00000000..3c15fa3c
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-secure-ssh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Secures the ONOS console for all instances in the cell ONOS cluster.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
+
+for node in $nodes; do
+ # Setup passwordless login for the remote user on the local bench host
+ onos-user-key $node
+
+ # Prune the node entry from the known hosts file since server key changes
+ ssh-keygen -f "$HOME/.ssh/known_hosts" -R [$node]:8101
+
+ # Setup passwordless login for the local user on the remote node
+ ssh $ONOS_USER@$node "
+ [ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q
+ $ONOS_INSTALL_DIR/bin/onos-user-key \$(id -un) \$(cut -d\\ -f2 ~/.ssh/id_rsa.pub)
+ $ONOS_INSTALL_DIR/bin/onos-secure-ssh "$@"
+
+ # Implicitly accept the new server key in dev/test environments
+ while ! ssh -p 8101 -o StrictHostKeyChecking=no localhost list 2>/dev/null; do
+ echo Waiting for connection...
+ sleep 1
+ done
+ "
+done
+
diff --git a/framework/src/onos/tools/test/bin/onos-service b/framework/src/onos/tools/test/bin/onos-service
new file mode 100755
index 00000000..cc694911
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-service
@@ -0,0 +1,55 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely administers the ONOS service on the specified node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
+
+function print_usage {
+ command_name=`basename $0`
+ echo "Remotely administer the ONOS service on a single node or the current ONOS cell."
+ echo
+ echo "Usage: $command_name <TARGET> [COMMAND]"
+ echo " $command_name [-h | --help]"
+ echo "Options:"
+ echo " TARGET The target of the command"
+ echo " COMMAND The command to execute. Default value is 'status'"
+ echo " [-h | --help] Print this help"
+ echo ""
+ echo "TARGET: <hostname | --cell>"
+ echo " hostname Execute on the specified host name"
+ echo " --cell Execute on the current ONOS cell"
+ echo ""
+ echo "COMMAND: [start|stop|restart|status]"
+ echo ""
+}
+
+# Print usage
+if [ "${1}" = "-h" -o "${1}" = "--help" ]; then
+ print_usage
+ exit 0
+fi
+
+case $2 in
+ start|stop|restart|status)
+
+ # Select the target
+ if [ "${1}" = "--cell" ]; then
+ nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
+ else
+ nodes=$(find_node ${1:-$OCI})
+ fi
+
+ # Execute the remote commands
+ for node in $nodes; do
+ ssh $ONOS_USER@${node} "sudo ${2:-status} onos"
+ done
+ ;;
+ *)
+ echo "error: $2 is not a valid command"
+ echo ""
+ print_usage
+ ;;
+esac
diff --git a/framework/src/onos/tools/test/bin/onos-set-controllers b/framework/src/onos/tools/test/bin/onos-set-controllers
new file mode 100755
index 00000000..5b3cd6f7
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-set-controllers
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Sets controllers on all OVS bridges on the mininet machine.
+# -----------------------------------------------------------------------------
+
+controllers=""
+
+for node in $ONOS_INSTANCES; do
+ controllers="$controllers tcp:$node:${OF_PORT:-6633}"
+done
+
+ssh ${ONOS_USER:-sdn}@$OCN "
+ sudo ovs-vsctl list-br | while read br; do
+ echo \$br: $controllers
+ sudo ovs-vsctl set-controller \$br $controllers
+ done
+"
diff --git a/framework/src/onos/tools/test/bin/onos-show-cell b/framework/src/onos/tools/test/bin/onos-show-cell
new file mode 100755
index 00000000..f5c75726
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-show-cell
@@ -0,0 +1,57 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Print the configuration of an ONOS cell.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+function print_usage {
+ echo "Print the configuration of an ONOS cell."
+ echo "If no arguments are specified, it will print the configuration for the default"
+ echo "ONOS cell as specified in the 'ONOS_CELL' environmental variable."
+ echo
+ echo "Optional arguments:"
+ echo " [cell-name] Print the configuration of 'cell-name'"
+ echo " [-h | --help] Print this help"
+}
+
+if [ "${1}" = "-h" -o "${1}" = "--help" ]; then
+ print_usage
+ exit 0
+fi
+
+if [ -n "${1}" ]; then
+ cell="${1}"
+else
+ if [ -z "${ONOS_CELL}" ]; then
+ echo "Environmental variable 'ONOS_CELL' is not defined"
+ exit 1
+ else
+ cell="${ONOS_CELL}"
+ fi
+fi
+
+if [ ! -f $ONOS_ROOT/tools/test/cells/${cell} ]; then
+ echo "No such cell: ${cell}"
+ exit 1
+fi
+
+# Load the cell setup
+. $ONOS_ROOT/tools/test/cells/${cell}
+
+echo "ONOS_CELL=${ONOS_CELL}"
+echo "ONOS_NIC=${ONOS_NIC}"
+# get number of OC variables
+max=$( env | egrep 'OC[0-9]+' | wc -l )
+for n in $( seq 0 ${max} ); do
+ ocn="OC${n}"
+ if [ -n "${!ocn}" ]; then
+ echo "$ocn=${!ocn}"
+ fi
+done
+echo "OCN=${OCN}"
+echo "OCT=${OCT}"
+echo "OCI=${OCI}"
+echo "ONOS_APPS=${ONOS_APPS}"
+echo "ONOS_BOOT_FEATURES=${ONOS_BOOT_FEATURES}"
diff --git a/framework/src/onos/tools/test/bin/onos-ssh b/framework/src/onos/tools/test/bin/onos-ssh
new file mode 100755
index 00000000..eb6b88e9
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-ssh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Logs in to the remote ONOS node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
+
+[ -n "$1" ] && OCI=$(find_node $1) && shift
+ssh -Y $ONOS_USER@$OCI "$@"
diff --git a/framework/src/onos/tools/test/bin/onos-stage-apps b/framework/src/onos/tools/test/bin/onos-stage-apps
new file mode 100755
index 00000000..4c2c230e
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-stage-apps
@@ -0,0 +1,29 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Stages builtin ONOS apps into the specified directory for packaging.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+export APPS=${1:-/tmp/apps}
+export KARAF_M2=${2:-/tmp/karaf/system}
+export AUX=$APPS/aux
+
+# Bail on any errors
+set -e
+
+mkdir -p $APPS $KARAF_M2
+rm -fr $AUX
+
+find $M2_REPO/org/onosproject/ -name "*.oar" -path "*/${ONOS_POM_VERSION}/*" | while read line; do
+ mkdir -p $AUX && cd $AUX
+ cp $line $AUX
+ jar -xf $AUX/*.oar
+ name=$(grep "name=" $AUX/app.xml | sed 's/<app name="//g;s/".*//g')
+ mkdir -p $APPS/$name
+ cp $AUX/app.xml $APPS/$name/app.xml
+ cp $AUX/*.oar $APPS/$name/$name.oar
+ cp -rf $AUX/m2/* $KARAF_M2
+ rm -fr $AUX
+done
diff --git a/framework/src/onos/tools/test/bin/onos-start-network b/framework/src/onos/tools/test/bin/onos-start-network
new file mode 100755
index 00000000..1e162fb4
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-start-network
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Verifies connectivity to each node in ONOS cell.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+SSHCMD="ssh -o PasswordAuthentication=no"
+SCPCMD="scp -q -o PasswordAuthentication=no"
+
+echo "Copying topology files to mininet vm."
+$SSHCMD -n $ONOS_USER@$OCN mkdir -p topos
+$SCPCMD $ONOS_ROOT/tools/test/topos/* $ONOS_USER@$OCN:topos/
+
+echo "Starting Network."
+$SSHCMD -t $ONOS_USER@$OCN sudo python topos/sol.py $(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
diff --git a/framework/src/onos/tools/test/bin/onos-topo-cfg b/framework/src/onos/tools/test/bin/onos-topo-cfg
new file mode 100755
index 00000000..5f40d8e7
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-topo-cfg
@@ -0,0 +1,14 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# ONOS topology configuration uploader.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node="${1:-$OCI}"
+file="${2:-$ONOS_ROOT/tools/test/topos/oe-linear-3.json}"
+
+curl -sS --fail -L --user $ONOS_WEB_USER:$ONOS_WEB_PASS \
+ -X POST -H 'Content-Type:application/json' \
+ http://$node:8181/onos/v1/config/topology -d@$file
diff --git a/framework/src/onos/tools/test/bin/onos-topo-cfg-all b/framework/src/onos/tools/test/bin/onos-topo-cfg-all
new file mode 100755
index 00000000..adf84c14
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-topo-cfg-all
@@ -0,0 +1,15 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# ONOS topology configuration uploader.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
+
+for node in $nodes; do
+ printf "$node..."
+ onos-topo-cfg $node $1
+done
+printf "\n"
diff --git a/framework/src/onos/tools/test/bin/onos-uninstall b/framework/src/onos/tools/test/bin/onos-uninstall
new file mode 100755
index 00000000..c04db7ac
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-uninstall
@@ -0,0 +1,14 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Remotely stops & uninstalls ONOS on the specified node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+remote=$ONOS_USER@${1:-$OCI}
+
+ssh $remote "
+ sudo stop onos 1>/dev/null 2>/dev/null
+ sudo rm -fr $ONOS_INSTALL_DIR
+"
diff --git a/framework/src/onos/tools/test/bin/onos-untar-and-run b/framework/src/onos/tools/test/bin/onos-untar-and-run
new file mode 100755
index 00000000..f6e8f9b2
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-untar-and-run
@@ -0,0 +1,24 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Untars ONOS tar.gz on the remote machine and runs ONOS.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCI}
+remote=$ONOS_USER@$node
+
+ssh $remote "
+ [ -d $ONOS_INSTALL_DIR/bin ] && echo \"ONOS is already installed\" && exit 1
+ cd /tmp && rm -fr /tmp/$ONOS_BITS
+ tar zxf /tmp/$ONOS_BITS.tar.gz
+
+ cd /tmp/$ONOS_BITS
+ export ONOS_NIC=$ONOS_NIC
+ bin/onos-service server 1>/tmp/onos.out 2>/tmp/onos.err &
+
+ # Setup a few symlinks to allow other tools to work
+ sudo ln -s /tmp/$ONOS_BITS $ONOS_INSTALL_DIR
+ sudo ln -s /tmp/$ONOS_BITS/$KARAF_DIST/data/log $ONOS_INSTALL_DIR/log
+"
diff --git a/framework/src/onos/tools/test/bin/onos-upload-sprites b/framework/src/onos/tools/test/bin/onos-upload-sprites
new file mode 100755
index 00000000..982d7132
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-upload-sprites
@@ -0,0 +1,18 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Tool to upload GUI sprites definitions using GUI REST API.
+# -----------------------------------------------------------------------------
+
+node=${1}
+sprites=${2}
+
+if [ -z "$node" -o -z "$sprites" ]
+then
+ echo "Usage: onos-upload-sprites <server-ip> <sprites-defn.json>"
+ exit 1
+fi
+
+export URL=http://$node:8181/onos/ui/rs/topology/sprites
+export HDR="-HContent-Type:application/json"
+
+curl --fail -sS -X POST $HDR $URL --data @$sprites
diff --git a/framework/src/onos/tools/test/bin/onos-user-key b/framework/src/onos/tools/test/bin/onos-user-key
new file mode 100755
index 00000000..b324c1a8
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-user-key
@@ -0,0 +1,13 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Adds or removes a user key for managing passwordless loging to ONOS console.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCI}
+user=${2:-$(id -un)}
+key=${3:-$(cut -d\ -f2 ~/.ssh/id_rsa.pub)}
+
+ssh $ONOS_USER@$node $ONOS_INSTALL_DIR/bin/onos-user-key $user $key
diff --git a/framework/src/onos/tools/test/bin/onos-verify-cell b/framework/src/onos/tools/test/bin/onos-verify-cell
new file mode 100755
index 00000000..4b3a0ee7
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-verify-cell
@@ -0,0 +1,11 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Verifies connectivity to each node in ONOS cell.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+for node in $(env | sort | egrep "OC[0-9N]+" | cut -d= -f2); do
+ printf "%s: " $node; ssh -n -o PasswordAuthentication=no $ONOS_USER@$node date
+done
diff --git a/framework/src/onos/tools/test/bin/onos-wait-for-start b/framework/src/onos/tools/test/bin/onos-wait-for-start
new file mode 100755
index 00000000..e643b5a6
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-wait-for-start
@@ -0,0 +1,28 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Waits for ONOS to reach run-level 100 on the specified remote node.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
+
+node=$(find_node ${1:-$OCI})
+
+remote=$ONOS_USER@$node
+
+ssh -t $remote "
+ # Wait until we reach the run-level 100
+ for i in \$(seq 1 45); do
+ $ONOS_INSTALL_DIR/bin/onos bundle:list 2>/dev/null | \
+ grep -q 'START LEVEL 100' && break || sleep 2
+ done
+
+ # Wait until ApplicationManager is available
+ for i in \$(seq 1 10); do
+ grep -q \" ApplicationManager .* Started\" \
+ $ONOS_INSTALL_DIR/log/karaf.log && break || sleep 1
+ done
+
+ grep -q \" ApplicationManager .* Started\" $ONOS_INSTALL_DIR/log/karaf.log
+"
diff --git a/framework/src/onos/tools/test/bin/onos-watch b/framework/src/onos/tools/test/bin/onos-watch
new file mode 100755
index 00000000..28e88c2f
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-watch
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Monitors selected set of ONOS commands using the system watch command.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+node=${1:-$OCI}
+
+commands="${2:-summary,intents,flows,hosts}"
+
+aux=/tmp/onos-watch.$$
+trap "rm -f $aux" EXIT
+
+echo "$commands" | tr ',' '\n' > $aux
+watch $3 "onos $node -b <$aux 2>/dev/null"
diff --git a/framework/src/onos/tools/test/bin/onos-wipe-out b/framework/src/onos/tools/test/bin/onos-wipe-out
new file mode 100755
index 00000000..6e996345
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-wipe-out
@@ -0,0 +1,9 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Wipes out all data from the ONOS cluster. Temporary until wipe-out is fixed.
+# -----------------------------------------------------------------------------
+
+for node in ${ONOS_INSTANCES:-$OCI}; do
+ onos $node wipe-out please
+done
+onos-check-summary $OCI '.*' 0 0 0 0 0
diff --git a/framework/src/onos/tools/test/bin/stc b/framework/src/onos/tools/test/bin/stc
new file mode 100755
index 00000000..fe8a5afe
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/stc
@@ -0,0 +1,23 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# System Test Coordinator
+#-------------------------------------------------------------------------------
+
+VER=1.3.0-SNAPSHOT
+JAR=~/.m2/repository/org/onosproject/onlab-stc/$VER/onlab-stc-$VER.jar
+SCENARIOS=$ONOS_ROOT/tools/test/scenarios
+
+DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=y"
+
+scenario=${1:-smoke}
+
+[ ! -f $scenario ] && scenario=$SCENARIOS/$scenario
+[ ! -f $scenario ] && scenario=$scenario.xml
+[ ! -f $scenario ] && echo "Scenario $scenario file not found" && exit 1
+
+[ $# -ge 1 ] && shift
+
+[ -t 1 ] && stcColor=true || unset stcColor
+
+[ -z "$stcDebug" ] && DEBUG_OPTS=""
+java $DEBUG_OPTS -jar $JAR $scenario "$@"
diff --git a/framework/src/onos/tools/test/bin/stc-launcher b/framework/src/onos/tools/test/bin/stc-launcher
new file mode 100755
index 00000000..6e473cdf
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/stc-launcher
@@ -0,0 +1,25 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# System Test Coordinator process launcher
+#-------------------------------------------------------------------------------
+
+#sleep 5 && exit 0;
+
+env=$1 && shift
+cwd=$1 && shift
+
+if [ $env != "-" -a $env != "~" ]; then
+ [ ! -f $env ] && echo "$env file not found" && exit 1
+ source $env
+fi
+
+if [ $cwd != "-" ]; then
+ [ ! -d $cwd ] && echo "$cwd directory not found" && exit 1
+ cd $cwd
+fi
+
+"$@" 2>&1
+status=$?
+
+[ $env != "~" ] && exit $status
+exit 0
diff --git a/framework/src/onos/tools/test/bin/stl b/framework/src/onos/tools/test/bin/stl
new file mode 100755
index 00000000..1487ab4f
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/stl
@@ -0,0 +1,7 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# System Test Coordinator
+#-------------------------------------------------------------------------------
+
+log=${2:-*}
+less /tmp/stc/$1/${log%.log}.log \ No newline at end of file
diff --git a/framework/src/onos/tools/test/cells/beast b/framework/src/onos/tools/test/cells/beast
new file mode 100644
index 00000000..6afd61d1
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/beast
@@ -0,0 +1,18 @@
+# Bare metal cluster (7-node)
+
+# Use the 1G NIC for cluster communications
+export ONOS_NIC="10.254.1.*"
+
+# ONOS Test proxy
+export OCT=10.254.1.200
+
+# Use the 1G NICs for external access
+export OC1=10.254.1.201
+export OC2=10.254.1.202
+export OC3=10.254.1.203
+export OC4=10.254.1.204
+export OC5=10.254.1.205
+export OC6=10.254.1.206
+export OC7=10.254.1.207
+
+export ONOS_APPS="drivers,null,intentperf"
diff --git a/framework/src/onos/tools/test/cells/beast-1 b/framework/src/onos/tools/test/cells/beast-1
new file mode 100644
index 00000000..698eded7
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/beast-1
@@ -0,0 +1,12 @@
+# Bare metal cluster (1-node)
+
+# Use the 1G NIC for cluster communications
+export ONOS_NIC="10.254.1.*"
+
+# ONOS Test proxy
+export OCT=10.254.1.200
+
+# Use the 1G NICs for external access
+export OC1=10.254.1.201
+
+export ONOS_APPS="drivers,null,intentperf"
diff --git a/framework/src/onos/tools/test/cells/beast-3 b/framework/src/onos/tools/test/cells/beast-3
new file mode 100644
index 00000000..6586ddc3
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/beast-3
@@ -0,0 +1,14 @@
+# Bare metal cluster (3-node)
+
+# Use the 1G NIC for cluster communications
+export ONOS_NIC="10.254.1.*"
+
+# ONOS Test proxy
+export OCT=10.254.1.200
+
+# Use the 1G NICs for external access
+export OC1=10.254.1.201
+export OC2=10.254.1.202
+export OC3=10.254.1.203
+
+export ONOS_APPS="drivers,null,intentperf"
diff --git a/framework/src/onos/tools/test/cells/beast-5 b/framework/src/onos/tools/test/cells/beast-5
new file mode 100644
index 00000000..e23f0771
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/beast-5
@@ -0,0 +1,18 @@
+# Bare metal cluster (5-node)
+
+# Use the 1G NIC for cluster communications
+export ONOS_NIC="10.254.1.*"
+
+# ONOS Test proxy
+export OCT=10.254.1.200
+
+export OCN=10.254.1.200
+
+# Use the 1G NICs for external access
+export OC1=10.254.1.201
+export OC2=10.254.1.202
+export OC3=10.254.1.203
+export OC4=10.254.1.204
+export OC5=10.254.1.205
+
+export ONOS_APPS="drivers,openflow,proxyarp,fwd"
diff --git a/framework/src/onos/tools/test/cells/bramble b/framework/src/onos/tools/test/cells/bramble
new file mode 100644
index 00000000..7f17d2f5
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/bramble
@@ -0,0 +1,8 @@
+export ONOS_NIC=192.168.1.*
+export OC1="192.168.1.11"
+export OC2="192.168.1.12"
+export OC3="192.168.1.13"
+export OC4="192.168.1.14"
+# export OC5="192.168.1.15"
+export OCN="192.168.1.15"
+export OCI="${OC1}"
diff --git a/framework/src/onos/tools/test/cells/ec2 b/framework/src/onos/tools/test/cells/ec2
new file mode 100644
index 00000000..3d64be27
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/ec2
@@ -0,0 +1,18 @@
+# EC2-based cluster (7-node)
+
+# Use the 10G NIC for cluster communications
+export ONOS_NIC="192.168.200.*"
+
+# ONOS Test proxy
+export OCT=192.168.200.101
+
+# Use the 1G NICs for external access
+export OC1=192.168.200.101
+export OC2=192.168.200.102
+export OC3=192.168.200.103
+export OC4=192.168.200.104
+export OC5=192.168.200.105
+export OC6=192.168.200.106
+export OC7=192.168.200.107
+
+export ONOS_APPS="drivers,null,intentperf"
diff --git a/framework/src/onos/tools/test/cells/local b/framework/src/onos/tools/test/cells/local
new file mode 100644
index 00000000..6d8b71cd
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/local
@@ -0,0 +1,8 @@
+# Local VirtualBox-based ONOS instances 1,2 & ONOS mininet box
+
+export ONOS_NIC=192.168.56.*
+export OC1="192.168.56.101"
+export OC2="192.168.56.102"
+export OCN="192.168.56.103"
+
+export ONOS_APPS="drivers,openflow,fwd,proxyarp,mobility"
diff --git a/framework/src/onos/tools/test/cells/madan3 b/framework/src/onos/tools/test/cells/madan3
new file mode 100644
index 00000000..857d096e
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/madan3
@@ -0,0 +1,7 @@
+# Madan's ProxMox ONOS instances 1,2,3 & ONOS mininet box
+
+export ONOS_NIC="10.128.4.*"
+export OC1="10.128.4.2"
+export OC2="10.128.4.3"
+export OC3="10.128.4.4"
+export OCN="10.128.4.5"
diff --git a/framework/src/onos/tools/test/cells/office b/framework/src/onos/tools/test/cells/office
new file mode 100644
index 00000000..2cd933e2
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/office
@@ -0,0 +1,7 @@
+# ONLAB_OF Wifi ProxMox-based cell; single node; no mininet-box
+
+export ONOS_NIC="10.1.10.*"
+export OC1="10.1.10.223"
+
+export ONOS_APPS="drivers,openflow,fwd,proxyarp,mobility"
+
diff --git a/framework/src/onos/tools/test/cells/prox b/framework/src/onos/tools/test/cells/prox
new file mode 100644
index 00000000..8af41989
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/prox
@@ -0,0 +1,6 @@
+# ProxMox-based cell of ONOS instances 1,2 & ONOS mininet box
+
+export ONOS_NIC="10.1.9.*"
+export OC1="10.1.9.94"
+export OC2="10.1.9.82"
+export OCN="10.1.9.93"
diff --git a/framework/src/onos/tools/test/cells/sdnip-pmox b/framework/src/onos/tools/test/cells/sdnip-pmox
new file mode 100644
index 00000000..e95b7e79
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/sdnip-pmox
@@ -0,0 +1,8 @@
+# SDN-IP ProxMox cell
+
+export ONOS_NIC=10.128.4.*
+export OC1="10.128.4.65"
+export OC2="10.128.4.66"
+export OC3="10.128.4.67"
+
+export ONOS_APPS="drivers,openflow,fwd,proxyarp,mobility,config,sdnip"
diff --git a/framework/src/onos/tools/test/cells/single b/framework/src/onos/tools/test/cells/single
new file mode 100644
index 00000000..dd03e491
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/single
@@ -0,0 +1,7 @@
+# Local VirtualBox-based single ONOS instance & ONOS mininet box
+
+export ONOS_NIC=192.168.56.*
+export OC1="192.168.56.101"
+export OCN="192.168.56.103"
+
+export ONOS_APPS="drivers,openflow,fwd,proxyarp,mobility"
diff --git a/framework/src/onos/tools/test/cells/single_optical b/framework/src/onos/tools/test/cells/single_optical
new file mode 100644
index 00000000..6bbe176e
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/single_optical
@@ -0,0 +1,7 @@
+# Optical use-case VirtualBox-based single ONOS instance & ONOS mininet box
+
+export ONOS_NIC=192.168.56.*
+export OC1="192.168.56.101"
+export OCN="192.168.56.103"
+
+export ONOS_APPS="drivers,openflow,fwd,proxyarp,mobility,optical"
diff --git a/framework/src/onos/tools/test/cells/tom b/framework/src/onos/tools/test/cells/tom
new file mode 100644
index 00000000..28d31729
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/tom
@@ -0,0 +1,7 @@
+# Thomas' VirtualBox-based 3 ONOS instances & ONOS mininet box
+
+export ONOS_NIC=192.168.56.*
+export OC1="192.168.56.11"
+export OC2="192.168.56.12"
+export OC3="192.168.56.13"
+export OCN="192.168.56.7"
diff --git a/framework/src/onos/tools/test/cells/tomx b/framework/src/onos/tools/test/cells/tomx
new file mode 100644
index 00000000..3e528ee8
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/tomx
@@ -0,0 +1,10 @@
+# Tom's ProxMox ONOS instances 1,2,3 & ONOS mininet box
+
+export ONOS_NIC="10.128.11.*"
+export OC1="10.128.11.1"
+export OC2="10.128.11.2"
+export OC3="10.128.11.3"
+export OCN="10.128.11.4"
+
+export OCT=$OC1
+export ONOS_APPS=drivers,openflow,proxyarp \ No newline at end of file
diff --git a/framework/src/onos/tools/test/cells/triple b/framework/src/onos/tools/test/cells/triple
new file mode 100644
index 00000000..42471228
--- /dev/null
+++ b/framework/src/onos/tools/test/cells/triple
@@ -0,0 +1,9 @@
+# Local VirtualBox-based ONOS instances 1,2,3 & ONOS mininet box
+
+export ONOS_NIC=192.168.56.*
+export OC1="192.168.56.101"
+export OC2="192.168.56.102"
+export OC3="192.168.56.104"
+export OCN="192.168.56.103"
+
+export ONOS_APPS="drivers,openflow,fwd,proxyarp,mobility"
diff --git a/framework/src/onos/tools/test/configs/l2-flow.json b/framework/src/onos/tools/test/configs/l2-flow.json
new file mode 100644
index 00000000..64bb5297
--- /dev/null
+++ b/framework/src/onos/tools/test/configs/l2-flow.json
@@ -0,0 +1,28 @@
+{
+ "isPermanent": true,
+ "priority": 100,
+ "selector": {
+ "criteria": [
+ {
+ "port": 2,
+ "type": "IN_PORT"
+ },
+ {
+ "mac": "00:00:00:00:11:22",
+ "type": "ETH_SRC"
+ },
+ {
+ "mac": "00:00:00:00:33:44",
+ "type": "ETH_DST"
+ }
+ ]
+ },
+ "treatment": {
+ "instructions": [
+ {
+ "port": 1,
+ "type": "OUTPUT"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/tools/test/configs/override-basic.json b/framework/src/onos/tools/test/configs/override-basic.json
new file mode 100644
index 00000000..c1f23ce6
--- /dev/null
+++ b/framework/src/onos/tools/test/configs/override-basic.json
@@ -0,0 +1,38 @@
+{
+ "devices": {
+ "of:0000000000000009": {
+ "basic": {
+ "allowed": true,
+ "owner": "Luigi"
+ }
+ },
+ "of:0000000000000008": {
+ "basic": {
+ "name": "NameChangeAgain",
+ "allowed": true,
+ "owner": "Mario"
+ }
+ },
+ "of:0000000000000007": {
+ "basic": {
+ "allowed": true,
+ "owner": "Peach",
+ "latitude": "25"
+ }
+ }
+ },
+ "links": {
+ "of:0000000000000006/2-of:0000000000000007/2": {
+ "basic": {
+ "allowed": true
+ }
+ }
+ },
+ "hosts": {
+ "00:00:00:00:00:03/-1": {
+ "basic": {
+ "allowed": true
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/tools/test/configs/sample-basic.json b/framework/src/onos/tools/test/configs/sample-basic.json
new file mode 100644
index 00000000..73cbd305
--- /dev/null
+++ b/framework/src/onos/tools/test/configs/sample-basic.json
@@ -0,0 +1,54 @@
+{
+ "devices": {
+ "of:0000000000000009": {
+ "basic": {
+ "allowed": true,
+ "owner": "Luigi"
+ }
+ },
+ "of:0000000000000008": {
+ "basic": {
+ "name": "NameChange",
+ "allowed": true,
+ "owner": "Mario"
+ }
+ },
+ "of:0000000000000007": {
+ "basic": {
+ "allowed": true,
+ "owner": "Peach",
+ "latitude": "25"
+ }
+ },
+ "of:0000000000000003": {
+ "basic": {
+ "allowed": true,
+ "owner": "Wario"
+ }
+ }
+ },
+ "links": {
+ "of:0000000000000006/2-of:0000000000000007/2": {
+ "basic": {
+ "allowed": true
+ }
+ }
+ },
+ "hosts": {
+ "00:00:00:00:00:03/-1": {
+ "basic": {
+ "allowed": false
+ }
+ },
+ "00:00:00:00:00:02/-1": {
+ "basic": {
+ "allowed": false
+ }
+ },
+ "00:00:00:00:00:01/-1": {
+ "basic": {
+ "allowed": false
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/tools/test/scenarios/archetypes.xml b/framework/src/onos/tools/test/scenarios/archetypes.xml
new file mode 100644
index 00000000..8244a32f
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/archetypes.xml
@@ -0,0 +1,50 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="archetypes" description="ONOS archetypes test">
+ <group name="Archetypes" cwd="${WORKSPACE}/tmp/test-app">
+ <step name="Clean-Up" cwd="${WORKSPACE}/tmp" env="~"
+ exec="rm -r test-app"/>
+
+ <step name="Create-App" cwd="${WORKSPACE}/tmp" requires="^"
+ exec="onos-create-app app org.test.app test-app 1.2.3 org.test.app -DinteractiveMode=false"/>
+ <step name="Build-App" requires="Create-App" exec="mvn clean install"/>
+ <step name="Install-App" requires="^"
+ exec="onos-app ${OCI} install! target/test-app-1.2.3.oar"/>
+ <step name="Verify-App" requires="^"
+ exec="onos-check-components ${OCI} org.test.app.AppComponent"/>
+
+ <step name="Create-App-CLI-Overlay" requires="Install-App"
+ exec="onos-create-app cli org.test.app test-app 1.2.3 org.test.app -DinteractiveMode=false"/>
+ <step name="Build-App-With-CLI" requires="^"
+ exec="mvn clean install"/>
+ <step name="Reinstall-App-With-CLI" requires="^,~Verify-App"
+ exec="onos-app ${OCI} reinstall! target/test-app-1.2.3.oar"/>
+ <step name="Verify-CLI" requires="^"
+ exec="onos ${OCI} sample"/>
+
+ <step name="Create-App-UI-Overlay" requires="Reinstall-App-With-CLI"
+ exec="onos-create-app ui org.test.app test-app 1.2.3 org.test.app -DinteractiveMode=false"/>
+ <step name="Build-App-With-UI" requires="^"
+ exec="mvn clean install"/>
+ <step name="Reinstall-App-With-UI" requires="^,~Verify-CLI"
+ exec="onos-app ${OCI} reinstall! target/test-app-1.2.3.oar"/>
+ <step name="Verify-UI" requires="^"
+ exec="onos-check-views ${OCI} id=sample"/>
+
+ <step name="Uninstall-App" requires="^"
+ exec="onos-app ${OCI} uninstall org.foo.app"/>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/bin/create-flow.py b/framework/src/onos/tools/test/scenarios/bin/create-flow.py
new file mode 100755
index 00000000..4e9b452b
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/bin/create-flow.py
@@ -0,0 +1,56 @@
+#! /usr/bin/env python
+
+import requests
+
+from requests.auth import HTTPBasicAuth
+import sys
+
+
+
+if len(sys.argv) != 6:
+ print "usage: create-flow onos-node name device in-port out-port"
+ sys.exit(1)
+
+node = sys.argv[1]
+name = sys.argv[2]
+device = sys.argv[3]
+inPort = sys.argv[4]
+outPort = sys.argv[5]
+
+flowJsonTemplate = \
+ '{{' + \
+ '"priority": 1,' + \
+ '"isPermanent": true,' + \
+ '"treatment": {{' + \
+ '"instructions": [' + \
+ '{{' + \
+ '"type": "OUTPUT",' + \
+ '"port": {}' + \
+ '}}' + \
+ ']' + \
+ '}},' + \
+ '"selector": {{' + \
+ '"criteria": [' + \
+ '{{' + \
+ '"type": "IN_PORT",' + \
+ '"port": {}' + \
+ '}}' + \
+ ']' + \
+ '}}' + \
+ '}}'
+
+flowJson = flowJsonTemplate.format(inPort, outPort)
+intentRequest = requests.post('http://' + node + ':8181/onos/v1/flows/' + device,
+ auth=HTTPBasicAuth('onos', 'rocks'),
+ data=flowJson)
+
+if intentRequest.status_code != 201:
+ print intentRequest.text
+ sys.exit(1)
+
+location = intentRequest.headers["location"]
+print "@stc " + name + "Location=" + location
+sys.exit(0)
+
+
+
diff --git a/framework/src/onos/tools/test/scenarios/bin/create-intent.py b/framework/src/onos/tools/test/scenarios/bin/create-intent.py
new file mode 100755
index 00000000..4e5d4f62
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/bin/create-intent.py
@@ -0,0 +1,49 @@
+#! /usr/bin/env python
+
+import requests
+
+from requests.auth import HTTPBasicAuth
+import sys
+
+
+
+if len(sys.argv) != 7:
+ print "usage: create-intent onos-node name ingressDevice ingressPort egressDevice egressPort"
+ sys.exit(1)
+
+node = sys.argv[1]
+name = sys.argv[2]
+ingress = sys.argv[3]
+ingressPort = sys.argv[4]
+egress = sys.argv[5]
+egressPort = sys.argv[6]
+
+intentJsonTemplate = \
+ '{{' + \
+ '"type": "PointToPointIntent",' + \
+ '"appId": "org.onosproject.cli",' + \
+ '"ingressPoint": {{' + \
+ ' "device": "{}",' + \
+ ' "port": "{}"' + \
+ '}},' + \
+ '"egressPoint": {{' + \
+ ' "device": "{}",' + \
+ ' "port": "{}"' + \
+ '}}' + \
+ '}}'
+
+intentJson = intentJsonTemplate.format(ingress, ingressPort, egress, egressPort)
+intentRequest = requests.post('http://' + node + ':8181/onos/v1/intents/',
+ auth=HTTPBasicAuth('onos', 'rocks'),
+ data=intentJson)
+
+if intentRequest.status_code != 201:
+ print intentRequest.text
+ sys.exit(1)
+
+location = intentRequest.headers["location"]
+print "@stc " + name + "Location=" + location
+sys.exit(0)
+
+
+
diff --git a/framework/src/onos/tools/test/scenarios/bin/find-device.py b/framework/src/onos/tools/test/scenarios/bin/find-device.py
new file mode 100755
index 00000000..430e18ad
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/bin/find-device.py
@@ -0,0 +1,39 @@
+#! /usr/bin/env python
+
+import requests
+import sys
+import urllib
+
+from requests.auth import HTTPBasicAuth
+
+if len(sys.argv) != 4:
+ print "usage: find-device onos-node name device-id"
+ sys.exit(1)
+
+node = sys.argv[1]
+name = sys.argv[2]
+id = sys.argv[3]
+
+deviceRequest = requests.get('http://' + node + ':8181/onos/v1/devices/' +
+ urllib.quote_plus(id),
+ auth=HTTPBasicAuth('onos', 'rocks'))
+
+if deviceRequest.status_code != 200:
+ print deviceRequest.text
+ sys.exit(1)
+
+deviceJson = deviceRequest.json()
+
+print "@stc " + name + "Id=" + deviceJson["id"]
+print "@stc " + name + "Type=" + deviceJson["type"]
+print "@stc " + name + "Available=" + str(deviceJson["available"])
+channelId = deviceJson["annotations"]["channelId"]
+channelIdWords = channelId.split(':')
+print "@stc " + name + "IpAddress=" + channelIdWords[0]
+
+sys.exit(0)
+
+
+
+
+
diff --git a/framework/src/onos/tools/test/scenarios/bin/find-flow.py b/framework/src/onos/tools/test/scenarios/bin/find-flow.py
new file mode 100755
index 00000000..a2f2e4d1
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/bin/find-flow.py
@@ -0,0 +1,40 @@
+#! /usr/bin/env python
+
+import requests
+import sys
+
+from requests.auth import HTTPBasicAuth
+
+if len(sys.argv) != 4:
+ print "usage: find-flow onos-node name device-id"
+ sys.exit(1)
+
+node = sys.argv[1]
+name = sys.argv[2]
+deviceId = sys.argv[3]
+
+flowsRequest = requests.get('http://' + node + ':8181/onos/v1/flows/' + deviceId,
+ auth=HTTPBasicAuth('onos', 'rocks'))
+
+if flowsRequest.status_code != 200:
+ print flowsRequest.text
+ sys.exit(1)
+
+flowsJson = flowsRequest.json()
+
+for flow in flowsJson["flows"]:
+ if deviceId == flow["deviceId"]:
+ for criterion in flow["selector"]["criteria"]:
+ if criterion["type"] == 'IN_PORT' and criterion["port"] > 0:
+ for instruction in flow["treatment"]["instructions"]:
+ if instruction["port"] > 0 and instruction["type"] == 'OUTPUT':
+ print "@stc " + name + "FlowState=" + flow["state"]
+ print "@stc " + name + "FlowId=" + flow["id"]
+ print "@stc " + name + "FlowPort=" + str(instruction["port"])
+ sys.exit(0)
+
+sys.exit(1)
+
+
+
+
diff --git a/framework/src/onos/tools/test/scenarios/bin/find-host.py b/framework/src/onos/tools/test/scenarios/bin/find-host.py
new file mode 100755
index 00000000..e87a4090
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/bin/find-host.py
@@ -0,0 +1,36 @@
+#! /usr/bin/env python
+
+import requests
+import sys
+import urllib
+
+from requests.auth import HTTPBasicAuth
+
+if len(sys.argv) != 4:
+ print "usage: find-host onos-node name device-id"
+ sys.exit(1)
+
+node = sys.argv[1]
+name = sys.argv[2]
+id = sys.argv[3]
+
+hostRequest = requests.get('http://' + node + ':8181/onos/v1/hosts/' +
+ urllib.quote_plus(id),
+ auth=HTTPBasicAuth('onos', 'rocks'))
+
+if hostRequest.status_code != 200:
+ print hostRequest.text
+ sys.exit(1)
+
+hostJson = hostRequest.json()
+
+print "@stc " + name + "Id=" + hostJson["id"]
+print "@stc " + name + "Mac=" + hostJson["mac"]
+print "@stc " + name + "IpAddress=" + hostJson["ipAddresses"][0]
+
+sys.exit(0)
+
+
+
+
+
diff --git a/framework/src/onos/tools/test/scenarios/bin/find-link.py b/framework/src/onos/tools/test/scenarios/bin/find-link.py
new file mode 100755
index 00000000..9ac6e358
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/bin/find-link.py
@@ -0,0 +1,45 @@
+#! /usr/bin/env python
+
+import requests
+import sys
+
+from requests.auth import HTTPBasicAuth
+
+if len(sys.argv) != 7:
+ print "usage: find-link onos-node name src-device-id src-port dst-device-id dst-port"
+ sys.exit(1)
+
+node = sys.argv[1]
+name = sys.argv[2]
+srcDeviceId = sys.argv[3]
+srcPort = sys.argv[4]
+dstDeviceId = sys.argv[5]
+dstPort = sys.argv[6]
+
+
+linksRequest = requests.get('http://' + node + ':8181/onos/v1/links?device=' +
+ srcDeviceId + '&port=' + srcPort,
+ auth=HTTPBasicAuth('onos', 'rocks'))
+
+if linksRequest.status_code != 200:
+ print linksRequest.text
+ sys.exit(1)
+
+linksJson = linksRequest.json()
+
+for link in linksJson["links"]:
+ if srcDeviceId == link["src"]["device"]:
+ if dstDeviceId == link["dst"]["device"]:
+ print "@stc " + name + "SrcDevice=" + link["src"]["device"]
+ print "@stc " + name + "SrcPort=" + link["src"]["port"]
+ print "@stc " + name + "DstDevice=" + link["dst"]["device"]
+ print "@stc " + name + "DstPort=" + link["dst"]["port"]
+ print "@stc " + name + "Type=" + link["type"]
+ print "@stc " + name + "State=" + link["state"]
+ sys.exit(0)
+
+sys.exit(1)
+
+
+
+
diff --git a/framework/src/onos/tools/test/scenarios/example.xml b/framework/src/onos/tools/test/scenarios/example.xml
new file mode 100644
index 00000000..65803141
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/example.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="example" description="Example">
+ <step name="One" exec="echo @stc foo=bar"/>
+ <step name="Two" requires="One" exec="echo ${foo}"/>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/net-create-flows.xml b/framework/src/onos/tools/test/scenarios/net-create-flows.xml
new file mode 100644
index 00000000..6a6a80b0
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-create-flows.xml
@@ -0,0 +1,93 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-create-flows"
+ description="Network Flow Creation Test Using REST API">
+ <!-- TODO: parametrize this via recipes -->
+ <group name="Net-Create-Flows">
+
+ <!-- Make sure that reactive forwarding is off -->
+ <step name="Net-Create-Flows.Uninstall-Reactive-Forwarding"
+ exec="onos ${OC1} app deactivate org.onosproject.fwd org.onosproject.ifwd"/>
+ <step name="Net-Create-Flows.Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} fwd,ifwd excludes"/>
+
+ <!-- Force discovery of hosts -->
+ <step name="Net-Create-Flows.Find-Host-1" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect 100% packet loss"/>
+ <step name="Net-Create-Flows.Find-Host-2" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 -w1 h1 --expect 100% packet loss"/>
+
+
+ <!-- Use REST API to create a point to point intent in each direction -->
+ <step name="Net-Create-Flows.1-to-Host" requires="Net-Create-Flows.Find-Host-2"
+ exec="create-flow.py ${OC1} f1 of:0000000000000001 5 1"/>
+ <step name="Net-Create-Flows.1-to-19" requires="^"
+ exec="create-flow.py ${OC1} f2 of:0000000000000001 1 2"/>
+ <step name="Net-Create-Flows.19-to-7" requires="^"
+ exec="create-flow.py ${OC1} f3 of:0000000000000019 2 8"/>
+ <step name="Net-Create-Flows.7-to-4" requires="^"
+ exec="create-flow.py ${OC1} f4 of:0000000000000007 2 3"/>
+ <step name="Net-Create-Flows.4-to-Host" requires="^"
+ exec="create-flow.py ${OC1} f5 of:0000000000000004 1 3"/>
+
+ <step name="Net-Create-Flows.Host-to-1" requires="^"
+ exec="create-flow.py ${OC1} f6 of:0000000000000001 1 5"/>
+ <step name="Net-Create-Flows.19-to-1" requires="^"
+ exec="create-flow.py ${OC1} f7 of:0000000000000001 2 1"/>
+ <step name="Net-Create-Flows.7-to-19" requires="^"
+ exec="create-flow.py ${OC1} f8 of:0000000000000019 8 2"/>
+ <step name="Net-Create-Flows.4-to-7" requires="^"
+ exec="create-flow.py ${OC1} f9 of:0000000000000007 3 2"/>
+ <step name="Net-Create-Flows.Host-to-4" requires="^"
+ exec="create-flow.py ${OC1} f10 of:0000000000000004 3 1"/>
+
+ <!-- Check that connectivity was established -->
+ <step name="Net-Create-Flows.Ping-XY" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
+ <step name="Net-Create-Flows.Ping-YX" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 h1 --expect \ 0% packet loss"/>
+
+ <!-- Use REST API to remove the flows. -->
+ <step name="Net-Create-Flows.Delete-f1" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f1Location}"/>
+ <step name="Net-Create-Flows.Delete-f2" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f2Location}"/>
+ <step name="Net-Create-Flows.Delete-f3" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f3Location}"/>
+ <step name="Net-Create-Flows.Delete-f4" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f4Location}"/>
+ <step name="Net-Create-Flows.Delete-f5" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f5Location}"/>
+ <step name="Net-Create-Flows.Delete-f6" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f6Location}"/>
+ <step name="Net-Create-Flows.Delete-f7" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f7Location}"/>
+ <step name="Net-Create-Flows.Delete-f8" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f8Location}"/>
+ <step name="Net-Create-Flows.Delete-f9" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f9Location}"/>
+ <step name="Net-Create-Flows.Delete-f10" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${f10Location}"/>
+
+ <!-- Ping again to be sure the path was removed. -->
+ <step name="Net-Create-Flows.Fail-Ping-XY" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 100% packet loss"/>
+ <step name="Net-Create-Flows.Fail-Ping-YX" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 h1 --expect \ 100% packet loss"/>
+
+
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/net-host-intent.xml b/framework/src/onos/tools/test/scenarios/net-host-intent.xml
new file mode 100644
index 00000000..fbf8c4ab
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-host-intent.xml
@@ -0,0 +1,59 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-host-intent" description="Network host intent connectivity test">
+ <!-- TODO: parametrize this via recipes -->
+ <group name="Host-Intent-Connectivity">
+ <step name="Host-Intent.Uninstall-Reactive-Forwarding"
+ exec="onos ${OC1} app deactivate org.onosproject.fwd org.onosproject.ifwd"/>
+ <step name="Host-Intent.Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} fwd,ifwd excludes"/>
+
+ <step name="Host-Intent.Find-Host-1" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect ."/>
+ <step name="Host-Intent.Find-Host-2" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 -w1 h1 --expect ."/>
+
+ <step name="Host-Intent.Create-Intent" requires="^"
+ exec="onos-create-intent ${OC1} h2h host 00:00:00:00:00:01/-1 00:00:00:00:00:04/-1"/>
+ <step name="Host-Intent.Validate-Intent-Installed" requires="Host-Intent.Create-Intent"
+ exec="onos-check-intent ${OC1} h2h INSTALLED"/>
+
+ <import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="Host-Intent"/>
+ <dependency name="Host-Intent.Net-Link-Down-Up"
+ requires="Host-Intent.Validate-Intent-Installed"/>
+
+ <step name="Host-Intent.Validate-Intent-Installed-Still" requires="Host-Intent.Link-1-Down"
+ exec="onos-check-intent ${OC1} h2h INSTALLED"/>
+
+ <dependency name="Host-Intent.Link-2-Down"
+ requires="~Host-Intent.Validate-Intent-Installed-Still" />
+
+ <step name="Host-Intent.Validate-Intent-Failed" requires="Host-Intent.Link-2-Down"
+ exec="onos-check-intent ${OC1} h2h FAILED"/>
+
+ <dependency name="Host-Intent.Link-1-Up"
+ requires="~Host-Intent.Validate-Intent-Failed" />
+
+ <step name="Host-Intent.Validate-Intent-Installed-Again" requires="Host-Intent.Link-1-Up"
+ exec="onos-check-intent ${OC1} h2h INSTALLED"/>
+
+ <dependency name="Host-Intent.Ping-4"
+ requires="~Host-Intent.Validate-Intent-Installed-Again" />
+
+ <step name="Host-Intent.Remove-Intent" requires="~Host-Intent.Net-Link-Down-Up"
+ exec="onos ${OC1} remove-intent -p org.onosproject.cli h2h"/>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/net-link-down-up.xml b/framework/src/onos/tools/test/scenarios/net-link-down-up.xml
new file mode 100644
index 00000000..8bcbfa7f
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-link-down-up.xml
@@ -0,0 +1,38 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-link-down-up" description="Network link up-down test">
+ <!-- TODO: parametrize this via recipes -->
+ <group name="Net-Link-Down-Up">
+ <step name="Ping-1"
+ exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
+ <step name="Link-1-Down" requires="~Ping-1"
+ exec="onos-mininet sendAndExpect link s4 s7 down --expect ."/>
+ <step name="Ping-2" requires="~Link-1-Down"
+ exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
+ <step name="Link-2-Down" requires="~Ping-2"
+ exec="onos-mininet sendAndExpect link s4 s5 down --expect ."/>
+ <step name="Ping-3" requires="~Link-2-Down"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect 100% packet loss"/>
+ <step name="Link-1-Up" requires="~Ping-3"
+ exec="onos-mininet sendAndExpect link s4 s7 up --expect ."/>
+ <step name="Ping-4" requires="~Link-1-Up"
+ exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
+ <step name="Link-2-Up" requires="~Ping-4"
+ exec="onos-mininet sendAndExpect link s4 s5 up --expect ."/>
+ <step name="Ping-5" requires="~Link-2-Up"
+ exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
+ </group>
+</scenario> \ No newline at end of file
diff --git a/framework/src/onos/tools/test/scenarios/net-pingall.xml b/framework/src/onos/tools/test/scenarios/net-pingall.xml
new file mode 100644
index 00000000..8968e0dc
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-pingall.xml
@@ -0,0 +1,37 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-pingall" description="Network pingall test">
+ <!-- TODO: parametrize this via recipes -->
+ <group name="Net-Pingall">
+ <step name="Install-Apps"
+ exec="onos ${OC1} app activate org.onosproject.openflow org.onosproject.proxyarp org.onosproject.fwd"/>
+ <step name="Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} drivers,openflow,proxyarp,fwd includes"/>
+
+ <!-- TODO: take this out when initial pingall sweep is 100% -->
+ <step name="Initial-Ping-All" requires="Check-Apps"
+ exec="onos-mininet sendAndExpect py net.pingAll(1) --expect 600 received"/>
+
+ <step name="Ping-All-And-Verify" requires="Check-Apps,Initial-Ping-All"
+ exec="onos-mininet sendAndExpect py net.pingAll(1) --expect 600/600 received"/>
+
+ <step name="Check-Summary-For-Hosts" requires="~Ping-All-And-Verify"
+ exec="onos-check-summary ${OC1} [0-9]* 25 140 25"/>
+
+ <step name="Config-Topo" requires="~Check-Summary-For-Hosts"
+ exec="onos-topo-cfg ${OC1} ${ONOS_ROOT}/tools/test/topos/attmpls.json"/>
+ </group>
+</scenario> \ No newline at end of file
diff --git a/framework/src/onos/tools/test/scenarios/net-point-intent.xml b/framework/src/onos/tools/test/scenarios/net-point-intent.xml
new file mode 100644
index 00000000..acb8212b
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-point-intent.xml
@@ -0,0 +1,77 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-point-intent"
+ description="Network point to point intent connectivity test">
+ <!-- TODO: parametrize this via recipes -->
+ <group name="P2P-Intent-Connectivity">
+ <step name="P2P-Intent.Uninstall-Reactive-Forwarding"
+ exec="onos ${OC1} app deactivate org.onosproject.fwd org.onosproject.ifwd"/>
+ <step name="P2P-Intent.Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} fwd,ifwd excludes"/>
+
+ <step name="P2P-Intent.Find-Host-1" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect ."/>
+ <step name="P2P-Intent.Find-Host-2" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 -w1 h1 --expect ."/>
+
+ <step name="P2P-Intent.Create-Intent-XY" requires="^"
+ exec="onos-create-intent ${OC1} xy point of:0000000000000001/1 of:0000000000000004/1"/>
+ <step name="P2P-Intent.Create-Intent-YX" requires="^"
+ exec="onos-create-intent ${OC1} yx point of:0000000000000004/1 of:0000000000000001/1"/>
+
+ <step name="P2P-Intent.Validate-Intent-XY-Installed" requires="^"
+ exec="onos-check-intent ${OC1} yx INSTALLED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Installed" requires="^"
+ exec="onos-check-intent ${OC1} xy INSTALLED"/>
+
+ <import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="P2P-Intent"/>
+ <dependency name="P2P-Intent.Net-Link-Down-Up"
+ requires="P2P-Intent.Validate-Intent-XY-Installed,
+ P2P-Intent.Validate-Intent-YX-Installed"/>
+
+ <step name="P2P-Intent.Validate-Intent-XY-Installed-Still" requires="P2P-Intent.Link-1-Down"
+ exec="onos-check-intent ${OC1} xy INSTALLED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Installed-Still" requires="P2P-Intent.Link-1-Down"
+ exec="onos-check-intent ${OC1} yx INSTALLED"/>
+
+ <dependency name="P2P-Intent.Link-2-Down"
+ requires="~P2P-Intent.Validate-Intent-XY-Installed-Still,
+ ~P2P-Intent.Validate-Intent-YX-Installed-Still"/>
+
+ <step name="P2P-Intent.Validate-Intent-XY-Failed" requires="P2P-Intent.Link-2-Down"
+ exec="onos-check-intent ${OC1} xy FAILED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Failed" requires="P2P-Intent.Link-2-Down"
+ exec="onos-check-intent ${OC1} yx FAILED"/>
+
+ <dependency name="P2P-Intent.Link-1-Up"
+ requires="~P2P-Intent.Validate-Intent-XY-Failed,
+ ~P2P-Intent.Validate-Intent-YX-Failed" />
+
+ <step name="P2P-Intent.Validate-Intent-XY-Installed-Again" requires="P2P-Intent.Link-1-Up"
+ exec="onos-check-intent ${OC1} xy INSTALLED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Installed-Again" requires="P2P-Intent.Link-1-Up"
+ exec="onos-check-intent ${OC1} yx INSTALLED"/>
+
+ <dependency name="P2P-Intent.Ping-4"
+ requires="~P2P-Intent.Validate-Intent-XY-Installed-Again,
+ ~P2P-Intent.Validate-Intent-YX-Installed-Again"/>
+
+ <step name="P2P-Intent.Remove-Intent-XY" requires="~P2P-Intent.Net-Link-Down-Up"
+ exec="onos ${OC1} remove-intent -p org.onosproject.cli xy"/>
+ <step name="P2P-Intent.Remove-Intent-YX" requires="~P2P-Intent.Net-Link-Down-Up"
+ exec="onos ${OC1} remove-intent -p org.onosproject.cli yx"/>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/net-rest.xml b/framework/src/onos/tools/test/scenarios/net-rest.xml
new file mode 100644
index 00000000..fc7b1d08
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-rest.xml
@@ -0,0 +1,160 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-rest"
+ description="Network REST API test">
+ <!-- TODO: parametrize this via recipes -->
+ <group name="Net-REST">
+
+ <!-- Make sure that reactive forwarding is off -->
+ <step name="Net-REST.Uninstall-Reactive-Forwarding"
+ exec="onos ${OC1} app deactivate org.onosproject.fwd org.onosproject.ifwd"/>
+ <step name="Net-REST.Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} fwd,ifwd excludes"/>
+
+ <!-- Force discovery of hosts -->
+ <step name="Net-REST.Find-Host-1" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect ."/>
+ <step name="Net-REST.Find-Host-2" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 -w1 h1 --expect ."/>
+
+ <!-- Verify some links using the REST API -->
+ <step name="Net-REST.Query-Link-1" requires="Net-REST.Find-Host-2"
+ exec="find-link.py ${OC1} link1 of:0000000000000001 5 of:0000000000000006 4"/>
+ <step name="Net-REST.Validate-Link-1-State" requires="^"
+ exec="test '${link1State}' == 'ACTIVE'"/>
+ <step name="Net-REST.Validate-Link-1-Type" requires="^"
+ exec="test '${link1Type}' == 'DIRECT'"/>
+ <step name="Net-REST.Validate-Link-1-Src-Device" requires="^"
+ exec="test '${link1SrcDevice}' == 'of:0000000000000001'"/>
+ <step name="Net-REST.Validate-Link-1-Dst-Device" requires="^"
+ exec="test '${link1DstDevice}' == 'of:0000000000000006'"/>
+ <step name="Net-REST.Validate-Link-1-Src-Port" requires="^"
+ exec="test '${link1SrcPort}' == '5'"/>
+ <step name="Net-REST.Validate-Link-1-Dst-Port" requires="^"
+ exec="test '${link1DstPort}' == '4'"/>
+
+ <step name="Net-REST.Query-Link-2" requires="Net-REST.Find-Host-2"
+ exec="find-link.py ${OC1} link2 of:0000000000000019 7 of:0000000000000006 3"/>
+ <step name="Net-REST.Validate-Link-2-State" requires="^"
+ exec="test '${link2State}' == 'ACTIVE'"/>
+ <step name="Net-REST.Validate-Link-2-Type" requires="^"
+ exec="test '${link2Type}' == 'DIRECT'"/>
+ <step name="Net-REST.Validate-Link-2-Src-Device" requires="^"
+ exec="test '${link2SrcDevice}' == 'of:0000000000000019'"/>
+ <step name="Net-REST.Validate-Link-2-Dst-Device" requires="^"
+ exec="test '${link2DstDevice}' == 'of:0000000000000006'"/>
+ <step name="Net-REST.Validate-Link-2-Src-Port" requires="^"
+ exec="test '${link2SrcPort}' == '7'"/>
+ <step name="Net-REST.Validate-Link-2-Dst-Port" requires="^"
+ exec="test '${link2DstPort}' == '3'"/>
+
+ <!-- Verify the hosts using the REST API -->
+ <step name="Net-REST.Query-Host-1" requires="Net-REST.Find-Host-2"
+ exec="find-host.py ${OC1} host1 00:00:00:00:00:01/-1"/>
+ <step name="Net-REST.Validate-Host-1-Id" requires="^"
+ exec="test '${host1Id}' == '00:00:00:00:00:01/-1'"/>
+ <step name="Net-REST.Validate-Host-1-Mac" requires="^"
+ exec="test '${host1Mac}' == '00:00:00:00:00:01'"/>
+ <step name="Net-REST.Validate-Host-1-Ip" requires="^"
+ exec="test '${host1IpAddress}' == '10.0.0.1'"/>
+
+ <step name="Net-REST.Query-Host-2" requires="Net-REST.Find-Host-2"
+ exec="find-host.py ${OC1} host2 00:00:00:00:00:04/-1"/>
+ <step name="Net-REST.Validate-Host-2-Id" requires="^"
+ exec="test '${host2Id}' == '00:00:00:00:00:04/-1'"/>
+ <step name="Net-REST.Validate-Host-2-Mac" requires="^"
+ exec="test '${host2Mac}' == '00:00:00:00:00:04'"/>
+ <step name="Net-REST.Validate-Host-2-Ip" requires="^"
+ exec="test '${host2IpAddress}' == '10.0.0.4'"/>
+
+ <!-- Verify a switch using the REST API -->
+ <step name="Net-REST.Query-Dev-1" requires="Net-REST.Find-Host-2"
+ exec="find-device.py ${OC1} dev1 of:0000000000000014"/>
+ <step name="Net-REST.Validate-Dev1-Id" requires="^"
+ exec="test '${dev1Id}' == 'of:0000000000000014'"/>
+ <step name="Net-REST.Validate-Dev1-Type" requires="^"
+ exec="test '${dev1Type}' == 'SWITCH'"/>
+ <step name="Net-REST.Validate-Dev1-Available" requires="^"
+ exec="test '${dev1Available}' == 'True'"/>
+ <step name="Net-REST.Validate-Dev1-ChannelId" requires="^"
+ exec="test '${dev1IpAddress}' == '${OCN}'"/>
+
+ <!-- Use REST API to create a point to point intent in each direction -->
+ <step name="Net-REST.Create-Intent-XY" requires="Net-REST.Find-Host-2"
+ exec="create-intent.py ${OC1} xy of:0000000000000001 1 of:0000000000000004 1"/>
+ <step name="Net-REST.Create-Intent-YX" requires="^"
+ exec="create-intent.py ${OC1} yx of:0000000000000004 1 of:0000000000000001 1"/>
+
+ <!-- Check that the intents can be fetched via the REST API -->
+ <step name="Net-REST.Validate-Intent-XY-Installed"
+ requires="Net-REST.Create-Intent-YX"
+ exec="curl -f -uonos:rocks ${xyLocation}"/>
+ <step name="Net-REST.Validate-Intent-YX-Installed"
+ requires="^"
+ exec="curl -f -uonos:rocks ${yxLocation}"/>
+
+ <!-- Use REST API to query flows created by the intents -->
+ <step name="Net-REST.Validate-Intent-XY-Flow-Installed"
+ requires="Net-REST.Create-Intent-YX"
+ exec="find-flow.py ${OC1} dev1out of:0000000000000001"/>
+ <step name="Net-REST.Validate-XY-Flow-State" requires="^"
+ exec="test '${dev1outFlowState}' == 'ADDED' -o '${dev1outFlowState}' == 'PENDING_ADD'"/>
+ <step name="Net-REST.Validate-XY-Flow-Port" requires="^"
+ exec="test ${dev1outFlowPort} -ge 1 -a ${dev1outFlowPort} -le 5"/>
+
+ <step name="Net-REST.Validate-Intent-YX-Flow-Installed" requires="Net-REST.Create-Intent-YX"
+ exec="find-flow.py ${OC1} dev4out of:0000000000000004"/>
+ <step name="Net-REST.Validate-YX-Flow-State" requires="^"
+ exec="test '${dev4outFlowState}' == 'ADDED' -o '${dev4outFlowState}' == 'PENDING_ADD'"/>
+ <step name="Net-REST.Validate-YX-Flow-Port" requires="^"
+ exec="test '${dev4outFlowPort}' == '3'"/>
+
+ <!-- Check that connectivity was established -->
+ <step name="Net-REST.Ping-XY" requires="Net-REST.Create-Intent-XY,Net-REST.Create-Intent-YX"
+ exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
+ <step name="Net-REST.Ping-YX" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 h1 --expect \ 0% packet loss"/>
+
+ <!-- Remove the intents via the REST API -->
+ <step name="Net-REST.Delete-Intent-XY"
+ requires="Net-REST.Validate-Intent-XY-Installed,
+ Net-REST.Validate-Intent-YX-Installed,
+ Net-REST.Validate-Intent-XY-Flow-Installed,
+ Net-REST.Validate-Intent-YX-Flow-Installed,
+ Net-REST.Ping-XY,
+ Net-REST.Ping-YX"
+ exec="curl -f -X DELETE -uonos:rocks ${xyLocation}"/>
+ <step name="Net-REST.Delete-Intent-YX" requires="^"
+ exec="curl -f -X DELETE -uonos:rocks ${yxLocation}"/>
+
+ <!-- Use REST API to be sure that flows are no longer installed -->
+ <step name="Net-REST.Validate-XY-Flows-Removed" requires="Net-REST.Delete-Intent-XY"
+ exec="find-flow.py ${OC1} dev1out of:0000000000000001"
+ env="!"/>
+ <step name="Net-REST.Validate-YX-Flows-Removed" requires="Net-REST.Delete-Intent-YX"
+ exec="find-flow.py ${OC1} dev4out of:0000000000000004"
+ env="!"/>
+
+ <!-- Check that the deleted intents no longer appear in the REST API -->
+ <step name="Net-REST.Allow-Intents-To-Purge" requires="Net-REST.Delete-Intent-XY"
+ exec="sleep 1"/>
+ <step name="Net-REST.Validate-Intent-XY-Removed" requires="Net-REST.Allow-Intents-To-Purge"
+ exec="curl -f -uonos:rocks ${xyLocation}" env="!"/>
+ <step name="Net-REST.Validate-Intent-YX-Removed" requires="Net-REST.Allow-Intents-To-Purge"
+ exec="curl -f -uonos:rocks ${yxLocation}" env="!"/>
+
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/net-setup.xml b/framework/src/onos/tools/test/scenarios/net-setup.xml
new file mode 100644
index 00000000..e179ec5a
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-setup.xml
@@ -0,0 +1,46 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-setup" description="Network setup steps">
+ <!-- TODO: parametrize this via recipes -->
+ <group name="Net-Setup">
+ <step name="Push-Topos" exec="onos-push-topos ${OCN}"/>
+ <step name="Stop-Mininet-If-Needed" env="~" exec="onos-mininet stop"/>
+
+ <step name="Wipe-Out-Data-Before" exec="onos-wipe-out"/>
+
+ <step name="Initial-Summary-Check" requires="~Wipe-Out-Data-Before"
+ exec="onos-check-summary ${OC1} [0-9]* 0 0 0"/>
+
+ <step name="Start-Mininet"
+ requires="Install-Apps,Initial-Summary-Check,Push-Topos,Stop-Mininet-If-Needed"
+ exec="onos-mininet start topos/topo att-onos.py ${ONOS_INSTANCES}"/>
+
+ <step name="Wait-For-Mininet" requires="Start-Mininet"
+ exec="onos-mininet wait 10"/>
+
+ <step name="Check-Summary" requires="Wait-For-Mininet"
+ exec="onos-check-summary ${OC1} [0-9]* 25 140 0"/>
+
+ <step name="Balance-Masters" requires="~Check-Summary" if="${OC2}"
+ exec="onos ${OC1} balance-masters"/>
+
+ <step name="Pause-For-Masters" requires="Balance-Masters" if="${OC2}"
+ exec="sleep 10"/>
+
+ <step name="Check-Flows" requires="~Pause-For-Masters,~Check-Summary"
+ exec="onos-check-flows ${OC1}"/>
+ </group>
+</scenario> \ No newline at end of file
diff --git a/framework/src/onos/tools/test/scenarios/net-smoke.xml b/framework/src/onos/tools/test/scenarios/net-smoke.xml
new file mode 100644
index 00000000..53a5729c
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-smoke.xml
@@ -0,0 +1,44 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-smoke" description="Basic network functionality smoke test">
+ <group name="Net-Smoke">
+ <import file="${ONOS_SCENARIOS}/net-setup.xml"/>
+
+ <import file="${ONOS_SCENARIOS}/net-pingall.xml" namespace="Reactive-Forwarding"/>
+ <dependency name="Reactive-Forwarding.Net-Pingall" requires="Net-Setup"/>
+
+ <import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="Reactive-Forwarding"/>
+ <dependency name="Reactive-Forwarding.Net-Link-Down-Up" requires="Net-Setup,~Reactive-Forwarding.Net-Pingall"/>
+
+ <import file="${ONOS_SCENARIOS}/net-host-intent.xml"/>
+ <dependency name="Host-Intent-Connectivity" requires="Net-Setup,~Reactive-Forwarding.Net-Link-Down-Up"/>
+
+ <import file="${ONOS_SCENARIOS}/net-point-intent.xml"/>
+ <dependency name="P2P-Intent-Connectivity" requires="Net-Setup,~Reactive-Forwarding.Net-Link-Down-Up,Host-Intent-Connectivity"/>
+
+ <import file="${ONOS_SCENARIOS}/net-rest.xml"/>
+ <dependency name="Net-REST" requires="Net-Setup,P2P-Intent-Connectivity"/>
+
+ <import file="${ONOS_SCENARIOS}/net-create-flows.xml"/>
+ <dependency name="Net-Create-Flows" requires="Net-Setup,P2P-Intent-Connectivity,Net-REST"/>
+
+ <import file="${ONOS_SCENARIOS}/net-teardown.xml"/>
+ <dependency name="Net-Teardown" requires="~Host-Intent-Connectivity,
+ ~P2P-Intent-Connectivity,
+ ~Net-REST,
+ ~Net-Create-Flows"/>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/net-teardown.xml b/framework/src/onos/tools/test/scenarios/net-teardown.xml
new file mode 100644
index 00000000..a5d93ee2
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/net-teardown.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="net-setup" description="Network teardown steps">
+ <group name="Net-Teardown">
+ <step name="Stop-Mininet" exec="onos-mininet stop"/>
+ <XXXstep name="Wipe-Out-Data-After" requires="~Stop-Mininet" exec="onos-wipe-out"/>
+ </group>
+</scenario> \ No newline at end of file
diff --git a/framework/src/onos/tools/test/scenarios/prerequisites.xml b/framework/src/onos/tools/test/scenarios/prerequisites.xml
new file mode 100644
index 00000000..650aa411
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/prerequisites.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="prerequisites" description="ONOS test pre-requisites">
+ <group name="Prerequisites">
+ <step name="Check-Environment" exec="test -n ${ONOS_ROOT} -a -n ${ONOS_NIC} -a -n ${OC1}"/>
+ <step name="Check-ONOS-Bits" exec="onos-check-bits"/>
+
+ <parallel var="${OC#}">
+ <step name="Check-Passwordless-Login-${#}"
+ exec="ssh -n -o ConnectTimeout=3 -o PasswordAuthentication=no sdn@${OC#} date"/>
+ </parallel>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/setup.xml b/framework/src/onos/tools/test/scenarios/setup.xml
new file mode 100644
index 00000000..c26c0dea
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/setup.xml
@@ -0,0 +1,47 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="setup" description="ONOS cluster setup">
+ <group name="Setup">
+ <step name="Push-Bits" exec="onos-push-bits-through-proxy" if="${OCT}"/>
+ <step name="Secure-SSH" exec="onos-secure-ssh -u ${ONOS_WEB_USER} -p ${ONOS_WEB_PASS}" if="${ONOS_USE_SSH}"/>
+
+ <parallel var="${OC#}">
+ <step name="Push-Bits-${#}" exec="onos-push-bits ${OC#}"
+ unless="${OCT}"/>
+ <step name="Uninstall-${#}" exec="onos-uninstall ${OC#}"/>
+ <step name="Kill-${#}" env="~" exec="onos-kill ${OC#}"
+ requires="Uninstall-${#}"/>
+
+ <step name="Install-${#}" exec="onos-install ${OC#}"
+ requires="Kill-${#},Push-Bits-${#},Push-Bits"/>
+
+ <dependency name="Secure-SSH" requires="Install-${#}"/>
+
+ <step name="Wait-for-Start-${#}" exec="onos-wait-for-start ${OC#}"
+ requires="Install-${#},~Secure-SSH"/>
+
+ <step name="Check-Nodes-${#}" exec="onos-check-nodes ${OC#}"
+ requires="~Wait-for-Start-${#}"/>
+ <step name="Check-Logs-${#}" exec="onos-check-logs ${OC#}"
+ requires="~Wait-for-Start-${#}"/>
+ <step name="Check-Components-${#}"
+ exec="onos-check-components ${OC#}"
+ requires="~Wait-for-Start-${#},"/>
+ <step name="Check-Apps-${#}" exec="onos-check-apps ${OC#}"
+ requires="~Wait-for-Start-${#}"/>
+ </parallel>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/shutdown.xml b/framework/src/onos/tools/test/scenarios/shutdown.xml
new file mode 100644
index 00000000..0be21647
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/shutdown.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="shutdown" description="ONOS cluster shutdown">
+ <group name="Shutdown">
+ <parallel var="${OC#}">
+ <step name="Stop-Service-${#}" exec="onos-service ${OC#} stop"/>
+ <step name="Check-Logs-${#}" exec="onos-check-logs ${OC#}"
+ requires="~Stop-Service-${#}"/>
+ </parallel>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/smoke.xml b/framework/src/onos/tools/test/scenarios/smoke.xml
new file mode 100644
index 00000000..ce8140ad
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/smoke.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="smoke" description="ONOS smoke test">
+ <import file="${ONOS_SCENARIOS}/prerequisites.xml"/>
+
+ <import file="${ONOS_SCENARIOS}/setup.xml"/>
+ <dependency name="Setup" requires="Prerequisites"/>
+
+ <import file="${ONOS_SCENARIOS}/net-smoke.xml"/>
+ <dependency name="Net-Smoke" requires="Setup"/>
+
+ <import file="${ONOS_SCENARIOS}/archetypes.xml"/>
+ <dependency name="Archetypes" requires="Setup"/>
+
+ <import file="${ONOS_SCENARIOS}/wrapup.xml"/>
+ <dependency name="Wrapup" requires="~Archetypes,~Setup,~Net-Smoke"/>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/startup.xml b/framework/src/onos/tools/test/scenarios/startup.xml
new file mode 100644
index 00000000..430d51c3
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/startup.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="startup" description="ONOS cluster startup">
+ <group name="Startup">
+ <parallel var="${OC#}">
+ <step name="Start-Service-${#}" exec="onos-service ${OC#} start"/>
+ <step name="Wait-for-Start-${#}" exec="onos-wait-for-start ${OC#}"
+ requires="Start-Service-${#}"/>
+ <step name="Check-Logs-${#}" exec="onos-check-logs ${OC#}"
+ requires="~Wait-for-Start-${#}"/>
+ </parallel>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/tar-setup.xml b/framework/src/onos/tools/test/scenarios/tar-setup.xml
new file mode 100644
index 00000000..e330b2df
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/tar-setup.xml
@@ -0,0 +1,64 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="tar-setup" description="ONOS cluster setup via onos.tar.gz">
+ <group name="Setup-Instances">
+ <step name="Push-Bits" exec="onos-push-bits-through-proxy" if="${OCT}"/>
+ <step name="Secure-SSH" exec="onos-secure-ssh -u ${ONOS_WEB_USER} -p ${ONOS_WEB_PASS}" if="${ONOS_USE_SSH}"/>
+
+ <parallel var="${OC#}">
+ <step name="Push-Bits-${#}" exec="onos-push-bits ${OC#}" unless="${OCT}"/>
+ <step name="Uninstall-${#}" exec="onos-uninstall ${OC#}"/>
+ <step name="Kill-${#}" env="~" exec="onos-kill ${OC#}" requires="Uninstall-${#}"/>
+
+ <step name="Untar-And-Run-${#}" exec="onos-untar-and-run ${OC#}"
+ requires="Kill-${#},Push-Bits-${#},Push-Bits"/>
+
+ <dependency name="Secure-SSH" requires="Untar-And-Run-${#}"/>
+
+ <step name="Wait-for-Start-${#}" exec="onos-wait-for-start ${OC#}"
+ requires="Untar-And-Run-${#},~Secure-SSH"/>
+
+ <step name="Check-Logs-${#}" exec="onos-check-logs ${OC#}"
+ requires="~Wait-for-Start-${#}"/>
+ <step name="Check-Components-${#}" exec="onos-check-components ${OC#}"
+ requires="~Wait-for-Start-${#}"/>
+ <step name="Check-Apps-${#}" exec="onos-check-apps ${OC#} drivers"
+ requires="~Wait-for-Start-${#}"/>
+
+ <step name="Check-Nodes-${#}" exec="onos-check-nodes ${OC#} ${OC#}"
+ requires="~Wait-for-Start-${#}"/>
+ </parallel>
+ </group>
+
+ <group name="Setup-Cluster" requires="Setup-Instances" unless="${NO_CLUSTER}">
+ <step name="Form-Cluster" exec="onos-form-cluster -u ${ONOS_WEB_USER} -p ${ONOS_WEB_PASS} cell"/>
+ <parallel var="${OC#}">
+ <step name="Wait-for-Start-Again-${#}" exec="onos-wait-for-start ${OC#}"
+ requires="Form-Cluster"/>
+
+ <step name="Check-Logs-Again-${#}" exec="onos-check-logs ${OC#}"
+ requires="~Wait-for-Start-Again-${#}"/>
+ <step name="Check-Components-Again-${#}" exec="onos-check-components ${OC#}"
+ requires="~Wait-for-Start-Again-${#}"/>
+ <step name="Check-Apps-Again-${#}" exec="onos-check-apps ${OC#} drivers"
+ requires="~Wait-for-Start-Again-${#}"/>
+
+ <step name="Check-Nodes-Again-${#}" exec="onos-check-nodes ${OC#}"
+ requires="~Wait-for-Start-Again-${#}"/>
+ </parallel>
+ </group>
+
+</scenario>
diff --git a/framework/src/onos/tools/test/scenarios/wrapup.xml b/framework/src/onos/tools/test/scenarios/wrapup.xml
new file mode 100644
index 00000000..e46441d6
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/wrapup.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ 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.
+ -->
+<scenario name="wrapup" description="ONOS test wrapup">
+ <group name="Wrapup">
+ <parallel var="${OC#}">
+ <step name="Final-Check-Logs-${#}" exec="onos-check-logs ${OC#}"/>
+ <step name="Fetch-Logs-${#}" exec="onos-fetch-logs ${OC#}"
+ cwd="${WORKSPACE}/tmp/stc" requires="~^"/>
+ </parallel>
+ </group>
+</scenario>
diff --git a/framework/src/onos/tools/test/topos/att-onos b/framework/src/onos/tools/test/topos/att-onos
new file mode 100755
index 00000000..9ad918a9
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/att-onos
@@ -0,0 +1,10 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Starts ATT ONOS topology in mininet.
+# -----------------------------------------------------------------------------
+cd $(dirname $0)
+if [ -n "$1" ]; then
+ sudo python att-onos.py "$@"
+else
+ sudo python att-onos.py 10.128.11.1 10.128.11.2 10.128.11.3
+fi
diff --git a/framework/src/onos/tools/test/topos/att-onos-ext.py b/framework/src/onos/tools/test/topos/att-onos-ext.py
new file mode 100644
index 00000000..a058b648
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/att-onos-ext.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+
+import sys
+
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.node import RemoteController
+from mininet.link import TCLink
+
+from attmplsext import AttMplsTopoExt
+
+setLogLevel( 'info' )
+
+def run(controllers=[ '127.0.0.1' ]):
+ net = Mininet( topo=AttMplsTopoExt(), link=TCLink, build=False, autoSetMacs=True )
+ ctrl_count = 0
+ for controllerIP in controllers:
+ net.addController( 'c%d' % ctrl_count, RemoteController, ip=controllerIP )
+ net.build()
+ net.start()
+ CLI( net )
+ net.stop()
+
+if __name__ == '__main__':
+ if len( sys.argv ) > 1:
+ controllers = sys.argv[ 1: ]
+ else:
+ print 'Usage: att-onos-ext.py <c0 IP> <c1 IP> ...'
+ exit( 1 )
+ run( controllers )
diff --git a/framework/src/onos/tools/test/topos/att-onos.py b/framework/src/onos/tools/test/topos/att-onos.py
new file mode 100644
index 00000000..109d335d
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/att-onos.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+import sys
+
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.node import RemoteController
+from mininet.link import TCLink
+
+from attmpls import AttMplsTopo
+
+setLogLevel( 'info' )
+
+def pingloop( net ):
+ setLogLevel( 'error' )
+ try:
+ while True:
+ net.ping()
+ finally:
+ setLogLevel( 'info' )
+
+def run(controllers=[ '127.0.0.1' ]):
+ Mininet.pingloop = pingloop
+ net = Mininet( topo=AttMplsTopo(), link=TCLink, build=False, autoSetMacs=True )
+ ctrl_count = 0
+ for controllerIP in controllers:
+ net.addController( 'c%d' % ctrl_count, RemoteController, ip=controllerIP )
+ ctrl_count = ctrl_count + 1
+ net.build()
+ net.start()
+ CLI( net )
+ net.stop()
+
+if __name__ == '__main__':
+ if len( sys.argv ) > 1:
+ controllers = sys.argv[ 1: ]
+ else:
+ print 'Usage: att-onos.py <c0 IP> <c1 IP> ...'
+ exit( 1 )
+ run( controllers )
diff --git a/framework/src/onos/tools/test/topos/attcli.py b/framework/src/onos/tools/test/topos/attcli.py
new file mode 100644
index 00000000..19453204
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/attcli.py
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+
+"""
+CLI for test with AttMplsTopo
+"""
+
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.util import quietRun
+from mininet.log import setLogLevel, info, output, error
+from mininet.node import RemoteController
+
+from attmplsfast import AttMplsTopo
+
+from subprocess import PIPE, STDOUT
+from time import time
+import random
+
+class IperfCLI( CLI ):
+ "CLI with iperf UDP traffic generation"
+
+ def __init__( self, net, *args, **kwargs ):
+ self.iperfs = {}
+ self.bw = '12k'
+ self.mn = net
+ self.lastbw = {} # last bandwidth reports
+ self.start()
+ quietRun( 'rm /tmp/*.iperf /tmp/*.client' )
+ CLI.__init__( self, net, *args, **kwargs )
+
+ def __del__( self ):
+ "Destructor: kill *all* iperf servers and clients!"
+ quietRun( 'pkill -9 iperf' )
+
+ def start( self ):
+ "Start iperf servers"
+ for h in sorted( self.mn.hosts ):
+ with open( '/tmp/%s.iperf' % h, 'w' ) as f:
+ cmd = 'iperf -f k -i 1 -s -u'
+ popen = h.popen( cmd, stdin=PIPE, stdout=f, stderr=STDOUT )
+ self.iperfs[ h ] = popen
+
+ def udpstart( self, h1, h2, bw):
+ "Start up a udp iperf from h1 to h2 with bandwidth bw"
+ # For udp we don't have to wait for startup
+ self.udpstop( h1 )
+ h1.cmdPrint( 'iperf -c', h2.IP(),
+ '-t 36000 -u -b', bw,
+ '1>/tmp/%s.client 2>&1 &' % h1 )
+
+ def udpstop( self, h ):
+ "udpstop h: Stop udp client on host h"
+ h.cmdPrint( 'kill %iperf && wait %iperf' )
+ h.cmdPrint( 'rm /tmp/%s.client' % h )
+
+ def do_udp( self, line ):
+ """udp h1 h2 [rate]: start a udp iperf session from h1 to h2
+ rate: udp transmit rate [12k]"""
+ args = line.split()
+ if len( args ) not in ( 2, 3 ):
+ error( 'usage: udp h1 h2 [rate]\n' )
+ return
+ h1, h2 = self.mn.get( *args[ :2 ] )
+ bw = self.bw if len( args ) == 2 else args[ 2 ]
+ self.udpstart( h1, h2, bw )
+
+ def do_stop( self, line ):
+ "stop [host | all]: Stop iperf client on host"
+ if not line or line == 'all':
+ hosts = self.mn.hosts
+ else:
+ hosts = [ self.mn.get( line ) ]
+ for h in hosts:
+ self.udpstop( h )
+
+ def do_bw( self, line ):
+ "bw: show last reported iperf server ingress bandwidth"
+ output( "Last reported iperf UDP server input bandwidth:\n" )
+ for h in self.mn.hosts:
+ lastout, lasttime = self.lastbw.get( h, ( '', 0 ) )
+ out = h.cmd( 'tail -1 /tmp/%s.iperf' % h )
+ if '---' in out or ( out == lastout and
+ time() - lasttime > 1.5 ):
+ # Stale update - don't display
+ out = '\n'
+ else:
+ self.lastbw[ h ] = ( out, time() )
+ output( '%s:' % h, out )
+
+ def do_rand( self, line ):
+ """rand [N [bw]]: Start N random flows (default: 10)
+ at the given bandwidth (default: 12k)
+ Note: this may replace existing flows"""
+ args = line.split()
+ N = 10
+ if args:
+ try:
+ N = int( args[ 0 ] )
+ except:
+ error( 'please specify an integer' )
+ return
+ output( 'Starting/restarting', N, 'random flows...\n' )
+ bw = self.bw if len( args ) < 2 else args[ 1 ]
+ servers = random.sample( self.mn.hosts, N )
+ clients = []
+ for server in servers:
+ allclients = [ h for h in self.mn.hosts
+ if h not in clients ]
+ client = random.choice( allclients )
+ clients.append( client )
+ self.udpstart( client, server, bw )
+
+ def do_jobs( self, line ):
+ "jobs: List iperf jobs"
+ output( "Currently running jobs:\n" )
+ for h in self.mn.hosts:
+ output( '%s:' % h, h.cmd( 'jobs' ).strip(), '\n' )
+
+
+def run( Topo=AttMplsTopo ):
+ "Create network and run CLI"
+ topo = Topo()
+ net = Mininet( topo=topo, controller=RemoteController )
+ net.start()
+ info( '\n### Welcome to the custom iperf udp CLI!\n'
+ '###\n'
+ '### udp h1 h2 [bw] start iperf udp from h1 to h2\n'
+ '### stop h1 h2 stop iperf udp from h1 to h2\n'
+ '### rand [N] start/restart N random udp iperfs\n'
+ '### bw show last reported udp ingress bandwidth\n'
+ '### jobs list iperf jobs\n\n' )
+ IperfCLI( net )
+ net.stop()
+
+
+if __name__ == '__main__':
+ setLogLevel( 'info' )
+ run()
diff --git a/framework/src/onos/tools/test/topos/attmpls-intents b/framework/src/onos/tools/test/topos/attmpls-intents
new file mode 100755
index 00000000..f4624595
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/attmpls-intents
@@ -0,0 +1,8 @@
+#!/bin/bash
+# Creates some sample intents
+onos $OCI add-host-intent 00:00:00:00:00:15/-1 00:00:00:00:00:0b/-1
+onos $OCI add-host-intent 00:00:00:00:00:15/-1 00:00:00:00:00:0e/-1
+onos $OCI add-host-intent 00:00:00:00:00:10/-1 00:00:00:00:00:0a/-1
+onos $OCI add-host-intent 00:00:00:00:00:09/-1 00:00:00:00:00:0c/-1
+onos $OCI add-host-intent 00:00:00:00:00:02/-1 00:00:00:00:00:0e/-1
+onos $OCI add-host-intent 00:00:00:00:00:11/-1 00:00:00:00:00:05/-1
diff --git a/framework/src/onos/tools/test/topos/attmpls.json b/framework/src/onos/tools/test/topos/attmpls.json
new file mode 100644
index 00000000..096a78fa
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/attmpls.json
@@ -0,0 +1,58 @@
+{
+ "devices": [
+ { "alias": "s1", "uri": "of:0000000000000001", "mac": "000000000001", "annotations": { "name": "CMBR", "latitude": 42.373730, "longitude": -71.109734 }, "type": "SWITCH" },
+ { "alias": "s2", "uri": "of:0000000000000002", "mac": "000000000002", "annotations": { "name": "CHCG", "latitude": 41.877461, "longitude": -87.642892 }, "type": "SWITCH" },
+ { "alias": "s3", "uri": "of:0000000000000003", "mac": "000000000003", "annotations": { "name": "CLEV", "latitude": 41.498928, "longitude": -81.695217 }, "type": "SWITCH" },
+ { "alias": "s4", "uri": "of:0000000000000004", "mac": "000000000004", "annotations": { "name": "RLGH", "latitude": 35.780150, "longitude": -78.644026 }, "type": "SWITCH" },
+ { "alias": "s5", "uri": "of:0000000000000005", "mac": "000000000005", "annotations": { "name": "ATLN", "latitude": 33.749017, "longitude": -84.394168 }, "type": "SWITCH" },
+ { "alias": "s6", "uri": "of:0000000000000006", "mac": "000000000006", "annotations": { "name": "PHLA", "latitude": 39.952906, "longitude": -75.172278 }, "type": "SWITCH" },
+ { "alias": "s7", "uri": "of:0000000000000007", "mac": "000000000007", "annotations": { "name": "WASH", "latitude": 38.906696, "longitude": -77.035509 }, "type": "SWITCH" },
+ { "alias": "s8", "uri": "of:0000000000000008", "mac": "000000000008", "annotations": { "name": "NSVL", "latitude": 36.166410, "longitude": -86.787305 }, "type": "SWITCH" },
+ { "alias": "s9", "uri": "of:0000000000000009", "mac": "000000000009", "annotations": { "name": "STLS", "latitude": 38.626418, "longitude": -90.198143 }, "type": "SWITCH" },
+ { "alias": "s10", "uri": "of:000000000000000a", "mac": "00000000000a", "annotations": { "name": "NWOR", "latitude": 29.951475, "longitude": -90.078434 }, "type": "SWITCH" },
+ { "alias": "s11", "uri": "of:000000000000000b", "mac": "00000000000b", "annotations": { "name": "HSTN", "latitude": 29.763249, "longitude": -95.368332 }, "type": "SWITCH" },
+ { "alias": "s12", "uri": "of:000000000000000c", "mac": "00000000000c", "annotations": { "name": "SNAN", "latitude": 29.424331, "longitude": -98.491745 }, "type": "SWITCH" },
+ { "alias": "s13", "uri": "of:000000000000000d", "mac": "00000000000d", "annotations": { "name": "DLLS", "latitude": 32.777665, "longitude": -96.802064 }, "type": "SWITCH" },
+ { "alias": "s14", "uri": "of:000000000000000e", "mac": "00000000000e", "annotations": { "name": "ORLD", "latitude": 28.538641, "longitude": -81.381110 }, "type": "SWITCH" },
+ { "alias": "s15", "uri": "of:000000000000000f", "mac": "00000000000f", "annotations": { "name": "DNVR", "latitude": 39.736623, "longitude": -104.984887 }, "type": "SWITCH" },
+ { "alias": "s16", "uri": "of:0000000000000010", "mac": "000000000010", "annotations": { "name": "KSCY", "latitude": 39.100725, "longitude": -94.581228 }, "type": "SWITCH" },
+ { "alias": "s17", "uri": "of:0000000000000011", "mac": "000000000011", "annotations": { "name": "SNFN", "latitude": 37.779751, "longitude": -122.409791 }, "type": "SWITCH" },
+ { "alias": "s18", "uri": "of:0000000000000012", "mac": "000000000012", "annotations": { "name": "SCRM", "latitude": 38.581001, "longitude": -121.497844 }, "type": "SWITCH" },
+ { "alias": "s19", "uri": "of:0000000000000013", "mac": "000000000013", "annotations": { "name": "PTLD", "latitude": 45.523317, "longitude": -122.677768 }, "type": "SWITCH" },
+ { "alias": "s20", "uri": "of:0000000000000014", "mac": "000000000014", "annotations": { "name": "STTL", "latitude": 47.607326, "longitude": -122.331786 }, "type": "SWITCH" },
+ { "alias": "s21", "uri": "of:0000000000000015", "mac": "000000000015", "annotations": { "name": "SLKC", "latitude": 40.759577, "longitude": -111.895079 }, "type": "SWITCH" },
+ { "alias": "s22", "uri": "of:0000000000000016", "mac": "000000000016", "annotations": { "name": "LA03", "latitude": 34.056346, "longitude": -118.235951 }, "type": "SWITCH" },
+ { "alias": "s23", "uri": "of:0000000000000017", "mac": "000000000017", "annotations": { "name": "SNDG", "latitude": 32.714564, "longitude": -117.153528 }, "type": "SWITCH" },
+ { "alias": "s24", "uri": "of:0000000000000018", "mac": "000000000018", "annotations": { "name": "PHNX", "latitude": 33.448289, "longitude": -112.076299 }, "type": "SWITCH" },
+ { "alias": "s25", "uri": "of:0000000000000019", "mac": "000000000019", "annotations": { "name": "NY54", "latitude": 40.728270, "longitude": -73.994483 }, "type": "SWITCH" }
+ ],
+
+ "hosts": [
+ { "alias": "h1", "mac": "00:00:00:00:00:01", "vlan": -1, "location": "of:0000000000000001/1", "ip": "10.0.0.1", "annotations": { "name": "CMBR", "latitude": 43.355715, "longitude": -69.528243 } },
+ { "alias": "h2", "mac": "00:00:00:00:00:02", "vlan": -1, "location": "of:0000000000000002/1", "ip": "10.0.0.2", "annotations": { "name": "CHCG", "latitude": 43.632679, "longitude": -88.772526 } },
+ { "alias": "h3", "mac": "00:00:00:00:00:03", "vlan": -1, "location": "of:0000000000000003/1", "ip": "10.0.0.3", "annotations": { "name": "CLEV", "latitude": 42.756945, "longitude": -79.831317 } },
+ { "alias": "h4", "mac": "00:00:00:00:00:04", "vlan": -1, "location": "of:0000000000000004/1", "ip": "10.0.0.4", "annotations": { "name": "RLGH", "latitude": 36.972249, "longitude": -76.667163 } },
+ { "alias": "h5", "mac": "00:00:00:00:00:05", "vlan": -1, "location": "of:0000000000000005/1", "ip": "10.0.0.5", "annotations": { "name": "ATLN", "latitude": 35.427493, "longitude": -83.885831 } },
+ { "alias": "h6", "mac": "00:00:00:00:00:06", "vlan": -1, "location": "of:0000000000000006/1", "ip": "10.0.0.6", "annotations": { "name": "PHLA", "latitude": 39.208113, "longitude": -73.421341 } },
+ { "alias": "h7", "mac": "00:00:00:00:00:07", "vlan": -1, "location": "of:0000000000000007/1", "ip": "10.0.0.7", "annotations": { "name": "WASH", "latitude": 40.133860, "longitude": -79.238299 } },
+ { "alias": "h8", "mac": "00:00:00:00:00:08", "vlan": -1, "location": "of:0000000000000008/1", "ip": "10.0.0.8", "annotations": { "name": "NSVL", "latitude": 37.407589, "longitude": -84.415068 } },
+ { "alias": "h9", "mac": "00:00:00:00:00:09", "vlan": -1, "location": "of:0000000000000009/1", "ip": "10.0.0.9", "annotations": { "name": "STLS", "latitude": 40.066810, "longitude": -90.932405 } },
+ { "alias": "h10", "mac": "00:00:00:00:00:0a", "vlan": -1, "location": "of:000000000000000a/1", "ip": "10.0.0.10", "annotations": { "name": "NWOR", "latitude": 31.470982, "longitude": -88.779353 } },
+ { "alias": "h11", "mac": "00:00:00:00:00:0b", "vlan": -1, "location": "of:000000000000000b/1", "ip": "10.0.0.11", "annotations": { "name": "HSTN", "latitude": 31.136858, "longitude": -94.351656 } },
+ { "alias": "h12", "mac": "00:00:00:00:00:0c", "vlan": -1, "location": "of:000000000000000c/1", "ip": "10.0.0.12", "annotations": { "name": "SNAN", "latitude": 28.040975, "longitude": -99.169527 } },
+ { "alias": "h13", "mac": "00:00:00:00:00:0d", "vlan": -1, "location": "of:000000000000000d/1", "ip": "10.0.0.13", "annotations": { "name": "DLLS", "latitude": 31.899825, "longitude": -99.287263 } },
+ { "alias": "h14", "mac": "00:00:00:00:00:0e", "vlan": -1, "location": "of:000000000000000e/1", "ip": "10.0.0.14", "annotations": { "name": "ORLD", "latitude": 26.670509, "longitude": -81.291920 } },
+ { "alias": "h15", "mac": "00:00:00:00:00:0f", "vlan": -1, "location": "of:000000000000000f/1", "ip": "10.0.0.15", "annotations": { "name": "DNVR", "latitude": 40.888148, "longitude": -103.459878 } },
+ { "alias": "h16", "mac": "00:00:00:00:00:10", "vlan": -1, "location": "of:0000000000000010/1", "ip": "10.0.0.16", "annotations": { "name": "KSCY", "latitude": 40.545088, "longitude": -93.734002 } },
+ { "alias": "h17", "mac": "00:00:00:00:00:11", "vlan": -1, "location": "of:0000000000000011/1", "ip": "10.0.0.17", "annotations": { "name": "SNFN", "latitude": 39.081743, "longitude": -124.330172 } },
+ { "alias": "h18", "mac": "00:00:00:00:00:12", "vlan": -1, "location": "of:0000000000000012/1", "ip": "10.0.0.18", "annotations": { "name": "SCRM", "latitude": 40.107468, "longitude": -120.424689 } },
+ { "alias": "h19", "mac": "00:00:00:00:00:13", "vlan": -1, "location": "of:0000000000000013/1", "ip": "10.0.0.19", "annotations": { "name": "PTLD", "latitude": 44.383051, "longitude": -124.767594 } },
+ { "alias": "h20", "mac": "00:00:00:00:00:14", "vlan": -1, "location": "of:0000000000000014/1", "ip": "10.0.0.20", "annotations": { "name": "STTL", "latitude": 48.832627, "longitude": -120.298441 } },
+ { "alias": "h21", "mac": "00:00:00:00:00:15", "vlan": -1, "location": "of:0000000000000015/1", "ip": "10.0.0.21", "annotations": { "name": "SLKC", "latitude": 42.301734, "longitude": -111.217297 } },
+ { "alias": "h22", "mac": "00:00:00:00:00:16", "vlan": -1, "location": "of:0000000000000016/1", "ip": "10.0.0.22", "annotations": { "name": "LA03", "latitude": 33.224634, "longitude": -121.532943 } },
+ { "alias": "h23", "mac": "00:00:00:00:00:17", "vlan": -1, "location": "of:0000000000000017/1", "ip": "10.0.0.23", "annotations": { "name": "SNDG", "latitude": 31.834607, "longitude": -118.847982 } },
+ { "alias": "h24", "mac": "00:00:00:00:00:18", "vlan": -1, "location": "of:0000000000000018/1", "ip": "10.0.0.24", "annotations": { "name": "PHNX", "latitude": 34.662290, "longitude": -110.946662 } },
+ { "alias": "h25", "mac": "00:00:00:00:00:19", "vlan": -1, "location": "of:0000000000000019/1", "ip": "10.0.0.25", "annotations": { "name": "NY54", "latitude": 42.395459, "longitude": -75.293563 } }
+ ]
+
+}
diff --git a/framework/src/onos/tools/test/topos/attmpls.py b/framework/src/onos/tools/test/topos/attmpls.py
new file mode 100644
index 00000000..4fe71154
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/attmpls.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+
+"""
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+
+class AttMplsTopo( Topo ):
+ "Internet Topology Zoo Specimen."
+
+ def __init__( self ):
+ "Create a topology."
+
+ # Initialize Topology
+ Topo.__init__( self )
+
+ # add nodes, switches first...
+ NY54 = self.addSwitch( 's25' ) # 40.728270, -73.994483
+ CMBR = self.addSwitch( 's1' ) # 42.373730, -71.109734
+ CHCG = self.addSwitch( 's2', protocols='OpenFlow13' ) # 41.877461, -87.642892
+ CLEV = self.addSwitch( 's3' ) # 41.498928, -81.695217
+ RLGH = self.addSwitch( 's4' ) # 35.780150, -78.644026
+ ATLN = self.addSwitch( 's5' ) # 33.749017, -84.394168
+ PHLA = self.addSwitch( 's6' ) # 39.952906, -75.172278
+ WASH = self.addSwitch( 's7' ) # 38.906696, -77.035509
+ NSVL = self.addSwitch( 's8' ) # 36.166410, -86.787305
+ STLS = self.addSwitch( 's9', protocols='OpenFlow13' ) # 38.626418, -90.198143
+ NWOR = self.addSwitch( 's10' ) # 29.951475, -90.078434
+ HSTN = self.addSwitch( 's11' ) # 29.763249, -95.368332
+ SNAN = self.addSwitch( 's12' ) # 29.424331, -98.491745
+ DLLS = self.addSwitch( 's13' ) # 32.777665, -96.802064
+ ORLD = self.addSwitch( 's14' ) # 28.538641, -81.381110
+ DNVR = self.addSwitch( 's15' ) # 39.736623, -104.984887
+ KSCY = self.addSwitch( 's16' ) # 39.100725, -94.581228
+ SNFN = self.addSwitch( 's17' ) # 37.779751, -122.409791
+ SCRM = self.addSwitch( 's18' ) # 38.581001, -121.497844
+ PTLD = self.addSwitch( 's19' ) # 45.523317, -122.677768
+ STTL = self.addSwitch( 's20' ) # 47.607326, -122.331786
+ SLKC = self.addSwitch( 's21' ) # 40.759577, -111.895079
+ LA03 = self.addSwitch( 's22', protocols='OpenFlow13' ) # 34.056346, -118.235951
+ SNDG = self.addSwitch( 's23' ) # 32.714564, -117.153528
+ PHNX = self.addSwitch( 's24' ) # 33.448289, -112.076299
+
+ # ... and now hosts
+ NY54_host = self.addHost( 'h25' )
+ CMBR_host = self.addHost( 'h1' )
+ CHCG_host = self.addHost( 'h2' )
+ CLEV_host = self.addHost( 'h3' )
+ RLGH_host = self.addHost( 'h4' )
+ ATLN_host = self.addHost( 'h5' )
+ PHLA_host = self.addHost( 'h6' )
+ WASH_host = self.addHost( 'h7' )
+ NSVL_host = self.addHost( 'h8' )
+ STLS_host = self.addHost( 'h9' )
+ NWOR_host = self.addHost( 'h10' )
+ HSTN_host = self.addHost( 'h11' )
+ SNAN_host = self.addHost( 'h12' )
+ DLLS_host = self.addHost( 'h13' )
+ ORLD_host = self.addHost( 'h14' )
+ DNVR_host = self.addHost( 'h15' )
+ KSCY_host = self.addHost( 'h16' )
+ SNFN_host = self.addHost( 'h17' )
+ SCRM_host = self.addHost( 'h18' )
+ PTLD_host = self.addHost( 'h19' )
+ STTL_host = self.addHost( 'h20' )
+ SLKC_host = self.addHost( 'h21' )
+ LA03_host = self.addHost( 'h22' )
+ SNDG_host = self.addHost( 'h23' )
+ PHNX_host = self.addHost( 'h24' )
+
+ # add edges between switch and corresponding host
+ self.addLink( NY54 , NY54_host )
+ self.addLink( CMBR , CMBR_host )
+ self.addLink( CHCG , CHCG_host )
+ self.addLink( CLEV , CLEV_host )
+ self.addLink( RLGH , RLGH_host )
+ self.addLink( ATLN , ATLN_host )
+ self.addLink( PHLA , PHLA_host )
+ self.addLink( WASH , WASH_host )
+ self.addLink( NSVL , NSVL_host )
+ self.addLink( STLS , STLS_host )
+ self.addLink( NWOR , NWOR_host )
+ self.addLink( HSTN , HSTN_host )
+ self.addLink( SNAN , SNAN_host )
+ self.addLink( DLLS , DLLS_host )
+ self.addLink( ORLD , ORLD_host )
+ self.addLink( DNVR , DNVR_host )
+ self.addLink( KSCY , KSCY_host )
+ self.addLink( SNFN , SNFN_host )
+ self.addLink( SCRM , SCRM_host )
+ self.addLink( PTLD , PTLD_host )
+ self.addLink( STTL , STTL_host )
+ self.addLink( SLKC , SLKC_host )
+ self.addLink( LA03 , LA03_host )
+ self.addLink( SNDG , SNDG_host )
+ self.addLink( PHNX , PHNX_host )
+
+ # add edges between switches
+ self.addLink( NY54 , CMBR, bw=10, delay='0.979030824185ms')
+ self.addLink( NY54 , CMBR, bw=10, delay='0.979030824185ms')
+ self.addLink( NY54 , CMBR, bw=10, delay='0.979030824185ms')
+ self.addLink( NY54 , CHCG, bw=10, delay='0.806374975652ms')
+ self.addLink( NY54 , PHLA, bw=10, delay='0.686192970166ms')
+ self.addLink( NY54 , PHLA, bw=10, delay='0.686192970166ms')
+ self.addLink( NY54 , WASH, bw=10, delay='0.605826192092ms')
+ self.addLink( CMBR , PHLA, bw=10, delay='1.4018238197ms')
+ self.addLink( CHCG , CLEV, bw=10, delay='0.232315346482ms')
+ self.addLink( CHCG , PHLA, bw=10, delay='1.07297714274ms')
+ self.addLink( CHCG , STLS, bw=10, delay='1.12827896944ms')
+ self.addLink( CHCG , DNVR, bw=10, delay='1.35964770335ms')
+ self.addLink( CHCG , KSCY, bw=10, delay='1.5199778541ms')
+ self.addLink( CHCG , KSCY, bw=10, delay='1.5199778541ms')
+ self.addLink( CHCG , SNFN, bw=10, delay='0.620743405435ms')
+ self.addLink( CHCG , STTL, bw=10, delay='0.93027212534ms')
+ self.addLink( CHCG , SLKC, bw=10, delay='0.735621751348ms')
+ self.addLink( CLEV , NSVL, bw=10, delay='0.523419372248ms')
+ self.addLink( CLEV , STLS, bw=10, delay='1.00360290845ms')
+ self.addLink( CLEV , PHLA, bw=10, delay='0.882912133249ms')
+ self.addLink( RLGH , ATLN, bw=10, delay='1.1644489729ms')
+ self.addLink( RLGH , WASH, bw=10, delay='1.48176810502ms')
+ self.addLink( ATLN , WASH, bw=10, delay='0.557636936322ms')
+ self.addLink( ATLN , NSVL, bw=10, delay='1.32869749865ms')
+ self.addLink( ATLN , STLS, bw=10, delay='0.767705554748ms')
+ self.addLink( ATLN , DLLS, bw=10, delay='0.544782086448ms')
+ self.addLink( ATLN , DLLS, bw=10, delay='0.544782086448ms')
+ self.addLink( ATLN , DLLS, bw=10, delay='0.544782086448ms')
+ self.addLink( ATLN , ORLD, bw=10, delay='1.46119152532ms')
+ self.addLink( PHLA , WASH, bw=10, delay='0.372209320106ms')
+ self.addLink( NSVL , STLS, bw=10, delay='1.43250491305ms')
+ self.addLink( NSVL , DLLS, bw=10, delay='1.67698215288ms')
+ self.addLink( STLS , DLLS, bw=10, delay='0.256389964194ms')
+ self.addLink( STLS , KSCY, bw=10, delay='0.395511571791ms')
+ self.addLink( STLS , LA03, bw=10, delay='0.257085227363ms')
+ self.addLink( NWOR , HSTN, bw=10, delay='0.0952906633914ms')
+ self.addLink( NWOR , DLLS, bw=10, delay='1.60231329739ms')
+ self.addLink( NWOR , ORLD, bw=10, delay='0.692731063896ms')
+ self.addLink( HSTN , SNAN, bw=10, delay='0.284150653798ms')
+ self.addLink( HSTN , DLLS, bw=10, delay='1.65690128332ms')
+ self.addLink( HSTN , ORLD, bw=10, delay='0.731886304782ms')
+ self.addLink( SNAN , PHNX, bw=10, delay='1.34258627257ms')
+ self.addLink( SNAN , DLLS, bw=10, delay='1.50063532341ms')
+ self.addLink( DLLS , DNVR, bw=10, delay='0.251471593235ms')
+ self.addLink( DLLS , DNVR, bw=10, delay='0.251471593235ms')
+ self.addLink( DLLS , KSCY, bw=10, delay='0.18026026737ms')
+ self.addLink( DLLS , KSCY, bw=10, delay='0.18026026737ms')
+ self.addLink( DLLS , SNFN, bw=10, delay='0.74304274592ms')
+ self.addLink( DLLS , LA03, bw=10, delay='0.506439293357ms')
+ self.addLink( DLLS , LA03, bw=10, delay='0.506439293357ms')
+ self.addLink( DNVR , KSCY, bw=10, delay='0.223328790403ms')
+ self.addLink( DNVR , SNFN, bw=10, delay='0.889017541903ms')
+ self.addLink( DNVR , SNFN, bw=10, delay='0.889017541903ms')
+ self.addLink( DNVR , SLKC, bw=10, delay='0.631898982721ms')
+ self.addLink( KSCY , SNFN, bw=10, delay='0.922778522233ms')
+ self.addLink( SNFN , SCRM, bw=10, delay='0.630352278097ms')
+ self.addLink( SNFN , PTLD, bw=10, delay='0.828572513655ms')
+ self.addLink( SNFN , STTL, bw=10, delay='1.54076081649ms')
+ self.addLink( SNFN , SLKC, bw=10, delay='0.621507502625ms')
+ self.addLink( SNFN , LA03, bw=10, delay='0.602936230151ms')
+ self.addLink( SNFN , LA03, bw=10, delay='0.602936230151ms')
+ self.addLink( SNFN , LA03, bw=10, delay='0.602936230151ms')
+ self.addLink( SCRM , SLKC, bw=10, delay='0.461350343644ms')
+ self.addLink( PTLD , STTL, bw=10, delay='1.17591515181ms')
+ self.addLink( SLKC , LA03, bw=10, delay='0.243225267023ms')
+ self.addLink( LA03 , SNDG, bw=10, delay='0.681264950821ms')
+ self.addLink( LA03 , SNDG, bw=10, delay='0.681264950821ms')
+ self.addLink( LA03 , PHNX, bw=10, delay='0.343709457969ms')
+ self.addLink( LA03 , PHNX, bw=10, delay='0.343709457969ms')
+ self.addLink( SNDG , PHNX, bw=10, delay='0.345064487693ms')
+
+topos = { 'att': ( lambda: AttMplsTopo() ) }
diff --git a/framework/src/onos/tools/test/topos/attmplsfast.py b/framework/src/onos/tools/test/topos/attmplsfast.py
new file mode 100644
index 00000000..7f904462
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/attmplsfast.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+
+"""
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+
+class AttMplsTopo( Topo ):
+ "Internet Topology Zoo Specimen."
+
+ def build( self ):
+ "Create a topology."
+
+ # add nodes, switches first...
+ CMBR = self.addSwitch( 's1' ) # 42.373730, -71.109734
+ CHCG = self.addSwitch( 's2' ) # 41.877461, -87.642892
+ CLEV = self.addSwitch( 's3' ) # 41.498928, -81.695217
+ RLGH = self.addSwitch( 's4' ) # 35.780150, -78.644026
+ ATLN = self.addSwitch( 's5' ) # 33.749017, -84.394168
+ PHLA = self.addSwitch( 's6' ) # 39.952906, -75.172278
+ WASH = self.addSwitch( 's7' ) # 38.906696, -77.035509
+ NSVL = self.addSwitch( 's8' ) # 36.166410, -86.787305
+ STLS = self.addSwitch( 's9' ) # 38.626418, -90.198143
+ NWOR = self.addSwitch( 's10' ) # 29.951475, -90.078434
+ HSTN = self.addSwitch( 's11' ) # 29.763249, -95.368332
+ SNAN = self.addSwitch( 's12' ) # 29.424331, -98.491745
+ DLLS = self.addSwitch( 's13' ) # 32.777665, -96.802064
+ ORLD = self.addSwitch( 's14' ) # 28.538641, -81.381110
+ DNVR = self.addSwitch( 's15' ) # 39.736623, -104.984887
+ KSCY = self.addSwitch( 's16' ) # 39.100725, -94.581228
+ SNFN = self.addSwitch( 's17' ) # 37.779751, -122.409791
+ SCRM = self.addSwitch( 's18' ) # 38.581001, -121.497844
+ PTLD = self.addSwitch( 's19' ) # 45.523317, -122.677768
+ STTL = self.addSwitch( 's20' ) # 47.607326, -122.331786
+ SLKC = self.addSwitch( 's21' ) # 40.759577, -111.895079
+ LA03 = self.addSwitch( 's22' ) # 34.056346, -118.235951
+ SNDG = self.addSwitch( 's23' ) # 32.714564, -117.153528
+ PHNX = self.addSwitch( 's24' ) # 33.448289, -112.076299
+ NY54 = self.addSwitch( 's25' ) # 40.728270, -73.994483
+
+ # ... and now hosts
+ CMBR_host = self.addHost( 'h1' )
+ CHCG_host = self.addHost( 'h2' )
+ CLEV_host = self.addHost( 'h3' )
+ RLGH_host = self.addHost( 'h4' )
+ ATLN_host = self.addHost( 'h5' )
+ PHLA_host = self.addHost( 'h6' )
+ WASH_host = self.addHost( 'h7' )
+ NSVL_host = self.addHost( 'h8' )
+ STLS_host = self.addHost( 'h9' )
+ NWOR_host = self.addHost( 'h10' )
+ HSTN_host = self.addHost( 'h11' )
+ SNAN_host = self.addHost( 'h12' )
+ DLLS_host = self.addHost( 'h13' )
+ ORLD_host = self.addHost( 'h14' )
+ DNVR_host = self.addHost( 'h15' )
+ KSCY_host = self.addHost( 'h16' )
+ SNFN_host = self.addHost( 'h17' )
+ SCRM_host = self.addHost( 'h18' )
+ PTLD_host = self.addHost( 'h19' )
+ STTL_host = self.addHost( 'h20' )
+ SLKC_host = self.addHost( 'h21' )
+ LA03_host = self.addHost( 'h22' )
+ SNDG_host = self.addHost( 'h23' )
+ PHNX_host = self.addHost( 'h24' )
+ NY54_host = self.addHost( 'h25' )
+
+ # add edges between switch and corresponding host
+ self.addLink( NY54 , NY54_host )
+ self.addLink( CMBR , CMBR_host )
+ self.addLink( CHCG , CHCG_host )
+ self.addLink( CLEV , CLEV_host )
+ self.addLink( RLGH , RLGH_host )
+ self.addLink( ATLN , ATLN_host )
+ self.addLink( PHLA , PHLA_host )
+ self.addLink( WASH , WASH_host )
+ self.addLink( NSVL , NSVL_host )
+ self.addLink( STLS , STLS_host )
+ self.addLink( NWOR , NWOR_host )
+ self.addLink( HSTN , HSTN_host )
+ self.addLink( SNAN , SNAN_host )
+ self.addLink( DLLS , DLLS_host )
+ self.addLink( ORLD , ORLD_host )
+ self.addLink( DNVR , DNVR_host )
+ self.addLink( KSCY , KSCY_host )
+ self.addLink( SNFN , SNFN_host )
+ self.addLink( SCRM , SCRM_host )
+ self.addLink( PTLD , PTLD_host )
+ self.addLink( STTL , STTL_host )
+ self.addLink( SLKC , SLKC_host )
+ self.addLink( LA03 , LA03_host )
+ self.addLink( SNDG , SNDG_host )
+ self.addLink( PHNX , PHNX_host )
+
+ # add edges between switches
+ self.addLink( NY54 , CMBR)
+ self.addLink( NY54 , CMBR)
+ self.addLink( NY54 , CMBR)
+ self.addLink( NY54 , CHCG)
+ self.addLink( NY54 , PHLA)
+ self.addLink( NY54 , PHLA)
+ self.addLink( NY54 , WASH)
+ self.addLink( CMBR , PHLA)
+ self.addLink( CHCG , CLEV)
+ self.addLink( CHCG , PHLA)
+ self.addLink( CHCG , STLS)
+ self.addLink( CHCG , DNVR)
+ self.addLink( CHCG , KSCY)
+ self.addLink( CHCG , KSCY)
+ self.addLink( CHCG , SNFN)
+ self.addLink( CHCG , STTL)
+ self.addLink( CHCG , SLKC)
+ self.addLink( CLEV , NSVL)
+ self.addLink( CLEV , STLS)
+ self.addLink( CLEV , PHLA)
+ self.addLink( RLGH , ATLN)
+ self.addLink( RLGH , WASH)
+ self.addLink( ATLN , WASH)
+ self.addLink( ATLN , NSVL)
+ self.addLink( ATLN , STLS)
+ self.addLink( ATLN , DLLS)
+ self.addLink( ATLN , DLLS)
+ self.addLink( ATLN , DLLS)
+ self.addLink( ATLN , ORLD)
+ self.addLink( PHLA , WASH)
+ self.addLink( NSVL , STLS)
+ self.addLink( NSVL , DLLS)
+ self.addLink( STLS , DLLS)
+ self.addLink( STLS , KSCY)
+ self.addLink( STLS , LA03)
+ self.addLink( NWOR , HSTN)
+ self.addLink( NWOR , DLLS)
+ self.addLink( NWOR , ORLD)
+ self.addLink( HSTN , SNAN)
+ self.addLink( HSTN , DLLS)
+ self.addLink( HSTN , ORLD)
+ self.addLink( SNAN , PHNX)
+ self.addLink( SNAN , DLLS)
+ self.addLink( DLLS , DNVR)
+ self.addLink( DLLS , DNVR)
+ self.addLink( DLLS , KSCY)
+ self.addLink( DLLS , KSCY)
+ self.addLink( DLLS , SNFN)
+ self.addLink( DLLS , LA03)
+ self.addLink( DLLS , LA03)
+ self.addLink( DNVR , KSCY)
+ self.addLink( DNVR , SNFN)
+ self.addLink( DNVR , SNFN)
+ self.addLink( DNVR , SLKC)
+ self.addLink( KSCY , SNFN)
+ self.addLink( SNFN , SCRM)
+ self.addLink( SNFN , PTLD)
+ self.addLink( SNFN , STTL)
+ self.addLink( SNFN , SLKC)
+ self.addLink( SNFN , LA03)
+ self.addLink( SNFN , LA03)
+ self.addLink( SNFN , LA03)
+ self.addLink( SCRM , SLKC)
+ self.addLink( PTLD , STTL)
+ self.addLink( SLKC , LA03)
+ self.addLink( LA03 , SNDG)
+ self.addLink( LA03 , SNDG)
+ self.addLink( LA03 , PHNX)
+ self.addLink( LA03 , PHNX)
+ self.addLink( SNDG , PHNX)
+
+topos = { 'att': ( lambda: AttMplsTopo() ) }
diff --git a/framework/src/onos/tools/test/topos/chordal.py b/framework/src/onos/tools/test/topos/chordal.py
new file mode 100644
index 00000000..22f9ca19
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/chordal.py
@@ -0,0 +1,402 @@
+"""
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+
+class chordalTopo( Topo ):
+
+ def __init__( self, **opts ):
+ "Create a topology."
+
+ # Initialize Topology
+ Topo.__init__( self, **opts )
+
+ # add nodes, switches first...
+ s1 = self.addSwitch( 's1' )
+ s2 = self.addSwitch( 's2' )
+ s3 = self.addSwitch( 's3' )
+ s4 = self.addSwitch( 's4' )
+ s5 = self.addSwitch( 's5' )
+ s6 = self.addSwitch( 's6' )
+ s7 = self.addSwitch( 's7' )
+ s8 = self.addSwitch( 's8' )
+ s9 = self.addSwitch( 's9' )
+ s10 = self.addSwitch( 's10' )
+ s11 = self.addSwitch( 's11' )
+ s12 = self.addSwitch( 's12' )
+ s13 = self.addSwitch( 's13' )
+ s14 = self.addSwitch( 's14' )
+ s15 = self.addSwitch( 's15' )
+ s16 = self.addSwitch( 's16' )
+ s17 = self.addSwitch( 's17' )
+ s18 = self.addSwitch( 's18' )
+ s19 = self.addSwitch( 's19' )
+ s20 = self.addSwitch( 's20' )
+ s21 = self.addSwitch( 's21' )
+ s22 = self.addSwitch( 's22' )
+ s23 = self.addSwitch( 's23' )
+ s24 = self.addSwitch( 's24' )
+ s25 = self.addSwitch( 's25' )
+
+ # ... and now hosts
+ s1_host = self.addHost( 'h1' )
+ s2_host = self.addHost( 'h2' )
+ s3_host = self.addHost( 'h3' )
+ s4_host = self.addHost( 'h4' )
+ s5_host = self.addHost( 'h5' )
+ s6_host = self.addHost( 'h6' )
+ s7_host = self.addHost( 'h7' )
+ s8_host = self.addHost( 'h8' )
+ s9_host = self.addHost( 'h9' )
+ s10_host = self.addHost( 'h10' )
+ s11_host = self.addHost( 'h11' )
+ s12_host = self.addHost( 'h12' )
+ s13_host = self.addHost( 'h13' )
+ s14_host = self.addHost( 'h14' )
+ s15_host = self.addHost( 'h15' )
+ s16_host = self.addHost( 'h16' )
+ s17_host = self.addHost( 'h17' )
+ s18_host = self.addHost( 'h18' )
+ s19_host = self.addHost( 'h19' )
+ s20_host = self.addHost( 'h20' )
+ s21_host = self.addHost( 'h21' )
+ s22_host = self.addHost( 'h22' )
+ s23_host = self.addHost( 'h23' )
+ s24_host = self.addHost( 'h24' )
+ s25_host = self.addHost( 'h25' )
+
+ # add edges between switch and corresponding host
+ self.addLink( s1 , s1_host )
+ self.addLink( s2 , s2_host )
+ self.addLink( s3 , s3_host )
+ self.addLink( s4 , s4_host )
+ self.addLink( s5 , s5_host )
+ self.addLink( s6 , s6_host )
+ self.addLink( s7 , s7_host )
+ self.addLink( s8 , s8_host )
+ self.addLink( s9 , s9_host )
+ self.addLink( s10 , s10_host )
+ self.addLink( s11 , s11_host )
+ self.addLink( s12 , s12_host )
+ self.addLink( s13 , s13_host )
+ self.addLink( s14 , s14_host )
+ self.addLink( s15 , s15_host )
+ self.addLink( s16 , s16_host )
+ self.addLink( s17 , s17_host )
+ self.addLink( s18 , s18_host )
+ self.addLink( s19 , s19_host )
+ self.addLink( s20 , s20_host )
+ self.addLink( s21 , s21_host )
+ self.addLink( s22 , s22_host )
+ self.addLink( s23 , s23_host )
+ self.addLink( s24 , s24_host )
+ self.addLink( s25 , s25_host )
+ self.addLink(s1, s2)
+ self.addLink(s1, s3)
+ self.addLink(s1, s4)
+ self.addLink(s1, s5)
+ self.addLink(s1, s6)
+ self.addLink(s1, s7)
+ self.addLink(s1, s8)
+ self.addLink(s1, s9)
+ self.addLink(s1, s10)
+ self.addLink(s1, s11)
+ self.addLink(s1, s12)
+ self.addLink(s1, s13)
+ self.addLink(s1, s14)
+ self.addLink(s1, s15)
+ self.addLink(s1, s16)
+ self.addLink(s1, s17)
+ self.addLink(s1, s18)
+ self.addLink(s1, s19)
+ self.addLink(s1, s20)
+ self.addLink(s1, s21)
+ self.addLink(s1, s22)
+ self.addLink(s1, s23)
+ self.addLink(s1, s24)
+ self.addLink(s1, s25)
+ self.addLink(s2, s3)
+ self.addLink(s2, s4)
+ self.addLink(s2, s5)
+ self.addLink(s2, s6)
+ self.addLink(s2, s7)
+ self.addLink(s2, s8)
+ self.addLink(s2, s9)
+ self.addLink(s2, s10)
+ self.addLink(s2, s11)
+ self.addLink(s2, s12)
+ self.addLink(s2, s13)
+ self.addLink(s2, s14)
+ self.addLink(s2, s15)
+ self.addLink(s2, s16)
+ self.addLink(s2, s17)
+ self.addLink(s2, s18)
+ self.addLink(s2, s19)
+ self.addLink(s2, s20)
+ self.addLink(s2, s21)
+ self.addLink(s2, s22)
+ self.addLink(s2, s23)
+ self.addLink(s2, s24)
+ self.addLink(s2, s25)
+ self.addLink(s3, s4)
+ self.addLink(s3, s5)
+ self.addLink(s3, s6)
+ self.addLink(s3, s7)
+ self.addLink(s3, s8)
+ self.addLink(s3, s9)
+ self.addLink(s3, s10)
+ self.addLink(s3, s11)
+ self.addLink(s3, s12)
+ self.addLink(s3, s13)
+ self.addLink(s3, s14)
+ self.addLink(s3, s15)
+ self.addLink(s3, s16)
+ self.addLink(s3, s17)
+ self.addLink(s3, s18)
+ self.addLink(s3, s19)
+ self.addLink(s3, s20)
+ self.addLink(s3, s21)
+ self.addLink(s3, s22)
+ self.addLink(s3, s23)
+ self.addLink(s3, s24)
+ self.addLink(s3, s25)
+ self.addLink(s4, s5)
+ self.addLink(s4, s6)
+ self.addLink(s4, s7)
+ self.addLink(s4, s8)
+ self.addLink(s4, s9)
+ self.addLink(s4, s10)
+ self.addLink(s4, s11)
+ self.addLink(s4, s12)
+ self.addLink(s4, s13)
+ self.addLink(s4, s14)
+ self.addLink(s4, s15)
+ self.addLink(s4, s16)
+ self.addLink(s4, s17)
+ self.addLink(s4, s18)
+ self.addLink(s4, s19)
+ self.addLink(s4, s20)
+ self.addLink(s4, s21)
+ self.addLink(s4, s22)
+ self.addLink(s4, s23)
+ self.addLink(s4, s24)
+ self.addLink(s4, s25)
+ self.addLink(s5, s6)
+ self.addLink(s5, s7)
+ self.addLink(s5, s8)
+ self.addLink(s5, s9)
+ self.addLink(s5, s10)
+ self.addLink(s5, s11)
+ self.addLink(s5, s12)
+ self.addLink(s5, s13)
+ self.addLink(s5, s14)
+ self.addLink(s5, s15)
+ self.addLink(s5, s16)
+ self.addLink(s5, s17)
+ self.addLink(s5, s18)
+ self.addLink(s5, s19)
+ self.addLink(s5, s20)
+ self.addLink(s5, s21)
+ self.addLink(s5, s22)
+ self.addLink(s5, s23)
+ self.addLink(s5, s24)
+ self.addLink(s5, s25)
+ self.addLink(s6, s7)
+ self.addLink(s6, s8)
+ self.addLink(s6, s9)
+ self.addLink(s6, s10)
+ self.addLink(s6, s11)
+ self.addLink(s6, s12)
+ self.addLink(s6, s13)
+ self.addLink(s6, s14)
+ self.addLink(s6, s15)
+ self.addLink(s6, s16)
+ self.addLink(s6, s17)
+ self.addLink(s6, s18)
+ self.addLink(s6, s19)
+ self.addLink(s6, s20)
+ self.addLink(s6, s21)
+ self.addLink(s6, s22)
+ self.addLink(s6, s23)
+ self.addLink(s6, s24)
+ self.addLink(s6, s25)
+ self.addLink(s7, s8)
+ self.addLink(s7, s9)
+ self.addLink(s7, s10)
+ self.addLink(s7, s11)
+ self.addLink(s7, s12)
+ self.addLink(s7, s13)
+ self.addLink(s7, s14)
+ self.addLink(s7, s15)
+ self.addLink(s7, s16)
+ self.addLink(s7, s17)
+ self.addLink(s7, s18)
+ self.addLink(s7, s19)
+ self.addLink(s7, s20)
+ self.addLink(s7, s21)
+ self.addLink(s7, s22)
+ self.addLink(s7, s23)
+ self.addLink(s7, s24)
+ self.addLink(s7, s25)
+ self.addLink(s8, s9)
+ self.addLink(s8, s10)
+ self.addLink(s8, s11)
+ self.addLink(s8, s12)
+ self.addLink(s8, s13)
+ self.addLink(s8, s14)
+ self.addLink(s8, s15)
+ self.addLink(s8, s16)
+ self.addLink(s8, s17)
+ self.addLink(s8, s18)
+ self.addLink(s8, s19)
+ self.addLink(s8, s20)
+ self.addLink(s8, s21)
+ self.addLink(s8, s22)
+ self.addLink(s8, s23)
+ self.addLink(s8, s24)
+ self.addLink(s8, s25)
+ self.addLink(s9, s10)
+ self.addLink(s9, s11)
+ self.addLink(s9, s12)
+ self.addLink(s9, s13)
+ self.addLink(s9, s14)
+ self.addLink(s9, s15)
+ self.addLink(s9, s16)
+ self.addLink(s9, s17)
+ self.addLink(s9, s18)
+ self.addLink(s9, s19)
+ self.addLink(s9, s20)
+ self.addLink(s9, s21)
+ self.addLink(s9, s22)
+ self.addLink(s9, s23)
+ self.addLink(s9, s24)
+ self.addLink(s9, s25)
+ self.addLink(s10, s11)
+ self.addLink(s10, s12)
+ self.addLink(s10, s13)
+ self.addLink(s10, s14)
+ self.addLink(s10, s15)
+ self.addLink(s10, s16)
+ self.addLink(s10, s17)
+ self.addLink(s10, s18)
+ self.addLink(s10, s19)
+ self.addLink(s10, s20)
+ self.addLink(s10, s21)
+ self.addLink(s10, s22)
+ self.addLink(s10, s23)
+ self.addLink(s10, s24)
+ self.addLink(s10, s25)
+ self.addLink(s11, s12)
+ self.addLink(s11, s13)
+ self.addLink(s11, s14)
+ self.addLink(s11, s15)
+ self.addLink(s11, s16)
+ self.addLink(s11, s17)
+ self.addLink(s11, s18)
+ self.addLink(s11, s19)
+ self.addLink(s11, s20)
+ self.addLink(s11, s21)
+ self.addLink(s11, s22)
+ self.addLink(s11, s23)
+ self.addLink(s11, s24)
+ self.addLink(s11, s25)
+ self.addLink(s12, s13)
+ self.addLink(s12, s14)
+ self.addLink(s12, s15)
+ self.addLink(s12, s16)
+ self.addLink(s12, s17)
+ self.addLink(s12, s18)
+ self.addLink(s12, s19)
+ self.addLink(s12, s20)
+ self.addLink(s12, s21)
+ self.addLink(s12, s22)
+ self.addLink(s12, s23)
+ self.addLink(s12, s24)
+ self.addLink(s12, s25)
+ self.addLink(s13, s14)
+ self.addLink(s13, s15)
+ self.addLink(s13, s16)
+ self.addLink(s13, s17)
+ self.addLink(s13, s18)
+ self.addLink(s13, s19)
+ self.addLink(s13, s20)
+ self.addLink(s13, s21)
+ self.addLink(s13, s22)
+ self.addLink(s13, s23)
+ self.addLink(s13, s24)
+ self.addLink(s13, s25)
+ self.addLink(s14, s15)
+ self.addLink(s14, s16)
+ self.addLink(s14, s17)
+ self.addLink(s14, s18)
+ self.addLink(s14, s19)
+ self.addLink(s14, s20)
+ self.addLink(s14, s21)
+ self.addLink(s14, s22)
+ self.addLink(s14, s23)
+ self.addLink(s14, s24)
+ self.addLink(s14, s25)
+ self.addLink(s15, s16)
+ self.addLink(s15, s17)
+ self.addLink(s15, s18)
+ self.addLink(s15, s19)
+ self.addLink(s15, s20)
+ self.addLink(s15, s21)
+ self.addLink(s15, s22)
+ self.addLink(s15, s23)
+ self.addLink(s15, s24)
+ self.addLink(s15, s25)
+ self.addLink(s16, s17)
+ self.addLink(s16, s18)
+ self.addLink(s16, s19)
+ self.addLink(s16, s20)
+ self.addLink(s16, s21)
+ self.addLink(s16, s22)
+ self.addLink(s16, s23)
+ self.addLink(s16, s24)
+ self.addLink(s16, s25)
+ self.addLink(s17, s18)
+ self.addLink(s17, s19)
+ self.addLink(s17, s20)
+ self.addLink(s17, s21)
+ self.addLink(s17, s22)
+ self.addLink(s17, s23)
+ self.addLink(s17, s24)
+ self.addLink(s17, s25)
+ self.addLink(s18, s19)
+ self.addLink(s18, s20)
+ self.addLink(s18, s21)
+ self.addLink(s18, s22)
+ self.addLink(s18, s23)
+ self.addLink(s18, s24)
+ self.addLink(s18, s25)
+ self.addLink(s19, s20)
+ self.addLink(s19, s21)
+ self.addLink(s19, s22)
+ self.addLink(s19, s23)
+ self.addLink(s19, s24)
+ self.addLink(s19, s25)
+ self.addLink(s20, s21)
+ self.addLink(s20, s22)
+ self.addLink(s20, s23)
+ self.addLink(s20, s24)
+ self.addLink(s20, s25)
+ self.addLink(s21, s22)
+ self.addLink(s21, s23)
+ self.addLink(s21, s24)
+ self.addLink(s21, s25)
+ self.addLink(s22, s23)
+ self.addLink(s22, s24)
+ self.addLink(s22, s25)
+ self.addLink(s23, s24)
+ self.addLink(s23, s25)
+ self.addLink(s24, s25)
+
+topos = { 'chordal': ( lambda: chordalTopo() ) }
diff --git a/framework/src/onos/tools/test/topos/cord.json b/framework/src/onos/tools/test/topos/cord.json
new file mode 100644
index 00000000..418a6b4b
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/cord.json
@@ -0,0 +1,24 @@
+{
+ "devices": [
+ { "uri": "of:00010001e88b9368", "mac": "0001e88b9368", "annotations": { "name": "s101", "latitude": 37.710742, "longitude": -103.975010 }},
+ { "uri": "of:00010001e88b939b", "mac": "0001e88b939b", "annotations": { "name": "s102", "latitude": 37.756072, "longitude": -97.547678 }},
+ { "uri": "of:00010001e88b938c", "mac": "0001e88b938c", "annotations": { "name": "s103", "latitude": 37.657851, "longitude": -90.778101 }},
+ { "uri": "of:00010001e88b93ad", "mac": "0001e88b93ad", "annotations": { "name": "s104", "latitude": 37.634692, "longitude": -84.215821 }},
+ { "uri": "of:00010001e88b93bc", "mac": "0001e88b93bc", "annotations": { "name": "s105", "latitude": 41.951018, "longitude": -103.853350 }},
+ { "uri": "of:00010001e88b93c2", "mac": "0001e88b93c2", "annotations": { "name": "s106", "latitude": 41.945684, "longitude": -97.526174 }},
+ { "uri": "of:00010001e88b9398", "mac": "0001e88b9398", "annotations": { "name": "s107", "latitude": 41.952876, "longitude": -90.696484 }},
+ { "uri": "of:00010001e88b27e3", "mac": "0001e88b27e3", "annotations": { "name": "s108", "latitude": 41.996877, "longitude": -84.169273 }}
+ ],
+ "hosts": [
+ { "id": "00:1f:29:e1:2c:36/-1", "mac": "00:1f:29:e1:2c:36", "vlan": -1, "location": "of:00010001e88b9368/46", "ip": "10.200.1.11", "annotations": { "name": "h11", "latitude": 34.384830, "longitude": -104.019262 }},
+ { "id": "00:1e:0b:cb:9d:64/-1", "mac": "00:1e:0b:cb:9d:64", "vlan": -1, "location": "of:00010001e88b9368/45", "ip": "10.200.1.12", "annotations": { "name": "h12", "latitude": 34.384830, "longitude": -104.019262 }},
+ { "id": "00:1c:c4:6b:d8:12/-1", "mac": "00:1c:c4:6b:d8:12", "vlan": -1, "location": "of:00010001e88b939b/46", "ip": "10.200.2.21", "annotations": { "name": "h21", "latitude": 34.133376, "longitude": -89.442032 }},
+ { "id": "00:1e:0b:ca:90:44/-1", "mac": "00:1e:0b:ca:90:44", "vlan": -1, "location": "of:00010001e88b939b/45", "ip": "10.200.2.22", "annotations": { "name": "h22", "latitude": 34.133376, "longitude": -89.442032 }},
+ { "id": "00:1e:0b:ca:e5:1a/-1", "mac": "00:1e:0b:ca:e5:1a", "vlan": -1, "location": "of:00010001e88b938c/46", "ip": "10.200.3.31", "annotations": { "name": "h31", "latitude": 34.166625, "longitude": -91.983293 }},
+ { "id": "2c:44:fd:e0:90:40/-1", "mac": "2c:44:fd:e0:90:40", "vlan": -1, "location": "of:00010001e88b938c/45", "ip": "10.200.3.32", "annotations": { "name": "h32", "latitude": 34.166625, "longitude": -91.983293 }},
+ { "id": "2c:44:fd:e0:90:44/-1", "mac": "2c:44:fd:e0:90:44", "vlan": -1, "location": "of:00010001e88b938c/47", "ip": "10.200.3.33", "annotations": { "name": "h33", "latitude": 34.166625, "longitude": -91.983293 }},
+ { "id": "00:1e:0b:cb:3f:ac/-1", "mac": "00:1e:0b:cb:3f:ac", "vlan": -1, "location": "of:00010001e88b93ad/46", "ip": "10.200.4.41", "annotations": { "name": "h41", "latitude": 34.225065, "longitude": -97.492882 }},
+ { "id": "c8:1f:66:e2:9b:d0/-1", "mac": "c8:1f:66:e2:9b:d0", "vlan": -1, "location": "of:00010001e88b93ad/45", "ip": "10.200.4.42", "annotations": { "name": "h42", "latitude": 34.249236, "longitude": -84.253025 }},
+ { "id": "c8:1f:66:e2:9b:d2/-1", "mac": "c8:1f:66:e2:9b:d2", "vlan": -1, "location": "of:00010001e88b93ad/47", "ip": "10.200.4.43", "annotations": { "name": "h43", "latitude": 34.249236, "longitude": -84.253025 }}
+ ]
+}
diff --git a/framework/src/onos/tools/test/topos/fractal.py b/framework/src/onos/tools/test/topos/fractal.py
new file mode 100755
index 00000000..bc5c6899
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/fractal.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+from mininet.topo import Topo
+
+class FractalTopo( Topo ):
+ def build( self, n=3, h=2 ):
+
+ clusters = []
+ for i in range( 1, n+1 ):
+ clusterSws = []
+ # create switches in cluster
+ for j in range( 1, n+1 ):
+ id = i * 1000 + j
+ sw = self.addSwitch('s%d' % id, dpid=str(id).zfill(16))
+ [ self.addLink(s, sw) for s in clusterSws ]
+ clusterSws.append(sw)
+ clusters.append(clusterSws)
+
+ for i in range( 1, n+1 ):
+ # create the edge switch
+ id = i * 10000
+ sw = self.addSwitch('s%d' % id, dpid=str(id).zfill(16))
+ self.addLink(clusters[i-1].pop(0), sw)
+ for j in range( 1, h+1 ):
+ id = i * 1000 + j
+ host = self.addHost( 'h%d' % id )
+ self.addLink( host, sw )
+
+ for i in range( 1, n+1 ):
+ # connect the clusters
+ if i == n:
+ id = n * 1000000 + 10000
+ sw = self.addSwitch('s%d' % id, dpid=str(id).zfill(16))
+ self.addLink(clusters[i-1].pop(0), sw)
+ self.addLink(clusters[0].pop(0), sw)
+
+ else:
+ id = (i+1) * 1000000 + i * 10000
+ sw = self.addSwitch('s%d' % id, dpid=str(id).zfill(16))
+ self.addLink(clusters[i-1].pop(0), sw)
+ self.addLink(clusters[i].pop(0), sw)
+
+
+topos = { 'fractal': FractalTopo }
+
+def run():
+ topo = FractalTopo()
+ net = Mininet( topo=topo, controller=RemoteController, autoSetMacs=True )
+ net.start()
+ CLI( net )
+ net.stop()
+
+if __name__ == '__main__':
+ setLogLevel( 'info' )
+ run()
+
diff --git a/framework/src/onos/tools/test/topos/linear-2.json b/framework/src/onos/tools/test/topos/linear-2.json
new file mode 100644
index 00000000..c248a236
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/linear-2.json
@@ -0,0 +1,6 @@
+{
+ "devices": [
+ { "alias": "s1", "uri": "of:0000000000000001", "annotations": { "driver": "ovs-corsa" } },
+ { "alias": "s2", "uri": "of:0000000000000002", "annotations": { "driver": "ovs-corsa" } }
+ ]
+}
diff --git a/framework/src/onos/tools/test/topos/newFuncTopo.py b/framework/src/onos/tools/test/topos/newFuncTopo.py
new file mode 100644
index 00000000..5edf7f78
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/newFuncTopo.py
@@ -0,0 +1,148 @@
+#!/usr/bin/python
+
+"""
+Custom topology for Mininet
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import Host, RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+from mininet.node import ( UserSwitch, OVSSwitch, IVSSwitch )
+
+class VLANHost( Host ):
+ def config( self, vlan=100, **params ):
+ r = super( Host, self ).config( **params )
+ intf = self.defaultIntf()
+ self.cmd( 'ifconfig %s inet 0' % intf )
+ self.cmd( 'vconfig add %s %d' % ( intf, vlan ) )
+ self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) )
+ newName = '%s.%d' % ( intf, vlan )
+ intf.name = newName
+ self.nameToIntf[ newName ] = intf
+ return r
+
+class IPv6Host( Host ):
+ def config( self, v6Addr='1000:1/64', **params ):
+ r = super( Host, self ).config( **params )
+ intf = self.defaultIntf()
+ self.cmd( 'ifconfig %s inet 0' % intf )
+ self.cmd( 'ip -6 addr add %s dev %s' % ( v6Addr, intf ) )
+ return r
+
+class dualStackHost( Host ):
+ def config( self, v6Addr='2000:1/64', **params ):
+ r = super( Host, self ).config( **params )
+ intf = self.defaultIntf()
+ self.cmd( 'ip -6 addr add %s dev %s' % ( v6Addr, intf ) )
+ return r
+
+class MyTopo( Topo ):
+
+ def __init__( self ):
+ # Initialize topology
+ Topo.__init__( self )
+ # Switch S5 Hosts
+ host1=self.addHost( 'h1', ip='10.1.0.2/24' )
+ host2=self.addHost( 'h2', cls=IPv6Host, v6Addr='1000::2/64' )
+ host3=self.addHost( 'h3', ip='10.1.0.3/24', cls=dualStackHost, v6Addr='2000::2/64' )
+ #VLAN hosts
+ host4=self.addHost( 'h4', ip='100.1.0.2/24', cls=VLANHost, vlan=100 )
+ host5=self.addHost( 'h5', ip='200.1.0.2/24', cls=VLANHost, vlan=200 )
+ #VPN-1 and VPN-2 Hosts
+ host6=self.addHost( 'h6', ip='11.1.0.2/24' )
+ host7=self.addHost( 'h7', ip='12.1.0.2/24' )
+ #Multicast Sender
+ host8=self.addHost( 'h8', ip='10.1.0.4/24' )
+
+ # Switch S6 Hosts
+ host9=self.addHost( 'h9', ip='10.1.0.5/24' )
+ host10=self.addHost( 'h10', cls=IPv6Host, v6Addr='1000::3/64' )
+ host11=self.addHost( 'h11', ip='10.1.0.6/24', cls=dualStackHost, v6Addr='2000::3/64' )
+ #VLAN hosts
+ host12=self.addHost( 'h12', ip='100.1.0.3/24', cls=VLANHost, vlan=100 )
+ host13=self.addHost( 'h13', ip='200.1.0.3/24', cls=VLANHost, vlan=200 )
+ #VPN-1 and VPN-2 Hosts
+ host14=self.addHost( 'h14', ip='11.1.0.3/24' )
+ host15=self.addHost( 'h15', ip='12.1.0.3/24' )
+ #Multicast Receiver
+ host16=self.addHost( 'h16', ip='10.1.0.7/24' )
+
+ # Switch S7 Hosts
+ host17=self.addHost( 'h17', ip='10.1.0.8/24' )
+ host18=self.addHost( 'h18', cls=IPv6Host, v6Addr='1000::4/64' )
+ host19=self.addHost( 'h19', ip='10.1.0.9/24', cls=dualStackHost, v6Addr='2000::4/64' )
+ #VLAN hosts
+ host20=self.addHost( 'h20', ip='100.1.0.4/24', cls=VLANHost, vlan=100 )
+ host21=self.addHost( 'h21', ip='200.1.0.4/24', cls=VLANHost, vlan=200 )
+ #VPN-1 and VPN-2 Hosts
+ host22=self.addHost( 'h22', ip='11.1.0.4/24' )
+ host23=self.addHost( 'h23', ip='12.1.0.4/24' )
+ #Multicast Receiver
+ host24=self.addHost( 'h24', ip='10.1.0.10/24' )
+
+ s1 = self.addSwitch( 's1' )
+ s2 = self.addSwitch( 's2' )
+ s3 = self.addSwitch( 's3' )
+ s4 = self.addSwitch( 's4' )
+ s5 = self.addSwitch( 's5' )
+ s6 = self.addSwitch( 's6' )
+ s7 = self.addSwitch( 's7' )
+
+ self.addLink(s5,host1)
+ self.addLink(s5,host2)
+ self.addLink(s5,host3)
+ self.addLink(s5,host4)
+ self.addLink(s5,host5)
+ self.addLink(s5,host6)
+ self.addLink(s5,host7)
+ self.addLink(s5,host8)
+
+ self.addLink(s6,host9)
+ self.addLink(s6,host10)
+ self.addLink(s6,host11)
+ self.addLink(s6,host12)
+ self.addLink(s6,host13)
+ self.addLink(s6,host14)
+ self.addLink(s6,host15)
+ self.addLink(s6,host16)
+
+ self.addLink(s7,host17)
+ self.addLink(s7,host18)
+ self.addLink(s7,host19)
+ self.addLink(s7,host20)
+ self.addLink(s7,host21)
+ self.addLink(s7,host22)
+ self.addLink(s7,host23)
+ self.addLink(s7,host24)
+
+ self.addLink(s1,s2)
+ self.addLink(s1,s3)
+ self.addLink(s1,s4)
+ self.addLink(s1,s5)
+ self.addLink(s2,s3)
+ self.addLink(s2,s5)
+ self.addLink(s2,s6)
+ self.addLink(s3,s4)
+ self.addLink(s3,s6)
+ self.addLink(s4,s7)
+ topos = { 'mytopo': ( lambda: MyTopo() ) }
+
+# HERE THE CODE DEFINITION OF THE TOPOLOGY ENDS
+
+def setupNetwork():
+ "Create network"
+ topo = MyTopo()
+ network = Mininet(topo=topo, autoSetMacs=True, controller=None)
+ network.start()
+ CLI( network )
+ network.stop()
+
+if __name__ == '__main__':
+ setLogLevel('info')
+ #setLogLevel('debug')
+ setupNetwork()
diff --git a/framework/src/onos/tools/test/topos/obelisk.py b/framework/src/onos/tools/test/topos/obelisk.py
new file mode 100755
index 00000000..fb6ccdbe
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/obelisk.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+from mininet.topo import Topo
+
+class ObeliskTopo( Topo ):
+ def __init__( self ):
+ Topo.__init__( self )
+ topSwitch = self.addSwitch('s1',dpid='1000'.zfill(16))
+ leftTopSwitch = self.addSwitch('s2',dpid='2000'.zfill(16))
+ rightTopSwitch = self.addSwitch('s5',dpid='5000'.zfill(16))
+ leftBotSwitch = self.addSwitch('s3',dpid='3000'.zfill(16))
+ rightBotSwitch = self.addSwitch('s6',dpid='6000'.zfill(16))
+ midBotSwitch = self.addSwitch('s28',dpid='2800'.zfill(16))
+
+ topHost = self.addHost( 'h1' )
+ leftTopHost = self.addHost('h2')
+ rightTopHost = self.addHost('h5')
+ leftBotHost = self.addHost('h3')
+ rightBotHost = self.addHost('h6')
+ midBotHost = self.addHost('h28')
+ self.addLink(topSwitch,topHost)
+ self.addLink(leftTopSwitch,leftTopHost)
+ self.addLink(rightTopSwitch,rightTopHost)
+ self.addLink(leftBotSwitch,leftBotHost)
+ self.addLink(rightBotSwitch,rightBotHost)
+ self.addLink(midBotSwitch,midBotHost)
+ self.addLink(leftTopSwitch,rightTopSwitch)
+ self.addLink(topSwitch,leftTopSwitch)
+ self.addLink(topSwitch,rightTopSwitch)
+ self.addLink(leftTopSwitch,leftBotSwitch)
+ self.addLink(rightTopSwitch,rightBotSwitch)
+ self.addLink(leftBotSwitch,midBotSwitch)
+ self.addLink(midBotSwitch,rightBotSwitch)
+
+ agg1Switch = self.addSwitch('s4',dpid = '3004'.zfill(16))
+ agg2Switch = self.addSwitch('s7',dpid = '6007'.zfill(16))
+ agg1Host = self.addHost('h4')
+ agg2Host = self.addHost('h7')
+ self.addLink(agg1Switch,agg1Host)
+ self.addLink(agg2Switch,agg2Host)
+ self.addLink(agg1Switch, leftBotSwitch)
+ self.addLink(agg2Switch, rightBotSwitch)
+
+ for i in range(10):
+ num = str(i+8)
+ switch = self.addSwitch('s'+num,dpid = ('30'+num.zfill(2)).zfill(16))
+ host = self.addHost('h'+num)
+ self.addLink(switch, host)
+ self.addLink(switch, agg1Switch)
+
+ for i in range(10):
+ num = str(i+18)
+ switch = self.addSwitch('s'+num,dpid = ('60'+num.zfill(2)).zfill(16))
+ host = self.addHost('h'+num)
+ self.addLink(switch, host)
+ self.addLink(switch, agg2Switch)
+
+topos = { 'obelisk': (lambda: ObeliskTopo() ) }
+
+def run():
+ topo = ObeliskTopo()
+ net = Mininet( topo=topo, controller=RemoteController, autoSetMacs=True )
+ net.start()
+ CLI( net )
+ net.stop()
+
+if __name__ == '__main__':
+ setLogLevel( 'info' )
+ run()
+
diff --git a/framework/src/onos/tools/test/topos/obeliskHostCheck.py b/framework/src/onos/tools/test/topos/obeliskHostCheck.py
new file mode 100755
index 00000000..e928f89f
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/obeliskHostCheck.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+
+import sys
+import os
+import json
+
+# TODO: if none given, use OCI
+try:
+ onosIp = sys.argv[1]
+ print "Reading hosts view from ONOS node " + onosIp + ":"
+except Exception as e:
+ print "Error reading ONOS IP arguement"
+ print e
+# Grab the json objects from ONOS
+output = os.popen("onos " + onosIp + " \"hosts -j\"" )
+hosts = json.loads( output.read() )
+#hosts = json.loads( output.split( 'Logging in as karaf\n' )[1] )
+
+hostAttachment = True
+# FIXME: topo-HA/obelisk specific mappings:
+# key is mac and value is dpid
+mappings = {}
+for i in range( 1, 29 ): # hosts 1 through 28
+ # set up correct variables:
+ macId = "00:" * 5 + hex( i ).split( "0x" )[1].upper().zfill(2)
+ if i == 1:
+ deviceId = "1000".zfill(16)
+ elif i == 2:
+ deviceId = "2000".zfill(16)
+ elif i == 3:
+ deviceId = "3000".zfill(16)
+ elif i == 4:
+ deviceId = "3004".zfill(16)
+ elif i == 5:
+ deviceId = "5000".zfill(16)
+ elif i == 6:
+ deviceId = "6000".zfill(16)
+ elif i == 7:
+ deviceId = "6007".zfill(16)
+ elif i >= 8 and i <= 17:
+ dpid = '3' + str( i ).zfill( 3 )
+ deviceId = dpid.zfill(16)
+ elif i >= 18 and i <= 27:
+ dpid = '6' + str( i ).zfill( 3 )
+ deviceId = dpid.zfill(16)
+ elif i == 28:
+ deviceId = "2800".zfill(16)
+ mappings[ macId ] = deviceId
+
+if hosts or "Error" not in hosts:
+ if hosts == []:
+ print "WARNING: There are no hosts discovered"
+ else:
+ for host in hosts:
+ mac = None
+ location = None
+ device = None
+ port = None
+ try:
+ mac = host.get( 'mac' )
+ assert mac, "mac field could not be found for this host object"
+
+ location = host.get( 'location' )
+ assert location, "location field could not be found for this host object"
+
+ # Trim the protocol identifier off deviceId
+ device = str( location.get( 'elementId' ) ).split(':')[1]
+ assert device, "elementId field could not be found for this host location object"
+
+ port = location.get( 'port' )
+ assert port, "port field could not be found for this host location object"
+
+ # Now check if this matches where they should be
+ if mac and device and port:
+ if device != mappings[ str( mac ) ]:
+ print "The attachment device is incorrect for host " + str( mac ) +\
+ ". Expected: " + mappings[ str( mac ) ] + "; Actual: " + device
+ hostAttachment = False
+ if str( port ) != "1":
+ print "The attachment port is incorrect for host " + str( mac ) +\
+ ". Expected: 1; Actual: " + str( port)
+ hostAttachment = False
+ else:
+ hostAttachment = False
+ except AssertionError as e:
+ print "ERROR: Json object not as expected:"
+ print e
+ print "host object: " + repr( host )
+ hostAttachment = False
+else:
+ print "No hosts json output or \"Error\" in output. hosts = " + repr( hosts )
diff --git a/framework/src/onos/tools/test/topos/oe-linear-3.json b/framework/src/onos/tools/test/topos/oe-linear-3.json
new file mode 100644
index 00000000..44fccd99
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/oe-linear-3.json
@@ -0,0 +1,48 @@
+{
+ "devices" : [
+ {
+ "uri": "of:0000ffffffffff01", "mac": "ffffffffffff01", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROADM1", "latitude": 37.6, "longitude": -122.3, "optical.regens": 0 },
+ "ports": [ { "port": 10, "speed": 100000, "type": "FIBER" }, { "port": 20, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff02", "mac": "ffffffffffff02", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROADM2", "latitude": 37.3, "longitude": -121.9, "optical.regens": 0 },
+ "ports": [ { "port": 11, "speed": 100000, "type": "FIBER" }, { "port": 21, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff03", "mac": "ffffffffffff03", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROADM3", "latitude": 33.9, "longitude": -118.4, "optical.regens": 2 },
+ "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+ },
+
+ {
+ "uri": "of:0000ffffffff0001", "mac": "ffffffffff0001", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROUTER1", "latitude": 37.6, "longitude": -122.3 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0002", "mac": "ffffffffff0002", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROUTER2", "latitude": 37.3, "longitude": -121.9 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ }
+ ],
+
+ "links" : [
+ { "src": "of:0000ffffffffff01/20", "dst": "of:0000ffffffffff03/30", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "durable": "true", "inactive": "true" } },
+ { "src": "of:0000ffffffffff02/21", "dst": "of:0000ffffffffff03/31", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "durable": "true", "inactive": "true" } },
+
+ { "src": "of:0000ffffffff0001/2", "dst": "of:0000ffffffffff01/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true", "inactive": "true" } },
+ { "src": "of:0000ffffffff0002/2", "dst": "of:0000ffffffffff02/11", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true", "inactive": "true" } }
+ ],
+
+ "hosts" : [
+ { "mac": "00:00:00:00:00:01", "vlan": -1, "location": "of:0000ffffffff0001/1", "ip": "10.0.0.1" },
+ { "mac": "00:00:00:00:00:02", "vlan": -1, "location": "of:0000ffffffff0002/1", "ip": "10.0.0.2" }
+ ]
+} \ No newline at end of file
diff --git a/framework/src/onos/tools/test/topos/oe-nonlinear-10.json b/framework/src/onos/tools/test/topos/oe-nonlinear-10.json
new file mode 100644
index 00000000..9bf291e8
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/oe-nonlinear-10.json
@@ -0,0 +1,149 @@
+{
+ "devices" : [
+ {
+ "uri": "of:0000ffffffffff01", "mac": "ffffffffffff01", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "SFO-W10", "latitude": 37.6, "longitude": -122.3, "optical.regens": 0 },
+ "ports": [ { "port": 10, "speed": 100000, "type": "FIBER" },
+ { "port": 20, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed":100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff02", "mac": "ffffffffffff02", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "SJC-W10", "latitude": 37.3, "longitude": -121.9, "optical.regens": 0 },
+ "ports": [ { "port": 20, "speed": 100000, "type": "FIBER" },
+ { "port": 30, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff03", "mac": "ffffffffffff03", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "LAX-W10", "latitude": 33.9, "longitude": -118.4, "optical.regens": 0 },
+ "ports": [ { "port": 30, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" },
+ { "port": 20, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff04", "mac": "ffffffffffff04", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "SDG-W10", "latitude": 32.8, "longitude": -117.1, "optical.regens": 3 },
+ "ports": [ { "port": 30, "speed": 0, "type": "FIBER" },
+ { "port":50, "speed": 0, "type": "FIBER" },
+ { "port":20, "speed": 0, "type": "FIBER" }]
+ },
+ {
+ "uri": "of:0000ffffffffff05", "mac": "ffffffffffff05", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "MSP-M10", "latitude": 44.8, "longitude": -93.1, "optical.regens": 3 },
+ "ports": [ { "port": 20, "speed": 0, "type": "FIBER" },
+ { "port": 30, "speed": 0, "type": "FIBER" },
+ { "port": 40, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" }]
+ },
+ {
+ "uri": "of:0000ffffffffff06", "mac": "ffffffffffff06", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "DFW-M10", "latitude": 32.8, "longitude": -97.1, "optical.regens": 3 },
+ "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+ { "port": 20, "speed": 0, "type": "FIBER" },
+ { "port": 30, "speed": 0, "type": "FIBER" },
+ { "port": 40, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" }]
+ },
+ {
+ "uri": "of:0000ffffffffff07", "mac": "ffffffffffff07", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "CHG-N10", "latitude": 41.8, "longitude": -87.6, "optical.regens": 3 },
+ "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+ { "port": 20, "speed": 0, "type": "FIBER" },
+ { "port": 30, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" }]
+ },
+ {
+ "uri": "of:0000ffffffffff08", "mac": "ffffffffffff08", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "IAD-M10", "latitude": 38.8, "longitude": -77.1, "optical.regens": 3 },
+ "ports": [ { "port": 20, "speed": 0, "type": "FIBER" },
+ { "port": 30, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" }]
+ },
+ {
+ "uri": "of:0000ffffffffff09", "mac": "ffffffffffff09", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "JFK-M10", "latitude": 40.8, "longitude": -73.1, "optical.regens": 0 },
+ "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+ { "port": 20, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" }]
+ },
+ {
+ "uri": "of:0000ffffffffff0A", "mac": "ffffffffffff0A", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ATL-S10", "latitude": 33.8, "longitude": -84.1, "optical.regens": 0 },
+ "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+ { "port": 20, "speed": 0, "type": "FIBER" },
+ { "port": 50, "speed": 0, "type": "FIBER" }]
+ },
+ {
+ "uri": "of:0000ffffffff0001", "mac": "ffffffffff0001", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "SFO-R10", "latitude": 37.6, "longitude": -122.3 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0002", "mac": "ffffffffff0003", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "LAX-R10", "latitude": 33.9, "longitude": -118.4 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0003", "mac": "ffffffffff0004", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "SDG-R10", "latitude": 32.8, "longitude": -117.1 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0004", "mac": "ffffffffff0007", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "CHG-R10", "latitude": 41.8, "longitude": -87.6 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0005", "mac": "ffffffffff0009", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "JFK-R10", "latitude": 40.8, "longitude": -73.1 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0006", "mac": "ffffffffff000A", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "ATL-R10", "latitude": 33.8, "longitude": -84.1 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ }
+
+ ],
+
+ "links" : [
+ { "src": "of:0000ffffffffff01/50", "dst": "of:0000ffffffffff02/30","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 48, "durable": "true" } },
+ { "src": "of:0000ffffffffff02/50", "dst": "of:0000ffffffffff03/30","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 493, "durable": "true" } },
+ { "src": "of:0000ffffffffff03/50", "dst": "of:0000ffffffffff04/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 171, "durable": "true" } },
+ { "src": "of:0000ffffffffff01/20", "dst": "of:0000ffffffffff05/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 2555, "durable": "true" } },
+ { "src": "of:0000ffffffffff02/20", "dst": "of:0000ffffffffff05/20","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 2539, "durable": "true" } },
+ { "src": "of:0000ffffffffff03/20", "dst": "of:0000ffffffffff06/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1979, "durable": "true" } },
+ { "src": "of:0000ffffffffff04/20", "dst": "of:0000ffffffffff06/20","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1867, "durable": "true" } },
+ { "src": "of:0000ffffffffff05/30", "dst": "of:0000ffffffffff06/40","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1378, "durable": "true" } },
+ { "src": "of:0000ffffffffff05/40", "dst": "of:0000ffffffffff07/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 2200, "durable": "true" } },
+ { "src": "of:0000ffffffffff06/30", "dst": "of:0000ffffffffff08/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1918, "durable": "true" } },
+ { "src": "of:0000ffffffffff07/20", "dst": "of:0000ffffffffff08/30", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 3625, "durable": "true" } },
+ { "src": "of:0000ffffffffff07/30", "dst": "of:0000ffffffffff09/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 3880, "durable": "true" } },
+ { "src": "of:0000ffffffffff08/20", "dst": "of:0000ffffffffff0A/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 838, "durable": "true" } },
+ { "src": "of:0000ffffffffff09/20", "dst": "of:0000ffffffffff0A/20","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1245, "durable": "true" } },
+
+ { "src": "of:0000ffffffff0001/2", "dst": "of:0000ffffffffff01/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
+ { "src": "of:0000ffffffff0002/2", "dst": "of:0000ffffffffff04/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
+ { "src": "of:0000ffffffff0003/2", "dst": "of:0000ffffffffff06/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
+ { "src": "of:0000ffffffff0004/2", "dst": "of:0000ffffffffff07/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
+ { "src": "of:0000ffffffff0005/2", "dst": "of:0000ffffffffff09/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
+ { "src": "of:0000ffffffff0006/2", "dst": "of:0000ffffffffff0A/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }
+ ]
+}
diff --git a/framework/src/onos/tools/test/topos/oe-nonlinear-4.json b/framework/src/onos/tools/test/topos/oe-nonlinear-4.json
new file mode 100644
index 00000000..47782a86
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/oe-nonlinear-4.json
@@ -0,0 +1,52 @@
+{
+ "devices" : [
+ {
+ "uri": "of:0000ffffffffff01", "mac": "ffffffffffff01", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROADM1", "latitude": 37.6, "longitude": -122.3, "optical.regens": 0 },
+ "ports": [ { "port": 10, "speed": 100000, "type": "FIBER" }, { "port": 20, "speed": 0, "type": "FIBER" }, { "port": 22, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff02", "mac": "ffffffffffff02", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROADM2", "latitude": 37.3, "longitude": -121.9, "optical.regens": 0 },
+ "ports": [ { "port": 11, "speed": 100000, "type": "FIBER" }, { "port": 21, "speed": 0, "type": "FIBER" }, { "port": 22, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff03", "mac": "ffffffffffff03", "type": "ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROADM3", "latitude": 33.9, "longitude": -118.4, "optical.regens": 2 },
+ "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffffff04", "mac": "ffffffffffff04", "type":"ROADM",
+ "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROADM4", "latitude": 39.9, "longitude": -119.4, "optical.regens": 2 },
+ "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0001", "mac": "ffffffffff0001", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROUTER1", "latitude": 37.6, "longitude": -122.3 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ },
+ {
+ "uri": "of:0000ffffffff0002", "mac": "ffffffffff0002", "type": "SWITCH",
+ "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?",
+ "annotations": { "name": "ROUTER2", "latitude": 37.3, "longitude": -121.9 },
+ "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
+ }
+ ],
+
+ "links" : [
+ { "src": "of:0000ffffffffff01/20", "dst": "of:0000ffffffffff03/30", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "durable": "true", "inactive": "true" } },
+ { "src": "of:0000ffffffffff02/21", "dst": "of:0000ffffffffff03/31", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "durable": "true", "inactive": "true" } },
+ { "src": "of:0000ffffffffff01/22", "dst": "of:0000ffffffffff04/30", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "durable": "true", "inactive": "true" } },
+ { "src": "of:0000ffffffffff04/31", "dst": "of:0000ffffffffff02/22", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "durable": "true", "inactive": "true" } },
+
+ { "src": "of:0000ffffffff0001/2", "dst": "of:0000ffffffffff01/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true", "inactive": "true" } },
+ { "src": "of:0000ffffffff0002/2", "dst": "of:0000ffffffffff02/11", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true", "inactive": "true" } }
+ ]
+
+}
+
diff --git a/framework/src/onos/tools/test/topos/onos.py b/framework/src/onos/tools/test/topos/onos.py
new file mode 100755
index 00000000..3e5bff7c
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/onos.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+
+# TODO add onos-app-fwd to features
+# TODO check if service is running... i think this might already be done by mn
+
+from mininet.node import Controller, OVSSwitch, CPULimitedHost, RemoteController
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.topo import LinearTopo, Topo
+from mininet.log import setLogLevel, info, warn
+from mininet.util import quietRun, numCores
+
+from shutil import copyfile
+from os import environ, path
+from functools import partial
+import time
+from sys import argv
+from time import sleep
+from sets import Set
+
+class ONOS( Controller ):
+ "TODO"
+
+ onosDir = '/opt/onos/'
+
+ def __init__( self, name, onosDir=onosDir,
+ reactive=True, features=[ 'onos-app-tvue' ],
+ **kwargs ):
+ '''TODO'''
+
+ Controller.__init__( self, name, **kwargs )
+ # the following have been done for us:
+ #self.ip = ip ('127.0.0.1')
+ #self.port = port (6633)
+ #self.protocol = protocol ('tcp')
+ #self.checkListening()
+
+ self.onosDir = onosDir
+ self.karafDir = onosDir + 'apache-karaf-3.0.3/'
+ self.instanceDir = self.karafDir
+
+ # add default modules
+ # TODO: consider an ordered set
+ self.features = Set([ 'webconsole',
+ 'onos-rest',
+ 'onos-api',
+ 'onos-cli',
+ 'onos-openflow' ])
+ self.features.update( features )
+ # add reactive forwarding modules
+ if reactive:
+ self.features.update( ['onos-app-fwd',
+ 'onos-app-proxyarp',
+ 'onos-app-mobility' ] )
+ # add the distributed core if we are in a namespace with no trivial core
+ if self.inNamespace and 'onos-core-trivial' not in self.features:
+ self.features.add( 'onos-core' )
+ # if there is no core, add the trivial one
+ if 'onos-core' not in self.features:
+ self.features.add( 'onos-core-trivial' )
+ print self.features
+
+ def start( self ):
+ if self.inNamespace:
+ instanceOpts = ( '-furl mvn:org.onosproject/onos-features/1.3.0-SNAPSHOT/xml/features '
+ '-s 8101' )
+ if self.ip is not None:
+ instanceOpts += (' -a %s' % self.IP() )
+ self.userCmd( self.karafDir + 'bin/instance create %s %s' % ( instanceOpts, self.name ) )
+ self.instanceDir = self.karafDir + 'instances/%s/' % self.name
+ else:
+ # we are running in the root namespace, so let's use the root instance
+ # clean up the data directory
+ #self.userCmd( 'rm -rf '+ self.karafDir + 'data/' )
+ pass
+
+ self.userCmd( 'rm -rf '+ self.instanceDir + 'data/' )
+
+ # Update etc/org.apache.karaf.features.cfg
+ self.updateFeatures()
+
+ # TODO 2. Update etc/hazelcast.xml : interface lines
+ #cp etc/hazelcast.xml instances/c1/etc/
+ self.updateHazelcast()
+
+ # TODO 3. Update etc/system.properties : onos.ip
+ # TODO 4. Update config/cluster.json : with all nodes
+
+ # start onos
+ self.userCmd( '%sbin/instance start -d %s' % ( self.karafDir, self.name ) )
+ #TODO we should wait for startup...
+
+ def stop( self ):
+ self.userCmd( self.instanceDir + 'bin/stop' )
+ #if self.inNamespace:
+ # self.userCmd( self.karafDir + 'bin/instance destroy %s' % self.name )
+ self.terminate()
+
+ def updateHazelcast( self ):
+ hz = '192.168.123.*'
+ if self.ip is not None:
+ hz = '.'.join(self.ip.split('.')[:-1]) + '.*'
+
+ readfile = self.karafDir + 'etc/hazelcast.xml'
+ writefile = self.instanceDir + 'etc/hazelcast.xml'
+ with open( readfile, 'r' ) as r:
+ with open( writefile, 'w' ) as w:
+ for line in r.readlines():
+ if '<interface>' in line:
+ line = '<interface>' + hz + '</interface>\n'
+ w.write( line )
+
+ def updateFeatures( self ):
+ filename = self.instanceDir + 'etc/org.apache.karaf.features.cfg'
+ with open( filename, 'r+' ) as f:
+ lines = f.readlines()
+ f.seek(0)
+ f.truncate()
+ for line in lines:
+ #print '?', line,
+ if 'featuresBoot=' in line:
+ # parse the features from the line
+ features = line.rstrip().split('=')[1].split(',')
+ # add the features to our features set
+ self.features.update( features )
+ # generate the new features line
+ line = 'featuresBoot=' + ','.join( self.features ) + '\n'
+ #print '!', line,
+ f.write( line )
+
+
+ @classmethod
+ def isAvailable( self ):
+ return quietRun( 'ls %s' % self.onosDir )
+
+ def userCmd( self, cmd ):
+ # switch to the non-root user because karaf gets upset otherwise
+ # because the .m2repo is not stored with root
+ cmd = 'sudo -u %s %s' % ( self.findUser(), cmd )
+ return self.cmd( cmd )
+
+ @staticmethod
+ def findUser():
+ "Try to return logged-in (usually non-root) user"
+ try:
+ # If we're running sudo
+ return os.environ[ 'SUDO_USER' ]
+ except:
+ try:
+ # Logged-in user (if we have a tty)
+ return quietRun( 'who am i' ).split()[ 0 ]
+ except:
+ # Give up and return effective user
+ return quietRun( 'whoami' )
+
+
+class ControlNetwork( Topo ):
+ "Control Network Topology"
+ def __init__( self, n, dataController=ONOS, **kwargs ):
+ """n: number of data network controller nodes
+ dataController: class for data network controllers"""
+ Topo.__init__( self, **kwargs )
+ # Connect everything to a single switch
+ cs0 = self.addSwitch( 'cs0' )
+ # Add hosts which will serve as data network controllers
+ for i in range( 1, n+1 ):
+ c = self.addHost( 'c%s' % i, cls=dataController,
+ inNamespace=True )
+ self.addLink( c, cs0 )
+ # Connect switch to root namespace so that data network
+ # switches will be able to talk to us
+ root = self.addHost( 'root', inNamespace=False )
+ self.addLink( root, cs0 )
+
+class ONOSCluster( Controller ):
+ # TODO
+ n = 3
+
+ def start( self ):
+ ctopo = ControlNetwork( n=self.n, dataController=ONOS )
+ self.cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', controller=None )
+ self.cnet.addController( 'cc0', controller=Controller )
+ self.cnet.start()
+
+ self.ctrls = []
+ for host in self.cnet.hosts:
+ if isinstance( host, Controller ):
+ self.ctrls.append( host )
+ host.start()
+
+ def stop( self ):
+ for host in self.cnet.hosts:
+ if isinstance( host, Controller ):
+ host.stop()
+ self.cnet.stop()
+
+ def clist( self ):
+ "Return list of Controller proxies for this ONOS cluster"
+ print 'controllers:', self.ctrls
+ return self.ctrls
+
+class OVSSwitchONOS( OVSSwitch ):
+ "OVS switch which connects to multiple controllers"
+ def start( self, controllers ):
+ assert len( controllers ) == 1
+ c0 = controllers[ 0 ]
+ assert type( c0 ) == ONOSCluster
+ controllers = c0.clist()
+ OVSSwitch.start( self, controllers )
+
+controllers = { 'onos': ONOS }
+switches = { 'ovso': OVSSwitchONOS }
+
+if __name__ == '__main__':
+ # Simple test for ONOS() controller class
+ setLogLevel( 'info' ) #TODO info
+ size = 2 if len( argv ) != 2 else int( argv[ 1 ] )
+ net = Mininet( topo=LinearTopo( size ),
+ #controller=ONOS,
+ controller=partial( ONOSCluster, n=3 ), #TODO
+ switch=OVSSwitchONOS )
+ net.start()
+ #waitConnected( net.switches )
+ CLI( net )
+ net.stop()
diff --git a/framework/src/onos/tools/test/topos/optical.py b/framework/src/onos/tools/test/topos/optical.py
new file mode 100755
index 00000000..300332aa
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/optical.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+''' file: optical.py '''
+
+from mininet.topo import Topo
+from mininet.node import RemoteController
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.log import setLogLevel, info
+from mininet.link import Intf, Link
+from mininet.util import irange
+
+class NullIntf( Intf ):
+ "A dummy interface with a blank name that doesn't do any configuration"
+ def __init__( self, name, **params ):
+ self.name = ''
+
+class NullLink( Link ):
+ "A dummy link that doesn't touch either interface"
+ def makeIntfPair( cls, intf1, intf2, addr1=None, addr2=None ):
+ pass
+ def delete( self ):
+ pass
+
+class OpticalTopo( Topo ):
+
+ def addIntf( self, switch, intfName ):
+ "Add intf intfName to switch"
+ self.addLink( switch, switch, cls=NullLink,
+ intfName1=intfName, cls2=NullIntf, intfName2=intfName )
+
+ def build( self, n=2, tapStart=3 ):
+
+ # Add hosts and switches
+ hosts = []
+ switches = []
+ for i in irange( 1, n ):
+ h = self.addHost( 'h%d' % i )
+ s = self.addSwitch( 's%d' % i, dpid="0000ffffffff%04d" % i )
+ self.addLink( h, s )
+ hosts.append( h )
+ switches.append( s )
+
+ # Add optical tap interfaces
+ tapNum = tapStart
+ for sw in switches:
+ self.addIntf( sw, 'tap%d' % tapNum )
+ tapNum += 1
+
+# if you use, sudo mn --custom custom/optical.py, then register the topo:
+#sudo mn --custom optical.py --topo optical,5
+topos = { 'optical': OpticalTopo }
+
+def installStaticFlows( net ):
+ for sw in net.switches:
+ info( 'Adding flows to %s...' % sw.name )
+ sw.dpctl( 'add-flow', 'in_port=1,actions=output=2' )
+ sw.dpctl( 'add-flow', 'in_port=2,actions=output=1' )
+ info( sw.dpctl( 'dump-flows' ) )
+
+def run( n ):
+ topo = OpticalTopo( n )
+ net = Mininet( topo=topo, controller=RemoteController, autoSetMacs=True )
+ net.start()
+ #installStaticFlows( net )
+ CLI( net )
+ net.stop()
+
+# if the script is run directly (sudo custom/optical.py):
+if __name__ == '__main__':
+ import sys
+ try:
+ n = int( sys.argv[1] )
+ except:
+ print ( 'Usage: ./optical.py n # n is number of switches\n'
+ 'Starting with default of 2 switches...\n' )
+ n = 2
+ setLogLevel( 'info' )
+ run( n )
diff --git a/framework/src/onos/tools/test/topos/optical2.py b/framework/src/onos/tools/test/topos/optical2.py
new file mode 100644
index 00000000..36cdbadd
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/optical2.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+''' file: custom/optical.py '''
+
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.log import setLogLevel, info
+from mininet.link import Intf, Link
+from mininet.node import RemoteController
+
+class NullIntf( Intf ):
+ "A dummy interface with a blank name that doesn't do any configuration"
+ def __init__( self, name, **params ):
+ self.name = ''
+
+class NullLink( Link ):
+ "A dummy link that doesn't touch either interface"
+ def makeIntfPair( cls, intf1, intf2, *args, **kwargs ):
+ pass
+ def delete( self ):
+ pass
+
+class OpticalTopo(Topo):
+ def addIntf( self, switch, intfName ):
+ "Add intf intfName to switch"
+ self.addLink( switch, switch, cls=NullLink,
+ intfName1=intfName, cls2=NullIntf )
+ def __init__(self):
+
+ # Initialize topology
+ Topo.__init__(self)
+
+ # Add hosts and switches
+ h1 = self.addHost('h1')
+ h2 = self.addHost('h2')
+ h3 = self.addHost('h3')
+ h4 = self.addHost('h4')
+ h5 = self.addHost('h5')
+ h6 = self.addHost('h6')
+
+ s1 = self.addSwitch('s1', dpid="0000ffffffff0001")
+ s2 = self.addSwitch('s2', dpid="0000ffffffff0002")
+ s3 = self.addSwitch('s3', dpid="0000ffffffff0003")
+ s4 = self.addSwitch('s4', dpid="0000ffffffff0004")
+ s5 = self.addSwitch('s5', dpid="0000ffffffff0005")
+ s6 = self.addSwitch('s6', dpid="0000ffffffff0006")
+
+
+ # Add links from hosts to OVS
+ self.addLink(s1, h1)
+ self.addLink(s2, h2)
+ self.addLink(s3, h3)
+ self.addLink(s4, h4)
+ self.addLink(s5, h5)
+ self.addLink(s6, h6)
+
+ # add links from ovs to linc-oe
+ # sorry about the syntax :(
+ self.addIntf(s1,'tap29')
+ self.addIntf(s2,'tap30')
+ self.addIntf(s3,'tap31')
+ self.addIntf(s4,'tap32')
+ self.addIntf(s5,'tap33')
+ self.addIntf(s6,'tap34')
+
+ # if you use, sudo mn --custom custom/optical.py, then register the topo:
+topos = {'optical': ( lambda: OpticalTopo() )}
+
+
+def run():
+ c = RemoteController('c','127.0.0.1',6633)
+ net = Mininet( topo=OpticalTopo(),controller=None,autoSetMacs=True)
+ net.addController(c)
+ net.start()
+
+ #installStaticFlows( net )
+ CLI( net )
+ net.stop()
+
+# if the script is run directly (sudo custom/optical.py):
+if __name__ == '__main__':
+ setLogLevel('info')
+ run()
diff --git a/framework/src/onos/tools/test/topos/opticalTest.py b/framework/src/onos/tools/test/topos/opticalTest.py
new file mode 100644
index 00000000..b34f08da
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/opticalTest.py
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+
+from opticalUtils import MininetOE, LINCSwitch, LINCLink
+from mininet.topo import Topo
+from mininet.log import setLogLevel
+from mininet.node import RemoteController
+from mininet.cli import CLI
+
+class SmallOpticalTopo( Topo ):
+
+ def build( self ):
+ o1ann = { "latitude": 37.6, "longitude": -122.3, "optical.regens": 0 }
+ O1 = self.addSwitch( 'SFO-W10', dpid='0000ffffffffff01', annotations=o1ann, cls=LINCSwitch )
+ o2ann = { "latitude": 37.3, "longitude": -121.9, "optical.regens": 0 }
+ O2 = self.addSwitch( 'SJC-W10', dpid='0000ffffffffff02', annotations=o2ann, cls=LINCSwitch )
+ o3ann = { "latitude": 33.9, "longitude": -118.4, "optical.regens": 0 }
+ O3 = self.addSwitch( 'LAX-W10', dpid='0000ffffffffff03', annotations=o3ann, cls=LINCSwitch )
+ o4ann = { "latitude": 32.8, "longitude": -117.1, "optical.regens": 3 }
+ O4 = self.addSwitch( 'SDG-W10', dpid='0000ffffffffff04', annotations=o4ann, cls=LINCSwitch )
+ o5ann = { "latitude": 44.8, "longitude": -93.1, "optical.regens": 3 }
+ O5 = self.addSwitch( 'MSP-M10', dpid='0000ffffffffff05', annotations=o5ann, cls=LINCSwitch )
+ o6ann = { "latitude": 32.8, "longitude": -97.1, "optical.regens": 3 }
+ O6 = self.addSwitch( 'DFW-M10', dpid='0000ffffffffff06', annotations=o6ann, cls=LINCSwitch )
+ o7ann = { "latitude": 41.8, "longitude": -87.6, "optical.regens": 3 }
+ O7 = self.addSwitch( 'CHG-N10', dpid='0000ffffffffff07', annotations=o7ann, cls=LINCSwitch )
+ o8ann = { "latitude": 38.8, "longitude": -77.1, "optical.regens": 3 }
+ O8 = self.addSwitch( 'IAD-M10', dpid='0000ffffffffff08', annotations=o8ann, cls=LINCSwitch )
+ o9ann = { "latitude": 40.8, "longitude": -73.1, "optical.regens": 0 }
+ O9 = self.addSwitch( 'JFK-M10', dpid='0000ffffffffff09', annotations=o9ann, cls=LINCSwitch )
+ o10ann = { "latitude": 33.8, "longitude": -84.1, "optical.regens": 0 }
+ O10 = self.addSwitch( 'ATL-S10', dpid='0000ffffffffff0a', annotations=o10ann, cls=LINCSwitch )
+
+
+ SFOR10 = self.addSwitch( 'SFO-R10', dpid='0000ffffffff0001', annotations={"latitude": 37.6, "longitude": -122.3} )
+ LAXR10 = self.addSwitch( 'LAX-R10', dpid='0000ffffffff0002', annotations={ "latitude": 33.9, "longitude": -118.4 } )
+ SDGR10 = self.addSwitch( 'SDG-R10', dpid='0000ffffffff0003', annotations={ "latitude": 32.8, "longitude": -117.1 } )
+ CHGR10 = self.addSwitch( 'CHG-R10', dpid='0000ffffffff0004', annotations={ "latitude": 41.8, "longitude": -87.6 } )
+ JFKR10 = self.addSwitch( 'JFK-R10', dpid='0000ffffffff0005', annotations={ "latitude": 40.8, "longitude": -73.1 } )
+ ATLR10 = self.addSwitch( 'ATL-R10', dpid='0000ffffffff0006', annotations={ "latitude": 33.8, "longitude": -84.1 } )
+
+ self.addLink( O1, O2, port1=50, port2=30, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O2, O3, port1=50, port2=30, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O3, O4, port1=50, port2=50, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O1, O5, port1=20, port2=50, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O2, O5, port1=20, port2=20, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O3, O6, port1=20, port2=50, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O4, O6, port1=20, port2=20, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O5, O6, port1=30, port2=40, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O5, O7, port1=40, port2=50, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O6, O8, port1=30, port2=50, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O7, O8, port1=20, port2=30, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O7, O9, port1=30, port2=50, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O8, O10, port1=20, port2=50, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+ self.addLink( O9, O10, port1=20, port2=20, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" }, cls=LINCLink )
+
+ self.addLink( SFOR10, O1, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SFOR10, O1, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+
+ self.addLink( LAXR10, O3, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ # added second tap
+ self.addLink( LAXR10, O3, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SDGR10, O4, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( CHGR10, O7, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+
+ self.addLink( JFKR10, O9, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( JFKR10, O9, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+
+ self.addLink( ATLR10, O10, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+
+ h1 = self.addHost( 'h1' )
+ h2 = self.addHost( 'h2' )
+ h3 = self.addHost( 'h3' )
+ h4 = self.addHost( 'h4' )
+ h5 = self.addHost( 'h5' )
+ h6 = self.addHost( 'h6' )
+
+ self.addLink( SFOR10, h1, port1=1 )
+ self.addLink( LAXR10, h2, port1=1 )
+ self.addLink( SDGR10, h3, port1=1 )
+ self.addLink( CHGR10, h4, port1=1 )
+ self.addLink( JFKR10, h5, port1=1 )
+ self.addLink( ATLR10, h6, port1=1 )
+
+if __name__ == '__main__':
+ import sys
+ if len( sys.argv ) >= 2:
+ controllers = sys.argv[1:]
+ else:
+ print 'Usage:sudo -E python opticalTest.py (<Controller IP>)+'
+ print 'Using localhost...\n'
+ controllers = [ '127.0.0.1' ]
+
+ setLogLevel( 'info' )
+ net = MininetOE( topo=SmallOpticalTopo(), controller=None, autoSetMacs=True )
+ net.addControllers( controllers )
+ net.start()
+ CLI( net )
+ net.stop()
diff --git a/framework/src/onos/tools/test/topos/opticalTestBig.py b/framework/src/onos/tools/test/topos/opticalTestBig.py
new file mode 100644
index 00000000..943699b0
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/opticalTestBig.py
@@ -0,0 +1,391 @@
+#!/usr/bin/python
+
+from opticalUtils import MininetOE, LINCSwitch, LINCLink
+from mininet.topo import Topo
+from mininet.log import setLogLevel
+from mininet.node import RemoteController
+from mininet.cli import CLI
+
+class BigOpticalTopo( Topo ):
+
+ def build( self ):
+ # Optical layer ROADMs
+ o1ann = { "latitude": 32.508086, "longitude": -99.741564, "optical.regens": 0 }
+ O1 = self.addSwitch( 'ABLNTXRO', dpid='0000ffffffffff01', annotations=o1ann, cls=LINCSwitch )
+ o2ann = { "latitude": 35.084446, "longitude": -106.649719, "optical.regens": 0 }
+ O2 = self.addSwitch( 'ALBQNMMA', dpid='0000ffffffffff02', annotations=o2ann, cls=LINCSwitch )
+ o3ann = { "latitude": 42.652222, "longitude": -73.758333, "optical.regens": 0 }
+ O3 = self.addSwitch( 'ALBYNYSS', dpid='0000ffffffffff03', annotations=o3ann, cls=LINCSwitch )
+ o4ann = { "latitude": 33.755833, "longitude": -97.743057, "optical.regens": 5 }
+ O4 = self.addSwitch( 'ATLNGATL', dpid='0000ffffffffff04', annotations=o4ann, cls=LINCSwitch ) # ATLNGATL Connected to packet node
+ o5ann = { "latitude": 42.882778, "longitude": -78.877778, "optical.regens": 0 }
+ O5 = self.addSwitch( 'BFLONYFR', dpid='0000ffffffffff05', annotations=o5ann, cls=LINCSwitch )
+ o6ann = { "latitude": 45.781667, "longitude": -108.509167, "optical.regens": 0 }
+ O6 = self.addSwitch( 'BLNGMTMA', dpid='0000ffffffffff06', annotations=o6ann, cls=LINCSwitch )
+ o7ann = { "latitude": 39.293781, "longitude": -76.614127, "optical.regens": 0 }
+ O7 = self.addSwitch( 'BLTMMDCH', dpid='0000ffffffffff07', annotations=o7ann, cls=LINCSwitch )
+ o8ann = { "latitude": 33.517223, "longitude": -86.812225, "optical.regens": 0 }
+ O8 = self.addSwitch( 'BRHMALMT', dpid='0000ffffffffff08', annotations=o8ann, cls=LINCSwitch )
+ o9ann = { "latitude": 46.836379, "longitude": -100.796917, "optical.regens": 0 }
+ O9 = self.addSwitch( 'BSMRNDJC', dpid='0000ffffffffff09', annotations=o9ann, cls=LINCSwitch )
+ o10ann = { "latitude": 30.449722, "longitude": -91.184167, "optical.regens": 0 }
+ O10 = self.addSwitch( 'BTRGLAMA', dpid='0000ffffffffff0a', annotations=o10ann, cls=LINCSwitch )
+ o11ann = { "latitude": 41.881484, "longitude": -87.640432, "optical.regens": 4 }
+ O11 = self.addSwitch( 'CHCGILCL', dpid='0000ffffffffff0b', annotations=o11ann, cls=LINCSwitch )
+ o12ann = { "latitude": 35.224924, "longitude": -80.837502, "optical.regens": 0 }
+ O12 = self.addSwitch( 'CHRLNCCA', dpid='0000ffffffffff0c', annotations=o12ann, cls=LINCSwitch )
+ o13ann = { "latitude": 32.785278, "longitude": -79.938056, "optical.regens": 0 }
+ O13 = self.addSwitch( 'CHTNSCDT', dpid='0000ffffffffff0d', annotations=o13ann, cls=LINCSwitch )
+ o14ann = { "latitude": 41.498333, "longitude": -81.686943, "optical.regens": 0 }
+ O14 = self.addSwitch( 'CLEVOH02', dpid='0000ffffffffff0e', annotations=o14ann, cls=LINCSwitch )
+ o15ann = { "latitude": 39.965279, "longitude": -82.996666, "optical.regens": 0 }
+ O15 = self.addSwitch( 'CLMBOH11', dpid='0000ffffffffff0f', annotations=o15ann, cls=LINCSwitch )
+ o16ann = { "latitude": 42.36745, "longitude": -71.084918, "optical.regens": 0 }
+ O16 = self.addSwitch( 'CMBRMA01', dpid='0000ffffffffff10', annotations=o16ann, cls=LINCSwitch )
+ o17ann = { "latitude": 39.102778, "longitude": -84.516944, "optical.regens": 0 }
+ O17 = self.addSwitch( 'CNCNOHWS', dpid='0000ffffffffff11', annotations=o17ann, cls=LINCSwitch )
+ o18ann = { "latitude": 32.797524, "longitude": -96.780431, "optical.regens": 0 }
+ O18 = self.addSwitch( 'DLLSTXTL', dpid='0000ffffffffff12', annotations=o18ann, cls=LINCSwitch ) # DLLSTXTL Connected to packet node
+ o19ann = { "latitude": 39.744999, "longitude": -104.996391, "optical.regens": 0 }
+ O19 = self.addSwitch( 'DNVRCOMA', dpid='0000ffffffffff13', annotations=o19ann, cls=LINCSwitch )
+ o20ann = { "latitude": 42.332779, "longitude": -83.054169, "optical.regens": 5 }
+ O20 = self.addSwitch( 'DTRTMIBA', dpid='0000ffffffffff14', annotations=o20ann, cls=LINCSwitch )
+ o21ann = { "latitude": 31.756389, "longitude": -106.483611, "optical.regens": 0 }
+ O21 = self.addSwitch( 'ELPSTXMA', dpid='0000ffffffffff15', annotations=o21ann, cls=LINCSwitch )
+ o22ann = { "latitude": 36.73923, "longitude": -119.79423, "optical.regens": 0 }
+ O22 = self.addSwitch( 'FRSNCA01', dpid='0000ffffffffff16', annotations=o22ann, cls=LINCSwitch )
+ o23ann = { "latitude": 36.072222, "longitude": -79.793889, "optical.regens": 0 }
+ O23 = self.addSwitch( 'GNBONCEU', dpid='0000ffffffffff17', annotations=o23ann, cls=LINCSwitch )
+ o24ann = { "latitude": 41.765833, "longitude": -72.676389, "optical.regens": 0 }
+ O24 = self.addSwitch( 'HRFRCT03', dpid='0000ffffffffff18', annotations=o24ann, cls=LINCSwitch )
+ o25ann = { "latitude": 29.748333, "longitude": -95.36528, "optical.regens": 0 }
+ O25 = self.addSwitch( 'HSTNTX01', dpid='0000ffffffffff19', annotations=o25ann, cls=LINCSwitch )
+ o26ann = { "latitude": 30.33071, "longitude": -81.43, "optical.regens": 0 }
+ O26 = self.addSwitch( 'JCVLFLCL', dpid='0000ffffffffff1a', annotations=o26ann, cls=LINCSwitch )
+ o27ann = { "latitude": 39.096649, "longitude": -94.578716, "optical.regens": 0 }
+ O27 = self.addSwitch( 'KSCYMO09', dpid='0000ffffffffff1b', annotations=o27ann, cls=LINCSwitch )
+ o28ann = { "latitude": 40.5899999,"longitude": -73.6699993, "optical.regens": 0 }
+ O28 = self.addSwitch( 'LGISLAND', dpid='0000ffffffffff1c', annotations=o28ann, cls=LINCSwitch )
+ o29ann = { "latitude": 34.051227, "longitude": -118.252958, "optical.regens": 0 }
+ O29 = self.addSwitch( 'LSANCA03', dpid='0000ffffffffff1d', annotations=o29ann, cls=LINCSwitch ) # LSANCA03 Connected to packet node
+ o30ann = { "latitude": 36.168056, "longitude": -115.138889, "optical.regens": 0 }
+ O30 = self.addSwitch( 'LSVGNV02', dpid='0000ffffffffff1e', annotations=o30ann, cls=LINCSwitch )
+ o31ann = { "latitude":38.249167, "longitude": -85.760833, "optical.regens": 0 }
+ O31 = self.addSwitch( 'LSVLKYCS', dpid='0000ffffffffff1f', annotations=o31ann, cls=LINCSwitch )
+ o32ann = { "latitude": 34.740833, "longitude": -92.271942, "optical.regens": 2 }
+ O32 = self.addSwitch( 'LTRKARFR', dpid='0000ffffffffff20', annotations=o32ann, cls=LINCSwitch )
+ o33ann = { "latitude": 25.779167, "longitude": -80.195, "optical.regens": 0 }
+ O33 = self.addSwitch( 'MIAMFLAC', dpid='0000ffffffffff21', annotations=o33ann, cls=LINCSwitch )
+ o34ann = { "latitude": 43.037224, "longitude": -87.922501, "optical.regens": 0 }
+ O34 = self.addSwitch( 'MILWWIHE', dpid='0000ffffffffff22', annotations=o34ann, cls=LINCSwitch )
+ o35ann = { "latitude": 35.145158, "longitude": -90.048058, "optical.regens": 0 }
+ O35 = self.addSwitch( 'MMPHTNMA', dpid='0000ffffffffff23', annotations=o35ann, cls=LINCSwitch )
+ o36ann = { "latitude": 44.977365, "longitude": -93.26718, "optical.regens": 0 }
+ O36 = self.addSwitch( 'MPLSMNDT', dpid='0000ffffffffff24', annotations=o36ann, cls=LINCSwitch ) # MPLSMNDT Connected to packet node
+ o37ann = { "latitude": 36.853333, "longitude": -76.29, "optical.regens": 0 }
+ O37 = self.addSwitch( 'NRFLVABS', dpid='0000ffffffffff25', annotations=o37ann, cls=LINCSwitch )
+ o38ann = { "latitude": 36.163955, "longitude": -86.775558, "optical.regens": 0 }
+ O38 = self.addSwitch( 'NSVLTNMT', dpid='0000ffffffffff26', annotations=o38ann, cls=LINCSwitch )
+ o39ann = { "latitude": 29.949806, "longitude": -90.07222, "optical.regens": 0 }
+ O39 = self.addSwitch( 'NWORLAMA', dpid='0000ffffffffff27', annotations=o39ann, cls=LINCSwitch )
+ o40ann = { "latitude": 40.734408, "longitude": -74.177978, "optical.regens": 0 }
+ O40 = self.addSwitch( 'NWRKNJ02', dpid='0000ffffffffff28', annotations=o40ann, cls=LINCSwitch ) # NWRKNJ02 Connected to packet node
+ o41ann = { "latitude": 40.767497, "longitude": -73.989713, "optical.regens": 0 }
+ O41 = self.addSwitch( 'NYCMNY54', dpid='0000ffffffffff29', annotations=o41ann, cls=LINCSwitch )
+ o42ann = { "latitude": 35.470833, "longitude": -97.515274, "optical.regens": 0 }
+ O42 = self.addSwitch( 'OKCYOKCE', dpid='0000ffffffffff2a', annotations=o42ann, cls=LINCSwitch )
+ o43ann = { "latitude": 37.805556, "longitude": -122.268889, "optical.regens": 2 }
+ O43 = self.addSwitch( 'OKLDCA03', dpid='0000ffffffffff2b', annotations=o43ann, cls=LINCSwitch )
+ o44ann = { "latitude": 41.259167, "longitude":-95.940277, "optical.regens": 0 }
+ O44 = self.addSwitch( 'OMAHNENW', dpid='0000ffffffffff2c', annotations=o44ann, cls=LINCSwitch )
+ o45ann = { "latitude": 28.543279, "longitude": -81.377502, "optical.regens": 0 }
+ O45 = self.addSwitch( 'ORLDFLMA', dpid='0000ffffffffff2d', annotations=o45ann, cls=LINCSwitch ) # ORLDFLMA Connected to packet node
+ o46ann = { "latitude": 39.946446, "longitude": -75.184139, "optical.regens": 0 }
+ O46 = self.addSwitch( 'PHLAPASL', dpid='0000ffffffffff2e', annotations=o46ann, cls=LINCSwitch )
+ o47ann = { "latitude": 33.450361, "longitude": -112.07709, "optical.regens": 0 }
+ O47 = self.addSwitch( 'PHNXAZMA', dpid='0000ffffffffff2f', annotations=o47ann, cls=LINCSwitch ) # PHNXAZMA Connected to packet node
+ o48ann = { "latitude":40.441387, "longitude": -79.995552, "optical.regens": 0 }
+ O48 = self.addSwitch( 'PITBPADG', dpid='0000ffffffffff30', annotations=o48ann, cls=LINCSwitch )
+ o49ann = { "latitude":41.818889, "longitude": -71.415278, "optical.regens": 0 }
+ O49 = self.addSwitch( 'PRVDRIGR', dpid='0000ffffffffff31', annotations=o49ann, cls=LINCSwitch )
+ o50ann = { "latitude": 45.522499, "longitude": -122.678055, "optical.regens": 2 }
+ O50 = self.addSwitch( 'PTLDOR62', dpid='0000ffffffffff32', annotations=o50ann, cls=LINCSwitch )
+ o51ann = { "latitude": 37.540752, "longitude": -77.436096, "optical.regens": 0 }
+ O51 = self.addSwitch( 'RCMDVAGR', dpid='0000ffffffffff33', annotations=o51ann, cls=LINCSwitch )
+ o52ann = { "latitude": 35.779656, "longitude": -78.640831, "optical.regens": 0 }
+ O52 = self.addSwitch( 'RLGHNCMO', dpid='0000ffffffffff34', annotations=o52ann, cls=LINCSwitch )
+ o53ann = { "latitude": 43.157222, "longitude": -77.616389, "optical.regens": 0 }
+ O53 = self.addSwitch( 'ROCHNYXA', dpid='0000ffffffffff35', annotations=o53ann, cls=LINCSwitch ) # ROCHNYXA Connected to packet node
+ o54ann = { "latitude": 38.578609, "longitude": -121.487221, "optical.regens": 0 }
+ O54 = self.addSwitch( 'SCRMCA01', dpid='0000ffffffffff36', annotations=o54ann, cls=LINCSwitch )
+ o55ann = { "latitude": 41.415278, "longitude": -75.649167, "optical.regens": 0 }
+ O55 = self.addSwitch( 'SCTNPA01', dpid='0000ffffffffff37', annotations=o55ann, cls=LINCSwitch )
+ o56ann = { "latitude": 40.767776, "longitude": -111.888336, "optical.regens": 0 }
+ O56 = self.addSwitch( 'SLKCUTMA', dpid='0000ffffffffff38', annotations=o56ann, cls=LINCSwitch )
+ o57ann = { "latitude": 29.429445, "longitude": -98.488892, "optical.regens": 0 }
+ O57 = self.addSwitch( 'SNANTXCA', dpid='0000ffffffffff39', annotations=o57ann, cls=LINCSwitch ) # SNANTXCA Connected to packet node
+ o58ann = { "latitude": 34.418889, "longitude": -119.7, "optical.regens": 0 }
+ O58 = self.addSwitch( 'SNBBCA01', dpid='0000ffffffffff3a', annotations=o58ann, cls=LINCSwitch )
+ o59ann = { "latitude":32.746944, "longitude": -117.158611, "optical.regens": 0 }
+ O59 = self.addSwitch( 'SNDGCA02', dpid='0000ffffffffff3b', annotations=o59ann, cls=LINCSwitch )
+ o60ann = { "latitude":37.785143, "longitude": -122.397263, "optical.regens": 0 }
+ O60 = self.addSwitch( 'SNFCCA21', dpid='0000ffffffffff3c', annotations=o60ann, cls=LINCSwitch )
+ o61ann = { "latitude": 37.333333, "longitude": -121.892778, "optical.regens": 0 }
+ O61 = self.addSwitch( 'SNJSCA02', dpid='0000ffffffffff3d', annotations=o61ann, cls=LINCSwitch ) # SNJSCA02 Connected to packet node
+ o62ann = { "latitude": 39.795278, "longitude": -89.649444, "optical.regens": 0 }
+ O62 = self.addSwitch( 'SPFDILSD', dpid='0000ffffffffff3e', annotations=o62ann, cls=LINCSwitch )
+ o63ann = { "latitude": 47.654724, "longitude": -117.419167, "optical.regens": 0 }
+ O63 = self.addSwitch( 'SPKNWA01', dpid='0000ffffffffff3f', annotations=o63ann, cls=LINCSwitch )
+ o64ann = { "latitude": 38.633335, "longitude": -90.215279, "optical.regens": 0 }
+ O64 = self.addSwitch( 'STLSMO09', dpid='0000ffffffffff40', annotations=o64ann, cls=LINCSwitch )
+ o65ann = { "latitude": 47.606945, "longitude": -122.333336, "optical.regens": 0 }
+ O65 = self.addSwitch( 'STTLWA06', dpid='0000ffffffffff41', annotations=o65ann, cls=LINCSwitch )
+ o66ann = { "latitude": 43.049444, "longitude": -76.1475, "optical.regens": 3 }
+ O66 = self.addSwitch( 'SYRCNYSU', dpid='0000ffffffffff42', annotations=o66ann, cls=LINCSwitch )
+ o67ann = { "latitude": 28.0225, "longitude": -82.522778, "optical.regens": 0 }
+ O67 = self.addSwitch( 'TAMQFLFN', dpid='0000ffffffffff43', annotations=o67ann, cls=LINCSwitch )
+ o68ann = { "latitude": 32.224444, "longitude": -110.968333, "optical.regens": 0 }
+ O68 = self.addSwitch( 'TCSNAZMA', dpid='0000ffffffffff44', annotations=o68ann, cls=LINCSwitch )
+ o69ann = { "latitude": 30.456389, "longitude": -84.290833, "optical.regens": 0 }
+ O69 = self.addSwitch( 'TLHSFLAT', dpid='0000ffffffffff45', annotations=o69ann, cls=LINCSwitch )
+ o70ann = { "latitude": 41.65, "longitude": -83.538056, "optical.regens": 2 }
+ O70 = self.addSwitch( 'TOLDOH21', dpid='0000ffffffffff46', annotations=o70ann, cls=LINCSwitch )
+ o71ann = { "latitude": 36.151669, "longitude": -95.985832, "optical.regens": 0 }
+ O71 = self.addSwitch( 'TULSOKTB', dpid='0000ffffffffff47', annotations=o71ann, cls=LINCSwitch )
+ o72ann = { "latitude": 38.88306 , "longitude": -77.01028, "optical.regens": 0 }
+ O72 = self.addSwitch( 'WASHDCSW', dpid='0000ffffffffff48', annotations=o72ann, cls=LINCSwitch ) # WASHDCSW Connected to packet node
+ o73ann = { "latitude": 39.739167, "longitude": -75.553889, "optical.regens": 0 }
+ O73 = self.addSwitch( 'WLMGDE01', dpid='0000ffffffffff49', annotations=o73ann, cls=LINCSwitch )
+ o74ann = { "latitude": 26.709391, "longitude": -80.05278, "optical.regens": 0 }
+ O74 = self.addSwitch( 'WPBHFLAN', dpid='0000ffffffffff4a', annotations=o74ann, cls=LINCSwitch )
+ o75ann = { "latitude": 29.57, "longitude": -96.7, "optical.regens": 0 }
+ O75 = self.addSwitch( 'AUSTTXGR', dpid='0000ffffffffff4b', annotations=o75ann, cls=LINCSwitch )
+ #o25ann = { "latitude": 29.748333, "longitude": -95.36528, "optical.regens": 0 }
+ #o57ann = { "latitude": 29.429445, "longitude": -98.488892, "optical.regens": 0 }
+
+
+ # Packet Layer switches
+ ''' # from opticalTest.py
+ SFOR10 = self.addSwitch( 'SFO-R10', dpid='0000ffffffff0001', annotations={"latitude": 37.6, "longitude": -122.3} )
+ LAXR10 = self.addSwitch( 'LAX-R10', dpid='0000ffffffff0002', annotations={ "latitude": 33.9, "longitude": -118.4 } )
+ SDGR10 = self.addSwitch( 'SDG-R10', dpid='0000ffffffff0003', annotations={ "latitude": 32.8, "longitude": -117.1 } )
+ CHGR10 = self.addSwitch( 'CHG-R10', dpid='0000ffffffff0004', annotations={ "latitude": 41.8, "longitude": -87.6 } )
+ JFKR10 = self.addSwitch( 'JFK-R10', dpid='0000ffffffff0005', annotations={ "latitude": 40.8, "longitude": -73.1 } )
+ ATLR10 = self.addSwitch( 'ATL-R10', dpid='0000ffffffff0006', annotations={ "latitude": 33.8, "longitude": -84.1 } )
+ '''
+ WASHDCSWR = self.addSwitch( 'WASHDCSW-R', dpid='0000ffffff000001', annotations={ "latitude": 38.8, "longitude": -77.0 } ) # this switch is O72
+ SNJSCA02R = self.addSwitch( 'SNJSCA02-R', dpid='0000ffffff000002', annotations={ "latitude": 37.3, "longitude": -121.8 } ) # O61
+ SNANTXCAR = self.addSwitch( 'SNANTXCA-R', dpid='0000ffffff000003', annotations={ "latitude": 29.4, "longitude": -98.4 } ) # O57
+ ROCHNYXAR = self.addSwitch( 'ROCHNYXA-R', dpid='0000ffffff000004', annotations={ "latitude": 43.1, "longitude": -77.6 } ) # O53
+ PHNXAZMAR = self.addSwitch( 'PHNXAZMA-R', dpid='0000ffffff000005', annotations={ "latitude": 33.4, "longitude": -112.0 } ) # O47
+ ORLDFLMAR = self.addSwitch( 'ORLDFLMA-R', dpid='0000ffffff000006', annotations={ "latitude": 28.5, "longitude": -81.3 } ) # O45
+ NWRKNJ02R = self.addSwitch( 'NWRKNJ02-R', dpid='0000ffffff000007', annotations={ "latitude": 40.7, "longitude": -74.1 } ) # O40
+ MPLSMNDTR = self.addSwitch( 'MPLSMNDT-R', dpid='0000ffffff000008', annotations={ "latitude": 44.9, "longitude": -93.2 } ) # O36
+ LSANCA03R = self.addSwitch( 'LSANCA03-R', dpid='0000ffffff000009', annotations={ "latitude": 34.1, "longitude": -118.3 } ) # O29
+ DLLSTXTLR = self.addSwitch( 'DLLSTXTL-R', dpid='0000ffffff00000a', annotations={ "latitude": 32.7, "longitude": -96.7 } ) # O18
+ ATLNGATLR = self.addSwitch( 'ATLNGATL-R', dpid='0000ffffff00000b', annotations={ "latitude": 33.7, "longitude": -97.7 } ) # O4
+
+
+
+ # Optical Links between the ROADMs (although Distance is not used; we should keep these for future reference)
+ self.addLink( O1, O18, port1=100, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 334, "durable": "true" }, cls=LINCLink ) # ABLNTXRO DLLSTXTL
+ self.addLink( O1, O21, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 768, "durable": "true" }, cls=LINCLink ) # ABLNTXRO ELPSTXMA
+ self.addLink( O3, O16, port1=100, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 265, "durable": "true" }, cls=LINCLink ) # ALBYNYSS CMBRMA01
+ self.addLink( O3, O66, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 239, "durable": "true" }, cls=LINCLink ) # ALBYNYSS SYRCNYSU
+ self.addLink( O2, O18, port1=100, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1134, "durable": "true" }, cls=LINCLink ) # ALBQNMMA DLLSTXTL
+ self.addLink( O2, O19, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 646, "durable": "true" }, cls=LINCLink ) # ALBQNMMA DNVRCOMA
+ self.addLink( O2, O21, port1=102, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 444, "durable": "true" }, cls=LINCLink ) # ALBQNMMA ELPSTXMA
+ self.addLink( O2, O30, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 931, "durable": "true" }, cls=LINCLink ) # ALBQNMMA LSVGNV02
+ self.addLink( O4, O8, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 271, "durable": "true" }, cls=LINCLink ) # ATLNGATL BRHMALMT
+ self.addLink( O4, O12, port1=102, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 436, "durable": "true" }, cls=LINCLink ) # ATLNGATL CHRLNCCA
+ self.addLink( O4, O26, port1=103, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 566, "durable": "true" }, cls=LINCLink ) # ATLNGATL JCVLFLCL
+ self.addLink( O75, O25, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 283, "durable": "true" }, cls=LINCLink ) # AUSTTXGR HSTNTX01
+ self.addLink( O75, O57, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 141, "durable": "true" }, cls=LINCLink ) # AUSTTXGR SNANTXCA
+ self.addLink( O7, O46, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 170, "durable": "true" }, cls=LINCLink ) # BLTMMDCH PHLAPASL
+ self.addLink( O7, O48, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 378, "durable": "true" }, cls=LINCLink ) # BLTMMDCH PITBPADG
+ self.addLink( O7, O70, port1=103, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 68, "durable": "true" }, cls=LINCLink ) # BLTMMDCH WASHDCSW
+ self.addLink( O10, O25, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 491, "durable": "true" }, cls=LINCLink ) # BTRGLAMA HSTNTX01
+ self.addLink( O10, O39, port1=102, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 144, "durable": "true" }, cls=LINCLink ) # BTRGLAMA NWORLAMA
+ self.addLink( O6, O9, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 724, "durable": "true" }, cls=LINCLink ) # BLNGMTMA BSMRNDJC
+ self.addLink( O6, O19, port1=102, port2=107, annotations={ "optical.wves": 80, "optical.type": "WDM", "optical.kms": 875, "durable": "true" }, cls=LINCLink ) # BLNGMTMA DNVRCOMA
+ self.addLink( O6, O63, port1=103, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 852, "durable": "true" }, cls=LINCLink ) # BLNGMTMA SPKNWA01
+ self.addLink( O8, O38, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 353, "durable": "true" }, cls=LINCLink ) # BRHMALMT NSVLTNMT
+ self.addLink( O8, O39, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 602, "durable": "true" }, cls=LINCLink ) # BRHMALMT NWORLAMA
+ self.addLink( O9, O36, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 741, "durable": "true" }, cls=LINCLink ) # BSMRNDJC MPLSMNDT
+ self.addLink( O16, O49, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 80, "durable": "true" }, cls=LINCLink ) # CMBRMA01 PRVDRIGR
+ self.addLink( O5, O14, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 333, "durable": "true" }, cls=LINCLink ) # BFLONYFR CLEVOH02
+ self.addLink( O5, O53, port1=104, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 128, "durable": "true" }, cls=LINCLink ) # BFLONYFR ROCHNYXA
+ self.addLink( O13, O26, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 368, "durable": "true" }, cls=LINCLink ) # CHTNSCDT JCVLFLCL
+ self.addLink( O13, O52, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 424, "durable": "true" }, cls=LINCLink ) # CHTNSCDT RLGHNCMO
+ self.addLink( O12, O23, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 160, "durable": "true" }, cls=LINCLink ) # CHRLNCCA GNBONCEU
+ self.addLink( O11, O20, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 458, "durable": "true" }, cls=LINCLink ) # CHCGILCL DTRTMIBA
+ self.addLink( O11, O34, port1=102, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 156, "durable": "true" }, cls=LINCLink ) # CHCGILCL MILWWIHE
+ self.addLink( O11, O62, port1=103, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 344, "durable": "true" }, cls=LINCLink ) # CHCGILCL SPFDILSD
+ self.addLink( O17, O15, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 194, "durable": "true" }, cls=LINCLink ) # CNCNOHWS CLMBOH11
+ self.addLink( O17, O31, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 172, "durable": "true" }, cls=LINCLink ) # CNCNOHWS LSVLKYCS
+ self.addLink( O17, O72, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 779, "durable": "true" }, cls=LINCLink ) # CNCNOHWS WASHDCSW
+ self.addLink( O14, O15, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 243, "durable": "true" }, cls=LINCLink ) # CLEVOH02 CLMBOH11
+ self.addLink( O14, O70, port1=102, port2=101, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 185, "durable": "true" }, cls=LINCLink ) # CLEVOH02 TOLDOH21
+ self.addLink( O15, O48, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 312, "durable": "true" }, cls=LINCLink ) # CLMBOH11 PITBPADG
+ self.addLink( O18, O25, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 437, "durable": "true" }, cls=LINCLink ) # DLLSTXTL HSTNTX01
+ self.addLink( O18, O32, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 563, "durable": "true" }, cls=LINCLink ) # DLLSTXTL LTRKARFR
+ self.addLink( O18, O42, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 365, "durable": "true" }, cls=LINCLink ) # DLLSTXTL OKCYOKCE
+ self.addLink( O19, O44, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 940, "durable": "true" }, cls=LINCLink ) # DNVRCOMA OMAHNENW
+ self.addLink( O19, O56, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 714, "durable": "true" }, cls=LINCLink ) # DNVRCOMA SLKCUTMA
+ self.addLink( O20, O70, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 103, "durable": "true" }, cls=LINCLink ) # DTRTMIBA TOLDOH21
+ self.addLink( O21, O57, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 969, "durable": "true" }, cls=LINCLink ) # ELPSTXMA SNANTXCA
+ self.addLink( O21, O68, port1=102, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 511, "durable": "true" }, cls=LINCLink ) # ELPSTXMA TCSNAZMA
+ self.addLink( O22, O31, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 505, "durable": "true" }, cls=LINCLink ) # FRSNCA01 LSVGNV02
+ self.addLink( O22, O29, port1=102, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 396, "durable": "true" }, cls=LINCLink ) # FRSNCA01 LSANCA03
+ self.addLink( O22, O42, port1=103, port2=108, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 298, "durable": "true" }, cls=LINCLink ) # FRSNCA01 OKLDCA03
+ self.addLink( O23, O31, port1=101, port2=108, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 697, "durable": "true" }, cls=LINCLink ) # GNBONCEU LSVLKYCS
+ self.addLink( O23, O52, port1=102, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 130, "durable": "true" }, cls=LINCLink ) # GNBONCEU RLGHNCMO
+ self.addLink( O23, O51, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 319, "durable": "true" }, cls=LINCLink ) # GNBONCEU RCMDVAGR
+ self.addLink( O24, O28, port1=101, port2=108, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 185, "durable": "true" }, cls=LINCLink ) # HRFRCT03 L_Island
+ self.addLink( O24, O49, port1=102, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 125, "durable": "true" }, cls=LINCLink ) # HRFRCT03 PRVDRIGR
+ self.addLink( O26, O45, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 238, "durable": "true" }, cls=LINCLink ) # JCVLFLCL ORLDFLMA
+ self.addLink( O27, O44, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 320, "durable": "true" }, cls=LINCLink ) # KSCYMO09 OMAHNENW
+ self.addLink( O27, O64, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 457, "durable": "true" }, cls=LINCLink ) # KSCYMO09 STLSMO09
+ self.addLink( O27, O71, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 420, "durable": "true" }, cls=LINCLink ) # KSCYMO09 TULSOKTB
+ self.addLink( O30, O47, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 494, "durable": "true" }, cls=LINCLink ) # LSVGNV02 PHNXAZMA
+ self.addLink( O30, O56, port1=102, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 701, "durable": "true" }, cls=LINCLink ) # LSVGNV02 SLKCUTMA
+ self.addLink( O32, O35, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 249, "durable": "true" }, cls=LINCLink ) # LTRKARFR MMPHTNMA
+ self.addLink( O28, O41, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 40, "durable": "true" }, cls=LINCLink ) # L_Island NYCMNY54
+ self.addLink( O29, O59, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 212, "durable": "true" }, cls=LINCLink ) # LSANCA03 SNDGCA02
+ self.addLink( O29, O58, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 167, "durable": "true" }, cls=LINCLink ) # LSANCA03 SNBBCA01
+ self.addLink( O31, O38, port1=104, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 298, "durable": "true" }, cls=LINCLink ) # LSVLKYCS NSVLTNMT
+ self.addLink( O31, O64, port1=102, port2=108, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 468, "durable": "true" }, cls=LINCLink ) # LSVLKYCS STLSMO09
+ self.addLink( O35, O38, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 380, "durable": "true" }, cls=LINCLink ) # MMPHTNMA NSVLTNMT
+ self.addLink( O33, O67, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 407, "durable": "true" }, cls=LINCLink ) # MIAMFLAC TAMQFLFN
+ self.addLink( O33, O74, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 125, "durable": "true" }, cls=LINCLink ) # MIAMFLAC WPBHFLAN
+ self.addLink( O34, O36, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 574, "durable": "true" }, cls=LINCLink ) # MILWWIHE MPLSMNDT
+ self.addLink( O36, O44, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 560, "durable": "true" }, cls=LINCLink ) # MPLSMNDT OMAHNENW
+ self.addLink( O39, O69, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 670, "durable": "true" }, cls=LINCLink ) # NWORLAMA TLHSFLAT
+ self.addLink( O41, O40, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 19, "durable": "true" }, cls=LINCLink ) # NYCMNY54 NWRKNJ02
+ self.addLink( O41, O55, port1=102, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 187, "durable": "true" }, cls=LINCLink ) # NYCMNY54 SCTNPA01
+ self.addLink( O41, O73, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 210, "durable": "true" }, cls=LINCLink ) # NYCMNY54 WLMGDE01
+ self.addLink( O40, O46, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 146, "durable": "true" }, cls=LINCLink ) # NWRKNJ02 PHLAPASL
+ self.addLink( O37, O52, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 290, "durable": "true" }, cls=LINCLink ) # NRFLVABS RLGHNCMO
+ self.addLink( O37, O73, port1=102, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 392, "durable": "true" }, cls=LINCLink ) # NRFLVABS WLMGDE01
+ self.addLink( O43, O54, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 131, "durable": "true" }, cls=LINCLink ) # OKLDCA03 SCRMCA01
+ self.addLink( O43, O56, port1=102, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1142, "durable": "true" }, cls=LINCLink ) # OKLDCA03 SLKCUTMA
+ self.addLink( O43, O60, port1=103, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 13, "durable": "true" }, cls=LINCLink ) # OKLDCA03 SNFCCA21
+ self.addLink( O42, O71, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 188, "durable": "true" }, cls=LINCLink ) # OKCYOKCE TULSOKTB
+ self.addLink( O45, O74, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 290, "durable": "true" }, cls=LINCLink ) # ORLDFLMA WPBHFLAN
+ self.addLink( O46, O55, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 201, "durable": "true" }, cls=LINCLink ) # PHLAPASL SCTNPA01
+ self.addLink( O47, O59, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 575, "durable": "true" }, cls=LINCLink ) # PHNXAZMA SNDGCA02
+ self.addLink( O47, O68, port1=102, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 205, "durable": "true" }, cls=LINCLink ) # PHNXAZMA TCSNAZMA
+ self.addLink( O48, O55, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 457, "durable": "true" }, cls=LINCLink ) # PITBPADG SCTNPA01
+ self.addLink( O50, O54, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 934, "durable": "true" }, cls=LINCLink ) # PTLDOR62 SCRMCA01
+ self.addLink( O50, O56, port1=102, port2=108, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1225, "durable": "true" }, cls=LINCLink ) # PTLDOR62 SLKCUTMA
+ self.addLink( O50, O65, port1=103, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 280, "durable": "true" }, cls=LINCLink ) # PTLDOR62 STTLWA06
+ self.addLink( O51, O72, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 184, "durable": "true" }, cls=LINCLink ) # RCMDVAGR WASHDCSW
+ self.addLink( O53, O66, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 143, "durable": "true" }, cls=LINCLink ) # ROCHNYXA SYRCNYSU
+ self.addLink( O60, O61, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 80., "durable": "true" }, cls=LINCLink ) # SNFCCA21 SNJSCA02
+ self.addLink( O61, O58, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 455, "durable": "true" }, cls=LINCLink ) # SNJSCA02 SNBBCA01
+ self.addLink( O55, O66, port1=101, port2=105, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 223, "durable": "true" }, cls=LINCLink ) # SCTNPA01 SYRCNYSU
+ self.addLink( O65, O63, port1=101, port2=107, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 442, "durable": "true" }, cls=LINCLink ) # STTLWA06 SPKNWA01
+ self.addLink( O62, O64, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 165, "durable": "true" }, cls=LINCLink ) # SPFDILSD STLSMO09
+ self.addLink( O69, O67, port1=101, port2=106, annotations={ "optical.waves": 80, "optical.type": "WDM", "optical.kms": 384, "durable": "true" }, cls=LINCLink ) # TLHSFLAT TAMQFLFN
+
+ # Packet/Optical cross connect links (this will be the tap interfaces)
+ self.addLink( WASHDCSWR, O72, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( WASHDCSWR, O72, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( WASHDCSWR, O72, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( WASHDCSWR, O72, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( WASHDCSWR, O72, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNJSCA02R, O61, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNJSCA02R, O61, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNJSCA02R, O61, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNJSCA02R, O61, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNJSCA02R, O61, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNANTXCAR, O57, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNANTXCAR, O57, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNANTXCAR, O57, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNANTXCAR, O57, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( SNANTXCAR, O57, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ROCHNYXAR, O53, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ROCHNYXAR, O53, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ROCHNYXAR, O53, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ROCHNYXAR, O53, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ROCHNYXAR, O53, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( PHNXAZMAR, O47, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( PHNXAZMAR, O47, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( PHNXAZMAR, O47, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( PHNXAZMAR, O47, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( PHNXAZMAR, O47, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ORLDFLMAR, O45, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ORLDFLMAR, O45, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ORLDFLMAR, O45, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ORLDFLMAR, O45, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ORLDFLMAR, O45, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( NWRKNJ02R, O40, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( NWRKNJ02R, O40, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( NWRKNJ02R, O40, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( NWRKNJ02R, O40, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( NWRKNJ02R, O40, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( MPLSMNDTR, O36, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( MPLSMNDTR, O36, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( MPLSMNDTR, O36, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( MPLSMNDTR, O36, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( MPLSMNDTR, O36, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( LSANCA03R, O29, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( LSANCA03R, O29, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( LSANCA03R, O29, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( LSANCA03R, O29, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( LSANCA03R, O29, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( DLLSTXTLR, O18, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( DLLSTXTLR, O18, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( DLLSTXTLR, O18, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( DLLSTXTLR, O18, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( DLLSTXTLR, O18, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ATLNGATLR, O4, port1=2, port2=10, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ATLNGATLR, O4, port1=3, port2=11, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ATLNGATLR, O4, port1=4, port2=12, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ATLNGATLR, O4, port1=5, port2=13, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+ self.addLink( ATLNGATLR, O4, port1=6, port2=14, speed1=10000, annotations={ "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" }, cls=LINCLink )
+
+
+ # Attach hosts to the packet layer switches
+ for i in range( 1, 4 ): #don't make this more than 4!!!!!
+ # Create Hosts 1..11
+ h1 = self.addHost( 'h1d%d' % i, ip='10.0.1.%d/16' % i )
+ h2 = self.addHost( 'h2d%d' % i, ip='10.0.2.%d/16' % i )
+ h3 = self.addHost( 'h3d%d' % i, ip='10.0.3.%d/16' % i )
+ h4 = self.addHost( 'h4d%d' % i, ip='10.0.4.%d/16' % i )
+ h5 = self.addHost( 'h5d%d' % i, ip='10.0.5.%d/16' % i )
+ h6 = self.addHost( 'h6d%d' % i, ip='10.0.6.%d/16' % i )
+ h7 = self.addHost( 'h7d%d' % i, ip='10.0.7.%d/16' % i )
+ h8 = self.addHost( 'h8d%d' % i, ip='10.0.8.%d/16' % i )
+ h9 = self.addHost( 'h9d%d' % i, ip='10.0.9.%d/16' % i )
+ h10 = self.addHost( 'h10d%d' % i, ip='10.0.10.%d/16' % i )
+ h11 = self.addHost( 'h11d%d' % i, ip='10.0.11.%d/16' % i )
+
+ port = i + 6
+ self.addLink( SNJSCA02R, h1, port1=port )
+ self.addLink( SNANTXCAR, h2, port1=port )
+ self.addLink( ROCHNYXAR, h3, port1=port )
+ self.addLink( PHNXAZMAR, h4, port1=port )
+ self.addLink( ORLDFLMAR, h5, port1=port )
+ self.addLink( NWRKNJ02R, h6, port1=port )
+ self.addLink( MPLSMNDTR, h7, port1=port )
+ self.addLink( LSANCA03R, h8, port1=port )
+ self.addLink( DLLSTXTLR, h9, port1=port )
+ self.addLink( ATLNGATLR, h10, port1=port )
+ self.addLink( WASHDCSWR, h11, port1=port )
+
+if __name__ == '__main__':
+ import sys
+ if len( sys.argv ) >= 2:
+ controllers = sys.argv[1:]
+ else:
+ print 'Usage: sudo -E python opticalTestBig.py (<Controller IP>)+'
+ print 'Using localhost...\n'
+ controllers = [ '127.0.0.1' ]
+
+ setLogLevel( 'info' )
+ net = MininetOE( topo=BigOpticalTopo(), controller=None, autoSetMacs=True )
+ net.addControllers( controllers )
+ net.start()
+ CLI( net )
+ net.stop()
diff --git a/framework/src/onos/tools/test/topos/opticalUtils.py b/framework/src/onos/tools/test/topos/opticalUtils.py
new file mode 100644
index 00000000..bef9deca
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/opticalUtils.py
@@ -0,0 +1,771 @@
+#!/usr/bin/python
+
+'''
+Notes:
+
+This file contains classes and methods useful for integrating LincOE with Mininet,
+such as startOE, stopOE, LINCLink, and OpticalSwitch
+
+- $ONOS_ROOT ust be set
+- Need to run with sudo -E to preserve ONOS_ROOT env var
+- We assume LINC-Config-Generator is named LINC-Config-Generator
+- We also assume linc-oe is named linc-oe
+- LINC-config-generator and linc-oe must be subdirectories of the user's
+ home directory
+
+ TODO
+ -----------
+ - clean up files after runtime
+ - maybe save the old files in a separate directory?
+ - modify script to allow startOE to run before net.start()
+ - add ONOS as a controller in script
+
+ Usage:
+ ------------
+ - import LINCLink and OpticalSwitch from this module
+ - import startOE and stopOE from this module
+ - create topology as you would a normal topology. when
+ to an optical switch with topo.addLink, always specify cls=LINCLink
+ - when creating an optical switch, use cls=OpticalSwitch in topo.addSwitch
+ - for annotations on links and switches, a dictionary must be passed in as
+ the annotations argument
+ - startOE must be run AFTER net.start() with net as an argument.
+ - stopOE can be run at any time
+
+I created a separate function to start lincOE to avoid subclassing Mininet.
+In case anyone wants to write something that DOES subclass Mininet, I
+thought I would outline how:
+
+If we want an object that starts lincOE within the mininet class itself,
+we need to add another object to Mininet that contains all of the json object
+information for each switch. We would still subclass switch and link, but these
+classes would basically be dummy classes that store their own json information
+in the Mininet class object. We may also change the default switch class to add
+it's tap interfaces from lincOE during startup. The start() method for mininet would
+grab all of the information from these switches and links, write configuration files
+for lincOE using the json module, start lincOE, then run the start methodfor each
+switch. The new start() method for each switch would parse through the sys.config
+file that was created and find the tap interface it needs to connect to, similar
+to the findTap function that I currently use. After all of the controllers and
+switches have been started, the new Mininet start() method should also push the
+Topology configuration file to ONOS.
+
+'''
+import sys
+import re
+import json
+import os
+from time import sleep
+import urllib2
+
+from mininet.node import Switch, RemoteController
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.net import Mininet
+from mininet.log import setLogLevel, info, error, warn
+from mininet.link import Link, Intf
+from mininet.cli import CLI
+
+# Sleep time and timeout values in seconds
+SLEEP_TIME = 2
+TIMEOUT = 60
+
+REST_USER = 'onos'
+REST_PW = 'rocks'
+
+class OpticalSwitch(Switch):
+ """
+ For now, same as Switch class.
+ """
+ pass
+
+class OpticalIntf(Intf):
+ """
+ For now,same as Intf class.
+ """
+ pass
+
+class OpticalLink(Link):
+ """
+ For now, same as Link.
+ """
+ pass
+
+class LINCSwitch(OpticalSwitch):
+ """
+ LINCSwitch class
+ """
+ # FIXME:Sometimes LINC doesn't remove pipes and on restart increase the pipe
+ # number from erlang.pipe.1.* to erlang.pipe.2.*, so should read and write
+ # from latest pipe files. For now we are removing all the pipes before
+ # starting LINC.
+ ### User Name ###
+ user = os.getlogin()
+ ### pipes ###
+ readPipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.r".format(user)
+ writePipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.w".format(user)
+ ### sys.config path ###
+ sysConfig = "/home/{}/linc-oe/rel/linc/releases/1.0/sys.config".format(user)
+ ### method, mapping dpid to LINC switchId ###
+ @staticmethod
+ def dpids_to_ids(sysConfig):
+ '''
+ return the dict containing switch dpids as key and LINC switch id as values
+ '''
+ dpids_to_ids = {}
+ fd = None
+ try:
+ with open(sysConfig, 'r', 0) as fd:
+ switch_id = 1
+ for line in fd:
+ dpid = re.search(r'([0-9A-Fa-f]{2}[:-]){7}([0-9A-Fa-f]{2})+', line, re.I)
+ if dpid:
+ dpids_to_ids[dpid.group().replace(':', '')] = switch_id
+ switch_id += 1
+ return dpids_to_ids
+ except:
+ print "Error working with {}\nError: {}\n".format(sysConfig, sys.exc_info())
+ fd.close()
+ return None
+ ### dict of containing dpids as key and corresponding LINC switchId as values ###
+ dpidsToLINCSwitchId = dpids_to_ids.__func__(sysConfig)
+ @staticmethod
+ def findDir(directory, userName):
+ "finds and returns the path of any directory in the user's home directory"
+ homeDir = '/home/' + userName
+ Dir = quietRun('find %s -maxdepth 1 -name %s -type d' % (homeDir, directory)).strip('\n')
+ DirList = Dir.split('\n')
+ if not Dir:
+ return None
+ elif len(DirList) > 1 :
+ warn('***WARNING: Found multiple instances of %s; using %s\n'
+ % (directory, DirList[ 0 ]))
+ return DirList[ 0 ]
+ else:
+ return Dir
+ ### ONOS Directory ###
+ try:
+ onosDir = os.environ[ 'ONOS_ROOT' ]
+ except:
+ onosDir = findDir('onos', user)
+ if not onosDir:
+ error('Please set ONOS_ROOT environment variable!\n')
+ else:
+ os.environ[ 'ONOS_ROOT' ] = onosDir
+ ### LINC-directory
+ lincDir = findDir.__func__('linc-oe', user)
+ if not lincDir:
+ error("***ERROR: Could not find linc-oe in user's home directory\n")
+ ### LINC config generator directory###
+ configGen = findDir.__func__('LINC-config-generator', user)
+ if not configGen:
+ error("***ERROR: Could not find LINC-config-generator in user's home directory\n")
+ # list of all the controllers
+ controllers = None
+ def __init__(self, name, dpid=None, allowed=True,
+ switchType='ROADM', topo=None, annotations={}, controller=None, **params):
+ params[ 'inNamespace' ] = False
+ Switch.__init__(self, name, dpid=dpid, **params)
+ self.name = name
+ self.annotations = annotations
+ self.allowed = allowed
+ self.switchType = switchType
+ self.configDict = {} # dictionary that holds all of the JSON configuration data
+ self.crossConnects = []
+ self.deletedCrossConnects = []
+ self.controller = controller
+ self.lincId = self._get_linc_id() # use to communicate with LINC
+ self.lincStarted = False
+
+ def start(self, *opts, **params):
+ '''Instead of starting a virtual switch, we build the JSON
+ dictionary for the emulated optical switch'''
+ # TODO:Once LINC has the ability to spawn network element dynamically
+ # we need to use this method to spawn new logical LINC switch rather then
+ # bulding JSON.
+ # if LINC is started then we can start and stop logical switches else create JSON
+ if self.lincStarted:
+ return self.start_oe()
+ self.configDict[ 'uri' ] = 'of:' + self.dpid
+ self.configDict[ 'annotations' ] = self.annotations
+ self.configDict[ 'annotations' ].setdefault('name', self.name)
+ self.configDict[ 'hw' ] = 'LINC-OE'
+ self.configDict[ 'mfr' ] = 'Linc'
+ self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1]
+ self.configDict[ 'type' ] = self.switchType
+ self.configDict[ 'ports' ] = []
+ for port, intf in self.intfs.items():
+ if intf.name == 'lo':
+ continue
+ else:
+ self.configDict[ 'ports' ].append(intf.json())
+ self.lincStarted = True
+
+ def stop(self, deleteIntfs=False):
+ '''
+ stop the existing switch
+ '''
+ # TODO:Add support for deleteIntf
+ self.stop_oe()
+
+ def dpctl( self, *args ):
+ "Run dpctl command: ignore for now"
+ pass
+
+ def write_to_cli(self, command):
+ '''
+ send command to LINC
+ '''
+ fd = None
+ try:
+ fd = open(self.writePipe, 'w', 0)
+ fd.write(command)
+ fd.close()
+ except:
+ print "Error working with {}\nError: {}\n".format(self.writePipe, sys.exc_info())
+ if fd:
+ fd.close()
+
+ def read_from_cli(self):
+ '''
+ read the output from the LINC CLI
+ '''
+ response = None
+ fd = None
+ try:
+ fd = open(self.readPipe, 'r', 0)
+ fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) # for non-blocking read
+ # FIXME:Due to non-blocking read most for the time we read nothing
+ response = fd.read()
+ fd.close()
+ except :
+ # print "Error working with {}\nError: {}\n".format(self.readPipe, sys.exc_info())
+ if fd:
+ fd.close()
+ return response
+
+ def _get_linc_id(self):
+ '''
+ return the corresponding LINC switchId.
+ '''
+ return LINCSwitch.dpidsToLINCSwitchId.get(self.dpid)
+ #--------------------------------------------------------------------------
+ # LINC CLI commands
+ #--------------------------------------------------------------------------
+ def start_oe(self):
+ '''
+ existing LINC switch
+ '''
+ #starting Switch
+ cmd = "linc:start_switch({}).\r\n".format(self.lincId)
+ self.write_to_cli(cmd)
+ #hanlding taps interfaces related to the switch
+ crossConnectJSON = {}
+ linkConfig = []
+ for i in range(0,len(self.deletedCrossConnects)):
+ crossConnect = self.deletedCrossConnects.pop()
+ tap = None
+ if isinstance(crossConnect.intf1.node, LINCSwitch):
+ intf = crossConnect.intf2
+ tapPort = crossConnect.intf1.port
+ else:
+ intf = crossConnect.intf1
+ tapPort = crossConnect.intf2.port
+ tap = LINCSwitch.findTap(self, tapPort)
+ if tap:
+ LINCSwitch.setupInts([tap])
+ intf.node.attach(tap)
+ self.crossConnects.append(crossConnect)
+ linkConfig.append(crossConnect.json())
+ #Sending crossConnect info to the ONOS.
+ crossConnectJSON['links'] = linkConfig
+ with open("crossConnect.json", 'w') as fd:
+ json.dump(crossConnectJSON, fd, indent=4, separators=(',', ': '))
+ info('*** Pushing crossConnect.json to ONOS\n')
+ output = quietRun('%s/tools/test/bin/onos-topo-cfg %s\
+ Topology.json' % (self.onosDir, self.controllers[ 0 ].ip), shell=True)
+
+ def stop_oe(self):
+ '''
+ stop the existing LINC switch
+ '''
+ cmd = "linc:stop_switch({}).\r\n".format(self.lincId)
+ self.write_to_cli(cmd)
+ #handling taps if any
+ for i in range(0, len(self.crossConnects)):
+ crossConnect = self.crossConnects.pop()
+ if isinstance(crossConnect.intf1.node, LINCSwitch):
+ intf = crossConnect.intf2
+ tapPort = crossConnect.intf1.port
+ else:
+ intf = crossConnect.intf1
+ tapPort = crossConnect.intf2.port
+ intf.node.detach(LINCSwitch.findTap(self, tapPort))
+ self.deletedCrossConnects.append(crossConnect)
+
+ def w_port_up(self, port):
+ '''
+ port_up
+ '''
+ cmd = "linc:port_up({},{}).\r\n".format(self.lincId, port)
+ self.write_to_cli(cmd)
+
+ def w_port_down(self, port):
+ '''
+ port_down
+ '''
+ cmd = "linc:port_down({},{}).\r\n".format(self.lincId, port)
+ self.write_to_cli(cmd)
+
+ # helper functions
+ @staticmethod
+ def switchJSON(switch):
+ "Returns the json configuration for a packet switch"
+ configDict = {}
+ configDict[ 'uri' ] = 'of:' + switch.dpid
+ configDict[ 'mac' ] = quietRun('cat /sys/class/net/%s/address' % switch.name).strip('\n').translate(None, ':')
+ configDict[ 'hw' ] = 'PK' # FIXME what about OVS?
+ configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS?
+ configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS?
+ annotations = switch.params.get('annotations', {})
+ annotations.setdefault('name', switch.name)
+ configDict[ 'annotations' ] = annotations
+ ports = []
+ for port, intf in switch.intfs.items():
+ if intf.name == 'lo':
+ continue
+ portDict = {}
+ portDict[ 'port' ] = port
+ portDict[ 'type' ] = 'FIBER' if isinstance(intf.link, LINCLink) else 'COPPER'
+ intfList = [ intf.link.intf1, intf.link.intf2 ]
+ intfList.remove(intf)
+ portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance(intf.link, LINCLink) else 0
+ ports.append(portDict)
+ configDict[ 'ports' ] = ports
+ return configDict
+
+ @staticmethod
+ def bootOE(net):
+ "Start the LINC optical emulator within a mininet instance"
+ LINCSwitch.opticalJSON = {}
+ linkConfig = []
+ devices = []
+ #setting up the controllers for LINCSwitch class
+ LINCSwitch.controllers = net.controllers
+
+ for switch in net.switches:
+ if isinstance(switch, OpticalSwitch):
+ devices.append(switch.json())
+ else:
+ devices.append(LINCSwitch.switchJSON(switch))
+ LINCSwitch.opticalJSON[ 'devices' ] = devices
+
+ for link in net.links:
+ if isinstance(link, LINCLink) :
+ linkConfig.append(link.json())
+ LINCSwitch.opticalJSON[ 'links' ] = linkConfig
+
+ info('*** Writing Topology.json file\n')
+ with open('Topology.json', 'w') as outfile:
+ json.dump(LINCSwitch.opticalJSON, outfile, indent=4, separators=(',', ': '))
+
+ info('*** Converting Topology.json to linc-oe format (TopoConfig.json) file (no oecfg) \n')
+
+ topoConfigJson = {};
+ dpIdToName = {};
+
+ topoConfigJson["switchConfig"] = LINCSwitch.getSwitchConfig(dpIdToName);
+ topoConfigJson["linkConfig"] = LINCSwitch.getLinkConfig(dpIdToName);
+
+ #Writing to TopoConfig.json
+ with open( 'TopoConfig.json', 'w' ) as outfile:
+ json.dump( topoConfigJson, outfile, indent=4, separators=(',', ': ') )
+
+ info('*** Creating sys.config...\n')
+ output = quietRun('%s/config_generator TopoConfig.json %s/sys.config.template %s %s'
+ % (LINCSwitch.configGen, LINCSwitch.configGen, LINCSwitch.controllers[ 0 ].ip, LINCSwitch.controllers[ 0 ].port), shell=True)
+ if output:
+ error('***ERROR: Error creating sys.config file: %s\n' % output)
+ return False
+
+ info ('*** Setting multiple controllers in sys.config...\n')
+ searchStr = '\[{"Switch.*$'
+ ctrlStr = ''
+ for index in range(len(LINCSwitch.controllers)):
+ ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (index, net.controllers[index].ip, net.controllers[index].port)
+ replaceStr = '[%s]},' % ctrlStr[:-1] # Cut off last comma
+ sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr)
+ output = quietRun(sedCmd, shell=True)
+
+ info('*** Copying sys.config to linc-oe directory: ', output + '\n')
+ output = quietRun('cp -v sys.config %s/rel/linc/releases/1.0/' % LINCSwitch.lincDir, shell=True).strip('\n')
+ info(output + '\n')
+
+ info('*** Adding taps and bringing them up...\n')
+ LINCSwitch.setupInts(LINCSwitch.getTaps())
+
+ info('*** removing pipes if any \n')
+ quietRun('rm /tmp/home/%s/linc-oe/rel/linc/*' % LINCSwitch.user, shell=True)
+
+ info('*** Starting linc OE...\n')
+ output = quietRun('%s/rel/linc/bin/linc start' % LINCSwitch.lincDir, shell=True)
+ if output:
+ error('***ERROR: LINC-OE: %s' % output + '\n')
+ quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
+ return False
+
+ info('*** Waiting for linc-oe to start...\n')
+ LINCSwitch.waitStarted(net)
+
+ info('*** Adding cross-connect (tap) interfaces to packet switches...\n')
+ for link in net.links:
+ if isinstance(link, LINCLink):
+ if link.annotations[ 'optical.type' ] == 'cross-connect':
+ for intf in [ link.intf1, link.intf2 ]:
+ if not isinstance(intf, LINCIntf):
+ intfList = [ intf.link.intf1, intf.link.intf2 ]
+ intfList.remove(intf)
+ intf2 = intfList[ 0 ]
+ intf.node.attach(LINCSwitch.findTap(intf2.node, intf2.node.ports[ intf2 ]))
+
+ info('*** Waiting for all devices to be available in ONOS...\n')
+ url = 'http://%s:8181/onos/v1/devices' % LINCSwitch.controllers[0].ip
+ time = 0
+ # Set up password authentication
+ pw_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
+ pw_mgr.add_password(None, url, REST_USER, REST_PW)
+ handler = urllib2.HTTPBasicAuthHandler(pw_mgr)
+ opener = urllib2.build_opener(handler)
+ opener.open(url)
+ urllib2.install_opener(opener)
+ while True:
+ response = json.load(urllib2.urlopen(url))
+ devs = response.get('devices')
+
+ # Wait for all devices to be registered
+ if (len(devices) != len(devs)):
+ continue
+
+ # Wait for all devices to available
+ available = True
+ for d in devs:
+ available &= d['available']
+ if available:
+ break
+
+ if (time >= TIMEOUT):
+ error('***ERROR: ONOS did not register devices within %s seconds\n' % TIMEOUT)
+ break
+
+ time += SLEEP_TIME
+ sleep(SLEEP_TIME)
+
+ info('*** Pushing Topology.json to ONOS\n')
+ for index in range(len(LINCSwitch.controllers)):
+ output = quietRun('%s/tools/test/bin/onos-topo-cfg %s Topology.json &' % (LINCSwitch.onosDir, LINCSwitch.controllers[ index ].ip), shell=True)
+ # successful output contains the two characters '{}'
+ # if there is more output than this, there is an issue
+ if output.strip('{}'):
+ warn('***WARNING: Could not push topology file to ONOS: %s\n' % output)
+
+ #converts node ids to linc-oe format, with colons every two chars
+ @staticmethod
+ def dpId(id):
+ nodeDpid = ""
+ id = id.split("/", 1)[0]
+ for i in range(3, len(id) - 1, 2):
+ nodeDpid += (id[i:(i + 2):]) + ":"
+ return nodeDpid[0:-1];
+
+ @staticmethod
+ def getSwitchConfig (dpIdToName):
+ switchConfig = [];
+ #Iterate through all switches and convert the ROADM switches to linc-oe format
+ for switch in LINCSwitch.opticalJSON["devices"]:
+ if switch.get("type", "none") == "ROADM":
+ builtSwitch = {}
+
+ #set basic switch params based on annotations
+ builtSwitch["allowed"] = True;
+ builtSwitch["latitude"] = switch["annotations"].get("latitude", 0.0);
+ builtSwitch["longitude"] = switch["annotations"].get("longitude", 0.0);
+
+ #assumed that all switches have this entry
+ nodeId = switch["uri"]
+
+ #convert the nodeId to linc-oe format
+ nodeDpid = LINCSwitch.dpId(nodeId);
+
+ builtSwitch["name"] = switch.get("name", "none");
+
+ #keep track of the name corresponding to each switch dpid
+ dpIdToName[nodeDpid] = builtSwitch["name"];
+
+ builtSwitch["nodeDpid"] = nodeDpid
+
+ #set switch params and type
+ builtSwitch["params"] = {};
+ builtSwitch["params"]["numregens"] = switch["annotations"].get("optical.regens", 0);
+ builtSwitch["type"] = "Roadm"
+
+ #append to list of switches
+ switchConfig.append(builtSwitch);
+ return switchConfig
+
+ @staticmethod
+ def getLinkConfig (dpIdToName):
+ newLinkConfig = [];
+ #Iterate through all optical links and convert them to linc-oe format
+ for link in LINCSwitch.opticalJSON["links"]:
+ if link.get("type", "none") == "OPTICAL":
+ builtLink = {}
+
+ #set basic link params for src and dst
+ builtLink["allowed"] = True;
+ builtLink["nodeDpid1"] = LINCSwitch.dpId(link["src"])
+ builtLink["nodeDpid2"] = LINCSwitch.dpId(link["dst"])
+
+ #set more params such as name/bandwidth/port/waves if they exist
+ params = {}
+ params["nodeName1"] = dpIdToName.get(builtLink["nodeDpid1"], "none")
+ params["nodeName2"] = dpIdToName.get(builtLink["nodeDpid2"], "none")
+
+ params["port1"] = int(link["src"].split("/")[1])
+ params["port2"] = int(link["dst"].split("/")[1])
+
+ if "bandwidth" in link["annotations"]:
+ params["bandwidth"] = link["annotations"]["bandwidth"]
+
+ if "optical.waves" in link["annotations"]:
+ params["numWaves"] = link["annotations"]["optical.waves"]
+
+ builtLink["params"] = params
+
+ #set type of link (WDM or pktOpt)
+ if link["annotations"].get("optical.type", "cross-connect") == "WDM":
+ builtLink["type"] = "wdmLink"
+ else:
+ builtLink["type"] = "pktOptLink"
+
+ newLinkConfig.append(builtLink);
+ return newLinkConfig
+
+
+ @staticmethod
+ def waitStarted(net, timeout=TIMEOUT):
+ "wait until all tap interfaces are available"
+ tapCount = 0
+ time = 0
+ for link in net.links:
+ if isinstance(link, LINCLink):
+ if link.annotations[ 'optical.type' ] == 'cross-connect':
+ tapCount += 1
+
+ while True:
+ if str(tapCount) == quietRun('ip addr | grep tap | wc -l', shell=True).strip('\n'):
+ return True
+ if timeout:
+ if time >= TIMEOUT:
+ error('***ERROR: LINC OE did not start within %s seconds\n' % TIMEOUT)
+ return False
+ time += SLEEP_TIME
+ sleep(SLEEP_TIME)
+
+ @staticmethod
+ def shutdownOE():
+ "stop the optical emulator"
+ info('*** Stopping linc OE...\n')
+ quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
+
+ @staticmethod
+ def setupInts(intfs):
+ '''
+ add taps and bring them up.
+ '''
+ for i in intfs:
+ quietRun('ip tuntap add dev %s mode tap' % i)
+ quietRun('ip link set dev %s up' % i)
+ info('*** Intf %s set\n' % i)
+
+ @staticmethod
+ def getTaps(path=None):
+ '''
+ return list of all the tops in sys.config
+ '''
+ if path is None:
+ path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
+ fd = open(path, 'r', 0)
+ sys_data = fd.read()
+ taps = re.findall('tap\d+', sys_data)
+ fd.close()
+ return taps
+
+ @staticmethod
+ def findUser():
+ "Try to return logged-in (usually non-root) user"
+ try:
+ # If we're running sudo
+ return os.environ[ 'SUDO_USER' ]
+ except:
+ try:
+ # Logged-in user (if we have a tty)
+ return quietRun('who am i').split()[ 0 ]
+ except:
+ # Give up and return effective user
+ return quietRun('whoami')
+
+
+ @staticmethod
+ def findTap(node, port, path=None):
+ '''utility function to parse through a sys.config
+ file to find tap interfaces for a switch'''
+ switch = False
+ portLine = ''
+ intfLines = []
+
+ if path is None:
+ path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
+
+ with open(path) as f:
+ for line in f:
+ if 'tap' in line:
+ intfLines.append(line)
+ if node.dpid in line.translate(None, ':'):
+ switch = True
+ continue
+ if switch:
+ if 'switch' in line:
+ switch = False
+ if 'port_no,%s}' % port in line:
+ portLine = line
+ break
+
+ if portLine:
+ m = re.search('port,\d+', portLine)
+ port = m.group(0).split(',')[ 1 ]
+ else:
+ error('***ERROR: Could not find any ports in sys.config\n')
+ return
+
+ for intfLine in intfLines:
+ if 'port,%s' % port in intfLine:
+ return re.findall('tap\d+', intfLine)[ 0 ]
+
+ def json(self):
+ "return json configuration dictionary for switch"
+ return self.configDict
+
+ def terminate(self):
+ pass
+
+
+
+class LINCLink(Link):
+ """
+ LINC link class
+ """
+ def __init__(self, node1, node2, port1=None, port2=None, allowed=True,
+ intfName1=None, intfName2=None, linkType='OPTICAL',
+ annotations={}, speed1=0, speed2=0, **params):
+ "Creates a dummy link without a virtual ethernet pair."
+ self.allowed = allowed
+ self.annotations = annotations
+ self.linkType = linkType
+ self.port1 = port1
+ self.port2 = port2
+ params1 = { 'speed': speed1 }
+ params2 = { 'speed': speed2 }
+ # self.isCrossConnect = True if self.annotations.get('optical.type') == 'cross-connect' else False
+ if isinstance(node1, LINCSwitch) and isinstance(node2, LINCSwitch):
+ self.isCrossConnect = False
+ else:
+ self.isCrossConnect = True
+ if isinstance(node1, LINCSwitch):
+ cls1 = LINCIntf
+ if self.isCrossConnect:
+ node1.crossConnects.append(self)
+ else:
+ cls1 = Intf
+ # bad hack to stop error message from appearing when we try to set up intf in a packet switch,
+ # and there is no interface there( because we do not run makeIntfPair ). This way, we just set lo up
+ intfName1 = 'lo'
+ if isinstance(node2, LINCSwitch):
+ cls2 = LINCIntf
+ if self.isCrossConnect:
+ node2.crossConnects.append(self)
+ else:
+ cls2 = Intf
+ intfName2 = 'lo'
+ Link.__init__(self, node1, node2, port1=port1, port2=port2,
+ intfName1=intfName1, intfName2=intfName2, cls1=cls1,
+ cls2=cls2, params1=params1, params2=params2)
+
+ @classmethod
+ def makeIntfPair(_cls, intfName1, intfName2, *args, **kwargs):
+ pass
+
+ def json(self):
+ "build and return the json configuration dictionary for this link"
+ configData = {}
+ configData[ 'src' ] = ('of:' + self.intf1.node.dpid +
+ '/%s' % self.intf1.node.ports[ self.intf1 ])
+ configData[ 'dst' ] = ('of:' + self.intf2.node.dpid +
+ '/%s' % self.intf2.node.ports[ self.intf2 ])
+ configData[ 'type' ] = self.linkType
+ configData[ 'annotations' ] = self.annotations
+ return configData
+
+class LINCIntf(OpticalIntf):
+ """
+ LINC interface class
+ """
+ def __init__(self, name=None, node=None, speed=0,
+ port=None, link=None, **params):
+ self.node = node
+ self.speed = speed
+ self.port = port
+ self.link = link
+ self.name = name
+ node.addIntf(self, port=port)
+ self.params = params
+ self.ip = None
+
+ def json(self):
+ "build and return the JSON information for this interface( not used right now )"
+ configDict = {}
+ configDict[ 'port' ] = self.port
+ configDict[ 'speed' ] = self.speed
+ configDict[ 'type' ] = 'FIBER'
+ return configDict
+
+ def config(self, *args, **kwargs):
+ "dont configure a dummy interface"
+ pass
+
+ def ifconfig(self, status):
+ "configure the status"
+ if status == "up":
+ return self.node.w_port_up(self.port)
+ elif status == "down":
+ return self.node.w_port_down(self.port)
+
+
+class MininetOE(Mininet):
+ "Mininet with Linc-OE support (starts and stops linc-oe)"
+
+ def start(self):
+ Mininet.start(self)
+ LINCSwitch.bootOE(self)
+
+ def stop(self):
+ Mininet.stop(self)
+ LINCSwitch.shutdownOE()
+
+ def addControllers(self, controllers):
+ i = 0
+ for ctrl in controllers:
+ self.addController(RemoteController('c%d' % i, ip=ctrl))
+ i += 1
+
+if __name__ == '__main__':
+ pass
diff --git a/framework/src/onos/tools/test/topos/rftest.py b/framework/src/onos/tools/test/topos/rftest.py
new file mode 100644
index 00000000..7aba54f9
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/rftest.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+
+import sys
+
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.node import RemoteController
+
+from rftesttopo import ReactiveForwardingTestTopo
+
+setLogLevel( 'info' )
+
+def pingloop( net ):
+ setLogLevel( 'error' )
+ try:
+ while True:
+ net.ping()
+ finally:
+ setLogLevel( 'info' )
+
+def run(controllers=[ '127.0.0.1' ]):
+ Mininet.pingloop = pingloop
+ net = Mininet( topo=ReactiveForwardingTestTopo(), build=False, autoSetMacs=True )
+ ctrl_count = 0
+ for controllerIP in controllers:
+ net.addController( 'c%d' % ctrl_count, RemoteController, ip=controllerIP )
+ ctrl_count = ctrl_count + 1
+ net.build()
+ net.start()
+ CLI( net )
+ net.stop()
+
+if __name__ == '__main__':
+ if len( sys.argv ) > 1:
+ controllers = sys.argv[ 1: ]
+ else:
+ print 'Usage: rf-test.py <c0 IP> <c1 IP> ...'
+ exit( 1 )
+ run( controllers )
diff --git a/framework/src/onos/tools/test/topos/rftesttopo.py b/framework/src/onos/tools/test/topos/rftesttopo.py
new file mode 100644
index 00000000..9b975785
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/rftesttopo.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+
+"""
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+
+class ReactiveForwardingTestTopo( Topo ):
+ "Internet Topology Zoo Specimen."
+
+ def __init__( self ):
+ "Create a topology."
+
+ # Initialize Topology
+ Topo.__init__( self )
+
+ # add nodes, switches first...
+ s1 = self.addSwitch( 's1' )
+ s2 = self.addSwitch( 's2' )
+ s3 = self.addSwitch( 's3' )
+ s4 = self.addSwitch( 's4' )
+ s5 = self.addSwitch( 's5' )
+ s6 = self.addSwitch( 's6' )
+ s7 = self.addSwitch( 's7' )
+ s8 = self.addSwitch( 's8' )
+ s9 = self.addSwitch( 's9' )
+
+ # ... and now hosts
+ h1 = self.addHost( 'h1' )
+ h2 = self.addHost( 'h2' )
+ h3 = self.addHost( 'h3' )
+ h4 = self.addHost( 'h4' )
+
+ # add edges between switch and corresponding host
+ self.addLink( s1 , h1 )
+ self.addLink( s2 , h2 )
+ self.addLink( s3 , h3 )
+ self.addLink( s4 , h4 )
+
+ # add edges between switches
+ self.addLink( s1 , s5 )
+ self.addLink( s2 , s5 )
+ self.addLink( s2 , s8 )
+ self.addLink( s3 , s4 )
+ self.addLink( s3 , s7 )
+ self.addLink( s4 , s5 )
+ self.addLink( s6 , s8 )
+ self.addLink( s6 , s7 )
+ self.addLink( s5 , s9 )
+ self.addLink( s6 , s9 )
+
+topos = { 'att': ( lambda: ReactiveForwardingTestTopo() ) }
diff --git a/framework/src/onos/tools/test/topos/sdn-ip.json b/framework/src/onos/tools/test/topos/sdn-ip.json
new file mode 100644
index 00000000..153d9959
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/sdn-ip.json
@@ -0,0 +1,26 @@
+{
+ "devices": [
+ { "alias": "s1", "uri": "of:0000000000000001", "mac": "000000000001", "annotations": { "name": "DEN", "latitude": 39.739317, "longitude": -104.983791 }, "type": "SWITCH" },
+ { "alias": "s2", "uri": "of:0000000000000002", "mac": "000000000002", "annotations": { "name": "IND", "latitude": 39.769089, "longitude": -86.158039 }, "type": "SWITCH" },
+ { "alias": "s3", "uri": "of:0000000000000003", "mac": "000000000003", "annotations": { "name": "ABQ", "latitude": 35.116541, "longitude": -106.604146 }, "type": "SWITCH" },
+ { "alias": "s4", "uri": "of:0000000000000004", "mac": "000000000004", "annotations": { "name": "DFW", "latitude": 32.779501, "longitude": -96.801104 }, "type": "SWITCH" },
+ { "alias": "s5", "uri": "of:0000000000000005", "mac": "000000000005", "annotations": { "name": "PDX", "latitude": 45.522585, "longitude": -122.677890 }, "type": "SWITCH" },
+ { "alias": "s6", "uri": "of:0000000000000006", "mac": "000000000006", "annotations": { "name": "SFO", "latitude": 37.785286, "longitude": -122.406509 }, "type": "SWITCH" },
+ { "alias": "s7", "uri": "of:0000000000000007", "mac": "000000000007", "annotations": { "name": "LAX", "latitude": 34.055604, "longitude": -118.248567 }, "type": "SWITCH" },
+ { "alias": "s8", "uri": "of:0000000000000008", "mac": "000000000008", "annotations": { "name": "JFK", "latitude": 40.769487, "longitude": -73.972520 }, "type": "SWITCH" },
+ { "alias": "s9", "uri": "of:0000000000000009", "mac": "000000000009", "annotations": { "name": "IAD", "latitude": 38.897676, "longitude": -77.036525 }, "type": "SWITCH" },
+ { "alias": "s10", "uri": "of:0000000000000010", "mac": "000000000010", "annotations": { "name": "ATL", "latitude": 33.756298, "longitude": -84.388507 }, "type": "SWITCH" }
+ ],
+
+ "hosts" : [
+ { "mac": "00:00:00:00:00:01", "vlan": -1, "location": "of:0000000000000001/10", "ip": "10.0.1.2, 10.0.2.2", "annotations": { "type": "bgpSpeaker", "latitude": 42.292306, "longitude": -104.084378 } },
+ { "mac": "00:00:00:00:00:02", "vlan": -1, "location": "of:0000000000000002/10", "ip": "10.0.11.2, 10.0.22.2, 10.0.3.2, 10.0.4.2", "annotations": { "type": "bgpSpeaker", "latitude": 41.019068, "longitude": -91.079570 } },
+ { "mac": "00:00:00:00:00:03", "vlan": -1, "location": "of:0000000000000003/10", "ip": "10.0.33.2, 10.0.44.2", "annotations": { "type": "bgpSpeaker", "latitude": 32.043892, "longitude": -105.644437 } },
+ { "mac": "00:00:00:00:01:01", "vlan": -1, "location": "of:0000000000000005/10", "ip": "10.0.1.1", "annotations": { "type": "router", "latitude": 42.985256, "longitude": -127.074018 } },
+ { "mac": "00:00:00:00:01:02", "vlan": -1, "location": "of:0000000000000006/10", "ip": "10.0.11.1", "annotations": { "type": "router", "latitude": 40.593824, "longitude": -127.074018 } },
+ { "mac": "00:00:00:00:02:01", "vlan": -1, "location": "of:0000000000000007/10", "ip": "10.0.2.1, 10.0.22.1", "annotations": { "type": "router", "latitude": 31.277098, "longitude": -121.35488 } },
+ { "mac": "00:00:00:00:03:01", "vlan": -1, "location": "of:0000000000000008/10", "ip": "10.0.3.1, 10.0.33.1", "annotations": { "type": "router", "latitude": 39.368502, "longitude": -69.976271 } },
+ { "mac": "00:00:00:00:04:01", "vlan": -1, "location": "of:0000000000000009/10", "ip": "10.0.4.1", "annotations": { "type": "router", "latitude": 34.936264, "longitude": -75.526168 } },
+ { "mac": "00:00:00:00:44:01", "vlan": -1, "location": "of:0000000000000010/10", "ip": "10.0.44.1", "annotations": { "type": "router", "latitude": 32.863420, "longitude": -77.505795 } }
+ ]
+}
diff --git a/framework/src/onos/tools/test/topos/sol.py b/framework/src/onos/tools/test/topos/sol.py
new file mode 100755
index 00000000..68f2d406
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/sol.py
@@ -0,0 +1,4 @@
+#!/usr/bin/python
+import sys, solar
+topo = solar.Solar(cips=sys.argv[1:])
+topo.run()
diff --git a/framework/src/onos/tools/test/topos/solar.py b/framework/src/onos/tools/test/topos/solar.py
new file mode 100644
index 00000000..ea11b664
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/solar.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+from mininet.cli import CLI
+from mininet.net import Mininet
+from mininet.node import RemoteController, OVSKernelSwitch
+
+MAC = 12
+DPID = 16
+
+class CustomCLI(CLI):
+ """Custom CLI to allow us to add our own commands."""
+
+ def __init__ (self, net):
+ """Init method for our custom CLI."""
+ self.net = net
+ CLI.__init__(self, net)
+
+class Solar(object):
+ """ Create a tiered topology from semi-scratch in Mininet """
+
+ def __init__(self, cname='onos', cips=['192.168.56.1'], islands=3, edges=2, hosts=2):
+ """Create tower topology for mininet"""
+
+ # We are creating the controller with local-loopback on purpose to avoid
+ # having the switches connect immediately. Instead, we'll set controller
+ # explicitly for each switch after configuring it as we want.
+ self.ctrls = [ RemoteController(cname, cip, 6633) for cip in cips ]
+ self.net = Mininet(controller=RemoteController, switch = OVSKernelSwitch,
+ build=False)
+
+ self.cips = cips
+ self.spines = []
+ self.leaves = []
+ self.hosts = []
+ for ctrl in self.ctrls:
+ self.net.addController(ctrl)
+
+ # Create the two core switches and links between them
+ c1 = self.net.addSwitch('c1',dpid='1111000000000000')
+ c2 = self.net.addSwitch('c2',dpid='2222000000000000')
+ self.spines.append(c1)
+ self.spines.append(c2)
+
+ self.net.addLink(c1, c2)
+ self.net.addLink(c2, c1)
+
+ for i in range(1, islands + 1):
+ sc = self.createSpineClump(i, edges, hosts)
+ self.net.addLink(c1, sc[0])
+ self.net.addLink(c2, sc[0])
+ self.net.addLink(c1, sc[1])
+ self.net.addLink(c2, sc[1])
+
+ def createSpineClump(self, island, edges, hosts):
+ """ Creates a clump of spine and edge switches with hosts"""
+ s1 = self.net.addSwitch('s%1d1' % island,dpid='00000%1d0100000000' % island)
+ s2 = self.net.addSwitch('s%1d2' % island,dpid='00000%1d0200000000' % island)
+ self.net.addLink(s1, s2)
+ self.net.addLink(s2, s1)
+
+ for i in range(1, edges + 1):
+ es = self.createEdgeSwitch(island, i, hosts)
+ self.net.addLink(es, s1)
+ self.net.addLink(es, s2)
+
+ self.spines.append(s1)
+ self.spines.append(s2)
+
+ clump = []
+ clump.append(s1)
+ clump.append(s2)
+ return clump
+
+ def createEdgeSwitch(self, island, index, hosts):
+ """ Creates an edge switch in an island and ads hosts to it"""
+ sw = self.net.addSwitch('e%1d%1d' % (island, index),dpid='0000000%1d0000000%1d' % (island, index))
+ self.leaves.append(sw)
+
+ for j in range(1, hosts + 1):
+ host = self.net.addHost('h%d%d%d' % (island, index, j),ip='10.%d.%d.%d' % (island, index, j))
+ self.net.addLink(host, sw)
+ self.hosts.append(host)
+ return sw
+
+ def run(self):
+ """ Runs the created network topology and launches mininet cli"""
+ self.net.build()
+ self.net.start()
+ CustomCLI(self.net)
+ self.net.stop()
+
+ def pingAll(self):
+ """ PingAll to create flows - for unit testing """
+ self.net.pingAll()
+
+ def stop(self):
+ "Stops the topology. You should call this after run_silent"
+ self.net.stop()
diff --git a/framework/src/onos/tools/test/topos/sys-nonlinear-10.config b/framework/src/onos/tools/test/topos/sys-nonlinear-10.config
new file mode 100644
index 00000000..2b999d39
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/sys-nonlinear-10.config
@@ -0,0 +1,183 @@
+[{linc,
+ [{of_config,disabled},
+ {software_desc,<<"LINC-OE OpenFlow Software Switch 1.1">>},
+ {capable_switch_ports,
+ [{port,1,[{interface,"dummy"},{type,optical}]},
+ {port,2,[{interface,"dummy"},{type,optical}]},
+ {port,3,[{interface,"dummy"},{type,optical}]},
+ {port,4,[{interface,"dummy"},{type,optical}]},
+ {port,5,[{interface,"dummy"},{type,optical}]},
+ {port,6,[{interface,"dummy"},{type,optical}]},
+ {port,7,[{interface,"dummy"},{type,optical}]},
+ {port,8,[{interface,"dummy"},{type,optical}]},
+ {port,9,[{interface,"dummy"},{type,optical}]},
+ {port,10,[{interface,"dummy"},{type,optical}]},
+ {port,11,[{interface,"dummy"},{type,optical}]},
+ {port,12,[{interface,"dummy"},{type,optical}]},
+ {port,13,[{interface,"dummy"},{type,optical}]},
+ {port,14,[{interface,"dummy"},{type,optical}]},
+ {port,15,[{interface,"dummy"},{type,optical}]},
+ {port,16,[{interface,"dummy"},{type,optical}]},
+ {port,17,[{interface,"dummy"},{type,optical}]},
+ {port,18,[{interface,"dummy"},{type,optical}]},
+ {port,19,[{interface,"dummy"},{type,optical}]},
+ {port,20,[{interface,"dummy"},{type,optical}]},
+ {port,21,[{interface,"dummy"},{type,optical}]},
+ {port,22,[{interface,"dummy"},{type,optical}]},
+ {port,23,[{interface,"dummy"},{type,optical}]},
+ {port,24,[{interface,"dummy"},{type,optical}]},
+ {port,25,[{interface,"dummy"},{type,optical}]},
+ {port,26,[{interface,"dummy"},{type,optical}]},
+ {port,27,[{interface,"dummy"},{type,optical}]},
+ {port,28,[{interface,"dummy"},{type,optical}]},
+ {port,29,[{interface,"tap29"}]},
+ {port,30,[{interface,"tap30"}]},
+ {port,31,[{interface,"tap31"}]},
+ {port,32,[{interface,"tap32"}]},
+ {port,33,[{interface,"tap33"}]},
+ {port,34,[{interface,"tap34"}]}]},
+ {capable_switch_queues,[]},
+ {optical_links,
+ [{{1,50},{2,30}},
+ {{2,50},{3,30}},
+ {{3,50},{4,50}},
+ {{1,20},{5,50}},
+ {{2,20},{5,20}},
+ {{3,20},{6,50}},
+ {{4,20},{6,20}},
+ {{5,30},{6,40}},
+ {{5,40},{7,50}},
+ {{6,30},{8,50}},
+ {{7,20},{8,30}},
+ {{7,30},{9,50}},
+ {{8,20},{10,50}},
+ {{9,20},{10,20}}]},
+ {logical_switches,
+ [{switch,1,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:01"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,1,[{queues,[]},{port_no,50}]},
+ {port,7,[{queues,[]},{port_no,20}]},
+ {port,29,[{queues,[]},{port_no,10}]}]}]},
+ {switch,2,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:02"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,2,[{queues,[]},{port_no,30}]},
+ {port,3,[{queues,[]},{port_no,50}]},
+ {port,9,[{queues,[]},{port_no,20}]}]}]},
+ {switch,3,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:03"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,4,[{queues,[]},{port_no,30}]},
+ {port,5,[{queues,[]},{port_no,50}]},
+ {port,11,[{queues,[]},{port_no,20}]}]}]},
+ {switch,4,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:04"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,6,[{queues,[]},{port_no,50}]},
+ {port,13,[{queues,[]},{port_no,20}]},
+ {port,30,[{queues,[]},{port_no,10}]}]}]},
+ {switch,5,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:05"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,8,[{queues,[]},{port_no,50}]},
+ {port,10,[{queues,[]},{port_no,20}]},
+ {port,15,[{queues,[]},{port_no,30}]},
+ {port,17,[{queues,[]},{port_no,40}]}]}]},
+ {switch,7,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:07"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,18,[{queues,[]},{port_no,50}]},
+ {port,21,[{queues,[]},{port_no,20}]},
+ {port,23,[{queues,[]},{port_no,30}]},
+ {port,32,[{queues,[]},{port_no,10}]}]}]},
+ {switch,8,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:08"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,20,[{queues,[]},{port_no,50}]},
+ {port,22,[{queues,[]},{port_no,30}]},
+ {port,25,[{queues,[]},{port_no,20}]}]}]},
+ {switch,9,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:09"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,24,[{queues,[]},{port_no,50}]},
+ {port,27,[{queues,[]},{port_no,20}]},
+ {port,33,[{queues,[]},{port_no,10}]}]}]},
+ {switch,10,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:0A"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,26,[{queues,[]},{port_no,50}]},
+ {port,28,[{queues,[]},{port_no,20}]},
+ {port,34,[{queues,[]},{port_no,10}]}]}]},
+ {switch,6,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:06"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,12,[{queues,[]},{port_no,50}]},
+ {port,14,[{queues,[]},{port_no,20}]},
+ {port,16,[{queues,[]},{port_no,40}]},
+ {port,19,[{queues,[]},{port_no,30}]},
+ {port,31,[{queues,[]},{port_no,10}]}]}]}]}]},
+ {epcap,[{verbose,false},{stats_interval,10}]},
+ {enetconf,
+ [{capabilities,
+ [{base,{1,0}},
+ {base,{1,1}},
+ {startup,{1,0}},
+ {'writable-running',{1,0}}]},
+ {callback_module,linc_ofconfig},
+ {sshd_ip,any},
+ {sshd_port,1830},
+ {sshd_user_passwords,[{"linc","linc"}]}]},
+ {lager,
+ [{handlers,
+ [{lager_console_backend,info},
+ {lager_file_backend,
+ [{"log/error.log",error,10485760,"$D0",5},
+ {"log/console.log",info,10485760,"$D0",5}]}]}]},
+ {sasl,
+ [{sasl_error_logger,{file,"log/sasl-error.log"}},
+ {errlog_type,error},
+ {error_logger_mf_dir,"log/sasl"},
+ {error_logger_mf_maxbytes,10485760},
+ {error_logger_mf_maxfiles,5}]},
+ {sync,[{excluded_modules,[procket]}]}].
diff --git a/framework/src/onos/tools/test/topos/sys-nonlinear-4.config b/framework/src/onos/tools/test/topos/sys-nonlinear-4.config
new file mode 100644
index 00000000..b843146a
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/sys-nonlinear-4.config
@@ -0,0 +1,79 @@
+[{linc,
+ [{of_config,disabled},
+ {software_desc,<<"LINC-OE OpenFlow Software Switch 1.1">>},
+ {capable_switch_ports,
+ [{port,1,[{interface,"dummy"},{type,optical}]},
+ {port,2,[{interface,"dummy"},{type,optical}]},
+ {port,5,[{interface,"dummy"},{type,optical}]},
+ {port,6,[{interface,"dummy"},{type,optical}]},
+ {port,7,[{interface,"dummy"},{type,optical}]},
+ {port,8,[{interface,"dummy"},{type,optical}]},
+ {port,9,[{interface,"dummy"},{type,optical}]},
+ {port,10,[{interface,"dummy"},{type,optical}]},
+ {port,3,[{interface,"tap3"}]},
+ {port,4,[{interface,"tap4"}]}]},
+ {capable_switch_queues,[]},
+ {optical_links,[{{1,20},{3,30}},{{3,31},{2,21}},{{1,22},{4,30}},{{4,31},{2,22}}]},
+ {logical_switches,
+ [{switch,1,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:01"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,1,[{queues,[]},{port_no,20}]},
+ {port,7,[{queues,[]},{port_no,22}]},
+ {port,3,[{queues,[]},{port_no,10}]}]}]},
+ {switch,3,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:03"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,5,[{queues,[]},{port_no,30}]},
+ {port,6,[{queues,[]},{port_no,31}]}]}]},
+ {switch,2,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:02"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,2,[{queues,[]},{port_no,21}]},
+ {port,8,[{queues,[]},{port_no,22}]},
+ {port,4,[{queues,[]},{port_no,11}]}]}]},
+ {switch,4,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:04"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,9,[{queues,[]},{port_no,30}]},
+ {port,10,[{queues,[]},{port_no,31}]}]}]}]}]},
+ {epcap,[{verbose,false},{stats_interval,10}]},
+ {enetconf,
+ [{capabilities,
+ [{base,{1,0}},
+ {base,{1,1}},
+ {startup,{1,0}},
+ {'writable-running',{1,0}}]},
+ {callback_module,linc_ofconfig},
+ {sshd_ip,any},
+ {sshd_port,1830},
+ {sshd_user_passwords,[{"linc","linc"}]}]},
+ {lager,
+ [{handlers,
+ [{lager_console_backend,debug},
+ {lager_file_backend,
+ [{"log/error.log",error,10485760,"$D0",5},
+ {"log/console.log",info,10485760,"$D0",5}]}]}]},
+ {sasl,
+ [{sasl_error_logger,{file,"log/sasl-error.log"}},
+ {errlog_type,error},
+ {error_logger_mf_dir,"log/sasl"},
+ {error_logger_mf_maxbytes,10485760},
+ {error_logger_mf_maxfiles,5}]},
+ {sync,[{excluded_modules,[procket]}]}].
diff --git a/framework/src/onos/tools/test/topos/sys.config b/framework/src/onos/tools/test/topos/sys.config
new file mode 100644
index 00000000..2b999d39
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/sys.config
@@ -0,0 +1,183 @@
+[{linc,
+ [{of_config,disabled},
+ {software_desc,<<"LINC-OE OpenFlow Software Switch 1.1">>},
+ {capable_switch_ports,
+ [{port,1,[{interface,"dummy"},{type,optical}]},
+ {port,2,[{interface,"dummy"},{type,optical}]},
+ {port,3,[{interface,"dummy"},{type,optical}]},
+ {port,4,[{interface,"dummy"},{type,optical}]},
+ {port,5,[{interface,"dummy"},{type,optical}]},
+ {port,6,[{interface,"dummy"},{type,optical}]},
+ {port,7,[{interface,"dummy"},{type,optical}]},
+ {port,8,[{interface,"dummy"},{type,optical}]},
+ {port,9,[{interface,"dummy"},{type,optical}]},
+ {port,10,[{interface,"dummy"},{type,optical}]},
+ {port,11,[{interface,"dummy"},{type,optical}]},
+ {port,12,[{interface,"dummy"},{type,optical}]},
+ {port,13,[{interface,"dummy"},{type,optical}]},
+ {port,14,[{interface,"dummy"},{type,optical}]},
+ {port,15,[{interface,"dummy"},{type,optical}]},
+ {port,16,[{interface,"dummy"},{type,optical}]},
+ {port,17,[{interface,"dummy"},{type,optical}]},
+ {port,18,[{interface,"dummy"},{type,optical}]},
+ {port,19,[{interface,"dummy"},{type,optical}]},
+ {port,20,[{interface,"dummy"},{type,optical}]},
+ {port,21,[{interface,"dummy"},{type,optical}]},
+ {port,22,[{interface,"dummy"},{type,optical}]},
+ {port,23,[{interface,"dummy"},{type,optical}]},
+ {port,24,[{interface,"dummy"},{type,optical}]},
+ {port,25,[{interface,"dummy"},{type,optical}]},
+ {port,26,[{interface,"dummy"},{type,optical}]},
+ {port,27,[{interface,"dummy"},{type,optical}]},
+ {port,28,[{interface,"dummy"},{type,optical}]},
+ {port,29,[{interface,"tap29"}]},
+ {port,30,[{interface,"tap30"}]},
+ {port,31,[{interface,"tap31"}]},
+ {port,32,[{interface,"tap32"}]},
+ {port,33,[{interface,"tap33"}]},
+ {port,34,[{interface,"tap34"}]}]},
+ {capable_switch_queues,[]},
+ {optical_links,
+ [{{1,50},{2,30}},
+ {{2,50},{3,30}},
+ {{3,50},{4,50}},
+ {{1,20},{5,50}},
+ {{2,20},{5,20}},
+ {{3,20},{6,50}},
+ {{4,20},{6,20}},
+ {{5,30},{6,40}},
+ {{5,40},{7,50}},
+ {{6,30},{8,50}},
+ {{7,20},{8,30}},
+ {{7,30},{9,50}},
+ {{8,20},{10,50}},
+ {{9,20},{10,20}}]},
+ {logical_switches,
+ [{switch,1,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:01"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,1,[{queues,[]},{port_no,50}]},
+ {port,7,[{queues,[]},{port_no,20}]},
+ {port,29,[{queues,[]},{port_no,10}]}]}]},
+ {switch,2,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:02"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,2,[{queues,[]},{port_no,30}]},
+ {port,3,[{queues,[]},{port_no,50}]},
+ {port,9,[{queues,[]},{port_no,20}]}]}]},
+ {switch,3,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:03"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,4,[{queues,[]},{port_no,30}]},
+ {port,5,[{queues,[]},{port_no,50}]},
+ {port,11,[{queues,[]},{port_no,20}]}]}]},
+ {switch,4,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:04"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,6,[{queues,[]},{port_no,50}]},
+ {port,13,[{queues,[]},{port_no,20}]},
+ {port,30,[{queues,[]},{port_no,10}]}]}]},
+ {switch,5,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:05"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,8,[{queues,[]},{port_no,50}]},
+ {port,10,[{queues,[]},{port_no,20}]},
+ {port,15,[{queues,[]},{port_no,30}]},
+ {port,17,[{queues,[]},{port_no,40}]}]}]},
+ {switch,7,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:07"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,18,[{queues,[]},{port_no,50}]},
+ {port,21,[{queues,[]},{port_no,20}]},
+ {port,23,[{queues,[]},{port_no,30}]},
+ {port,32,[{queues,[]},{port_no,10}]}]}]},
+ {switch,8,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:08"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,20,[{queues,[]},{port_no,50}]},
+ {port,22,[{queues,[]},{port_no,30}]},
+ {port,25,[{queues,[]},{port_no,20}]}]}]},
+ {switch,9,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:09"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,24,[{queues,[]},{port_no,50}]},
+ {port,27,[{queues,[]},{port_no,20}]},
+ {port,33,[{queues,[]},{port_no,10}]}]}]},
+ {switch,10,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:0A"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,26,[{queues,[]},{port_no,50}]},
+ {port,28,[{queues,[]},{port_no,20}]},
+ {port,34,[{queues,[]},{port_no,10}]}]}]},
+ {switch,6,
+ [{backend,linc_us4_oe},
+ {datapath_id,"00:00:ff:ff:ff:ff:ff:06"},
+ {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+ {controllers_listener,disabled},
+ {queues_status,disabled},
+ {ports,
+ [{port,12,[{queues,[]},{port_no,50}]},
+ {port,14,[{queues,[]},{port_no,20}]},
+ {port,16,[{queues,[]},{port_no,40}]},
+ {port,19,[{queues,[]},{port_no,30}]},
+ {port,31,[{queues,[]},{port_no,10}]}]}]}]}]},
+ {epcap,[{verbose,false},{stats_interval,10}]},
+ {enetconf,
+ [{capabilities,
+ [{base,{1,0}},
+ {base,{1,1}},
+ {startup,{1,0}},
+ {'writable-running',{1,0}}]},
+ {callback_module,linc_ofconfig},
+ {sshd_ip,any},
+ {sshd_port,1830},
+ {sshd_user_passwords,[{"linc","linc"}]}]},
+ {lager,
+ [{handlers,
+ [{lager_console_backend,info},
+ {lager_file_backend,
+ [{"log/error.log",error,10485760,"$D0",5},
+ {"log/console.log",info,10485760,"$D0",5}]}]}]},
+ {sasl,
+ [{sasl_error_logger,{file,"log/sasl-error.log"}},
+ {errlog_type,error},
+ {error_logger_mf_dir,"log/sasl"},
+ {error_logger_mf_maxbytes,10485760},
+ {error_logger_mf_maxfiles,5}]},
+ {sync,[{excluded_modules,[procket]}]}].
diff --git a/framework/src/onos/tools/test/topos/topo b/framework/src/onos/tools/test/topos/topo
new file mode 100755
index 00000000..854de504
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/topo
@@ -0,0 +1,10 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Starts the specified mininet topology.
+# -----------------------------------------------------------------------------
+cd $(dirname $0)
+
+topo=${1:-att-onos.py}
+
+[ -n "$1" ] && shift
+sudo python $topo "$@"
diff --git a/framework/src/onos/tools/test/topos/topo-200sw-linkalarm.py b/framework/src/onos/tools/test/topos/topo-200sw-linkalarm.py
new file mode 100644
index 00000000..bb964e2b
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/topo-200sw-linkalarm.py
@@ -0,0 +1,20 @@
+
+from mininet.topo import Topo
+
+class MyTopo( Topo ):
+ "10 'floating' switch topology"
+
+ def __init__( self ):
+ # Initialize topology
+ Topo.__init__( self )
+
+ sw_list = []
+ swC = self.addSwitch('sc', dpid = 'ffffffff00000001')
+
+ for i in range(1, 201):
+ switch=self.addSwitch('s'+str(i), dpid = str(i).zfill(16))
+ self.addLink(switch,swC)
+
+ sw_list.append(switch)
+
+topos = { 'mytopo': ( lambda: MyTopo() ) }
diff --git a/framework/src/onos/tools/test/topos/tower b/framework/src/onos/tools/test/topos/tower
new file mode 100755
index 00000000..8244bae9
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/tower
@@ -0,0 +1,2 @@
+#!/bin/bash
+cd ~/topos && sudo mn --custom tower.py --topo tower --controller remote,${1:-192.168.56.101} --mac
diff --git a/framework/src/onos/tools/test/topos/tower.py b/framework/src/onos/tools/test/topos/tower.py
new file mode 100755
index 00000000..b75bfe40
--- /dev/null
+++ b/framework/src/onos/tools/test/topos/tower.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+
+from mininet.topo import Topo
+from mininet.cli import CLI
+from mininet.net import Mininet
+from mininet.node import RemoteController, OVSKernelSwitch
+from mininet.log import setLogLevel
+
+
+class TowerTopo( Topo ):
+ """Create a tower topology"""
+
+ def build( self, k=4, h=6 ):
+ spines = []
+ leaves = []
+ hosts = []
+
+ # Create the two spine switches
+ spines.append(self.addSwitch('s1'))
+ spines.append(self.addSwitch('s2'))
+
+ # Create two links between the spine switches
+ self.addLink(spines[0], spines[1])
+ #TODO add second link between spines when multi-link topos are supported
+ #self.addLink(spines[0], spines[1])
+
+ # Now create the leaf switches, their hosts and connect them together
+ i = 1
+ c = 0
+ while i <= k:
+ leaves.append(self.addSwitch('s1%d' % i))
+ for spine in spines:
+ self.addLink(leaves[i-1], spine)
+
+ j = 1
+ while j <= h:
+ hosts.append(self.addHost('h%d%d' % (i, j)))
+ self.addLink(hosts[c], leaves[i-1])
+ j+=1
+ c+=1
+
+ i+=1
+
+topos = { 'tower': TowerTopo }
+
+def run():
+ topo = TowerTopo()
+ net = Mininet( topo=topo, controller=RemoteController, autoSetMacs=True )
+ net.start()
+ CLI( net )
+ net.stop()
+
+if __name__ == '__main__':
+ setLogLevel( 'info' )
+ run()