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