diff options
author | Mofassir Arif <mofassir@gmail.com> | 2015-10-22 12:39:37 -0700 |
---|---|---|
committer | Mofassir Arif <mofassir@gmail.com> | 2015-11-05 06:17:02 -0800 |
commit | 95bf8a8c96b2be94512e042f3f3c82edcbebf84d (patch) | |
tree | 7c7d1acd4dd596e84699a18d04e6ba2790e6fec2 | |
parent | ed6de63572d92bb5af8be22ced0a749400f4d3d4 (diff) |
Python Framework for QTIP
Dhrystone Whetstone and DPI benchmarks have been implemented
CLI arguments have been implemented
test case are sorted based on category such as compute,network and storage
glance and heat client have been used to generate the stack.
automatic upload of QTIP image and delete function for existing stack before
creating new stack has been implemented
system information collecton and result generation has been implemented
JIRA: QTIP-17
Signed-off-by: Mofassir Arif <mofassir_arif@dell.com>
Change-Id: I4b7b134017723c30c771cc14d2edce33fcb8ba00
52 files changed, 1742 insertions, 311 deletions
diff --git a/.create_zones.py.swp b/.create_zones.py.swp Binary files differnew file mode 100644 index 00000000..0467b7b2 --- /dev/null +++ b/.create_zones.py.swp diff --git a/FUELCRED b/FUELCRED new file mode 100644 index 00000000..d2cebb0c --- /dev/null +++ b/FUELCRED @@ -0,0 +1,32 @@ + +#!/bin/bash + +# To use an Openstack cloud you need to authenticate against keystone, which +# returns a **Token** and **Service Catalog**. The catalog contains the +# endpoint for all services the user/tenant has access to - including nova, +# glance, keystone, swift. +# +# *NOTE*: Using the 2.0 *auth api* does not mean that compute api is 2.0. We +# will use the 1.1 *compute api* +export OS_AUTH_URL=http://172.18.0.69:5000/v2.0 + +# With the addition of Keystone we have standardized on the term **tenant** +# as the entity that owns the resources. +export OS_TENANT_ID=48ea2b0008dd459b8713fe6977836318 +export OS_TENANT_NAME="admin" + +# In addition to the owning entity (tenant), openstack stores the entity +# performing the action as the **user**. +export OS_USERNAME="admin" + +# With Keystone you pass the keystone password. +echo "Please enter your OpenStack Password: " +read -sr OS_PASSWORD_INPUT +export OS_PASSWORD=$OS_PASSWORD_INPUT + +# If your configuration has multiple regions, we set that information here. +# OS_REGION_NAME is optional and only valid in certain environments. +export OS_REGION_NAME="RegionOne" +# Don't leave a blank variable, unset it if it was empty +if [ -z "$OS_REGION_NAME" ]; then unset OS_REGION_NAME; fi + diff --git a/QTIP.sh b/QTIP.sh deleted file mode 100755 index 2a313420..00000000 --- a/QTIP.sh +++ /dev/null @@ -1,137 +0,0 @@ -#! /bin/bash - -WDIR=$PWD - - - -function Call_Test { - - case "$1" in - dhrystone) - mkdir $PWD/results/dhrystone - ansible-playbook -s $PWD/benchmarks/playbooks/dhrystone.yaml --extra-vars "Dest_dir=$PWD/results" -v - - ;; - - ramspeed) - mkdir $PWD/results/ramspeed - ansible-playbook -s $PWD/benchmarks/playbooks/ramspeedbench.yaml --extra-vars "Dest_dir=$PWD/results" -v - ;; - - cachebench) - mkdir $PWD/results/cachebench - ansible-playbook -s $PWD/benchmarks/playbooks/cachebench.yaml --extra-vars "Dest_dir=$PWD/results" -v - ;; - - whetstone) - mkdir $PWD/results/whetstone - ansible-playbook -s $PWD/benchmarks/playbooks/whetstone.yaml --extra-vars "Dest_dir=$PWD/results" -v - ;; - - *) - echo "Please pass a correct argument to test. use -h for more details" - ;; - esac - -} - -function Fetch_VM_Image { - - mkdir $PWD/Temp_Image - - file="$PWD/Temp_Image/Cent7Modified.qcow2" - if [ -f "$file" ] - then - echo "Image already downdloaded" - else - echo "Fetching QTIP_VM Image" - cd $PWD/Temp_Image && wget https://www.dropbox.com/s/3uswrydrvhxw3qm/Cent7Modified.qcow2 - echo "Uploading image to glance" - glance image-create --name "QTIP_CentOS" --is-public true --disk-format qcow2 \ - --container-format bare \ - --file $PWD/Temp_Image/Cent7Modified.qcow2 - - - fi - cd $WDIR -} -mkdir $PWD/results -case "$1" in - -h) - printf "To run test.sh, 2 arguments are required\n" - printf "First argument: The Test case to run\nOptions:\nFirst: For a comparison between a baremetal machine and a VM\nSecond: For a comparison between two baremetal machines\n\nSecond argument: The Benchmark to run\nOptions:\ndhrystone\nwhetstone\nramspeed\ncachebench\n" - ;; - First) - - Fetch_VM_Image - - ipvar=$(cat $PWD/Test-cases/Bare_vs_VM/Config.yaml | grep "Machine_1_IP" | awk '{print$2;}') - - - passwordvar=$(cat $PWD/Test-cases/Bare_vs_VM/Config.yaml | grep "Machine_1_Password" | awk '{print$2;}') - - expect $PWD/data/ssh_exch.exp $ipvar $passwordvar - heat stack-create exp2 -f $PWD/Test-cases/Bare_vs_VM/SampleHeat.yaml - sleep 3 - VAR1=$( heat stack-show exp2 | grep "stack_status_reason" | awk '{print $6;}') - echo $VAR1 - while [ "$VAR1" != completed ] - do - echo VM is coming up - VAR1=$( heat stack-show exp2 | grep "stack_status_reason" | awk '{print $6;}') - #echo $VAR1 - done - echo VM Created - - if [ "$VAR1" == "completed" ]; then - VAR=$( heat stack-show exp2 | grep "output_value" | awk '{print $4;}'| cut -d '"' -f2) - - echo IP of VM is: - echo $VAR - - sed -i '/demo1/a '$VAR'' /etc/ansible/hosts - sed -i '/demo1/a '$ipvar'' /etc/ansible/hosts - - - - echo Waiting for ping - while ! ping -c1 $VAR &> /dev/null; do - echo Waiting for ping - done - - echo Ping detected - expect $PWD/data/ssh_exch.exp $VAR - Call_Test $2 - - echo cleaning environment - sleep 10 - $PWD/clean.sh - - - fi - - ;; - Second) - - ipvar=$(cat $PWD/Test-cases/Bare_vs_Bare/Config.yaml | grep "Machine_1_IP" | awk '{print$2;}') - echo $ipvar - passwordvar=$(cat $PWD/Test-cases/Bare_vs_Bare/Config.yaml | grep "Machine_1_IP_Password" | awk '{print$2;}') - echo $passwordvar - expect $PWD/data/ssh_exch.exp $ipvar $passwordvar - sed -i '/demo1/a '$ipvar'' /etc/ansible/hosts - ipvar=$(cat $PWD/Test-cases/Bare_vs_Bare/Config.yaml | grep "Machine_2_IP" | awk '{print$2;}') - passwordvar=$(cat $PWD/Test-cases/Bare_vs_Bare/Config.yaml | grep "Machine_2_IP_Password" | awk '{print$2;}') - expect $PWD/data/ssh_exch.exp $ipvar $passwordvar - sed -i '/demo1/a '$ipvar'' /etc/ansible/hosts - Call_Test $2 - echo cleaning environment - sleep 10 - $PWD/clean.sh - ;; - - *) - echo Incorrect Arguments passed to the script. Run script with -h for more help - ;; -esac - - @@ -15,27 +15,30 @@ The efforts in QTIP are mostly focused on identifying -QTIP currently consists of a bash script (QTIP.sh). +QTIP Framework can now be called: (qtip.py). -The script can run 4 comuting benchmarks: +The Framework can run 5 computing benchmarks: 1. Dhrystone 2. Whetstone 3. RamBandwidth -4. Cachebandwidth +4. SSL +5. nDPI These benchmarks can be run in 2 test cases: 1. VM vs Baremetal -2. Baremetal vs Baremeatl +2. Baremetal vs Baremetal Instructions to run the script: -1. Download the OpenStack adminrc file for the deployment on which you want to create the VM for benchmarking -2. run ./QTIP {TEST CASE} {BENCHMARK} -3. ./QTIP.sh -h for more help +1. Download and source the OpenStack adminrc file for the deployment on which you want to create the VM for benchmarking +2. run python qtip.py -s {SUITE} -b {BENCHMARK} +3. run python qtip.py -h for more help +4. list of benchmarks can be found in the qtip/test-cases directory +5. SUITE referes to compute, network or storage Requirments: 1. Ansible 1.9.2 2. Python 2.7 - +3. PyYAML Configuring Test Cases: @@ -44,6 +47,23 @@ For each Test case, a Config.yaml file contains the details for the machines upo Edit the IP and the Password fields within the files for the machines on which the benchmark is to run. A robust framework that would allow to include more tests would be included within the future +Jump Host requirements: +The following packages should be installed on the server from which you intend to run QTIP. +1: Heat Client +2: Glance Client +3: Nova Client +4: Neutron Client +5: Wget +6: pyYaml + +Networking +1: The Host Machines/compute nodes to be benchmarked should have public/access network +2: The Host Machines/compute nodes should allow Password Login + + +QTIP support for Foreman + +{TBA} diff --git a/Test-cases/Bare_vs_Bare/Config.yaml b/Test-cases/Bare_vs_Bare/Config.yaml deleted file mode 100644 index 6612cbdc..00000000 --- a/Test-cases/Bare_vs_Bare/Config.yaml +++ /dev/null @@ -1,4 +0,0 @@ -Machine_1_IP: 172.18.0.17 -Machine_1_Password: Op3nStack -Machine_2_IP: 172.18.0.16 -Machine_2_Password: Op3nStack diff --git a/Test-cases/Bare_vs_VM/Config.yaml b/Test-cases/Bare_vs_VM/Config.yaml deleted file mode 100644 index e410a632..00000000 --- a/Test-cases/Bare_vs_VM/Config.yaml +++ /dev/null @@ -1,2 +0,0 @@ -Machine_1_IP: 172.18.0.17 -Machine_1_Password: Op3nStack diff --git a/benchmarks/foo b/benchmarks/foo new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/benchmarks/foo diff --git a/benchmarks/playbooks/cachebench.yaml b/benchmarks/playbooks/cachebench.yaml deleted file mode 100644 index d0e04140..00000000 --- a/benchmarks/playbooks/cachebench.yaml +++ /dev/null @@ -1,38 +0,0 @@ - - - hosts: demo1 - - tasks: - - name: clean - shell: rm -rf /usr/bin/phoronix-test-suite - shell: rm -rf /usr/share/doc/phoronix-test-suite/ - shell: rm -rf /usr/share/phoronix-test-suite - shell: rm -rf /root/photmp/ - - name: cleaning results - file: path=/root/results state=absent - - name: make direc - file: path=/root/photmp/ state=directory - - name: Fetch Phornonix - shell: cd /root/photmp/ && wget https://www.dropbox.com/s/5kks513ozxy7vvs/phoronix-suite.tar.gz - - name: unarchive Phoronix - shell: cd /root/photmp/ && tar -zxvf phoronix-suite.tar.gz - - name: Install Phornonix Dependencies - shell: yum install php php-xml php-client php-process -y - - name: Install Phornonix - shell: cd /root/photmp/phoronix-test-suite-master/&&./install-sh - - name: batchSetup - shell: phoronix-test-suite batch-setup - - name: install - shell: phoronix-test-suite batch-install cachebench - - name: run - shell: phoronix-test-suite batch-run cachebench - - name: making directory - file: path=/root/results state=directory - - name: copying result to temp directory - shell: cp -r /var/lib/phoronix-test-suite/test-results/* /root/results/ - - name: registering files - shell: (cd /root/results/; find . -maxdepth 1 -type f) | cut -d'/' -f2 - register: files_to_copy - - name: copy results - fetch: src=/root/results/{{item}} dest={{Dest_dir}}/cachebench - with_items: files_to_copy.stdout_lines - diff --git a/benchmarks/playbooks/dhrystone.yaml b/benchmarks/playbooks/dhrystone.yaml deleted file mode 100644 index d0e5f20d..00000000 --- a/benchmarks/playbooks/dhrystone.yaml +++ /dev/null @@ -1,31 +0,0 @@ - - - hosts: demo1 - - tasks: - - name: cleaning - file: path=/root/tempT state=absent - - name: cleaning results - file: path=/root/results state=absent - - name: Installing UnixBench dependencies - shell: yum install git gcc patch perl-Time-HiRes -y - - name: Clone unixbench - shell: git clone https://github.com/kdlucas/byte-unixbench.git /root/tempT - - name: make - shell: make --directory /root/tempT/UnixBench/ - - name: downloading_patch - shell: cd /root/tempT/UnixBench/ && wget https://www.dropbox.com/s/11z85gfu0trkhus/fix-limitation.patch - - name: applying_patch - shell: cd /root/tempT/UnixBench/ && patch Run fix-limitation.patch - - name: Run dhrystone - shell: cd /root/tempT/UnixBench/&&./Run -v dhrystone - - name: making directory - file: path=/root/results state=directory - - name: copying result to temp directory - shell: cp -r /root/tempT/UnixBench/results/* /root/results/ - - name: registering files - shell: (cd /root/results/; find . -maxdepth 1 -type f) | cut -d'/' -f2 - register: files_to_copy - - name: copy results - fetch: src=/root/results/{{item}} dest={{Dest_dir}}/dhrystone - with_items: files_to_copy.stdout_lines - diff --git a/benchmarks/playbooks/ramspeedbench.yaml b/benchmarks/playbooks/ramspeedbench.yaml deleted file mode 100644 index 37ea91a8..00000000 --- a/benchmarks/playbooks/ramspeedbench.yaml +++ /dev/null @@ -1,38 +0,0 @@ - - - hosts: demo1 - - tasks: - - name: clean - shell: rm -rf /usr/bin/phoronix-test-suite - shell: rm -rf /usr/share/doc/phoronix-test-suite/ - shell: rm -rf /usr/share/phoronix-test-suite - shell: rm -rf /root/photmp/ - - name: clean previous results - file: path=/root/results path=absent - - name: make direc - file: path=/root/photmp/ state=directory - - name: Fetch Phornonix - shell: cd /root/photmp/ && wget https://www.dropbox.com/s/5kks513ozxy7vvs/phoronix-suite.tar.gz - - name: unarchive Phoronix - shell: cd /root/photmp/ && tar -zxvf phoronix-suite.tar.gz - - name: Phornonix Dependencies - shell: yum install php php-xml php-client php-process -y - - name: Install Phornonix - shell: cd /root/photmp/phoronix-test-suite-master/&&./install-sh - - name: batchSetup - shell: phoronix-test-suite batch-setup - - name: install - shell: phoronix-test-suite batch-install ramspeed - - name: run - shell: phoronix-test-suite batch-run ramspeed - - name: making directory - file: path=/root/results state=directory - - name: copying result to temp directory - shell: cp -r /var/lib/phoronix-test-suite/test-results/* /root/results/ - - name: registering files - shell: (cd /root/results/; find . -maxdepth 1 -type f) | cut -d'/' -f2 - register: files_to_copy - - name: copy results - fetch: src=/root/results/{{item}} dest={{Dest_dir}}/dhrystone - with_items: files_to_copy.stdout_lines - diff --git a/benchmarks/playbooks/whetstone.yaml b/benchmarks/playbooks/whetstone.yaml deleted file mode 100644 index 497797ff..00000000 --- a/benchmarks/playbooks/whetstone.yaml +++ /dev/null @@ -1,31 +0,0 @@ - - - hosts: demo1 - - tasks: - - name: cleaning - shell: rm -rf /root/tempT - - name: cleaning previous results - file: path=/root/results state=absent - - name: Installing UnixBench dependencies - shell: yum install git gcc patch perl-Time-HiRes -y - - name: Clone unixbench - shell: git clone https://github.com/kdlucas/byte-unixbench.git /root/tempT - - name: make - shell: make --directory /root/tempT/UnixBench/ - - name: downloading_patch - shell: cd /root/tempT/UnixBench/ && wget https://www.dropbox.com/s/11z85gfu0trkhus/fix-limitation.patch - - name: applying_patch - shell: cd /root/tempT/UnixBench/ && patch Run fix-limitation.patch - - name: Run whetstone - shell: cd /root/tempT/UnixBench/&&./Run -v whetstone - - name: making directory - file: path=/root/results state=directory - - name: copying result to temp directory - shell: cp -r /root/tempT/UnixBench/results/* /root/results/ - - name: registering files - shell: (cd /root/results/; find . -maxdepth 1 -type f) | cut -d'/' -f2 - register: files_to_copy - - name: copy results - fetch: src=/root/results/{{item}} dest={{Dest_dir}}/whetstone - with_items: files_to_copy.stdout_lines - @@ -1,6 +1,6 @@ #! /bin/bash echo cleaning Ip -sed -i -e '/demo1/{n;N;d;}' /etc/ansible/hosts +#sed -i -e '/demo1/{ n;N;N;N;N;d; }' /etc/ansible/hosts neutron floatingip-delete $(neutron floatingip-list| grep "17" | awk '{print $2;}') -heat stack-delete exp2 +#heat stack-delete exp2 diff --git a/data/ssh_exch.exp b/data/ssh_exch.exp index 1b462c42..4ced0c6a 100755 --- a/data/ssh_exch.exp +++ b/data/ssh_exch.exp @@ -2,11 +2,8 @@ set timeout 4 set ip [lindex $argv 0] set pswd [lindex $argv 1] -spawn ssh-copy-id -i /root/.ssh/id_rsa $ip +spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $ip expect "Are you sure you want to continue connecting" {send "yes\r"} -expect "password" { send "$pswd\r"} +expect "password:" { send "$pswd\r"} interact - - - diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml new file mode 100644 index 00000000..3bfca80d --- /dev/null +++ b/docs/sample_config.yaml @@ -0,0 +1,47 @@ + ## This is a sample Config.yaml file + +#Scenario would define the test case scenario. +#The benchmark key contains the benchmark to run such as dhrystone,whetstone,dpi,ssh etc. +# Host and server list he differnet machines on which the benchmark would run. +# On machines lised within hosts, the benchmarks would run in parallel. +# On machines listed within server, the benchmarks would run when the benechmarks running on hosts have been completed. +# This has been used to control the folow of the testcase. For example, running the testcases on a vm vs hostmachin, we would like to run the test case serially. It should run first on the host machine and then on the vm. This testcase flow control could be used for other testcases to be developed such as those for networking. +Scenario: + benchmark: dhrystone + host: machine_1, machine_2, virtualmachine_1 + server: + + +#Context would define the enviironment on wichic to run: +#Host Machine keys would contain Host_Machines/ Baremetal machines to run the benchmarks on +#e.g in Host Machine , machine_1 and machine_2 are the bare metal machines. For each baremetal machine its IP(which should be reachable from the location on which you run QTIP), passwords and its role(host or server) +Context: + Host_Machines: + machine_1: + ip: 172.18.0.16 + pw: Op3nStack + role: host + Virtual_Machines: + virtualmachine_1: + availability_zone: nova + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: server + +# A geeral description of the testcase. Could be used later for reports. +Test_Description: + Test_category: "Compute" + Benchmark: "dhrystone" + Overview: > + ''' This test will run the dhrystone benchmark in serial on machine_1 and machine_2.\n + if you wish to add a virtual machine add the following information under the Virtual_Machine tag + + virtualmachine_1: + availability_zone: + public_network: + OS_image: + flavor: + role: ''' + + diff --git a/fetch_os_creds.sh b/fetch_os_creds.sh new file mode 100755 index 00000000..cefc8576 --- /dev/null +++ b/fetch_os_creds.sh @@ -0,0 +1,171 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2015 Ericsson AB and others. +# jose.lausuch@ericsson.com +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + +usage() { + echo "usage: $0 -d <destination> -i <installer_type> -a <installer_ip>" >&2 +} + +info () { + logger -s -t "fetch_os_creds.info" "$*" +} + + +error () { + logger -s -t "fetch_os_creds.error" "$*" + exit 1 +} + + +verify_connectivity() { + local ip=$1 + info "Verifying connectivity to $ip..." + for i in $(seq 0 10); do + if ping -c 1 -W 1 $ip > /dev/null; then + info "$ip is reachable!" + return 0 + fi + sleep 1 + done + error "Can not talk to $ip." +} + + + +#Get options +while getopts ":d:i:a:h:" optchar; do + case "${optchar}" in + d) dest_path=${OPTARG} ;; + i) installer_type=${OPTARG} ;; + a) installer_ip=${OPTARG} ;; + *) echo "Non-option argument: '-${OPTARG}'" >&2 + usage + exit 2 + ;; + esac +done + +# set vars from env if not provided by user as options +dest_path=${dest_path:-$HOME/opnfv-openrc.sh} +installer_type=${installer_type:-$INSTALLER_TYPE} +installer_ip=${installer_ip:-$INSTALLER_IP} + +if [ -z $dest_path ] || [ -z $installer_type ] || [ -z $installer_ip ]; then + usage + exit 2 +fi + +# Checking if destination path is valid +if [ -d $dest_path ]; then + error "Please provide the full destination path for the credentials file including the filename" +else + # Check if we can create the file (e.g. path is correct) + touch $dest_path || error "Cannot create the file specified. Check that the path is correct and run the script again." +fi + + +ssh_options="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + +# Start fetching the files +if [ "$installer_type" == "fuel" ]; then + #ip_fuel="10.20.0.2" + verify_connectivity $installer_ip + + # Check if controller is alive (online='True') + controller_ip=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ + 'fuel node | grep controller | grep True | awk "{print \$10}" | tail -1') &> /dev/null + + if [ -z $controller_ip ]; then + error "The controller $controller_ip is not up. Please check that the POD is correctly deployed." + fi + + info "Fetching rc file from controller $controller_ip..." + sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ + "scp $ssh_options ${controller_ip}:/root/openrc ." &> /dev/null + sshpass -p r00tme scp 2>/dev/null $ssh_options root@${installer_ip}:~/openrc $dest_path &> /dev/null + + #This file contains the mgmt keystone API, we need the public one for our rc file + admin_ip=$(cat $dest_path | grep "OS_AUTH_URL" | sed 's/^.*\=//' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g" | sed s'/\/$//') + public_ip=$(sshpass -p r00tme ssh $ssh_options root@${installer_ip} \ + "ssh ${controller_ip} 'source openrc; keystone endpoint-list'" \ + | grep $admin_ip | sed 's/ /\n/g' | grep ^http | head -1) &> /dev/null + #| grep http | head -1 | cut -d '|' -f 4 | sed 's/v1\/.*/v1\//' | sed 's/ //g') &> /dev/null + #NOTE: this is super ugly sed 's/v1\/.*/v1\//'OS_AUTH_URL + # but sometimes the output of endpoint-list is like this: http://172.30.9.70:8004/v1/%(tenant_id)s + + +elif [ "$installer_type" == "foreman" ]; then + #ip_foreman="172.30.10.73" + controller="oscontroller1.opnfv.com" + verify_connectivity $installer_ip + + # Check if controller is alive (here is more difficult to get the ip from a command like "fuel node") + sshpass -p vagrant ssh $ssh_options root@${installer_ip} \ + "sshpass -p Op3nStack ssh $ssh_options root@${controller} 'ls'" &> /dev/null + if [ $? -ne 0 ]; then + error "The controller ${controller} is not up. Please check that the POD is correctly deployed." + fi + + info "Fetching openrc from a Foreman Controller '${controller}'..." + sshpass -p vagrant ssh $ssh_options root@${installer_ip} \ + "sshpass -p Op3nStack scp $ssh_options root@${controller}:~/keystonerc_admin ." &> /dev/null + sshpass -p vagrant scp $ssh_options root@${installer_ip}:~/keystonerc_admin $dest_path &> /dev/null + + #This file contains the mgmt keystone API, we need the public one for our rc file + admin_ip=$(cat $dest_path | grep "OS_AUTH_URL" | sed 's/^.*\=//' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g" | sed s'/\/$//') + public_ip=$(sshpass -p vagrant ssh $ssh_options root@${installer_ip} \ + "sshpass -p Op3nStack ssh $ssh_options root@${controller} \ + 'source keystonerc_admin;keystone endpoint-list'" \ + | grep $admin_ip | sed 's/ /\n/g' | grep ^http | head -1) &> /dev/null + +elif [ "$installer_type" == "compass" ]; then + #ip_compass="10.1.0.12" + verify_connectivity $installer_ip + + # controller_ip='10.1.0.222' + controller_ip=$(sshpass -p'root' ssh 2>/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@10.1.0.12 \ + 'mysql -ucompass -pcompass -Dcompass -e"select package_config from cluster;"' \ + | awk -F"," '{for(i=1;i<NF;i++)if($i~/\"ha_proxy\": {\"vip\":/)print $i}' \ + | grep -oP "\d+.\d+.\d+.\d+") + if [ -z $controller_ip ]; then + error "The controller $controller_ip is not up. Please check that the POD is correctly deployed." + fi + + info "Fetching rc file from controller $controller_ip..." + sshpass -p root ssh 2>/dev/null $ssh_options root@${installer_ip} \ + "scp $ssh_options ${controller_ip}:/opt/admin-openrc.sh ." &> /dev/null + sshpass -p root scp 2>/dev/null $ssh_options root@${installer_ip}:~/admin-openrc.sh $dest_path &> /dev/null + echo 'export OS_REGION_NAME=regionOne' >> $dest_path + + info "This file contains the mgmt keystone API, we need the public one for our rc file" + admin_ip=$(cat $dest_path | grep "OS_AUTH_URL" | sed 's/^.*\=//' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g" | sed s'/\/$//') + info "admin_ip: $admin_ip" + public_ip=$(sshpass -p root ssh $ssh_options root@${installer_ip} \ + "ssh ${controller_ip} 'source /opt/admin-openrc.sh; keystone endpoint-list'" \ + | grep $admin_ip | sed 's/ /\n/g' | grep ^http | head -1) + info "public_ip: $public_ip" + +else + error "Installer $installer is not supported by this script" +fi + + + +if [ "$public_ip" == "" ]; then + error "Cannot retrieve the public IP from keystone" +fi + +info "Keystone public IP is $public_ip" +sed -i "/OS_AUTH_URL/c\export OS_AUTH_URL=\'$public_ip'" $dest_path + +echo "-------- Credentials: --------" +cat $dest_path + +exit 0 diff --git a/foremancred b/foremancred new file mode 100644 index 00000000..4f238938 --- /dev/null +++ b/foremancred @@ -0,0 +1,5 @@ +export OS_USERNAME=admin +export OS_TENANT_NAME=admin +export OS_PASSWORD=octopus +export OS_AUTH_URL='http://172.18.0.27:5000/v2.0' +export PS1='[\u@\h \W(openstack_admin)]\$ ' diff --git a/func/__init__.py b/func/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/func/__init__.py diff --git a/func/__init__.pyc b/func/__init__.pyc Binary files differnew file mode 100644 index 00000000..d217b489 --- /dev/null +++ b/func/__init__.pyc diff --git a/func/cli.py b/func/cli.py new file mode 100644 index 00000000..235040b5 --- /dev/null +++ b/func/cli.py @@ -0,0 +1,60 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import sys +import os +from func.env_setup import Env_setup +from func.driver import Driver +from func.spawn_vm import SpawnVM +import argparse + + +class cli(): + + def __init__(self): + + parser = argparse.ArgumentParser() + + parser.add_argument('-s ', '--suite', help='compute network storage ') + parser.add_argument('-b', '--benchmark', + help='''COMPUTE: + dhrystone_serial.yaml \n + dhrystone_paralle.yaml \n + whetstone_serial.yaml \n + whetstone_parllel.yaml \n + dpi_serial.yaml \n + dpi_paralle.yaml \n + ssl_serial.yaml \n + ssl_parallel.yaml ''') + args = parser.parse_args() + if not (args.suite or args.benchmark): + parser.error('Not enough arguments, -h, --help ') + sys.exit(0) + if (args.suite and args.benchmark): + obj = Env_setup() + if os.path.isfile( + './test_cases/' + + args.suite + + '/' + + args.benchmark): + + [benchmark, roles, vm_info] = obj.parse( + './test_cases/' + args.suite + '/' + args.benchmark) + + if len(vm_info) != 0: + vmObj = SpawnVM(vm_info) + + obj.callpingtest() + obj.callsshtest() + obj.updateAnsible() + dvr = Driver() + dvr.drive_bench(benchmark, obj.roles_dict.items()) + else: + print (args.benchmark, ' is not a Template in the Directory - \ + Enter a Valid file name. or use qtip.py -h for list') diff --git a/func/cli.pyc b/func/cli.pyc Binary files differnew file mode 100644 index 00000000..3a09e907 --- /dev/null +++ b/func/cli.pyc diff --git a/func/create_zones.py b/func/create_zones.py new file mode 100644 index 00000000..92ce43fe --- /dev/null +++ b/func/create_zones.py @@ -0,0 +1,117 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + + +from keystoneclient.auth.identity import v2 +from keystoneclient import session +from novaclient import client +import os +from collections import defaultdict + + +class create_zones: + + def __init__(self): + print 'Creating Zones' + self._keystone_client = None + self._nova_client = None + + def _get_keystone_client(self): + '''returns a keystone client instance''' + + if self._keystone_client is None: + ''' + self._keystone_client = keystoneclient.v2_0.client.Client( + auth_url=os.environ.get('OS_AUTH_URL'), + username=os.environ.get('OS_USERNAME'), + password=os.environ.get('OS_PASSWORD'), + tenant_name=os.environ.get('OS_TENANT_NAME')) + ''' + auth = v2.Password(auth_url=os.environ.get('OS_AUTH_URL'), + username=os.environ.get('OS_USERNAME'), + password=os.environ.get('OS_PASSWORD'), + tenant_name=os.environ.get('OS_TENANT_NAME')) + + sess = session.Session(auth=auth) + + return sess + + def _get_nova_client(self): + if self._nova_client is None: + keystone = self._get_keystone_client() + self._nova_client = client.Client('2', session=keystone) + return self._nova_client + + def check_aggregate(self, nova, agg_name): + list1 = nova.aggregates.list() + + agg_name_exist = False + for x in list1: + + if x.name == agg_name: + agg_name_exist = True + return agg_name_exist + + def get_aggregate_id(self, nova, agg_name): + list1 = nova.aggregates.list() + agg_id = 0 + agg_name_exist = False + for x in list1: + if x.name == agg_name: + agg_id = x.id + return agg_id + + def check_host_added_to_aggregate(self, nova, agg_id, hostname): + host_added = False + list1 = nova.aggregates.get_details(agg_id) + + nme = str(list1.hosts) + if(hostname in nme): + host_added = True + return host_added + + def del_agg(self, nova, id, host): + + nova.aggregates.remove_host(id, host) + nova.aggregates.delete(id) + + def create_agg(self, D): + nova = self._get_nova_client() + hyper_list = nova.hypervisors.list() + hostnA = [] + zone_machine = defaultdict(list) + + x = 0 + for x in range(len(hyper_list)): + + hostnA.append(hyper_list[x].service['host']) + hostnA[x] = str(hostnA[x]) + + hostnA.sort() + for k in D: + + zone_machine[k].append(' ') + + for x in range(len(zone_machine)): + if not self.check_aggregate(nova, hostnA[x]): + agg_idA = nova.aggregates.create(hostnA[x], D[x]) + nova.aggregates.add_host(aggregate=agg_idA, host=hostnA[x]) + + else: + + id1 = self.get_aggregate_id(nova, hostnA[x]) + self.del_agg(nova, id1, hostnA[x]) + agg_idA = nova.aggregates.create(hostnA[x], D[x]) + id1 = self.get_aggregate_id(nova, hostnA[x]) + + if not self.check_host_added_to_aggregate( + nova, id1, hostnA[x]): + + nova.aggregates.add_host(aggregate=id1, host=hostnA[x]) diff --git a/func/create_zones.pyc b/func/create_zones.pyc Binary files differnew file mode 100644 index 00000000..4faf6abd --- /dev/null +++ b/func/create_zones.pyc diff --git a/func/driver.py b/func/driver.py new file mode 100644 index 00000000..45ec3fa2 --- /dev/null +++ b/func/driver.py @@ -0,0 +1,29 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + + +import os + + +class Driver: + + def __init__(self): + print "Class driver initialized\n" + + def drive_bench(self, benchmark, roles): + result_dir = '$PWD/results' + benchmark_name = benchmark + '.yaml' + print roles + for k, v in roles: + print k + run_play = 'ansible-playbook -s $PWD/benchmarks/playbooks/{0} --extra-vars "Dest_dir={1} role={2}" -vvv'.format( + benchmark_name, result_dir, k) + + status = os.system(run_play) diff --git a/func/driver.pyc b/func/driver.pyc Binary files differnew file mode 100644 index 00000000..0ad3c584 --- /dev/null +++ b/func/driver.pyc diff --git a/func/env_setup.py b/func/env_setup.py new file mode 100644 index 00000000..919df176 --- /dev/null +++ b/func/env_setup.py @@ -0,0 +1,160 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + + + + +import os +import sys +from collections import defaultdict +import yaml +import time +import paramiko + +class Env_setup(): + roles_ip_list = [] # ROLE and its corresponding IP address list + ip_pw_list = [] # IP and password, this will be used to ssh + roles_dict = defaultdict(list) + ip_pw_dict = defaultdict(list) + vm_parameters = defaultdict(list) + benchmark = '' + + def __init__(self): + print '\nParsing class initiated\n' +# obj1 = SpawnVM() + + def writeTofile(self, role): + fname2 = open('/etc/ansible/hosts', 'w') + print role.items() + for k in role: + fname2.write('[' + k + ']\n') + num = len(role[k]) + for x in range(num): + fname2.write(role[k][x] + '\n') + fname2.close + + def sshtest(self, lister): + print 'list: ',lister + for k, v in lister: + ipvar = k + pwvar = v + print '\nBeginning SSH Test!\n' + if v != '': + print ('\nSSH->>>>> %s\n' % k) + time.sleep(2) + + ssh_c = 'ssh-keyscan {0} >> ~/.ssh/known_hosts'.format(k) + + os.system(ssh_c) + ssh_cmd = 'expect ./data/ssh_exch.exp {0} {1}'.format( + ipvar, pwvar) + res = os.system(ssh_cmd) + ''' + for infinity in range(10000): + try : + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(hostname = k , username = 'root', password = v) + stdin, stdout, stderr = ssh.exec_command('ls') + print('SSH successful') + break + except: + print 'Retrying SSH' + time.sleep(1) + ''' + if v == '': + print ('SSH->>>>>', k) + ssh_c = 'ssh-keyscan {0} >> ~/.ssh/known_hosts'.format(k) + + time.sleep(3) + os.system(ssh_c) + + for infinity in range(10000): + try : + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(hostname = k ) + stdin, stdout, stderr = ssh.exec_command('ls') + break + except: + print 'Retrying SSH' + + def pingtest(self, lister): + pingFlag = 0 + + for k, v in lister.iteritems(): + time.sleep(10) + for val in v: + ipvar = val + ping_cmd = 'ping -D -c1 {0}'.format(ipvar) + while os.system(ping_cmd) != 0: + print '\nWaiting for machine\n' + time.sleep(10) + pingFlag = 0 + print ('\n\n %s is UP \n\n ' % ipvar) + + def GetHostMachineinfo(self, Hosttag): + num = len(Hosttag) + offset = len(self.roles_ip_list) + + for x in range(num): + hostlabel = 'machine_' + str(x + 1) + self.roles_ip_list.insert( + offset, (Hosttag[hostlabel]['role'], Hosttag[hostlabel]['ip'])) + self.ip_pw_list.insert( + offset, (Hosttag[hostlabel]['ip'], Hosttag[hostlabel]['pw'])) + + def GetVirtualMachineinfo(self, Virtualtag): + num = len(Virtualtag) + + for x in range(num): + hostlabel = 'virtualmachine_' + str(x + 1) + for k, v in Virtualtag[hostlabel].iteritems(): + self.vm_parameters[k].append(v) + + def parse(self, configfilepath): + try: + fname = open(configfilepath, 'r+') + doc = yaml.load(fname) +# valid_file = validate_yaml.Validate_Yaml(doc) + fname.close() + for scenario in doc: + self.benchmark = doc['Scenario']['benchmark'] + if doc['Context']['Virtual_Machines']: + self.GetVirtualMachineinfo(doc['Context']['Virtual_Machines']) + if doc['Context']['Host_Machines']: + self.GetHostMachineinfo(doc['Context']['Host_Machines']) + + # num = len(doc['Context']['Vir_Machines']) + # for x in range(num): + # lab = 'host_machine'+ str(x+1) + # self.roles_ip_list.insert(x,(doc[lab]['role'],doc[lab]['ip'])) + # self.ip_pw_list.insert(x,(doc[lab]['ip'],doc[lab]['pw'])) + for k, v in self.roles_ip_list: + self.roles_dict[k].append(v) + for k, v in self.ip_pw_list: + self.ip_pw_dict[k].append(v) + return ( + self.benchmark, + self.roles_dict.items(), + self.vm_parameters) + except KeyboardInterrupt: + fname.close() + print 'ConfigFile Closed: exiting!' + sys.exit(0) + + def updateAnsible(self): + self.writeTofile(self.roles_dict) + + def callpingtest(self): + self.pingtest(self.roles_dict) + + def callsshtest(self): + self.sshtest(self.ip_pw_list) diff --git a/func/env_setup.pyc b/func/env_setup.pyc Binary files differnew file mode 100644 index 00000000..0f9c1433 --- /dev/null +++ b/func/env_setup.pyc diff --git a/func/fetchimg.py b/func/fetchimg.py new file mode 100644 index 00000000..106dc7e8 --- /dev/null +++ b/func/fetchimg.py @@ -0,0 +1,30 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + + +import os +import time + + +class FetchImg: + + def __init__(self): + print 'Fetching Image!' + print 'Fetching QTIP_VM Image' + + def download(self): + time.sleep(2) + os.system( + 'cd ./Temp_Img && wget http://artifacts.opnfv.org/qtip/QTIP_CentOS.qcow2') + + filepath = './Temp_Img/QTIP_CentOS.qcow2' + while not os.path.isfile(filepath): + time.sleep(10) + print 'Download Completed!' diff --git a/func/fetchimg.pyc b/func/fetchimg.pyc Binary files differnew file mode 100644 index 00000000..0c0b228d --- /dev/null +++ b/func/fetchimg.pyc diff --git a/func/spawn_vm.py b/func/spawn_vm.py new file mode 100644 index 00000000..a9dada2e --- /dev/null +++ b/func/spawn_vm.py @@ -0,0 +1,263 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + + +import os +import sys +from collections import defaultdict +from func.env_setup import Env_setup +from func.fetchimg import FetchImg +import yaml +import heatclient.client +import keystoneclient +import glanceclient +from novaclient import client +import time +import json + + +from func.create_zones import create_zones + + +class SpawnVM(Env_setup): + vm_role_ip_dict = defaultdict(list) + + def __init__(self, vm_info): + print 'SpawnVM Class initiated' + + # def setupVM(self,vm_info): + vm_role_ip_dict = vm_info.copy() + print 'Generating Heat Template\n' + self._keystone_client = None + self._heat_client = None + self._glance_client = None + self._nova_client = None + nova =self. _get_nova_client() + azoneobj = create_zones() + azoneobj.create_agg(vm_info['availability_zone']) + + self.Heat_template1 = self.HeatTemplate_vm(vm_info) + self.create_stack(vm_role_ip_dict, self.Heat_template1) + + def HeatTemplate_vm(self, vm_params): + try: + with open('./heat/SampleHeat.yaml', 'r+') as H_temp: + Heat_Dic = yaml.load(H_temp) + except yaml.YAMLError as exc: + if hasattr(exc, 'problem_mark'): + mark = exc.problem_mark + print 'Error in qtip/heat/SampleHeat.yaml at: (%s,%s)' % (mark.line + 1, mark.column + 1) + print 'EXITING PROGRAM. Correct File and restart' + sys.exit(0) + fopen = open('/root/.ssh/id_rsa.pub', 'r') + fopenstr = fopen.read() + fopenstr = fopenstr.rstrip() + scriptcmd = '#!/bin/bash \n echo {0} >> foo.txt \n echo {1} >> /root/.ssh/authorized_keys'.format( + fopenstr, fopenstr) + + Heat_Dic['heat_template_version'] = '2014-10-16' + Heat_Dic['resources']['KeyPairSavePrivate'] = { + 'type': 'OS::Nova::KeyPair', + 'properties': { + 'save_private_key': 'true', + 'name': 'my_key' + } + } + for x in range(1, len(vm_params['availability_zone']) + 1): + avail_zone = vm_params['availability_zone'][x - 1] + img = vm_params['OS_image'][x - 1] + flavor = vm_params['flavor'][x - 1] + + Heat_Dic['parameters']['availability_zone_' +str(x)] = { + 'description': 'Availability Zone of the instance', + 'default': avail_zone, + 'type': 'string' + + } + + Heat_Dic['resources'][ + 'public_port_' + + str(x)] = { + 'type': 'OS::Neutron::Port', + 'properties': { + 'network': {'get_resource': 'private_network'}, + 'security_groups': [{ 'get_resource': 'demo1_security_Group'}], + 'fixed_ips': [ + { + 'subnet_id': {'get_resource': 'private_subnet'}}]}} + + Heat_Dic['resources']['floating_ip_' + str(x)] = { + 'type': 'OS::Neutron::FloatingIP', + 'properties': { + 'floating_network': {'get_param': 'public_network'}}} + + Heat_Dic['resources']['floating_ip_assoc_' + str(x)] = { + 'type': 'OS::Neutron::FloatingIPAssociation', + 'properties': { + 'floatingip_id': {'get_resource': 'floating_ip_' + str(x)}, + 'port_id': {'get_resource': 'public_port_' + str(x)}}} + + Heat_Dic['resources']['my_instance_' + str(x)] = { + 'type': 'OS::Nova::Server', + 'properties': { + 'image': img, + 'networks': + [{'port': {'get_resource': 'public_port_' + str(x)}}], + 'flavor': flavor, + 'availability_zone': avail_zone, + 'name': 'QTIP_Instance_' + str(x), + 'key_name': {'get_resource': 'KeyPairSavePrivate'}, + 'user_data_format': 'RAW', + 'user_data': scriptcmd}} + + Heat_Dic['resources']['demo1_security_Group'] = { + 'type': 'OS::Neutron::SecurityGroup', + 'properties': { + 'name': 'demo1_security_Group', + 'rules': [{ + 'protocol': 'tcp', + 'port_range_min': 22, + 'port_range_max': 22}, + {'protocol': 'icmp'}]}} + + Heat_Dic['outputs']['instance_ip_' +str(x)] = { + 'description': 'IP address of the instance', + 'value': {'get_attr': ['floating_ip_' + str(x), 'floating_ip_address']}} + + Heat_Dic['outputs']['availability_instance_' + str(x)] = { + 'description': 'Availability Zone of the Instance', + 'value': { 'get_param': 'availability_zone_'+str(x)}} + + + Heat_Dic['outputs']['KeyPair_PublicKey'] = { + 'description': 'Private Key', + 'value': {'get_attr': ['KeyPairSavePrivate', 'private_key']} + } + del Heat_Dic['outputs']['description'] + return Heat_Dic + + def _get_keystone_client(self): + '''returns a keystone client instance''' + + if self._keystone_client is None: + self._keystone_client = keystoneclient.v2_0.client.Client( + auth_url=os.environ.get('OS_AUTH_URL'), + username=os.environ.get('OS_USERNAME'), + password=os.environ.get('OS_PASSWORD'), + tenant_name=os.environ.get('OS_TENANT_NAME')) + return self._keystone_client + + def _get_nova_client(self): + if self._nova_client is None: + keystone = self._get_keystone_client() + self._nova_client = client.Client('2', token=keystone.auth_token) + return self._nova_client + + def _get_heat_client(self): + '''returns a heat client instance''' + if self._heat_client is None: + keystone = self._get_keystone_client() + heat_endpoint = keystone.service_catalog.url_for( + service_type='orchestration') + self._heat_client = heatclient.client.Client( + '1', endpoint=heat_endpoint, token=keystone.auth_token) + return self._heat_client + + def _get_glance_client(self): + if self._glance_client is None: + keystone = self._get_keystone_client() + glance_endpoint = keystone.service_catalog.url_for( + service_type='image') + self._glance_client = glanceclient.Client( + '2', glance_endpoint, token=keystone.auth_token) + return self._glance_client + + def create_stack(self, vm_role_ip_dict, Heat_template): + + stackname = 'QTIP' + heat = self._get_heat_client() + glance = self._get_glance_client() + + available_images = [] + for image_list in glance.images.list(): + + available_images.append(image_list.name) + + if 'QTIP_CentOS' in available_images: + print 'Image Present' + + elif 'QTIP_CentOS' not in available_images: + fetchImage = FetchImg() + fetchImage.download() + print 'Uploading Image to Glance. Please wait' + qtip_image = glance.images.create( + name='QTIP_CentOS', + visibility='public', + disk_format='qcow2', + container_format='bare') + qtip_image = glance.images.upload( + qtip_image.id, open('./Temp_Img/QTIP_CentOS.qcow2')) + json_temp = json.dumps(Heat_template) +# cluster_body = { +# "stack_name": stackname, +# "template": Heat_template +# } + for checks in range(3): + for prev_stacks in heat.stacks.list(): + + if prev_stacks.stack_name == 'QTIP': + print 'QTIP Stacks exists.\nDeleting Existing Stack' + heat.stacks.delete('QTIP') + time.sleep(10) + + print '\nStack Creating Started\n' + + try: + heat.stacks.create(stack_name=stackname, template=Heat_template) + + except: + print 'Create Failed :( ' + + cluster_detail = heat.stacks.get(stackname) + while(cluster_detail.status != 'COMPLETE'): + if cluster_detail.status == 'IN_PROGRESS': + print 'Stack Creation in Progress' + cluster_detail = heat.stacks.get(stackname) + time.sleep(10) + print 'Stack Created' + print 'Getting Public IP(s)' + zone = [] + s=0 + for vm in range(len(vm_role_ip_dict['OS_image'])): + + for I in cluster_detail.outputs: + availabilityKey = 'availability_instance_'+str(vm+1) + + if I['output_key'] == availabilityKey: + zone.insert(s,str(I['output_value'])) + s=s+1 + + for i in cluster_detail.outputs: + instanceKey = "instance_ip_" + str(vm + 1) + + if i['output_key'] == instanceKey: + + Env_setup.roles_dict[vm_role_ip_dict['role'][ + vm]].append(str(i['output_value'])) + + Env_setup.ip_pw_list.append( + (str(i['output_value']),'')) + if i['output_key'] == 'KeyPair_PublicKey': + sshkey = str(i['output_value']) + + with open('/root/.ssh/my_key.pem', 'w') as fopen: + fopen.write(sshkey) + fopen.close() + print Env_setup.ip_pw_list diff --git a/func/spawn_vm.pyc b/func/spawn_vm.pyc Binary files differnew file mode 100644 index 00000000..8e6ce8f1 --- /dev/null +++ b/func/spawn_vm.pyc diff --git a/func/validate_yaml.py b/func/validate_yaml.py new file mode 100644 index 00000000..c0df4d87 --- /dev/null +++ b/func/validate_yaml.py @@ -0,0 +1,32 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + + +import yaml +import os + + +class Validate_Yaml(): + + def __init__(self, doc): + + print 'Validating YAML CONFIG FILE' + + if not doc['Scenario']: + print '\nScenario Field missing\n' + if not doc['Scenario']['benchmark']: + print '\nBenchmark field missing' + if not doc['Scenario']['pointless']: + print '\nBabyeating anumal' + if not doc['Context']: + print '\nEntire Context is missing' + if not doc['Context']['Host_Machine']: + print '\nNo Host Machine' + if not doc['Context']['Host_Machine']['machine_1'] diff --git a/func/validate_yaml.pyc b/func/validate_yaml.pyc Binary files differnew file mode 100644 index 00000000..9a560316 --- /dev/null +++ b/func/validate_yaml.pyc diff --git a/heat/HeatTemplate.yaml b/heat/HeatTemplate.yaml new file mode 100644 index 00000000..4b0aa7aa --- /dev/null +++ b/heat/HeatTemplate.yaml @@ -0,0 +1,120 @@ +heat_template_version: 2014-10-16 +outputs: + description: this + instance_ip_1: + description: IP address of the instance + value: + get_attr: + - floating_ip_1 + - floating_ip_address + instance_ip_2: + description: IP address of the instance + value: + get_attr: + - floating_ip_2 + - floating_ip_address +parameters: + availability_zone: + default: compute1 + description: The AvailZone. + type: string + private_net_name: + default: private_network + type: string + public_network: + default: provider_network + description: Public + label: Publi_N_ID + type: string +resources: + demo1_security_Group: + properties: + name: demo1_security_Group + rules: + - port_range_max: 22 + port_range_min: 22 + protocol: tcp + - protocol: icmp + type: OS::Neutron::SecurityGroup + floating_ip_1: + properties: + floating_network: + get_param: public_network + type: OS::Neutron::FloatingIP + floating_ip_2: + properties: + floating_network: + get_param: public_network + type: OS::Neutron::FloatingIP + floating_ip_assoc_1: + properties: + floatingip_id: + get_resource: floating_ip_1 + port_id: + get_resource: public_port_1 + type: OS::Neutron::FloatingIPAssociation + floating_ip_assoc_2: + properties: + floatingip_id: + get_resource: floating_ip_2 + port_id: + get_resource: public_port_2 + type: OS::Neutron::FloatingIPAssociation + my_instance_1: + properties: + availability_zone: nova + flavor: m1.small + image: Cirros + networks: + - port: + get_resource: public_port_1 + type: OS::Nova::Server + my_instance_2: + properties: + availability_zone: nova + flavor: m1.small + image: Cirros + networks: + - port: + get_resource: public_port_2 + type: OS::Nova::Server + private_network: + type: OS::Neutron::Net + private_subnet: + properties: + cidr: 10.10.17.0/24 + dns_nameservers: [ "8.8.8.8" ] + network_id: { get_resource: private_network } + type: OS::Neutron::Subnet + public_port_1: + properties: + fixed_ips: + - subnet_id: + get_resource: private_subnet + network: + get_resource: private_network + security_groups: + - get_resource: demo1_security_Group + type: OS::Neutron::Port + public_port_2: + properties: + fixed_ips: + - subnet_id: + get_resource: private_subnet + network: + get_resource: private_network + security_groups: + - get_resource: demo1_security_Group + type: OS::Neutron::Port + router_1: + properties: + external_gateway_info: + network: { get_param: public_network } + type: OS::Neutron::Router + router_interface: + properties: + router_id: { get_resource: router_1 } + subnet: { get_resource: private_subnet } + type: OS::Neutron::RouterInterface +outputs: + description: 'none' diff --git a/heat/SampleHeat.yaml b/heat/SampleHeat.yaml new file mode 100644 index 00000000..28c37b97 --- /dev/null +++ b/heat/SampleHeat.yaml @@ -0,0 +1,42 @@ +heat_template_version: 2014-10-16 +parameters: + + public_network: + type: string + label: Publi_N_ID + description: Public + default: 'provider_network' + + private_net_name: + type: string + default: 'private_network' + + availability_zone: + type: string + description: The AvailZone. + default: compute1 + +resources: + + private_network: + type: OS::Neutron::Net + private_subnet: + type: OS::Neutron::Subnet + properties: + network_id: { get_resource: private_network } + cidr: '10.10.17.0/24' + dns_nameservers: [ '8.8.8.8' ] + gateway_ip: '10.10.17.1' + allocation_pools: [ {"start":'10.10.17.2', "end": '10.10.17.200'} ] + router_1: + type: OS::Neutron::Router + properties: + external_gateway_info: + network: { get_param: public_network } + router_interface: + type: OS::Neutron::RouterInterface + properties: + router_id: { get_resource: router_1 } + subnet: { get_resource: private_subnet } +outputs: + description: 'none' diff --git a/heat/TEST.yaml b/heat/TEST.yaml new file mode 100644 index 00000000..17ba9cc8 --- /dev/null +++ b/heat/TEST.yaml @@ -0,0 +1,133 @@ +heat_template_version: 2013-05-23 + +description: > + HOT template to create a new neutron network plus a router to the public + network, and for deploying two servers into the new network. The template also + assigns floating IP addresses to each server so they are routable from the + public network. +parameters: + key_name: + type: string + description: Name of keypair to assign to servers + default: 'key' + image: + type: string + description: Name of image to use for servers + default: 'QTIP_CentOS' + flavor: + type: string + description: Flavor to use for servers + default: 'm1.large' + public_net: + type: string + description: > + ID or name of public network for which floating IP addresses will be allocated + default: 'provider_network' + private_net_name: + type: string + description: Name of private network to be created + default: 'private_network' + private_net_cidr: + type: string + description: Private network address (CIDR notation) + default: '10.10.17.0/24' + private_net_gateway: + type: string + description: Private network gateway address + default: '10.10.17.1' + private_net_pool_start: + type: string + description: Start of private network IP address allocation pool + default: '10.10.17.2' + private_net_pool_end: + type: string + description: End of private network IP address allocation pool + default: '10.10.17.200' + +resources: + private_net: + type: OS::Neutron::Net + properties: + name: { get_param: private_net_name } + + private_subnet: + type: OS::Neutron::Subnet + properties: + network_id: { get_resource: private_net } + cidr: { get_param: private_net_cidr } + gateway_ip: { get_param: private_net_gateway } + allocation_pools: + - start: { get_param: private_net_pool_start } + end: { get_param: private_net_pool_end } + + router: + type: OS::Neutron::Router + properties: + external_gateway_info: + network: { get_param: public_net } + + router_interface: + type: OS::Neutron::RouterInterface + properties: + router_id: { get_resource: router } + subnet_id: { get_resource: private_subnet } + + server1: + type: OS::Nova::Server + properties: + name: Server1 + image: { get_param: image } + flavor: { get_param: flavor } + + networks: + - port: { get_resource: server1_port } + + server1_port: + type: OS::Neutron::Port + properties: + network_id: { get_resource: private_net } + fixed_ips: + - subnet_id: { get_resource: private_subnet } + + server1_floating_ip: + type: OS::Neutron::FloatingIP + properties: + floating_network: { get_param: public_net } + port_id: { get_resource: server1_port } + + server2: + type: OS::Nova::Server + properties: + name: Server2 + image: { get_param: image } + flavor: { get_param: flavor } + + networks: + - port: { get_resource: server2_port } + + server2_port: + type: OS::Neutron::Port + properties: + network_id: { get_resource: private_net } + fixed_ips: + - subnet_id: { get_resource: private_subnet } + + server2_floating_ip: + type: OS::Neutron::FloatingIP + properties: + floating_network: { get_param: public_net } + port_id: { get_resource: server2_port } + +outputs: + server1_private_ip: + description: IP address of server1 in private network + value: { get_attr: [ server1, first_address ] } + server1_public_ip: + description: Floating IP address of server1 in public network + value: { get_attr: [ server1_floating_ip, floating_ip_address ] } + server2_private_ip: + description: IP address of server2 in private network + value: { get_attr: [ server2, first_address ] } + server2_public_ip: + description: Floating IP address of server2 in public network + value: { get_attr: [ server2_floating_ip, floating_ip_address ] } diff --git a/heat/WorkingTemplate.yaml b/heat/WorkingTemplate.yaml new file mode 100644 index 00000000..299962d4 --- /dev/null +++ b/heat/WorkingTemplate.yaml @@ -0,0 +1,70 @@ +heat_template_version: 2014-10-16 +outputs: + + instance_ip_1: + description: IP address of the instance + value: {get_attr: [floating_ip_1, floating_ip_address]} +parameters: + availability_zone: + default: compute1 + description: The AvailZone. + type: string + private_net_name: + default: private_network + type: string + public_network: + default: provider_network + description: Public + label: Publi_N_ID + type: string +resources: + demo1_security_Group: + properties: + name: demo1_security_Group + rules: + - port_range_max: 22 + port_range_min: 22 + protocol: tcp + - protocol: icmp + type: OS::Neutron::SecurityGroup + floating_ip_1: + properties: + floating_network: {get_param: public_network} + type: OS::Neutron::FloatingIP + floating_ip_assoc_1: + properties: + floatingip_id: {get_resource: floating_ip_1} + port_id: {get_resource: public_port_1} + type: OS::Neutron::FloatingIPAssociation + my_instance_1: + properties: + availability_zone: nova + flavor: m1.small + image: Cirros + networks: + - port: {get_resource: public_port_1} + type: OS::Nova::Server + private_network: + type: OS::Neutron::Net + private_subnet: + properties: + cidr: 10.10.17.0/24 + dns_nameservers: + - 8.8.8.8 + network_id: { get_resource: private_network } + type: OS::Neutron::Subnet + public_port_1: + properties: + network: {get_resource: private_network} + security_groups: [{get_resource: demo1_security_Group}] + type: OS::Neutron::Port + router_1: + properties: + external_gateway_info: + network: { get_param: public_network } + type: OS::Neutron::Router + router_interface: + properties: + router_id: { get_resource: router_1 } + subnet: { get_resource: private_subnet } + type: OS::Neutron::RouterInterface diff --git a/Test-cases/Bare_vs_VM/SampleHeat.yaml b/heat/heat.yaml index 6ee76ac0..2ed45429 100644 --- a/Test-cases/Bare_vs_VM/SampleHeat.yaml +++ b/heat/heat.yaml @@ -13,7 +13,17 @@ private_net_name: type: string default: "private_network" + + flavor: + type: string + label: Flavor + default: m1.large + image: + type: string + label: Image name + default: CentOS + availability_zone: type: string description: The Availability Zone to launch the instance. @@ -71,19 +81,7 @@ port_range_min: 22 port_range_max: 22 - protocol: icmp - - my_instance: - type: OS::Nova::Server - properties: - image: QTIP_CentOS7 - flavor: m1.large - availability_zone: { get_param: availability_zone } - networks: - - port: { get_resource: public_port } - - - - outputs: + outputs: instance_ip: description: IP address of the instance value: { get_attr: [floating_ip, floating_ip_address] } diff --git a/qtip.py b/qtip.py new file mode 100644 index 00000000..2c488e60 --- /dev/null +++ b/qtip.py @@ -0,0 +1,18 @@ +############################################################################## +# Copyright (c) 2015 Dell Inc and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + + +from func.cli import cli + +def main(): + Objcli = cli() + +if __name__ == "__main__": + main() diff --git a/test_cases/.TESTER.yaml.swo b/test_cases/.TESTER.yaml.swo Binary files differnew file mode 100644 index 00000000..b51f8c90 --- /dev/null +++ b/test_cases/.TESTER.yaml.swo diff --git a/test_cases/.TESTER.yaml.swp b/test_cases/.TESTER.yaml.swp Binary files differnew file mode 100644 index 00000000..aa95a5c1 --- /dev/null +++ b/test_cases/.TESTER.yaml.swp diff --git a/Test-cases/SampleHeat.yaml b/test_cases/SampleHeat.yaml index 0cf0c45f..95b9a137 100644 --- a/Test-cases/SampleHeat.yaml +++ b/test_cases/SampleHeat.yaml @@ -13,7 +13,17 @@ private_net_name: type: string default: "private_network" + + flavor: + type: string + label: Flavor + default: m1.large + image: + type: string + label: Image name + default: CentOS + availability_zone: type: string description: The Availability Zone to launch the instance. @@ -75,8 +85,8 @@ my_instance: type: OS::Nova::Server properties: - image: CentOS - flavor: m1.large + image: { get_param: image} + flavor: { get_param: flavor} availability_zone: { get_param: availability_zone } networks: - port: { get_resource: public_port } diff --git a/test_cases/TESTER.yaml b/test_cases/TESTER.yaml new file mode 100644 index 00000000..5a3f2d33 --- /dev/null +++ b/test_cases/TESTER.yaml @@ -0,0 +1,36 @@ +Scenario: + benchmark: dpi + host: virtualmachine_1 + server: virtualmachine_2 + pointless: +Context: + Host_Machines: + + + Virtual_Machines: + virtualmachine_1: + availability_zone: nova + OS_image: QTIP_CentOS + public_network: 'provider_network' + role: iiihost + flavor: m1.large + virtualmachine_2: + availability_zone: nova + OS_image: QTIP_CentOS + public_network: 'provider_network' + role: server + flavor: m1.large + +Test_Description: + Test_category: "Compute" + Benchmark: "dpi" + Overview: > + '''This test will run the DPI benchmark in serial on virutalmachine_1 and virtualmachine_2.\n + if you wish to add a host machine add the following information under the Host_Machine tag + + machine_1: + ip: + pw: + role: + ''' + diff --git a/test_cases/compute/.whetstone_serial.yaml.swp b/test_cases/compute/.whetstone_serial.yaml.swp Binary files differnew file mode 100644 index 00000000..bbfd3be2 --- /dev/null +++ b/test_cases/compute/.whetstone_serial.yaml.swp diff --git a/test_cases/compute/dhrystone_parallel.yaml b/test_cases/compute/dhrystone_parallel.yaml new file mode 100644 index 00000000..29de6d6f --- /dev/null +++ b/test_cases/compute/dhrystone_parallel.yaml @@ -0,0 +1,45 @@ +Scenario: + benchmark: dhrystone + host: machine_1, machine_2 + server: blakc + +Context: + Host_Machines: + + Virtual_Machines: + virtualmachine_1: + availability_zone: compute1 + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: host + virtualmachine_2: + availability_zone: compute2 + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: host + +Test_Description: + Test_category: "Compute" + Benchmark: "dhrystone" + Overview: > + '''This test will run the dhrystone benchmark in parallel on machine_1 and machine_2.\n + if you wish to add a virtual machine add the following information under the Virtual_Machine tag + machine_1: + ip: 172.18.0.16 + pw: Op3nStack + role: host + machine_2: + ip: 172.18.0.15 + pw: Op3nStack + role: host + + virtualmachine_1: + availability_zone: + public_network: + OS_image: + flavor: + role: + ''' + diff --git a/test_cases/compute/dhrystone_serial.yaml b/test_cases/compute/dhrystone_serial.yaml new file mode 100644 index 00000000..e15e8ecc --- /dev/null +++ b/test_cases/compute/dhrystone_serial.yaml @@ -0,0 +1,35 @@ + +Scenario: + benchmark: dhrystone + host: machine_1, machine_2, virtualmachine_1 + server: + +Context: + Host_Machines: + machine_1: + ip: 172.18.0.16 + pw: Op3nStack + role: host + Virtual_Machines: + virtualmachine_1: + availability_zone: nova + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: server + +Test_Description: + Test_category: "Compute" + Benchmark: "dhrystone" + Overview: > + ''' This test will run the dhrystone benchmark in serial on machine_1 and machine_2.\n + if you wish to add a virtual machine add the following information under the Virtual_Machine tag + + virtualmachine_1: + availability_zone: + public_network: + OS_image: + flavor: + role: ''' + + diff --git a/test_cases/compute/dpi_parallel.yaml b/test_cases/compute/dpi_parallel.yaml new file mode 100644 index 00000000..5edb3968 --- /dev/null +++ b/test_cases/compute/dpi_parallel.yaml @@ -0,0 +1,36 @@ +Scenario: + benchmark: dpi + 1Run : virtualmachine_1, virtualmachine_2 + 2Run: + +Context: + Host_Machines: + + + Virtual_Machines: + virtualmachine_1: + availability_zone: compute1 + OS_image: QTIP_CentOS + public_network: 'provider_network' + role: 1Run + flavor: m1.large + virtualmachine_2: + availability_zone: compute2 + OS_image: QTIP_CentOS + public_network: 'provider_network' + role: 1Run + flavor: m1.large + +Test_Description: + Test_category: "Compute" + Benchmark: "dpi" + Overview: > + '''This test will run the DPI benchmark in parallel on virutalmachine_1 and virtualmachine_2.\n + if you wish to add a host machine add the following information under the Host_Machine tag + + machine_1: + ip: + pw: + role: + ''' + diff --git a/test_cases/compute/dpi_serial.yaml b/test_cases/compute/dpi_serial.yaml new file mode 100644 index 00000000..539975f7 --- /dev/null +++ b/test_cases/compute/dpi_serial.yaml @@ -0,0 +1,38 @@ +Scenario: + benchmark: dpi + host: virtualmachine_1 + server: virtualmachine_2 + +Context: + Host_Machines: + machine_1: + ip: 172.18.0.76 + pw: r00tme + role: 1host + + Virtual_Machines: + virtualmachine_1: + availability_zone: compute1 + OS_image: QTIP_CentOS + public_network: 'provider_network' + role: 2host + flavor: m1.large + +Test_Description: + Test_category: "Compute" + Benchmark: "dpi" + Overview: > + '''This test will run the DPI benchmark in serial on virutalmachine_1 and virtualmachine_2.\n + if you wish to add a host machine add the following information under the Host_Machine tag + virtualmachine_2: + availability_zone: compute1 + OS_image: QTIP_CentOS + public_network: 'provider_network' + role: 1host + flavor: m1.large + machine_1: + ip: + pw: + role: + ''' + diff --git a/test_cases/compute/ssl_parallel.yaml b/test_cases/compute/ssl_parallel.yaml new file mode 100644 index 00000000..eb46d8d8 --- /dev/null +++ b/test_cases/compute/ssl_parallel.yaml @@ -0,0 +1,37 @@ +Scenario: + benchmark: ssl + host: machine_1, machine_2 + server: + +Context: + Host_Machines: + + Virtual_Machines: + virtualmachine_1: + availability_zone: compute1 + public_network: 'net04_ext' + OS_image: 'QTIP_CentOS' + flavor: 'm1.large' + role: host + virtualmachine_2: + availability_zone: compute2 + public_network: 'net04_ext' + OS_image: 'QTIP_CentOS' + flavor: 'm1.large' + role: host + + +Test_Description: + Test_category: "Compute" + Benchmark: "ssl" + Overview: > + '''This test will run the SSL benchmark in parallel on virtualmachine_1 and machine_1.\n + if you wish to add a virtual machine add the following information under the Virtual_Machine tag + + virtualmachine_1: + availability_zone: + public_network: + OS_image: + flavor: + role: + ''' diff --git a/test_cases/compute/ssl_serial.yaml b/test_cases/compute/ssl_serial.yaml new file mode 100644 index 00000000..756951bf --- /dev/null +++ b/test_cases/compute/ssl_serial.yaml @@ -0,0 +1,34 @@ +Scenario: + benchmark: ssl + 1Run: machine_1 + 2Run: virtualmachine_1 + +Context: + Host_Machines: + machine_1: + ip: 172.18.0.16 + pw: Op3nStack + role: 1Run + Virtual_Machines: + virtualmachine_1: + availability_zone: compute1 + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: 2Run + +Test_Description: + Test_category: "Compute" + Benchmark: "ssl" + Overview: > + '''This test will run the SSL benchmark in serial on virtualmachine_1 and machine_1. + The Test will run first on the Host_Machine and then on the Virtual Machine. + if you wish to add a virtual machine add the following information under the Virtual_Machine tag + + virtualmachine_1: + availability_zone: + public_network: + OS_image: + flavor: + role: + ''' diff --git a/test_cases/compute/whetstone_parallel.yaml b/test_cases/compute/whetstone_parallel.yaml new file mode 100644 index 00000000..48bc7230 --- /dev/null +++ b/test_cases/compute/whetstone_parallel.yaml @@ -0,0 +1,45 @@ +Scenario: + benchmark: whetstone + host: machine_1, virtualmachine_1 + server: + +Context: + Host_Machines: + machine_1: + ip: 172.18.0.76 + pw: r00tme + role: host + machine_2: + ip: 172.18.0.75 + pw: r00tme + role: host + + Virtual_Machines: + virtualmachine_1: + availability_zone: compute1 + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: host + +Test_Description: + Test_category: "Compute" + Benchmark: "dhrystone" + Overview: > + '''This test will run the whetstone benchmark in parallel on machine_1 and machine_2.\n + if you wish to add a virtual machine add the following information under the Virtual_Machine tag + virtualmachine_1: + availability_zone: nova + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: host + + virtualmachine_1: + availability_zone: + public_network: + OS_image: + flavor: + role: + ''' + diff --git a/test_cases/compute/whetstone_serial.yaml b/test_cases/compute/whetstone_serial.yaml new file mode 100644 index 00000000..25cefbf8 --- /dev/null +++ b/test_cases/compute/whetstone_serial.yaml @@ -0,0 +1,35 @@ + +Scenario: + benchmark: whetstone + host: machine_1, + server: virtualmachine_1 + +Context: + Host_Machines: + machine_1: + ip: 172.18.0.16 + pw: Op3nStack + role: host + Virtual_Machines: + virtualmachine_1: + availability_zone: nova + public_network: 'net04_ext' + OS_image: QTIP_CentOS + flavor: m1.large + role: server + +Test_Description: + Test_category: "Compute" + Benchmark: "whetstone" + Overview: > + ''' This test will run the whetstone benchmark in serial on machine_1 and machine_2.\n + if you wish to add a virtual machine add the following information under the Virtual_Machine tag + + virtualmachine_1: + availability_zone: + public_network: + OS_image: + flavor: + role: ''' + + diff --git a/test_cases/network/iperf.yaml b/test_cases/network/iperf.yaml new file mode 100644 index 00000000..56c49e28 --- /dev/null +++ b/test_cases/network/iperf.yaml @@ -0,0 +1,17 @@ +scenario: + benchmark: dpi + ExecOrder1: vm_1 + ExecOrder2: vm_2 + +Context: + VirtualMachines: + vm_1: + availability_zone: compute1 + OS_image: centos7 + public_network: "provider_network" + role: ExecOrder1 + vm_2: + availability_zone: compute1 + OS_image: centos7 + public_network: "provider_network" + role: ExecOrder2 |