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