blob: 4e59bd6936840d57bfe9d99bf9929478d21cf423 [file] [log] [blame]
Petr Michalec1ed1b3c2017-08-08 19:19:01 +02001#!/bin/bash -e
2
3# bootstrap.sh
4
5# Installs Salt and configure minimal SaltMaster or Minion to be used with:
6# - http://github.com/salt-formulas-scripts
7# - http://github.com/salt-formulas/salt-formula-salt (salt.master sls)
8
9# TODO:
10# - use PPA repository as formula source
11# - support for spm/yum
12
13
14# Source specific env vars.
15# shopt -u dotglob
16export RECLASS_ROOT=${RECLASS_ROOT:-/srv/salt/reclass}
17function source_local_envs() {
Petr Michalecb444ef92017-08-17 13:53:14 +020018 for path in / /tmp/kitchen /srv/salt . ${RECLASS_ROOT}/classes/cluster ${RECLASS_ROOT}/classes/cluster/${CLUSTER_NAME}; do
Vasyl Saienko7a4161c2017-08-14 17:43:15 +030019 for f in $(find $path -maxdepth 1 -name '*.env' 2> /dev/null); do
20 echo "Sourcing env variables from $f"
21 source $f
22 done
23 done
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020024}
25source_local_envs
26
27##########################################
28# Set defaults env variables
29
30if [[ $DEBUG =~ ^(True|true|1|yes)$ ]]; then
31 set -x
32 SALT_LOG_LEVEL="--state-verbose=true -ldebug"
33fi
34
35export MAGENTA='\033[0;95m'
36export YELLOW='\033[1;33m'
37export BLUE='\033[0;35m'
38export CYAN='\033[0;96m'
39export RED='\033[0;31m'
40export NC='\033[0m' # No Color'
41
42export LC_ALL=C
43export SALT_LOG_LEVEL="--state-verbose=false -lerror"
44export SALT_OPTS="${SALT_OPTS:- --timeout=120 --state-output=changes --retcode-passthrough --force-color $SALT_LOG_LEVEL }"
45export SALT_STATE_RETRY=${SALT_STATE_RETRY:-3}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020046
47
48# salt apt repository
49test -e /etc/lsb-release && eval $(cat /etc/lsb-release)
50which lsb_release && DISTRIB_CODENAME=${DISTRIB_CODENAME:-$(lsb_release -cs)}
51#
Dmitry Ukov95492a02017-10-23 11:34:45 +040052export APT_REPOSITORY=${APT_REPOSITORY:- deb [arch=amd64] http://apt.mirantis.com/${DISTRIB_CODENAME} ${DISTRIB_REVISION:-stable} salt}
chnyda30c07a62017-09-20 14:28:02 +020053export APT_REPOSITORY_GPG=${APT_REPOSITORY_GPG:-http://apt.mirantis.com/public.gpg}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020054
55# reclass
56export RECLASS_ADDRESS=${RECLASS_ADDRESS:-https://github.com/salt-formulas/openstack-salt.git} # https/git
57
58# formula
59export FORMULAS_BASE=${FORMULAS_BASE:-https://github.com/salt-formulas}
60export FORMULAS_PATH=${FORMULAS_PATH:-/usr/share/salt-formulas}
61export FORMULAS_BRANCH=${FORMULAS_BRANCH:-master}
62export FORMULAS_SOURCE=${FORMULAS_SOURCE:-pkg} # pkg/git
Petr Michalec515356f2017-11-16 11:20:20 +010063# Essential set of formulas (known to by used on cfg01 node for most setups during bootsrap)
64# DEPRECATED: FORMULAS_SALT_MASTER=${FORMULAS_SALT_MASTER:- $EXTRA_FORMULAS maas memcached ntp nginx collectd sensu heka sphinx mysql grafana libvirt rsyslog glusterfs postfix xtrabackup freeipa prometheus telegraf elasticsearch kibana rundeck devops-portal rsync docker keepalived aptly jenkins gerrit artifactory influxdb horizon}
Petr Michalece07cd0b2017-11-15 11:41:57 +010065FORMULAS_SALT_MASTER=${FORMULAS_SALT_MASTER:- $EXTRA_FORMULAS}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020066# minimal set of formulas for salt-master bootstrap
Petr Michalec515356f2017-11-16 11:20:20 +010067declare -a FORMULAS_SALT_MASTER=(reclass salt git openssh linux $(echo $FORMULAS_SALT_MASTER))
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020068export FORMULAS_SALT_MASTER
69
70# system / host
Petr Michalecc749e862017-09-06 21:10:10 +020071export HOSTNAME=${HOSTNAME:-`hostname -s`}
72export HOSTNAME=${HOSTNAME//.*/}
73export DOMAIN=${DOMAIN:-`hostname -d`}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020074export DOMAIN=${DOMAIN:-bootstrap.local}
75
76# salt
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020077export MINION_ID=${MINION_ID:-${HOSTNAME}.${DOMAIN}}
Petr Michalec2e3a4992017-08-17 14:20:43 +020078export MASTER_HOSTNAME=${MASTER_HOSTNAME:-${HOSTNAME}.${DOMAIN}}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020079
80# saltstack
Petr Michalec33c04892017-09-08 15:10:30 +020081BOOTSTRAP_SALTSTACK=${BOOTSTRAP_SALTSTACK:-True}
Petr Michalece11cf612017-09-08 18:21:48 +020082BOOTSTRAP_SALTSTACK_VERSION=${BOOTSTRAP_SALTSTACK_VERSION:- stable 2016.3 }
Petr Michalec33c04892017-09-08 15:10:30 +020083BOOTSTRAP_SALTSTACK_OPTS=${BOOTSTRAP_SALTSTACK_OPTS:- -dX $BOOTSTRAP_SALTSTACK_VERSION }
Petr Michalece11cf612017-09-08 18:21:48 +020084SALT_SOURCE=${SALT_SOURCE:-pkg}
85# the version below is used salt pillar data
86SALT_VERSION=${SALT_VERSION:-latest}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020087
88# environment
89if [ "$FORMULAS_SOURCE" == "git" ]; then
90 SALT_ENV=${SALT_ENV:-dev}
91elif [ "$FORMULAS_SOURCE" == "pkg" ]; then
92 SALT_ENV=${SALT_ENV:-prd}
93fi
Petr Michalec05b52452017-09-08 14:26:59 +020094eval "$(grep -h '=' /etc/*release 2> /dev/null)"
Petr Michalec1ed1b3c2017-08-08 19:19:01 +020095PLATFORM_FAMILY=$(echo ${ID_LIKE// */} | tr A-Z a-z)
96case $PLATFORM_FAMILY in
97 debian )
98 PKGTOOL="$SUDO apt-get"
99 test ${VERSION_ID//\.*/} -ge 16 && {
100 SVCTOOL=service
101 } || { SVCTOOL=service
102 }
103 ;;
104 rhel )
105 PKGTOOL="$SUDO yum"
106 test ${VERSION_ID//\.*/} -ge 7 && {
107 SVCTOOL=systemctl
108 } || { SVCTOOL=service
109 }
110 ;;
111esac
112
113export PLATFORM_FAMILY
114export PKGTOOL
115export SVCTOOL
116
117##########################################
118# FUNCTIONS
119
120log_info() {
121 echo -e "${YELLOW}[INFO] $* ${NC}"
122}
123
124log_warn() {
125 echo -e "${MAGENTA}[WARN] $* ${NC}"
126}
127
Petr Michalec24b30e82017-08-21 10:59:18 +0200128log_debug() {
129 echo -e "${CYAN}[WARN] $* ${NC}"
130}
131
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200132log_err() {
133 echo -e "${RED}[ERROR] $* ${NC}" >&2
134}
135
136configure_pkg_repo()
137{
138
139 case $PLATFORM_FAMILY in
140 debian)
141 if [ -n "$APT_REPOSITORY_PPA" ]; then
142 which add-apt-repository || $SUDO apt-get install -y software-properties-common
143 $SUDO add-apt-repository -y ppa:${APT_REPOSITORY_PPA}
144 else
Mykyta Karpinfbcb5482017-10-04 14:15:25 +0300145 echo -e "$APT_REPOSITORY " | $SUDO tee /etc/apt/sources.list.d/mcp_salt.list >/dev/null
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200146 curl -sL $APT_REPOSITORY_GPG | $SUDO apt-key add -
147 fi
148 $SUDO apt-get clean
149 $SUDO apt-get update
150 ;;
151 rhel)
152 $SUDO yum install -y https://repo.saltstack.com/yum/redhat/salt-repo-latest-1.el${VERSION_ID}.noarch.rpm
153 $SUDO yum clean all
154 ;;
155 esac
156
157}
158
159_atexit() {
160 RETVAL=$?
161 trap true INT TERM EXIT
162
163 if [ $RETVAL -ne 0 ]; then
164 log_err "Execution failed"
165 else
166 log_info "Execution successful"
167 fi
168 return $RETVAL
169}
170
171retry() {
172 local tries
173 if [[ $1 =~ ^[0-9]+$ ]]; then
174 tries=$1; shift
175 else
176 tries=3
177 fi
Petr Michalec262e3ad2017-10-06 13:41:58 +0200178 ret=1
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200179 for i in $(seq 1 $tries); do
Petr Michalec262e3ad2017-10-06 13:41:58 +0200180 "$@" && return $? || ret=$?
181 sleep $i
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200182 done
Petr Michalec9fec8b32017-10-05 14:46:42 +0200183 return $ret
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200184}
185
186function clone_reclass() {
Petr Michaleca361d4e2017-09-08 11:38:16 +0200187 if [ ! -d ${RECLASS_ROOT}/classes ]; then
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200188 # No reclass at all, clone from given address
189 ssh-keyscan -H github.com >> ~/.ssh/known_hosts || true
190 if echo ${RECLASS_BRANCH:-master} | egrep -q "^refs"; then
191 git clone ${RECLASS_ADDRESS} ${RECLASS_ROOT}
192 cd ${RECLASS_ROOT}
193 git fetch ${RECLASS_ADDRESS} ${RECLASS_BRANCH:-master} && git checkout FETCH_HEAD
194 cd -
195 else
196 git clone -b ${RECLASS_BRANCH:-master} ${RECLASS_ADDRESS} ${RECLASS_ROOT};
197 fi;
198 fi;
Petr Michalec679f15b2017-09-18 16:16:29 +0200199 if [ ! -d ${RECLASS_ROOT}/classes ]; then
Petr Michaleca361d4e2017-09-08 11:38:16 +0200200 log_err "Reclass ${RECLASS_ROOT} is not fetched locally;"
201 ls -Rla ${RECLASS_ROOT}
202 exit 1
203 fi;
204 $SUDO mkdir -p $RECLASS_ROOT/classes/service
205 $SUDO mkdir -p $RECLASS_ROOT/nodes/_generated
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200206}
207
208
209##########################################
210# Main calls
211
Petr Michalecda014202017-08-18 11:26:07 +0200212system_config_ssh_conf() {
213 for conf in ~/.ssh/config /root/.ssh/config; do
214 $SUDO mkdir -p $(dirname $conf)
215 if ! grep StrictHostKeyChecking $conf; then
216 # this should be used only in CI environment
217 echo -e "Host *\n\tStrictHostKeyChecking no\n" | $SUDO tee $conf >/dev/null
218 fi
219 done
220 if ! grep github.com ~/.ssh/known_hosts; then
221 ssh-keyscan -H github.com >> ~/.ssh/known_hosts || true
222 fi
223}
224
225system_config_salt_modules_prereq() {
226 # salt-formulas custom modules dependencies, etc:
227 $SUDO $PKGTOOL install -y iproute2 curl sudo apt-transport-https python-psutil python-apt python-m2crypto python-oauth python-pip &>/dev/null
228}
229
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200230system_config_minion() {
231 log_info "System configuration salt minion"
232}
233
234system_config_master() {
235 log_info "System configuration salt master"
236
Petr Michalecda014202017-08-18 11:26:07 +0200237 system_config_salt_modules_prereq
238 system_config_ssh_conf
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200239
Petr Michalecda014202017-08-18 11:26:07 +0200240 if ! grep '127.0.1.2.*salt' /etc/hosts; then
241 echo "127.0.1.2 salt" | $SUDO tee -a /etc/hosts >/dev/null
242 fi
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200243
244 which reclass || $SUDO $PKGTOOL install -y reclass
245
246 which reclass-salt || {
247 test -e /usr/share/reclass/reclass-salt && {
248 ln -fs /usr/share/reclass/reclass-salt /usr/bin
249 }
250 }
251}
252
253configure_salt_master()
254{
255
256 echo "Configuring salt-master ..."
257
Petr Michalec4be5e5b2017-08-17 11:44:49 +0200258 if [[ $RECLASS_IGNORE_CLASS_NOTFOUND =~ ^(True|true|1|yes)$ ]]; then
Petr Michalec29d3ea32017-10-31 17:22:36 +0100259 read -d '' IGNORE_CLASS_NOTFOUND <<-EOF
260 ignore_class_notfound: True
261 ignore_class_regexp:
262 - 'service.*'
263EOF
Petr Michalec4be5e5b2017-08-17 11:44:49 +0200264 fi
265
Petr Michalecdd1a0472017-09-06 19:27:24 +0200266 # to force alternative reclass module path
Petr Michalecd9d0a322017-09-06 19:38:32 +0200267 if [ -n "$RECLASS_SOURCE_PATH" ]; then
268 RECLASS_SOURCE_PATH="reclass_source_path: ${RECLASS_SOURCE_PATH}"
269 else
270 RECLASS_SOURCE_PATH=""
271 fi
Petr Michalecdd1a0472017-09-06 19:27:24 +0200272
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200273 [ ! -d /etc/salt/master.d ] && mkdir -p /etc/salt/master.d
274 cat <<-EOF > /etc/salt/master.d/master.conf
275 file_roots:
276 base:
277 - /usr/share/salt-formulas/env
278 prd:
279 - /srv/salt/env/prd
280 dev:
281 - /srv/salt/env/dev
282 pillar_opts: False
283 open_mode: True
284 reclass: &reclass
285 storage_type: yaml_fs
286 inventory_base_uri: ${RECLASS_ROOT}
Petr Michalec4be5e5b2017-08-17 11:44:49 +0200287 ${IGNORE_CLASS_NOTFOUND}
Petr Michalecdd1a0472017-09-06 19:27:24 +0200288 ${RECLASS_SOURCE_PATH}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200289 ext_pillar:
290 - reclass: *reclass
291 master_tops:
292 reclass: *reclass
293EOF
294
295 echo "Configuring reclass ..."
296
297 [ ! -d /etc/reclass ] && mkdir /etc/reclass
298 cat <<-EOF > /etc/reclass/reclass-config.yml
299 storage_type: yaml_fs
300 pretty_print: True
301 output: yaml
302 inventory_base_uri: ${RECLASS_ROOT}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200303EOF
304
305 clone_reclass
306 # override some envs from cluster level *.env, use with care
307 source_local_envs
308
309 cd ${RECLASS_ROOT}
310 if [ ! -d ${RECLASS_ROOT}/classes/system/linux ]; then
311 # Possibly subrepo checkout needed
312 git submodule update --init --recursive
313 fi
314
Petr Michalec212cc6a2017-08-17 21:39:40 +0200315 mkdir -vp ${RECLASS_ROOT}/nodes/_generated
Petr Michalec51ece842017-09-06 20:44:15 +0200316 rm -rvf ${RECLASS_ROOT}/nodes/_generated/*
317
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200318 CONFIG=$(find ${RECLASS_ROOT}/nodes -name ${MINION_ID}.yml| grep yml | tail -n1)
Petr Michalec212cc6a2017-08-17 21:39:40 +0200319 CONFIG=${CONFIG:-${RECLASS_ROOT}/nodes/_generated/${MINION_ID}.yml}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200320 if [[ $SALT_MASTER_BOOTSTRAP_MINIMIZED =~ ^(True|true|1|yes)$ || ! -f "${CONFIG}" ]]; then
Petr Michalec24b30e82017-08-21 10:59:18 +0200321 log_warn "Salt Master node specification has not been found in model."
322 log_warn "Creating temporary cfg01 configuration for bootstrap: ${CONFIG}"
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200323 cat <<-EOF > ${CONFIG}
324 classes:
Petr Michalecd81d1f52017-08-17 20:18:06 +0200325 - cluster.${CLUSTER_NAME}.infra.config
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200326 parameters:
327 _param:
Petr Michaleca7de6df2017-08-31 12:16:57 +0200328 salt_master_host: ${MASTER_IP:-$MASTER_HOSTNAME}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200329 salt_master_base_environment: $SALT_ENV
Petr Michalecd81d1f52017-08-17 20:18:06 +0200330 salt_formula_branch: ${SALT_FORMULAS_BRANCH:-master}
331 reclass_data_revision: ${RECLASS_BRANCH:-master}
332 reclass_data_repository: "$RECLASS_ADDRESS"
Petr Michaleca7de6df2017-08-31 12:16:57 +0200333 reclass_config_master: ${MASTER_IP:-$MASTER_HOSTNAME}
Petr Michalecd81d1f52017-08-17 20:18:06 +0200334 linux_system_codename: ${DISTRIB_CODENAME}
335 cluster_name: ${CLUSTER_NAME}
336 cluster_domain: ${DOMAIN:-$CLUSTER_NAME.local}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200337 linux:
338 system:
Petr Michalecd81d1f52017-08-17 20:18:06 +0200339 name: ${HOSTNAME:-cfg01}
340 domain: ${DOMAIN:-$CLUSTER_NAME.local}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200341 # ########
342EOF
343
344 if [ "$SALT_VERSION" == "latest" ]; then
345 VERSION=""
346 else
347 VERSION="version: $SALT_VERSION"
348 fi
349
350 cat <<-EOF >> ${CONFIG}
351 salt:
352 master:
353 accept_policy: open_mode
354 source:
355 engine: $SALT_SOURCE
356 $VERSION
357 minion:
358 source:
359 engine: $SALT_SOURCE
360 $VERSION
361 # ########
362 # vim: ft=yaml sw=2 ts=2 sts=2
363EOF
364 fi
Petr Michalec24b30e82017-08-21 10:59:18 +0200365
366 log_debug "Salt Master node config yaml:"
367 log_debug "$(cat ${CONFIG})"
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200368}
369
370configure_salt_minion()
371{
372 [ ! -d /etc/salt/minion.d ] && mkdir -p /etc/salt/minion.d
373 cat <<-EOF > /etc/salt/minion.d/minion.conf
Petr Michaleca7de6df2017-08-31 12:16:57 +0200374 master: ${MASTER_IP:-$MASTER_HOSTNAME}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200375 id: $MINION_ID
376 EOF
377}
378
Petr Michaleca6cd2bd2017-09-07 16:59:19 +0200379install_reclass()
380{
381 VERSION=${1:-$RECLASS_VERSION}
Petr Michalec372fa032017-11-15 17:36:19 +0100382 VERSION=${VERSION:-pkg}
Petr Michalec800dd072017-11-15 17:19:26 +0100383 case ${VERSION} in
384 pkg|package)
385 which reclass || $SUDO $PKGTOOL install -y reclass
386 ;;
387 *)
Petr Michalec981f3cc2017-11-15 17:40:31 +0100388 log_warn "Install development version of reclass"
Petr Michalec1b37d3d2017-11-15 18:20:46 +0100389 # Note: dev/git/pip version...
390 # It replaces all local reclass versions on system
391 # Required for reclass/git features:
392 # $SUDO $PKGTOOL install -y libffi-dev libgit2-dev || true
Petr Michalec800dd072017-11-15 17:19:26 +0100393 for s in $(python -c "import site; print(' '.join(site.getsitepackages()))"); do
Petr Michalec23020832017-11-15 17:34:49 +0100394 sudo -H pip install --install-option="--prefix=" --upgrade --force-reinstall -I \
Petr Michalec800dd072017-11-15 17:19:26 +0100395 -t "$s" git+https://github.com/salt-formulas/reclass.git@${VERSION};
396 done
397 ;;
398 esac
Petr Michaleca6cd2bd2017-09-07 16:59:19 +0200399}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200400
401install_salt_master_pkg()
402{
403 echo -e "\nPreparing base OS repository ...\n"
404
405 configure_pkg_repo
406
407 echo -e "\nInstalling salt master ...\n"
408
409 case $PLATFORM_FAMILY in
410 debian)
411 $SUDO apt-get install -y git
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200412 curl -L https://bootstrap.saltstack.com | $SUDO sh -s -- -M ${BOOTSTRAP_SALTSTACK_OPTS} &>/dev/null || true
413 ;;
414 rhel)
415 yum install -y git
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200416 curl -L https://bootstrap.saltstack.com | $SUDO sh -s -- -M ${BOOTSTRAP_SALTSTACK_OPTS} &>/dev/null || true
417 ;;
418 esac
419
420 which reclass-salt || {
421 test -e /usr/share/reclass/reclass-salt && {
422 ln -fs /usr/share/reclass/reclass-salt /usr/bin
423 }
424 }
425
426 configure_salt_master
427
428 echo -e "\nRestarting services ...\n"
429 [ -f /etc/salt/pki/minion/minion_master.pub ] && rm -f /etc/salt/pki/minion/minion_master.pub
430 $SVCTOOL salt-master restart
431}
432
433install_salt_master_pip()
434{
435 echo -e "\nPreparing base OS repository ...\n"
436
437 case $PLATFORM_FAMILY in
438 debian)
439 $SUDO apt-get install -y python-pip python-dev zlib1g-dev git
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200440 ;;
441 rhel)
442 $SUDO yum install -y git
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200443 ;;
444 esac
445
446 echo -e "\nInstalling salt master ...\n"
447 # TODO: replace with saltstack bootstrap script
448
449 if [ "$SALT_VERSION" == "latest" ]; then
450 pip install salt
451 else
452 pip install salt==$SALT_VERSION
453 fi
454
455 curl -Lo /etc/init.d/salt-master https://anonscm.debian.org/cgit/pkg-salt/salt.git/plain/debian/salt-master.init && chmod 755 /etc/init.d/salt-master
456 ln -s /usr/local/bin/salt-master /usr/bin/salt-master
457
458 which reclass-salt || {
459 test -e /usr/share/reclass/reclass-salt && {
460 ln -fs /usr/share/reclass/reclass-salt /usr/bin
461 }
462 }
463
464 configure_salt_master
465
466 echo -e "\nRestarting services ...\n"
467 [ -f /etc/salt/pki/minion/minion_master.pub ] && rm -f /etc/salt/pki/minion/minion_master.pub
468 $SVCTOOL salt-master restart
469}
470
471
472
473install_salt_minion_pkg()
474{
475
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200476 echo -e "\nInstalling salt minion ...\n"
477
478 case $PLATFORM_FAMILY in
479 debian)
480 curl -L https://bootstrap.saltstack.com | $SUDO sh -s -- ${BOOTSTRAP_SALTSTACK_OPTS} &>/dev/null || true
481 ;;
482 rhel)
483 curl -L https://bootstrap.saltstack.com | $SUDO sh -s -- ${BOOTSTRAP_SALTSTACK_OPTS} &>/dev/null || true
484 ;;
485 esac
486
487
488 configure_salt_minion
Petr Michalec3b7fdd82017-09-08 15:35:56 +0200489 #$SVCTOOL salt-minion restart
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200490}
491
492install_salt_minion_pip()
493{
494 echo -e "\nInstalling salt minion ...\n"
495
496 curl -Lo /etc/init.d/salt-minion https://anonscm.debian.org/cgit/pkg-salt/salt.git/plain/debian/salt-minion.init && chmod 755 /etc/init.d/salt-minion
497 ln -s /usr/local/bin/salt-minion /usr/bin/salt-minion
498
499 configure_salt_minion
Petr Michalec3b7fdd82017-09-08 15:35:56 +0200500 #$SVCTOOL salt-minion restart
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200501}
502
503
504install_salt_formula_pkg()
505{
506 configure_pkg_repo
507
508 case $PLATFORM_FAMILY in
509 debian)
510 echo "Configuring necessary formulas ..."
511
512 [ ! -d ${RECLASS_ROOT}/classes/service ] && mkdir -p ${RECLASS_ROOT}/classes/service
513 # Set essentials if FORMULAS_SALT_MASTER is not defined at all
514 [ -z ${FORMULAS_SALT_MASTER+x} ] && declare -a FORMULAS_SALT_MASTER=("linux" "reclass" "salt" "memcached")
515 for formula_service in "${FORMULAS_SALT_MASTER[@]}"; do
516 echo -e "\nConfiguring salt formula ${formula_service} ...\n"
517 [ ! -d "${FORMULAS_PATH}/env/${formula_service}" ] && \
518 if ! $SUDO apt-get install -y salt-formula-${formula_service}; then
519 echo -e "\nInstall salt-formula-${formula_service} failed.\n"
520 exit 1
521 fi
522 [ ! -L "${RECLASS_ROOT}/classes/service/${formula_service}" ] && \
523 ln -sf ${FORMULAS_PATH}/reclass/service/${formula_service} ${RECLASS_ROOT}/classes/service/${formula_service}
524 done
525 ;;
526 rhel)
527 # TODO
528 ;;
529 esac
530
531 [ ! -d /srv/salt/env ] && mkdir -p /srv/salt/env || echo ""
532 [ ! -L /srv/salt/env/prd ] && ln -s ${FORMULAS_PATH}/env /srv/salt/env/prd || echo ""
533}
534
535install_salt_formula_git()
536{
537 echo "Configuring necessary formulas ..."
538
539 [ ! -d ${RECLASS_ROOT}/classes/service ] && mkdir -p ${RECLASS_ROOT}/classes/service
540 # Set essentials if FORMULAS_SALT_MASTER is not defined at all
541 [ -z ${FORMULAS_SALT_MASTER+x} ] && declare -a FORMULAS_SALT_MASTER=("linux" "reclass" "salt" "memcached")
542 for formula_service in "${FORMULAS_SALT_MASTER[@]}"; do
543 echo -e "\nConfiguring salt formula ${formula_service} ...\n"
544 _BRANCH=${FORMULAS_BRANCH}
545 [ ! -d "${FORMULAS_PATH}/env/_formulas/${formula_service}" ] && {
546 if ! git ls-remote --exit-code --heads ${FORMULAS_BASE}/salt-formula-${formula_service}.git ${_BRANCH}; then
547 # Fallback to the master branch if the branch doesn't exist for this repository
548 _BRANCH=master
549 fi
550 if ! git clone ${FORMULAS_BASE}/salt-formula-${formula_service}.git ${FORMULAS_PATH}/env/_formulas/${formula_service} -b ${_BRANCH}; then
551 echo -e "\nCloning of ${FORMULAS_BASE}/salt-formula-${formula_service}.git failed.\n"
552 exit 1
553 fi
554 } || {
555 cd ${FORMULAS_PATH}/env/_formulas/${formula_service};
556 git fetch origin/${_BRANCH} || git fetch --all
557 git checkout ${_BRANCH} && git pull || git pull;
558 cd -
559 }
560 [ ! -L "/usr/share/salt-formulas/env/${formula_service}" ] && \
561 ln -sf ${FORMULAS_PATH}/env/_formulas/${formula_service}/${formula_service} /usr/share/salt-formulas/env/${formula_service}
562 [ ! -L "${RECLASS_ROOT}/classes/service/${formula_service}" ] && \
563 ln -sf ${FORMULAS_PATH}/env/_formulas/${formula_service}/metadata/service ${RECLASS_ROOT}/classes/service/${formula_service}
564 done
565
566 [ ! -d /srv/salt/env ] && mkdir -p /srv/salt/env || echo ""
567 [ ! -L /srv/salt/env/dev ] && ln -s /usr/share/salt-formulas/env /srv/salt/env/dev || echo ""
568}
569
570
571saltmaster_bootstrap() {
572
573 log_info "Salt master setup"
574 test -n "$MASTER_HOSTNAME" || exit 1
575
576 clone_reclass
577 # override some envs from cluster level *.env, use with care
578 source_local_envs
579
Petr Michalec7ed7d8f2017-10-10 15:38:29 +0200580 pgrep salt-master | sed /$$/d | xargs --no-run-if-empty -i{} $SUDO kill -9 {} || true
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200581 pkill -9 salt-minion
projoke3c30e7d2017-10-19 17:15:40 +0800582 SCRIPTS=$(dirname $0)
583
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200584 test -e ${SCRIPTS}/.salt-master-setup.sh.passed || {
Adam Tengler035f24f2017-09-11 19:29:31 +0200585 export MASTER_IP=${MASTER_IP:-127.0.0.1}
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200586 export MINION_ID=${MASTER_HOSTNAME}
587 if ! [[ $DEBUG =~ ^(True|true|1|yes)$ ]]; then
588 SALT_MASTER_SETUP_OUTPUT='/dev/stdout'
589 fi
590 # call local "setup() master"
591 #if ! $SUDO ${SCRIPTS}/salt-master-setup.sh master &> ${SALT_MASTER_SETUP_OUTPUT:-/tmp/salt-master-setup.log}; then
592 if ! setup master; then
593 #cat /tmp/salt-master-setup.log
594 log_err "salt master setup() failed."
595 exit 1
596 else
597 $SUDO touch ${SCRIPTS}/.salt-master-setup.sh.passed
598 fi
599 }
600
Petr Michalec981f3cc2017-11-15 17:40:31 +0100601 log_info "Install reclass"
602 install_reclass ${RECLASS_VERSION/dev*/develop}
Petr Michaleca6cd2bd2017-09-07 16:59:19 +0200603
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200604 log_info "Re/starting salt services"
Petr Michalec7ed7d8f2017-10-10 15:38:29 +0200605 $SUDO service salt-minion stop
606 $SUDO service salt-master stop
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200607 sleep 10
Petr Michalec7ed7d8f2017-10-10 15:38:29 +0200608 pgrep salt-master | sed /$$/d | xargs --no-run-if-empty -i{} $SUDO kill -9 {} || true
609 pkill -9 salt-minion
610 $SUDO service salt-master start
611 $SUDO service salt-minion start
612 sleep 15
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200613}
614
615# Init salt master
616saltmaster_init() {
617
618 log_info "Runing saltmaster states"
619 test -n "$MASTER_HOSTNAME" || exit 1
620
621 set -e
622 $SUDO salt-call saltutil.sync_all >/dev/null
623
Petr Michalecda014202017-08-18 11:26:07 +0200624 # workarond isolated and not fully bootstraped environments
Petr Michalec2801acb2017-10-31 15:00:15 +0100625 if [[ $RECLASS_IGNORE_CLASS_NOTFOUND =~ ^(True|true|1|yes)$ ]]; then
Petr Michalec64adbd72017-10-31 15:26:41 +0100626 SALT_MASTER_PILLAR='"salt":{"master":{"pillar":{"reclass":{"ignore_class_notfound": "'${RECLASS_IGNORE_CLASS_NOTFOUND:-False}'", "ignore_class_regexp": ["service.*"]}}}},'
Petr Michalec2801acb2017-10-31 15:00:15 +0100627 fi
Petr Michalec85ef7ad2017-11-30 15:21:19 +0100628 PILLAR=\'{'${SALT_MASTER_PILLAR}' "reclass":{"storage":{"data_source":{"engine":"local"}}} }'\'
Petr Michalecda014202017-08-18 11:26:07 +0200629
Petr Michalec8b92d552017-11-29 12:28:50 +0100630 log_info "State: salt.master.env,salt.master.pillar"
Petr Michalec85ef7ad2017-11-30 15:21:19 +0100631 if ! retry ${SALT_STATE_RETRY} $SUDO salt-call ${SALT_OPTS} state.apply salt.master.env,salt.master.pillar pillar=$PILLAR; then
632 log_err "State \`salt.master.env,salt.master.pillar pillar=$PILLAR\` failed, keep your eyes wide open!"
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200633 fi
634
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200635 # Revert temporary SaltMaster minimal configuration, if any
636 pushd $RECLASS_ROOT
637 if [ $(git diff --name-only nodes | sort | uniq | wc -l) -ge 1 ]; then
Petr Michalec87778fc2017-11-02 10:13:25 +0100638 PILLAR='{"reclass":{"storage":{"data_source":{"engine":"local"}}} }'
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200639 git status || true
Petr Michalecda014202017-08-18 11:26:07 +0200640 log_warn "Locally modified $RECLASS_ROOT/nodes found. (Possibly salt-master minimized setup from bootstrap.sh call)"
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200641 log_info "Checkout HEAD state of $RECLASS_ROOT/nodes/*."
642 git checkout -- $RECLASS_ROOT/nodes || true
643 log_info "Re-Run states: salt.master.env and salt.master.pillar according the HEAD state."
Petr Michalec7edf8322017-11-30 12:01:09 +0100644 log_info "State: salt.master.env,salt.master.pillar"
Petr Michalec85ef7ad2017-11-30 15:21:19 +0100645 if ! retry ${SALT_STATE_RETRY} $SUDO salt-call ${SALT_OPTS} state.apply salt.master.env,salt.master.pillar pillar=$PILLAR; then
646 log_err "State \`salt.master.env,salt.master.pillar pillar=$PILLAR\` failed, keep your eyes wide open!"
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200647 fi
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200648 fi
649 popd
650
Petr Michalecda014202017-08-18 11:26:07 +0200651 # finally re-configure salt master conf, ie: may remove ignore_class_notfound option
652 log_info "State: salt.master.service"
Petr Michalec9fec8b32017-10-05 14:46:42 +0200653 retry ${SALT_STATE_RETRY} $SUDO salt-call ${SALT_OPTS} state.apply salt.master.service || true
Petr Michalecda014202017-08-18 11:26:07 +0200654
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200655 log_info "State: salt.master.storage.node"
656 set +e
Petr Michalec7edf8322017-11-30 12:01:09 +0100657 # TODO: PLACEHOLDER TO TRIGGER NODE GENERATION THROUG SALT REACT.
658 # FIXME: PLACEHOLDER TO TRIGGER NODE GENERATION THROUG SALT REACT.
Petr Michalec9fec8b32017-10-05 14:46:42 +0200659 retry ${SALT_STATE_RETRY} $SUDO salt-call ${SALT_OPTS} state.apply reclass.storage.node
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200660 ret=$?
661 set -e
662
663 if [[ $ret -eq 2 ]]; then
664 log_err "State reclass.storage.node failed with exit code 2 but continuing."
665 elif [[ $ret -ne 0 ]]; then
666 log_err "State reclass.storage.node failed with exit code $ret"
667 exit 1
668 fi
669
670 log_info "Re/starting salt services"
671 $SUDO sed -i 's/^master:.*/master: localhost/' /etc/salt/minion.d/minion.conf
Petr Michalecc0bfa972017-09-08 15:21:01 +0200672 $SUDO service salt-minion stop
673 $SUDO service salt-master stop
Petr Michalec7ed7d8f2017-10-10 15:38:29 +0200674 sleep 10
675 pgrep salt-master | sed /$$/d | xargs --no-run-if-empty -i{} $SUDO kill -9 {} || true
Petr Michalecc0bfa972017-09-08 15:21:01 +0200676 $SUDO service salt-master start
677 $SUDO service salt-minion start
Petr Michalec7ed7d8f2017-10-10 15:38:29 +0200678 sleep 15
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200679 $SUDO salt-call ${SALT_OPTS} saltutil.sync_all >/dev/null
680
681 verify_salt_master
682 set +e
683
684}
685
686
687function verify_salt_master() {
688 set -e
689
690 log_info "Verify Salt master"
691 test -n "$MASTER_HOSTNAME" || exit 1
692
693 if [[ $VERIFY_SALT_CALL =~ ^(True|true|1|yes)$ ]]; then
Petr Michaleca5141342017-08-16 12:55:20 +0200694 $SUDO salt-call ${SALT_OPTS} --id=${MASTER_HOSTNAME} reclass.validate_yaml > /tmp/${MASTER_HOSTNAME}.reclass.validate_yaml
695 $SUDO salt-call ${SALT_OPTS} --id=${MASTER_HOSTNAME} reclass.validate_pillar > /tmp/${MASTER_HOSTNAME}.reclass.validate_pillar
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200696 $SUDO salt-call ${SALT_OPTS} --id=${MASTER_HOSTNAME} grains.item roles > /tmp/${MASTER_HOSTNAME}.grains.item.roles
697 $SUDO salt-call ${SALT_OPTS} --id=${MASTER_HOSTNAME} state.show_lowstate > /tmp/${MASTER_HOSTNAME}.state.show_state
698 $SUDO salt-call --no-color grains.items
699 $SUDO salt-call --no-color pillar.data
700 fi
Petr Michaleca5141342017-08-16 12:55:20 +0200701 # TODO: REMOVE reclass --nodeinfo section / run only on debug - as the only required is reclass.validate_*
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200702 if ! $SUDO reclass --nodeinfo ${MASTER_HOSTNAME} > /tmp/${MASTER_HOSTNAME}.reclass.nodeinfo; then
703 log_err "For more details see full log /tmp/${MASTER_HOSTNAME}.reclass.nodeinfo"
704 exit 1
705 fi
Petr Michalec7edf8322017-11-30 12:01:09 +0100706 set +e
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200707}
708
709function verify_salt_minion() {
710 set -e
711 node=$1
712 log_info "Verifying ${node}"
713 if [[ $VERIFY_SALT_CALL =~ ^(True|true|1|yes)$ ]]; then
714 $SUDO salt-call ${SALT_OPTS} --id=${node} grains.item roles > /tmp/${node}.grains.item.roles
715 $SUDO salt-call ${SALT_OPTS} --id=${node} state.show_lowstate > /tmp/${node}.state.show_lowstate
716 fi
717 if ! $SUDO reclass --nodeinfo ${node} > /tmp/${node}.reclass.nodeinfo; then
718 log_err "For more details see full log /tmp/${node}.reclass.nodeinfo"
719 if [[ ${BREAK_ON_VERIFICATION_ERROR:-yes} =~ ^(True|true|1|yes)$ ]]; then
720 exit 1
721 fi
722 fi
Petr Michalec7edf8322017-11-30 12:01:09 +0100723 set +e
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200724}
725
726function verify_salt_minions() {
727 #set -e
Petr Michalec679f15b2017-09-18 16:16:29 +0200728 NODES=$(find $RECLASS_ROOT/nodes/_generated/ -name "*.yml" | grep -v "cfg")
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200729 log_info "Verifying minions: $(echo ${NODES}|xargs)"
730
731 # Parallel
732 #echo $NODES | parallel --no-notice -j 2 --halt 2 "verify_salt_minion \$(basename {} .yml) > {}.pillar_verify"
733 #ls -lrta *.pillar_verify | tail -n 1 | xargs -n1 tail -n30
734
735 function filterFails() {
736 grep -v '/grains' | tee -a $1 | tail -n20
737 }
738
739 log_info "Verify nodes"
740 passed=0
741 for node in ${NODES}; do
742 node=$(basename $node .yml)
743
744 # filter first in cluster.. ctl-01, mon-01, etc..
745 if [[ "${node//.*}" =~ 01 || "${node//.*}" =~ 02 ]] ;then
746 verify_salt_minion ${node} || continue
747 else
748 echo Skipped $node.
749 fi
750 passed=$(($passed+1))
751 done
752 # fail on failures
753 total=$(echo $NODES | xargs --no-run-if-empty -n1 echo |wc -l)
754 test ! $passed -lt $total || log_err "Results: $passed of $total passed."
755 test ! $passed -lt $total || {
756 tail -n50 /tmp/*.pillar_verify
757 return 1
758 }
Petr Michalec7edf8322017-11-30 12:01:09 +0100759 #set +e
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200760}
761
762
763
764##########################################
765# To install salt master/minon
766
767function install() {
768 setup $@
769}
770
771function setup() {
772 # CLI
773 while [ x"$1" != x"" ]; do
774 which curl &>/dev/null || $PKGTOOL -y install curl &>/dev/null
775
776 case $1 in
777 master )
778 install_salt_master_$SALT_SOURCE
779 install_salt_minion_$SALT_SOURCE
780 install_salt_formula_$FORMULAS_SOURCE
781 ;;
782 minion )
783 install_salt_minion_$SALT_SOURCE
784 ;;
785 esac
786 shift
787 done
788 echo DONE
789}
790
791function bootstrap() {
792 log_info "Bootstrap & verification of SaltMaster and configured minions."
793 trap _atexit INT TERM EXIT
794
795 system_config_master
796 saltmaster_bootstrap &&\
Petr Michalec58575b92017-08-20 10:42:25 +0200797 saltmaster_init #&&\
Petr Michaleca5141342017-08-16 12:55:20 +0200798 #verify_salt_minions
Petr Michalec1ed1b3c2017-08-08 19:19:01 +0200799}
800
801function default() {
802 bootstrap $@
803}
804
805
806##########################################
807[[ "$0" != "$BASH_SOURCE" ]] || {
808# unless file is being sourced
809 default $@
810}