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