f6af1b57a8b776d639ca3ac58f357321cae76e82
[fuel.git] / ci / deploy.sh
1 #!/bin/bash
2 # shellcheck disable=SC2034,SC2154,SC1091
3 set -ex
4 ##############################################################################
5 # Copyright (c) 2017 Ericsson AB, Mirantis Inc., Enea AB and others.
6 # jonas.bjurel@ericsson.com
7 # All rights reserved. This program and the accompanying materials
8 # are made available under the terms of the Apache License, Version 2.0
9 # which accompanies this distribution, and is available at
10 # http://www.apache.org/licenses/LICENSE-2.0
11 ##############################################################################
12
13 ##############################################################################
14 # BEGIN of Exit handlers
15 #
16 do_exit () {
17     clean
18     echo "Exiting ..."
19 }
20 #
21 # End of Exit handlers
22 ##############################################################################
23
24 ##############################################################################
25 # BEGIN of usage description
26 #
27 usage ()
28 {
29 cat << EOF
30 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
31 $(notify "$(basename "$0"): Deploy the Fuel@OPNFV MCP stack" 3)
32
33 $(notify "USAGE:" 2)
34   $(basename "$0") -b base-uri -l lab-name -p pod-name -s deploy-scenario \\
35     [-B PXE Bridge [-B Mgmt Bridge [-B Internal Bridge [-B Public Bridge]]]] \\
36     [-S storage-dir] [-L /path/to/log/file.tar.gz]
37
38 $(notify "OPTIONS:" 2)
39   -b  Base-uri for the stack-configuration structure
40   -B  Bridge(s): 1st usage = PXE, 2nd = Mgmt, 3rd = Internal, 4th = Public
41   -h  Print this message and exit
42   -l  Lab-name
43   -p  Pod-name
44   -s  Deploy-scenario short-name
45   -S  Storage dir for VM images
46   -L  Deployment log path and file name
47
48 $(notify "DISABLED OPTIONS (not yet supported with MCP):" 3)
49   -d  (disabled) Dry-run
50   -e  (disabled) Do not launch environment deployment
51   -f  (disabled) Deploy on existing Salt master
52   -F  (disabled) Do only create a Salt master
53   -i  (disabled) iso url
54   -T  (disabled) Timeout, in minutes, for the deploy.
55
56 $(notify "Description:" 2)
57 Deploys the Fuel@OPNFV stack on the indicated lab resource.
58
59 This script provides the Fuel@OPNFV deployment abstraction.
60 It depends on the OPNFV official configuration directory/file structure
61 and provides a fairly simple mechanism to execute a deployment.
62
63 $(notify "Input parameters to the build script are:" 2)
64 -b Base URI to the configuration directory (needs to be provided in a URI
65    style, it can be a local resource: file:// or a remote resource http(s)://)
66 -B Bridges to be used by deploy script. It can be specified several times,
67    or as a comma separated list of bridges, or both: -B br1 -B br2,br3
68    First occurence sets PXE Brige, next Mgmt, then Internal and Public.
69    For an empty value, the deploy script will use virsh to create the default
70    expected network (e.g. -B pxe,,,public will use existing "pxe" and "public"
71    bridges, respectively create "mgmt" and "internal").
72    Note that a virtual network "mcpcontrol" is always created. For virtual
73    deploys, "mcpcontrol" is also used for PXE, leaving the PXE bridge unused.
74    For baremetal deploys, PXE bridge is used for baremetal node provisioning,
75    while "mcpcontrol" is used to provision the infrastructure VMs only.
76    The default is 'pxebr'.
77 -h Print this message and exit
78 -L Deployment log path and name, eg. -L /home/jenkins/job.log.tar.gz
79 -l Lab name as defined in the configuration directory, e.g. lf
80 -p POD name as defined in the configuration directory, e.g. pod-1
81 -s Deployment-scenario, this points to a short deployment scenario name, which
82    has to be defined in config directory (e.g. os-odl-nofeature-ha).
83 -S Storage dir for VM images, default is mcp/deploy/images
84
85 $(notify "Disabled input parameters (not yet supported with MCP):" 3)
86 -d (disabled) Dry-run - Produce deploy config files, but do not execute deploy
87 -f (disabled) Deploy on existing Salt master
88 -e (disabled) Do not launch environment deployment
89 -F (disabled) Do only create a Salt master
90 -T (disabled) Timeout, in minutes, for the deploy.
91    It defaults to using the DEPLOY_TIMEOUT environment variable when defined.
92 -i (disabled) .iso image to be deployed (needs to be provided in a URI
93    style, it can be a local resource: file:// or a remote resource http(s)://)
94
95 $(notify "[NOTE] sudo & virsh priviledges are needed for this script to run" 3)
96
97 Example:
98
99 $(notify "sudo $(basename "$0") \\
100   -b file:///home/jenkins/lab-config \\
101   -l lf -p pod2 \\
102   -s os-odl-nofeature-ha" 2)
103 EOF
104 }
105
106 #
107 # END of usage description
108 ##############################################################################
109
110 ##############################################################################
111 # BEGIN of colored notification wrapper
112 #
113 notify() {
114     tput setaf "${2:-1}" || true
115     echo -en "${1:-"[WARN] Unsupported opt arg: $3\\n"}"
116     tput sgr0
117 }
118 #
119 # END of colored notification wrapper
120 ##############################################################################
121
122 ##############################################################################
123 # BEGIN of deployment clean-up
124 #
125 clean() {
126     echo "Cleaning up deploy tmp directories"
127 }
128 #
129 # END of deployment clean-up
130 ##############################################################################
131
132 ##############################################################################
133 # BEGIN of variables to customize
134 #
135 SCRIPT_PATH=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")
136 DEPLOY_DIR=$(cd "${SCRIPT_PATH}/../mcp/scripts"; pwd)
137 STORAGE_DIR=$(cd "${SCRIPT_PATH}/../mcp/deploy/images"; pwd)
138 RECLASS_CLUSTER_DIR=$(cd "${SCRIPT_PATH}/../mcp/reclass/classes/cluster"; pwd)
139 DEPLOY_TYPE='baremetal'
140 OPNFV_BRIDGES=('pxebr' 'mgmt' 'internal' 'public')
141 URI_REGEXP='(file|https?|ftp)://.*'
142
143 export SSH_KEY=${SSH_KEY:-"/var/lib/opnfv/mcp.rsa"}
144 export SALT_MASTER=${INSTALLER_IP:-10.20.0.2}
145 export SALT_MASTER_USER=${SALT_MASTER_USER:-ubuntu}
146 export MAAS_IP=${MAAS_IP:-${SALT_MASTER%.*}.3}
147 export MAAS_PXE_NETWORK=${MAAS_PXE_NETWORK:-192.168.11.0}
148
149 # Derivated from above global vars
150 export MCP_CTRL_NETWORK_ROOTSTR=${SALT_MASTER%.*}
151 export MAAS_PXE_NETWORK_ROOTSTR=${MAAS_PXE_NETWORK%.*}
152 export SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ${SSH_KEY}"
153 export SSH_SALT="${SALT_MASTER_USER}@${SALT_MASTER}"
154
155 # Variables below are disabled for now, to be re-introduced or removed later
156 set +x
157 USE_EXISTING_FUEL=''
158 FUEL_CREATION_ONLY=''
159 NO_DEPLOY_ENVIRONMENT=''
160 DRY_RUN=0
161 if ! [ -z "${DEPLOY_TIMEOUT}" ]; then
162     DEPLOY_TIMEOUT="-dt ${DEPLOY_TIMEOUT}"
163 else
164     DEPLOY_TIMEOUT=""
165 fi
166 set -x
167 #
168 # END of variables to customize
169 ##############################################################################
170
171 ##############################################################################
172 # BEGIN of main
173 #
174 set +x
175 OPNFV_BRIDGE_IDX=0
176 while getopts "b:B:dfFl:L:p:s:S:T:i:he" OPTION
177 do
178     case $OPTION in
179         b)
180             BASE_CONFIG_URI=${OPTARG}
181             if [[ ! $BASE_CONFIG_URI =~ ${URI_REGEXP} ]]; then
182                 notify "[ERROR] -b $BASE_CONFIG_URI - invalid URI\n"
183                 usage
184                 exit 1
185             fi
186             ;;
187         B)
188             OIFS=${IFS}
189             IFS=','
190             OPT_BRIDGES=($OPTARG)
191             for bridge in "${OPT_BRIDGES[@]}"; do
192                 if [ -n "${bridge}" ]; then
193                     OPNFV_BRIDGES[${OPNFV_BRIDGE_IDX}]="${bridge}"
194                 fi
195                 OPNFV_BRIDGE_IDX=$((OPNFV_BRIDGE_IDX + 1))
196             done
197             IFS=${OIFS}
198             ;;
199         d)
200             notify '' 3 "${OPTION}"; continue
201             DRY_RUN=1
202             ;;
203         f)
204             notify '' 3 "${OPTION}"; continue
205             USE_EXISTING_FUEL='-nf'
206             ;;
207         F)
208             notify '' 3 "${OPTION}"; continue
209             FUEL_CREATION_ONLY='-fo'
210             ;;
211         e)
212             notify '' 3 "${OPTION}"; continue
213             NO_DEPLOY_ENVIRONMENT='-nde'
214             ;;
215         l)
216             TARGET_LAB=${OPTARG}
217             ;;
218         L)
219             DEPLOY_LOG="${OPTARG}"
220             ;;
221         p)
222             TARGET_POD=${OPTARG}
223             if [[ "${TARGET_POD}" =~ "virtual" ]]; then
224                 DEPLOY_TYPE='virtual'
225             fi
226             ;;
227         s)
228             DEPLOY_SCENARIO=${OPTARG}
229             ;;
230         S)
231             if [[ ${OPTARG} ]]; then
232                 STORAGE_DIR="${OPTARG}"
233             fi
234             ;;
235         T)
236             notify '' 3 "${OPTION}"; continue
237             DEPLOY_TIMEOUT="-dt ${OPTARG}"
238             ;;
239         i)
240             notify '' 3 "${OPTION}"; continue
241             ISO=${OPTARG}
242             if [[ ! $ISO =~ ${URI_REGEXP} ]]; then
243                 notify "[ERROR] -i $ISO - invalid URI\n"
244                 usage
245                 exit 1
246             fi
247             ;;
248         h)
249             usage
250             exit 0
251             ;;
252         *)
253             notify "[ERROR] Arguments not according to new argument style\n"
254             exit 1
255             ;;
256     esac
257 done
258
259 if [[ "$(sudo whoami)" != 'root' ]]; then
260     notify "This script requires sudo rights\n" 1>&2
261     exit 1
262 fi
263
264 if ! virsh list >/dev/null 2>&1; then
265     notify "This script requires hypervisor access\n" 1>&2
266     exit 1
267 fi
268
269 # Validate mandatory arguments are set
270 if [ -z "${TARGET_LAB}" ] || [ -z "${TARGET_POD}" ] || \
271    [ -z "${DEPLOY_SCENARIO}" ]; then
272     notify "[ERROR] At least one of the mandatory args is missing!\n" 1>&2
273     usage
274     exit 1
275 fi
276
277 set -x
278
279 # Enable the automatic exit trap
280 trap do_exit SIGINT SIGTERM EXIT
281
282 # Set no restrictive umask so that Jenkins can remove any residuals
283 umask 0000
284
285 clean
286
287 pushd "${DEPLOY_DIR}" > /dev/null
288 # Prepare the deploy config files based on lab/pod information, deployment
289 # scenario, etc.
290
291 # Install required packages
292 [ -n "$(command -v apt-get)" ] && sudo apt-get install -y \
293   git make rsync mkisofs curl virtinst cpu-checker qemu-kvm
294 [ -n "$(command -v yum)" ] && sudo yum install -y --skip-broken \
295   git make rsync genisoimage curl virt-install qemu-kvm
296
297 if [ "$(uname -i)" = "aarch64" ]; then
298   [ -n "$(command -v apt-get)" ] && sudo apt-get install -y vgabios && \
299   sudo ln -sf /usr/share/vgabios/vgabios.bin /usr/share/qemu/vgabios-stdvga.bin
300   [ -n "$(command -v yum)" ] && sudo yum install -y --skip-broken vgabios
301 fi
302
303 # Check scenario file existence
304 SCENARIO_DIR="../config/scenario"
305 if [ ! -f  "${SCENARIO_DIR}/${DEPLOY_TYPE}/${DEPLOY_SCENARIO}.yaml" ]; then
306     notify "[WARN] ${DEPLOY_SCENARIO}.yaml not found! \
307             Setting simplest scenario (os-nosdn-nofeature-noha)\n" 3
308     DEPLOY_SCENARIO='os-nosdn-nofeature-noha'
309     if [ ! -f  "${SCENARIO_DIR}/${DEPLOY_TYPE}/${DEPLOY_SCENARIO}.yaml" ]; then
310         notify "[ERROR] Scenario definition file is missing!\n" 1>&2
311         exit 1
312     fi
313 fi
314
315 # Check defaults file existence
316 if [ ! -f  "${SCENARIO_DIR}/defaults-$(uname -i).yaml" ]; then
317     notify "[ERROR] Scenario defaults file is missing!\n" 1>&2
318     exit 1
319 fi
320
321 # Get required infra deployment data
322 source lib.sh
323 eval "$(parse_yaml "${SCENARIO_DIR}/defaults-$(uname -i).yaml")"
324 eval "$(parse_yaml "${SCENARIO_DIR}/${DEPLOY_TYPE}/${DEPLOY_SCENARIO}.yaml")"
325
326 export CLUSTER_DOMAIN=${cluster_domain}
327
328 declare -A virtual_nodes_ram virtual_nodes_vcpus
329 for node in "${virtual_nodes[@]}"; do
330     virtual_custom_ram="virtual_${node}_ram"
331     virtual_custom_vcpus="virtual_${node}_vcpus"
332     virtual_nodes_ram[$node]=${!virtual_custom_ram:-$virtual_default_ram}
333     virtual_nodes_vcpus[$node]=${!virtual_custom_vcpus:-$virtual_default_vcpus}
334 done
335
336 # Expand reclass and virsh network templates
337 for tp in "${RECLASS_CLUSTER_DIR}/all-mcp-ocata-common/opnfv/"*.template \
338     net_*.template; do envsubst < "${tp}" > "${tp%.template}"; done
339
340 # Infra setup
341 generate_ssh_key
342 prepare_vms virtual_nodes "${base_image}" "${STORAGE_DIR}"
343 create_networks OPNFV_BRIDGES
344 create_vms virtual_nodes virtual_nodes_ram virtual_nodes_vcpus \
345   OPNFV_BRIDGES "${STORAGE_DIR}"
346 update_mcpcontrol_network
347 start_vms virtual_nodes
348 check_connection
349
350 ./salt.sh
351
352 # Openstack cluster setup
353 for state in "${cluster_states[@]}"; do
354     notify "STATE: ${state}\n" 2
355     # shellcheck disable=SC2086,2029
356     ssh ${SSH_OPTS} "ubuntu@${SALT_MASTER}" \
357         sudo "/root/fuel/mcp/config/states/${state} || true"
358 done
359
360 ./log.sh "${DEPLOY_LOG}"
361
362 popd > /dev/null
363
364 #
365 # END of main
366 ##############################################################################