2 # shellcheck disable=SC2034,SC2154,SC1091
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 ##############################################################################
13 ##############################################################################
14 # BEGIN of Exit handlers
21 # End of Exit handlers
22 ##############################################################################
24 ##############################################################################
25 # BEGIN of usage description
30 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
31 $(notify "$(basename "$0"): Deploy the Fuel@OPNFV MCP stack" 3)
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]
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 -e Do not launch environment deployment
42 -f Deploy on existing Salt master
43 -F Do only create a Salt master
44 -h Print this message and exit
47 -s Deploy-scenario short-name
48 -S Storage dir for VM images
49 -L Deployment log path and file name
51 $(notify "DISABLED OPTIONS (not yet supported with MCP):" 3)
54 -T (disabled) Timeout, in minutes, for the deploy.
56 $(notify "Description:" 2)
57 Deploys the Fuel@OPNFV stack on the indicated lab resource.
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.
63 $(notify "Input parameters to the build script are:" 2)
64 -b Base URI to the configuration directory (needs to be provided in URI style,
65 it can be a local resource: file:// or a remote resource http(s)://).
66 A POD Descriptor File (PDF) should be available at:
67 <base-uri>/labs/<lab-name>/<pod-name>.yaml
68 The default is './mcp/config'.
69 -B Bridges to be used by deploy script. It can be specified several times,
70 or as a comma separated list of bridges, or both: -B br1 -B br2,br3
71 First occurence sets PXE Brige, next Mgmt, then Internal and Public.
72 For an empty value, the deploy script will use virsh to create the default
73 expected network (e.g. -B pxe,,,public will use existing "pxe" and "public"
74 bridges, respectively create "mgmt" and "internal").
75 Note that a virtual network "mcpcontrol" is always created. For virtual
76 deploys, "mcpcontrol" is also used for PXE, leaving the PXE bridge unused.
77 For baremetal deploys, PXE bridge is used for baremetal node provisioning,
78 while "mcpcontrol" is used to provision the infrastructure VMs only.
79 The default is 'pxebr'.
80 -e Do not launch environment deployment
81 -f Deploy on existing Salt master
82 -F Do only create a Salt master
83 -h Print this message and exit
84 -L Deployment log path and name, eg. -L /home/jenkins/job.log.tar.gz
85 -l Lab name as defined in the configuration directory, e.g. lf
86 -p POD name as defined in the configuration directory, e.g. pod2
87 -s Deployment-scenario, this points to a short deployment scenario name, which
88 has to be defined in config directory (e.g. os-odl-nofeature-ha).
89 -S Storage dir for VM images, default is mcp/deploy/images
91 $(notify "Disabled input parameters (not yet supported with MCP):" 3)
92 -d (disabled) Dry-run - Produce deploy config files, but do not execute deploy
93 -T (disabled) Timeout, in minutes, for the deploy.
94 It defaults to using the DEPLOY_TIMEOUT environment variable when defined.
95 -i (disabled) .iso image to be deployed (needs to be provided in a URI
96 style, it can be a local resource: file:// or a remote resource http(s)://)
98 $(notify "[NOTE] sudo & virsh priviledges are needed for this script to run" 3)
102 $(notify "sudo $(basename "$0") \\
103 -b file:///home/jenkins/securedlab \\
105 -s os-odl-nofeature-ha" 2)
110 # END of usage description
111 ##############################################################################
113 ##############################################################################
114 # BEGIN of colored notification wrapper
117 tput setaf "${2:-1}" || true
118 echo -en "${1:-"[WARN] Unsupported opt arg: $3\\n"}"
122 # END of colored notification wrapper
123 ##############################################################################
125 ##############################################################################
126 # BEGIN of deployment clean-up
129 echo "Cleaning up deploy tmp directories"
132 # END of deployment clean-up
133 ##############################################################################
135 ##############################################################################
136 # BEGIN of variables to customize
138 REPO_ROOT_PATH=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")
139 DEPLOY_DIR=$(cd "${REPO_ROOT_PATH}/mcp/scripts"; pwd)
140 STORAGE_DIR=$(cd "${REPO_ROOT_PATH}/mcp/deploy/images"; pwd)
141 RECLASS_CLUSTER_DIR=$(cd "${REPO_ROOT_PATH}/mcp/reclass/classes/cluster"; pwd)
142 DEPLOY_TYPE='baremetal'
143 OPNFV_BRIDGES=('pxebr' 'mgmt' 'internal' 'public')
144 URI_REGEXP='(file|https?|ftp)://.*'
145 BASE_CONFIG_URI="file://${REPO_ROOT_PATH}/mcp/config"
147 export SSH_KEY=${SSH_KEY:-"/var/lib/opnfv/mcp.rsa"}
148 export SALT_MASTER=${INSTALLER_IP:-10.20.0.2}
149 export SALT_MASTER_USER=${SALT_MASTER_USER:-ubuntu}
150 export MAAS_IP=${MAAS_IP:-${SALT_MASTER%.*}.3}
151 export MAAS_PXE_NETWORK=${MAAS_PXE_NETWORK:-192.168.11.0}
153 # Derivated from above global vars
154 export MCP_CTRL_NETWORK_ROOTSTR=${SALT_MASTER%.*}
155 export MAAS_PXE_NETWORK_ROOTSTR=${MAAS_PXE_NETWORK%.*}
156 export SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ${SSH_KEY}"
157 export SSH_SALT="${SALT_MASTER_USER}@${SALT_MASTER}"
159 # Customize deploy workflow
160 export USE_EXISTING_INFRA=${USE_EXISTING_INFRA:-0}
161 export INFRA_CREATION_ONLY=${INFRA_CREATION_ONLY:-0}
162 export NO_DEPLOY_ENVIRONMENT=${NO_DEPLOY_ENVIRONMENT:-0}
164 # Variables below are disabled for now, to be re-introduced or removed later
167 if ! [ -z "${DEPLOY_TIMEOUT}" ]; then
168 DEPLOY_TIMEOUT="-dt ${DEPLOY_TIMEOUT}"
174 # END of variables to customize
175 ##############################################################################
177 ##############################################################################
182 while getopts "b:B:dfFl:L:p:s:S:T:i:he" OPTION
186 BASE_CONFIG_URI=${OPTARG}
187 if [[ ! $BASE_CONFIG_URI =~ ${URI_REGEXP} ]]; then
188 notify "[ERROR] -b $BASE_CONFIG_URI - invalid URI\n"
196 OPT_BRIDGES=($OPTARG)
197 for bridge in "${OPT_BRIDGES[@]}"; do
198 if [ -n "${bridge}" ]; then
199 OPNFV_BRIDGES[${OPNFV_BRIDGE_IDX}]="${bridge}"
201 OPNFV_BRIDGE_IDX=$((OPNFV_BRIDGE_IDX + 1))
206 notify '' 3 "${OPTION}"; continue
213 INFRA_CREATION_ONLY=1
216 NO_DEPLOY_ENVIRONMENT=1
222 DEPLOY_LOG="${OPTARG}"
226 if [[ "${TARGET_POD}" =~ "virtual" ]]; then
227 DEPLOY_TYPE='virtual'
231 DEPLOY_SCENARIO=${OPTARG}
234 if [[ ${OPTARG} ]]; then
235 STORAGE_DIR="${OPTARG}"
239 notify '' 3 "${OPTION}"; continue
240 DEPLOY_TIMEOUT="-dt ${OPTARG}"
243 notify '' 3 "${OPTION}"; continue
245 if [[ ! $ISO =~ ${URI_REGEXP} ]]; then
246 notify "[ERROR] -i $ISO - invalid URI\n"
256 notify "[ERROR] Arguments not according to new argument style\n"
262 if [[ "$(sudo whoami)" != 'root' ]]; then
263 notify "This script requires sudo rights\n" 1>&2
267 if ! virsh list >/dev/null 2>&1; then
268 notify "This script requires hypervisor access\n" 1>&2
272 # Validate mandatory arguments are set
273 if [ -z "${TARGET_LAB}" ] || [ -z "${TARGET_POD}" ] || \
274 [ -z "${DEPLOY_SCENARIO}" ]; then
275 notify "[ERROR] At least one of the mandatory args is missing!\n" 1>&2
282 # Enable the automatic exit trap
283 trap do_exit SIGINT SIGTERM EXIT
285 # Set no restrictive umask so that Jenkins can remove any residuals
290 pushd "${DEPLOY_DIR}" > /dev/null
291 # Prepare the deploy config files based on lab/pod information, deployment
294 # Install required packages
295 [ -n "$(command -v apt-get)" ] && sudo apt-get install -y \
296 git make rsync mkisofs curl virtinst cpu-checker qemu-kvm
297 [ -n "$(command -v yum)" ] && sudo yum install -y --skip-broken \
298 git make rsync genisoimage curl virt-install qemu-kvm
300 if [ "$(uname -i)" = "aarch64" ]; then
301 [ -n "$(command -v apt-get)" ] && sudo apt-get install -y vgabios && \
302 sudo ln -sf /usr/share/vgabios/vgabios.bin /usr/share/qemu/vgabios-stdvga.bin
303 [ -n "$(command -v yum)" ] && sudo yum install -y --skip-broken vgabios
306 # Clone git submodules and apply our patches
307 make -C "${REPO_ROOT_PATH}/mcp/patches" deepclean patches-import
309 # Convert Pharos-compatible POD Descriptor File (PDF) to reclass model input
310 PHAROS_GEN_CONFIG_SCRIPT="./pharos/config/utils/generate_config.py"
311 PHAROS_INSTALLER_ADAPTER="./pharos/config/installers/fuel/pod_config.yml.j2"
312 BASE_CONFIG_PDF="${BASE_CONFIG_URI}/labs/${TARGET_LAB}/${TARGET_POD}.yaml"
313 LOCAL_PDF="${STORAGE_DIR}/$(basename "${BASE_CONFIG_PDF}")"
314 LOCAL_PDF_RECLASS="${STORAGE_DIR}/pod_config.yml"
315 if ! curl --create-dirs -o "${LOCAL_PDF}" "${BASE_CONFIG_PDF}"; then
316 if [ "${DEPLOY_TYPE}" = 'baremetal' ]; then
317 notify "[ERROR] Could not retrieve PDF (Pod Descriptor File)!\n" 1>&2
320 notify "[WARN] Could not retrieve PDF (Pod Descriptor File)!\n" 3
322 elif ! "${PHAROS_GEN_CONFIG_SCRIPT}" -y "${LOCAL_PDF}" \
323 -j "${PHAROS_INSTALLER_ADAPTER}" > "${LOCAL_PDF_RECLASS}"; then
324 notify "[ERROR] Could not convert PDF to reclass model input!\n" 1>&2
328 # Check scenario file existence
329 SCENARIO_DIR="../config/scenario"
330 if [ ! -f "${SCENARIO_DIR}/${DEPLOY_TYPE}/${DEPLOY_SCENARIO}.yaml" ]; then
331 notify "[WARN] ${DEPLOY_SCENARIO}.yaml not found! \
332 Setting simplest scenario (os-nosdn-nofeature-noha)\n" 3
333 DEPLOY_SCENARIO='os-nosdn-nofeature-noha'
334 if [ ! -f "${SCENARIO_DIR}/${DEPLOY_TYPE}/${DEPLOY_SCENARIO}.yaml" ]; then
335 notify "[ERROR] Scenario definition file is missing!\n" 1>&2
340 # Check defaults file existence
341 if [ ! -f "${SCENARIO_DIR}/defaults-$(uname -i).yaml" ]; then
342 notify "[ERROR] Scenario defaults file is missing!\n" 1>&2
346 # Get required infra deployment data
348 eval "$(parse_yaml "${SCENARIO_DIR}/defaults-$(uname -i).yaml")"
349 eval "$(parse_yaml "${SCENARIO_DIR}/${DEPLOY_TYPE}/${DEPLOY_SCENARIO}.yaml")"
351 export CLUSTER_DOMAIN=${cluster_domain}
353 declare -A virtual_nodes_ram virtual_nodes_vcpus
354 for node in "${virtual_nodes[@]}"; do
355 virtual_custom_ram="virtual_${node}_ram"
356 virtual_custom_vcpus="virtual_${node}_vcpus"
357 virtual_nodes_ram[$node]=${!virtual_custom_ram:-$virtual_default_ram}
358 virtual_nodes_vcpus[$node]=${!virtual_custom_vcpus:-$virtual_default_vcpus}
361 # Expand reclass and virsh network templates
362 for tp in "${RECLASS_CLUSTER_DIR}/all-mcp-ocata-common/opnfv/"*.template \
363 net_*.template; do envsubst < "${tp}" > "${tp%.template}"; done
366 if [ ${USE_EXISTING_INFRA} -eq 1 ]; then
367 notify "Use existing infra\n" 2 1>&2
371 prepare_vms virtual_nodes "${base_image}" "${STORAGE_DIR}"
372 create_networks OPNFV_BRIDGES
373 create_vms virtual_nodes virtual_nodes_ram virtual_nodes_vcpus \
374 OPNFV_BRIDGES "${STORAGE_DIR}"
375 update_mcpcontrol_network
376 start_vms virtual_nodes
378 ./salt.sh "${LOCAL_PDF_RECLASS}"
381 if [ ${INFRA_CREATION_ONLY} -eq 1 ] || [ ${NO_DEPLOY_ENVIRONMENT} -eq 1 ]; then
382 echo "Skip openstack cluster setup\n" 2
384 # Openstack cluster setup
385 for state in "${cluster_states[@]}"; do
386 notify "STATE: ${state}\n" 2
387 # shellcheck disable=SC2086,2029
388 ssh ${SSH_OPTS} "ubuntu@${SALT_MASTER}" \
389 sudo "/root/fuel/mcp/config/states/${state} || true"
393 ./log.sh "${DEPLOY_LOG}"
399 ##############################################################################