Enhancing STC

Change-Id: Ibb8a001f5c6550860c4ade97378af7e97876a0ab
diff --git a/tools/test/bin/onos-check-apps b/tools/test/bin/onos-check-apps
index 9760a41..db5a473 100755
--- a/tools/test/bin/onos-check-apps
+++ b/tools/test/bin/onos-check-apps
@@ -13,7 +13,8 @@
 cut -c7- $aux | cut -d\  -f1 | sort > $aux.1
 
 # Normalize the expected apps
-apps=${ONOS_APPS:-drivers,openflow}
+apps=${2:-$ONOS_APPS}
+apps=${apps:-drivers,openflow}
 (for app in ${apps//,/ }; do echo org.onosproject.$app; done) | sort > $aux.2
 
 # Check for differences
diff --git a/tools/test/bin/onos-check-nodes b/tools/test/bin/onos-check-nodes
new file mode 100755
index 0000000..983d1e6
--- /dev/null
+++ b/tools/test/bin/onos-check-nodes
@@ -0,0 +1,21 @@
+#!/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" > $aux
+cat $aux
+
+# Normalize the nodes
+cut -d= -f3 $aux | cut -d: -f1 | sort > $aux.1
+
+# Normalize the expected apps
+ONOS_NODES=$(env | egrep "OC[0-9]*=" | cut -d= -f2 | sort)
+nodes=${2:-$ONOS_NODES}
+(for node in $nodes; do echo $node; done) | sort > $aux.2
+
+# Check for differences
+diff $aux.1 $aux.2
diff --git a/tools/test/bin/onos-untar-and-run b/tools/test/bin/onos-untar-and-run
new file mode 100755
index 0000000..74ce559
--- /dev/null
+++ b/tools/test/bin/onos-untar-and-run
@@ -0,0 +1,22 @@
+#!/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
+    bin/onos-service server 1>/tmp/onos.out 2>/tmp/onos.err &
+
+    # Setup a symlink to allow other tools to work
+    sudo ln -s /tmp/$ONOS_BITS $ONOS_INSTALL_DIR
+"
diff --git a/tools/test/cells/tomx b/tools/test/cells/tomx
index b055449..8522bd5 100644
--- a/tools/test/cells/tomx
+++ b/tools/test/cells/tomx
@@ -5,3 +5,5 @@
 export OC2="10.128.11.2"
 export OC3="10.128.11.3"
 export OCN="10.128.11.4"
+
+export OCT=$OC1
diff --git a/tools/test/scenarios/setup.xml b/tools/test/scenarios/setup.xml
index 8a24540..9630c98 100644
--- a/tools/test/scenarios/setup.xml
+++ b/tools/test/scenarios/setup.xml
@@ -18,10 +18,11 @@
         <step name="Push-Bits" exec="onos-push-bits-through-proxy" if="${OCT}"/>
 
         <parallel var="${OC#}">
+            <step name="Push-Bits-${#}" exec="onos-push-bits ${OC#}" unless="${OCT}"/>
             <step name="Uninstall-${#}" exec="onos-uninstall ${OC#}"/>
 
             <step name="Install-${#}" exec="onos-install ${OC#}"
-                  requires="Uninstall-${#},Push-Bits"/>
+                  requires="Uninstall-${#},Push-Bits-${#},Push-Bits"/>
 
             <step name="Wait-for-Start-${#}" exec="onos-wait-for-start ${OC#}"
                   requires="Install-${#}"/>
diff --git a/tools/test/scenarios/tar-setup.xml b/tools/test/scenarios/tar-setup.xml
new file mode 100644
index 0000000..964c83e
--- /dev/null
+++ b/tools/test/scenarios/tar-setup.xml
@@ -0,0 +1,66 @@
+<!--
+  ~ 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}"/>
+
+        <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#}"/>
+
+            <step name="Untar-And-Run-${#}" exec="onos-untar-and-run ${OC#}"
+                  requires="Uninstall-${#},Push-Bits-${#},Push-Bits"/>
+
+            <step name="Wait-for-Start-${#}" exec="onos-wait-for-start ${OC#}"
+                  requires="Untar-And-Run-${#}"/>
+
+            <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 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/utils/stc/src/main/java/org/onlab/stc/Compiler.java b/utils/stc/src/main/java/org/onlab/stc/Compiler.java
index daa9f77..2a8a2ce 100644
--- a/utils/stc/src/main/java/org/onlab/stc/Compiler.java
+++ b/utils/stc/src/main/java/org/onlab/stc/Compiler.java
@@ -106,7 +106,8 @@
                                       ImmutableSet.copyOf(dependencies));
 
         // Extract the log directory if there was one specified
-        String path = scenario.definition().getString(LOG_DIR, DEFAULT_LOG_DIR);
+        String defaultPath = DEFAULT_LOG_DIR + scenario.name();
+        String path = scenario.definition().getString(LOG_DIR, defaultPath);
         logDir = new File(expand(path));
     }
 
diff --git a/utils/stc/src/main/java/org/onlab/stc/ScenarioStore.java b/utils/stc/src/main/java/org/onlab/stc/ScenarioStore.java
index 614afb1..70b5cb0 100644
--- a/utils/stc/src/main/java/org/onlab/stc/ScenarioStore.java
+++ b/utils/stc/src/main/java/org/onlab/stc/ScenarioStore.java
@@ -38,6 +38,7 @@
 
     private final ProcessFlow processFlow;
     private final File storeFile;
+    private final File logDir;
 
     private final List<StepEvent> events = Lists.newArrayList();
     private final Map<String, Status> statusMap = Maps.newConcurrentMap();
@@ -51,6 +52,7 @@
      */
     ScenarioStore(ProcessFlow processFlow, File logDir, String name) {
         this.processFlow = processFlow;
+        this.logDir = logDir;
         this.storeFile = new File(logDir, name + ".stc");
         load();
     }
@@ -63,6 +65,7 @@
         statusMap.clear();
         processFlow.getVertexes().forEach(step -> statusMap.put(step.name(), WAITING));
         try {
+            removeLogs();
             PropertiesConfiguration cfg = new PropertiesConfiguration(storeFile);
             cfg.clear();
             cfg.save();
@@ -171,4 +174,18 @@
         }
     }
 
+    /**
+     * Removes all scenario log files.
+     */
+    private void removeLogs() {
+        File[] logFiles = logDir.listFiles();
+        if (logFiles != null && logFiles.length > 0) {
+            for (File file : logFiles) {
+                if (!file.delete()) {
+                    print("Unable to delete log file %s", file);
+                }
+            }
+        }
+    }
+
 }