3 # Deploy script to install provisioning server for OPNFV Apex
4 # author: Dan Radez (dradez@redhat.com)
5 # author: Tim Rozet (trozet@redhat.com)
7 # Based on RDO Manager http://www.rdoproject.org
20 ntp_server="pool.ntp.org"
21 net_isolation_enabled="TRUE"
26 SSH_OPTIONS=(-o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o LogLevel=error)
28 RESOURCES=/var/opt/opnfv/stack
30 INSTACKENV=$CONFIG/instackenv.json
31 NETENV=$CONFIG/network-environment.yaml
34 ##verify internet connectivity
36 function verify_internet {
37 if ping -c 2 $ping_site > /dev/null; then
38 if ping -c 2 www.google.com > /dev/null; then
39 echo "${blue}Internet connectivity detected${reset}"
42 echo "${red}Internet connectivity detected, but DNS lookup failed${reset}"
46 echo "${red}No internet connectivity detected${reset}"
51 ##download dependencies if missing and configure host
53 function configure_deps {
54 if ! verify_internet; then
55 echo "${red}Will not download dependencies${reset}"
59 # verify ip forwarding
60 if sysctl net.ipv4.ip_forward | grep 0; then
61 sudo sysctl -w net.ipv4.ip_forward=1
62 sudo sh -c "echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf"
65 # ensure brbm networks are configured
66 systemctl start openvswitch
67 ovs-vsctl list-br | grep brbm > /dev/null || ovs-vsctl add-br brbm
68 virsh net-list --all | grep brbm > /dev/null || virsh net-create $CONFIG/brbm-net.xml
69 virsh net-list | grep -E "brbm\s+active" > /dev/null || virsh net-start brbm
70 ovs-vsctl list-br | grep brbm1 > /dev/null || ovs-vsctl add-br brbm1
71 virsh net-list --all | grep brbm1 > /dev/null || virsh net-create $CONFIG/brbm1-net.xml
72 virsh net-list | grep -E "brbm1\s+active" > /dev/null || virsh net-start brbm1
74 # ensure storage pool exists and is started
75 virsh pool-list --all | grep default > /dev/null || virsh pool-create $CONFIG/default-pool.xml
76 virsh pool-list | grep -Eo "default\s+active" > /dev/null || virsh pool-start default
78 if virsh net-list | grep default > /dev/null; then
79 num_ints_same_subnet=$(ip addr show | grep "inet 192.168.122" | wc -l)
80 if [ "$num_ints_same_subnet" -gt 1 ]; then
81 virsh net-destroy default
82 ##go edit /etc/libvirt/qemu/networks/default.xml
83 sed -i 's/192.168.122/192.168.123/g' /etc/libvirt/qemu/networks/default.xml
84 sed -i 's/192.168.122/192.168.123/g' instackenv-virt.json
86 virsh net-start default
87 virsh net-autostart default
91 if ! egrep '^flags.*(vmx|svm)' /proc/cpuinfo > /dev/null; then
92 echo "${red}virtualization extensions not found, kvm kernel module insertion may fail.\n \
93 Are you sure you have enabled vmx in your bios or hypervisor?${reset}"
96 if ! lsmod | grep kvm > /dev/null; then modprobe kvm; fi
97 if ! lsmod | grep kvm_intel > /dev/null; then modprobe kvm_intel; fi
99 if ! lsmod | grep kvm > /dev/null; then
100 echo "${red}kvm kernel modules not loaded!${reset}"
105 if [ ! -e ~/.ssh/id_rsa.pub ]; then
106 ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
109 echo "${blue}All dependencies installed and running${reset}"
112 ##verify vm exists, an has a dhcp lease assigned to it
114 function setup_instack_vm {
115 if ! virsh list --all | grep instack > /dev/null; then
116 #virsh vol-create default instack.qcow2.xml
117 virsh define $CONFIG/instack.xml
119 #Upload instack image
120 #virsh vol-create default --file instack.qcow2.xml
121 virsh vol-create-as default instack.qcow2 30G --format qcow2
122 virsh vol-upload --pool default --vol instack.qcow2 --file $CONFIG/stack/instack.qcow2
124 sleep 1 # this was to let the copy settle, needed with vol-upload?
127 echo "Found Instack VM, using existing VM"
130 # if the VM is not running update the authkeys and start it
131 if ! virsh list | grep instack > /dev/null; then
132 echo "Injecting ssh key to instack VM"
133 virt-customize -c qemu:///system -d instack --upload ~/.ssh/id_rsa.pub:/root/.ssh/authorized_keys \
134 --run-command "chmod 600 /root/.ssh/authorized_keys && restorecon /root/.ssh/authorized_keys" \
135 --run-command "cp /root/.ssh/authorized_keys /home/stack/.ssh/" \
136 --run-command "chown stack:stack /home/stack/.ssh/authorized_keys && chmod 600 /home/stack/.ssh/authorized_keys"
140 sleep 3 # let DHCP happen
143 echo -n "${blue}Waiting for instack's dhcp address${reset}"
144 while ! grep instack /var/lib/libvirt/dnsmasq/default.leases > /dev/null && [ $CNT -gt 0 ]; do
150 # get the instack VM IP
151 UNDERCLOUD=$(grep instack /var/lib/libvirt/dnsmasq/default.leases | awk '{print $3}' | head -n 1)
152 if -n $UNDERCLOUD; then
153 echo "Never got IP for Instack. Can Not Continue."
156 echo -e "${blue}\rInstack VM has IP $UNDERCLOUD${reset}"
160 echo -en "${blue}\rValidating instack VM connectivity${reset}"
161 while ! ping -c 1 $UNDERCLOUD > /dev/null && [ $CNT -gt 0 ]; do
167 echo "Failed to contact Instack. Can Not Continue"
171 while ! ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "echo ''" 2>&1> /dev/null && [ $CNT -gt 0 ]; do
177 echo "Failed to connect to Instack. Can Not Continue"
181 # extra space to overwrite the previous connectivity output
182 echo -e "${blue}\r ${reset}"
184 #add the instack brbm1 interface
185 virsh attach-interface --domain instack --type network --source brbm1 --model rtl8139 --config --live
187 ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "if ! ip a s eth2 | grep 192.168.37.1 > /dev/null; then ip a a 192.168.37.1/24 dev eth2; ip link set up dev eth2; fi"
189 # ssh key fix for stack user
190 ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "restorecon -r /home/stack"
193 ##Create virtual nodes in virsh
195 function setup_virtual_baremetal {
196 for i in $(seq 0 $vm_index); do
197 if ! virsh list --all | grep baremetalbrbm_brbm1_${i} > /dev/null; then
198 if [ ! -e $CONFIG/baremetalbrbm_brbm1_${i}.xml ]; then
199 define_virtual_node baremetalbrbm_brbm1_${i}
201 virsh define $CONFIG/baremetalbrbm_brbm1_${i}.xml
203 echo "Found Baremetal ${i} VM, using existing VM"
205 virsh vol-list default | grep baremetalbrbm_brbm1_${i} 2>&1> /dev/null || virsh vol-create-as default baremetalbrbm_brbm1_${i}.qcow2 40G --format qcow2
209 ##Copy over the glance images and instack json file
211 function copy_materials {
214 echo "Copying configuration file and disk images to instack"
215 scp ${SSH_OPTIONS[@]} $RESOURCES/deploy-ramdisk-ironic.initramfs "stack@$UNDERCLOUD":
216 scp ${SSH_OPTIONS[@]} $RESOURCES/deploy-ramdisk-ironic.kernel "stack@$UNDERCLOUD":
217 scp ${SSH_OPTIONS[@]} $RESOURCES/ironic-python-agent.initramfs "stack@$UNDERCLOUD":
218 scp ${SSH_OPTIONS[@]} $RESOURCES/ironic-python-agent.kernel "stack@$UNDERCLOUD":
219 scp ${SSH_OPTIONS[@]} $RESOURCES/ironic-python-agent.vmlinuz "stack@$UNDERCLOUD":
220 scp ${SSH_OPTIONS[@]} $RESOURCES/overcloud-full.initrd "stack@$UNDERCLOUD":
221 scp ${SSH_OPTIONS[@]} $RESOURCES/overcloud-full.qcow2 "stack@$UNDERCLOUD":
222 scp ${SSH_OPTIONS[@]} $RESOURCES/overcloud-full.vmlinuz "stack@$UNDERCLOUD":
223 scp ${SSH_OPTIONS[@]} $NETENV "stack@$UNDERCLOUD":
224 scp ${SSH_OPTIONS[@]} $CONFIG/opendaylight.yaml "stack@$UNDERCLOUD":
225 scp ${SSH_OPTIONS[@]} -r $CONFIG/nics/ "stack@$UNDERCLOUD":
228 # when OpenDaylight lands in upstream RDO manager this can be removed
229 # apply the opendaylight patch
230 scp ${SSH_OPTIONS[@]} $CONFIG/opendaylight.patch "root@$UNDERCLOUD":
231 ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "cd /usr/share/openstack-tripleo-heat-templates/; patch -Np1 < /root/opendaylight.patch"
234 # ensure stack user on instack machine has an ssh key
235 ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" "if [ ! -e ~/.ssh/id_rsa.pub ]; then ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa; fi"
237 if [ "$virtual" == "TRUE" ]; then
238 # fix MACs to match new setup
239 for i in $(seq 0 $vm_index); do
240 pyscript="import json
241 data = json.load(open('$CONFIG/instackenv-virt.json'))
242 print data['nodes'][$i]['mac'][0]"
244 old_mac=$(python -c "$pyscript")
245 new_mac=$(virsh dumpxml baremetalbrbm_brbm1_$i | grep "mac address" | cut -d = -f2 | grep -Eo "[0-9a-f:]+")
246 # this doesn't work with multiple vnics on the vms
247 #if [ "$old_mac" != "$new_mac" ]; then
248 # echo "${blue}Modifying MAC for node from $old_mac to ${new_mac}${reset}"
249 # sed -i 's/'"$old_mac"'/'"$new_mac"'/' $CONFIG/instackenv-virt.json
253 DEPLOY_OPTIONS+="--libvirt-type qemu"
254 INSTACKENV=$CONFIG/instackenv-virt.json
255 NETENV=$CONFIG/network-environment.yaml
258 # upload instackenv file to Instack
259 scp ${SSH_OPTIONS[@]} $INSTACKENV "stack@$UNDERCLOUD":instackenv.json
262 # allow stack to control power management on the hypervisor via sshkey
263 # only if this is a virtual deployment
264 if [ "$virtual" == "TRUE" ]; then
265 ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
266 while read -r line; do
267 stack_key=\${stack_key}\\\\\\\\n\${line}
268 done < <(cat ~/.ssh/id_rsa)
269 stack_key=\$(echo \$stack_key | sed 's/\\\\\\\\n//')
270 sed -i 's~INSERT_STACK_USER_PRIV_KEY~'"\$stack_key"'~' instackenv.json
274 # copy stack's ssh key to this users authorized keys
275 ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" "cat /home/stack/.ssh/id_rsa.pub" >> ~/.ssh/authorized_keys
278 ##preping it for deployment and launch the deploy
280 function undercloud_prep_overcloud_deploy {
281 # check if HA is enabled
282 if [ $ha_enabled == "TRUE" ]; then
283 DEPLOY_OPTIONS+=" --control-scale 3 --compute-scale 2"
284 DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/puppet-pacemaker.yaml"
285 DEPLOY_OPTIONS+=" --ntp-server $ntp_server"
288 if [ $net_isolation_enabled == "TRUE" ]; then
289 DEPLOY_OPTIONS+=" -e /usr/share/openstack-tripleo-heat-templates/environments/network-isolation.yaml"
290 DEPLOY_OPTIONS+=" -e network-environment.yaml"
293 ssh -T ${SSH_OPTIONS[@]} "stack@$UNDERCLOUD" <<EOI
296 echo "Uploading overcloud glance images"
297 openstack overcloud image upload
298 echo "Configuring undercloud and discovering nodes"
299 openstack baremetal import --json instackenv.json
300 openstack baremetal configure boot
301 openstack baremetal introspection bulk start
302 echo "Configuring flavors"
303 openstack flavor list | grep baremetal || openstack flavor create --id auto --ram 4096 --disk 39 --vcpus 1 baremetal
304 openstack flavor set --property "cpu_arch"="x86_64" --property "capabilities:boot_option"="local" baremetal
305 echo "Configuring nameserver on ctlplane network"
306 neutron subnet-update \$(neutron subnet-list | grep -v id | grep -v \\\\-\\\\- | awk {'print \$2'}) --dns-nameserver 8.8.8.8
307 echo "Executing overcloud deployment, this should run for an extended period without output."
308 sleep 60 #wait for Hypervisor stats to check-in to nova
309 openstack overcloud deploy --templates $DEPLOY_OPTIONS -e opendaylight.yaml
315 echo -e "Usage:\n$0 [arguments] \n"
316 echo -e " -c|--config : Directory to configuration files. Optional. Defaults to /var/opt/opnfv/ \n"
317 echo -e " -i|--instackenv : Full path to instack environment file. Optional. Defaults to \$CONFIG/instackenv.json \n"
318 echo -e " -n|--netenv : Full path to network environment file. Optional. Defaults to \$CONFIG/network-environment.json \n"
319 echo -e " -p|--ping-site : site to use to verify IP connectivity. Optional. Defaults to 8.8.8.8 \n"
320 echo -e " -r|--resources : Directory to deployment resources. Optional. Defaults to /var/opt/opnfv/stack \n"
321 echo -e " -v|--virtual : Virtualize overcloud nodes instead of using baremetal. \n"
322 echo -e " --no-ha : disable High Availablility deployment scheme, this assumes a single controller and single compute node \n"
323 echo -e " --flat : disable Network Isolation and use a single flat network for the underlay network."
326 ##translates the command line paramaters into variables
327 ##params: $@ the entire command line is passed
328 ##usage: parse_cmd_line() "$@"
330 echo -e "\n\n${blue}This script is used to deploy the Apex Installer and Provision OPNFV Target System${reset}\n\n"
331 echo "Use -h to display help"
334 while [ "${1:0:1}" = "-" ]
343 echo "Deployment Configuration Directory Overridden to: $2"
356 echo "Using $2 as the ping site"
361 echo "Deployment Resources Directory Overridden to: $2"
366 echo "Executing a Virtualized Deployment"
371 echo "HA Deployment Disabled"
375 net_isolation_enabled="FALSE"
376 echo "Underlay Network Isolation Disabled: using flat configuration"
391 if ! configure_deps; then
392 echo "Dependency Validation Failed, Exiting."
395 if [ $virtual == "TRUE" ]; then
396 setup_virtual_baremetal
399 undercloud_prep_overcloud_deploy