Merge "Serialize db_sync and increase sql sleep timer"
[apex.git] / ci / deploy.sh
index 47ab59c..30a6af2 100755 (executable)
@@ -22,7 +22,6 @@ blue=$(tput setaf 4 || echo "")
 red=$(tput setaf 1 || echo "")
 green=$(tput setaf 2 || echo "")
 
-vm_index=4
 interactive="FALSE"
 ping_site="8.8.8.8"
 ntp_server="pool.ntp.org"
@@ -33,18 +32,40 @@ debug="FALSE"
 declare -i CNT
 declare UNDERCLOUD
 declare -A deploy_options_array
+declare -a performance_options
 declare -A NET_MAP
 
 SSH_OPTIONS=(-o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o LogLevel=error)
 DEPLOY_OPTIONS=""
-RESOURCES=/var/opt/opnfv/images
-CONFIG=/var/opt/opnfv
+CONFIG=${CONFIG:-'/var/opt/opnfv'}
+RESOURCES=${RESOURCES:-"$CONFIG/images"}
+LIB=${LIB:-"$CONFIG/lib"}
 OPNFV_NETWORK_TYPES="admin_network private_network public_network storage_network"
+
+VM_CPUS=4
+VM_RAM=8
+VM_COMPUTES=2
+
 # Netmap used to map networks to OVS bridge names
 NET_MAP['admin_network']="br-admin"
 NET_MAP['private_network']="br-private"
 NET_MAP['public_network']="br-public"
 NET_MAP['storage_network']="br-storage"
+ext_net_type="interface"
+ip_address_family=4
+
+# Libraries
+lib_files=(
+$LIB/common-functions.sh
+$LIB/utility-functions.sh
+$LIB/installer/onos/onos_gw_mac_update.sh
+)
+for lib_file in ${lib_files[@]}; do
+  if ! source $lib_file; then
+    echo -e "${red}ERROR: Failed to source $lib_file${reset}"
+    exit 1
+  fi
+done
 
 ##FUNCTIONS
 ##translates yaml into variables
@@ -98,163 +119,31 @@ parse_setting_value() {
   local mystr=$1
   echo $(echo $mystr | grep -Eo "\=.*$" | tr -d '=')
 }
+
 ##parses network settings yaml into globals
 parse_network_settings() {
-  local required_network_settings="cidr"
-  local common_optional_network_settings="usable_ip_range"
-  local admin_network_optional_settings="provisioner_ip dhcp_range introspection_range"
-  local public_network_optional_settings="floating_ip_range gateway provisioner_ip"
-  local nic_value cidr
-
-  eval $(parse_yaml ${NETSETS})
-  for network in ${OPNFV_NETWORK_TYPES}; do
-    if [[ $(eval echo \${${network}_enabled}) == 'true' ]]; then
-      enabled_network_list+="${network} "
-    elif [ "${network}" == 'admin_network' ]; then
-      echo -e "${red}ERROR: You must enable admin_network and configure it explicitly or use auto-detection${reset}"
-      exit 1
-    elif [[ "${network}" == 'public_network' && "$net_isolation_enabled" == "TRUE" ]]; then
-      echo -e "${red}ERROR: You must enable public_network and configure it explicitly or use auto-detection${reset}"
+  local output
+  if output=$(python3.4 -B $LIB/python/apex-python-utils.py parse-net-settings -s $NETSETS -i $net_isolation_enabled -e $CONFIG/network-environment.yaml); then
+      echo -e "${blue}${output}${reset}"
+      eval "$output"
+  else
+      echo -e "${red}ERROR: Failed to parse network settings file $NETSETS ${reset}"
       exit 1
-    else
-      echo -e "${blue}INFO: Network: ${network} is disabled, will collapse into admin_network"
-    fi
-  done
-
-  # check for enabled network values
-  for enabled_network in ${enabled_network_list}; do
-    # detect required settings first to continue
-    echo -e "${blue}INFO: Detecting Required settings for: ${enabled_network}${reset}"
-    for setting in ${required_network_settings}; do
-      eval "setting_value=\${${enabled_network}_${setting}}"
-      if [ -z "${setting_value}" ]; then
-        # if setting is missing we try to autodetect
-        eval "nic_value=\${${enabled_network}_bridged_interface}"
-        if [ -n "$nic_value" ]; then
-          setting_value=$(eval find_${setting} ${nic_value})
-          if [ -n "$setting_value" ]; then
-            eval "${enabled_network}_${setting}=${setting_value}"
-            echo -e "${blue}INFO: Auto-detection: ${enabled_network}_${setting}: ${setting_value}${reset}"
-          else
-            echo -e "${red}ERROR: Auto-detection failed: ${setting} not found using interface: ${nic_value}${reset}"
-            exit 1
-          fi
-        else
-          echo -e "${red}ERROR: Required setting: ${setting} not found, and bridge interface not provided\
-for Auto-detection${reset}"
-          exit 1
-        fi
-      else
-        echo -e "${blue}INFO: ${enabled_network}_${setting}: ${setting_value}${reset}"
-      fi
-    done
-    echo -e "${blue}INFO: Detecting Common settings for: ${enabled_network}${reset}"
-    # detect optional common settings
-    # these settings can be auto-generated if missing
-    for setting in ${common_optional_network_settings}; do
-      eval "setting_value=\${${enabled_network}_${setting}}"
-      if [ -z "${setting_value}" ]; then
-        if [ -n "$nic_value" ]; then
-          setting_value=$(eval find_${setting} ${nic_value})
-        else
-          setting_value=''
-          echo -e "${blue}INFO: Skipping Auto-detection, NIC not specified for ${enabled_network}.  Attempting Auto-generation...${reset}"
-        fi
-        if [ -n "$setting_value" ]; then
-          eval "${enabled_network}_${setting}=${setting_value}"
-          echo -e "${blue}INFO: Auto-detection: ${enabled_network}_${setting}: ${setting_value}${reset}"
-        else
-          # if Auto-detection fails we can auto-generate with CIDR
-          eval "cidr=\${${enabled_network}_cidr}"
-          if [ -n "$cidr" ]; then
-            echo -e "${blue}INFO: Auto-generating: ${setting}${reset}"
-            setting_value=$(eval generate_${setting} ${cidr})
-          else
-            setting_value=''
-            echo -e "${red}ERROR: Auto-generation failed: required parameter CIDR missing for network ${enabled_network}${reset}"
-          fi
-          if [ -n "$setting_value" ]; then
-            eval "${enabled_network}_${setting}=${setting_value}"
-            echo -e "${blue}INFO: Auto-generated: ${enabled_network}_${setting}: ${setting_value}${reset}"
-          else
-            echo -e "${red}ERROR: Auto-generation failed: ${setting} not found${reset}"
-            exit 1
-          fi
-        fi
-      else
-        echo -e "${blue}INFO: ${enabled_network}_${setting}: ${setting_value}${reset}"
-      fi
-    done
-    echo -e "${blue}INFO: Detecting Network Specific settings for: ${enabled_network}${reset}"
-    # detect network specific settings
-    for setting in $(eval echo \${${enabled_network}_optional_settings}); do
-      eval "setting_value=\${${enabled_network}_${setting}}"
-      if [ -z "${setting_value}" ]; then
-        if [ -n "$nic_value" ]; then
-          setting_value=$(eval find_${setting} ${nic_value})
-        else
-          setting_value=''
-          echo -e "${blue}INFO: Skipping Auto-detection, NIC not specified for ${enabled_network}.  Attempting Auto-generation...${reset}"
-        fi
-        if [ -n "$setting_value" ]; then
-          eval "${enabled_network}_${setting}=${setting_value}"
-          echo -e "${blue}INFO: Auto-detection: ${enabled_network}_${setting}: ${setting_value}${reset}"
-        else
-          eval "cidr=\${${enabled_network}_cidr}"
-          if [ -n "$cidr" ]; then
-            setting_value=$(eval generate_${setting} ${cidr})
-          else
-            setting_value=''
-            echo -e "${red}ERROR: Auto-generation failed: required parameter CIDR missing for network ${enabled_network}${reset}"
-          fi
-          if [ -n "$setting_value" ]; then
-            eval "${enabled_network}_${setting}=${setting_value}"
-            echo -e "${blue}INFO: Auto-generated: ${enabled_network}_${setting}: ${setting_value}${reset}"
-          else
-            echo -e "${red}ERROR: Auto-generation failed: ${setting} not found${reset}"
-            exit 1
-          fi
-        fi
-      else
-        echo -e "${blue}INFO: ${enabled_network}_${setting}: ${setting_value}${reset}"
-      fi
-    done
-  done
+  fi
 }
-##parses deploy settings yaml into globals and options array
-##params: none
-##usage:  parse_deploy_settings
+
+##parses deploy settings yaml into globals
 parse_deploy_settings() {
-  local global_prefix="deploy_global_params_"
-  local options_prefix="deploy_deploy_options_"
-  local myvar myvalue
-  local settings=$(parse_yaml $DEPLOY_SETTINGS_FILE "deploy_")
-
-  for this_setting in $settings; do
-    if contains_prefix $this_setting $global_prefix; then
-      myvar=$(parse_setting_var $this_setting $global_prefix)
-      if [ -z "$myvar" ]; then
-        echo -e "${red}ERROR: while parsing ${DEPLOY_SETTINGS_FILE} for setting: ${this_setting}${reset}"
-      fi
-      myvalue=$(parse_setting_value $this_setting)
-      # Do not override variables set by cmdline
-      if [ -z "$(eval echo \$$myvar)" ]; then
-        eval "$myvar=\$myvalue"
-        echo -e "${blue}Global parameter set: ${myvar}:${myvalue}${reset}"
-      else
-        echo -e "${blue}Global parameter already set: ${myvar}${reset}"
-      fi
-    elif contains_prefix $this_setting $options_prefix; then
-      myvar=$(parse_setting_var $this_setting $options_prefix)
-      if [ -z "$myvar" ]; then
-        echo -e "${red}ERROR: while parsing ${DEPLOY_SETTINGS_FILE} for setting: ${this_setting}${reset}"
-      fi
-      myvalue=$(parse_setting_value $this_setting)
-      deploy_options_array[$myvar]=$myvalue
-      echo -e "${blue}Deploy option set: ${myvar}:${myvalue}${reset}"
-    fi
-  done
+  local output
+  if output=$(python3.4 -B $LIB/python/apex-python-utils.py parse-deploy-settings -f $DEPLOY_SETTINGS_FILE); then
+      echo -e "${blue}${output}${reset}"
+      eval "$output"
+  else
+      echo -e "${red}ERROR: Failed to parse deploy settings file $DEPLOY_SETTINGS_FILE ${reset}"
+      exit 1
+  fi
 }
+
 ##parses baremetal yaml settings into compatible json
 ##writes the json to $CONFIG/instackenv_tmp.json
 ##params: none
@@ -285,7 +174,7 @@ parse_inventory_file() {
 
   node_total=$node_count
 
-  if [[ "$node_total" -lt 5 && ( ha_enabled == "TRUE" || "$ha_enabled" == "true" ) ]]; then
+  if [[ "$node_total" -lt 5 && "$ha_enabled" == "True" ]]; then
     echo -e "${red}ERROR: You must provide at least 5 nodes for HA baremetal deployment${reset}"
     exit 1
   elif [[ "$node_total" -lt 2 ]]; then
@@ -401,10 +290,11 @@ function configure_deps {
   virsh net-list --all | grep -E "default\s+active" > /dev/null || virsh net-start default
   virsh net-list --all | grep -E "default\s+active\s+yes" > /dev/null || virsh net-autostart --network default
 
-  for network in ${OPNFV_NETWORK_TYPES}; do
-    echo "${blue}INFO: Creating Virsh Network: $network & OVS Bridge: ${NET_MAP[$network]}${reset}"
-    ovs-vsctl list-br | grep ${NET_MAP[$network]} > /dev/null || ovs-vsctl add-br ${NET_MAP[$network]}
-    virsh net-list --all | grep $network > /dev/null || (cat > ${libvirt_dir}/apex-virsh-net.xml && virsh net-define ${libvirt_dir}/apex-virsh-net.xml) << EOF
+  if [[ -z "$virtual" || "$virtual" == "FALSE" ]]; then
+    for network in ${OPNFV_NETWORK_TYPES}; do
+      echo "${blue}INFO: Creating Virsh Network: $network & OVS Bridge: ${NET_MAP[$network]}${reset}"
+      ovs-vsctl list-br | grep "^${NET_MAP[$network]}$" > /dev/null || ovs-vsctl add-br ${NET_MAP[$network]}
+      virsh net-list --all | grep $network > /dev/null || (cat > ${libvirt_dir}/apex-virsh-net.xml && virsh net-define ${libvirt_dir}/apex-virsh-net.xml) << EOF
 <network>
   <name>$network</name>
   <forward mode='bridge'/>
@@ -412,21 +302,18 @@ function configure_deps {
   <virtualport type='openvswitch'/>
 </network>
 EOF
-    if ! (virsh net-list --all | grep $network > /dev/null); then
-        echo "${red}ERROR: unable to create network: ${network}${reset}"
-        exit 1;
-    fi
-    rm -f ${libvirt_dir}/apex-virsh-net.xml &> /dev/null;
-    virsh net-list | grep -E "$network\s+active" > /dev/null || virsh net-start $network
-    virsh net-list | grep -E "$network\s+active\s+yes" > /dev/null || virsh net-autostart --network $network
-  done
+      if ! (virsh net-list --all | grep $network > /dev/null); then
+          echo "${red}ERROR: unable to create network: ${network}${reset}"
+          exit 1;
+      fi
+      rm -f ${libvirt_dir}/apex-virsh-net.xml &> /dev/null;
+      virsh net-list | grep -E "$network\s+active" > /dev/null || virsh net-start $network
+      virsh net-list | grep -E "$network\s+active\s+yes" > /dev/null || virsh net-autostart --network $network
+    done
 
-  echo -e "${blue}INFO: Bridges set: ${reset}"
-  ovs-vsctl list-br
-  echo -e "${blue}INFO: virsh networks set: ${reset}"
-  virsh net-list
+    echo -e "${blue}INFO: Bridges set: ${reset}"
+    ovs-vsctl list-br
 
-  if [[ -z "$virtual" || "$virtual" == "FALSE" ]]; then
     # bridge interfaces to correct OVS instances for baremetal deployment
     for network in ${enabled_network_list}; do
       if [[ "$network" != "admin_network" && "$network" != "public_network" ]]; then
@@ -446,8 +333,31 @@ EOF
         exit 1
       fi
     done
+  else
+    for network in ${OPNFV_NETWORK_TYPES}; do
+      echo "${blue}INFO: Creating Virsh Network: $network${reset}"
+      virsh net-list --all | grep $network > /dev/null || (cat > ${libvirt_dir}/apex-virsh-net.xml && virsh net-define ${libvirt_dir}/apex-virsh-net.xml) << EOF
+<network ipv6='yes'>
+<name>$network</name>
+<bridge name='${NET_MAP[$network]}'/>
+</network>
+EOF
+      if ! (virsh net-list --all | grep $network > /dev/null); then
+          echo "${red}ERROR: unable to create network: ${network}${reset}"
+          exit 1;
+      fi
+      rm -f ${libvirt_dir}/apex-virsh-net.xml &> /dev/null;
+      virsh net-list | grep -E "$network\s+active" > /dev/null || virsh net-start $network
+      virsh net-list | grep -E "$network\s+active\s+yes" > /dev/null || virsh net-autostart --network $network
+    done
+
+    echo -e "${blue}INFO: Bridges set: ${reset}"
+    brctl show
   fi
 
+  echo -e "${blue}INFO: virsh networks set: ${reset}"
+  virsh net-list
+
   # ensure storage pool exists and is started
   virsh pool-list --all | grep default > /dev/null || virsh pool-define-as --name default dir --target /var/lib/libvirt/images
   virsh pool-list | grep -Eo "default\s+active" > /dev/null || (virsh pool-autostart default; virsh pool-start default)
@@ -481,7 +391,7 @@ function setup_undercloud_vm {
       if [[ $enabled_network_list =~ "public_network" ]]; then
         undercloud_nets+=" public_network"
       fi
-      define_vm undercloud hd 30 "$undercloud_nets"
+      define_vm undercloud hd 30 "$undercloud_nets" 4 12288
 
       ### this doesn't work for some reason I was getting hangup events so using cp instead
       #virsh vol-upload --pool default --vol undercloud.qcow2 --file $CONFIG/stack/undercloud.qcow2
@@ -580,8 +490,19 @@ function setup_undercloud_vm {
 }
 
 ##Create virtual nodes in virsh
-##params: none
+##params: vcpus, ramsize
 function setup_virtual_baremetal {
+  local vcpus ramsize
+  if [ -z "$1" ]; then
+    vcpus=4
+    ramsize=8192
+  elif [ -z "$2" ]; then
+    vcpus=$1
+    ramsize=8192
+  else
+    vcpus=$1
+    ramsize=$(($2*1024))
+  fi
   #start by generating the opening json for instackenv.json
   cat > $CONFIG/instackenv-virt.json << EOF
 {
@@ -589,9 +510,19 @@ function setup_virtual_baremetal {
 EOF
 
   # next create the virtual machines and add their definitions to the file
+  if [ "$ha_enabled" == "False" ]; then
+      # 1 controller + computes
+      # zero based so just pass compute count
+      vm_index=$VM_COMPUTES
+  else
+      # 3 controller + computes
+      # zero based so add 2 to compute count
+      vm_index=$((2+$VM_COMPUTES))
+  fi
+
   for i in $(seq 0 $vm_index); do
     if ! virsh list --all | grep baremetal${i} > /dev/null; then
-      define_vm baremetal${i} network 41 'admin_network'
+      define_vm baremetal${i} network 41 'admin_network' $vcpus $ramsize
       for n in private_network public_network storage_network; do
         if [[ $enabled_network_list =~ $n ]]; then
           echo -n "$n "
@@ -613,8 +544,8 @@ EOF
       "mac": [
         "$mac"
       ],
-      "cpu": "2",
-      "memory": "8192",
+      "cpu": "$vcpus",
+      "memory": "$ramsize",
       "disk": "41",
       "arch": "x86_64"
     },
@@ -643,12 +574,27 @@ EOF
 ##        bootdev - String: boot device for the VM
 ##        disksize - Number: size of the disk in GB
 ##        ovs_bridges: - List: list of ovs bridges
+##        vcpus - Number of VCPUs to use (defaults to 4)
+##        ramsize - Size of RAM for VM in MB (defaults to 8192)
 function define_vm () {
+  local vcpus ramsize
+
+  if [ -z "$5" ]; then
+    vcpus=4
+    ramsize=8388608
+  elif [ -z "$6" ]; then
+    vcpus=$5
+    ramsize=8388608
+  else
+    vcpus=$5
+    ramsize=$(($6*1024))
+  fi
+
   # Create the libvirt storage volume
   if virsh vol-list default | grep ${1}.qcow2 2>&1> /dev/null; then
     volume_path=$(virsh vol-path --pool default ${1}.qcow2 || echo "/var/lib/libvirt/images/${1}.qcow2")
     echo "Volume ${1} exists. Deleting Existing Volume $volume_path"
-    virsh vol-dumpxml ${1}.qcow2 --pool default
+    virsh vol-dumpxml ${1}.qcow2 --pool default > /dev/null || echo '' #ok for this to fail
     touch $volume_path
     virsh vol-delete ${1}.qcow2 --pool default
   fi
@@ -665,78 +611,47 @@ function define_vm () {
                                               --image "$volume_path" \
                                               --diskbus sata \
                                               --arch x86_64 \
-                                              --cpus 2 \
-                                              --memory 8388608 \
+                                              --cpus $vcpus \
+                                              --memory $ramsize \
                                               --libvirt-nic-driver virtio \
                                               --baremetal-interface $4
 }
 
-##Set network-environment settings
-##params: network-environment file to edit
-function configure_network_environment {
-  local tht_dir nic_ext
-  tht_dir=/usr/share/openstack-tripleo-heat-templates/network
-  nic_ext=''
-
-  sed -i '/ControlPlaneSubnetCidr/c\\  ControlPlaneSubnetCidr: "'${admin_network_cidr##*/}'"' $1
-  sed -i '/ControlPlaneDefaultRoute/c\\  ControlPlaneDefaultRoute: '${admin_network_provisioner_ip}'' $1
-  sed -i '/ExternalNetCidr/c\\  ExternalNetCidr: '${public_network_cidr}'' $1
-  sed -i "/ExternalAllocationPools/c\\  ExternalAllocationPools: [{'start': '${public_network_usable_ip_range%%,*}', 'end': '${public_network_usable_ip_range##*,}'}]" $1
-  sed -i '/ExternalInterfaceDefaultRoute/c\\  ExternalInterfaceDefaultRoute: '${public_network_gateway}'' $1
-  sed -i '/EC2MetadataIp/c\\  EC2MetadataIp: '${admin_network_provisioner_ip}'' $1
-
-  # check for private network
-  if [[ ! -z "$private_network_enabled" && "$private_network_enabled" == "true" ]]; then
-      sed -i 's#^.*Network::Tenant.*$#  OS::TripleO::Network::Tenant: '${tht_dir}'/tenant.yaml#' $1
-      sed -i 's#^.*Controller::Ports::TenantPort:.*$#  OS::TripleO::Controller::Ports::TenantPort: '${tht_dir}'/ports/tenant.yaml#' $1
-      sed -i 's#^.*Compute::Ports::TenantPort:.*$#  OS::TripleO::Compute::Ports::TenantPort: '${tht_dir}'/ports/tenant.yaml#' $1
-      sed -i "/TenantAllocationPools/c\\  TenantAllocationPools: [{'start': '${private_network_usable_ip_range%%,*}', 'end': '${private_network_usable_ip_range##*,}'}]" $1
-      sed -i '/TenantNetCidr/c\\  TenantNetCidr: '${private_network_cidr}'' $1
-      nic_ext+=_private
-  else
-      sed -i 's#^.*Network::Tenant.*$#  OS::TripleO::Network::Tenant: '${tht_dir}'/noop.yaml#' $1
-      sed -i 's#^.*Controller::Ports::TenantPort:.*$#  OS::TripleO::Controller::Ports::TenantPort: '${tht_dir}'/ports/noop.yaml#' $1
-      sed -i 's#^.*Compute::Ports::TenantPort:.*$#  OS::TripleO::Compute::Ports::TenantPort: '${tht_dir}'/ports/noop.yaml#' $1
-  fi
-
-  # check for storage network
-  if [[ ! -z "$storage_network_enabled" && "$storage_network_enabled" == "true" ]]; then
-      sed -i 's#^.*Network::Storage.*$#  OS::TripleO::Network::Storage: '${tht_dir}'/storage.yaml#' $1
-      sed -i 's#^.*Controller::Ports::StoragePort:.*$#  OS::TripleO::Controller::Ports::StoragePort: '${tht_dir}'/ports/storage.yaml#' $1
-      sed -i 's#^.*Compute::Ports::StoragePort:.*$#  OS::TripleO::Compute::Ports::StoragePort: '${tht_dir}'/ports/storage.yaml#' $1
-      sed -i "/StorageAllocationPools/c\\  StorageAllocationPools: [{'start': '${storage_network_usable_ip_range%%,*}', 'end': '${storage_network_usable_ip_range##*,}'}]" $1
-      sed -i '/StorageNetCidr/c\\  StorageNetCidr: '${storage_network_cidr}'' $1
-      nic_ext+=_storage
-  else
-      sed -i 's#^.*Network::Storage.*$#  OS::TripleO::Network::Storage: '${tht_dir}'/noop.yaml#' $1
-      sed -i 's#^.*Controller::Ports::StoragePort:.*$#  OS::TripleO::Controller::Ports::StoragePort: '${tht_dir}'/ports/noop.yaml#' $1
-      sed -i 's#^.*Compute::Ports::StoragePort:.*$#  OS::TripleO::Compute::Ports::StoragePort: '${tht_dir}'/ports/noop.yaml#' $1
-  fi
-
-  sed -i 's#^.*Controller::Net::SoftwareConfig:.*$#  OS::TripleO::Controller::Net::SoftwareConfig: nics/controller'${nic_ext}'.yaml#' $1
-
-  # check for ODL L3
-  if [ "${deploy_options_array['sdn_l3']}" == 'true' ]; then
-      nic_ext+=_br-ex_no-public-ip
-  fi
-
-  # set nics appropriately
-  sed -i 's#^.*Compute::Net::SoftwareConfig:.*$#  OS::TripleO::Compute::Net::SoftwareConfig: nics/compute'${nic_ext}'.yaml#' $1
-
-}
 ##Copy over the glance images and instackenv json file
 ##params: none
 function configure_undercloud {
-
+  local controller_nic_template compute_nic_template
   echo
   echo "Copying configuration files to Undercloud"
   if [[ "$net_isolation_enabled" == "TRUE" ]]; then
-    configure_network_environment $CONFIG/network-environment.yaml
     echo -e "${blue}Network Environment set for Deployment: ${reset}"
-    cat $CONFIG/network-environment.yaml
-    scp ${SSH_OPTIONS[@]} $CONFIG/network-environment.yaml "stack@$UNDERCLOUD":
+    cat /tmp/network-environment.yaml
+    scp ${SSH_OPTIONS[@]} /tmp/network-environment.yaml "stack@$UNDERCLOUD":
+
+    # check for ODL L3/ONOS
+    if [ "${deploy_options_array['sdn_l3']}" == 'True' ]; then
+      ext_net_type=br-ex
+    fi
+
+    if ! controller_nic_template=$(python3.4 -B $LIB/python/apex-python-utils.py nic-template -t $CONFIG/nics-controller.yaml.jinja2 -n "$enabled_network_list" -e $ext_net_type -af $ip_addr_family); then
+      echo -e "${red}ERROR: Failed to generate controller NIC heat template ${reset}"
+      exit 1
+    fi
+
+    if ! compute_nic_template=$(python3.4 -B $LIB/python/apex-python-utils.py nic-template -t $CONFIG/nics-compute.yaml.jinja2 -n "$enabled_network_list" -e $ext_net_type -af $ip_addr_family); then
+      echo -e "${red}ERROR: Failed to generate compute NIC heat template ${reset}"
+      exit 1
+    fi
+    ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" << EOI
+mkdir nics/
+cat > nics/controller.yaml << EOF
+$controller_nic_template
+EOF
+cat > nics/compute.yaml << EOF
+$compute_nic_template
+EOF
+EOI
   fi
-  scp ${SSH_OPTIONS[@]} -r $CONFIG/nics/ "stack@$UNDERCLOUD":
 
   # ensure stack user on Undercloud machine has an ssh key
   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "if [ ! -e ~/.ssh/id_rsa.pub ]; then ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa; fi"
@@ -820,6 +735,11 @@ sleep 30
 sudo systemctl restart openstack-glance-api
 sudo systemctl restart openstack-nova-conductor
 sudo systemctl restart openstack-nova-compute
+
+sudo sed -i '/num_engine_workers/c\num_engine_workers = 2' /etc/heat/heat.conf
+sudo sed -i '/#workers\s=/c\workers = 2' /etc/heat/heat.conf
+sudo systemctl restart openstack-heat-engine
+sudo systemctl restart openstack-heat-api
 EOI
 # WORKAROUND: must restart the above services to fix sync problem with nova compute manager
 # TODO: revisit and file a bug if necessary. This should eventually be removed
@@ -833,17 +753,17 @@ sleep 15
 ##params: none
 function undercloud_prep_overcloud_deploy {
   if [[ "${#deploy_options_array[@]}" -eq 0 || "${deploy_options_array['sdn_controller']}" == 'opendaylight' ]]; then
-    if [ "${deploy_options_array['sdn_l3']}" == 'true' ]; then
+    if [ "${deploy_options_array['sdn_l3']}" == 'True' ]; then
       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight_l3.yaml"
-    elif [ "${deploy_options_array['sfc']}" == 'true' ]; then
+    elif [ "${deploy_options_array['sfc']}" == 'True' ]; then
       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight_sfc.yaml"
-    elif [ "${deploy_options_array['vpn']}" == 'true' ]; then
+    elif [ "${deploy_options_array['vpn']}" == 'True' ]; then
       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight_sdnvpn.yaml"
     else
       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight.yaml"
     fi
     SDN_IMAGE=opendaylight
-    if [ "${deploy_options_array['sfc']}" == 'true' ]; then
+    if [ "${deploy_options_array['sfc']}" == 'True' ]; then
       SDN_IMAGE+=-sfc
       if [ ! -f $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 ]; then
           echo "${red} $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 is required to execute an SFC deployment."
@@ -860,12 +780,12 @@ function undercloud_prep_overcloud_deploy {
   elif [ "${deploy_options_array['sdn_controller']}" == 'opencontrail' ]; then
     echo -e "${red}ERROR: OpenContrail is currently unsupported...exiting${reset}"
     exit 1
-  elif [[ -z "${deploy_options_array['sdn_controller']}" || "${deploy_options_array['sdn_controller']}" == 'false' ]]; then
+  elif [[ -z "${deploy_options_array['sdn_controller']}" || "${deploy_options_array['sdn_controller']}" == 'False' ]]; then
     echo -e "${blue}INFO: SDN Controller disabled...will deploy nosdn scenario${reset}"
     SDN_IMAGE=opendaylight
   else
     echo "${red}Invalid sdn_controller: ${deploy_options_array['sdn_controller']}${reset}"
-    echo "${red}Valid choices are opendaylight, opendaylight-external, onos, opencontrail, false, or null${reset}"
+    echo "${red}Valid choices are opendaylight, opendaylight-external, onos, opencontrail, False, or null${reset}"
     exit 1
   fi
 
@@ -878,8 +798,20 @@ function undercloud_prep_overcloud_deploy {
   fi
 
   echo "Copying overcloud image to Undercloud"
+  ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "rm -f overcloud-full.qcow2"
   scp ${SSH_OPTIONS[@]} $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 "stack@$UNDERCLOUD":overcloud-full.qcow2
 
+  # Push performance options to subscript to modify per-role images as needed
+  for option in "${performance_options[@]}" ; do
+    echo -e "${blue}Setting performance option $option${reset}"
+    ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "bash build_perf_image.sh $option"
+  done
+
+  # Add performance deploy options if they have been set
+  if [ ! -z "${deploy_options_array['performance']}" ]; then
+    DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/numa.yaml"
+  fi
+
   # make sure ceph is installed
   DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml"
 
@@ -887,7 +819,7 @@ function undercloud_prep_overcloud_deploy {
   total_nodes=$(ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "cat /home/stack/instackenv.json | grep -c memory")
 
   # check if HA is enabled
-  if [[ "$ha_enabled" == "TRUE" || "$ha_enabled" == "true" ]]; then
+  if [[ "$ha_enabled" == "True" ]]; then
      DEPLOY_OPTIONS+=" --control-scale 3"
      compute_nodes=$((total_nodes - 3))
      DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/puppet-pacemaker.yaml"
@@ -908,14 +840,18 @@ function undercloud_prep_overcloud_deploy {
      DEPLOY_OPTIONS+=" -e network-environment.yaml"
   fi
 
-  if [[ "$ha_enabled" == "TRUE" || "$ha_enabled" == "true"  ]] || [[ "$net_isolation_enabled" == "TRUE" ]]; then
+  if [[ "$ha_enabled" == "True" ]] || [[ "$net_isolation_enabled" == "TRUE" ]]; then
      DEPLOY_OPTIONS+=" --ntp-server $ntp_server"
   fi
 
   if [[ ! "$virtual" == "TRUE" ]]; then
      DEPLOY_OPTIONS+=" --control-flavor control --compute-flavor compute"
+  else
+     DEPLOY_OPTIONS+=" -e virtual-environment.yaml"
   fi
 
+  DEPLOY_OPTIONS+=" -e opnfv-environment.yaml"
+
   echo -e "${blue}INFO: Deploy options set:\n${DEPLOY_OPTIONS}${reset}"
 
   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
@@ -927,6 +863,9 @@ source stackrc
 set -o errexit
 echo "Uploading overcloud glance images"
 openstack overcloud image upload
+
+bash -x set_perf_images.sh ${performance_roles[@]}
+
 echo "Configuring undercloud and discovering nodes"
 openstack baremetal import --json instackenv.json
 openstack baremetal configure boot
@@ -966,8 +905,12 @@ EOI
 
   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
 source stackrc
-set -o errexit
 openstack overcloud deploy --templates $DEPLOY_OPTIONS --timeout 90
+if ! heat stack-list | grep CREATE_COMPLETE 1>/dev/null; then
+  $(typeset -f debug_stack)
+  debug_stack
+  exit 1
+fi
 EOI
 
   if [ "$debug" == 'TRUE' ]; then
@@ -1034,7 +977,7 @@ EOI
   fi
 
   # for sfc deployments we need the vxlan workaround
-  if [ "${deploy_options_array['sfc']}" == 'true' ]; then
+  if [ "${deploy_options_array['sfc']}" == 'True' ]; then
       ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
 source stackrc
 set -o errexit
@@ -1083,18 +1026,17 @@ EOI
 
 display_usage() {
   echo -e "Usage:\n$0 [arguments] \n"
-  echo -e "   -c|--config : Directory to configuration files. Optional.  Defaults to /var/opt/opnfv/ \n"
-  echo -e "   -d|--deploy-settings : Full path to deploy settings yaml file. Optional.  Defaults to null \n"
-  echo -e "   -i|--inventory : Full path to inventory yaml file. Required only for baremetal \n"
-  echo -e "   -n|--net-settings : Full path to network settings file. Optional. \n"
-  echo -e "   -p|--ping-site : site to use to verify IP connectivity. Optional. Defaults to 8.8.8.8 \n"
-  echo -e "   -r|--resources : Directory to deployment resources. Optional.  Defaults to /var/opt/opnfv/stack \n"
-  echo -e "   -v|--virtual : Virtualize overcloud nodes instead of using baremetal. \n"
-  echo -e "   --no-ha : disable High Availability deployment scheme, this assumes a single controller and single compute node \n"
-  echo -e "   --flat : disable Network Isolation and use a single flat network for the underlay network.\n"
+  echo -e "   -d|--deploy-settings : Full path to deploy settings yaml file. Optional.  Defaults to null"
+  echo -e "   -i|--inventory : Full path to inventory yaml file. Required only for baremetal"
+  echo -e "   -n|--net-settings : Full path to network settings file. Optional."
+  echo -e "   -p|--ping-site : site to use to verify IP connectivity. Optional. Defaults to 8.8.8.8"
+  echo -e "   -v|--virtual : Virtualize overcloud nodes instead of using baremetal."
+  echo -e "   --flat : disable Network Isolation and use a single flat network for the underlay network."
   echo -e "   --no-post-config : disable Post Install configuration."
   echo -e "   --debug : enable debug output."
   echo -e "   --interactive : enable interactive deployment mode which requires user to confirm steps of deployment."
+  echo -e "   --virtual-cpus : Number of CPUs to use per Overcloud VM in a virtual deployment (defaults to 4)."
+  echo -e "   --virtual-ram : Amount of RAM to use per Overcloud VM in GB (defaults to 8)."
 }
 
 ##translates the command line parameters into variables
@@ -1112,11 +1054,6 @@ parse_cmdline() {
                 display_usage
                 exit 0
             ;;
-        -c|--config)
-                CONFIG=$2
-                echo "Deployment Configuration Directory Overridden to: $2"
-                shift 2
-            ;;
         -d|--deploy-settings)
                 DEPLOY_SETTINGS_FILE=$2
                 echo "Deployment Configuration file: $2"
@@ -1136,22 +1073,11 @@ parse_cmdline() {
                 echo "Using $2 as the ping site"
                 shift 2
             ;;
-        -r|--resources)
-                RESOURCES=$2
-                echo "Deployment Resources Directory Overridden to: $2"
-                shift 2
-            ;;
         -v|--virtual)
                 virtual="TRUE"
                 echo "Executing a Virtual Deployment"
                 shift 1
             ;;
-        --no-ha )
-                ha_enabled="FALSE"
-                vm_index=1
-                echo "HA Deployment Disabled"
-                shift 1
-            ;;
         --flat )
                 net_isolation_enabled="FALSE"
                 echo "Underlay Network Isolation Disabled: using flat configuration"
@@ -1172,6 +1098,21 @@ parse_cmdline() {
                 echo "Interactive mode enabled"
                 shift 1
             ;;
+        --virtual-cpus )
+                VM_CPUS=$2
+                echo "Number of CPUs per VM set to $VM_CPUS"
+                shift 2
+            ;;
+        --virtual-ram )
+                VM_RAM=$2
+                echo "Amount of RAM per VM set to $VM_RAM"
+                shift 2
+            ;;
+        --virtual-computes )
+                VM_COMPUTES=$2
+                echo "Virtual Compute nodes set to $VM_COMPUTES"
+                shift 2
+            ;;
         *)
                 display_usage
                 exit 1
@@ -1216,16 +1157,13 @@ parse_cmdline() {
     post_config="FALSE"
   fi
 
-  ##LIBRARIES
-  # Do this after cli parse so that $CONFIG is set properly
-  source $CONFIG/lib/common-functions.sh
-  source $CONFIG/lib/installer/onos/onos_gw_mac_update.sh
-
 }
 
 ##END FUNCTIONS
 
 main() {
+  # Make sure jinja2 is installed
+  easy_install-3.4 jinja2 > /dev/null
   parse_cmdline "$@"
   echo -e "${blue}INFO: Parsing network settings file...${reset}"
   parse_network_settings
@@ -1234,11 +1172,12 @@ main() {
     exit 1
   fi
   if [ -n "$DEPLOY_SETTINGS_FILE" ]; then
+    echo -e "${blue}INFO: Parsing deploy settings file...${reset}"
     parse_deploy_settings
   fi
   setup_undercloud_vm
   if [ "$virtual" == "TRUE" ]; then
-    setup_virtual_baremetal
+    setup_virtual_baremetal $VM_CPUS $VM_RAM
   elif [ -n "$INVENTORY_FILE" ]; then
     parse_inventory_file
   fi