Merge "Moving parser functions to a sourced file"
[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 reset=$(tput sgr0 || echo "")
21 blue=$(tput setaf 4 || echo "")
22 red=$(tput setaf 1 || echo "")
23 green=$(tput setaf 2 || echo "")
24
25 interactive="FALSE"
26 ping_site="8.8.8.8"
27 ntp_server="pool.ntp.org"
28 net_isolation_enabled="TRUE"
29 post_config="TRUE"
30 debug="FALSE"
31
32 declare -i CNT
33 declare UNDERCLOUD
34 declare -A deploy_options_array
35 declare -a performance_options
36 declare -A NET_MAP
37
38 SSH_OPTIONS=(-o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o LogLevel=error)
39 DEPLOY_OPTIONS=""
40 CONFIG=${CONFIG:-'/var/opt/opnfv'}
41 RESOURCES=${RESOURCES:-"$CONFIG/images"}
42 LIB=${LIB:-"$CONFIG/lib"}
43 OPNFV_NETWORK_TYPES="admin_network private_network public_network storage_network api_network"
44
45 VM_CPUS=4
46 VM_RAM=8
47 VM_COMPUTES=2
48
49 # Netmap used to map networks to OVS bridge names
50 NET_MAP['admin_network']="br-admin"
51 NET_MAP['private_network']="br-private"
52 NET_MAP['public_network']="br-public"
53 NET_MAP['storage_network']="br-storage"
54 NET_MAP['api_network']="br-api"
55 ext_net_type="interface"
56 ip_address_family=4
57
58 # Libraries
59 lib_files=(
60 $LIB/common-functions.sh
61 $LIB/parse-functions.sh
62 $LIB/utility-functions.sh
63 $LIB/installer/onos/onos_gw_mac_update.sh
64 )
65 for lib_file in ${lib_files[@]}; do
66   if ! source $lib_file; then
67     echo -e "${red}ERROR: Failed to source $lib_file${reset}"
68     exit 1
69   fi
70 done
71
72 ##FUNCTIONS
73 ##checks if prefix exists in string
74 ##params: string, prefix
75 ##usage: contains_prefix "deploy_setting_launcher=1" "deploy_setting"
76 contains_prefix() {
77   local mystr=$1
78   local prefix=$2
79   if echo $mystr | grep -E "^$prefix.*$" > /dev/null; then
80     return 0
81   else
82     return 1
83   fi
84 }
85
86 ##verify internet connectivity
87 #params: none
88 function verify_internet {
89   if ping -c 2 $ping_site > /dev/null; then
90     if ping -c 2 www.google.com > /dev/null; then
91       echo "${blue}Internet connectivity detected${reset}"
92       return 0
93     else
94       echo "${red}Internet connectivity detected, but DNS lookup failed${reset}"
95       return 1
96     fi
97   else
98     echo "${red}No internet connectivity detected${reset}"
99     return 1
100   fi
101 }
102
103 ##download dependencies if missing and configure host
104 #params: none
105 function configure_deps {
106   if ! verify_internet; then
107     echo "${red}Will not download dependencies${reset}"
108     internet=false
109   fi
110
111   # verify ip forwarding
112   if sysctl net.ipv4.ip_forward | grep 0; then
113     sudo sysctl -w net.ipv4.ip_forward=1
114     sudo sh -c "echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf"
115   fi
116
117   # ensure no dhcp server is running on jumphost
118   if ! sudo systemctl status dhcpd | grep dead; then
119     echo "${red}WARN: DHCP Server detected on jumphost, disabling...${reset}"
120     sudo systemctl stop dhcpd
121     sudo systemctl disable dhcpd
122   fi
123
124   # ensure networks are configured
125   systemctl status libvirtd || systemctl start libvirtd
126   systemctl status openvswitch || systemctl start openvswitch
127
128   # If flat we only use admin network
129   if [[ "$net_isolation_enabled" == "FALSE" ]]; then
130     virsh_enabled_networks="admin_network"
131     enabled_network_list="admin_network"
132   # For baremetal we only need to create/attach Undercloud to admin and public
133   elif [ "$virtual" == "FALSE" ]; then
134     virsh_enabled_networks="admin_network public_network"
135   else
136     virsh_enabled_networks=$enabled_network_list
137   fi
138
139   # ensure default network is configured correctly
140   libvirt_dir="/usr/share/libvirt/networks"
141   virsh net-list --all | grep default || virsh net-define ${libvirt_dir}/default.xml
142   virsh net-list --all | grep -E "default\s+active" > /dev/null || virsh net-start default
143   virsh net-list --all | grep -E "default\s+active\s+yes" > /dev/null || virsh net-autostart --network default
144
145   if [[ -z "$virtual" || "$virtual" == "FALSE" ]]; then
146     for network in ${enabled_network_list}; do
147       echo "${blue}INFO: Creating Virsh Network: $network & OVS Bridge: ${NET_MAP[$network]}${reset}"
148       ovs-vsctl list-br | grep "^${NET_MAP[$network]}$" > /dev/null || ovs-vsctl add-br ${NET_MAP[$network]}
149       virsh net-list --all | grep $network > /dev/null || (cat > ${libvirt_dir}/apex-virsh-net.xml && virsh net-define ${libvirt_dir}/apex-virsh-net.xml) << EOF
150 <network>
151   <name>$network</name>
152   <forward mode='bridge'/>
153   <bridge name='${NET_MAP[$network]}'/>
154   <virtualport type='openvswitch'/>
155 </network>
156 EOF
157       if ! (virsh net-list --all | grep $network > /dev/null); then
158           echo "${red}ERROR: unable to create network: ${network}${reset}"
159           exit 1;
160       fi
161       rm -f ${libvirt_dir}/apex-virsh-net.xml &> /dev/null;
162       virsh net-list | grep -E "$network\s+active" > /dev/null || virsh net-start $network
163       virsh net-list | grep -E "$network\s+active\s+yes" > /dev/null || virsh net-autostart --network $network
164     done
165
166     echo -e "${blue}INFO: Bridges set: ${reset}"
167     ovs-vsctl list-br
168
169     # bridge interfaces to correct OVS instances for baremetal deployment
170     for network in ${enabled_network_list}; do
171       if [[ "$network" != "admin_network" && "$network" != "public_network" ]]; then
172         continue
173       fi
174       this_interface=$(eval echo \${${network}_bridged_interface})
175       # check if this a bridged interface for this network
176       if [[ ! -z "$this_interface" || "$this_interface" != "none" ]]; then
177         if ! attach_interface_to_ovs ${NET_MAP[$network]} ${this_interface} ${network}; then
178           echo -e "${red}ERROR: Unable to bridge interface ${this_interface} to bridge ${NET_MAP[$network]} for enabled network: ${network}${reset}"
179           exit 1
180         else
181           echo -e "${blue}INFO: Interface ${this_interface} bridged to bridge ${NET_MAP[$network]} for enabled network: ${network}${reset}"
182         fi
183       else
184         echo "${red}ERROR: Unable to determine interface to bridge to for enabled network: ${network}${reset}"
185         exit 1
186       fi
187     done
188   else
189     for network in ${OPNFV_NETWORK_TYPES}; do
190       echo "${blue}INFO: Creating Virsh Network: $network${reset}"
191       virsh net-list --all | grep $network > /dev/null || (cat > ${libvirt_dir}/apex-virsh-net.xml && virsh net-define ${libvirt_dir}/apex-virsh-net.xml) << EOF
192 <network ipv6='yes'>
193 <name>$network</name>
194 <bridge name='${NET_MAP[$network]}'/>
195 </network>
196 EOF
197       if ! (virsh net-list --all | grep $network > /dev/null); then
198           echo "${red}ERROR: unable to create network: ${network}${reset}"
199           exit 1;
200       fi
201       rm -f ${libvirt_dir}/apex-virsh-net.xml &> /dev/null;
202       virsh net-list | grep -E "$network\s+active" > /dev/null || virsh net-start $network
203       virsh net-list | grep -E "$network\s+active\s+yes" > /dev/null || virsh net-autostart --network $network
204     done
205
206     echo -e "${blue}INFO: Bridges set: ${reset}"
207     brctl show
208   fi
209
210   echo -e "${blue}INFO: virsh networks set: ${reset}"
211   virsh net-list
212
213   # ensure storage pool exists and is started
214   virsh pool-list --all | grep default > /dev/null || virsh pool-define-as --name default dir --target /var/lib/libvirt/images
215   virsh pool-list | grep -Eo "default\s+active" > /dev/null || (virsh pool-autostart default; virsh pool-start default)
216
217   if ! egrep '^flags.*(vmx|svm)' /proc/cpuinfo > /dev/null; then
218     echo "${red}virtualization extensions not found, kvm kernel module insertion may fail.\n  \
219 Are you sure you have enabled vmx in your bios or hypervisor?${reset}"
220   fi
221
222   if ! lsmod | grep kvm > /dev/null; then modprobe kvm; fi
223   if ! lsmod | grep kvm_intel > /dev/null; then modprobe kvm_intel; fi
224
225   if ! lsmod | grep kvm > /dev/null; then
226     echo "${red}kvm kernel modules not loaded!${reset}"
227     return 1
228   fi
229
230   ##sshkeygen for root
231   if [ ! -e ~/.ssh/id_rsa.pub ]; then
232     ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
233   fi
234
235   echo "${blue}All dependencies installed and running${reset}"
236 }
237
238 ##verify vm exists, an has a dhcp lease assigned to it
239 ##params: none
240 function setup_undercloud_vm {
241   if ! virsh list --all | grep undercloud > /dev/null; then
242       undercloud_nets="default admin_network"
243       if [[ $enabled_network_list =~ "public_network" ]]; then
244         undercloud_nets+=" public_network"
245       fi
246       define_vm undercloud hd 30 "$undercloud_nets" 4 12288
247
248       ### this doesn't work for some reason I was getting hangup events so using cp instead
249       #virsh vol-upload --pool default --vol undercloud.qcow2 --file $CONFIG/stack/undercloud.qcow2
250       #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)
251       #2015-12-05 12:57:20.569+0000: 8755: warning : virKeepAliveTimerInternal:143 : No response from client 0x7ff1e231e630 after 6 keepalive messages in 35 seconds
252       #2015-12-05 12:57:20.569+0000: 8756: warning : virKeepAliveTimerInternal:143 : No response from client 0x7ff1e231e630 after 6 keepalive messages in 35 seconds
253       #error: cannot close volume undercloud.qcow2
254       #error: internal error: received hangup / error event on socket
255       #error: Reconnected to the hypervisor
256
257       local undercloud_dst=/var/lib/libvirt/images/undercloud.qcow2
258       cp -f $RESOURCES/undercloud.qcow2 $undercloud_dst
259
260       # resize Undercloud machine
261       echo "Checking if Undercloud needs to be resized..."
262       undercloud_size=$(LIBGUESTFS_BACKEND=direct virt-filesystems --long -h --all -a $undercloud_dst |grep device | grep -Eo "[0-9\.]+G" | sed -n 's/\([0-9][0-9]*\).*/\1/p')
263       if [ "$undercloud_size" -lt 30 ]; then
264         qemu-img resize /var/lib/libvirt/images/undercloud.qcow2 +25G
265         LIBGUESTFS_BACKEND=direct virt-resize --expand /dev/sda1 $RESOURCES/undercloud.qcow2 $undercloud_dst
266         LIBGUESTFS_BACKEND=direct virt-customize -a $undercloud_dst --run-command 'xfs_growfs -d /dev/sda1 || true'
267         new_size=$(LIBGUESTFS_BACKEND=direct virt-filesystems --long -h --all -a $undercloud_dst |grep filesystem | grep -Eo "[0-9\.]+G" | sed -n 's/\([0-9][0-9]*\).*/\1/p')
268         if [ "$new_size" -lt 30 ]; then
269           echo "Error resizing Undercloud machine, disk size is ${new_size}"
270           exit 1
271         else
272           echo "Undercloud successfully resized"
273         fi
274       else
275         echo "Skipped Undercloud resize, upstream is large enough"
276       fi
277
278   else
279       echo "Found Undercloud VM, using existing VM"
280   fi
281
282   # if the VM is not running update the authkeys and start it
283   if ! virsh list | grep undercloud > /dev/null; then
284     echo "Injecting ssh key to Undercloud VM"
285     LIBGUESTFS_BACKEND=direct virt-customize -a $undercloud_dst --run-command "mkdir -p /root/.ssh/" \
286         --upload ~/.ssh/id_rsa.pub:/root/.ssh/authorized_keys \
287         --run-command "chmod 600 /root/.ssh/authorized_keys && restorecon /root/.ssh/authorized_keys" \
288         --run-command "cp /root/.ssh/authorized_keys /home/stack/.ssh/" \
289         --run-command "chown stack:stack /home/stack/.ssh/authorized_keys && chmod 600 /home/stack/.ssh/authorized_keys"
290     virsh start undercloud
291   fi
292
293   sleep 10 # let undercloud get started up
294
295   # get the undercloud VM IP
296   CNT=10
297   echo -n "${blue}Waiting for Undercloud's dhcp address${reset}"
298   undercloud_mac=$(virsh domiflist undercloud | grep default | awk '{ print $5 }')
299   while ! $(arp -e | grep ${undercloud_mac} > /dev/null) && [ $CNT -gt 0 ]; do
300       echo -n "."
301       sleep 10
302       CNT=$((CNT-1))
303   done
304   UNDERCLOUD=$(arp -e | grep ${undercloud_mac} | awk {'print $1'})
305
306   if [ -z "$UNDERCLOUD" ]; then
307     echo "\n\nCan't get IP for Undercloud. Can Not Continue."
308     exit 1
309   else
310      echo -e "${blue}\rUndercloud VM has IP $UNDERCLOUD${reset}"
311   fi
312
313   CNT=10
314   echo -en "${blue}\rValidating Undercloud VM connectivity${reset}"
315   while ! ping -c 1 $UNDERCLOUD > /dev/null && [ $CNT -gt 0 ]; do
316       echo -n "."
317       sleep 3
318       CNT=$((CNT-1))
319   done
320   if [ "$CNT" -eq 0 ]; then
321       echo "Failed to contact Undercloud. Can Not Continue"
322       exit 1
323   fi
324   CNT=10
325   while ! ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "echo ''" 2>&1> /dev/null && [ $CNT -gt 0 ]; do
326       echo -n "."
327       sleep 3
328       CNT=$((CNT-1))
329   done
330   if [ "$CNT" -eq 0 ]; then
331       echo "Failed to connect to Undercloud. Can Not Continue"
332       exit 1
333   fi
334
335   # extra space to overwrite the previous connectivity output
336   echo -e "${blue}\r                                                                 ${reset}"
337   sleep 1
338
339   # ssh key fix for stack user
340   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "restorecon -r /home/stack"
341 }
342
343 ##Create virtual nodes in virsh
344 ##params: vcpus, ramsize
345 function setup_virtual_baremetal {
346   local vcpus ramsize
347   if [ -z "$1" ]; then
348     vcpus=4
349     ramsize=8192
350   elif [ -z "$2" ]; then
351     vcpus=$1
352     ramsize=8192
353   else
354     vcpus=$1
355     ramsize=$(($2*1024))
356   fi
357   #start by generating the opening json for instackenv.json
358   cat > $CONFIG/instackenv-virt.json << EOF
359 {
360   "nodes": [
361 EOF
362
363   # next create the virtual machines and add their definitions to the file
364   if [ "$ha_enabled" == "False" ]; then
365       # 1 controller + computes
366       # zero based so just pass compute count
367       vm_index=$VM_COMPUTES
368   else
369       # 3 controller + computes
370       # zero based so add 2 to compute count
371       vm_index=$((2+$VM_COMPUTES))
372   fi
373
374   for i in $(seq 0 $vm_index); do
375     if ! virsh list --all | grep baremetal${i} > /dev/null; then
376       define_vm baremetal${i} network 41 'admin_network' $vcpus $ramsize
377       for n in private_network public_network storage_network api_network; do
378         if [[ $enabled_network_list =~ $n ]]; then
379           echo -n "$n "
380           virsh attach-interface --domain baremetal${i} --type network --source $n --model virtio --config
381         fi
382       done
383     else
384       echo "Found Baremetal ${i} VM, using existing VM"
385     fi
386     #virsh vol-list default | grep baremetal${i} 2>&1> /dev/null || virsh vol-create-as default baremetal${i}.qcow2 41G --format qcow2
387     mac=$(virsh domiflist baremetal${i} | grep admin_network | awk '{ print $5 }')
388
389     if [ "$VM_COMPUTES" -gt 0 ]; then
390       capability="profile:compute"
391       VM_COMPUTES=$((VM_COMPUTES - 1))
392     else
393       capability="profile:control"
394     fi
395
396     cat >> $CONFIG/instackenv-virt.json << EOF
397     {
398       "pm_addr": "192.168.122.1",
399       "pm_user": "root",
400       "pm_password": "INSERT_STACK_USER_PRIV_KEY",
401       "pm_type": "pxe_ssh",
402       "mac": [
403         "$mac"
404       ],
405       "cpu": "$vcpus",
406       "memory": "$ramsize",
407       "disk": "41",
408       "arch": "x86_64",
409       "capabilities": "$capability"
410     },
411 EOF
412   done
413
414   #truncate the last line to remove the comma behind the bracket
415   tail -n 1 $CONFIG/instackenv-virt.json | wc -c | xargs -I {} truncate $CONFIG/instackenv-virt.json -s -{}
416
417   #finally reclose the bracket and close the instackenv.json file
418   cat >> $CONFIG/instackenv-virt.json << EOF
419     }
420   ],
421   "arch": "x86_64",
422   "host-ip": "192.168.122.1",
423   "power_manager": "nova.virt.baremetal.virtual_power_driver.VirtualPowerManager",
424   "seed-ip": "",
425   "ssh-key": "INSERT_STACK_USER_PRIV_KEY",
426   "ssh-user": "root"
427 }
428 EOF
429   #Overwrite the tripleo-inclubator domain.xml with our own, keeping a backup.
430   if [ ! -f /usr/share/tripleo/templates/domain.xml.bak ]; then
431     /usr/bin/mv -f /usr/share/tripleo/templates/domain.xml /usr/share/tripleo/templates/domain.xml.bak
432   fi
433
434   /usr/bin/cp -f $LIB/installer/domain.xml /usr/share/tripleo/templates/domain.xml
435 }
436
437 ##Create virtual nodes in virsh
438 ##params: name - String: libvirt name for VM
439 ##        bootdev - String: boot device for the VM
440 ##        disksize - Number: size of the disk in GB
441 ##        ovs_bridges: - List: list of ovs bridges
442 ##        vcpus - Number of VCPUs to use (defaults to 4)
443 ##        ramsize - Size of RAM for VM in MB (defaults to 8192)
444 function define_vm () {
445   local vcpus ramsize
446
447   if [ -z "$5" ]; then
448     vcpus=4
449     ramsize=8388608
450   elif [ -z "$6" ]; then
451     vcpus=$5
452     ramsize=8388608
453   else
454     vcpus=$5
455     ramsize=$(($6*1024))
456   fi
457
458   # Create the libvirt storage volume
459   if virsh vol-list default | grep ${1}.qcow2 2>&1> /dev/null; then
460     volume_path=$(virsh vol-path --pool default ${1}.qcow2 || echo "/var/lib/libvirt/images/${1}.qcow2")
461     echo "Volume ${1} exists. Deleting Existing Volume $volume_path"
462     virsh vol-dumpxml ${1}.qcow2 --pool default > /dev/null || echo '' #ok for this to fail
463     touch $volume_path
464     virsh vol-delete ${1}.qcow2 --pool default
465   fi
466   virsh vol-create-as default ${1}.qcow2 ${3}G --format qcow2
467   volume_path=$(virsh vol-path --pool default ${1}.qcow2)
468   if [ ! -f $volume_path ]; then
469       echo "$volume_path Not created successfully... Aborting"
470       exit 1
471   fi
472
473   # create the VM
474   /usr/libexec/openstack-tripleo/configure-vm --name $1 \
475                                               --bootdev $2 \
476                                               --image "$volume_path" \
477                                               --diskbus sata \
478                                               --arch x86_64 \
479                                               --cpus $vcpus \
480                                               --memory $ramsize \
481                                               --libvirt-nic-driver virtio \
482                                               --baremetal-interface $4
483 }
484
485 ##Copy over the glance images and instackenv json file
486 ##params: none
487 function configure_undercloud {
488   local controller_nic_template compute_nic_template
489   echo
490   echo "Copying configuration files to Undercloud"
491   if [[ "$net_isolation_enabled" == "TRUE" ]]; then
492     echo -e "${blue}Network Environment set for Deployment: ${reset}"
493     cat /tmp/network-environment.yaml
494     scp ${SSH_OPTIONS[@]} /tmp/network-environment.yaml "stack@$UNDERCLOUD":
495
496     # check for ODL L3/ONOS
497     if [ "${deploy_options_array['sdn_l3']}" == 'True' ]; then
498       ext_net_type=br-ex
499     fi
500
501     if [ "${deploy_options_array['dataplane']}" == 'ovs_dpdk' ]; then
502       ovs_dpdk_bridge='br-phy'
503     else
504       ovs_dpdk_bridge=''
505     fi
506
507     if ! controller_nic_template=$(python3.4 -B $LIB/python/apex_python_utils.py nic-template -r controller -s $NETSETS -i $net_isolation_enabled -t $CONFIG/nics-template.yaml.jinja2 -n "$enabled_network_list" -e "br-ex" -af $ip_addr_family); then
508       echo -e "${red}ERROR: Failed to generate controller NIC heat template ${reset}"
509       exit 1
510     fi
511
512     if ! compute_nic_template=$(python3.4 -B $LIB/python/apex_python_utils.py nic-template -r compute -s $NETSETS -i $net_isolation_enabled -t $CONFIG/nics-template.yaml.jinja2 -n "$enabled_network_list" -e $ext_net_type -af $ip_addr_family -d "$ovs_dpdk_bridge"); then
513       echo -e "${red}ERROR: Failed to generate compute NIC heat template ${reset}"
514       exit 1
515     fi
516     ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" << EOI
517 mkdir nics/
518 cat > nics/controller.yaml << EOF
519 $controller_nic_template
520 EOF
521 cat > nics/compute.yaml << EOF
522 $compute_nic_template
523 EOF
524 EOI
525   fi
526
527   # ensure stack user on Undercloud machine has an ssh key
528   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "if [ ! -e ~/.ssh/id_rsa.pub ]; then ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa; fi"
529
530   if [ "$virtual" == "TRUE" ]; then
531
532       # copy the Undercloud VM's stack user's pub key to
533       # root's auth keys so that Undercloud can control
534       # vm power on the hypervisor
535       ssh ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "cat /home/stack/.ssh/id_rsa.pub" >> /root/.ssh/authorized_keys
536
537       DEPLOY_OPTIONS+=" --libvirt-type qemu"
538       INSTACKENV=$CONFIG/instackenv-virt.json
539
540       # upload instackenv file to Undercloud for virtual deployment
541       scp ${SSH_OPTIONS[@]} $INSTACKENV "stack@$UNDERCLOUD":instackenv.json
542   fi
543
544   # allow stack to control power management on the hypervisor via sshkey
545   # only if this is a virtual deployment
546   if [ "$virtual" == "TRUE" ]; then
547       ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
548 while read -r line; do
549   stack_key=\${stack_key}\\\\\\\\n\${line}
550 done < <(cat ~/.ssh/id_rsa)
551 stack_key=\$(echo \$stack_key | sed 's/\\\\\\\\n//')
552 sed -i 's~INSERT_STACK_USER_PRIV_KEY~'"\$stack_key"'~' instackenv.json
553 EOI
554   fi
555
556   # copy stack's ssh key to this users authorized keys
557   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "cat /home/stack/.ssh/id_rsa.pub" >> ~/.ssh/authorized_keys
558
559   # disable requiretty for sudo
560   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "sed -i 's/Defaults\s*requiretty//'" /etc/sudoers
561
562   # configure undercloud on Undercloud VM
563   echo "Running undercloud configuration."
564   echo "Logging undercloud configuration to undercloud:/home/stack/apex-undercloud-install.log"
565   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" << EOI
566 if [[ "$net_isolation_enabled" == "TRUE" ]]; then
567   sed -i 's/#local_ip/local_ip/' undercloud.conf
568   sed -i 's/#network_gateway/network_gateway/' undercloud.conf
569   sed -i 's/#network_cidr/network_cidr/' undercloud.conf
570   sed -i 's/#dhcp_start/dhcp_start/' undercloud.conf
571   sed -i 's/#dhcp_end/dhcp_end/' undercloud.conf
572   sed -i 's/#inspection_iprange/inspection_iprange/' undercloud.conf
573   sed -i 's/#undercloud_debug/undercloud_debug/' undercloud.conf
574
575   openstack-config --set undercloud.conf DEFAULT local_ip ${admin_network_provisioner_ip}/${admin_network_cidr##*/}
576   openstack-config --set undercloud.conf DEFAULT network_gateway ${admin_network_provisioner_ip}
577   openstack-config --set undercloud.conf DEFAULT network_cidr ${admin_network_cidr}
578   openstack-config --set undercloud.conf DEFAULT dhcp_start ${admin_network_dhcp_range%%,*}
579   openstack-config --set undercloud.conf DEFAULT dhcp_end ${admin_network_dhcp_range##*,}
580   openstack-config --set undercloud.conf DEFAULT inspection_iprange ${admin_network_introspection_range}
581   openstack-config --set undercloud.conf DEFAULT undercloud_debug false
582
583 fi
584
585 sudo sed -i '/CephClusterFSID:/c\\  CephClusterFSID: \\x27$(cat /proc/sys/kernel/random/uuid)\\x27' /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
586 sudo sed -i '/CephMonKey:/c\\  CephMonKey: \\x27'"\$(ceph-authtool --gen-print-key)"'\\x27' /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
587 sudo sed -i '/CephAdminKey:/c\\  CephAdminKey: \\x27'"\$(ceph-authtool --gen-print-key)"'\\x27' /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml
588
589 # we assume that packages will not need to be updated with undercloud install
590 # and that it will be used only to configure the undercloud
591 # packages updates would need to be handled manually with yum update
592 sudo cp -f /usr/share/diskimage-builder/elements/yum/bin/install-packages /usr/share/diskimage-builder/elements/yum/bin/install-packages.bak
593 cat << 'EOF' | sudo tee /usr/share/diskimage-builder/elements/yum/bin/install-packages > /dev/null
594 #!/bin/sh
595 exit 0
596 EOF
597
598 openstack undercloud install &> apex-undercloud-install.log || {
599     # cat the undercloud install log incase it fails
600     echo "ERROR: openstack undercloud install has failed. Dumping Log:"
601     cat apex-undercloud-install.log
602     exit 1
603 }
604
605 sleep 30
606 sudo systemctl restart openstack-glance-api
607 sudo systemctl restart openstack-nova-conductor
608 sudo systemctl restart openstack-nova-compute
609
610 sudo sed -i '/num_engine_workers/c\num_engine_workers = 2' /etc/heat/heat.conf
611 sudo sed -i '/#workers\s=/c\workers = 2' /etc/heat/heat.conf
612 sudo systemctl restart openstack-heat-engine
613 sudo systemctl restart openstack-heat-api
614 EOI
615
616 # configure external network
617   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" << EOI
618 if [[ "$public_network_vlan" != "native" ]]; then
619   cat <<EOF > /etc/sysconfig/network-scripts/ifcfg-vlan${public_network_vlan}
620 DEVICE=vlan${public_network_vlan}
621 ONBOOT=yes
622 DEVICETYPE=ovs
623 TYPE=OVSIntPort
624 BOOTPROTO=static
625 IPADDR=${public_network_provisioner_ip}
626 PREFIX=${public_network_cidr##*/}
627 OVS_BRIDGE=br-ctlplane
628 OVS_OPTIONS="tag=${public_network_vlan}"
629 EOF
630   ifup vlan${public_network_vlan}
631 else
632   if ! ip a s eth2 | grep ${public_network_provisioner_ip} > /dev/null; then
633       ip a a ${public_network_provisioner_ip}/${public_network_cidr##*/} dev eth2
634       ip link set up dev eth2
635   fi
636 fi
637 EOI
638
639 # WORKAROUND: must restart the above services to fix sync problem with nova compute manager
640 # TODO: revisit and file a bug if necessary. This should eventually be removed
641 # as well as glance api problem
642 echo -e "${blue}INFO: Sleeping 15 seconds while services come back from restart${reset}"
643 sleep 15
644
645 }
646
647 ##preping it for deployment and launch the deploy
648 ##params: none
649 function undercloud_prep_overcloud_deploy {
650   if [[ "${#deploy_options_array[@]}" -eq 0 || "${deploy_options_array['sdn_controller']}" == 'opendaylight' ]]; then
651     if [ "${deploy_options_array['sdn_l3']}" == 'True' ]; then
652       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight_l3.yaml"
653     elif [ "${deploy_options_array['sfc']}" == 'True' ]; then
654       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight_sfc.yaml"
655     elif [ "${deploy_options_array['vpn']}" == 'True' ]; then
656       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight_sdnvpn.yaml"
657     elif [ "${deploy_options_array['vpp']}" == 'True' ]; then
658       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight_fdio.yaml"
659     else
660       DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight.yaml"
661     fi
662     SDN_IMAGE=opendaylight
663     if [ "${deploy_options_array['sfc']}" == 'True' ]; then
664       SDN_IMAGE+=-sfc
665       if [ ! -f $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 ]; then
666           echo "${red} $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 is required to execute an SFC deployment."
667           echo "Please install the opnfv-apex-opendaylight-sfc package to provide this overcloud image for deployment.${reset}"
668           exit 1
669       fi
670     fi
671   elif [ "${deploy_options_array['sdn_controller']}" == 'opendaylight-external' ]; then
672     DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/opendaylight-external.yaml"
673     SDN_IMAGE=opendaylight
674   elif [ "${deploy_options_array['sdn_controller']}" == 'onos' ]; then
675     DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/onos.yaml"
676     SDN_IMAGE=onos
677   elif [ "${deploy_options_array['sdn_controller']}" == 'opencontrail' ]; then
678     echo -e "${red}ERROR: OpenContrail is currently unsupported...exiting${reset}"
679     exit 1
680   elif [[ -z "${deploy_options_array['sdn_controller']}" || "${deploy_options_array['sdn_controller']}" == 'False' ]]; then
681     echo -e "${blue}INFO: SDN Controller disabled...will deploy nosdn scenario${reset}"
682     SDN_IMAGE=opendaylight
683   else
684     echo "${red}Invalid sdn_controller: ${deploy_options_array['sdn_controller']}${reset}"
685     echo "${red}Valid choices are opendaylight, opendaylight-external, onos, opencontrail, False, or null${reset}"
686     exit 1
687   fi
688
689
690
691   # Make sure the correct overcloud image is available
692   if [ ! -f $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 ]; then
693       echo "${red} $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 is required to execute your deployment."
694       echo "Both ONOS and OpenDaylight are currently deployed from this image."
695       echo "Please install the opnfv-apex package to provide this overcloud image for deployment.${reset}"
696       exit 1
697   fi
698
699   echo "Copying overcloud image to Undercloud"
700   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "rm -f overcloud-full.qcow2"
701   scp ${SSH_OPTIONS[@]} $RESOURCES/overcloud-full-${SDN_IMAGE}.qcow2 "stack@$UNDERCLOUD":overcloud-full.qcow2
702
703   # Install ovs-dpdk inside the overcloud image if it is enabled.
704   if [ "${deploy_options_array['dataplane']}" == 'ovs_dpdk' ]; then
705     # install dpdk packages before ovs
706     echo -e "${blue}INFO: Enabling kernel modules for dpdk inside overcloud image${reset}"
707
708     ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
709       cat << EOF > vfio_pci.modules
710 #!/bin/bash
711 exec /sbin/modprobe vfio_pci >/dev/null 2>&1
712 EOF
713
714       cat << EOF > uio_pci_generic.modules
715 #!/bin/bash
716 exec /sbin/modprobe uio_pci_generic >/dev/null 2>&1
717 EOF
718
719       LIBGUESTFS_BACKEND=direct virt-customize --upload vfio_pci.modules:/etc/sysconfig/modules/ \
720                                                --upload uio_pci_generic.modules:/etc/sysconfig/modules/ \
721                                                --run-command "chmod 0755 /etc/sysconfig/modules/vfio_pci.modules" \
722                                                --run-command "chmod 0755 /etc/sysconfig/modules/uio_pci_generic.modules" \
723                                                --run-command "yum install -y /root/dpdk_rpms/*" \
724                                                -a overcloud-full.qcow2
725 EOI
726   elif [ "${deploy_options_array['dataplane']}" != 'ovs' ]; then
727     echo "${red}${deploy_options_array['dataplane']} not supported${reset}"
728     exit 1
729   fi
730
731   # Set ODL version accordingly
732   if [[ "${deploy_options_array['sdn_controller']}" == 'opendaylight' && "${deploy_options_array['odl_version']}" == 'boron' ]]; then
733     ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
734       LIBGUESTFS_BACKEND=direct virt-customize --run-command "yum -y remove opendaylight" \
735                                                --run-command "yum -y install /root/boron/*" \
736                                                -a overcloud-full.qcow2
737 EOI
738   fi
739
740   # Add performance deploy options if they have been set
741   if [ ! -z "${deploy_options_array['performance']}" ]; then
742
743     # Remove previous kernel args files per role
744     ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "rm -f Compute-kernel_params.txt"
745     ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "rm -f Controller-kernel_params.txt"
746
747     # Push performance options to subscript to modify per-role images as needed
748     for option in "${performance_options[@]}" ; do
749       echo -e "${blue}Setting performance option $option${reset}"
750       ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "bash build_perf_image.sh $option"
751     done
752
753     # Build IPA kernel option ramdisks
754     ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" <<EOI
755 /bin/cp -f /home/stack/ironic-python-agent.initramfs /root/
756 mkdir -p ipa/
757 pushd ipa
758 gunzip -c ../ironic-python-agent.initramfs | cpio -i
759 if [ ! -f /home/stack/Compute-kernel_params.txt ]; then
760   touch /home/stack/Compute-kernel_params.txt
761   chown stack /home/stack/Compute-kernel_params.txt
762 fi
763 /bin/cp -f /home/stack/Compute-kernel_params.txt tmp/kernel_params.txt
764 echo "Compute params set: "
765 cat tmp/kernel_params.txt
766 /bin/cp -f /root/image.py usr/lib/python2.7/site-packages/ironic_python_agent/extensions/image.py
767 /bin/cp -f /root/image.pyc usr/lib/python2.7/site-packages/ironic_python_agent/extensions/image.pyc
768 find . | cpio -o -H newc | gzip > /home/stack/Compute-ironic-python-agent.initramfs
769 chown stack /home/stack/Compute-ironic-python-agent.initramfs
770 if [ ! -f /home/stack/Controller-kernel_params.txt ]; then
771   touch /home/stack/Controller-kernel_params.txt
772   chown stack /home/stack/Controller-kernel_params.txt
773 fi
774 /bin/cp -f /home/stack/Controller-kernel_params.txt tmp/kernel_params.txt
775 echo "Controller params set: "
776 cat tmp/kernel_params.txt
777 find . | cpio -o -H newc | gzip > /home/stack/Controller-ironic-python-agent.initramfs
778 chown stack /home/stack/Controller-ironic-python-agent.initramfs
779 popd
780 /bin/rm -rf ipa/
781 EOI
782
783     DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/numa.yaml"
784   fi
785
786   # make sure ceph is installed
787   DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/storage-environment.yaml"
788
789   # scale compute nodes according to inventory
790   total_nodes=$(ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "cat /home/stack/instackenv.json | grep -c memory")
791
792   # check if HA is enabled
793   if [[ "$ha_enabled" == "True" ]]; then
794      DEPLOY_OPTIONS+=" --control-scale 3"
795      compute_nodes=$((total_nodes - 3))
796      DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/puppet-pacemaker.yaml"
797   else
798      compute_nodes=$((total_nodes - 1))
799   fi
800
801   if [ "$compute_nodes" -le 0 ]; then
802     echo -e "${red}ERROR: Invalid number of compute nodes: ${compute_nodes}. Check your inventory file.${reset}"
803     exit 1
804   else
805     echo -e "${blue}INFO: Number of compute nodes set for deployment: ${compute_nodes}${reset}"
806     DEPLOY_OPTIONS+=" --compute-scale ${compute_nodes}"
807   fi
808
809   if [[ "$net_isolation_enabled" == "TRUE" ]]; then
810      #DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/network-isolation.yaml"
811      DEPLOY_OPTIONS+=" -e network-environment.yaml"
812   fi
813
814   if [[ "$ha_enabled" == "True" ]] || [[ "$net_isolation_enabled" == "TRUE" ]]; then
815      DEPLOY_OPTIONS+=" --ntp-server $ntp_server"
816   fi
817
818   if [[ ! "$virtual" == "TRUE" ]]; then
819      DEPLOY_OPTIONS+=" --control-flavor control --compute-flavor compute"
820   else
821      DEPLOY_OPTIONS+=" -e virtual-environment.yaml"
822   fi
823
824   DEPLOY_OPTIONS+=" -e opnfv-environment.yaml"
825
826   echo -e "${blue}INFO: Deploy options set:\n${DEPLOY_OPTIONS}${reset}"
827
828   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
829 if [ "$debug" == 'TRUE' ]; then
830     LIBGUESTFS_BACKEND=direct virt-customize -a overcloud-full.qcow2 --root-password password:opnfvapex
831 fi
832
833 source stackrc
834 set -o errexit
835 echo "Uploading overcloud glance images"
836 openstack overcloud image upload
837
838 echo "Configuring undercloud and discovering nodes"
839 openstack baremetal import --json instackenv.json
840 openstack baremetal configure boot
841 bash -x set_perf_images.sh ${performance_roles[@]}
842 #if [[ -z "$virtual" ]]; then
843 #  openstack baremetal introspection bulk start
844 #fi
845 echo "Configuring flavors"
846 for flavor in baremetal control compute; do
847   echo -e "${blue}INFO: Updating flavor: \${flavor}${reset}"
848   if openstack flavor list | grep \${flavor}; then
849     openstack flavor delete \${flavor}
850   fi
851   openstack flavor create --id auto --ram 4096 --disk 39 --vcpus 1 \${flavor}
852   if ! openstack flavor list | grep \${flavor}; then
853     echo -e "${red}ERROR: Unable to create flavor \${flavor}${reset}"
854   fi
855 done
856 openstack flavor set --property "cpu_arch"="x86_64" --property "capabilities:boot_option"="local" baremetal
857 openstack flavor set --property "cpu_arch"="x86_64" --property "capabilities:boot_option"="local" --property "capabilities:profile"="control" control
858 openstack flavor set --property "cpu_arch"="x86_64" --property "capabilities:boot_option"="local" --property "capabilities:profile"="compute" compute
859 echo "Configuring nameserver on ctlplane network"
860 dns_server_ext=''
861 for dns_server in ${dns_servers}; do
862   dns_server_ext="\${dns_server_ext} --dns-nameserver \${dns_server}"
863 done
864 neutron subnet-update \$(neutron subnet-list | grep -Ev "id|tenant|external|storage" | grep -v \\\\-\\\\- | awk {'print \$2'}) \${dns_server_ext}
865 echo "Executing overcloud deployment, this should run for an extended period without output."
866 sleep 60 #wait for Hypervisor stats to check-in to nova
867 # save deploy command so it can be used for debugging
868 cat > deploy_command << EOF
869 openstack overcloud deploy --templates $DEPLOY_OPTIONS --timeout 90
870 EOF
871 EOI
872
873   if [ "$interactive" == "TRUE" ]; then
874     if ! prompt_user "Overcloud Deployment"; then
875       echo -e "${blue}INFO: User requests exit${reset}"
876       exit 0
877     fi
878   fi
879
880   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
881 source stackrc
882 openstack overcloud deploy --templates $DEPLOY_OPTIONS --timeout 90
883 if ! heat stack-list | grep CREATE_COMPLETE 1>/dev/null; then
884   $(typeset -f debug_stack)
885   debug_stack
886   exit 1
887 fi
888 EOI
889
890   # Configure DPDK
891   if [ "${deploy_options_array['dataplane']}" == 'ovs_dpdk' ]; then
892     ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI || (echo "DPDK config failed, exiting..."; exit 1)
893 source stackrc
894 set -o errexit
895 for node in \$(nova list | grep novacompute | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"); do
896 echo "Running DPDK test app on \$node"
897 ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" <<EOF
898 set -o errexit
899 sudo dpdk_helloworld --no-pci
900 sudo dpdk_nic_bind -s
901 EOF
902 done
903 EOI
904   fi
905
906   if [ "$debug" == 'TRUE' ]; then
907       ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
908 source overcloudrc
909 echo "Keystone Endpoint List:"
910 openstack endpoint list
911 echo "Keystone Service List"
912 openstack service list
913 cinder quota-show \$(openstack project list | grep admin | awk {'print \$2'})
914 EOI
915   fi
916 }
917
918 ##Post configuration after install
919 ##params: none
920 function configure_post_install {
921   local opnfv_attach_networks ovs_ip ip_range net_cidr tmp_ip
922   opnfv_attach_networks="admin_network public_network"
923
924   echo -e "${blue}INFO: Post Install Configuration Running...${reset}"
925
926   echo -e "${blue}INFO: Configuring ssh for root to overcloud nodes...${reset}"
927   # copy host key to instack
928   scp ${SSH_OPTIONS[@]} /root/.ssh/id_rsa.pub "stack@$UNDERCLOUD":jumphost_id_rsa.pub
929
930   # add host key to overcloud nodes authorized keys
931   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" << EOI
932 source stackrc
933 nodes=\$(nova list | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
934 for node in \$nodes; do
935 cat ~/jumphost_id_rsa.pub | ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" 'cat >> ~/.ssh/authorized_keys'
936 done
937 EOI
938
939   if [ "${deploy_options_array['dataplane']}" == 'ovs_dpdk' ]; then
940     echo -e "${blue}INFO: Bringing up br-phy and ovs-agent for dpdk compute nodes...${reset}"
941     compute_nodes=$(undercloud_connect stack "source stackrc; nova list | grep compute | wc -l")
942     i=0
943     while [ "$i" -lt "$compute_nodes" ]; do
944       overcloud_connect compute${i} "sudo ifup br-phy; sudo systemctl restart neutron-openvswitch-agent"
945       i=$((i + 1))
946     done
947   fi
948
949   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
950 source overcloudrc
951 set -o errexit
952 echo "Configuring Neutron external network"
953 neutron net-create external --router:external=True --tenant-id \$(openstack project show service | grep id | awk '{ print \$4 }')
954 neutron subnet-create --name external-net --tenant-id \$(openstack project show service | grep id | awk '{ print \$4 }') --disable-dhcp external --gateway ${public_network_gateway} --allocation-pool start=${public_network_floating_ip_range%%,*},end=${public_network_floating_ip_range##*,} ${public_network_cidr}
955
956 echo "Removing sahara endpoint and service"
957 sahara_service_id=\$(openstack service list | grep sahara | cut -d ' ' -f 2)
958 sahara_endpoint_id=\$(openstack endpoint list | grep sahara | cut -d ' ' -f 2)
959 openstack endpoint delete \$sahara_endpoint_id
960 openstack service delete \$sahara_service_id
961
962 echo "Removing swift endpoint and service"
963 swift_service_id=\$(openstack service list | grep swift | cut -d ' ' -f 2)
964 swift_endpoint_id=\$(openstack endpoint list | grep swift | cut -d ' ' -f 2)
965 openstack endpoint delete \$swift_endpoint_id
966 openstack service delete \$swift_service_id
967
968 if [ "${deploy_options_array['congress']}" == 'True' ]; then
969     for s in nova neutronv2 ceilometer cinder glancev2 keystone; do
970         openstack congress datasource create \$s "\$s" \\
971             --config username=\$OS_USERNAME \\
972             --config tenant_name=\$OS_TENANT_NAME \\
973             --config password=\$OS_PASSWORD \\
974             --config auth_url=\$OS_AUTH_URL
975     done
976 fi
977 EOI
978
979   echo -e "${blue}INFO: Checking if OVS bridges have IP addresses...${reset}"
980   for network in ${opnfv_attach_networks}; do
981     ovs_ip=$(find_ip ${NET_MAP[$network]})
982     tmp_ip=''
983     if [ -n "$ovs_ip" ]; then
984       echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} has IP address ${ovs_ip}${reset}"
985     else
986       echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} missing IP, will configure${reset}"
987       # use last IP of allocation pool
988       eval "ip_range=\${${network}_usable_ip_range}"
989       ovs_ip=${ip_range##*,}
990       eval "net_cidr=\${${network}_cidr}"
991       sudo ip addr add ${ovs_ip}/${net_cidr##*/} dev ${NET_MAP[$network]}
992       sudo ip link set up ${NET_MAP[$network]}
993       tmp_ip=$(find_ip ${NET_MAP[$network]})
994       if [ -n "$tmp_ip" ]; then
995         echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} IP set: ${tmp_ip}${reset}"
996         continue
997       else
998         echo -e "${red}ERROR: Unable to set OVS Bridge ${NET_MAP[$network]} with IP: ${ovs_ip}${reset}"
999         return 1
1000       fi
1001     fi
1002   done
1003
1004   # for virtual, we NAT public network through Undercloud
1005   if [ "$virtual" == "TRUE" ]; then
1006     if ! configure_undercloud_nat ${public_network_cidr}; then
1007       echo -e "${red}ERROR: Unable to NAT undercloud with external net: ${public_network_cidr}${reset}"
1008       exit 1
1009     else
1010       echo -e "${blue}INFO: Undercloud VM has been setup to NAT Overcloud public network${reset}"
1011     fi
1012   fi
1013
1014   # for sfc deployments we need the vxlan workaround
1015   if [ "${deploy_options_array['sfc']}" == 'True' ]; then
1016       ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
1017 source stackrc
1018 set -o errexit
1019 for node in \$(nova list | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"); do
1020 ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" <<EOF
1021 sudo ifconfig br-int up
1022 sudo ip route add 123.123.123.0/24 dev br-int
1023 EOF
1024 done
1025 EOI
1026   fi
1027
1028   # Collect deployment logs
1029   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
1030 mkdir -p ~/deploy_logs
1031 rm -rf deploy_logs/*
1032 source stackrc
1033 set -o errexit
1034 for node in \$(nova list | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"); do
1035  ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" <<EOF
1036  sudo cp /var/log/messages /home/heat-admin/messages.log
1037  sudo chown heat-admin /home/heat-admin/messages.log
1038 EOF
1039 scp ${SSH_OPTIONS[@]} heat-admin@\$node:/home/heat-admin/messages.log ~/deploy_logs/\$node.messages.log
1040 if [ "$debug" == "TRUE" ]; then
1041     nova list --ip \$node
1042     echo "---------------------------"
1043     echo "-----/var/log/messages-----"
1044     echo "---------------------------"
1045     cat ~/deploy_logs/\$node.messages.log
1046     echo "---------------------------"
1047     echo "----------END LOG----------"
1048     echo "---------------------------"
1049 fi
1050  ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" <<EOF
1051  sudo rm -f /home/heat-admin/messages.log
1052 EOF
1053 done
1054
1055 # Print out the undercloud IP and dashboard URL
1056 source stackrc
1057 echo "Undercloud IP: $UNDERCLOUD, please connect by doing 'opnfv-util undercloud'"
1058 echo "Overcloud dashboard available at http://\$(heat output-show overcloud PublicVip | sed 's/"//g')/dashboard"
1059 EOI
1060
1061 }
1062
1063 display_usage() {
1064   echo -e "Usage:\n$0 [arguments] \n"
1065   echo -e "   -d|--deploy-settings : Full path to deploy settings yaml file. Optional.  Defaults to null"
1066   echo -e "   -i|--inventory : Full path to inventory yaml file. Required only for baremetal"
1067   echo -e "   -n|--net-settings : Full path to network settings file. Optional."
1068   echo -e "   -p|--ping-site : site to use to verify IP connectivity. Optional. Defaults to 8.8.8.8"
1069   echo -e "   -v|--virtual : Virtualize overcloud nodes instead of using baremetal."
1070   echo -e "   --flat : disable Network Isolation and use a single flat network for the underlay network."
1071   echo -e "   --no-post-config : disable Post Install configuration."
1072   echo -e "   --debug : enable debug output."
1073   echo -e "   --interactive : enable interactive deployment mode which requires user to confirm steps of deployment."
1074   echo -e "   --virtual-cpus : Number of CPUs to use per Overcloud VM in a virtual deployment (defaults to 4)."
1075   echo -e "   --virtual-ram : Amount of RAM to use per Overcloud VM in GB (defaults to 8)."
1076 }
1077
1078 ##translates the command line parameters into variables
1079 ##params: $@ the entire command line is passed
1080 ##usage: parse_cmd_line() "$@"
1081 parse_cmdline() {
1082   echo -e "\n\n${blue}This script is used to deploy the Apex Installer and Provision OPNFV Target System${reset}\n\n"
1083   echo "Use -h to display help"
1084   sleep 2
1085
1086   while [ "${1:0:1}" = "-" ]
1087   do
1088     case "$1" in
1089         -h|--help)
1090                 display_usage
1091                 exit 0
1092             ;;
1093         -d|--deploy-settings)
1094                 DEPLOY_SETTINGS_FILE=$2
1095                 echo "Deployment Configuration file: $2"
1096                 shift 2
1097             ;;
1098         -i|--inventory)
1099                 INVENTORY_FILE=$2
1100                 shift 2
1101             ;;
1102         -n|--net-settings)
1103                 NETSETS=$2
1104                 echo "Network Settings Configuration file: $2"
1105                 shift 2
1106             ;;
1107         -p|--ping-site)
1108                 ping_site=$2
1109                 echo "Using $2 as the ping site"
1110                 shift 2
1111             ;;
1112         -v|--virtual)
1113                 virtual="TRUE"
1114                 echo "Executing a Virtual Deployment"
1115                 shift 1
1116             ;;
1117         --flat )
1118                 net_isolation_enabled="FALSE"
1119                 echo "Underlay Network Isolation Disabled: using flat configuration"
1120                 shift 1
1121             ;;
1122         --no-post-config )
1123                 post_config="FALSE"
1124                 echo "Post install configuration disabled"
1125                 shift 1
1126             ;;
1127         --debug )
1128                 debug="TRUE"
1129                 echo "Enable debug output"
1130                 shift 1
1131             ;;
1132         --interactive )
1133                 interactive="TRUE"
1134                 echo "Interactive mode enabled"
1135                 shift 1
1136             ;;
1137         --virtual-cpus )
1138                 VM_CPUS=$2
1139                 echo "Number of CPUs per VM set to $VM_CPUS"
1140                 shift 2
1141             ;;
1142         --virtual-ram )
1143                 VM_RAM=$2
1144                 echo "Amount of RAM per VM set to $VM_RAM"
1145                 shift 2
1146             ;;
1147         --virtual-computes )
1148                 VM_COMPUTES=$2
1149                 echo "Virtual Compute nodes set to $VM_COMPUTES"
1150                 shift 2
1151             ;;
1152         *)
1153                 display_usage
1154                 exit 1
1155             ;;
1156     esac
1157   done
1158
1159   if [[ ! -z "$NETSETS" && "$net_isolation_enabled" == "FALSE" ]]; then
1160     echo -e "${red}INFO: Single flat network requested. Only admin_network settings will be used!${reset}"
1161   elif [[ -z "$NETSETS" ]]; then
1162     echo -e "${red}ERROR: You must provide a network_settings file with -n.${reset}"
1163     exit 1
1164   fi
1165
1166   if [[ -n "$virtual" && -n "$INVENTORY_FILE" ]]; then
1167     echo -e "${red}ERROR: You should not specify an inventory with virtual deployments${reset}"
1168     exit 1
1169   fi
1170
1171   if [[ -z "$DEPLOY_SETTINGS_FILE" || ! -f "$DEPLOY_SETTINGS_FILE" ]]; then
1172     echo -e "${red}ERROR: Deploy Settings: ${DEPLOY_SETTINGS_FILE} does not exist! Exiting...${reset}"
1173     exit 1
1174   fi
1175
1176   if [[ ! -z "$NETSETS" && ! -f "$NETSETS" ]]; then
1177     echo -e "${red}ERROR: Network Settings: ${NETSETS} does not exist! Exiting...${reset}"
1178     exit 1
1179   fi
1180
1181   if [[ ! -z "$INVENTORY_FILE" && ! -f "$INVENTORY_FILE" ]]; then
1182     echo -e "{$red}ERROR: Inventory File: ${INVENTORY_FILE} does not exist! Exiting...${reset}"
1183     exit 1
1184   fi
1185
1186   if [[ -z "$virtual" && -z "$INVENTORY_FILE" ]]; then
1187     echo -e "${red}ERROR: You must specify an inventory file for baremetal deployments! Exiting...${reset}"
1188     exit 1
1189   fi
1190
1191   if [[ "$net_isolation_enabled" == "FALSE" && "$post_config" == "TRUE" ]]; then
1192     echo -e "${blue}INFO: Post Install Configuration will be skipped.  It is not supported with --flat${reset}"
1193     post_config="FALSE"
1194   fi
1195
1196 }
1197
1198 ##END FUNCTIONS
1199
1200 main() {
1201   parse_cmdline "$@"
1202   echo -e "${blue}INFO: Parsing network settings file...${reset}"
1203   parse_network_settings
1204   if ! configure_deps; then
1205     echo -e "${red}Dependency Validation Failed, Exiting.${reset}"
1206     exit 1
1207   fi
1208   if [ -n "$DEPLOY_SETTINGS_FILE" ]; then
1209     echo -e "${blue}INFO: Parsing deploy settings file...${reset}"
1210     parse_deploy_settings
1211   fi
1212   setup_undercloud_vm
1213   if [ "$virtual" == "TRUE" ]; then
1214     setup_virtual_baremetal $VM_CPUS $VM_RAM
1215   elif [ -n "$INVENTORY_FILE" ]; then
1216     parse_inventory_file
1217   fi
1218   configure_undercloud
1219   undercloud_prep_overcloud_deploy
1220   if [ "$post_config" == "TRUE" ]; then
1221     if ! configure_post_install; then
1222       echo -e "${red}ERROR:Post Install Configuration Failed, Exiting.${reset}"
1223       exit 1
1224     else
1225       echo -e "${blue}INFO: Post Install Configuration Complete${reset}"
1226     fi
1227   fi
1228   if [[ "${deploy_options_array['sdn_controller']}" == 'onos' ]]; then
1229     if ! onos_update_gw_mac ${public_network_cidr} ${public_network_gateway}; then
1230       echo -e "${red}ERROR:ONOS Post Install Configuration Failed, Exiting.${reset}"
1231       exit 1
1232     else
1233       echo -e "${blue}INFO: ONOS Post Install Configuration Complete${reset}"
1234     fi
1235   fi
1236 }
1237
1238 main "$@"