baremetal, virtual: Bump kernel to hwe-18.04 (5.0)
[fuel.git] / ci / deploy.sh
1 #!/bin/bash -e
2 # shellcheck disable=SC2034,SC2154,SC1090,SC1091,SC2155
3 ##############################################################################
4 # Copyright (c) 2018 Ericsson AB, Mirantis Inc., Enea AB and others.
5 # jonas.bjurel@ericsson.com
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10 ##############################################################################
11
12 ##############################################################################
13 # BEGIN of Exit handlers
14 #
15 do_exit () {
16     local RC=$?
17     cleanup_mounts > /dev/null 2>&1
18     if [ ${RC} -eq 0 ]; then
19         notify_n "[OK] MCP: Installation of $DEPLOY_SCENARIO finished succesfully!" 2
20     else
21         notify_n "[ERROR] MCP: Installation  of $DEPLOY_SCENARIO threw a fatal error!"
22     fi
23 }
24 #
25 # End of Exit handlers
26 ##############################################################################
27
28 ##############################################################################
29 # BEGIN of usage description
30 #
31 usage ()
32 {
33 cat << EOF
34 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
35 $(notify "$(basename "$0"): Deploy the OPNFV Fuel MCP stack" 3)
36
37 $(notify "USAGE:" 2)
38   $(basename "$0") -l lab-name -p pod-name -s deploy-scenario \\
39     [-b Lab Config Base URI] \\
40     [-S storage-dir] [-L /path/to/log/file.tar.gz] \\
41     [-f] [-F[F]] [-e[e] | -E[E]] [-d] [-D] [-N] [-m] \\
42     [-o operating-system]
43
44 $(notify "OPTIONS:" 2)
45   -b  Base-uri for the stack-configuration structure
46   -d  Dry-run
47   -D  Debug logging
48   -e  Do not launch environment deployment (use twice to skip cloud setup)
49   -E  Remove existing VCP VMs (use twice to redeploy baremetal nodes)
50   -f  Deploy on existing Salt master (use twice or more to skip states)
51   -F  Same as -e, do not launch environment deployment (legacy option)
52   -h  Print this message and exit
53   -l  Lab-name
54   -p  Pod-name
55   -o  Use specified operating system for jumpserver/VCP VMs
56   -P  Skip installation of package dependencies
57   -s  Deploy-scenario short-name
58   -S  Storage dir for VM images and other deploy artifacts
59   -L  Deployment log path and file name
60   -m  Use single socket CPU compute nodes (only affects virtual computes)
61   -N  Experimental: Do not virtualize control plane (novcp)
62
63 $(notify_i "Description:" 2)
64 Deploys the OPNFV Fuel stack on the indicated lab resource.
65
66 This script provides the OPNFV Fuel deployment abstraction.
67 It depends on the OPNFV official configuration directory/file structure
68 and provides a fairly simple mechanism to execute a deployment.
69
70 $(notify_i "Input parameters to the build script are:" 2)
71 -b Base URI to the configuration directory (needs to be provided in URI style,
72    it can be a local resource: file:// or a remote resource http(s)://).
73    A POD Descriptor File (PDF) and its Installer Descriptor File (IDF)
74    companion should be available at:
75    <base-uri>/labs/<lab-name>/<pod-name>.yaml
76    <base-uri>/labs/<lab-name>/idf-<pod-name>.yaml
77    The default is using the git submodule tracking 'OPNFV Pharos' in
78    <./mcp/scripts/pharos>.
79 -d Dry-run - Produce deploy config files, but do not execute deploy
80 -D Debug logging - Enable extra logging in sh deploy scripts (set -x)
81 -e Do not launch environment deployment
82    If specified twice (e.g. -e -e), only the operating system and networks
83    will be provisioned, skipping cloud installation.
84 -E Remove existing VCP VMs. It will destroy and undefine all VCP VMs
85    currently defined on cluster KVM nodes. If specified twice (e.g. -E -E),
86    baremetal nodes (VCP too, implicitly) will be removed, then reprovisioned.
87    Only applicable for baremetal deploys.
88    If specified 3 times, a complete uninstallation (cleanup) will be performed
89    on the jumpserver (even for virtual deploys): VMs, virsh networks,
90    containers, networks, services etc.
91 -f Deploy on existing Salt master. It will skip infrastructure VM creation,
92    but it will still sync reclass configuration from current repo to Salt
93    Master node.
94    Each additional use skips one more state file. For example, -fff would
95    skip the first 3 state files (e.g. virtual_init, maas, baremetal_init).
96 -F Same as -e, do not launch environment deployment (legacy option)
97 -h Print this message and exit
98 -L Deployment log path and name, eg. -L /home/jenkins/job.log.tar.gz
99 -l Lab name as defined in the configuration directory, e.g. lf
100 -p POD name as defined in the configuration directory, e.g. pod2
101 -m Use single socket compute nodes. Instead of using default NUMA-enabled
102    topology for virtual compute nodes created via libvirt, configure a
103    single guest CPU socket.
104 -N Experimental: Instead of virtualizing the control plane (VCP), deploy
105    control plane directly on baremetal nodes
106 -o Operating system to be preinstalled on jumpserver VMs (for virtual/hybrid
107    deployments) and/or VCP VMs (for baremetal deployments).
108    Defaults to 'ubuntu1804' (Bionic).
109 -P Skip installing dependency distro packages on current host
110    This flag should only be used if you have kept back older packages that
111    would be upgraded and that is undesirable on the current system.
112    Note that without the required packages, deploy will fail.
113 -s Deployment-scenario, this points to a short deployment scenario name, which
114    has to be defined in config directory (e.g. os-odl-nofeature-ha).
115 -S Storage dir for VM images, default is /var/lib/opnfv/tmpdir
116    It is recommended to store the deploy artifacts on a fast disk, outside of
117    the current git repository (so clean operations won't erase it).
118
119 $(notify_i "[NOTE] sudo & virsh priviledges are needed for this script to run" 3)
120
121 Example:
122
123 $(notify_i "sudo $(basename "$0") \\
124   -b file:///home/jenkins/securedlab \\
125   -l lf -p pod2 \\
126   -s os-odl-nofeature-ha \\
127   -S /home/jenkins/tmpdir" 2)
128 EOF
129 }
130
131 #
132 # END of usage description
133 ##############################################################################
134
135 ##############################################################################
136 # BEGIN of variables to customize
137 #
138 CI_DEBUG=${CI_DEBUG:-0}; [[ "${CI_DEBUG}" =~ (false|0) ]] || set -x
139 MCP_REPO_ROOT_PATH=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")
140 DEPLOY_DIR=$(cd "${MCP_REPO_ROOT_PATH}/mcp/scripts"; pwd)
141 MCP_STORAGE_DIR='/var/lib/opnfv/tmpdir'
142 URI_REGEXP='(file|https?|ftp)://.*'
143 BASE_CONFIG_URI="file://${MCP_REPO_ROOT_PATH}/mcp/scripts/pharos"
144 OPNFV_BRANCH=$(sed -ne 's/defaultbranch=//p' "${MCP_REPO_ROOT_PATH}/.gitreview")
145 DEF_DOCKER_TAG=$(basename "${OPNFV_BRANCH/master/latest}")
146
147 # Customize deploy workflow
148 DRY_RUN=${DRY_RUN:-0}
149 USE_EXISTING_PKGS=${USE_EXISTING_PKGS:-0}
150 USE_EXISTING_INFRA=${USE_EXISTING_INFRA:-0}
151 MCP_NO_DEPLOY_ENVIRONMENT=${MCP_NO_DEPLOY_ENVIRONMENT:-0}
152 ERASE_ENV=${ERASE_ENV:-0}
153 MCP_VCP=${MCP_VCP:-1}
154 MCP_DOCKER_TAG=${MCP_DOCKER_TAG:-${DEF_DOCKER_TAG}}
155 MCP_CMP_SS=${MCP_CMP_SS:-0}
156 MCP_OS=${MCP_OS:-ubuntu1804}
157
158 source "${DEPLOY_DIR}/globals.sh"
159 source "${DEPLOY_DIR}/lib.sh"
160 source "${DEPLOY_DIR}/lib_template.sh"
161 source "${DEPLOY_DIR}/lib_jump_common.sh"
162 source "${DEPLOY_DIR}/lib_jump_deploy.sh"
163
164 #
165 # END of variables to customize
166 ##############################################################################
167
168 ##############################################################################
169 # BEGIN of main
170 #
171 set +x
172 while getopts "b:dDfEFl:L:No:p:Ps:S:he" OPTION
173 do
174     case $OPTION in
175         b)
176             BASE_CONFIG_URI=${OPTARG}
177             if [[ ! $BASE_CONFIG_URI =~ ${URI_REGEXP} ]]; then
178                 notify "[ERROR] -b $BASE_CONFIG_URI - invalid URI"
179                 usage
180                 exit 1
181             fi
182             ;;
183         d)
184             DRY_RUN=1
185             ;;
186         D)
187             CI_DEBUG=1
188             ;;
189         f)
190             ((USE_EXISTING_INFRA+=1))
191             ;;
192         F|e)
193             ((MCP_NO_DEPLOY_ENVIRONMENT+=1))
194             ;;
195         E)
196             ((ERASE_ENV+=1))
197             ;;
198         l)
199             TARGET_LAB=${OPTARG}
200             ;;
201         L)
202             DEPLOY_LOG="${OPTARG}"
203             ;;
204         m)
205             MCP_CMP_SS=1
206             ;;
207         N)
208             MCP_VCP=0
209             ;;
210         o)
211             MCP_OS=${OPTARG}
212             ;;
213         p)
214             TARGET_POD=${OPTARG}
215             ;;
216         P)
217             USE_EXISTING_PKGS=1
218             ;;
219         s)
220             DEPLOY_SCENARIO=${OPTARG}
221             ;;
222         S)
223             if [[ ${OPTARG} ]]; then
224                 MCP_STORAGE_DIR="${OPTARG}"
225             fi
226             ;;
227         h)
228             usage
229             exit 0
230             ;;
231         *)
232             notify_e "[ERROR] Unsupported arg, see -h for help"
233             ;;
234     esac
235 done
236
237 if [[ "$(sudo whoami)" != 'root' ]]; then
238     notify_e "[ERROR] This script requires sudo rights"
239 fi
240
241 # Validate mandatory arguments are set
242 if [ -z "${TARGET_LAB}" ] || [ -z "${TARGET_POD}" ] || \
243    [ -z "${DEPLOY_SCENARIO}" ]; then
244     usage
245     notify_e "[ERROR] At least one of the mandatory args is missing!"
246 fi
247
248 [[ "${CI_DEBUG}" =~ (false|0) ]] || set -x
249
250 # Enable the automatic exit trap
251 trap do_exit SIGINT SIGTERM EXIT
252
253 # Set no restrictive umask so that Jenkins can remove any residuals
254 umask 0000
255
256 pushd "${DEPLOY_DIR}" > /dev/null
257 # Prepare the deploy config files based on lab/pod information, deployment
258 # scenario, etc.
259
260 # Install required packages on jump server
261 sudo mkdir -p "${MCP_STORAGE_DIR}"
262 sudo chown -R "${USER}:${USER}" "${MCP_STORAGE_DIR}"
263 if [ ${USE_EXISTING_PKGS} -eq 1 ]; then
264     notify "[NOTE] Skipping distro pkg installation" 2
265 else
266     notify "[NOTE] Installing required distro pkgs" 2
267     jumpserver_pkg_install 'deploy'
268     docker_install "${MCP_STORAGE_DIR}"
269     virtinst_install "${MCP_STORAGE_DIR}"
270     # Ubuntu 18.04 cloud image requires newer e2fsprogs
271     if [[ "${MCP_OS:-}" =~ ubuntu1804 ]]; then
272         e2fsprogs_install "${MCP_STORAGE_DIR}"
273     fi
274 fi
275
276 if ! ${VIRSH} list >/dev/null 2>&1; then
277     notify_e "[ERROR] This script requires hypervisor access"
278 fi
279
280 # Collect jump server system information for deploy debugging
281 ./sysinfo_print.sh
282
283 # Clone git submodules and apply our patches
284 make -C "${MCP_REPO_ROOT_PATH}/mcp/patches" deepclean patches-import
285
286 # Check scenario file existence
287 SCENARIO_DIR="$(readlink -f "../config/scenario")"
288 if [ ! -f "${SCENARIO_DIR}/${DEPLOY_SCENARIO}.yaml" ] && \
289    [ ! -f "${SCENARIO_DIR}/${DEPLOY_SCENARIO}.yaml.j2" ]; then
290     notify_e "[ERROR] Scenario definition file is missing!"
291 fi
292
293 # key might not exist yet ...
294 generate_ssh_key
295 export MAAS_SSH_KEY="$(cat "$(basename "${SSH_KEY}").pub")"
296
297 # Expand jinja2 templates based on PDF data and env vars
298 [[ "${DEPLOY_SCENARIO}" =~ -ha$ ]] || MCP_VCP=0
299 export MCP_REPO_ROOT_PATH MCP_VCP MCP_STORAGE_DIR MCP_DOCKER_TAG MCP_CMP_SS \
300        MCP_JUMP_ARCH=$(uname -i) MCP_DEPLOY_SCENARIO="${DEPLOY_SCENARIO}" \
301        MCP_NO_DEPLOY_ENVIRONMENT MCP_OS
302 do_templates_scenario "${MCP_STORAGE_DIR}" "${TARGET_LAB}" "${TARGET_POD}" \
303                       "${BASE_CONFIG_URI}" "${SCENARIO_DIR}" \
304                       "${SCENARIO_DIR}/${DEPLOY_SCENARIO}.yaml"
305 do_templates_cluster  "${MCP_STORAGE_DIR}" "${TARGET_LAB}" "${TARGET_POD}" \
306                       "${MCP_REPO_ROOT_PATH}" \
307                       "${SCENARIO_DIR}/defaults.yaml"
308
309 # Determine additional data (e.g. jump bridge names) based on XDF
310 source "${DEPLOY_DIR}/xdf_data.sh"
311
312 # Jumpserver prerequisites check
313 notify "[NOTE] Using bridges: ${OPNFV_BRIDGES[*]}" 2
314 jumpserver_check_requirements "${cluster_states[*]}" "${virtual_nodes[*]}" \
315                               "${OPNFV_BRIDGES[@]}"
316
317 # Infra setup
318 if [ ${DRY_RUN} -eq 1 ]; then
319     notify "[NOTE] Dry run, skipping all deployment tasks" 2
320     exit 0
321 elif [ ${ERASE_ENV} -gt 2 ]; then
322     notify "[NOTE] Uninstall / cleanup all jumpserver Fuel resources" 2
323     cleanup_all "${MCP_STORAGE_DIR}" "${OPNFV_BRIDGES[@]}"
324     exit 0
325 elif [ ${USE_EXISTING_INFRA} -gt 0 ]; then
326     notify "[NOTE] Use existing infra: skip first ${USE_EXISTING_INFRA} states" 2
327     notify "[STATE] Skipping: ${cluster_states[*]::${USE_EXISTING_INFRA}}" 2
328 else
329     prepare_vms "${base_image}" "${MCP_STORAGE_DIR}" "${virtual_repos_pkgs}"
330     create_networks "${OPNFV_BRIDGES[@]}"
331     do_sysctl_cfg
332     do_udev_cfg
333     create_vms "${MCP_STORAGE_DIR}" "${virtual_nodes_data}" "${OPNFV_BRIDGES[@]}"
334     start_vms "${virtual_nodes[@]}"
335
336     # https://github.com/docker/libnetwork/issues/1743
337     # rm -f /var/lib/docker/network/files/local-kv.db
338     sudo systemctl restart docker
339     prepare_containers "${MCP_STORAGE_DIR}"
340 fi
341
342 start_containers "${MCP_STORAGE_DIR}"
343 check_connection
344
345 # Openstack cluster setup
346 set +x
347 if [ ${MCP_NO_DEPLOY_ENVIRONMENT} -eq 1 ]; then
348     notify "[NOTE] Skip openstack cluster setup" 2
349 else
350     for state in "${cluster_states[@]:${USE_EXISTING_INFRA}}"; do
351         notify "[STATE] Applying state: ${state}" 2
352         # shellcheck disable=SC2086,2029
353         wait_for 5 "ssh ${SSH_OPTS} ${SSH_SALT} sudo \
354             CI_DEBUG=$CI_DEBUG ERASE_ENV=$ERASE_ENV \
355             /root/fuel/mcp/config/states/${state}"
356         if [ "${state}" = 'maas' ]; then
357             # For hybrid PODs (virtual + baremetal nodes), the virtual nodes
358             # should be reset to force a DHCP request from MaaS DHCP
359             reset_vms "${virtual_nodes[@]}"
360         fi
361     done
362
363     ./log.sh "${DEPLOY_LOG}"
364 fi
365
366 popd > /dev/null
367
368 #
369 # END of main
370 ##############################################################################