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