Changes to docker file and cluster creation, complete stc test on single instance, but not yet on multi-instances Alao, we add detailed checking for every step in ODTN testing.

Change-Id: Id074e2db89a8892ed263880cfa670c4861e011b9
diff --git a/tools/test/scenarios/odtn/README.md b/tools/test/scenarios/odtn/README.md
new file mode 100644
index 0000000..8a6eae6
--- /dev/null
+++ b/tools/test/scenarios/odtn/README.md
@@ -0,0 +1,36 @@
+## Description
+
+This directory contains several Shell scripts for ODTN project testing in STC environment.
+The normal steps of 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..792a8d7
--- /dev/null
+++ b/tools/test/scenarios/odtn/checkNetInit.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+# Two input parameters:
+# $1 - one of {device, port, link}, specify what needs to be checked.
+# $2 - IP address of ONOS instance.
+
+line_num=`cat ~/emulator/net-summary.json | wc -l`
+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=$?
+        num_in_topo=`onos $2 devices | wc -l`
+        num_in_tapi=`onos $2 odtn-show-tapi-context | grep "<node>" | wc -l`
+        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
+            num_in_topo=`onos $2 devices | wc -l`
+                num_in_tapi=`onos $2 odtn-show-tapi-context | grep "<node>" | wc -l`
+            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=$?
+        num_in_tapi=`onos $2 odtn-show-tapi-context | grep "<owned-node-edge-point>" | wc -l`
+        num_in_topo=`onos $2 ports | wc -l`
+        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
+            num_in_topo=`onos $2 ports | wc -l`
+            num_in_topo=$[num_in_topo-device_num]
+            num_in_tapi=`onos $2 odtn-show-tapi-context | grep "<owned-node-edge-point>" | wc -l`
+            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=$?
+        num_in_topo=`onos $2 links | wc -l`
+        num_in_tapi=`onos $2 odtn-show-tapi-context | grep "<link>" | wc -l`
+            while [[ "$num_in_topo" != "$link_num" || "$num_in_tapi" != "$link_num" ]]
+            do
+                    echo "On ONOS $2, current link num: $num_in_topo, expected $link_num. Waiting..."
+            sleep 10
+                    num_in_topo=`onos $2 links | wc -l`
+            num_in_tapi=`onos $2 odtn-show-tapi-context | grep "<link>" | wc -l`
+            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..808ac0e
--- /dev/null
+++ b/tools/test/scenarios/odtn/checkUntilSucc.sh
@@ -0,0 +1,31 @@
+#!/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=$?
+        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