906196e52d2bd522298ba3e8af2c82e7c1b6efb7
[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   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
940 source overcloudrc
941 set -o errexit
942 echo "Configuring Neutron external network"
943 neutron net-create external --router:external=True --tenant-id \$(openstack project show service | grep id | awk '{ print \$4 }')
944 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}
945
946 echo "Removing sahara endpoint and service"
947 sahara_service_id=\$(openstack service list | grep sahara | cut -d ' ' -f 2)
948 sahara_endpoint_id=\$(openstack endpoint list | grep sahara | cut -d ' ' -f 2)
949 openstack endpoint delete \$sahara_endpoint_id
950 openstack service delete \$sahara_service_id
951
952 echo "Removing swift endpoint and service"
953 swift_service_id=\$(openstack service list | grep swift | cut -d ' ' -f 2)
954 swift_endpoint_id=\$(openstack endpoint list | grep swift | cut -d ' ' -f 2)
955 openstack endpoint delete \$swift_endpoint_id
956 openstack service delete \$swift_service_id
957
958 if [ "${deploy_options_array['congress']}" == 'True' ]; then
959     for s in nova neutronv2 ceilometer cinder glancev2 keystone; do
960         openstack congress datasource create \$s "\$s" \\
961             --config username=\$OS_USERNAME \\
962             --config tenant_name=\$OS_TENANT_NAME \\
963             --config password=\$OS_PASSWORD \\
964             --config auth_url=\$OS_AUTH_URL
965     done
966 fi
967 EOI
968
969   echo -e "${blue}INFO: Checking if OVS bridges have IP addresses...${reset}"
970   for network in ${opnfv_attach_networks}; do
971     ovs_ip=$(find_ip ${NET_MAP[$network]})
972     tmp_ip=''
973     if [ -n "$ovs_ip" ]; then
974       echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} has IP address ${ovs_ip}${reset}"
975     else
976       echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} missing IP, will configure${reset}"
977       # use last IP of allocation pool
978       eval "ip_range=\${${network}_usable_ip_range}"
979       ovs_ip=${ip_range##*,}
980       eval "net_cidr=\${${network}_cidr}"
981       sudo ip addr add ${ovs_ip}/${net_cidr##*/} dev ${NET_MAP[$network]}
982       sudo ip link set up ${NET_MAP[$network]}
983       tmp_ip=$(find_ip ${NET_MAP[$network]})
984       if [ -n "$tmp_ip" ]; then
985         echo -e "${blue}INFO: OVS Bridge ${NET_MAP[$network]} IP set: ${tmp_ip}${reset}"
986         continue
987       else
988         echo -e "${red}ERROR: Unable to set OVS Bridge ${NET_MAP[$network]} with IP: ${ovs_ip}${reset}"
989         return 1
990       fi
991     fi
992   done
993
994   # for virtual, we NAT public network through Undercloud
995   if [ "$virtual" == "TRUE" ]; then
996     if ! configure_undercloud_nat ${public_network_cidr}; then
997       echo -e "${red}ERROR: Unable to NAT undercloud with external net: ${public_network_cidr}${reset}"
998       exit 1
999     else
1000       echo -e "${blue}INFO: Undercloud VM has been setup to NAT Overcloud public network${reset}"
1001     fi
1002   fi
1003
1004   # for sfc deployments we need the vxlan workaround
1005   if [ "${deploy_options_array['sfc']}" == 'True' ]; then
1006       ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
1007 source stackrc
1008 set -o errexit
1009 for node in \$(nova list | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"); do
1010 ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" <<EOF
1011 sudo ifconfig br-int up
1012 sudo ip route add 123.123.123.0/24 dev br-int
1013 EOF
1014 done
1015 EOI
1016   fi
1017
1018   # Collect deployment logs
1019   ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
1020 mkdir -p ~/deploy_logs
1021 rm -rf deploy_logs/*
1022 source stackrc
1023 set -o errexit
1024 for node in \$(nova list | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"); do
1025  ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" <<EOF
1026  sudo cp /var/log/messages /home/heat-admin/messages.log
1027  sudo chown heat-admin /home/heat-admin/messages.log
1028 EOF
1029 scp ${SSH_OPTIONS[@]} heat-admin@\$node:/home/heat-admin/messages.log ~/deploy_logs/\$node.messages.log
1030 if [ "$debug" == "TRUE" ]; then
1031     nova list --ip \$node
1032     echo "---------------------------"
1033     echo "-----/var/log/messages-----"
1034     echo "---------------------------"
1035     cat ~/deploy_logs/\$node.messages.log
1036     echo "---------------------------"
1037     echo "----------END LOG----------"
1038     echo "---------------------------"
1039 fi
1040  ssh -T ${SSH_OPTIONS[@]} "heat-admin@\$node" <<EOF
1041  sudo rm -f /home/heat-admin/messages.log
1042 EOF
1043 done
1044
1045 # Print out the undercloud IP and dashboard URL
1046 source stackrc
1047 echo "Undercloud IP: $UNDERCLOUD, please connect by doing 'opnfv-util undercloud'"
1048 echo "Overcloud dashboard available at http://\$(heat output-show overcloud PublicVip | sed 's/"//g')/dashboard"
1049 EOI
1050
1051 }
1052
1053 display_usage() {
1054   echo -e "Usage:\n$0 [arguments] \n"
1055   echo -e "   -d|--deploy-settings : Full path to deploy settings yaml file. Optional.  Defaults to null"
1056   echo -e "   -i|--inventory : Full path to inventory yaml file. Required only for baremetal"
1057   echo -e "   -n|--net-settings : Full path to network settings file. Optional."
1058   echo -e "   -p|--ping-site : site to use to verify IP connectivity. Optional. Defaults to 8.8.8.8"
1059   echo -e "   -v|--virtual : Virtualize overcloud nodes instead of using baremetal."
1060   echo -e "   --flat : disable Network Isolation and use a single flat network for the underlay network."
1061   echo -e "   --no-post-config : disable Post Install configuration."
1062   echo -e "   --debug : enable debug output."
1063   echo -e "   --interactive : enable interactive deployment mode which requires user to confirm steps of deployment."
1064   echo -e "   --virtual-cpus : Number of CPUs to use per Overcloud VM in a virtual deployment (defaults to 4)."
1065   echo -e "   --virtual-ram : Amount of RAM to use per Overcloud VM in GB (defaults to 8)."
1066 }
1067
1068 ##translates the command line parameters into variables
1069 ##params: $@ the entire command line is passed
1070 ##usage: parse_cmd_line() "$@"
1071 parse_cmdline() {
1072   echo -e "\n\n${blue}This script is used to deploy the Apex Installer and Provision OPNFV Target System${reset}\n\n"
1073   echo "Use -h to display help"
1074   sleep 2
1075
1076   while [ "${1:0:1}" = "-" ]
1077   do
1078     case "$1" in
1079         -h|--help)
1080                 display_usage
1081                 exit 0
1082             ;;
1083         -d|--deploy-settings)
1084                 DEPLOY_SETTINGS_FILE=$2
1085                 echo "Deployment Configuration file: $2"
1086                 shift 2
1087             ;;
1088         -i|--inventory)
1089                 INVENTORY_FILE=$2
1090                 shift 2
1091             ;;
1092         -n|--net-settings)
1093                 NETSETS=$2
1094                 echo "Network Settings Configuration file: $2"
1095                 shift 2
1096             ;;
1097         -p|--ping-site)
1098                 ping_site=$2
1099                 echo "Using $2 as the ping site"
1100                 shift 2
1101             ;;
1102         -v|--virtual)
1103                 virtual="TRUE"
1104                 echo "Executing a Virtual Deployment"
1105                 shift 1
1106             ;;
1107         --flat )
1108                 net_isolation_enabled="FALSE"
1109                 echo "Underlay Network Isolation Disabled: using flat configuration"
1110                 shift 1
1111             ;;
1112         --no-post-config )
1113                 post_config="FALSE"
1114                 echo "Post install configuration disabled"
1115                 shift 1
1116             ;;
1117         --debug )
1118                 debug="TRUE"
1119                 echo "Enable debug output"
1120                 shift 1
1121             ;;
1122         --interactive )
1123                 interactive="TRUE"
1124                 echo "Interactive mode enabled"
1125                 shift 1
1126             ;;
1127         --virtual-cpus )
1128                 VM_CPUS=$2
1129                 echo "Number of CPUs per VM set to $VM_CPUS"
1130                 shift 2
1131             ;;
1132         --virtual-ram )
1133                 VM_RAM=$2
1134                 echo "Amount of RAM per VM set to $VM_RAM"
1135                 shift 2
1136             ;;
1137         --virtual-computes )
1138                 VM_COMPUTES=$2
1139                 echo "Virtual Compute nodes set to $VM_COMPUTES"
1140                 shift 2
1141             ;;
1142         *)
1143                 display_usage
1144                 exit 1
1145             ;;
1146     esac
1147   done
1148
1149   if [[ ! -z "$NETSETS" && "$net_isolation_enabled" == "FALSE" ]]; then
1150     echo -e "${red}INFO: Single flat network requested. Only admin_network settings will be used!${reset}"
1151   elif [[ -z "$NETSETS" ]]; then
1152     echo -e "${red}ERROR: You must provide a network_settings file with -n.${reset}"
1153     exit 1
1154   fi
1155
1156   if [[ -n "$virtual" && -n "$INVENTORY_FILE" ]]; then
1157     echo -e "${red}ERROR: You should not specify an inventory with virtual deployments${reset}"
1158     exit 1
1159   fi
1160
1161   if [[ -z "$DEPLOY_SETTINGS_FILE" || ! -f "$DEPLOY_SETTINGS_FILE" ]]; then
1162     echo -e "${red}ERROR: Deploy Settings: ${DEPLOY_SETTINGS_FILE} does not exist! Exiting...${reset}"
1163     exit 1
1164   fi
1165
1166   if [[ ! -z "$NETSETS" && ! -f "$NETSETS" ]]; then
1167     echo -e "${red}ERROR: Network Settings: ${NETSETS} does not exist! Exiting...${reset}"
1168     exit 1
1169   fi
1170
1171   if [[ ! -z "$INVENTORY_FILE" && ! -f "$INVENTORY_FILE" ]]; then
1172     echo -e "{$red}ERROR: Inventory File: ${INVENTORY_FILE} does not exist! Exiting...${reset}"
1173     exit 1
1174   fi
1175
1176   if [[ -z "$virtual" && -z "$INVENTORY_FILE" ]]; then
1177     echo -e "${red}ERROR: You must specify an inventory file for baremetal deployments! Exiting...${reset}"
1178     exit 1
1179   fi
1180
1181   if [[ "$net_isolation_enabled" == "FALSE" && "$post_config" == "TRUE" ]]; then
1182     echo -e "${blue}INFO: Post Install Configuration will be skipped.  It is not supported with --flat${reset}"
1183     post_config="FALSE"
1184   fi
1185
1186 }
1187
1188 ##END FUNCTIONS
1189
1190 main() {
1191   parse_cmdline "$@"
1192   echo -e "${blue}INFO: Parsing network settings file...${reset}"
1193   parse_network_settings
1194   if ! configure_deps; then
1195     echo -e "${red}Dependency Validation Failed, Exiting.${reset}"
1196     exit 1
1197   fi
1198   if [ -n "$DEPLOY_SETTINGS_FILE" ]; then
1199     echo -e "${blue}INFO: Parsing deploy settings file...${reset}"
1200     parse_deploy_settings
1201   fi
1202   setup_undercloud_vm
1203   if [ "$virtual" == "TRUE" ]; then
1204     setup_virtual_baremetal $VM_CPUS $VM_RAM
1205   elif [ -n "$INVENTORY_FILE" ]; then
1206     parse_inventory_file
1207   fi
1208   configure_undercloud
1209   undercloud_prep_overcloud_deploy
1210   if [ "$post_config" == "TRUE" ]; then
1211     if ! configure_post_install; then
1212       echo -e "${red}ERROR:Post Install Configuration Failed, Exiting.${reset}"
1213       exit 1
1214     else
1215       echo -e "${blue}INFO: Post Install Configuration Complete${reset}"
1216     fi
1217   fi
1218   if [[ "${deploy_options_array['sdn_controller']}" == 'onos' ]]; then
1219     if ! onos_update_gw_mac ${public_network_cidr} ${public_network_gateway}; then
1220       echo -e "${red}ERROR:ONOS Post Install Configuration Failed, Exiting.${reset}"
1221       exit 1
1222     else
1223       echo -e "${blue}INFO: ONOS Post Install Configuration Complete${reset}"
1224     fi
1225   fi
1226 }
1227
1228 main "$@"