Embed public key in user data, various other updates 67/25367/1
authorBryan Sullivan <bryan.sullivan@att.com>
Thu, 1 Dec 2016 21:20:47 +0000 (13:20 -0800)
committerBryan Sullivan <bryan.sullivan@att.com>
Thu, 1 Dec 2016 21:20:47 +0000 (13:20 -0800)
JIRA: MODELS-23

Add test duration and timestamps.
Add image and key cleanup to stop function.
Update Tacker Heat timeout config values.

Change-Id: I55da984477389d4eabb84abec522f58b3eed0032
Signed-off-by: Bryan Sullivan <bryan.sullivan@att.com>
tests/blueprints/tosca-vnfd-hello-world-tacker/blueprint.yaml
tests/utils/tacker-setup.sh
tests/vHello_Tacker.sh

index 99b8d9d..bf570cc 100755 (executable)
@@ -12,7 +12,7 @@ topology_template:
       artifacts:
         VNFImage:
           type: tosca.artifacts.Deployment.Image.VM
-          file: http://artifacts.opnfv.org/models/images/xenial-server-cloudimg-amd64-disk1.img
+          file: http://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img
       capabilities:
         nfv_compute:
           properties:
@@ -29,6 +29,12 @@ topology_template:
         user_data: |
           #!/bin/bash
           set -x
+          mkdir /home/ubuntu
+          mkdir /home/ubuntu/.ssh
+          cat << EOM >/home/ubuntu/.ssh/authorized_keys
+          <pubkey>
+          EOM
+          chown -R ubuntu /home/ubuntu
           sudo mount /dev/sr0 /mnt/
           cd /tmp
           id=$(cut -d ',' -f 3 /mnt/openstack/latest/meta_data.json)
index a523a8a..4935d93 100644 (file)
 #   setup: Setup of Tacker in the docker container
 #   clean: Clean
 
+trap 'fail' ERR
+
 pass() {
-  echo "$0: Hooray!"
-  set +x #echo off
+  echo "$0: $(date) Hooray!"
+  end=`date +%s`
+  runtime=$((end-start))
+  echo "$0: $(date) Duration = $runtime seconds"
   exit 0
 }
 
 fail() {
-  echo "$0: Failed!"
-  set +x
+  echo "$0: $(date) Test Failed!"
+  end=`date +%s`
+  runtime=$((end-start))
+  runtime=$((runtime/60))
+  echo "$0: $(date) Duration = $runtime seconds"
   exit 1
 }
 
 function setenv () {
-  echo "$0: Setup shared virtual folders and save this script there"
+  echo "$0: $(date) Setup shared virtual folders and save this script there"
   mkdir /tmp/tacker
   cp $0 /tmp/tacker/.
   chmod 755 /tmp/tacker/*.sh
 
-  echo "$0: Setup admin-openrc.sh"
+  echo "$0: $(date) Setup admin-openrc.sh"
 
   if [ "$dist" == "Ubuntu" ]; then
-    echo "$0: Ubuntu-based install"
-    echo "$0: Create the environment file"
+    echo "$0: $(date) Ubuntu-based install"
+    echo "$0: $(date) Create the environment file"
     KEYSTONE_HOST=$(juju status --format=short | awk "/keystone\/0/ { print \$3 }")
     cat <<EOF >/tmp/tacker/admin-openrc.sh
 export CONGRESS_HOST=$(juju status --format=short | awk "/openstack-dashboard/ { print \$3 }")
@@ -68,12 +75,12 @@ export OS_REGION_NAME=RegionOne
 EOF
  else
     # Centos
-    echo "$0: Centos-based install"
-    echo "$0: Setup undercloud environment so we can get overcloud Controller server address"
+    echo "$0: $(date) Centos-based install"
+    echo "$0: $(date) Setup undercloud environment so we can get overcloud Controller server address"
     source ~/stackrc
-    echo "$0: Get address of Controller node"
+    echo "$0: $(date) Get address of Controller node"
     export CONTROLLER_HOST1=$(openstack server list | awk "/overcloud-controller-0/ { print \$8 }" | sed 's/ctlplane=//g')
-    echo "$0: Create the environment file"
+    echo "$0: $(date) Create the environment file"
     cat <<EOF >/tmp/tacker/admin-openrc.sh
 export CONGRESS_HOST=$CONTROLLER_HOST1
 export KEYSTONE_HOST=$CONTROLLER_HOST1
@@ -104,17 +111,17 @@ function get_external_net () {
     EXTERNAL_NETWORK_NAME=$(openstack network show $ext_net_id | awk "/ name / { print \$4 }")
     EXTERNAL_SUBNET_ID=$(openstack network show $EXTERNAL_NETWORK_NAME | awk "/ subnets / { print \$4 }")
   else
-    echo "$0: External network not found"
+    echo "$0: $(date) External network not found"
     exit 1
   fi
 }
 
 function create_container () {
-  echo "$0: Creating docker container for Tacker installation"
+  echo "$0: $(date) Creating docker container for Tacker installation"
   # STEP 1: Create the Tacker container and launch it
-  echo "$0: Setup container"
+  echo "$0: $(date) Setup container"
   if [ "$dist" == "Ubuntu" ]; then
-    echo "$0: Ubuntu-based install"
+    echo "$0: $(date) Ubuntu-based install"
     # xenial is needed for python 3.5
     sudo docker pull ubuntu:xenial
     sudo service docker start
@@ -139,10 +146,10 @@ EOF
 }
 
 function setup () {
-  echo "$0: Installing Tacker"
+  echo "$0: $(date) Installing Tacker"
   # STEP 2: Install Tacker in the container
   # Per http://docs.openstack.org/developer/tacker/install/manual_installation.html
-  echo "$0: Install dependencies - OS specific"
+  echo "$0: $(date) Install dependencies - OS specific"
   if [ "$dist" == "Ubuntu" ]; then
     apt-get update
     apt-get install -y python
@@ -164,29 +171,29 @@ function setup () {
 
   cd /tmp/tacker
 
-  echo "$0: create Tacker database"
+  echo "$0: $(date) create Tacker database"
   mysql --user=root --password=$MYSQL_PASSWORD -e "CREATE DATABASE tacker; GRANT ALL PRIVILEGES ON tacker.* TO 'root@localhost' IDENTIFIED BY '"$MYSQL_PASSWORD"'; GRANT ALL PRIVILEGES ON tacker.* TO 'root'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"';"
 
-  echo "$0: Upgrage pip again - needs to be the latest version due to errors found in earlier testing"
+  echo "$0: $(date) Upgrage pip again - needs to be the latest version due to errors found in earlier testing"
   pip install --upgrade pip
 
-  echo "$0: install python-openstackclient python-glanceclient"
+  echo "$0: $(date) install python-openstackclient python-glanceclient"
   pip install --upgrade python-openstackclient python-glanceclient python-neutronclient keystonemiddleware
 
-  echo "$0: Setup admin-openrc.sh"
+  echo "$0: $(date) Setup admin-openrc.sh"
   source /tmp/tacker/admin-openrc.sh
 
-  echo "$0: Setup Tacker user in OpenStack"
+  echo "$0: $(date) Setup Tacker user in OpenStack"
   service_project=$(openstack project list | awk "/service/ { print \$4 }")
   openstack user create --project $service_project --password tacker tacker
   openstack role add --project $service_project --user tacker admin
 
-  echo "$0: Create Tacker service in OpenStack"
+  echo "$0: $(date) Create Tacker service in OpenStack"
   sid=$(openstack service list | awk "/ tacker / { print \$2 }")
   openstack service create --name tacker --description "Tacker Project" nfv-orchestration
   sid=$(openstack service list | awk "/ tacker / { print \$2 }")
 
-  echo "$0: Create Tacker service endpoint in OpenStack"
+  echo "$0: $(date) Create Tacker service endpoint in OpenStack"
   ip=$(ip addr | awk "/ global eth0/ { print \$2 }" | sed -- 's/\/16//')
   region=$(openstack endpoint list | awk "/ nova / { print \$4 }")
   openstack endpoint create --region $region \
@@ -194,25 +201,25 @@ function setup () {
       --adminurl "http://$ip:9890/" \
       --internalurl "http://$ip:9890/" $sid
 
-  echo "$0: Clone Tacker"
+  echo "$0: $(date) Clone Tacker"
   if [[ -d /tmp/tacker/tacker ]]; then rm -rf /tmp/tacker/tacker; fi
   git clone git://git.openstack.org/openstack/tacker
   cd tacker
   git checkout stable/mitaka
 
-  echo "$0: Setup Tacker"
+  echo "$0: $(date) Setup Tacker"
   pip install -r requirements.txt
   pip install tosca-parser
   python setup.py install
   mkdir /var/log/tacker
 
   # Following lines apply to master and not stable/mitaka
-  #echo "$0: install tox"
+  #echo "$0: $(date) install tox"
   #pip install tox
-  #echo "$0: generate tacker.conf.sample"
+  #echo "$0: $(date) generate tacker.conf.sample"
   #tox -e config-gen
 
-  echo "$0: Update tacker.conf values"
+  echo "$0: $(date) Update tacker.conf values"
   mkdir /usr/local/etc/tacker
   cp etc/tacker/tacker.conf /usr/local/etc/tacker/tacker.conf
   sed -i -- 's/# auth_strategy = keystone/auth_strategy = keystone/' /usr/local/etc/tacker/tacker.conf
@@ -232,11 +239,13 @@ function setup () {
   sed -i -- "s~# api_paste_config = api-paste.ini~api_paste_config = /tmp/tacker/tacker/etc/tacker/api-paste.ini~" /usr/local/etc/tacker/tacker.conf
   sed -i -- "s/# bind_host = 0.0.0.0/bind_host = $ip/" /usr/local/etc/tacker/tacker.conf
   sed -i -- "s/# bind_port = 8888/bind_port = 9890/" /usr/local/etc/tacker/tacker.conf
+  sed -i -- "s/stack_retries = 60/stack_retries = 10/" /usr/local/etc/tacker/tacker.conf
+  sed -i -- "s/stack_retry_wait = 5/stack_retry_wait = 60/" /usr/local/etc/tacker/tacker.conf
 
-  echo "$0: Populate Tacker database"
+  echo "$0: $(date) Populate Tacker database"
   /usr/local/bin/tacker-db-manage --config-file /usr/local/etc/tacker/tacker.conf upgrade head
 
-  echo "$0: Install Tacker Client"
+  echo "$0: $(date) Install Tacker Client"
   cd /tmp/tacker
   if [[ -d /tmp/tacker/python-tackerclient ]]; then rm -rf /tmp/tacker/python-tackerclient; fi
   git clone https://github.com/openstack/python-tackerclient
@@ -245,7 +254,7 @@ function setup () {
   python setup.py install
 
   # deferred until its determined how to get this to Horizon
-  #echo "$0: Install Tacker Horizon plugin"
+  #echo "$0: $(date) Install Tacker Horizon plugin"
   #cd /tmp/tacker
   #git clone https://github.com/openstack/tacker-horizon
   #cd tacker-horizon
@@ -254,13 +263,13 @@ function setup () {
   #cp openstack_dashboard_extensions/* /usr/share/openstack-dashboard/openstack_dashboard/enabled/
   #service apache2 restart
 
-  echo "$0: Start the Tacker Server"
+  echo "$0: $(date) Start the Tacker Server"
   nohup python /usr/local/bin/tacker-server --config-file /usr/local/etc/tacker/tacker.conf --log-file /var/log/tacker/tacker.log & disown
 
-  echo "$0: Wait 30 seconds for Tacker server to come online"
+  echo "$0: $(date) Wait 30 seconds for Tacker server to come online"
   sleep 30
 
-  echo "$0: Register default VIM"
+  echo "$0: $(date) Register default VIM"
   cd /tmp/tacker
   cat <<EOF >vim-config.yaml 
 auth_url: $OS_AUTH_URL
@@ -277,43 +286,43 @@ EOF
 function setup_test_environment () {
   echo "Create management network"
   if [ $(neutron net-list | awk "/ vnf_mgmt / { print \$2 }") ]; then
-    echo "$0: vnf_mgmt network exists"
+    echo "$0: $(date) vnf_mgmt network exists"
   else
     neutron net-create vnf_mgmt                
-    echo "$0: Create management subnet"
+    echo "$0: $(date) Create management subnet"
     neutron subnet-create vnf_mgmt 192.168.200.0/24 --name vnf_mgmt --gateway 192.168.200.1 --enable-dhcp --allocation-pool start=192.168.200.2,end=192.168.200.254 --dns-nameserver 8.8.8.8
   fi
 
-  echo "$0: Create router for vnf_mgmt network"
+  echo "$0: $(date) Create router for vnf_mgmt network"
   if [ $(neutron router-list | awk "/ vnf_mgmt / { print \$2 }") ]; then
-    echo "$0: vnf_mgmt router exists"
+    echo "$0: $(date) vnf_mgmt router exists"
   else
     neutron router-create vnf_mgmt_router
-    echo "$0: Create router gateway for vnf_mgmt network"
+    echo "$0: $(date) Create router gateway for vnf_mgmt network"
     get_external_net
     neutron router-gateway-set vnf_mgmt_router $EXTERNAL_NETWORK_NAME
-    echo "$0: Add router interface for vnf_mgmt network"
+    echo "$0: $(date) Add router interface for vnf_mgmt network"
     neutron router-interface-add vnf_mgmt_router subnet=vnf_mgmt
   fi
 
   echo "Create private network"
   if [ $(neutron net-list | awk "/ vnf_private / { print \$2 }") ]; then
-    echo "$0: vnf_private network exists"
+    echo "$0: $(date) vnf_private network exists"
   else
     neutron net-create vnf_private             
-    echo "$0: Create private subnet"
+    echo "$0: $(date) Create private subnet"
     neutron subnet-create vnf_private 192.168.201.0/24 --name vnf_private --gateway 192.168.201.1 --enable-dhcp --allocation-pool start=192.168.201.2,end=192.168.201.254 --dns-nameserver 8.8.8.8
   fi
 
-  echo "$0: Create router for vnf_private network"
+  echo "$0: $(date) Create router for vnf_private network"
   if [ $(neutron router-list | awk "/ vnf_private / { print \$2 }") ]; then
-    echo "$0: vnf_private router exists"
+    echo "$0: $(date) vnf_private router exists"
   else
     neutron router-create vnf_private_router
-    echo "$0: Create router gateway for vnf_private network"
+    echo "$0: $(date) Create router gateway for vnf_private network"
     get_external_net
     neutron router-gateway-set vnf_private_router $EXTERNAL_NETWORK_NAME
-    echo "$0: Add router interface for vnf_private network"
+    echo "$0: $(date) Add router interface for vnf_private network"
     neutron router-interface-add vnf_private_router subnet=vnf_private
   fi
 }
@@ -338,13 +347,14 @@ function clean () {
   sudo docker rm -v $(sudo docker ps -a | awk "/tacker/ { print \$1 }")
 }
 
+start=`date +%s`
 dist=`grep DISTRIB_ID /etc/*-release | awk -F '=' '{print $2}'`
 case "$2" in
   "init")
     setenv
     uid=$(openstack user list | awk "/ tacker / { print \$2 }")
     if [[ $uid ]]; then
-      echo "$0: Remove prior Tacker user etc"
+      echo "$0: $(date) Remove prior Tacker user etc"
       openstack user delete tacker
       openstack service delete tacker
       # Note: deleting the service deletes the endpoint
index 9643130..0efa978 100644 (file)
 #
 # What this is: Deployment test for the Tacker Hello World blueprint.
 #
-# Status: this is a work in progress, under test.
+# Status: work in progress, planned for OPNFV Danube release.
+#
+# Use Case Description: A single-node simple python web server, connected to
+# two internal networks (private and admin), and accessible via a floating IP.
+# Based upon the OpenStack Tacker project's "tosca-vnfd-hello-world" blueprint,
+# as extended for testing of more Tacker-supported features as of OpenStack 
+# Mitaka.
+#
+# Prequisites: 
+#
 #
 # How to use:
 #   $ git clone https://gerrit.opnfv.org/gerrit/models
 #   stop: stop test and uninstall blueprint
 #   clean: cleanup after test
 
-set -x
-
 trap 'fail' ERR
 
 pass() {
-  echo "$0: Hooray!"
-  set +x #echo off
+  echo "$0: $(date) Hooray!"
+  end=`date +%s`
+  runtime=$((end-test_start))
+  echo "$0: $(date) Test Duration = $runtime seconds"
   exit 0
 }
 
 fail() {
-  echo "$0: Test Failed!"
-  set +x
+  echo "$0: $(date) Test Failed!"
+  end=`date +%s`
+  runtime=$((end-test_start))
+  runtime=$((runtime/60))
+  echo "$0: $(date) Test Duration = $runtime seconds"
   exit 1
 }
 
+assert() {
+  if [[ "$2" ]]; then echo "$0 test assertion passed: $1"
+  else 
+    echo "$0 test assertion failed: $1"
+    fail
+  fi
+}
+
 get_floating_net () {
   network_ids=($(neutron net-list|grep -v "+"|grep -v name|awk '{print $2}'))
   for id in ${network_ids[@]}; do
@@ -53,7 +73,7 @@ get_floating_net () {
   if [[ $FLOATING_NETWORK_ID ]]; then
     FLOATING_NETWORK_NAME=$(openstack network show $FLOATING_NETWORK_ID | awk "/ name / { print \$4 }")
   else
-    echo "$0: Floating network not found"
+    echo "$0: $(date) Floating network not found"
     exit 1
   fi
 }
@@ -67,115 +87,91 @@ try () {
     let count=$count-1
     $3
   done
-  if [[ $count -eq 0 ]]; then echo "$0: Command \"$3\" was not successful after $1 tries"; fi
+  if [[ $count -eq 0 ]]; then echo "$0: $(date) Command \"$3\" was not successful after $1 tries"; fi
 }
 
 setup () {
-  echo "$0: Setup temp test folder /tmp/tacker and copy this script there"
+  echo "$0: $(date) Setup temp test folder /tmp/tacker and copy this script there"
   if [ -d /tmp/tacker ]; then sudo rm -rf /tmp/tacker; fi 
   mkdir -p /tmp/tacker
   chmod 777 /tmp/tacker/
   cp $0 /tmp/tacker/.
   chmod 755 /tmp/tacker/*.sh
 
-  echo "$0: tacker-setup part 1"
+  echo "$0: $(date) tacker-setup part 1"
   bash utils/tacker-setup.sh $1 init
 
-  echo "$0: tacker-setup part 2"
+  echo "$0: $(date) tacker-setup part 2"
   CONTAINER=$(sudo docker ps -l | awk "/tacker/ { print \$1 }")
   dist=`grep DISTRIB_ID /etc/*-release | awk -F '=' '{print $2}'`
   if [ "$dist" == "Ubuntu" ]; then
-    echo "$0: JOID workaround for Colorado - enable ML2 port security"
+    echo "$0: $(date) JOID workaround for Colorado - enable ML2 port security"
     juju set neutron-api enable-ml2-port-security=true
 
-    echo "$0: Execute tacker-setup.sh in the container"
+    echo "$0: $(date) Execute tacker-setup.sh in the container"
     sudo docker exec -it $CONTAINER /bin/bash /tmp/tacker/tacker-setup.sh $1 setup
   else
-    echo "$0: Execute tacker-setup.sh in the container"
+    echo "$0: $(date) Execute tacker-setup.sh in the container"
     sudo docker exec -i -t $CONTAINER /bin/bash /tmp/tacker/tacker-setup.sh $1 setup
   fi
 
-  echo "$0: reset blueprints folder"
+  assert "models-tacker-001: Tacker is successfully installed in a docker container on the jumphost." true 
+
+  echo "$0: $(date) reset blueprints folder"
   if [[ -d /tmp/tacker/blueprints/tosca-vnfd-hello-world-tacker ]]; then rm -rf /tmp/tacker/blueprints/tosca-vnfd-hello-world-tacker; fi
   mkdir -p /tmp/tacker/blueprints/tosca-vnfd-hello-world-tacker
 
-  echo "$0: copy tosca-vnfd-hello-world-tacker to blueprints folder"
+  echo "$0: $(date) copy tosca-vnfd-hello-world-tacker to blueprints folder"
   cp -r blueprints/tosca-vnfd-hello-world-tacker /tmp/tacker/blueprints
 
-  # Following two steps are in testing still. The guestfish step needs work.
-
-  #  echo "$0: Create Nova key pair"
-  #  mkdir -p ~/.ssh
-  #  nova keypair-delete vHello
-  #  nova keypair-add vHello > /tmp/tacker/vHello.pem
-  #  chmod 600 /tmp/tacker/vHello.pem
-  #  pubkey=$(nova keypair-show vHello | grep "Public key:" | sed -- 's/Public key: //g')
-  #  nova keypair-show vHello | grep "Public key:" | sed -- 's/Public key: //g' >/tmp/tacker/vHello.pub
-
-  echo "$0: Inject key into xenial server image"
-  #  wget http://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img
-  #  sudo yum install -y libguestfs-tools
-  #  guestfish <<EOF
-#add xenial-server-cloudimg-amd64-disk1.img
-#run
-#mount /dev/sda1 /
-#mkdir /home/ubuntu
-#mkdir /home/ubuntu/.ssh
-#cat <<EOM >/home/ubuntu/.ssh/authorized_keys
-#$pubkey
-#EOM
-#exit
-#chown -R ubuntu /home/ubuntu
-#EOF
-
-  # Using pre-key-injected image for now, vHello.pem as provided in the blueprint
-  if [ ! -f /tmp/xenial-server-cloudimg-amd64-disk1.img ]; then 
-    wget -O /tmp/xenial-server-cloudimg-amd64-disk1.img  http://artifacts.opnfv.org/models/images/xenial-server-cloudimg-amd64-disk1.img
-  fi
-  cp ~/vHello.pem /tmp/tacker
-  chmod 600 /tmp/tacker/vHello.pem
-
-  echo "$0: setup OpenStack CLI environment"
+  echo "$0: $(date) setup OpenStack CLI environment"
   source /tmp/tacker/admin-openrc.sh
 
-  echo "$0: Setup image_id"
-  image_id=$(openstack image list | awk "/ models-xenial-server / { print \$2 }")
-  if [[ -z "$image_id" ]]; then glance --os-image-api-version 1 image-create --name models-xenial-server --disk-format qcow2 --file /tmp/xenial-server-cloudimg-amd64-disk1.img --container-format bare; fi 
+  echo "$0: $(date) Create Nova key pair"
+  if [[ -f /tmp/tacker/vHello ]]; then rm /tmp/tacker/vHello; fi
+  ssh-keygen -t rsa -N "" -f /tmp/tacker/vHello -C ubuntu@vHello
+  chmod 600 /tmp/tacker/vHello
+  openstack keypair create --public-key /tmp/tacker/vHello.pub vHello 
+
+  echo "$0: $(date) Inject public key into blueprint"
+  pubkey=$(cat /tmp/tacker/vHello.pub)
+  sed -i -- "s~<pubkey>~$pubkey~" /tmp/tacker/blueprints/tosca-vnfd-hello-world-tacker/blueprint.yaml
 }
 
 start() {
-  echo "$0: setup OpenStack CLI environment"
+  echo "$0: $(date) setup OpenStack CLI environment"
   source /tmp/tacker/admin-openrc.sh
 
   if [[ "$1" == "tacker-api" ]]; then
-    echo "$0: Tacker API use is not yet implemented"
+    echo "$0: $(date) Tacker API use is not yet implemented"
   else
     # Tacker CLI use
-    echo "$0: Get external network for Floating IP allocations"
+    echo "$0: $(date) Get external network for Floating IP allocations"
 
-    echo "$0: create VNFD"
+    echo "$0: $(date) create VNFD"
     cd /tmp/tacker/blueprints/tosca-vnfd-hello-world-tacker
     tacker vnfd-create --vnfd-file blueprint.yaml --name hello-world-tacker
     if [ $? -eq 1 ]; then fail; fi
 
-    echo "$0: create VNF"
+    echo "$0: $(date) create VNF"
     tacker vnf-create --vnfd-name hello-world-tacker --name hello-world-tacker
     if [ $? -eq 1 ]; then fail; fi
   fi
 
-  echo "$0: wait for hello-world-tacker to go ACTIVE"
+  echo "$0: $(date) wait for hello-world-tacker to go ACTIVE"
   active=""
   while [[ -z $active ]]
   do
     active=$(tacker vnf-show hello-world-tacker | grep ACTIVE)
     if [ "$(tacker vnf-show hello-world-tacker | grep -c ERROR)" == "1" ]; then 
-      echo "$0: hello-world-tacker VNF creation failed with state ERROR"
+      echo "$0: $(date) hello-world-tacker VNF creation failed with state ERROR"
       fail
     fi
     sleep 10
+    echo "$0: $(date) wait for hello-world-tacker to go ACTIVE"
   done
 
-  echo "$0: directly set port security on ports (bug/unsupported in Mitaka Tacker?)"
+  echo "$0: $(date) directly set port security on ports (bug/unsupported in Mitaka Tacker?)"
 #  HEAT_ID=$(tacker vnf-show hello-world-tacker | awk "/instance_id/ { print \$4 }")
 #  SERVER_ID=$(openstack stack resource list $HEAT_ID | awk "/VDU1 / { print \$4 }")
   SERVER_ID=$(openstack server list | awk "/VDU1/ { print \$2 }")
@@ -184,7 +180,7 @@ start() {
     if [[ $(neutron port-show $id|grep $SERVER_ID) ]]; then neutron port-update ${id} --port-security-enabled=True; fi
   done
 
-  echo "$0: directly assign security group (unsupported in Mitaka Tacker)"
+  echo "$0: $(date) directly assign security group (unsupported in Mitaka Tacker)"
   if [[ $(openstack security group list | awk "/ vHello / { print \$2 }") ]]; then openstack security group vHello; fi
   openstack security group create vHello
   openstack security group rule create --ingress --protocol TCP --dst-port 22:22 vHello
@@ -192,60 +188,65 @@ start() {
   openstack server add security group $SERVER_ID vHello
   openstack server add security group $SERVER_ID default
 
-  echo "$0: associate floating IP"
+  echo "$0: $(date) associate floating IP"
   get_floating_net
   FIP=$(openstack floating ip create $FLOATING_NETWORK_NAME | awk "/floating_ip_address/ { print \$4 }")
   nova floating-ip-associate $SERVER_ID $FIP
 
-  echo "$0: get vHello server address"
+  echo "$0: $(date) get vHello server address"
   SERVER_IP=$(openstack server show $SERVER_ID | awk "/ addresses / { print \$6 }")
   SERVER_URL="http://$SERVER_IP"
 
-  echo "$0: wait 30 seconds for vHello server to startup"
+  echo "$0: $(date) wait 30 seconds for vHello server to startup"
   sleep 30
 
-  echo "$0: verify vHello server is running"
+  echo "$0: $(date) verify vHello server is running"
   apt-get install -y curl
   if [[ $(curl $SERVER_URL | grep -c "Hello World") == 0 ]]; then fail; fi
 
-  echo "$0: verify contents of config drive are included in web page"
+  echo "$0: $(date) verify contents of config drive are included in web page"
   id=$(curl $SERVER_URL | awk "/uuid/ { print \$2 }")
   if [[ -z "$id" ]]; then fail; fi
 
 }
 
 stop() {
-  echo "$0: setup OpenStack CLI environment"
+  echo "$0: $(date) setup OpenStack CLI environment"
   source /tmp/tacker/admin-openrc.sh
 
   if [[ "$1" == "tacker-api" ]]; then
-    echo "$0: Tacker API use is not yet implemented"
+    echo "$0: $(date) Tacker API use is not yet implemented"
   else
-    echo "$0: uninstall vHello blueprint via CLI"
+    echo "$0: $(date) uninstall vHello blueprint via CLI"
     vid=($(tacker vnf-list|grep hello-world-tacker|awk '{print $2}')); for id in ${vid[@]}; do tacker vnf-delete ${id};  done
     vid=($(tacker vnfd-list|grep hello-world-tacker|awk '{print $2}')); for id in ${vid[@]}; do tacker vnfd-delete ${id};  done
     fip=($(neutron floatingip-list|grep -v "+"|grep -v id|awk '{print $2}')); for id in ${fip[@]}; do neutron floatingip-delete ${id};  done
     sg=($(openstack security group list|grep vHello|awk '{print $2}'))
     for id in ${sg[@]}; do try 5 5 "openstack security group delete ${id}";  done
+    iid=($(openstack image list|grep VNFImage|awk '{print $2}')); for id in ${iid[@]}; do openstack image delete ${id};  done
+    kid=($(openstack keypair list|grep vHello|awk '{print $2}')); for id in ${kid[@]}; do openstack keypair delete ${id};  done
   fi
 }
 
 forward_to_container () {
-  echo "$0: pass $2 command to vHello.sh in tacker container"
+  echo "$0: $(date) pass $2 command to vHello.sh in tacker container"
   CONTAINER=$(sudo docker ps -a | awk "/tacker/ { print \$1 }")
   sudo docker exec $CONTAINER /bin/bash /tmp/tacker/vHello_Tacker.sh $1 $2 $2
   if [ $? -eq 1 ]; then fail; fi
 }
 
+test_start=`date +%s`
 dist=`grep DISTRIB_ID /etc/*-release | awk -F '=' '{print $2}'`
 case "$2" in
   setup)
     setup $1
+    if [ $? -eq 1 ]; then fail; fi
     pass
     ;;
   run)
     setup $1
     forward_to_container $1 start
+    if [ $? -eq 1 ]; then fail; fi
     pass
     ;;
   start|stop)
@@ -254,11 +255,13 @@ case "$2" in
       # running inside the tacker container, ready to go
       $2 $1
     fi
+    if [ $? -eq 1 ]; then fail; fi
     pass
     ;;
   clean)
-    echo "$0: Uninstall Tacker and test environment"
+    echo "$0: $(date) Uninstall Tacker and test environment"
     bash utils/tacker-setup.sh $1 clean
+    if [ $? -eq 1 ]; then fail; fi
     pass
     ;;
   *)