Create testing for ODTN, including line-side/client-side connectivity creation and deletion. Testing succeeds on single ONOS instance.
Change-Id: I7d0eb4ff0e9160ef2fdd5fba9567399a4f1777eb
diff --git a/tools/test/bin/stc b/tools/test/bin/stc
index 9c5702f..4e4c2d8 100755
--- a/tools/test/bin/stc
+++ b/tools/test/bin/stc
@@ -3,6 +3,20 @@
# System Test Coordinator
#-------------------------------------------------------------------------------
+# If specifiy another env init script, load it.
+params=()
+index=0
+for i in $@; do
+ key=`echo $i | awk -F '=' '{print $1}'`
+ if [ "$key" == "-ENV_DEFAULT" ]; then
+ val=`echo $i | awk -F '=' '{print $2}'`
+ source $val
+ else
+ params[$index]=$i
+ let index+=1
+ fi
+done
+
. $ONOS_ROOT/tools/build/envDefaults
VER=${STC_VERSION:-2.5}
@@ -20,7 +34,7 @@
DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=y"
-scenario=${1:-smoke}
+scenario=${params[0]:-smoke}
if [ $scenario != "-?" -a $scenario != "-h" -a $scenario != "--help" ]; then
[ ! -f $scenario ] && scenario=$SCENARIOS/$scenario
@@ -38,4 +52,4 @@
# Run stc
[ -z "$stcDebug" ] && DEBUG_OPTS=""
stcTitle=${stcTitle:-} stcColor=${stcColor:-$interactive} stcDumpLogs=${stcDumpLogs:-$notInteractive} \
- java $DEBUG_OPTS -jar $JAR $scenario "$@"
+ java $DEBUG_OPTS -jar $JAR $scenario "${params[*]}"
diff --git a/tools/test/scenarios/bin/execute-tapi-delete-call.py b/tools/test/scenarios/bin/execute-tapi-delete-call.py
old mode 100644
new mode 100755
diff --git a/tools/test/scenarios/bin/execute-tapi-post-call.py b/tools/test/scenarios/bin/execute-tapi-post-call.py
index 59f535f..f6d419a 100755
--- a/tools/test/scenarios/bin/execute-tapi-post-call.py
+++ b/tools/test/scenarios/bin/execute-tapi-post-call.py
@@ -6,7 +6,7 @@
if len(sys.argv) < 4:
print "usage: execute-tapi-post-call <onos-node> <context> <empty> [uuid]."
- print "\t- If <empty> is \"empty\", it measn that it shoudl be no devices, links or ports"
+ print "\t- If <empty> is \"empty\", it measn that it should be no devices, links or ports"
print "\t- Uuid is optional and defaults to empty"
print "\t- For example:\n\t\t- line-side connectivity creation: %s\n\t\t- client-side connectivity creation: %s" % \
("python execute-tapi-post-call.py 127.0.0.1 tapi-connectivity:create-connectivity-service line-side",
@@ -30,7 +30,13 @@
print tapi_connection_json
if not tapi_connection_json["tapi-connectivity:output"] and empty != "empty":
print "No connection was established"
- sys.exit(1)
+ sys.exit(0)
+ if empty == "empty":
+ if not tapi_connection_json["tapi-connectivity:output"]:
+ sys.exit(0)
+ else:
+ print "There exist some connectivities!!!"
+ sys.exit(1)
if uuid == "":
# verify empty connection
print tapi_connection_json
diff --git a/tools/test/scenarios/net-odtn-presmoke.xml b/tools/test/scenarios/net-odtn-presmoke.xml
new file mode 100644
index 0000000..dbff113
--- /dev/null
+++ b/tools/test/scenarios/net-odtn-presmoke.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+ ~ Copyright 2018-present Open Networking Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<scenario name="net-odtn-presmoke" description="Start ODTN docker containers and set env variables">
+ <group name="ODTN-Net-Prepare">
+ <step name="ODTN-Net-Prepare.clean-docker" exec="bash ${ONOS_SCENARIOS}/odtn/destroyOdtnCell.sh"/>
+ <step name="ODTN-Net-Prepare.build-docker-img" exec="bash ${ONOS_SCENARIOS}/odtn/buildOdtnDocker.sh" requires="ODTN-Net-Prepare.clean-docker"/>
+ <step name="ODTN-Net-Prepare.create-docker-containers" requires="ODTN-Net-Prepare.build-docker-img" exec="source ${ONOS_SCENARIOS}/odtn/createOdtnCell.sh"/>
+ </group>
+</scenario>
diff --git a/tools/test/scenarios/net-odtn-restconf.xml b/tools/test/scenarios/net-odtn-restconf.xml
index 93d2095..571bc0b 100644
--- a/tools/test/scenarios/net-odtn-restconf.xml
+++ b/tools/test/scenarios/net-odtn-restconf.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
<!--
~ Copyright 2015-present Open Networking Foundation
~
@@ -13,42 +14,35 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<scenario name="net-odtn-restconf"
- description="ODTN RESTCONF API test">
- <group name="Net-ODTN-Restconf">
-
- <!-- Verify the correct topology is present -->
-
- <step name="Net-ODTN-Restconf.Tapi-context"
- exec="execute-tapi-context-get-call.py ${OC1} empty"/>
-
- <!-- Verify empty connectivity service -->
-
- <step name="Net-ODTN-Restconf.Tapi-connectivity" requires="Net-ODTN-Restconf.Tapi-context"
- exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty"/>
-
- <!-- Push the connectivity service request -->
-
- <!--<step name="ODTN-Net-Setup.Tapi-connectivity" requires="ODTN-Net-Setup.Tapi-context"
- exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list true"/>
-
- <group name="ODTN-Net-Setup.Verify-Logs-3" requires="ODTN-Net-Setup.Tapi-connectivity">
- <parallel var="${OC#}">
- <step name="Check-Logs-3-${#}" exec="onos-check-logs ${OC#}"/>
- </parallel>
- </group>
-
- <step name="ODTN-Net-Setup.Tapi-context" requires="ODTN-Net-Setup.Verify-Logs"
- exec="execute-tapi-context-get-call.py ${OC1} empty"/>
- <step name="ODTN-Net-Setup.Tapi-connectivity" requires="ODTN-Net-Setup.Tapi-context"
- exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty true"/>
-
- <group name="ODTN-Net-Setup.Verify-Logs-4" requires="ODTN-Net-Setup.Tapi-connectivity">
- <parallel var="${OC#}">
- <step name="Check-Logs-4-${#}" exec="onos-check-logs ${OC#}"/>
- </parallel>
- </group>-->
-
-
+<scenario name="net-odtn-restconf" description="ODTN RESTCONF API test">
+ <group name="Net-ODTN-Restconf">
+ <!-- Verify the correct topology is present -->
+ <step name="Net-ODTN-Restconf.Tapi-context" exec="execute-tapi-context-get-call.py ${OC1} empty"/>
+ <!-- Verify empty connectivity service -->
+ <step name="Net-ODTN-Restconf.Confirm-conn-empty" requires="Net-ODTN-Restconf.Tapi-context" exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty"/>
+ <!-- Push the line-side connectivity service request -->
+ <group name="Net-ODTN-Restconf.Line-side-test" requires="Net-ODTN-Restconf.Confirm-conn-empty">
+ <step name="Net-ODTN-Restconf.Create-line-side" exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:create-connectivity-service line-side"/>
+ <step name="Net-ODTN-Restconf.Check-line-side" requires="Net-ODTN-Restconf.Create-line-side" exec="${ONOS_SCENARIOS}/odtn/checkUntilSucc.sh 'execute-tapi-post-call.py+${OC1}+tapi-connectivity:get-connectivity-service-list+empty+|+grep+'tapi-connectivity:output'+|+grep+connection-uuid+-o+|+wc+-l' 1" />
+ <step name="Net-ODTN-Restconf.Delete-line-conn" requires="Net-ODTN-Restconf.Check-line-side" exec="execute-tapi-delete-call.py ${OC1} line"/>
+ <step name="Net-ODTN-Restconf.Confirm-conn-empty-2" requires="Net-ODTN-Restconf.Delete-line-conn" exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty"/>
+ <group name="Net-ODTN-Restconf.Verify-Logs" requires="Net-ODTN-Restconf.Confirm-conn-empty-2">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-Restconf-1-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
</group>
+ <!-- Push the client-side connectivity service request -->
+ <group name="Net-ODTN-Restconf.Client-side-test" requires="Net-ODTN-Restconf.Line-side-test" delay="10" >
+ <step name="Net-ODTN-Restconf.Create-client-side" exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:create-connectivity-service client-side"/>
+ <step name="Net-ODTN-Restconf.Check-client-side" requires="Net-ODTN-Restconf.Create-client-side" exec="${ONOS_SCENARIOS}/odtn/checkUntilSucc.sh 'execute-tapi-post-call.py+${OC1}+tapi-connectivity:get-connectivity-service-list+empty+|+grep+'tapi-connectivity:output'+|+grep+connection-uuid+-o+|+wc+-l' 1" />
+ <step name="Net-ODTN-Restconf.Delete-client-conn" requires="Net-ODTN-Restconf.Check-client-side" exec="execute-tapi-delete-call.py ${OC1} both"/>
+ <step name="Net-ODTN-Restconf.Confirm-conn-empty-3" requires="Net-ODTN-Restconf.Delete-client-conn" exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty"/>
+ <group name="Net-ODTN-Restconf.Verify-Logs-2" requires="Net-ODTN-Restconf.Confirm-conn-empty-3">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-Restconf-2-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
+ </group>
+ </group>
</scenario>
diff --git a/tools/test/scenarios/net-odtn-smoke.xml b/tools/test/scenarios/net-odtn-smoke.xml
index e49ca73..f1e1f7d 100644
--- a/tools/test/scenarios/net-odtn-smoke.xml
+++ b/tools/test/scenarios/net-odtn-smoke.xml
@@ -14,24 +14,10 @@
~ limitations under the License.
-->
-
-<scenario name="net-odtn-smoke"
- description="ODTN test steps">
-
- <import file="${ONOS_SCENARIOS}/net-setup-odtn.xml"/>
-
- <!--TODO check proper topology-->
- <!--<step name="Net-ODTN-Smoke.Check-Summary"
- requires="ODTN-Net-Setup.Verify-Logs-2" delay="5"
- exec="onos-check-summary ${OC1} [0-9]* 4 8 0 112"/>-->
-
- <import file="${ONOS_SCENARIOS}/net-odtn-restconf.xml"/>
- <dependency name="Net-ODTN-Restconf" requires="ODTN-Net-Setup"/>
-
- <import file="${ONOS_SCENARIOS}/net-teardown-odtn.xml"/>
- <dependency name="Net-Teardown-ODTN" requires="Net-ODTN-Restconf"/>
-
- <import file="${ONOS_SCENARIOS}/shutdown.xml"/>
- <dependency name="Shutdown-ONOS" requires="Net-Teardown-ODTN"/>
-
+<scenario name="net-odtn-smoke" description="ODTN test steps">
+ <import file="${ONOS_SCENARIOS}/net-setup-odtn.xml"/>
+ <import file="${ONOS_SCENARIOS}/net-odtn-restconf.xml"/>
+ <dependency name="Net-ODTN-Restconf" requires="ODTN-Net-Setup"/>
+ <import file="${ONOS_SCENARIOS}/net-teardown-odtn.xml"/>
+ <dependency name="Net-Teardown-ODTN" requires="Net-ODTN-Restconf"/>
</scenario>
diff --git a/tools/test/scenarios/net-setup-odtn.xml b/tools/test/scenarios/net-setup-odtn.xml
index 78987a2..1f69aed 100644
--- a/tools/test/scenarios/net-setup-odtn.xml
+++ b/tools/test/scenarios/net-setup-odtn.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
<!--
~ Copyright 2015-present Open Networking Foundation
~
@@ -13,81 +14,58 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
<scenario name="net-setup-odtn" description="ODTN network setup steps">
-
- <group name="ODTN-Net-Setup">
-
- <!-- Clean -->
- <step name="ODTN-Net-Setup.Wipe-Out-Data-Before" exec="onos-wipe-out"/>
-
- <!-- Make sure that there is no data in the system -->
- <step name="ODTN-Net-Setup.Initial-Summary-Check" requires="~ODTN-Net-Setup.Wipe-Out-Data-Before"
- exec="onos-check-summary ${OC1} [0-9]* 0 0 0"/>
-
- <!-- Deactivate unneeded apps -->
- <group name="ODTN-Net-Setup.Deactivate-Apps" requires="ODTN-Net-Setup.Initial-Summary-Check">
- <step name="App-Deactivate-fwd"
- exec="onos ${OCI} app deactivate org.onosproject.fwd"
- requires="ODTN-Net-Setup.Initial-Summary-Check"/>
- <step name="App-Deactivate-Openflow"
- exec="onos ${OCI} app deactivate org.onosproject.openflow"
- requires="ODTN-Net-Setup.Initial-Summary-Check"/>
- <step name="App-Deactivate-Drivers"
- exec="onos ${OCI} app deactivate org.onosproject.drivers"
- requires="ODTN-Net-Setup.Initial-Summary-Check"/>
- <step name="App-Deactivate-Mobility"
- exec="onos ${OCI} app deactivate org.onosproject.mobility"
- requires="ODTN-Net-Setup.Initial-Summary-Check"/>
- <step name="App-Deactivate-ProxyArp"
- exec="onos ${OCI} app deactivate org.onosproject.proxyarp"
- requires="ODTN-Net-Setup.Initial-Summary-Check"/>
- <step name="App-Deactivate-RouteService"
- exec="onos ${OCI} app deactivate org.onosproject.route-service"
- requires="ODTN-Net-Setup.Initial-Summary-Check"/>
- </group>
-
- <!-- Active required apps and yang models-->
- <group name="ODTN-Net-Setup.Activate-Apps" requires="ODTN-Net-Setup.Deactivate-Apps">
- <step name="App-Activate-Odtn-Service"
- exec="onos ${OCI} app activate org.onosproject.odtn-service"
- requires="ODTN-Net-Setup.Deactivate-Apps"/>
- </group>
-
- <group name="ODTN-Net-Setup.Verify-Apps" requires="ODTN-Net-Setup.Activate-Apps" delay="40">
- <parallel var="${OC#}">
- <step name="Check-Apps-${#}" exec="onos-check-apps ${OC#} optical-model,yang,config,configsync,faultmanagement,
- netconf,configsync-netconf,drivers,drivers.netconf,drivers.optical,restconf,protocols.restconfserver,
- odtn-api,drivers.odtn-driver,odtn-service,models.tapi,models.ietf,models.openconfig,models.openconfig-infinera,
- models.openconfig-odtn includes"
- requires="ODTN-Net-Setup.Activate-Apps"/>
- </parallel>
- </group>
-
- <group name="ODTN-Net-Setup.Verify-Logs" requires="ODTN-Net-Setup.Verify-Apps">
- <parallel var="${OC#}">
- <step name="Check-Logs-${#}" exec="onos-check-logs ${OC#}"/>
- </parallel>
- </group>
-
- <step name="ODTN-Net-Setup.Tapi-context" requires="ODTN-Net-Setup.Verify-Logs"
- exec="execute-tapi-context-get-call.py ${OC1} empty"/>
-
- <group name="ODTN-Net-Setup.Verify-Logs-2" requires="ODTN-Net-Setup.Tapi-context">
- <parallel var="${OC#}">
- <step name="Check-Logs-2-${#}" exec="onos-check-logs ${OC#}"/>
- </parallel>
- </group>
-
- <!-- Verify empty connectivity service -->
-
- <step name="ODTN-Net-Setup.Tapi-connectivity" requires="ODTN-Net-Setup.Tapi-context"
- exec="execute-tapi-post-call.py ${OC1} tapi-connectivity:get-connectivity-service-list empty"/>
-
- <!--TODO include check for empty connectivity service-->
- <!--TODO include 2 or more docker emulators to setup the network for phase 1.0-->
- <!--TODO push netcfg links between emulated devices -->
- <!--TODO push emulated links between emulated devices -->
- <!--TODO check logs -->
+ <group name="ODTN-Net-Setup">
+ <!-- Clean -->
+ <step name="ODTN-Net-Setup.Wipe-Out-Data-Before" exec="onos-wipe-out"/>
+ <!-- Make sure that there is no data in the system -->
+ <step name="ODTN-Net-Setup.Initial-Summary-Check" requires="~ODTN-Net-Setup.Wipe-Out-Data-Before" exec="onos-check-summary ${OC1} [0-9]* 0 0 0"/>
+ <step name="ODTN-Net-Setup.Activate-Apps" exec="onos ${OC1} app activate odtn-service" requires="ODTN-Net-Setup.Initial-Summary-Check" delay="30" />
+ <group name="ODTN-Net-Setup.Verify-Apps" requires="ODTN-Net-Setup.Activate-Apps" delay="30">
+ <parallel var="${OC#}">
+ <step name="Check-Apps-${#}" exec="onos-check-apps ${OC#} optical-model,yang,config,configsync,faultmanagement,netconf,configsync-netconf,drivers,drivers.netconf,drivers.optical,restconf,protocols.restconfserver,odtn-api,drivers.odtn-driver,odtn-service,models.tapi,models.ietf,models.openconfig,models.openconfig-infinera,models.openconfig-odtn includes" requires="ODTN-Net-Setup.Activate-Apps"/>
+ </parallel>
</group>
+ <group name="ODTN-Net-Setup.Tapi-context" requires="ODTN-Net-Setup.Verify-Apps">
+ <parallel var="${OC#}">
+ <step name="ODTN-Net-Setup.Tapi-context-${#}" exec="${ONOS_SCENARIOS}/odtn/checkUntilSucc.sh ${ONOS_SCENARIOS}/bin/execute-tapi-context-get-call.py+${OC#}+empty"/>
+ </parallel>
+ </group>
+ <!-- Verify empty connectivity service -->
+ <step name="ODTN-Net-Setup.Tapi-connectivity" requires="ODTN-Net-Setup.Tapi-context" exec="${ONOS_SCENARIOS}/odtn/checkUntilSucc.sh ${ONOS_SCENARIOS}/bin/execute-tapi-post-call.py+${OC1}+tapi-connectivity:get-connectivity-service-list+empty"/>
+ <group name="ODTN-Net-Setup.Verify-Logs-1" requires="ODTN-Net-Setup.Tapi-connectivity">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-Odtn-Setup-1-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
+ <!-- include 2 or more docker emulators to setup the network for phase 1.0-->
+ <group name="ODTN-Net-Setup.Init-network" requires="ODTN-Net-Setup.Verify-Logs-1">
+ <step name="ODTN-Net-Setup.Start-emulators" exec="docker-compose -f ${HOME}/emulator/docker-compose.yaml up -d"/>
+ <step name="ODTN-Net-Setup.Generate-cfg-files" requires="ODTN-Net-Setup.Start-emulators" exec="${ONOS_SCENARIOS}/odtn/createNetCfg.sh"/>
+ <step name="ODTN-Net-Setup.Put-nodes" requires="ODTN-Net-Setup.Generate-cfg-files" exec="onos-netcfg ${OC1} /tmp/odtn/openconfig-devices.json"/>
+ <group name="ODTN-Net-Setup.Wait-nodes" requires="ODTN-Net-Setup.Put-nodes">
+ <parallel var="${OC#}">
+ <step name="ODTN-Net-Setup.Wait-node-${#}" exec="${ONOS_SCENARIOS}/odtn/checkNetInit.sh device ${OC#}"/>
+ <step name="ODTN-Net-Setup.Wait-port-${#}" exec="${ONOS_SCENARIOS}/odtn/checkNetInit.sh port ${OC#}" requires="ODTN-Net-Setup.Wait-node-${#}"/>
+ </parallel>
+ </group>
+ <group name="ODTN-Net-Setup.Verify-Logs-2" requires="ODTN-Net-Setup.Wait-nodes">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-Odtn-Setup-2-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
+ <step name="ODTN-Net-Setup.Put-links" requires="ODTN-Net-Setup.Verify-Logs-2" exec="onos-netcfg ${OC1} /tmp/odtn/openconfig-device-link.json"/>
+ <group name="ODTN-Net-Setup.Wait-links" requires="ODTN-Net-Setup.Put-links" delay="30">
+ <parallel var="${OC#}">
+ <step name="ODTN-Net-Setup.Wait-link-${#}" exec="${ONOS_SCENARIOS}/odtn/checkNetInit.sh link ${OC#}"/>
+ </parallel>
+ </group>
+ </group>
+ <!-- check logs to verify -->
+ <group name="ODTN-Net-Setup.Verify-Logs-3" requires="ODTN-Net-Setup.Wait-links">
+ <parallel var="${OC#}">
+ <step name="Check-Logs-Odtn-Setup-3-${#}" exec="onos-check-logs ${OC#}"/>
+ </parallel>
+ </group>
+ </group>
</scenario>
diff --git a/tools/test/scenarios/net-teardown-odtn.xml b/tools/test/scenarios/net-teardown-odtn.xml
index be063c1..be78544 100644
--- a/tools/test/scenarios/net-teardown-odtn.xml
+++ b/tools/test/scenarios/net-teardown-odtn.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
<!--
~ Copyright 2015-present Open Networking Foundation
~
@@ -14,11 +15,8 @@
~ limitations under the License.
-->
<scenario name="net-teardown-odtn" description="Network teardown steps">
- <group name="Net-Teardown-ODTN">
- <!-- TODO remove docker simulators docker stop $(docker ps -aq) -->
- <group name="ODTN-Net-Teardown.Deactivate-Apps-2">
- <step name="App-Dectivate-Odtn-Service"
- exec="onos ${OCI} app deactivate org.onosproject.odtn-service"/>
- </group>
- </group>
-</scenario>
\ No newline at end of file
+ <group name="Net-Teardown-ODTN">
+ <step name="App-Dectivate-Odtn-Service" exec="onos ${OCI} app deactivate org.onosproject.odtn-service"/>
+ <step name="Remove-onos-images-stop-emulators" requires="App-Dectivate-Odtn-Service" exec="${ONOS_SCENARIOS}/odtn/destroyOdtnCell.sh"/>
+ </group>
+</scenario>
diff --git a/tools/test/scenarios/odtn/README.md b/tools/test/scenarios/odtn/README.md
new file mode 100644
index 0000000..61b68f9
--- /dev/null
+++ b/tools/test/scenarios/odtn/README.md
@@ -0,0 +1,44 @@
+## Description
+
+This directory contains several Shell scripts for ODTN project testing in STC environment.
+
+### The normal steps of single-instance ODTN testing are listed:
+
+#### 1. "./testOnSingleONOS.sh"
+
+This command do odtn-setvice startup on local ONOS instance, and line-side/client-side connectivity creation and deletion.
+The requirement for this script's invocation is explained in it's comment.
+
+### The normal steps of multi-instance ODTN testing are listed:
+
+#### 1. `stc net-odtn-presmoke`
+This command completes preparation for testing, including latest onos image build, and onos/atomix cluster containers startup. Also, because of dynamic IP Address for containers, some related environment variables are stored in /tmp/odtn/OCvar.sh. All subsequent stc command should source this file as default environment. An example of this file is:
+
+```shell
+#!/bin/bash
+export OC1=172.17.0.5
+export OC2=172.17.0.6
+export OC3=172.17.0.7
+export OCI=172.17.0.5
+export ONOS_INSTANCES="172.17.0.5 172.17.0.6 172.17.0.7"
+export ONOS_USER=root
+export ONOS_INSTALL_DIR=/root/onos/apache-karaf-4.2.3/data
+```
+
+Besides, the access for each onos container are very easy (`source /tmp/odtn/OCvar` firstly):
+* If you want to login ONOS CLI directly, please type `onos $OC1/2/3`.
+* If you want to login ONOS container, please type `ssh root@OC1/2/3`.
+
+#### 2. `stc -ENV_DEFAULT=/tmp/odtn/OCvar.sh net-odtn-smoke`
+
+This command contains thress substeps in order, you can use these steps one by one:
+* `stc -ENV_DEFAULT=/tmp/odtn/OCvar.sh net-setup-odtn`
+In this step, `odtn-service` and related multiple apps are installed and checked. Then emulator containers are started, whose topology is pushed into onos/atomix cluster via `onos-netcfg`.
+
+This command invokes script `CheckNetInit.sh`, which need file "~/emulator/net-summary.json" to load number of device/port/link.
+
+* `stc -ENV_DEFAULT=/tmp/odtn/OCvar.sh net-odtn-restconf`
+In this step, line-side and client-side connectivity creation and deletion are tested.
+
+* `stc -ENV_DEFAULT=/tmp/odtn/OCvar.sh net-teardown-odtn`
+In this step, all onos/atomix/emulator containers are stopped and removed, and onos images are removed.
diff --git a/tools/test/scenarios/odtn/buildOdtnDocker.sh b/tools/test/scenarios/odtn/buildOdtnDocker.sh
new file mode 100755
index 0000000..1844714
--- /dev/null
+++ b/tools/test/scenarios/odtn/buildOdtnDocker.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# This script is used to build onos by using bazel, and create related docker image from ${ONOS_ROOT}/tools/dev/Dockerfile-dev
+
+# Initialize the environment
+shopt -s expand_aliases
+export PATH="$PATH:$HOME/bin:onos/bin"
+export ONOS_ROOT=~/onos
+source ${ONOS_ROOT}/tools/dev/bash_profile
+
+# Compile and Package ONOS
+cd ${ONOS_ROOT}
+# ob is replaced by bazel build onos
+bazel build onos
+rtn=$?
+if [[ ${rtn} -ne 0 ]]
+then
+ exit ${rtn}
+fi
+# Re-deploy ONOS
+[ -f tools/dev/onos.tar.gz ] && rm -f tools/dev/onos.tar.gz
+cp bazel-bin/onos.tar.gz tools/dev/
+# Build ONOS's docker image, and start ONOS cluster through docker
+cd tools/dev/
+docker build -t onos -f Dockerfile-dev .
+rm -f onos.tar.gz
+exit $?
diff --git a/tools/test/scenarios/odtn/checkNetInit.sh b/tools/test/scenarios/odtn/checkNetInit.sh
new file mode 100755
index 0000000..d000c1a
--- /dev/null
+++ b/tools/test/scenarios/odtn/checkNetInit.sh
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+# Two input parameters:
+# $1 - one of {device, port, link}, specify what needs to be checked.
+# $2 - IP address of ONOS instance.
+
+# remove all spaces of first input parameter
+# In Mac or other systems, there maybe extra whitespaces before the result of `wc -l`
+function strip_space()
+{
+ tmp=$1
+ tmp="${tmp// /}"
+ return $tmp
+}
+
+strip_space $(cat ~/emulator/net-summary.json | wc -l)
+line_num=$?
+if [[ $line_num != 1 ]]; then
+ echo "JSON file should have only 1 line."
+ exit 1
+fi
+
+# Extract specific value from returned json string under onos command "odtn-show-tapi-context"
+function get_json_value()
+{
+ local json=$1
+ local key=$2
+
+ if [[ -z "$3" ]]; then
+ local num=1
+ else
+ local num=$3
+ fi
+
+ local value=$(echo "${json}" | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'${key}'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p)
+
+ return ${value}
+}
+
+tried=0
+case "$1" in
+ "device" )
+ get_json_value $( cat ~/emulator/net-summary.json) device_num
+ device_num=$?
+ strip_space $(onos $2 devices | wc -l)
+ num_in_topo=$?
+ strip_space $(onos $2 odtn-show-tapi-context | grep "<node>" | wc -l)
+ num_in_tapi=$?
+ while [[ "$num_in_topo" != "$device_num" || "$num_in_tapi" != "$device_num" ]]
+ do
+ echo "On ONOS $2, current device num in topo:$num_in_topo, num in tapi:$num_in_tapi, expected $device_num. Waiting..."
+ sleep 10
+ strip_space $(onos $2 devices | wc -l)
+ num_in_topo=$?
+ strip_space $(onos $2 odtn-show-tapi-context | grep "<node>" | wc -l)
+ num_in_tapi=$?
+ let "tried=tried+1"
+ if [[ "$tried" == "10" ]]; then
+ exit 99
+ fi
+ done
+ ;;
+ "port" )
+ get_json_value $( cat ~/emulator/net-summary.json) port_num
+ port_num=$?
+ get_json_value $( cat ~/emulator/net-summary.json) device_num
+ device_num=$?
+ strip_space $(onos $2 ports | wc -l)
+ num_in_topo=$?
+ strip_space $(onos $2 odtn-show-tapi-context | grep "<owned-node-edge-point>" | wc -l)
+ num_in_tapi=$?
+ num_in_topo=$[num_in_topo-device_num]
+ while [[ "$num_in_topo" != "$port_num" || "$num_in_tapi" != "$port_num" ]]
+ do
+ echo "On ONOS $2, current port num in topo: $num_in_topo, num in tapi: $num_in_tapi, expected $port_num. Waiting..."
+ sleep 10
+ strip_space $(onos $2 ports | wc -l)
+ num_in_topo=$?
+ strip_space $(onos $2 odtn-show-tapi-context | grep "<owned-node-edge-point>" | wc -l)
+ num_in_tapi=$?
+ num_in_topo=$[num_in_topo-device_num]
+ let "tried=tried+1"
+ if [[ "$tried" == "10" ]]; then
+ exit 99
+ fi
+ done
+ ;;
+ "link" )
+ get_json_value $( cat ~/emulator/net-summary.json) link_num
+ link_num=$?
+ strip_space $(onos $2 links | wc -l)
+ num_in_topo=$?
+ strip_space $(onos $2 odtn-show-tapi-context | grep "<link>" | wc -l)
+ num_in_tapi=$?
+ while [[ "$num_in_topo" != "$link_num" || "$num_in_tapi" != "$link_num" ]]
+ do
+ echo "On ONOS $2, current link num in topo: $num_in_topo, num in tapi: $num_in_tapi, expected $link_num. Waiting..."
+ sleep 10
+ num_in_topo=`onos $2 links | wc -l`
+ strip_space $(onos $2 links | wc -l)
+ num_in_topo=$?
+ strip_space $(onos $2 odtn-show-tapi-context | grep "<link>" | wc -l)
+ num_in_tapi=$?
+ let "tried=tried+1"
+ if [[ "$tried" == "10" ]]; then
+ exit 99
+ fi
+ done
+esac
diff --git a/tools/test/scenarios/odtn/checkUntilSucc.sh b/tools/test/scenarios/odtn/checkUntilSucc.sh
new file mode 100755
index 0000000..5dee974
--- /dev/null
+++ b/tools/test/scenarios/odtn/checkUntilSucc.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# This script is used to execute some checking commands in period to confirm whether specific requirement is satisfied.
+# $1 - the command to be executed in this script, whose parameter splitter is +, but ont space. This command could use |, &&, || to concatenate multiple shell commands.
+# $2 - Optional. If exists, it means the output (Note: not returned value) of $1 should equals $2.
+
+cmd=${1//'+'/' '}
+if [ $# == 1 ]; then
+ for i in {1..60}; do
+ eval ${cmd}
+ rtn=$?
+ if [[ ${rtn} -ne 0 ]]
+ then
+ echo "$i-th execution returns $rtn"
+ sleep 3
+ else
+ exit 0
+ fi
+ done
+elif [ $# == 2 ]; then
+ for i in {1..60}; do
+ out=`eval ${cmd}`
+ rtn=$?
+ out="${out// /}"
+ if [[ ${rtn} -ne 0 || "$out" != $2 ]]; then
+ echo "$i-th execution fails"
+ sleep 3
+ else
+ exit 0
+ fi
+ done
+fi
diff --git a/tools/test/scenarios/odtn/createNetCfg.sh b/tools/test/scenarios/odtn/createNetCfg.sh
new file mode 100755
index 0000000..9bbd456
--- /dev/null
+++ b/tools/test/scenarios/odtn/createNetCfg.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Get first IPv4 Address on local machine, even the machine has lots of NICs.
+localIP=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:" | head -n1`
+mkdir /tmp/odtn
+# Replace IP address in openconfig json files with real ones.
+cat ${ONOS_ROOT}/apps/odtn/api/src/test/resources/openconfig-devices.json | sed "s/127.0.0.1/${localIP}/g" > /tmp/odtn/openconfig-devices.json
+cat ${ONOS_ROOT}/apps/odtn/api/src/test/resources/openconfig-device-link.json | sed "s/127.0.0.1/${localIP}/g" > /tmp/odtn/openconfig-device-link.json
+sleep 30
diff --git a/tools/test/scenarios/odtn/createOdtnCell.sh b/tools/test/scenarios/odtn/createOdtnCell.sh
new file mode 100755
index 0000000..91f9197
--- /dev/null
+++ b/tools/test/scenarios/odtn/createOdtnCell.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+# Create onos and atomix containers from related images.
+
+# Initialize the environment
+shopt -s expand_aliases
+export PATH="$PATH:$HOME/bin:onos/bin"
+export ONOS_ROOT=~/onos
+source ${ONOS_ROOT}/tools/dev/bash_profile
+KARAF_VERSION=`cat ${ONOS_ROOT}/tools/build/envDefaults | grep KARAF_VERSION= | awk -F '=' '{print $2}'`
+
+# Start ONOS cluster through docker
+cd ~/onos/tools/tutorials/vm
+SSH_KEY=$(cut -d\ -f2 ~/.ssh/id_rsa.pub)
+FULL_SSH_KEY=$(cat ~/.ssh/id_rsa.pub)
+echo "The public key in local host is: $SSH_KEY"
+
+# Create Atomix cluster using Atomix docker image
+ATOMIX_IMAGE=atomix/atomix:3.1.5
+for i in {1..3}; do
+ echo "Setting up atomix-$i..."
+ docker container run --detach --name atomix-$i --hostname atomix-$i \
+ --restart=always -v /home/sdn/onos/tools/tutorials/vm/config:/atomix/config $ATOMIX_IMAGE \
+ --config /atomix/config/atomix-$i.conf
+done
+wait
+
+# Create and start ONOS cluster using ONOS docker image
+ONOS_IMAGE=onos:latest
+for i in {1..3}; do
+ echo "Setting up onos-$i..."
+ docker container run --detach --name onos-$i --hostname onos-$i --restart=always $ONOS_IMAGE
+ docker exec -i onos-$i /bin/bash -c "mkdir config; cat > config/cluster.json" < $ONOS_ROOT/tools/tutorials/vm/config/cluster-$i.json
+ docker exec -i onos-$i /bin/bash -c "touch /root/onos/apache-karaf-${KARAF_VERSION}/etc/keys.properties"
+ docker exec -i onos-$i /bin/bash -c "echo 'sdn=$SSH_KEY,_g_:admingroup' >> /root/onos/apache-karaf-${KARAF_VERSION}/etc/keys.properties"
+ docker exec -i onos-$i /bin/bash -c "/root/onos/bin/onos-user-password onos rocks"
+ docker exec -i onos-$i /bin/bash -c "ssh-keygen -f /root/.ssh/id_rsa -t rsa -N ''"
+ docker exec -i onos-$i /bin/bash -c "/etc/init.d/ssh start"
+ docker exec -i onos-$i /bin/bash -c "echo '$FULL_SSH_KEY' >> /root/.ssh/authorized_keys"
+done
+
+# Start onos and atomix docker containers
+function waitForStart {
+ sleep 5
+ for i in {1..3}; do
+ echo "Waiting for onos-$i startup..."
+ ip=$(docker container inspect onos-$i | grep \"IPAddress | cut -d: -f2 | sort -u | tr -d '", ')
+ echo "IP is: $ip"
+ for t in {1..60}; do
+ echo "$t-th times curl request"
+ curl --fail -sS http://$ip:8181/onos/v1/applications --user "onos:rocks" 1>/dev/null 2>&1 && break;
+ sleep 1;
+ done
+ echo
+ onos $ip summary >/dev/null 2>&1
+ done
+}
+
+# Extract the IP addresses of the ONOS nodes
+export OC1=$(docker container inspect onos-1 | grep \"IPAddress | cut -d: -f2 | sort -u | tr -d '", ')
+export OC2=$(docker container inspect onos-2 | grep \"IPAddress | cut -d: -f2 | sort -u | tr -d '", ')
+export OC3=$(docker container inspect onos-3 | grep \"IPAddress | cut -d: -f2 | sort -u | tr -d '", ')
+export ONOS_INSTANCES="\"$OC1 $OC2 $OC3\""
+
+waitForStart
+
+# remove known hosts
+ssh-keygen -R $OC1
+ssh-keygen -R $OC2
+ssh-keygen -R $OC3
+# add to known-hosts list
+ssh-keyscan $OC1 >> ~/.ssh/known_hosts
+ssh-keyscan $OC2 >> ~/.ssh/known_hosts
+ssh-keyscan $OC3 >> ~/.ssh/known_hosts
+
+echo "#!/bin/bash" > /tmp/odtn/OCvar.sh
+echo "export OC1=$OC1" >> /tmp/odtn/OCvar.sh
+echo "export OC2=$OC2" >> /tmp/odtn/OCvar.sh
+echo "export OC3=$OC3" >> /tmp/odtn/OCvar.sh
+echo "export OCI=$OC1" >> /tmp/odtn/OCvar.sh
+echo "export ONOS_INSTANCES=$ONOS_INSTANCES" >> /tmp/odtn/OCvar.sh
+echo "export ONOS_USER=root" >> /tmp/odtn/OCvar.sh
+echo "export ONOS_INSTALL_DIR=/root/onos/apache-karaf-${KARAF_VERSION}/data" >> /tmp/odtn/OCvar.sh
+# sleep to wait onos instances start up
+sleep 20
diff --git a/tools/test/scenarios/odtn/destroyOdtnCell.sh b/tools/test/scenarios/odtn/destroyOdtnCell.sh
new file mode 100755
index 0000000..edb640d
--- /dev/null
+++ b/tools/test/scenarios/odtn/destroyOdtnCell.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# remove existed onos and atomix containers and images, stop emulator containers
+containers=(`docker ps -a | grep -E 'onos-|atomix-|emulator' | awk '{print $1}'`)
+if [[ ${#containers} != 0 ]]; then
+ for var in ${containers[*]}; do
+ docker stop ${var} &
+ done
+ wait
+else
+ echo "There is no container existed."
+fi
+if [[ $# != 1 || "$1" != "stop-docker" ]]; then
+ if [[ ${#containers} != 0 ]]; then
+ for var in ${containers[*]}; do
+ docker rm ${var} &
+ done
+ wait
+ fi
+ images=(`docker images | grep -e onos -e none -e "<none>" | awk '{print $3}'`)
+ if [[ ${#images} != 0 ]]; then
+ for var in ${images[*]}; do
+ docker rmi ${var} &
+ done
+ wait
+ else
+ echo "There is no onos/atomix docker image existed."
+ fi
+else
+ echo "There is no container and image to be removed."
+fi
diff --git a/tools/test/scenarios/odtn/testOnSingleONOS.sh b/tools/test/scenarios/odtn/testOnSingleONOS.sh
new file mode 100755
index 0000000..4f223ac
--- /dev/null
+++ b/tools/test/scenarios/odtn/testOnSingleONOS.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# This scrip is used to test ODTN on single ONOS instance in branch 2.0
+# Before this script:
+# 1. Make sure the default Python version is 2.x
+# 2. Run ONOS locally (bazel run onos-local -- clean)
+# 3. Start sshd service, and make sure "ssh $USER@localhost" operation doesn't need passwd
+# 4. Emulator configuration could be found under directory $HOME/emulator
+
+# env configuration
+ONOS_ROOT="${ONOS_ROOT:-~/onos}"
+source ${ONOS_ROOT}/tools/dev/bash_profile
+source ${ONOS_ROOT}/tools/build/envDefaults
+unset OC2
+unset OC3
+export OC1="127.0.0.1"
+export OCI="$OC1"
+export ONOS_INSTANCES="$OC1"
+export ONOS_USER=$USER
+
+OV=`echo $ONOS_VERSION | sed "s/\.$USER/-SNAPSHOT/g" `
+export ONOS_INSTLL_DIR=/tmp/onos-${OV}/apache-karaf-${KARAF_VERSION}/data
+export EMULATOR_ROOT="${EMULATOR_ROOT:-$HOME/emulator}"
+
+for t in {1..60}; do
+ echo "$t-th times curl request"
+ curl --fail -sS http://localhost:8181/onos/v1/applications --user "onos:rocks" 1>/dev/null 2>&1 && break;
+ sleep 2
+done
+
+# activate odtn-service
+# run emulator, and push topo into local onos instance
+cd ${EMULATOR_ROOT}
+docker-compose up -d
+stc net-setup-odtn
+if [[ $? == 0 ]]; then
+ stc net-odtn-restconf
+fi
diff --git a/tools/test/scenarios/stop-docker.xml b/tools/test/scenarios/stop-docker.xml
new file mode 100644
index 0000000..fc95cc6
--- /dev/null
+++ b/tools/test/scenarios/stop-docker.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!--
+ ~ Copyright 2015-present Open Networking Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<scenario name="Stop-docker" description="Stop all docker containers with prefix onos- atomix- emulator-">
+ <step name="Stop-docker.stop-all" exec="${ONOS_SCENARIOS}/odtn/destroyOdtnCell.sh stop-docker"/>
+</scenario>