Adds scenario deploy settings files
[apex.git] / ci / deploy.sh
1 #!/bin/bash
2
3 # Deploy script to install provisioning server for OPNFV Apex
4 # author: Dan Radez (dradez@redhat.com)
5 # author: Tim Rozet (trozet@redhat.com)
6 #
7 # Based on RDO Manager http://www.rdoproject.org
8
9 set -e
10
11 ##VARIABLES
12 if [ "$TERM" != "unknown" ]; then
13   reset=$(tput sgr0)
14   blue=$(tput setaf 4)
15   red=$(tput setaf 1)
16   green=$(tput setaf 2)
17 else
18   reset=""
19   blue=""
20   red=""
21   green=""
22 fi
23
24 vm_index=4
25 ha_enabled="TRUE"
26 ping_site="8.8.8.8"
27 ntp_server="pool.ntp.org"
28 net_isolation_enabled="TRUE"
29 post_config="TRUE"
30
31 declare -i CNT
32 declare UNDERCLOUD
33 declare -A deploy_options_array
34 declare -A NET_MAP
35
36 SSH_OPTIONS=(-o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o LogLevel=error)
37 DEPLOY_OPTIONS=""
38 RESOURCES=/var/opt/opnfv/stack
39 CONFIG=/var/opt/opnfv
40 INSTACKENV=$CONFIG/instackenv.json
41 OPNFV_NETWORK_TYPES="admin_network private_network public_network storage_network"
42 # Netmap used to map networks to OVS bridge names
43 NET_MAP['admin_network']="brbm"
44 NET_MAP['private_network']="brbm1"
45 NET_MAP['public_network']="brbm2"
46 NET_MAP['storage_network']="brbm3"
47
48 ##LIBRARIES
49 source $CONFIG/lib/common-functions.sh
50
51 ##FUNCTIONS
52 ##translates yaml into variables
53 ##params: filename, prefix (ex. "config_")
54 ##usage: parse_yaml opnfv_ksgen_settings.yml "config_"
55 parse_yaml() {
56    local prefix=$2
57    local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
58    sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
59         -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p"  $1 |
60    awk -F$fs '{
61       indent = length($1)/2;
62       vname[indent] = $2;
63       for (i in vname) {if (i > indent) {delete vname[i]}}
64       if (length($3) > 0) {
65          vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
66          printf("%s%s%s=%s\n", "'$prefix'",vn, $2, $3);
67       }
68    }'
69 }
70
71 ##checks if prefix exists in string
72 ##params: string, prefix
73 ##usage: contains_prefix "deploy_setting_launcher=1" "deploy_setting"
74 contains_prefix() {
75   local mystr=$1
76   local prefix=$2
77   if echo $mystr | grep -E "^$prefix.*$" > /dev/null; then
78     return 0
79   else
80     return 1
81   fi
82 }
83 ##parses variable from a string with '='
84 ##and removes global prefix
85 ##params: string, prefix
86 ##usage: parse_setting_var 'deploy_myvar=2' 'deploy_'
87 parse_setting_var() {
88   local mystr=$1
89   local prefix=$2
90   if echo $mystr | grep -E "^.+\=" > /dev/null; then
91     echo $(echo $mystr | grep -Eo "^.+\=" | tr -d '=' |  sed 's/^'"$prefix"'//')
92   else
93     return 1
94   fi
95 }
96 ##parses value from a string with '='
97 ##params: string
98 ##usage: parse_setting_value
99 parse_setting_value() {
100   local mystr=$1
101   echo $(echo $mystr | grep -Eo "\=.*$" | tr -d '=')
102 }
103 ##parses network settings yaml into globals
104 parse_network_settings() {
105   local required_network_settings="cidr"
106   local common_optional_network_settings="usable_ip_range"
107   local admin_network_optional_settings="provisioner_ip dhcp_range introspection_range"
108   local public_network_optional_settings="floating_ip_range gateway provisioner_ip"
109   local nic_value cidr
110
111   eval $(parse_yaml ${NETSETS})
112   for network in ${OPNFV_NETWORK_TYPES}; do
113     if [[ $(eval echo \${${network}_enabled}) == 'true' ]]; then
114       enabled_network_list+="${network} "
115     elif [ "${network}" == 'admin_network' ]; then
116       echo -e "${red}ERROR: You must enable admin_network and configure it explicitly or use auto-detection${reset}"
117       exit 1
118     elif [ "${network}" == 'public_network' ]; then
119       echo -e "${red}ERROR: You must enable public_network and configure it explicitly or use auto-detection${reset}"
120       exit 1
121     else
122       echo -e "${blue}INFO: Network: ${network} is disabled, will collapse into admin_network"
123     fi
124   done
125
126   # check for enabled network values
127   for enabled_network in ${enabled_network_list}; do
128     # detect required settings first to continue
129     echo -e "${blue}INFO: Detecting Required settings for: ${enabled_network}${reset}"
130     for setting in ${required_network_settings}; do
131       eval "setting_value=\${${enabled_network}_${setting}}"
132       if [ -z "${setting_value}" ]; then
133         # if setting is missing we try to autodetect
134         eval "nic_value=\${${enabled_network}_bridged_interface}"
135         if [ -n "$nic_value" ]; then
136           setting_value=$(eval find_${setting} ${nic_value})
137           if [ -n "$setting_value" ]; then
138             eval "${enabled_network}_${setting}=${setting_value}"
139             echo -e "${blue}INFO: Auto-detection: ${enabled_network}_${setting}: ${setting_value}${reset}"
140           else
141             echo -e "${red}ERROR: Auto-detection failed: ${setting} not found using interface: ${nic_value}${reset}"
142             exit 1
143           fi
144         else
145           echo -e "${red}ERROR: Required setting: ${setting} not found, and bridge interface not provided\
146 for Auto-detection${reset}"
147           exit 1
148         fi
149       else
150         echo -e "${blue}INFO: ${enabled_network}_${setting}: ${setting_value}${reset}"
151       fi
152     done
153     echo -e "${blue}INFO: Detecting Common settings for: ${enabled_network}${reset}"
154     # detect optional common settings
155     # these settings can be auto-generated if missing
156     for setting in ${common_optional_network_settings}; do
157       eval "setting_value=\${${enabled_network}_${setting}}"
158       if [ -z "${setting_value}" ]; then
159         if [ -n "$nic_value" ]; then
160           setting_value=$(eval find_${setting} ${nic_value})
161         else
162           setting_value=''
163           echo -e "${blue}INFO: Skipping Auto-detection, NIC not specified for ${enabled_network}.  Attempting Auto-generation...${reset}"
164         fi
165         if [ -n "$setting_value" ]; then
166           eval "${enabled_network}_${setting}=${setting_value}"
167           echo -e "${blue}INFO: Auto-detection: ${enabled_network}_${setting}: ${setting_value}${reset}"
168         else
169           # if Auto-detection fails we can auto-generate with CIDR
170           eval "cidr=\${${enabled_network}_cidr}"
171           if [ -n "$cidr" ]; then
172             echo -e "${blue}INFO: Auto-generating: ${setting}${reset}"
173             setting_value=$(eval generate_${setting} ${cidr})
174           else
175             setting_value=''
176             echo -e "${red}ERROR: Auto-generation failed: required parameter CIDR missing for network ${enabled_network}${reset}"
177           fi
178           if [ -n "$setting_value" ]; then
179             eval "${enabled_network}_${setting}=${setting_value}"
180             echo -e "${blue}INFO: Auto-generated: ${enabled_network}_${setting}: ${setting_value}${reset}"
181           else
182             echo -e "${red}ERROR: Auto-generation failed: ${setting} not found${reset}"
183             exit 1
184           fi
185         fi
186       else
187         echo -e "${blue}INFO: ${enabled_network}_${setting}: ${setting_value}${reset}"
188       fi
189     done
190     echo -e "${blue}INFO: Detecting Network Specific settings for: ${enabled_network}${reset}"
191     # detect network specific settings
192     if [ -n $(eval echo \${${network}_optional_settings}) ]; then
193       eval "network_specific_settings=\${${enabled_network}_optional_settings}"
194       for setting in ${network_specific_settings}; do
195         eval "setting_value=\${${enabled_network}_${setting}}"
196         if [ -z "${setting_value}" ]; then
197           if [ -n "$nic_value" ]; then
198             setting_value=$(eval find_${setting} ${nic_value})
199           else
200             setting_value=''
201             echo -e "${blue}INFO: Skipping Auto-detection, NIC not specified for ${enabled_network}.  Attempting Auto-generation...${reset}"
202           fi
203           if [ -n "$setting_value" ]; then
204             eval "${enabled_network}_${setting}=${setting_value}"
205             echo -e "${blue}INFO: Auto-detection: ${enabled_network}_${setting}: ${setting_value}${reset}"
206           else
207             eval "cidr=\${${enabled_network}_cidr}"
208             if [ -n "$cidr" ]; then
209               setting_value=$(eval generate_${setting} ${cidr})
210             else
211               setting_value=''
212               echo -e "${red}ERROR: Auto-generation failed: required parameter CIDR missing for network ${enabled_network}${reset}"
213             fi
214             if [ -n "$setting_value" ]; then
215               eval "${enabled_network}_${setting}=${setting_value}"
216               echo -e "${blue}INFO: Auto-generated: ${enabled_network}_${setting}: ${setting_value}${reset}"
217             else
218               echo -e "${red}ERROR: Auto-generation failed: ${setting} not found${reset}"
219               exit 1
220             fi
221           fi
222         else
223           echo -e "${blue}INFO: ${enabled_network}_${setting}: ${setting_value}${reset}"
224         fi
225       done
226     fi
227   done
228 }
229 ##parses deploy settings yaml into globals and options array
230 ##params: none
231 ##usage:  parse_deploy_settings
232 parse_deploy_settings() {
233   local global_prefix="deploy_global_params_"
234   local options_prefix="deploy_deploy_options_"
235   local myvar myvalue
236   local settings=$(parse_yaml $DEPLOY_SETTINGS_FILE "deploy_")
237
238   for this_setting in $settings; do
239     if contains_prefix $this_setting $global_prefix; then
240       myvar=$(parse_setting_var $this_setting $global_prefix)
241       if [ -z "$myvar" ]; then
242         echo -e "${red}ERROR: while parsing ${DEPLOY_SETTINGS_FILE} for setting: ${this_setting}${reset}"
243       fi
244       myvalue=$(parse_setting_value $this_setting)
245       # Do not override variables set by cmdline
246       if [ -z "$(eval echo \$$myvar)" ]; then
247         eval "$myvar=\$myvalue"
248         echo -e "${blue}Global parameter set: ${myvar}:${myvalue}${reset}"
249       else
250         echo -e "${blue}Global parameter already set: ${myvar}${reset}"
251       fi
252     elif contains_prefix $this_setting $options_prefix; then
253       myvar=$(parse_setting_var $this_setting $options_prefix)
254       if [ -z "$myvar" ]; then
255         echo -e "${red}ERROR: while parsing ${DEPLOY_SETTINGS_FILE} for setting: ${this_setting}${reset}"
256       fi
257       myvalue=$(parse_setting_value $this_setting)
258       deploy_options_array[$myvar]=$myvalue
259       echo -e "${blue}Deploy option set: ${myvar}:${myvalue}${reset}"
260     fi
261   done
262 }
263 ##parses baremetal yaml settings into compatible json
264 ##writes the json to $CONFIG/instackenv_tmp.json
265 ##params: none
266 ##usage: parse_inventory_file
267 parse_inventory_file() {
268   local inventory=$(parse_yaml $INVENTORY_FILE)
269   local node_list
270   local node_prefix="node"
271   local node_count=0
272   local node_total
273   local inventory_list
274
275   # detect number of nodes
276   for entry in $inventory; do
277     if echo $entry | grep -Eo "^nodes_node[0-9]+_" > /dev/null; then
278       this_node=$(echo $entry | grep -Eo "^nodes_node[0-9]+_")
279       if [[ $inventory_list != *"$this_node"* ]]; then
280         inventory_list+="$this_node "
281       fi
282     fi
283   done
284
285   inventory_list=$(echo $inventory_list | sed 's/ $//')
286
287   for node in $inventory_list; do
288     ((node_count+=1))
289   done
290
291   node_total=$node_count
292
293   if [[ "$node_total" -lt 5 && ha_enabled == "TRUE" ]]; then
294     echo -e "${red}ERROR: You must provide at least 5 nodes for HA baremetal deployment${reset}"
295     exit 1
296   elif [[ "$node_total" -lt 2 ]]; then
297     echo -e "${red}ERROR: You must provide at least 2 nodes for non-HA baremetal deployment${reset}"
298     exit 1
299   fi
300
301   eval $(parse_yaml $INVENTORY_FILE)
302
303   instack_env_output="
304 {
305  \"nodes\" : [
306
307 "
308   node_count=0
309   for node in $inventory_list; do
310     ((node_count+=1))
311     node_output="
312         {
313           \"pm_password\": \"$(eval echo \${${node}ipmi_pass})\",
314           \"pm_type\": \"pxe_ipmitool\",
315           \"mac\": [
316             \"$(eval echo \${${node}mac_address})\"
317           ],
318           \"cpu\": \"$(eval echo \${${node}cpus})\",
319           \"memory\": \"$(eval echo \${${node}memory})\",
320           \"disk\": \"$(eval echo \${${node}disk})\",
321           \"arch\": \"$(eval echo \${${node}arch})\",
322           \"pm_user\": \"$(eval echo \${${node}ipmi_user})\",
323           \"pm_addr\": \"$(eval echo \${${node}ipmi_ip})\",
324           \"capabilities\": \"$(eval echo \${${node}capabilities})\"
325 "
326     instack_env_output+=${node_output}
327     if [ $node_count -lt $node_total ]; then
328       instack_env_output+="        },"
329     else
330       instack_env_output+="        }"
331     fi
332   done
333
334   instack_env_output+='
335   ]
336 }
337 '
338   #Copy instackenv.json to undercloud for baremetal
339   echo -e "{blue}Parsed instackenv JSON:\n${instack_env_output}${reset}"
340   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
341 cat > instackenv.json << EOF
342 $instack_env_output
343 EOF
344 EOI
345
346 }
347 ##verify internet connectivity
348 #params: none
349 function verify_internet {
350   if ping -c 2 $ping_site > /dev/null; then
351     if ping -c 2 www.google.com > /dev/null; then
352       echo "${blue}Internet connectivity detected${reset}"
353       return 0
354     else
355       echo "${red}Internet connectivity detected, but DNS lookup failed${reset}"
356       return 1
357     fi
358   else
359     echo "${red}No internet connectivity detected${reset}"
360     return 1
361   fi
362 }
363
364 ##download dependencies if missing and configure host
365 #params: none
366 function configure_deps {
367   if ! verify_internet; then
368     echo "${red}Will not download dependencies${reset}"
369     internet=false
370   fi
371
372   # verify ip forwarding
373   if sysctl net.ipv4.ip_forward | grep 0; then
374     sudo sysctl -w net.ipv4.ip_forward=1
375     sudo sh -c "echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf"
376   fi
377
378   # ensure no dhcp server is running on jumphost
379   if ! sudo systemctl status dhcpd | grep dead; then
380     echo "${red}WARN: DHCP Server detected on jumphost, disabling...${reset}"
381     sudo systemctl stop dhcpd
382     sudo systemctl disable dhcpd
383   fi
384
385   # ensure networks are configured
386   systemctl start openvswitch
387
388   # If flat we only use admin network
389   if [[ "$net_isolation_enabled" == "FALSE" ]]; then
390     virsh_enabled_networks="admin_network"
391   # For baremetal we only need to create/attach instack to admin and public
392   elif [ "$virtual" == "FALSE" ]; then
393     virsh_enabled_networks="admin_network public_network"
394   else
395     virsh_enabled_networks=$enabled_network_list
396   fi
397
398   for network in ${OPNFV_NETWORK_TYPES}; do
399     ovs-vsctl list-br | grep ${NET_MAP[$network]} > /dev/null || ovs-vsctl add-br ${NET_MAP[$network]}
400     virsh net-list --all | grep ${NET_MAP[$network]} > /dev/null || virsh net-create $CONFIG/${NET_MAP[$network]}-net.xml
401     virsh net-list | grep -E "${NET_MAP[$network]}\s+active" > /dev/null || virsh net-start ${NET_MAP[$network]}
402   done
403
404   echo -e "${blue}INFO: Bridges set: ${reset}"
405   ovs-vsctl list-br
406   echo -e "${blue}INFO: virsh networks set: ${reset}"
407   virsh net-list
408
409   if [[ -z "$virtual" || "$virtual" == "FALSE" ]]; then
410     # bridge interfaces to correct OVS instances for baremetal deployment
411     for network in ${enabled_network_list}; do
412       if [[ "$network" != "admin_network" && "$network" != "public_network" ]]; then
413         continue
414       fi
415       this_interface=$(eval echo \${${network}_bridged_interface})
416       # check if this a bridged interface for this network
417       if [[ ! -z "$this_interface" || "$this_interface" != "none" ]]; then
418         if ! attach_interface_to_ovs ${NET_MAP[$network]} ${this_interface} ${network}; then
419           echo -e "${red}ERROR: Unable to bridge interface ${this_interface} to bridge ${NET_MAP[$network]} for enabled network: ${network}${reset}"
420           exit 1
421         else
422           echo -e "${blue}INFO: Interface ${this_interface} bridged to bridge ${NET_MAP[$network]} for enabled network: ${network}${reset}"
423         fi
424       else
425         echo "${red}ERROR: Unable to determine interface to bridge to for enabled network: ${network}${reset}"
426         exit 1
427       fi
428     done
429   fi
430
431   # ensure storage pool exists and is started
432   virsh pool-list --all | grep default > /dev/null || virsh pool-create $CONFIG/default-pool.xml
433   virsh pool-list | grep -Eo "default\s+active" > /dev/null || virsh pool-start default
434
435   if virsh net-list | grep default > /dev/null; then
436     num_ints_same_subnet=$(ip addr show | grep "inet 192.168.122" | wc -l)
437     if [ "$num_ints_same_subnet" -gt 1 ]; then
438       virsh net-destroy default
439       ##go edit /etc/libvirt/qemu/networks/default.xml
440       sed -i 's/192.168.122/192.168.123/g' /etc/libvirt/qemu/networks/default.xml
441       sed -i 's/192.168.122/192.168.123/g' instackenv-virt.json
442       sleep 5
443       virsh net-start default
444       virsh net-autostart default
445     fi
446   fi
447
448   if ! egrep '^flags.*(vmx|svm)' /proc/cpuinfo > /dev/null; then
449     echo "${red}virtualization extensions not found, kvm kernel module insertion may fail.\n  \
450 Are you sure you have enabled vmx in your bios or hypervisor?${reset}"
451   fi
452
453   if ! lsmod | grep kvm > /dev/null; then modprobe kvm; fi
454   if ! lsmod | grep kvm_intel > /dev/null; then modprobe kvm_intel; fi
455
456   if ! lsmod | grep kvm > /dev/null; then
457     echo "${red}kvm kernel modules not loaded!${reset}"
458     return 1
459   fi
460
461   ##sshkeygen for root
462   if [ ! -e ~/.ssh/id_rsa.pub ]; then
463     ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
464   fi
465
466   echo "${blue}All dependencies installed and running${reset}"
467 }
468
469 ##verify vm exists, an has a dhcp lease assigned to it
470 ##params: none
471 function setup_instack_vm {
472   if ! virsh list --all | grep instack > /dev/null; then
473       #virsh vol-create default instack.qcow2.xml
474       virsh define $CONFIG/instack.xml
475
476       #Upload instack image
477       #virsh vol-create default --file instack.qcow2.xml
478       virsh vol-create-as default instack.qcow2 30G --format qcow2
479
480       ### this doesn't work for some reason I was getting hangup events so using cp instead
481       #virsh vol-upload --pool default --vol instack.qcow2 --file $CONFIG/stack/instack.qcow2
482       #2015-12-05 12:57:20.569+0000: 8755: info : libvirt version: 1.2.8, package: 16.el7_1.5 (CentOS BuildSystem <http://bugs.centos.org>, 2015-11-03-13:56:46, worker1.bsys.centos.org)
483       #2015-12-05 12:57:20.569+0000: 8755: warning : virKeepAliveTimerInternal:143 : No response from client 0x7ff1e231e630 after 6 keepalive messages in 35 seconds
484       #2015-12-05 12:57:20.569+0000: 8756: warning : virKeepAliveTimerInternal:143 : No response from client 0x7ff1e231e630 after 6 keepalive messages in 35 seconds
485       #error: cannot close volume instack.qcow2
486       #error: internal error: received hangup / error event on socket
487       #error: Reconnected to the hypervisor
488
489       instack_dst=/var/lib/libvirt/images/instack.qcow2
490       cp -f $RESOURCES/instack.qcow2 $instack_dst
491
492       # resize instack machine
493       echo "Checking if instack needs to be resized..."
494       instack_size=$(LIBGUESTFS_BACKEND=direct virt-filesystems --long -h --all -a $instack_dst |grep device | grep -Eo "[0-9\.]+G" | sed -n 's/\([0-9][0-9]*\).*/\1/p')
495       if [ "$instack_size" -lt 30 ]; then
496         qemu-img resize /var/lib/libvirt/images/instack.qcow2 +25G
497         LIBGUESTFS_BACKEND=direct virt-resize --expand /dev/sda1 $RESOURCES/instack.qcow2 $instack_dst
498         LIBGUESTFS_BACKEND=direct virt-customize -a $instack_dst --run-command 'xfs_growfs -d /dev/sda1 || true'
499         new_size=$(LIBGUESTFS_BACKEND=direct virt-filesystems --long -h --all -a $instack_dst |grep filesystem | grep -Eo "[0-9\.]+G" | sed -n 's/\([0-9][0-9]*\).*/\1/p')
500         if [ "$new_size" -lt 30 ]; then
501           echo "Error resizing instack machine, disk size is ${new_size}"
502           exit 1
503         else
504           echo "instack successfully resized"
505         fi
506       else
507         echo "skipped instack resize, upstream is large enough"
508       fi
509
510   else
511       echo "Found Instack VM, using existing VM"
512   fi
513
514   # if the VM is not running update the authkeys and start it
515   if ! virsh list | grep instack > /dev/null; then
516     echo "Injecting ssh key to instack VM"
517     virt-customize -c qemu:///system -d instack --run-command "mkdir -p /root/.ssh/" \
518         --upload ~/.ssh/id_rsa.pub:/root/.ssh/authorized_keys \
519         --run-command "chmod 600 /root/.ssh/authorized_keys && restorecon /root/.ssh/authorized_keys" \
520         --run-command "cp /root/.ssh/authorized_keys /home/stack/.ssh/" \
521         --run-command "chown stack:stack /home/stack/.ssh/authorized_keys && chmod 600 /home/stack/.ssh/authorized_keys"
522     virsh start instack
523   fi
524
525   sleep 3 # let DHCP happen
526
527   CNT=10
528   echo -n "${blue}Waiting for instack's dhcp address${reset}"
529   while ! grep instack /var/lib/libvirt/dnsmasq/default.leases > /dev/null && [ $CNT -gt 0 ]; do
530       echo -n "."
531       sleep 3
532       CNT=CNT-1
533   done
534
535   # get the instack VM IP
536   UNDERCLOUD=$(grep instack /var/lib/libvirt/dnsmasq/default.leases | awk '{print $3}' | head -n 1)
537   if [ -z "$UNDERCLOUD" ]; then
538     #if not found then dnsmasq may be using leasefile-ro
539     instack_mac=$(virsh domiflist instack | grep default | \
540                   grep -Eo "[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+")
541     UNDERCLOUD=$(/usr/sbin/arp -e | grep ${instack_mac} | awk {'print $1'})
542
543     if [ -z "$UNDERCLOUD" ]; then
544       echo "\n\nNever got IP for Instack. Can Not Continue."
545       exit 1
546     else
547       echo -e "${blue}\rInstack VM has IP $UNDERCLOUD${reset}"
548     fi
549   else
550      echo -e "${blue}\rInstack VM has IP $UNDERCLOUD${reset}"
551   fi
552
553   CNT=10
554   echo -en "${blue}\rValidating instack VM connectivity${reset}"
555   while ! ping -c 1 $UNDERCLOUD > /dev/null && [ $CNT -gt 0 ]; do
556       echo -n "."
557       sleep 3
558       CNT=$CNT-1
559   done
560   if [ "$CNT" -eq 0 ]; then
561       echo "Failed to contact Instack. Can Not Continue"
562       exit 1
563   fi
564   CNT=10
565   while ! ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "echo ''" 2>&1> /dev/null && [ $CNT -gt 0 ]; do
566       echo -n "."
567       sleep 3
568       CNT=$CNT-1
569   done
570   if [ "$CNT" -eq 0 ]; then
571       echo "Failed to connect to Instack. Can Not Continue"
572       exit 1
573   fi
574
575   # extra space to overwrite the previous connectivity output
576   echo -e "${blue}\r                                                                 ${reset}"
577
578   #add the instack public interface if net isolation is enabled (more than just admin network)
579   if [[ "$net_isolation_enabled" == "TRUE" ]]; then
580     virsh attach-interface --domain instack --type network --source ${NET_MAP['public_network']} --model rtl8139 --config --live
581     sleep 1
582     ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "if ! ip a s eth2 | grep ${public_network_provisioner_ip} > /dev/null; then ip a a ${public_network_provisioner_ip}/${public_network_cidr##*/} dev eth2; ip link set up dev eth2; fi"
583   fi
584   # ssh key fix for stack user
585   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "restorecon -r /home/stack"
586 }
587
588 ##Create virtual nodes in virsh
589 ##params: none
590 function setup_virtual_baremetal {
591   for i in $(seq 0 $vm_index); do
592     if ! virsh list --all | grep baremetalbrbm_brbm1_brbm2_brbm3_${i} > /dev/null; then
593       if [ ! -e $CONFIG/baremetalbrbm_brbm1_brbm2_brbm3_${i}.xml ]; then
594         define_virtual_node baremetalbrbm_brbm1_brbm2_brbm3_${i}
595       fi
596       # Fix for ramdisk using wrong pxeboot interface
597       # TODO: revisit this and see if there's a more proper fix
598       sed -i "/^\s*<source network='brbm2'\/>/{
599         N
600         s/^\(.*\)virtio\(.*\)$/\1rtl8139\2/
601         }" $CONFIG/baremetalbrbm_brbm1_brbm2_brbm3_${i}.xml
602       virsh define $CONFIG/baremetalbrbm_brbm1_brbm2_brbm3_${i}.xml
603     else
604       echo "Found Baremetal ${i} VM, using existing VM"
605     fi
606     virsh vol-list default | grep baremetalbrbm_brbm1_brbm2_brbm3_${i} 2>&1> /dev/null || virsh vol-create-as default baremetalbrbm_brbm1_brbm2_brbm3_${i}.qcow2 40G --format qcow2
607   done
608
609 }
610
611 ##Set network-environment settings
612 ##params: network-environment file to edit
613 function configure_network_environment {
614   local tht_dir nic_ext
615   tht_dir=/usr/share/openstack-tripleo-heat-templates/network
616   nic_ext=''
617
618   sed -i '/ControlPlaneSubnetCidr/c\\  ControlPlaneSubnetCidr: "'${admin_network_cidr##*/}'"' $1
619   sed -i '/ControlPlaneDefaultRoute/c\\  ControlPlaneDefaultRoute: '${admin_network_provisioner_ip}'' $1
620   sed -i '/ExternalNetCidr/c\\  ExternalNetCidr: '${public_network_cidr}'' $1
621   sed -i "/ExternalAllocationPools/c\\  ExternalAllocationPools: [{'start': '${public_network_usable_ip_range%%,*}', 'end': '${public_network_usable_ip_range##*,}'}]" $1
622   sed -i '/ExternalInterfaceDefaultRoute/c\\  ExternalInterfaceDefaultRoute: '${public_network_gateway}'' $1
623   sed -i '/EC2MetadataIp/c\\  EC2MetadataIp: '${admin_network_provisioner_ip}'' $1
624
625   # check for private network
626   if [[ ! -z "$private_network_enabled" && "$private_network_enabled" == "true" ]]; then
627       sed -i 's#^.*Network::Tenant.*$#  OS::TripleO::Network::Tenant: '${tht_dir}'/tenant.yaml#' $1
628       sed -i 's#^.*Controller::Ports::TenantPort:.*$#  OS::TripleO::Controller::Ports::TenantPort: '${tht_dir}'/ports/tenant.yaml#' $1
629       sed -i 's#^.*Compute::Ports::TenantPort:.*$#  OS::TripleO::Compute::Ports::TenantPort: '${tht_dir}'/ports/tenant.yaml#' $1
630       sed -i "/TenantAllocationPools/c\\  TenantAllocationPools: [{'start': '${private_network_usable_ip_range%%,*}', 'end': '${private_network_usable_ip_range##*,}'}]" $1
631       sed -i '/TenantNetCidr/c\\  TenantNetCidr: '${private_network_cidr}'' $1
632       nic_ext+=_private
633   else
634       sed -i 's#^.*Network::Tenant.*$#  OS::TripleO::Network::Tenant: '${tht_dir}'/noop.yaml#' $1
635       sed -i 's#^.*Controller::Ports::TenantPort:.*$#  OS::TripleO::Controller::Ports::TenantPort: '${tht_dir}'/ports/noop.yaml#' $1
636       sed -i 's#^.*Compute::Ports::TenantPort:.*$#  OS::TripleO::Compute::Ports::TenantPort: '${tht_dir}'/ports/noop.yaml#' $1
637   fi
638
639   # check for storage network
640   if [[ ! -z "$storage_network_enabled" && "$storage_network_enabled" == "true" ]]; then
641       sed -i 's#^.*Network::Storage.*$#  OS::TripleO::Network::Storage: '${tht_dir}'/storage.yaml#' $1
642       sed -i 's#^.*Controller::Ports::StoragePort:.*$#  OS::TripleO::Controller::Ports::StoragePort: '${tht_dir}'/ports/storage.yaml#' $1
643       sed -i 's#^.*Compute::Ports::StoragePort:.*$#  OS::TripleO::Compute::Ports::StoragePort: '${tht_dir}'/ports/storage.yaml#' $1
644       sed -i "/StorageAllocationPools/c\\  StorageAllocationPools: [{'start': '${storage_network_usable_ip_range%%,*}', 'end': '${storage_network_usable_ip_range##*,}'}]" $1
645       sed -i '/StorageNetCidr/c\\  StorageNetCidr: '${storage_network_cidr}'' $1
646       nic_ext+=_storage
647   else
648       sed -i 's#^.*Network::Storage.*$#  OS::TripleO::Network::Storage: '${tht_dir}'/noop.yaml#' $1
649       sed -i 's#^.*Controller::Ports::StoragePort:.*$#  OS::TripleO::Controller::Ports::StoragePort: '${tht_dir}'/ports/noop.yaml#' $1
650       sed -i 's#^.*Compute::Ports::StoragePort:.*$#  OS::TripleO::Compute::Ports::StoragePort: '${tht_dir}'/ports/noop.yaml#' $1
651   fi
652
653   # set nics appropriately
654   sed -i 's#^.*Compute::Net::SoftwareConfig:.*$#  OS::TripleO::Compute::Net::SoftwareConfig: nics/compute'${nic_ext}'.yaml#' $1
655   sed -i 's#^.*Controller::Net::SoftwareConfig:.*$#  OS::TripleO::Controller::Net::SoftwareConfig: nics/controller'${nic_ext}'.yaml#' $1
656 }
657 ##Copy over the glance images and instack json file
658 ##params: none
659 function configure_undercloud {
660
661   echo
662   echo "Copying configuration file and disk images to instack"
663   scp ${SSH_OPTIONS[@]} $RESOURCES/overcloud-full.qcow2 "stack@$UNDERCLOUD":
664   if [[ "$net_isolation_enabled" == "TRUE" ]]; then
665     configure_network_environment $CONFIG/network-environment.yaml
666     echo -e "${blue}Network Environment set for Deployment: ${reset}"
667     cat $CONFIG/network-environment.yaml
668     scp ${SSH_OPTIONS[@]} $CONFIG/network-environment.yaml "stack@$UNDERCLOUD":
669   fi
670   scp ${SSH_OPTIONS[@]} -r $CONFIG/nics/ "stack@$UNDERCLOUD":
671
672   # ensure stack user on instack machine has an ssh key
673   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "if [ ! -e ~/.ssh/id_rsa.pub ]; then ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa; fi"
674
675   if [ "$virtual" == "TRUE" ]; then
676
677       # copy the instack vm's stack user's pub key to
678       # root's auth keys so that instack can control
679       # vm power on the hypervisor
680       ssh ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "cat /home/stack/.ssh/id_rsa.pub" >> /root/.ssh/authorized_keys
681
682       # fix MACs to match new setup
683       for i in $(seq 0 $vm_index); do
684         pyscript="import json
685 data = json.load(open('$CONFIG/instackenv-virt.json'))
686 print data['nodes'][$i]['mac'][0]"
687
688         old_mac=$(python -c "$pyscript")
689         new_mac=$(virsh dumpxml baremetalbrbm_brbm1_brbm2_brbm3_$i | grep "mac address" | cut -d = -f2 | grep -Eo "[0-9a-f:]+")
690         # this doesn't work with multiple vnics on the vms
691         #if [ "$old_mac" != "$new_mac" ]; then
692         #  echo "${blue}Modifying MAC for node from $old_mac to ${new_mac}${reset}"
693         #  sed -i 's/'"$old_mac"'/'"$new_mac"'/' $CONFIG/instackenv-virt.json
694         #fi
695       done
696
697       DEPLOY_OPTIONS+=" --libvirt-type qemu"
698       INSTACKENV=$CONFIG/instackenv-virt.json
699
700       # upload instackenv file to Instack for virtual deployment
701       scp ${SSH_OPTIONS[@]} $INSTACKENV "stack@$UNDERCLOUD":instackenv.json
702   fi
703
704   # allow stack to control power management on the hypervisor via sshkey
705   # only if this is a virtual deployment
706   if [ "$virtual" == "TRUE" ]; then
707       ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
708 while read -r line; do
709   stack_key=\${stack_key}\\\\\\\\n\${line}
710 done < <(cat ~/.ssh/id_rsa)
711 stack_key=\$(echo \$stack_key | sed 's/\\\\\\\\n//')
712 sed -i 's~INSERT_STACK_USER_PRIV_KEY~'"\$stack_key"'~' instackenv.json
713 EOI
714   fi
715
716   # copy stack's ssh key to this users authorized keys
717   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "cat /home/stack/.ssh/id_rsa.pub" >> ~/.ssh/authorized_keys
718
719   # disable requiretty for sudo
720   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "sed -i 's/Defaults\s*requiretty//'" /etc/sudoers
721
722   # configure undercloud on Undercloud VM
723   echo "Running undercloud configuration."
724   echo "Logging undercloud configuration to instack:/home/stack/apex-undercloud-install.log"
725   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" << EOI
726 if [[ "$net_isolation_enabled" == "TRUE" ]]; then
727   sed -i 's/#local_ip/local_ip/' undercloud.conf
728   sed -i 's/#network_gateway/network_gateway/' undercloud.conf
729   sed -i 's/#network_cidr/network_cidr/' undercloud.conf
730   sed -i 's/#dhcp_start/dhcp_start/' undercloud.conf
731   sed -i 's/#dhcp_end/dhcp_end/' undercloud.conf
732   sed -i 's/#inspection_iprange/inspection_iprange/' undercloud.conf
733   sed -i 's/#undercloud_debug/undercloud_debug/' undercloud.conf
734
735   openstack-config --set undercloud.conf DEFAULT local_ip ${admin_network_provisioner_ip}/${admin_network_cidr##*/}
736   openstack-config --set undercloud.conf DEFAULT network_gateway ${admin_network_provisioner_ip}
737   openstack-config --set undercloud.conf DEFAULT network_cidr ${admin_network_cidr}
738   openstack-config --set undercloud.conf DEFAULT dhcp_start ${admin_network_dhcp_range%%,*}
739   openstack-config --set undercloud.conf DEFAULT dhcp_end ${admin_network_dhcp_range##*,}
740   openstack-config --set undercloud.conf DEFAULT inspection_iprange ${admin_network_introspection_range}
741   openstack-config --set undercloud.conf DEFAULT undercloud_debug false
742
743 fi
744
745 sudo sed -i '/CephClusterFSID:/c\\  CephClusterFSID: \\x27$(cat /proc/sys/kernel/random/uuid)\\x27' /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
746 sudo sed -i '/CephMonKey:/c\\  CephMonKey: \\x27'"\$(ceph-authtool --gen-print-key)"'\\x27' /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
747 sudo sed -i '/CephAdminKey:/c\\  CephAdminKey: \\x27'"\$(ceph-authtool --gen-print-key)"'\\x27' /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
748
749 openstack undercloud install &> apex-undercloud-install.log
750 sleep 30
751 sudo systemctl restart openstack-glance-api
752 sudo systemctl restart openstack-nova-conductor
753 sudo systemctl restart openstack-nova-compute
754 EOI
755 # WORKAROUND: must restart the above services to fix sync problem with nova compute manager
756 # TODO: revisit and file a bug if necessary. This should eventually be removed
757 # as well as glance api problem
758 echo -e "${blue}INFO: Sleeping 15 seconds while services come back from restart${reset}"
759 sleep 15
760
761 }
762
763 ##preping it for deployment and launch the deploy
764 ##params: none
765 function undercloud_prep_overcloud_deploy {
766   # TODO ADD ODL L3 logic here
767   if [[ ${#deploy_options_array[@]} -eq 0 || ${deploy_options_array['sdn_controller']} == 'opendaylight' ]]; then
768     DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight.yaml"
769   elif [ ${deploy_options_array['sdn_controller']} == 'opendaylight-external' ]; then
770     DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight-external.yaml"
771   elif [ ${deploy_options_array['sdn_controller']} == 'onos' ]; then
772     DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/onos.yaml"
773   elif [ ${deploy_options_array['sdn_controller']} == 'opencontrail' ]; then
774     echo -e "${red}ERROR: OpenContrail is currently unsupported...exiting${reset}"
775     exit 1
776   fi
777
778   # make sure ceph is installed
779   DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml"
780
781   # check if HA is enabled
782   if [[ "$ha_enabled" == "TRUE" ]]; then
783      DEPLOY_OPTIONS+=" --control-scale 3 --compute-scale 2"
784      DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/puppet-pacemaker.yaml"
785   fi
786
787   if [[ "$net_isolation_enabled" == "TRUE" ]]; then
788      #DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/network-isolation.yaml"
789      DEPLOY_OPTIONS+=" -e network-environment.yaml"
790   fi
791
792   if [[ "$ha_enabled" == "TRUE" ]] || [[ "$net_isolation_enabled" == "TRUE" ]]; then
793      DEPLOY_OPTIONS+=" --ntp-server $ntp_server"
794   fi
795
796   if [[ ! "$virtual" == "TRUE" ]]; then
797      DEPLOY_OPTIONS+=" --control-flavor control --compute-flavor compute"
798   fi
799
800   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
801 source stackrc
802 set -o errexit
803 echo "Uploading overcloud glance images"
804 openstack overcloud image upload
805 echo "Configuring undercloud and discovering nodes"
806 openstack baremetal import --json instackenv.json
807 openstack baremetal configure boot
808 openstack baremetal introspection bulk start
809 echo "Configuring flavors"
810 for flavor in baremetal control compute; do
811   echo -e "${blue}INFO: Updating flavor: \${flavor}${reset}"
812   if openstack flavor list | grep \${flavor}; then
813     openstack flavor delete \${flavor}
814   fi
815   openstack flavor create --id auto --ram 4096 --disk 39 --vcpus 1 \${flavor}
816   if ! openstack flavor list | grep \${flavor}; then
817     echo -e "${red}ERROR: Unable to create flavor \${flavor}${reset}"
818   fi
819 done
820 openstack flavor set --property "cpu_arch"="x86_64" --property "capabilities:boot_option"="local" baremetal
821 openstack flavor set --property "cpu_arch"="x86_64" --property "capabilities:boot_option"="local" --property "capabilities:profile"="control" control
822 openstack flavor set --property "cpu_arch"="x86_64" --property "capabilities:boot_option"="local" --property "capabilities:profile"="compute" compute
823 echo "Configuring nameserver on ctlplane network"
824 neutron subnet-update \$(neutron subnet-list | grep -v id | grep -v \\\\-\\\\- | awk {'print \$2'}) --dns-nameserver 8.8.8.8
825 echo "Executing overcloud deployment, this should run for an extended period without output."
826 sleep 60 #wait for Hypervisor stats to check-in to nova
827 # save deploy command so it can be used for debugging
828 cat > deploy_command << EOF
829 openstack overcloud deploy --templates $DEPLOY_OPTIONS
830 EOF
831 openstack overcloud deploy --templates $DEPLOY_OPTIONS
832 EOI
833
834 }
835
836 ##Post configuration after install
837 ##params: none
838 function configure_post_install {
839   local opnfv_attach_networks ovs_ip ip_range net_cidr tmp_ip
840   opnfv_attach_networks="admin_network public_network"
841
842   echo -e "${blue}INFO: Post Install Configuration Running...${reset}"
843
844   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
845 source overcloudrc
846 set -o errexit
847 echo "Configuring Neutron external network"
848 neutron net-create external --router:external=True
849 neutron subnet-create --name external-net --disable-dhcp external --gateway ${public_network_gateway} --allocation-pool start=${public_network_floating_ip_range%%,*},end=${public_network_floating_ip_range##*,} ${public_network_cidr}
850 EOI
851
852   echo -e "${blue}INFO: Checking if OVS bridges have IP addresses...${reset}"
853   for network in ${opnfv_attach_networks}; do
854     ovs_ip=$(find_ip ${NET_MAP[$network]})
855     tmp_ip=''
856     if [ -n "$ovs_ip" ]; then
857       echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} has IP address ${ovs_ip}${reset}"
858     else
859       echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} missing IP, will configure${reset}"
860       # use last IP of allocation pool
861       eval "ip_range=\${${network}_usable_ip_range}"
862       ovs_ip=${ip_range##*,}
863       eval "net_cidr=\${${network}_cidr}"
864       sudo ip addr add ${ovs_ip}/${net_cidr##*/} dev ${NET_MAP[$network]}
865       sudo ip link set up ${NET_MAP[$network]}
866       tmp_ip=$(find_ip ${NET_MAP[$network]})
867       if [ -n "$tmp_ip" ]; then
868         echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} IP set: ${tmp_ip}${reset}"
869         continue
870       else
871         echo -e "${red}ERROR: Unable to set OVS Bridge ${NET_MAP[$network]} with IP: ${ovs_ip}${reset}"
872         return 1
873       fi
874     fi
875   done
876 }
877
878 display_usage() {
879   echo -e "Usage:\n$0 [arguments] \n"
880   echo -e "   -c|--config : Directory to configuration files. Optional.  Defaults to /var/opt/opnfv/ \n"
881   echo -e "   -d|--deploy-settings : Full path to deploy settings yaml file. Optional.  Defaults to null \n"
882   echo -e "   -i|--inventory : Full path to inventory yaml file. Required only for baremetal \n"
883   echo -e "   -n|--net-settings : Full path to network settings file. Optional. \n"
884   echo -e "   -p|--ping-site : site to use to verify IP connectivity. Optional. Defaults to 8.8.8.8 \n"
885   echo -e "   -r|--resources : Directory to deployment resources. Optional.  Defaults to /var/opt/opnfv/stack \n"
886   echo -e "   -v|--virtual : Virtualize overcloud nodes instead of using baremetal. \n"
887   echo -e "   --no-ha : disable High Availability deployment scheme, this assumes a single controller and single compute node \n"
888   echo -e "   --flat : disable Network Isolation and use a single flat network for the underlay network.\n"
889   echo -e "   --no-post-config : disable Post Install configuration."
890 }
891
892 ##translates the command line parameters into variables
893 ##params: $@ the entire command line is passed
894 ##usage: parse_cmd_line() "$@"
895 parse_cmdline() {
896   echo -e "\n\n${blue}This script is used to deploy the Apex Installer and Provision OPNFV Target System${reset}\n\n"
897   echo "Use -h to display help"
898   sleep 2
899
900   while [ "${1:0:1}" = "-" ]
901   do
902     case "$1" in
903         -h|--help)
904                 display_usage
905                 exit 0
906             ;;
907         -c|--config)
908                 CONFIG=$2
909                 echo "Deployment Configuration Directory Overridden to: $2"
910                 shift 2
911             ;;
912         -d|--deploy-settings)
913                 DEPLOY_SETTINGS_FILE=$2
914                 echo "Deployment Configuration file: $2"
915                 shift 2
916             ;;
917         -i|--inventory)
918                 INVENTORY_FILE=$2
919                 shift 2
920             ;;
921         -n|--net-settings)
922                 NETSETS=$2
923                 echo "Network Settings Configuration file: $2"
924                 shift 2
925             ;;
926         -p|--ping-site)
927                 ping_site=$2
928                 echo "Using $2 as the ping site"
929                 shift 2
930             ;;
931         -r|--resources)
932                 RESOURCES=$2
933                 echo "Deployment Resources Directory Overridden to: $2"
934                 shift 2
935             ;;
936         -v|--virtual)
937                 virtual="TRUE"
938                 echo "Executing a Virtual Deployment"
939                 shift 1
940             ;;
941         --no-ha )
942                 ha_enabled="FALSE"
943                 echo "HA Deployment Disabled"
944                 shift 1
945             ;;
946         --flat )
947                 net_isolation_enabled="FALSE"
948                 echo "Underlay Network Isolation Disabled: using flat configuration"
949                 shift 1
950             ;;
951         --no-post-config )
952                 post_config="FALSE"
953                 echo "Post install configuration disabled"
954                 shift 1
955             ;;
956         *)
957                 display_usage
958                 exit 1
959             ;;
960     esac
961   done
962
963   if [[ ! -z "$NETSETS" && "$net_isolation_enabled" == "FALSE" ]]; then
964     echo -e "${red}INFO: Single flat network requested. Ignoring any network settings!${reset}"
965   elif [[ -z "$NETSETS" && "$net_isolation_enabled" == "TRUE" ]]; then
966     echo -e "${red}ERROR: You must provide a network_settings file with -n or use --flat to force a single flat network${reset}"
967     exit 1
968   fi
969
970   if [[ -n "$virtual" && -n "$INVENTORY_FILE" ]]; then
971     echo -e "${red}ERROR: You should not specify an inventory with virtual deployments${reset}"
972     exit 1
973   fi
974
975   if [[ ! -z "$DEPLOY_SETTINGS_FILE" && ! -f "$DEPLOY_SETTINGS_FILE" ]]; then
976     echo -e "${red}ERROR: ${DEPLOY_SETTINGS_FILE} does not exist! Exiting...${reset}"
977     exit 1
978   fi
979
980   if [[ ! -z "$NETSETS" && ! -f "$NETSETS" ]]; then
981     echo -e "${red}ERROR: ${NETSETS} does not exist! Exiting...${reset}"
982     exit 1
983   fi
984
985   if [[ ! -z "$INVENTORY_FILE" && ! -f "$INVENTORY_FILE" ]]; then
986     echo -e "{$red}ERROR: ${DEPLOY_SETTINGS_FILE} does not exist! Exiting...${reset}"
987     exit 1
988   fi
989
990   if [[ -z "$virtual" && -z "$INVENTORY_FILE" ]]; then
991     echo -e "${red}ERROR: You must specify an inventory file for baremetal deployments! Exiting...${reset}"
992     exit 1
993   fi
994
995   if [[ "$net_isolation_enabled" == "FALSE" && "$post_config" == "TRUE" ]]; then
996     echo -e "${blue}INFO: Post Install Configuration will be skipped.  It is not supported with --flat${reset}"
997     post_config="FALSE"
998   fi
999 }
1000
1001 ##END FUNCTIONS
1002
1003 main() {
1004   parse_cmdline "$@"
1005   if [[ "$net_isolation_enabled" == "TRUE" ]]; then
1006     echo -e "${blue}INFO: Parsing network settings file...${reset}"
1007     parse_network_settings
1008   fi
1009   if ! configure_deps; then
1010     echo -e "${red}Dependency Validation Failed, Exiting.${reset}"
1011     exit 1
1012   fi
1013   if [ -n "$DEPLOY_SETTINGS_FILE" ]; then
1014     parse_deploy_settings
1015   fi
1016   setup_instack_vm
1017   if [ "$virtual" == "TRUE" ]; then
1018     setup_virtual_baremetal
1019   elif [ -n "$INVENTORY_FILE" ]; then
1020     parse_inventory_file
1021   fi
1022   configure_undercloud
1023   undercloud_prep_overcloud_deploy
1024   if [ "$post_config" == "TRUE" ]; then
1025     if ! configure_post_install; then
1026       echo -e "${red}ERROR:Post Install Configuration Failed, Exiting.${reset}"
1027       exit 1
1028     else
1029       echo -e "${blue}INFO: Post Install Configuration Complete${reset}"
1030     fi
1031   fi
1032 }
1033
1034 main "$@"