From 3cd42882d317bea28501db270b5d14752e2e3d1b Mon Sep 17 00:00:00 2001 From: Alexander Lutay Date: Tue, 20 Mar 2018 17:11:15 +0100 Subject: [PATCH] TT#34318 Merge netscript.git code (commit 82bd20e) into deployment-iso.git We are going to provide common CE/PRO/Carrier install CD which will install one release only. So deployment-iso.git will follow the common NGCP branching/tagging model and will provide all the necessary information inside Install CD (including deployment.sh which previously was located into netscript.git). Change-Id: Ia74d8c83f966237815b19a4a503183dfe85aa9d5 --- .gitignore | 1 - Makefile | 22 +- debian/.gitignore | 8 + debian/changelog | 188 ++ debian/compat | 1 + debian/control | 24 + debian/copyright | 23 + debian/dirs | 1 + debian/install | 1 + debian/rules | 19 + debian/source/format | 1 + debian/source/options | 1 + t/Dockerfile | 33 + t/testrunner | 21 + templates/scripts/includes/deployment.sh | 2575 ++++++++++++++++++++++ templates/scripts/main.sh | 3 +- 16 files changed, 2908 insertions(+), 14 deletions(-) create mode 100644 debian/.gitignore create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/install create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/source/options create mode 100644 t/Dockerfile create mode 100755 t/testrunner create mode 100644 templates/scripts/includes/deployment.sh diff --git a/.gitignore b/.gitignore index 96fc48f..5340347 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,3 @@ grml64*.iso.sha1 templates/boot/grub/grub.cfg templates/boot/isolinux/isolinux.cfg templates/boot/isolinux/syslinux.cfg -templates/scripts/includes/netscript/ diff --git a/Makefile b/Makefile index 0ee88ac..8ee1392 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,30 @@ # for syntax checks BASH_SCRIPTS = ./templates/scripts/main.sh ./templates/scripts/includes/* ./build_iso.sh ./build_templates.sh - -RELEASE ?= trunk +NGCP_VERSION ?= $(shell git log --pretty=format:"%h" -1) +NGCP_VERSION := $(strip $(NGCP_VERSION)) all: build build: - @echo -n "Downloading deployment.sh scripts"; \ - wget -r --directory-prefix=./templates/scripts/includes/netscript/ --reject "index.html*" \ - --no-parent --no-host-directories --cut-dirs=1 "http://deb.sipwise.com/netscript/${RELEASE}/" ; \ - echo " done."; syntaxcheck: shellcheck shellcheck: @echo -n "Checking for shell syntax errors"; \ for SCRIPT in $(BASH_SCRIPTS); do \ - test -r $${SCRIPT} || continue ; \ - bash -n $${SCRIPT} || exit ; \ - echo -n "."; \ + test -r $${SCRIPT} || continue ; \ + bash -n $${SCRIPT} || exit ; \ + echo -n "."; \ done; \ echo " done."; \ +script_version: + echo "Adjust version information string in deployment.sh to ${NGCP_VERSION}" + sed -i "s/SCRIPT_VERSION=\"%SCRIPT_VERSION%\"/SCRIPT_VERSION=${NGCP_VERSION}/" \ + templates/scripts/includes/deployment.sh + clean: rm -f templates/boot/isolinux/syslinux.cfg - rm -rf templates/scripts/includes/netscript rm -f templates/boot/grub/grub.cfg rm -f templates/boot/isolinux/isolinux.cfg @@ -33,4 +33,4 @@ dist-clean: clean rm -f *.iso rm -f *.iso.sha1 -.PHONY: clean dist-clean syntaxcheck build all +.PHONY: clean dist-clean syntaxcheck shellcheck build all script_version diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 0000000..b7011e8 --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1,8 @@ +*.debhelper +*.log +*.substvars +/.debhelper/ +/debhelper-build-stamp +/files +/ngcp-deployment-iso/ +/ngcp-deployment-scripts/ \ No newline at end of file diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..d210d79 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,188 @@ +ngcp-deployment-iso (6.2.0.0+0~mr6.2.0.0) unstable; urgency=medium + + [ Michael Prokop ] + * [f0e7100] provide netscript and templates as separate package + * [db2e460] update to grml-live templates + * [da9f2de] Add package list for grml-sipwise ISO. + * [dcbae41] package config: add software for vmdebootstrap deployment + * [299637a] grml-live templates: drop ngcpmcast=226.94.1.1 (unused in HA v2 setup for now), default to ngcpeiface=eth0 (no bonding). + * [aa5048b] Provide documentation how to get a local mirror. + * [480464e] Add relevant template files for deployment ISO, update docs how to build a new ISO. + * [6bdd721] Drop unnecessary ngcp* bootoptions, change password from 'grml2011' to more generic 'grml'. + * [a545c0d] Provide grml-live, installer-testsuite and vmbuilder documentation in pro handbook. + * [74524ff] provide version specific sip:provider installation submenus + * [4a4ef1c] use sipwise as ssh password + * [238c953] No need to remaster the ISO any longer, just take the official Grml ISO and overlay our bootsplash stuff + * [f1cb5d4] deployment ISO: provide puppet + 2.5 release as entries in bootsplash + * [90bebb1] Provide boot menu entries for 2.6 release + pre-releases (ngcpautobuildrelease=...) + * [50e124a] provide grub.cfg to support [U]EFI boot on deployment ISO + * [29987bc] Provide sipwise logo and move Debian install options to submenu + * [64a7b0a] drop gfxpayload=keep from grub config so we get working UEFI boot on Dell hardware + * [2a0db7c] deployment ISO: provide Memtest86+ entry in boot splash + * [a5f86e6] add endtext for memtest86+ entry + * [0b42bcd] Update boot splash templates for 2.7 release + * [0c5a0ea] Deployment ISO: integrate submenu for Debian installations to support squeeze vs wheezy + * [09fc4b3] boot splash: provide back option in Debian release submenu + * [15be1e8] Explicitly set debianrelease boot option to be backwards and forward compatible + * [7c367fb] Provide boot menu entries for upcoming 3.0 stable release + * [93f1273] Fix debianrelease for ngcp 3.0 releases, drop duplicated debianrelease entries + * [81111cd] MT#6253 Initial templates for public Grml-Sipwise ISO + * [da2b541] MT#6253 Provide initial scripts + configs for customer deployments + * [c38b3f3] MT#6253 Add further boot entries to boot splash + * [7d79672] MT#6253 Support Debian installations, sync isolinux<->grub boot splashes + * [9a4d13d] MT#6253 Fix shebang line + * [56d68d2] MT#6253 Re-add missing trailing white space char in kernel command lines + * [d1b7bf0] MT#6253 Support usage of build script within git repository + * [1f055ee] MT#6253 Fix broken templates usage + * [e73f650] MT#6253 Properly exit if user doesn't want to deploy + * [29c796d] MT#6253 Improve prompting for public deployment ISO + * [4176153] MT#6253 Improve prompting to user for reboot and when cancelling + * [db3bbb7] MT#6253 Provide Makefile for syntaxcheck, cleanup and version handling + * [2036191] MT#6253 Fix script version usage + * [8aea373] MT#6253 Sync deployment.sh with status from netscript.git (12b283759) + * [7ea4f5e] MT#6253 Support setting target disk via TARGET_DISK env variable + * [09f9edf] MT#6253 Prompt user for target disk used for installation + * [7a0a08b] MT#6253 Improve prompting for netcardconfig + * [9aa7fd6] MT#6253 Sync deployment.sh with what we have in netscript.git as of commit 4222a9 + * [5361bac] MT#6253 Update fai-setup-storage + liblinux-lvm-perl to fix re-installation problem + * [9a3f98d] MT#6253 Enable ngcpnw.dhcp for DHCP entries, use Google's DNS server, add missing Debian/wheezy entries to Grub + * [6b846f5] MT#8347 Disable automatic boot / timeout + * [1fd3d0b] MT#6253 Display error message if "ngcp" PV exists already + * [a892da4] MT#6253 Sync deployment.sh with netscript.git + * [37239e5] MT#6253 Allow overwriting the disk that has a PV named "ngcp" + * [0103510] MT#6253 Fix check for target disk + * [c598296] MT#6253 Modify syntax to make it parseable by bash <4.3-7 + Zsh + * [cc98fb4] MT#9121 Sync deployment.sh with netscript.git (fixing 403 error with sipwise key) + * [f8dde4c] MT#12479 Use mgag200.modeset=0 as default boot option to mitigate Grml 2014.11 issue + * [9c3bd31] MT#12713 Add boot menu entries for Debian/jessie + * [d0d0ab1] MT#16709 Trunk installations are based on Debian/jessie now + * [71434f4] TT#9084 Default to Debian/jessie nowadays + * [eff3431] TT#15829 Ensure we run under 'set -e' + * [5dcee44] TT#15829 Use net.ifnames=0 by default, support Debian/stretch + sort GRUB menu + + [ Andreas Granig ] + * [1e5f621] Add 2.8 release and deprecate releases older than 2.4 + * [e6442b9] Reorder pre-releases and fix dns server. + + [ Andrew Pogrebennyk ] + * [0378d5f] Provide boot menu entries for 3.1 release. + * [9f7d06b] Add boot menu entries for 3.1 release to isolinux.cfg + * [b1cb4a4] MT#5847 Add PRO mr3.2.1 to deployment ISO. + * [74dfefc] MT#10421 Add mr3.6.2 release and mark it as latest + * [4a1c215] MT#10421 Add missed dot after mr3.6.1 release + * [30aa4ce] MT#13141 Add mr3.8.2 to releases file + * [6f3eaad] MT#16279 Add mr3.8.4 to releases file + * [1578dcf] MT#17685 Add mr3.8.5 to releases file + * [f33c94b] MT#19157 Add mr3.8.6 to releases file + + [ Alex Lutay ] + * [24e489f] MT#5847 Add mr3.2.1 support + * [4677daa] MT#6253 Add ngcpnoupload to trunk + * [9bb4e47] MT#6253 Sync deployment.sh (version 45bf9f2) + * [4e97c3b] MT#6253 Typo fixed (s/initrd.emg/initrd.img/) + * [27cf3a5] MT#6253 Removed SVN directories cleanup (using Git) + * [f517652] MT#6253 Merge build_release.sh and build_daily.sh into build_iso.sh + * [85d455d] MT#6253 Remove date for public install CD (documentation.git linking) + * [b358e3c] MT#7365 Move ip= option to the end, use Vienna IPs + * [b9a05e9] MT#7365 Move ip= option to the end, use Vienna IPs (stable release iso) + * [4f60c4a] MT#7365 Move ip= option (links 'latest' for non-public iso) + * [b8e6273] MT#6253 Improved boot screen layout + * [b71a7bf] MT#6253 Update hard disk typo + * [b18faf5] MT#6253 Restore support of 'devel/something.iso' GRML images + * [a7a9697] MT#8147 Add release mr3.3.2 and mark it as latest + * [9137b03] MT#8147 Add missed dot (it will be commmon mistake, need improvement here) + * [1ced947] MT#8871 Add mr3.4.2 to releases file + * [a9aba19] MT#8347 Remove auto-boot timeout for grub + * [160c3b1] MT#9191 Add initial Carrier 3.x menu for daily and release ISOs + * [fae5ba9] MT#9191 Add all the Carrier 3.x node types + * [ffbaf36] MT#9191 Restore ngcptrunk option for isolinux Carrier 3.X + * [539088d] MT#8473 Add mr3.5 and mr3.5.1 to releases file + * [f351561] MT#9919 Add mr3.6.1 release and mark it as latest + * [c685191] MT#7505 Add .gitreview file for deployment-iso + * [9ba39a6] MT#10093 Update boot menus to support PXE Carrier 3.x setup + * [4118fdd] MT#10277 Switch code to release-specific deployment.sh + * [60c4593] MT#11911 Add mr3.7.2 to releases file + * [bacb139] MT#11947 Include Sipwise keyring 'sipwise.gpg' into CE Install CD + * [8208be4] MT#9249 Fix 'make clean' (delete all generated sipwise_*.cfg files) + * [5148102] MT#9249 Add boot option 'ngcpfillcache' for Carrier + * [22610dc] MT#9249 Remove outdated boot option 'ngcpnoupload' + * [f010e6c] MT#11493 Add mr3.8 and mr3.8.1 releases + * [b43950e] MT#13679 Add mr4.0.1, mark mr4.0.1 as LATEST and mr3.8.2 as LTS + * [8d63df6] MT#14681 Add mr3.8.3 to releases file + * [4935b8e] MT#15581 Add mr4.1.1 to releases file + * [10189f4] MT#12713 Fix 9c3bd317: Add missed isolinux.cfg for jessie + * [0cd1223] MT#16755 Add mr4.2/mr4.2.1 to releases file + * [5663913] MT#17689 Add mr4.1.2 to releases + * [21a602d] MT#17685 Switch GRML iso from mirror.inode.at to deb.sipwise.com + * [2695d4f] MT#18419 Add mr4.3/mr4.3.1 to release file + * [1c40797] MT#19051 Add second DNS server for new installations + * [645f4f8] MT#19797 Add mr4.4/mr4.4.1 to releases file + * [33550d9] MT#20855 MT#20863 Add mr3.8.7 LTS and mr4.3.2 releases + * [b5a13fa] MT#20879 Add mr4.5.1 to deployment-iso releases file + * [634c0d7] MT#22083 Add GRML boot option nodhcp for all non-DHCP menu items + * [483bbb6] MT#22257 Change Carrier sample IP from 10.15.20.101 to 192.168.52.114 (to simplify testing) + * [cda3d64] TT#4162 Add mr4.4.2 to releases + * [2c72250] TT#4562 Add mr4.5.2 to the file 'release' + * [d41ef2b] TT#8299 Add mr4.5.3 to releases + * [325aac1] TT#10023 Add mr5.1/mr5.1.1 to releases + * [13f4233] TT#11315 Add mr5.0.2 to releases + * [a745d74] TT#11757 Add mr4.5.4 to releases + * [c62d200] TT#14939 Add mr3.8.10 LTS to releases + * [1189749] TT#16361 Add mr5.3.1 to releases + * [69051f7] TT#17032 Add mr4.5.5 LTS to releases + * [1adcca0] TT#19347 Remove 'latest' boot options from private (PRO/Carrier) ISOs + * [f08db1f] TT#19347 Move NGCP install option before Debian install options + * [0b4134a] TT#19347 Add missing space for boot option carrierweb01atrunkstatic + * [867e3ae] TT#19347 Improve label 'Install specific versions of CE/PRO/Carrier' + * [40bb927] TT#18360 Add mr5.4.1 to releases (mark mr5.4.1 as LATEST) + * [f9d1efc] TT#20300 Discontinue GRML boot option 'ngcptrunk' (use common 'ngcpvers=trunk') + * [42f3660] TT#20342 Add mr5.3.2 to releases + * [265cc33] TT#21905 Switch trunk/mr5.5 to Debian stretch + * [219d551] TT#21056 Add mr5.5.1 to releases + * [2d2623a] TT#26461 Add mr6.0(.1) to releases and mark it as the latest + * [25e147e] TT#34318 Merge netscript.git code (commit 82bd20e) into deployment-iso.git + + [ Victor Seva ] + * [da6de53] MT#6253 move jenkins scripts to repo. + * [d2a57a6] MT#6253 generate grub and isolinux include files for releases + * [193bda5] MT#6253 fix build.sh excution outside the source directory + * [2184a26] MT#6253 use templates too for public release + * [d578b66] MT#6659 add mr3.3.1 to releases list with LATEST tag + * [28b662e] MT#7945 add 3.4.1 and 3.4 versions + * [f1e0581] MT#8773 add DHCP option for PRO + * [eacff4b] MT#10805 add carrier support in templates + * [fd1ad85] MT#10805 Add mr3.7 and mr3.7.1 releases + * [62309fd] MT#16279 add mr4.0.2 release + * [46e679a] MT#19153 releases: Add mr4.2.2 + + [ Guillem Jover ] + * [f25f51e] MT#17177 Remove unused file + + [ Sergii Kipot ] + * [9489094] TT#4357 Add mr3.8.8 to deployment-iso releases file + * [f6c2566] TT#2385 Add mr5.0 and mr5.0.1 to releases + * [9e4857a] TT#8902 Add mr3.8.9 to deployment-iso releases file + * [efe928b] TT#12759 Add mr5.2/mr5.2.1 to releases + * [0a590a9] TT#14940 Add mr5.1.2 to releases + * [70a85cc] TT#17031 Add mr5.2.2 to releases + * [530dcf6] TT#20341 Add mr3.8.11 to releases + * [8c6ad3f] TT#21879 Add mr4.5.6 to releases + * [0d3e8ab] TT#21880 Add mr5.4.2 to releases + * [0192c68] TT#26460 Add mr3.8.12 to releases + * [9361812] TT#26463 Add mr4.5.7 to releases + * [1a720bc] TT#30371 Add mr6.1(.1) to releases and mark it as the latest + * [14b48fe] TT#33906 Add mr6.0.2 to releases + + [ Manuel Montecelo ] + * [4f607ab] TT#26462 Prepare and release mr5.5.2 + * [4429a61] TT#30372 Prepare release mr5.5.3 + + [ Mykola Malkov ] + * [35c1f29] TT#32751 Combine CE and Pro install cd + * [0616bb9] TT#32751 Remove obsolete not-used files + * [9bd4560] TT#32751 Build MR specific ISO files + * [85c8ec3] TT#32751 Remove outdated template files + * [2532db8] TT#32751 Update gitignore file + + -- Alex Lutay Tue, 20 Mar 2018 17:14:08 +0100 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..6151cac --- /dev/null +++ b/debian/control @@ -0,0 +1,24 @@ +Source: ngcp-deployment-iso +Section: admin +Priority: optional +Maintainer: Sipwise Development Team +Homepage: https://www.sipwise.com/ +Standards-Version: 3.9.8 +Build-Depends: + debhelper (>= 10), + git, + +Package: ngcp-deployment-scripts +Architecture: any +Depends: + ${misc:Depends}, + ${shlibs:Depends}, +Provides: + ngcp-netscript, +Breaks: + ngcp-netscript, +Replaces: + ngcp-netscript, +Description: NGCP deployment ISO scripts + Framework needed to install Sipwise NGCP system + using iPXE and GRML during the boot process. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..7c7a2d4 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,23 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Source: https://www.sipwise.com/ +Upstream-Contact: Sipwise Development Team + +Files: * +Copyright: + Copyright © 2007-2016 Sipwise GmbH, Austria +License: GPL-3+ + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . +Comment: + On Debian systems, the full text of the GNU General Public License + version 3 can be found in the file '/usr/share/common-licenses/GPL-3'. diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..817ef81 --- /dev/null +++ b/debian/dirs @@ -0,0 +1 @@ +/usr/share/ngcp-deployment-scripts diff --git a/debian/install b/debian/install new file mode 100644 index 0000000..ff4145f --- /dev/null +++ b/debian/install @@ -0,0 +1 @@ +templates/scripts/* usr/share/ngcp-deployment-scripts/ diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..d67e9bb --- /dev/null +++ b/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f +# Uncomment this to turn on verbose mode. +# export DH_VERBOSE=1 + +DEBVERSION:=$(shell head -n 1 debian/changelog \ + | sed -e 's/^[^(]*(\([^)]*\)).*/\1/') + +ifneq ($(GIT_COMMIT),) +export NGCP_VERSION := $(GIT_COMMIT) +else +export NGCP_VERSION:=$(DEBVERSION) +endif + +%: + dh $@ + +override_dh_auto_configure: + echo "NGCP_VERSION=$(NGCP_VERSION)" + make script_version diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 0000000..bcdff00 --- /dev/null +++ b/debian/source/options @@ -0,0 +1 @@ +extend-diff-ignore=.gitreview diff --git a/t/Dockerfile b/t/Dockerfile new file mode 100644 index 0000000..8209160 --- /dev/null +++ b/t/Dockerfile @@ -0,0 +1,33 @@ +# DOCKER_NAME=deployment-iso-stretch +FROM docker.mgm.sipwise.com/sipwise-stretch:latest + +# Important! Update this no-op ENV variable when this Dockerfile +# is updated with the current date. It will force refresh of all +# of the base images and things like `apt-get update` won't be using +# old cached versions when the Dockerfile is built. +ENV REFRESHED_AT 2018-03-20 + +RUN apt-get update && apt-get install --assume-yes git make + +RUN echo './t/testrunner' >>/root/.bash_history + +WORKDIR /code/ + +################################################################################ +# Instructions for usage +# ---------------------- +# When you want to build the base image from scratch +# jump to the next section if you don't want to build yourself!: +# +# % docker build --tag="lua-ngcp-kamailio-stretch" -f t/Dockerfile . +# % docker run --rm -i -t -v $(pwd):/code:rw lua-ngcp-kamailio-stretch:latest bash +# +# Use the existing docker image: +# % docker pull docker.mgm.sipwise.com/lua-ngcp-kamailio-stretch +# NOTE: run the following command from root folder of git repository: +# % docker run --rm -i -t -v $(pwd):/code:rw docker.mgm.sipwise.com/lua-ngcp-kamailio-stretch:latest bash +# +# Inside docker (the command is in history, just press UP button): +# ./t/testrunner +# +################################################################################ diff --git a/t/testrunner b/t/testrunner new file mode 100755 index 0000000..981e1c7 --- /dev/null +++ b/t/testrunner @@ -0,0 +1,21 @@ +#!/bin/bash +# This script is used for running the tests with proper arguments +# from within Jenkins + +set -e +set -u + +if [ -d /results ] ; then + # Running from Jenkins (RW) + RESULTS="/results" + + cd "/code" +else + # Running locally in Docker + RESULTS="./results" + mkdir -p "${RESULTS}" +fi + +make +make syntaxcheck +make script_version diff --git a/templates/scripts/includes/deployment.sh b/templates/scripts/includes/deployment.sh new file mode 100644 index 0000000..a147195 --- /dev/null +++ b/templates/scripts/includes/deployment.sh @@ -0,0 +1,2575 @@ +#!/bin/bash +# Purpose: automatically install Debian + sip:provider platform +################################################################################ + +INSTALL_LOG='/tmp/deployment-installer-debug.log' +exec > >(tee -a $INSTALL_LOG ) +exec 2> >(tee -a $INSTALL_LOG >&2) + +# set version to git commit ID +SCRIPT_VERSION="%SCRIPT_VERSION%" + +# not set? then fall back to timestamp of execution +if [ -z "$SCRIPT_VERSION" ] || [ "$SCRIPT_VERSION" = '%SCRIPT_VERSION%' ] ; then + SCRIPT_VERSION=$(date +%s) # seconds since 1970-01-01 00:00:00 UTC +fi + +# Never ever execute the script outside of a +# running Grml live system because partitioning +# disks might destroy data. Seriously. +if ! [ -r /etc/grml_cd ] ; then + echo "Not running inside Grml, better safe than sorry. Sorry." >&2 + exit 1 +fi + +# better safe than sorry +export LC_ALL=C +export LANG=C + +# avoid SHELL being set but not available, causing needrestart failure, see #788819 +unset SHELL + +# defaults +DEBUG_MODE=false +DEFAULT_INSTALL_DEV=eth0 +DEFAULT_IP1=192.168.255.251 +DEFAULT_IP2=192.168.255.252 +DEFAULT_IP_HA_SHARED=192.168.255.250 +DEFAULT_INTERNAL_NETMASK=255.255.255.248 +DEFAULT_MCASTADDR=226.94.1.1 +DEFAULT_EXT_IP=192.168.52.114 +DEFAULT_EXT_NETMASK=255.255.255.0 +DEFAULT_EXT_GW=192.168.52.1 +TARGET=/mnt +PRO_EDITION=false +CE_EDITION=false +CARRIER_EDITION=false +NGCP_INSTALLER=false +PUPPET='' +PUPPET_SERVER=puppet2.mgm.sipwise.com +PUPPET_GIT_REPO='' +PUPPET_GIT_BRANCH=master +PUPPET_LOCAL_GIT="${TARGET}/tmp/puppet.git" +PUPPET_RESCUE_PATH="/mnt/rescue_drive" +PUPPET_RESCUE_LABEL="SIPWRESCUE*" +RESTART_NETWORK=true +INTERACTIVE=false +DHCP=false +LOGO=true +BONDING=false +VLAN=false +VLANID='' +VLANIF='' +RETRIEVE_MGMT_CONFIG=false +TRUNK_VERSION=false +DEBIAN_RELEASE=stretch +HALT=false +REBOOT=false +STATUS_DIRECTORY=/srv/deployment/ +STATUS_WAIT=0 +LVM=true +VAGRANT=false +ADJUST_FOR_LOW_PERFORMANCE=false +ENABLE_VM_SERVICES=false +FILESYSTEM="ext4" +GPG_KEY_SERVER="pool.sks-keyservers.net" +DEBIAN_REPO_HOST="debian.sipwise.com" +DEBIAN_REPO_TRANSPORT="https" +SIPWISE_REPO_HOST="deb.sipwise.com" +SIPWISE_REPO_TRANSPORT="https" +DPL_MYSQL_REPLICATION=true +FILL_APPROX_CACHE=false +VLAN_BOOT_INT=2 +VLAN_SSH_EXT=300 +VLAN_WEB_EXT=1718 +VLAN_SIP_EXT=1719 +VLAN_SIP_INT=1720 +VLAN_HA_INT=1721 +VLAN_RTP_EXT=1722 +NGCP_INIT_SYSTEM="systemd" + +### helper functions {{{ +get_deploy_status() { + if [ -r "${STATUS_DIRECTORY}/status" ] ; then + cat "${STATUS_DIRECTORY}/status" + else + echo 'error' + fi +} + +set_deploy_status() { + [ -n "$1" ] || return 1 + echo "$*" > "${STATUS_DIRECTORY}"/status +} + +enable_deploy_status_server() { + mkdir -p "${STATUS_DIRECTORY}" + + # get rid of already running process + PID=$(pgrep -f 'python.*SimpleHTTPServer') || true + [ -n "$PID" ] && kill "$PID" + + ( + cd "${STATUS_DIRECTORY}" + python -m SimpleHTTPServer 4242 >/tmp/status_server.log 2>&1 & + ) +} + +CMD_LINE=$(cat /proc/cmdline) +stringInString() { + local to_test_="$1" # matching pattern + local source_="$2" # string to search in + case "$source_" in *$to_test_*) return 0;; esac + return 1 +} + +checkBootParam() { + stringInString " $1" "$CMD_LINE" + return "$?" +} + +getBootParam() { + local param_to_search="$1" + local result='' + + stringInString " $param_to_search=" "$CMD_LINE" || return 1 + result="${CMD_LINE##*$param_to_search=}" + result="${result%%[ ]*}" + echo "$result" + return 0 +} + +# load ":"-separated nfs ip into array BP[client-ip], BP[server-ip], ... +# ip=:::::: +# $1: Array name (needs "declare -A BP" before call), $2: ip=... string +loadNfsIpArray() { + [ -n "$1" ] && [ -n "$2" ] || return 0 + local IFS=":" + local ind=(client-ip server-ip gw-ip netmask hostname device autoconf) + local i + for i in $2 ; do + eval "$1[${ind[n++]}]=$i" + done + [ "$n" == "7" ] && return 0 || return 1 +} + +debootstrap_sipwise_key() { + mkdir -p /etc/debootstrap/pre-scripts/ + cat > /etc/debootstrap/pre-scripts/install-sipwise-key.sh << EOF +#!/bin/bash +# installed via deployment.sh +cp /etc/apt/trusted.gpg.d/sipwise.gpg "\${MNTPOINT}"/etc/apt/trusted.gpg.d/ +EOF + chmod 775 /etc/debootstrap/pre-scripts/install-sipwise-key.sh +} + +install_sipwise_key() { + if [ -f "/etc/apt/trusted.gpg.d/sipwise.gpg" ]; then + md5sum_sipwise_key=$(md5sum /etc/apt/trusted.gpg.d/sipwise.gpg | awk '{print $1}') + echo "Sipwise keyring already installed (MD5: [${md5sum_sipwise_key}]), debootstrap sipwise key" + debootstrap_sipwise_key + return + else + echo "Sipwise keyring not found, downloading." + fi + + for x in 1 2 3; do + + if "$PRO_EDITION" ; then + wget -O /etc/apt/trusted.gpg.d/sipwise.gpg ${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/sppro/sipwise.gpg + else + wget -O /etc/apt/trusted.gpg.d/sipwise.gpg ${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/spce/sipwise.gpg + fi + + md5sum_sipwise_key_expected=bcd09c9ad563b2d380152a97d5a0ea83 + md5sum_sipwise_key_calculated=$(md5sum /etc/apt/trusted.gpg.d/sipwise.gpg | awk '{print $1}') + + if [ "$md5sum_sipwise_key_calculated" != "$md5sum_sipwise_key_expected" ] ; then + echo "Sipwise keyring has wrong checksum (expected: [$md5sum_sipwise_key_expected] - got: [$md5sum_sipwise_key_calculated]), retry $x" + else + break + fi + done + + if [ "$md5sum_sipwise_key_calculated" != "$md5sum_sipwise_key_expected" ] ; then + die "Error validating sipwise keyring for apt usage, aborting installation." + fi + + debootstrap_sipwise_key +} + +install_apt_transport_https () { + echo "Installing apt-transport-https" + + if [ "$(dpkg-query -f "\${db:Status-Status} \${db:Status-Eflag}" -W apt-transport-https 2>/dev/null)" = 'installed ok' ]; then + echo "apt-transport-https is already installed, nothing to do about it." + return 0 + fi + + # use temporary apt database for speed reasons + local TMPDIR + TMPDIR=$(mktemp -d) + mkdir -p "${TMPDIR}/etc/preferences.d" "${TMPDIR}/statedir/lists/partial" \ + "${TMPDIR}/cachedir/archives/partial" + echo "deb http://${DEBIAN_REPO_HOST}/debian/ ${DEBIAN_RELEASE} main contrib non-free" > \ + "${TMPDIR}/etc/sources.list" + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::state="${TMPDIR}/statedir" -o dir::etc="${TMPDIR}/etc" \ + -o dir::etc::trustedparts="/etc/apt/trusted.gpg.d/" update + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::etc="${TMPDIR}/etc" -o dir::state="${TMPDIR}/statedir" \ + -o dir::etc::trustedparts="/etc/apt/trusted.gpg.d/" \ + -y --no-install-recommends install apt-transport-https +} + +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=776917 +debootstrap_upgrade() { + local required_version=1.0.87 + local present_version + + present_version=$(dpkg-query --show --showformat="\${Version}" debootstrap) + + if dpkg --compare-versions "${present_version}" lt "${required_version}" ; then + echo "deboostrap version $present_version is older than minimum required version $required_version - upgrading." + + # use temporary apt database for speed reasons + local TMPDIR + TMPDIR=$(mktemp -d) + mkdir -p "${TMPDIR}/statedir/lists/partial" "${TMPDIR}/cachedir/archives/partial" + local debsrcfile + debsrcfile=$(mktemp) + echo "deb ${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/debian stretch main" >> "$debsrcfile" + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::state="${TMPDIR}/statedir" -o dir::etc::sourcelist="$debsrcfile" \ + -o Dir::Etc::sourceparts=/dev/null update + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::state="${TMPDIR}/statedir" -o dir::etc::sourcelist="$debsrcfile" \ + -o Dir::Etc::sourceparts=/dev/null -y install debootstrap + fi +} + +grml_debootstrap_upgrade() { + local required_version=0.74 + local present_version + + present_version=$(dpkg-query --show --showformat="\${Version}" grml-debootstrap) + + if dpkg --compare-versions "${present_version}" lt "${required_version}" ; then + echo "grml-deboostrap version $present_version is older than minimum required version $required_version - upgrading." + + # use temporary apt database for speed reasons + local TMPDIR + TMPDIR=$(mktemp -d) + mkdir -p "${TMPDIR}/statedir/lists/partial" "${TMPDIR}/cachedir/archives/partial" + local debsrcfile + debsrcfile=$(mktemp) + echo "deb ${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/grml.org grml-testing main" >> "$debsrcfile" + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::state="${TMPDIR}/statedir" -o dir::etc::sourcelist="$debsrcfile" \ + -o Dir::Etc::sourceparts=/dev/null update + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::state="${TMPDIR}/statedir" -o dir::etc::sourcelist="$debsrcfile" \ + -o Dir::Etc::sourceparts=/dev/null -y install grml-debootstrap + fi +} + +install_vbox_iso() { + echo "Downloading virtualbox-guest-additions ISO" + + local vbox_checksum="6df8c8ab6e7ac3a70a5e29116f8a5dcdb7dfbd0b226ef849a5cd9502e956b06f" # sha256 + local vbox_iso="VBoxGuestAdditions_5.1.26.iso" + + mkdir -p "/usr/share/virtualbox/" + vbox_isofile="/usr/share/virtualbox/${vbox_iso}" + wget -c -O "$vbox_isofile" "https://deb.sipwise.com/files/${vbox_iso}" + + echo "${vbox_checksum} ${vbox_isofile}" | sha256sum --check || die "Error: failed to compute checksum for Virtualbox ISO. Exiting." +} + +set_custom_grub_boot_options() { + echo "Adjusting default GRUB boot options (enabling net.ifnames=0)" + sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 net.ifnames=0"/' "${TARGET}/etc/default/grub" + + echo "Invoking update-grub" + grml-chroot $TARGET update-grub + + if [ -d "${TARGET}/etc/.git" ]; then + echo "Commit /etc/default/grub changes using etckeeper" + chroot "$TARGET" etckeeper commit "/etc/default/grub changes" + fi +} + +ensure_augtool_present() { + if [ -x /usr/bin/augtool ] ; then + echo "/usr/bin/augtool is present, nothing to do" + return 0 + fi + + echo "augtool isn't present, installing augeas-tools package:" + + # use temporary apt database for speed reasons + local TMPDIR + TMPDIR=$(mktemp -d) + mkdir -p "${TMPDIR}/etc/preferences.d" "${TMPDIR}/statedir/lists/partial" \ + "${TMPDIR}/cachedir/archives/partial" + echo "deb http://${DEBIAN_REPO_HOST}/debian/ ${DEBIAN_RELEASE} main contrib non-free" > \ + "${TMPDIR}/etc/sources.list" + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::state="${TMPDIR}/statedir" -o dir::etc="${TMPDIR}/etc" \ + -o dir::etc::trustedparts="/etc/apt/trusted.gpg.d/" update + + DEBIAN_FRONTEND='noninteractive' apt-get -o dir::cache="${TMPDIR}/cachedir" \ + -o dir::etc="${TMPDIR}/etc" -o dir::state="${TMPDIR}/statedir" \ + -o dir::etc::trustedparts="/etc/apt/trusted.gpg.d/" \ + -y --no-install-recommends install augeas-tools +} +### }}} + +# logging {{{ +#cat > /etc/rsyslog.d/logsend.conf << EOF +#*.* @@192.168.51.28 +#EOF +#/etc/init.d/rsyslog restart + +logit() { + logger -t grml-deployment "$@" +} + +die() { + logger -t grml-deployment "$@" + echo "$@" >&2 + set_deploy_status "error" + exit 1 +} + +enable_trace() { + if "${DEBUG_MODE}" ; then + set -x + PS4='+\t ' + fi +} + +disable_trace() { + if "${DEBUG_MODE}" ; then + set +x + PS4='' + fi +} + + +logit "host-IP: $(ip-screen)" +logit "deployment-version: $SCRIPT_VERSION" +# }}} + +enable_deploy_status_server + +set_deploy_status "checkBootParam" + +if checkBootParam debugmode ; then + DEBUG_MODE=true + enable_trace +fi + +if checkBootParam targetdisk ; then + TARGET_DISK=$(getBootParam targetdisk) +fi + +# if TARGET_DISK environment variable is set accept it +if [ -n "$TARGET_DISK" ] ; then + export DISK="${TARGET_DISK}" +else # otherwise try to find sane default + if [ -L /sys/block/vda ] ; then + export DISK=vda # will be configured as /dev/vda + else + # in some cases, sda is not the HDD, but the CDROM, + # so better walk through all devices. + for i in /sys/block/sd*; do + if grep -q 0 "${i}/removable"; then + DISK=$(basename "$i") + export DISK + break + fi + done + fi +fi + +[ -z "${DISK}" ] && die "Error: No non-removable disk suitable for installation found" + +if checkBootParam ngcpstatus ; then + STATUS_WAIT=$(getBootParam ngcpstatus || true) + [ -n "$STATUS_WAIT" ] || STATUS_WAIT=30 +fi + +if checkBootParam noinstall ; then + echo "Exiting as requested via bootoption noinstall." + exit 0 +fi + +if checkBootParam nocolorlogo ; then + LOGO=false +fi + +if checkBootParam ngcpnobonding ; then + BONDING=false +fi + +if checkBootParam ngcpbonding ; then + BONDING=true +fi + +if checkBootParam vlan ; then + VLANPARAMS=($(getBootParam vlan | tr ":" "\n")) + if [ ${#VLANPARAMS[@]} -eq 2 ] ; then + VLAN=true + VLANID=${VLANPARAMS[0]} + VLANIF=${VLANPARAMS[1]} + fi +fi + +if checkBootParam ngcpmgmt ; then + MANAGEMENT_IP=$(getBootParam ngcpmgmt) + RETRIEVE_MGMT_CONFIG=true +fi + +## detect environment {{{ +CHASSIS="No physical chassis found" +if dmidecode| grep -q 'Rack Mount Chassis' ; then + CHASSIS="Running in Rack Mounted Chassis." +elif dmidecode| grep -q 'Location In Chassis: Not Specified'; then + : +elif dmidecode| grep -q 'Location In Chassis'; then + CHASSIS="Running in blade chassis $(dmidecode| awk '/Location In Chassis: Slot/ {print $4}')" +fi + +if checkBootParam ngcpinst || checkBootParam ngcpsp1 || checkBootParam ngcpsp2 || \ + checkBootParam ngcppro || checkBootParam ngcpce ; then + NGCP_INSTALLER=true +fi + +if checkBootParam ngcpce ; then + CE_EDITION=true +fi + +if checkBootParam ngcppro || checkBootParam ngcpsp1 || checkBootParam ngcpsp2 ; then + PRO_EDITION=true +fi + +if "$PRO_EDITION" ; then + ROLE=sp1 + + if checkBootParam ngcpsp2 ; then + ROLE=sp2 + fi +fi + +if checkBootParam "puppetenv" ; then + # we expected to get the environment for puppet + PUPPET=$(getBootParam puppetenv) +fi + +if checkBootParam "puppetserver" ; then + PUPPET_SERVER=$(getBootParam puppetserver) +fi + +if checkBootParam "puppetgitrepo" ; then + PUPPET_GIT_REPO=$(getBootParam puppetgitrepo) +fi + +if checkBootParam "puppetgitbranch" ; then + PUPPET_GIT_BRANCH=$(getBootParam puppetgitbranch) +fi + +if checkBootParam "debianrelease" ; then + DEBIAN_RELEASE=$(getBootParam debianrelease) +fi + +ARCH=$(dpkg --print-architecture) +if checkBootParam "arch" ; then + ARCH=$(getBootParam arch) +fi + +# test unfinished releases against +# "https://deb.sipwise.com/autobuild/ release-$AUTOBUILD_RELEASE" +if checkBootParam ngcpautobuildrelease ; then + AUTOBUILD_RELEASE=$(getBootParam ngcpautobuildrelease) + export SKIP_SOURCES_LIST=true # make sure it's available within grml-chroot subshell +fi + +# existing ngcp releases (like 2.2) with according repository and installer +if checkBootParam ngcpvers ; then + SP_VERSION=$(getBootParam ngcpvers) + if [ "${SP_VERSION:-}" = "trunk" ] ; then + TRUNK_VERSION=true + fi + export TRUNK_VERSION # make sure it's available within grml-chroot subshell +fi + +if checkBootParam nongcp ; then + echo "Will not execute ngcp-installer as requested via bootoption nongcp." + NGCP_INSTALLER=false +fi + +# configure static network in installed system? +if checkBootParam ngcpnw.dhcp ; then + DHCP=true +fi + +if checkBootParam ngcphostname ; then + TARGET_HOSTNAME="$(getBootParam ngcphostname)" || true +fi + +if [ -n "$TARGET_HOSTNAME" ] ; then + export HOSTNAME="$TARGET_HOSTNAME" +else + [ -n "$HOSTNAME" ] || HOSTNAME="nohostname" + export HOSTNAME +fi + +if checkBootParam ngcpip1 ; then + IP1=$(getBootParam ngcpip1) +fi + +if checkBootParam ngcpip2 ; then + IP2=$(getBootParam ngcpip2) +fi + +if checkBootParam ngcpipshared ; then + IP_HA_SHARED=$(getBootParam ngcpipshared) +fi + +if checkBootParam ngcpnetmask ; then + INTERNAL_NETMASK=$(getBootParam ngcpnetmask) +fi + +if checkBootParam ngcpextnetmask ; then + EXTERNAL_NETMASK=$(getBootParam ngcpextnetmask) +fi + +if checkBootParam ngcpeaddr ; then + EADDR=$(getBootParam ngcpeaddr) +fi + +if checkBootParam ngcpeiface ; then + EIFACE=$(getBootParam ngcpeiface) +fi + +if checkBootParam ngcpmcast ; then + MCASTADDR=$(getBootParam ngcpmcast) +fi + +if checkBootParam ngcpcrole ; then + CROLE=$(getBootParam ngcpcrole) + CARRIER_EDITION=true +fi + +if checkBootParam ngcpnolvm ; then + logit "Disabling LVM due to ngcpnolvm boot option" + LVM=false +fi + +case "$SP_VERSION" in + 2.*) + logit "Disabling LVM due to SP_VERSION [$SP_VERSION] matching 2.*" + LVM=false + ;; +esac + +case "$SP_VERSION" in + 2.*|3.0|3.1|mr3.2*) + FILESYSTEM="ext3" + logit "Using filesystem $FILESYSTEM for sip:provider release ${SP_VERSION}" + ;; +esac + +# allow forcing LVM mode +if checkBootParam ngcplvm ; then + logit "Enabling LVM due to ngcplvm boot option" + LVM=true +fi + +if checkBootParam ngcphalt ; then + HALT=true +fi + +if checkBootParam ngcpreboot ; then + REBOOT=true +fi + +if checkBootParam vagrant ; then + VAGRANT=true +fi + +if checkBootParam lowperformance ; then + ADJUST_FOR_LOW_PERFORMANCE=true +fi + +if checkBootParam enablevmservices ; then + ENABLE_VM_SERVICES=true +fi + +if checkBootParam ngcpnonwrecfg ; then + logit "Disabling reconfig network as requested via boot option ngcpnonwrecfg" + RESTART_NETWORK=false +fi + +if checkBootParam "debianrepo=" ; then + DEBIAN_REPO_HOST=$(getBootParam debianrepo) +fi + +if checkBootParam "sipwiserepo=" ; then + SIPWISE_REPO_HOST=$(getBootParam sipwiserepo) +fi + +if checkBootParam ngcpnomysqlrepl ; then + DPL_MYSQL_REPLICATION=false +fi + +if checkBootParam ngcpfillcache ; then + FILL_APPROX_CACHE=true +fi + +if checkBootParam ngcpvlanbootint ; then + VLAN_BOOT_INT=$(getBootParam ngcpvlanbootint) +fi + +if checkBootParam ngcpvlansshext ; then + VLAN_SSH_EXT=$(getBootParam ngcpvlansshext) +fi + +if checkBootParam ngcpvlanwebext ; then + VLAN_WEB_EXT=$(getBootParam ngcpvlanwebext) +fi + +if checkBootParam ngcpvlansipext ; then + VLAN_SIP_EXT=$(getBootParam ngcpvlansipext) +fi + +if checkBootParam ngcpvlansipint ; then + VLAN_SIP_INT=$(getBootParam ngcpvlansipint) +fi + +if checkBootParam ngcpvlanhaint ; then + VLAN_HA_INT=$(getBootParam ngcpvlanhaint) +fi + +if checkBootParam ngcpvlanrtpext ; then + VLAN_RTP_EXT=$(getBootParam ngcpvlanrtpext) +fi + +if checkBootParam ngcpppa ; then + NGCP_PPA=$(getBootParam ngcpppa) +fi + +if checkBootParam ngcpppainstaller ; then + NGCP_PPA_INSTALLER=$(getBootParam ngcpppainstaller) +fi + +if checkBootParam debianrepotransport ; then + DEBIAN_REPO_TRANSPORT=$(getBootParam debianrepotransport) +fi + +if checkBootParam sipwiserepotransport ; then + SIPWISE_REPO_TRANSPORT=$(getBootParam sipwiserepotransport) +fi + +if checkBootParam debootstrapkey ; then + GPG_KEY=$(getBootParam debootstrapkey) +fi + +if checkBootParam ngcpinitsystem ; then + NGCP_INIT_SYSTEM=$(getBootParam ngcpinitsystem) + logit "Using init system '${NGCP_INIT_SYSTEM}' as requested via boot option ngcpinitsystem" +fi +## }}} + +## interactive mode {{{ +# support command line options, overriding autodetected defaults +INTERACTIVE=true + +if [ -n "$NETSCRIPT" ] ; then + echo "Automatic deployment via bootoption netscript detected." + INTERACTIVE=false +fi + +usage() { + echo "$0 - automatically deploy Debian ${DEBIAN_RELEASE} and (optionally) ngcp ce/pro. + +Control installation parameters: + + ngcppro - install Pro Edition + ngcpsp1 - install first node (Pro Edition only) + ngcpsp2 - install second node (Pro Edition only) + ngcpce - install CE Edition + ngcpcrole=... - server role (Carrier) + ngcpvers=... - install specific SP/CE version + nongcp - do not install NGCP but install plain Debian only + noinstall - do not install neither Debian nor NGCP + ngcpinst - force usage of NGCP installer + ngcpinstvers=... - use specific NGCP installer version + debianrepo=... - hostname of Debian APT repository mirror + sipwiserepo=... - hostname of Sipwise APT repository mirror + ngcpnomysqlrepl - skip MySQL sp1<->sp2 replication configuration/check + ngcpppa=... - use NGCP PPA Debian repository + +Control target system: + + ngcpnw.dhcp - use DHCP as network configuration in installed system + ngcphostname=... - hostname of installed system (defaults to ngcp/sp[1,2]) + NOTE: do NOT use when installing Pro Edition! + ngcpeiface=... - external interface device (defaults to eth0) + ngcpip1=... - IP address of first node + ngcpip2=... - IP address of second node + ngcpipshared=... - HA shared IP address + ngcpnetmask=... - netmask of ha_int interface + ngcpeaddr=... - Cluster IP address + +The command line options correspond with the available bootoptions. +Command line overrides any present bootoption. + +Usage examples: + + # ngcp-deployment ngcpce ngcpnw.dhcp + + # netcardconfig # configure eth0 with static configuration + # ngcp-deployment ngcppro ngcpsp1 + + # netcardconfig # configure eth0 with static configuration + # ngcp-deployment ngcppro ngcpsp2 +" +} + +for param in "$@" ; do + case $param in + *-h*|*--help*|*help*) usage ; exit 0;; + *ngcpsp1*) ROLE=sp1 ; TARGET_HOSTNAME=sp1; PRO_EDITION=true; CE_EDITION=false ; NGCP_INSTALLER=true ;; + *ngcpsp2*) ROLE=sp2 ; TARGET_HOSTNAME=sp2; PRO_EDITION=true; CE_EDITION=false ; NGCP_INSTALLER=true ;; + *ngcppro*) PRO_EDITION=true; CE_EDITION=false ; NGCP_INSTALLER=true ;; + *ngcpce*) PRO_EDITION=false; CE_EDITION=true ; TARGET_HOSTNAME=spce ; ROLE='' ; NGCP_INSTALLER=true ;; + *ngcpvers=*) SP_VERSION="${param//ngcpvers=/}";; + *nongcp*) NGCP_INSTALLER=false;; + *noinstall*) NGCP_INSTALLER=false;; + *ngcpinst*) NGCP_INSTALLER=true;; + *ngcphostname=*) TARGET_HOSTNAME="${param//ngcphostname=/}";; + *ngcpeiface=*) EIFACE="${param//ngcpeiface=/}";; + *ngcpeaddr=*) EADDR="${param//ngcpeaddr=/}";; + *ngcpip1=*) IP1="${param//ngcpip1=/}";; + *ngcpip2=*) IP2="${param//ngcpip2=/}";; + *ngcpipshared=*) IP_HA_SHARED="${param//ngcpipshared=/}";; + *ngcpnetmask=*) INTERNAL_NETMASK="${param//ngcpnetmask=/}";; + *ngcpextnetmask=*) EXTERNAL_NETMASK="${param//ngcpextnetmask=/}";; + *ngcpmcast=*) MCASTADDR="${param//ngcpmcast=/}";; + *ngcpcrole=*) CARRIER_EDITION=true; CROLE="${param//ngcpcrole=/}";; + *ngcpnw.dhcp*) DHCP=true;; + *ngcpnobonding*) BONDING=false;; + *ngcpbonding*) BONDING=true;; + *ngcphalt*) HALT=true;; + *ngcpreboot*) REBOOT=true;; + *vagrant*) VAGRANT=true;; + *lowperformance*) ADJUST_FOR_LOW_PERFORMANCE=true;; + *enablevmservices*) ENABLE_VM_SERVICES=true;; + *ngcpfillcache*) FILL_APPROX_CACHE=true;; + *ngcpvlanbootint*) VLAN_BOOT_INT="${param//ngcpvlanbootint=/}";; + *ngcpvlansshext*) VLAN_SSH_EXT="${param//ngcpvlansshext=/}";; + *ngcpvlanwebext*) VLAN_WEB_EXT="${param//ngcpvlanwebext=/}";; + *ngcpvlansipext*) VLAN_SIP_EXT="${param//ngcpvlansipext=/}";; + *ngcpvlansipint*) VLAN_SIP_INT="${param//ngcpvlansipint=/}";; + *ngcpvlanhaint*) VLAN_HA_INT="${param//ngcpvlanhaint=/}";; + *ngcpvlanrtpext*) VLAN_RTP_EXT="${param//ngcpvlanrtpext=/}";; + *ngcpppainstaller*) NGCP_PPA_INSTALLER="${param//ngcpppainstaller=/}";; + *ngcpppa*) NGCP_PPA="${param//ngcpppa=/}";; + *ngcpinitsystem*) NGCP_INIT_SYSTEM="${param//ngcpinitsystem=/}";; + esac + shift +done + +if ! "$NGCP_INSTALLER" ; then + CARRIER_EDITION=false + PRO_EDITION=false + CE_EDITION=false + unset ROLE +fi + +set_deploy_status "installing_sipwise_keys" +install_sipwise_key + +set_deploy_status "installing_apt_transport_https" +install_apt_transport_https + +set_deploy_status "debootstrap_upgrade" +debootstrap_upgrade + +set_deploy_status "grml_debootstrap_upgrade" +grml_debootstrap_upgrade + +if "$NGCP_INSTALLER" ; then + set_deploy_status "ensure_augtool_present" + ensure_augtool_present +fi + +set_deploy_status "getconfig" + +# when using ip=....:$HOSTNAME:eth0:off file /etc/hosts doesn't contain the +# hostname by default, avoid warning/error messages in the host system +# and use it for IP address check in pro edition +if [ -z "$TARGET_HOSTNAME" ] ; then + if "$PRO_EDITION" ; then + TARGET_HOSTNAME="$ROLE" + fi + + if "$CE_EDITION" ; then + TARGET_HOSTNAME="spce" + fi + + # if we don't install ngcp ce/pro but + # $HOSTNAME is set via ip=.... then + # take it, otherwise fall back to safe default + if [ -z "$TARGET_HOSTNAME" ] ; then + if [ -n "$HOSTNAME" ] ; then + TARGET_HOSTNAME="$HOSTNAME" + else + TARGET_HOSTNAME="debian" + fi + fi +fi + +# get install device from "ip=:..." boot arg +if checkBootParam ip ; then + declare -A IP_ARR + if loadNfsIpArray IP_ARR "$(getBootParam ip)" ; then + INSTALL_DEV=${IP_ARR[device]} + EXT_GW=${IP_ARR[gw-ip]} + fi +fi + +# set reasonable install device from other source +if [ -z "$INSTALL_DEV" ] ; then + if [ -n "$EIFACE" ] ; then + INSTALL_DEV=$EIFACE + else + INSTALL_DEV=$DEFAULT_INSTALL_DEV + fi +fi +INSTALL_IP="$(ifdata -pa $INSTALL_DEV)" +logit "INSTALL_IP is $INSTALL_IP" + +# if the default network device (eth0) is unconfigured try to retrieve configuration from eth1 +if [ "$INSTALL_IP" = "NON-IP" ] && [ "$INSTALL_DEV" = "$DEFAULT_INSTALL_DEV" ] ; then + logit "Falling back to device eth1 for INSTALL_IP because $DEFAULT_INSTALL_DEV is unconfigured" + INSTALL_IP="$(ifdata -pa eth1)" + logit "INSTALL_IP is $INSTALL_IP" +fi + +# final external device and IP are same as installation +[ -n "$EXTERNAL_DEV" ] || EXTERNAL_DEV=$INSTALL_DEV +[ -n "$EXTERNAL_IP" ] || EXTERNAL_IP=$INSTALL_IP + +# hopefully set via bootoption/cmdline, +# otherwise fall back to hopefully-safe-defaults +# make sure the internal device (configured later) is not statically assigned, +# since when booting with ip=....eth1:off then the internal device needs to be eth0 +if "$PRO_EDITION" ; then + if [ -z "$INTERNAL_DEV" ] ; then + INTERNAL_DEV='eth1' + if [[ "$EXTERNAL_DEV" = "eth1" ]] ; then + INTERNAL_DEV='eth0' + fi + fi + + # needed for carrier + if "$RETRIEVE_MGMT_CONFIG" ; then + logit "Retrieving ha_int IPs configuration from management server" + wget --timeout=30 -O "/tmp/hosts" "${MANAGEMENT_IP}:3000/hostconfig/${TARGET_HOSTNAME}" + IP1=$(awk '/sp1/ { print $1 }' /tmp/hosts) || IP1=$DEFAULT_IP1 + IP2=$(awk '/sp2/ { print $1 }' /tmp/hosts) || IP2=$DEFAULT_IP2 + IP_HA_SHARED=$(awk '/sp(\s|$)/ { print $1 }' /tmp/hosts) || IP_HA_SHARED=$DEFAULT_IP_HA_SHARED + + if [ -z "$INTERNAL_NETMASK" ]; then + wget --timeout=30 -O "/tmp/interfaces" "http://${MANAGEMENT_IP}:3000/nwconfig/${TARGET_HOSTNAME}" + INTERNAL_NETMASK=$(grep "$INTERNAL_DEV inet" -A2 /tmp/interfaces | awk '/netmask/ { print $2 }') + fi + + if [ -z "$EXTERNAL_NETMASK" ]; then + wget --timeout=30 -O "/tmp/interfaces" "http://${MANAGEMENT_IP}:3000/nwconfig/${TARGET_HOSTNAME}" + EXTERNAL_NETMASK=$(grep "$EXTERNAL_DEV inet" -A2 /tmp/interfaces | awk '/netmask/ { print $2 }') + fi + fi + + [ -n "$EXT_GW" ] || EXT_GW=$DEFAULT_EXT_GW + [ -n "$IP1" ] || IP1=$DEFAULT_IP1 + [ -n "$IP2" ] || IP2=$DEFAULT_IP2 + [ -n "$IP_HA_SHARED" ] || IP_HA_SHARED=$DEFAULT_IP_HA_SHARED + # Use $IP_HA_SHARED as $MANAGEMENT_IP on PRO (it is comming from boot option 'ngcpmgmt' on Carrier) + [ -n "$MANAGEMENT_IP" ] || MANAGEMENT_IP="${IP_HA_SHARED}" + case "$ROLE" in + sp1) INTERNAL_IP=$IP1 ;; + sp2) INTERNAL_IP=$IP2 ;; + esac + [ -n "$INTERNAL_NETMASK" ] || INTERNAL_NETMASK=$DEFAULT_INTERNAL_NETMASK + [ -n "$EXTERNAL_NETMASK" ] || EXTERNAL_NETMASK=$DEFAULT_EXT_NETMASK + [ -n "$MCASTADDR" ] || MCASTADDR=$DEFAULT_MCASTADDR + + logit "ha_int sp1: $IP1 sp2: $IP2 shared sp: $IP_HA_SHARED netmask: $INTERNAL_NETMASK" +fi + +[ -n "$EIFACE" ] || EIFACE=$INSTALL_DEV + +if "$CARRIER_EDITION" ; then + # The first Carrier node is booted via DHCP, while requires static HW config on reboot + [ -n "$EADDR" ] || EADDR=$DEFAULT_EXT_IP +else + [ -n "$EADDR" ] || EADDR=$INSTALL_IP +fi + +if "$CE_EDITION" ; then + case "$SP_VERSION" in + # we do not have a local mirror for lenny, so disable it + 2.1) DEBIAN_RELEASE="lenny" ;; + 2.2) DEBIAN_RELEASE="squeeze" ;; + 2.4) DEBIAN_RELEASE="squeeze" ;; + 2.5) DEBIAN_RELEASE="squeeze" ;; + 2.6-rc1) DEBIAN_RELEASE="squeeze" ;; + 2.6-rc2) DEBIAN_RELEASE="squeeze" ;; + 2.6) DEBIAN_RELEASE="squeeze" ;; + 2.7-rc2) DEBIAN_RELEASE="squeeze" ;; + 2.7-rc3) DEBIAN_RELEASE="squeeze" ;; + 2.7) DEBIAN_RELEASE="squeeze" ;; + 2.8) DEBIAN_RELEASE="squeeze" ;; + esac +fi + +set_deploy_status "settings" + +### echo settings +[ -n "$SP_VERSION" ] && SP_VERSION_STR=$SP_VERSION || SP_VERSION_STR="" + +echo "Deployment Settings: + + Install ngcp: $NGCP_INSTALLER" + +if "$CARRIER_EDITION" ; then + echo " sip:carrier" +elif "$PRO_EDITION" ; then + echo " sip:provider: PRO" +elif "$CE_EDITION" ; then + echo " sip:provider: CE" +fi + +echo " + Target disk: /dev/$DISK + Target Hostname: $TARGET_HOSTNAME + Installer version: $SP_VERSION_STR + Install NW iface: $INSTALL_DEV + Install IP: $INSTALL_IP + Use DHCP in host: $DHCP + + Installing in chassis? $CHASSIS + +" | tee -a /tmp/installer-settings.txt + +if "$PRO_EDITION" ; then + echo " + Host Role: $ROLE + Host Role Carrier: $CROLE + Profile: $PROFILE + + External NW iface: $EXTERNAL_DEV + Ext host IP: $EXTERNAL_IP + Ext cluster iface: $EIFACE + Ext cluster IP: $EADDR + Multicast addr: $MCASTADDR + Internal NW iface: $INTERNAL_DEV + Int sp1 host IP: $IP1 + Int sp2 host IP: $IP2 + Int sp shared IP: $IP_HA_SHARED + Int netmask: $INTERNAL_NETMASK + MGMT address: $MANAGEMENT_IP +" | tee -a /tmp/installer-settings.txt +fi + +if "$INTERACTIVE" ; then + echo "WARNING: Execution will override any existing data!" + echo "Settings OK? y/N" + read a + if [[ "$a" != "y" ]] ; then + echo "Exiting as requested." + exit 2 + fi + unset a +fi +## }}} + +##### all parameters set ####################################################### + +set_deploy_status "start" + +# measure time of installation procedure - everyone loves stats! +start_seconds=$(cut -d . -f 1 /proc/uptime) + +if "$LOGO" ; then + disable_trace + GRML_INFO=$(cat /etc/grml_version) + IP_INFO=$(ip-screen) + CPU_INFO=$(lscpu | awk '/^CPU\(s\)/ {print $2}') + RAM_INFO=$(/usr/bin/gawk '/MemTotal/{print $2}' /proc/meminfo) + DATE_INFO=$(date) + INSTALLER_TYPE="Install CE: $CE_EDITION PRO: $PRO_EDITION [$ROLE] Carrier: $CARRIER_EDITION [$CROLE]" + if [ -n "$NGCP_PPA" ] ; then + PPA_INFO="| PPA: ${NGCP_PPA} " + fi + if [ -n "$NGCP_PPA_INSTALLER" ] ; then + PPA_INFO+="| Installer PPA: ${NGCP_PPA_INSTALLER}" + fi + # color + echo -ne "\ec\e[1;32m" + clear + #print logo + echo "+++ Grml-Sipwise Deployment +++" + echo "" + echo "$GRML_INFO" + echo "Host IP(s): $IP_INFO | Deployment version: $SCRIPT_VERSION" + echo "$CPU_INFO CPU(s) | ${RAM_INFO}kB RAM | $CHASSIS" + echo "" + echo "Install ngcp: $NGCP_INSTALLER | $INSTALLER_TYPE" + echo "Installing $SP_VERSION_STR platform | Debian: $DEBIAN_RELEASE $PPA_INFO" + echo "Install IP: $INSTALL_IP | Started deployment at $DATE_INFO" + # number of lines + echo -ne "\e[10;0r" + # reset color + echo -ne "\e[9B\e[1;m" + enable_trace +fi + +if "$PRO_EDITION" ; then + if "$RETRIEVE_MGMT_CONFIG" && "$RESTART_NETWORK" ; then + echo "Skipping $INTERNAL_DEV config" + else + # internal network (default on eth1) + if ifconfig "$INTERNAL_DEV" &>/dev/null ; then + ifconfig "$INTERNAL_DEV" $INTERNAL_IP netmask $INTERNAL_NETMASK + else + die "Error: no $INTERNAL_DEV NIC found, can not deploy internal network. Exiting." + fi + fi + # ipmi on IBM hardware + if ifconfig usb0 &>/dev/null ; then + ifconfig usb0 169.254.1.102 netmask 255.255.0.0 + fi +fi + +set_deploy_status "diskverify" + +# TODO - hardcoded for now, to avoid data damage +check_for_supported_disk() { + if grep -q 'ServeRAID' "/sys/block/${DISK}/device/model" ; then + return 0 + fi + + # IBM System x3250 M3 + if grep -q 'Logical Volume' "/sys/block/${DISK}/device/model" && \ + grep -q "LSILOGIC" "/sys/block/${DISK}/device/vendor" ; then + return 0 + fi + + # IBM System HS23 LSISAS2004 + if grep -q 'Logical Volume' "/sys/block/${DISK}/device/model" && \ + grep -q "LSI" "/sys/block/${DISK}/device/vendor" ; then + return 0 + fi + + # PERC H700, PERC H710,... + if grep -q 'PERC' "/sys/block/${DISK}/device/model" && \ + grep -q "DELL" "/sys/block/${DISK}/device/vendor" ; then + return 0 + fi + + # proxmox on blade, internal system + if grep -q 'COMSTAR' "/sys/block/${DISK}/device/model" && \ + grep -q "OI" "/sys/block/${DISK}/device/vendor" ; then + FIRMWARE_PACKAGES="$FIRMWARE_PACKAGES firmware-qlogic" + return 0 + fi + + local disk_model + disk_model=$(cat "/sys/block/${DISK}/device/model") || true + local disk_vendor + disk_vendor=$(cat "/sys/block/${DISK}/device/vendor") || true + + echo "WARNING: Cannot detect supported device vendor/model." >&2 + echo "(Disk: ${DISK} Vendor: ${disk_vendor} Model: ${disk_model})" >&2 + echo "Would you like to continue anyway? (yes/NO)" >&2 + read a + case "$a" in + y|Y|yes|YES) + echo "Continue anyway as requested." + return 0 + ;; + *) + echo "Aborting installation using disk '${DISK}'" >&2 + return 1 + ;; + esac + unset a + + # no match so far? + return 1 +} + +# run in according environment only +if [ -n "$TARGET_DISK" ] ; then + logit "Skipping check for supported disk as TARGET_DISK variable is set." +else + if [[ $(imvirt 2>/dev/null) == "Physical" ]] ; then + + if ! check_for_supported_disk ; then + die "Error: /dev/${DISK} does not look like a VirtIO, ServeRAID, LSILOGIC or PowerEdge disk/controller. Exiting to avoid possible data damage." + fi + + else + # make sure it runs only within qemu/kvm + if [[ "${DISK}" == "vda" ]] && readlink -f /sys/block/vda/device | grep -q 'virtio' ; then + echo "Looks like a virtio disk, ok." + elif grep -q 'QEMU HARDDISK' "/sys/block/${DISK}/device/model" ; then + echo "Looks like a QEMU harddisk, ok." + elif grep -q 'VBOX HARDDISK' "/sys/block/${DISK}/device/model" ; then + echo "Looks like a VBOX harddisk, ok." + elif grep -q 'Virtual disk' "/sys/block/${DISK}/device/model" && [[ $(imvirt) == "VMware ESX Server" ]] ; then + echo "Looks like a VMware ESX Server harddisk, ok." + else + die "Error: /dev/${DISK} does not look like a virtual disk. Exiting to avoid possible data damage. Note: imvirt output is $(imvirt)" + fi + fi +fi + +# relevant only while deployment, will be overridden later +if [ -n "$HOSTNAME" ] ; then + cat > /etc/hosts << EOF +127.0.0.1 grml localhost +::1 ip6-localhost ip6-loopback grml +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +ff02::3 ip6-allhosts + +127.0.0.1 $ROLE $HOSTNAME +$INSTALL_IP $ROLE $HOSTNAME +EOF +fi + +# remote login ftw +/etc/init.d/ssh start >/dev/null & +echo "root:sipwise" | chpasswd + +## partition disk +set_deploy_status "disksetup" + +# 2000GB = 2097152000 blocks in /proc/partitions - so make a rough estimation +if [ "$(awk "/ ${DISK}$/ {print \$3}" /proc/partitions)" -gt 2000000000 ] ; then + TABLE=gpt +else + TABLE=msdos +fi + +if "$LVM" ; then + # make sure lvcreate understands the --yes option + lv_create_opts='' + lvm_version=$(dpkg-query -W -f="\${Version}\n" lvm2) || die "Unknown package lvm2" + setupstorage_version=$(dpkg-query --show --showformat="\${Version}" fai-setup-storage) || die "Unknown package fai-setup-storage" + + if dpkg --compare-versions "$setupstorage_version" ge 5.0 ; then + logit "Installed fai-setup-storage version ${setupstorage_version} doesn't need the LVM '--yes' workaround." + elif dpkg --compare-versions "$lvm_version" lt 2.02.106 ; then + logit "Installed lvm2 version ${lvm_version} doesn't need the '--yes' workaround." + else + logit "Enabling '--yes' workaround for lvm2 version ${lvm_version}." + lv_create_opts='lvcreateopts="--yes"' + fi + + if "$NGCP_INSTALLER" ; then + VG_NAME="ngcp" + else + VG_NAME="vg0" + fi + + cat > /tmp/partition_setup.txt << EOF +disk_config ${DISK} disklabel:${TABLE} bootable:1 +primary - 4096- - - + +disk_config lvm +vg ${VG_NAME} ${DISK}1 +${VG_NAME}-root / -95% ext3 rw +${VG_NAME}-swap swap RAM:50% swap sw $lv_create_opts +EOF + + # make sure setup-storage/parted doesn't fail if LVM is already present + blockdev --rereadpt "/dev/${DISK}" + for disk in "/dev/${DISK}"* ; do + logit "Removing possibly existing LVM/PV label from $disk" + pvremove "$disk" --force --force --yes || true + done + dd if=/dev/zero of="/dev/${DISK}" bs=1M count=1 + blockdev --rereadpt "/dev/${DISK}" + + export LOGDIR='/tmp/setup-storage' + mkdir -p $LOGDIR + + # /usr/lib/fai/fai-disk-info is available as of FAI 4.0, + # older versions shipped /usr/lib/fai/disk-info which doesn't + # support the partition setup syntax we use in our setup + if ! [ -x /usr/lib/fai/fai-disk-info ] ; then + die "You are using an outdated ISO, please update it to have fai-setup-storage >=4.0.6 available." + fi + + disklist=$(/usr/lib/fai/fai-disk-info | sort) + export disklist + PATH=/usr/lib/fai:${PATH} setup-storage -f /tmp/partition_setup.txt -X || die "Failure during execution of setup-storage" + + # used later by installer + ROOT_FS="/dev/mapper/${VG_NAME}-root" + SWAP_PARTITION="/dev/mapper/${VG_NAME}-swap" + +else # no LVM + parted -s -a optimal "/dev/${DISK}" mktable "$TABLE" || die "Failed to set up partition table" + # hw-raid with rootfs + swap partition + parted -s -a optimal "/dev/${DISK}" 'mkpart primary ext4 2048s 95%' || die "Failed to set up primary partition" + parted -s -a optimal "/dev/${DISK}" 'mkpart primary linux-swap 95% -1' || die "Failed to set up swap partition" + sync + + # used later by installer + ROOT_FS="/dev/${DISK}1" + SWAP_PARTITION="/dev/${DISK}2" + + echo "Initialising swap partition $SWAP_PARTITION" + mkswap -L ngcp-swap "$SWAP_PARTITION" || die "Failed to initialise swap partition" + + # for later usage in /etc/fstab use /dev/disk/by-label/ngcp-swap instead of /dev/${DISK}2 + SWAP_PARTITION="/dev/disk/by-label/ngcp-swap" +fi + +# otherwise e2fsck fails with "need terminal for interactive repairs" +echo FSCK=no >>/etc/debootstrap/config + +# package selection +cat > /etc/debootstrap/packages << EOF +# addons: packages which d-i installs but debootstrap doesn't +eject +grub-pc +pciutils +usbutils +ucf +# locales -> but we want locales-all instead: +locales-all + +# required e.g. for "Broadcom NetXtreme II BCM5709S Gigabit Ethernet" +# lacking the firmware will result in non-working network on +# too many physical server systems, so just install it by default +firmware-bnx2 +firmware-bnx2x + +# MT#7999 ethtool used in bonding +ethtool + +# support acpi (d-i installs them as well) +acpi acpid acpi-support-base + +# be able to login on the system, even if just installing plain Debian +openssh-server + +# support bridge / vlan +bridge-utils +vlan + +# MT#13637 support https in sources.list +apt-transport-https + +# TT#5444 ca-certificates is necessary to wget ngcp-installer over https +ca-certificates + +# packages d-i installs but we ignore/skip: +#discover +#gettext-base +#installation-report +#kbd +#laptop-detect +#os-prober +EOF + +# ifenslave-2.6 in jessie+ is a transitional dummy package that will disappear. +case "$DEBIAN_RELEASE" in + lenny|squeeze|wheezy) + PKG_IFENSLAVE="ifenslave-2.6" + ;; + *) + PKG_IFENSLAVE="ifenslave" + ;; +esac +echo "Adding ${PKG_IFENSLAVE} package (because we're installing ${DEBIAN_RELEASE})" +logit "Adding ${PKG_IFENSLAVE} package (because we're installing ${DEBIAN_RELEASE})" +cat >> /etc/debootstrap/packages << EOF +# support bonding +${PKG_IFENSLAVE} +EOF + +# MT#8813 The linux-headers-2.6-amd64 package doesn't exist in jessie and newer +case "$DEBIAN_RELEASE" in + lenny|squeeze|wheezy) + echo "Adding linux-headers-2.6-amd64 package (because we're installing ${DEBIAN_RELEASE})" + logit "Adding linux-headers-2.6-amd64 package (because we're installing ${DEBIAN_RELEASE})" + cat >> /etc/debootstrap/packages << EOF +# required for dkms +linux-headers-2.6-amd64 +EOF + ;; + *) + echo "Adding linux-headers-amd64 package (because we're installing ${DEBIAN_RELEASE})" + logit "Adding linux-headers-amd64 package (because we're installing ${DEBIAN_RELEASE})" + cat >> /etc/debootstrap/packages << EOF +# required for dkms +linux-headers-amd64 +EOF + ;; +esac + +if "$LVM" ; then + cat >> /etc/debootstrap/packages << EOF +# support LVM +lvm2 +EOF +fi + +if [ -n "$FIRMWARE_PACKAGES" ] ; then + cat >> /etc/debootstrap/packages << EOF +# firmware packages for hardware specific needs +$FIRMWARE_PACKAGES +EOF +fi + +# NOTE: we use the debian.sipwise.com CNAME by intention here +# to avoid conflicts with apt-pinning, preferring deb.sipwise.com +# over official Debian +MIRROR="${DEBIAN_REPO_TRANSPORT}://${DEBIAN_REPO_HOST}/debian/" +SEC_MIRROR="${DEBIAN_REPO_TRANSPORT}://${DEBIAN_REPO_HOST}/debian-security/" +DBG_MIRROR="${DEBIAN_REPO_TRANSPORT}://${DEBIAN_REPO_HOST}/debian-debug/" + +if [ -z "${GPG_KEY}" ] ; then + KEYRING='/etc/apt/trusted.gpg.d/sipwise.gpg' +else + KEYRING='/etc/apt/trusted.gpg' + + echo "Fetching debootstrap keyring as GPG key '${GPG_KEY}'..." + logit "Fetching debootstrap keyring as GPG key '${GPG_KEY}'..." + + TRY=60 + while ! gpg --keyserver "${GPG_KEY_SERVER}" --recv-keys "${GPG_KEY}" ; do + if [ ${TRY} -gt 0 ] ; then + TRY=$((TRY-5)) + echo "Waiting for gpg keyserver '${GPG_KEY_SERVER}' availability ($TRY seconds)..." + sleep 5 + else + die "Failed to fetch GPG key '${GPG_KEY}' from '${GPG_KEY_SERVER}'" + fi + done + + if ! gpg -a --export "${GPG_KEY}" | apt-key add - ; then + die "Failed to import GPG key '${GPG_KEY}' as apt-key" + fi +fi + +set_deploy_status "debootstrap" + +mkdir -p /etc/debootstrap/etc/apt/ +logit "Setting up /etc/debootstrap/etc/apt/sources.list" +cat > /etc/debootstrap/etc/apt/sources.list << EOF +# Set up via deployment.sh for grml-debootstrap usage +deb ${MIRROR} ${DEBIAN_RELEASE} main contrib non-free +EOF + +echo "deb ${SEC_MIRROR} ${DEBIAN_RELEASE}-security main contrib non-free" >> /etc/debootstrap/etc/apt/sources.list +echo "deb ${MIRROR} ${DEBIAN_RELEASE}-updates main contrib non-free" >> /etc/debootstrap/etc/apt/sources.list + +if [ "$DEBIAN_RELEASE" != "jessie" ] ; then + echo "deb ${DBG_MIRROR} ${DEBIAN_RELEASE}-debug main contrib non-free" >> /etc/debootstrap/etc/apt/sources.list +fi + +# GRUB versions until Debian/wheezy generate an invalid device.map +# entry if /dev/disk/by-id/lvm-pv-uuid-* is present, resulting in +# a GRUB installation failing with "error: no such disk" during boot. +# This is only a problem if we're using a virtio disk and deploying +# from a system running lvm2 v2.02.106 or newer. +if [ "${DISK}" = "vda" ] ; then + case "$DEBIAN_RELEASE" in + lenny|squeeze|wheezy) + echo "Applying /dev/disk/by-id/lvm-pv-uuid-* workaround for virtio disk and Debian release <= wheezy" + logit "Applying /dev/disk/by-id/lvm-pv-uuid-* workaround for virtio disk and Debian release <= wheezy" + rm -f /dev/disk/by-id/lvm-pv-uuid-* + ;; + esac +fi + +if [ "$DEBIAN_RELEASE" = "stretch" ] && [ ! -r /usr/share/debootstrap/scripts/stretch ] ; then + echo "Enabling stretch support for debootstrap via symlink to sid" + ln -s /usr/share/debootstrap/scripts/sid /usr/share/debootstrap/scripts/stretch +fi + +# install Debian +# shellcheck disable=SC2086 +echo y | grml-debootstrap \ + --arch "${ARCH}" \ + --grub "/dev/${DISK}" \ + --filesystem "${FILESYSTEM}" \ + --hostname "${TARGET_HOSTNAME}" \ + --mirror "$MIRROR" \ + --debopt "--keyring=${KEYRING}" $EXTRA_DEBOOTSTRAP_OPTS \ + --keep_src_list \ + --defaultinterfaces \ + -r "$DEBIAN_RELEASE" \ + -t "$ROOT_FS" \ + --password 'sipwise' 2>&1 | tee -a /tmp/grml-debootstrap.log + +if [ "${PIPESTATUS[1]}" != "0" ]; then + die "Error during installation of Debian ${DEBIAN_RELEASE}. Find details via: mount $ROOT_FS $TARGET ; ls $TARGET/debootstrap/*.log" +fi + +sync +mount "$ROOT_FS" "$TARGET" + +# MT#13711 +case "$DEBIAN_RELEASE" in + lenny|squeeze) + echo "Setting up /etc/apt/apt.conf.d/42_ngcp_aptproxy to avoid random 'Hash Sum mismatch' failures." + logit "Setting up /etc/apt/apt.conf.d/42_ngcp_aptproxy to avoid random 'Hash Sum mismatch' failures." + echo "// NGCP_MANAGED_FILE - do not remove this line if it should be automatically handled" > "${TARGET}/etc/apt/apt.conf.d/42_ngcp_aptproxy" + echo "// Installed via 'deployment.sh' on $(date)" >> "${TARGET}/etc/apt/apt.conf.d/42_ngcp_aptproxy" + echo 'Acquire::http::Pipeline-Depth "0";' >> "${TARGET}/etc/apt/apt.conf.d/42_ngcp_aptproxy" + ;; +esac + +# MT#7805 +if "$NGCP_INSTALLER" ; then + cat << EOT | augtool --root="$TARGET" +insert opt after /files/etc/fstab/*[file="/"]/opt[last()] +set /files/etc/fstab/*[file="/"]/opt[last()] noatime +save +EOT +fi + +# provide useable swap partition +echo "Enabling swap partition $SWAP_PARTITION via /etc/fstab" +cat >> "${TARGET}/etc/fstab" << EOF +$SWAP_PARTITION none swap sw,pri=0 0 0 +EOF + +case "$DEBIAN_RELEASE" in + lenny|squeeze|wheezy) + echo "Removing packages which debootstrap installs but d-i doesn't" + chroot $TARGET apt-get --purge -y remove tcpd xauth + ;; +esac + +if "$PRO_EDITION" ; then + echo "Pro edition: keeping firmware* packages." +else + chroot $TARGET apt-get --purge -y remove \ + firmware-linux firmware-linux-free firmware-linux-nonfree || true +fi + +# get rid of automatically installed packages +chroot $TARGET apt-get --purge -y autoremove + +# purge removed packages +removed_packages=( $(chroot $TARGET dpkg --list | awk '/^rc/ {print $2}') ) +if [ ${#removed_packages[@]} -ne 0 ]; then + chroot "$TARGET" dpkg --purge "${removed_packages[@]}" +fi + +# make sure `hostname` and `hostname --fqdn` return data from chroot +grml-chroot $TARGET hostname -F /etc/hostname + +# make sure installations of packages works, will be overridden later again +cat > $TARGET/etc/hosts << EOF +127.0.0.1 localhost +127.0.0.1 $HOSTNAME + +::1 localhost ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +EOF + +if "$PRO_EDITION" && [[ $(imvirt) != "Physical" ]] ; then + echo "Generating udev persistent net rules." + INT_MAC=$(udevadm info -a -p /sys/class/net/${INTERNAL_DEV} | awk -F== '/ATTR{address}/ {print $2}') + EXT_MAC=$(udevadm info -a -p /sys/class/net/${EXTERNAL_DEV} | awk -F== '/ATTR{address}/ {print $2}') + + if [ "$INT_MAC" = "$EXT_MAC" ] ; then + die "Error: MAC address for $INTERNAL_DEV is same as for $EXTERNAL_DEV" + fi + + cat > $TARGET/etc/udev/rules.d/70-persistent-net.rules << EOF +## Generated by Sipwise deployment script +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}==$INT_MAC, ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="$INTERNAL_DEV" +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}==$EXT_MAC, ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="$EXTERNAL_DEV" +EOF +fi + +if "$RETRIEVE_MGMT_CONFIG" ; then + # needs to be executed *after* udev rules have been set up, + # otherwise we get duplicated MAC address<->device name mappings + echo "Retrieving network configuration from management server" + wget --timeout=30 -O /etc/network/interfaces "${MANAGEMENT_IP}:3000/nwconfig/$(cat ${TARGET}/etc/hostname)" + cp /etc/network/interfaces "${TARGET}/etc/network/interfaces" + # can't be moved to ngcp-installer, otherwise Grml can't execute: + # > wget --timeout=30 -O Packages.gz "${repos_base_path}Packages.gz" + # because host 'web01' is unknown + echo "Retrieving /etc/hosts configuration from management server" + wget --timeout=30 -O "${TARGET}/etc/hosts" "${MANAGEMENT_IP}:3000/hostconfig/$(cat ${TARGET}/etc/hostname)" +fi + +if "$RETRIEVE_MGMT_CONFIG" && "$RESTART_NETWORK" ; then + # restart networking for the time being only when running either in toram mode + # or not booting from NFS, once we've finished the carrier setup procedure we + # should be able to make this as our only supported default mode and drop + # everything inside the 'else' statement... + if grep -q 'toram' /proc/cmdline || ! grep -q 'root=/dev/nfs' /proc/cmdline ; then + logit 'Set /etc/hosts from TARGET' + cp ${TARGET}/etc/hosts /etc/hosts + echo 'Restarting networking' + logit 'Restarting networking' + /etc/init.d/networking restart + else + # make sure we can access the management system which might be reachable + # through a specific VLAN only + ip link set dev "$INTERNAL_DEV" down # avoid conflicts with VLAN device(s) + + # vlan-raw-device bond0 doesn't exist in the live environment, if we don't + # adjust it accordingly for our environment the vlan device(s) can't be + # brought up + # note: we do NOT modify the /e/n/i file from $TARGET here by intention + sed -i "s/vlan-raw-device .*/vlan-raw-device eth0/" /etc/network/interfaces + + while IFS= read -r interface ; do + echo "Bringing up VLAN interface ${interface}" + ifup "${interface}" + done < <(awk '/^auto vlan/ {print $2}' /etc/network/interfaces) + fi # toram +fi + +get_installer_path() { + if [ -z "$SP_VERSION" ] && ! $TRUNK_VERSION ; then + INSTALLER=ngcp-installer-latest.deb + + if "$PRO_EDITION" ; then + INSTALLER_PATH="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/sppro/" + else + INSTALLER_PATH="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/spce/" + fi + + return # we don't want to run any further code from this function + fi + + # use pool directory according for ngcp release + if "$PRO_EDITION" ; then + if "$CARRIER_EDITION" ; then + local installer_package='ngcp-installer-carrier' + else + local installer_package='ngcp-installer-pro' + fi + local repos_base_path="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/sppro/${SP_VERSION}/dists/${DEBIAN_RELEASE}/main/binary-amd64/" + INSTALLER_PATH="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/sppro/${SP_VERSION}/pool/main/n/ngcp-installer/" + else + local installer_package='ngcp-installer-ce' + local repos_base_path="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/spce/${SP_VERSION}/dists/${DEBIAN_RELEASE}/main/binary-amd64/" + INSTALLER_PATH="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/spce/${SP_VERSION}/pool/main/n/ngcp-installer/" + fi + + # use a separate repos for trunk releases + if $TRUNK_VERSION ; then + local repos_base_path="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/autobuild/dists/release-trunk-${DEBIAN_RELEASE}/main/binary-amd64/" + INSTALLER_PATH="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/autobuild/pool/main/n/ngcp-installer/" + fi + + if [ -n "$NGCP_PPA_INSTALLER" ] ; then + local repos_base_path="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/autobuild/dists/${NGCP_PPA_INSTALLER}/main/binary-amd64/" + INSTALLER_PATH="${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/autobuild/pool/main/n/ngcp-installer/" + fi + + wget --timeout=30 -O Packages.gz "${repos_base_path}Packages.gz" + # sed: display paragraphs matching the "Package: ..." string, then grab string "^Version: " and display the actual version via awk + # sort -u to avoid duplicates in repositories shipping the ngcp-installer-pro AND ngcp-installer-pro-ha-v3 debs + local version + version=$(zcat Packages.gz | sed "/./{H;\$!d;};x;/Package: ${installer_package}/b;d" | awk '/^Version: / {print $2}' | sort -u) + + [ -n "$version" ] || die "Error: installer version for ngcp ${SP_VERSION}, Debian release $DEBIAN_RELEASE with installer package $installer_package could not be detected." + + if "$CARRIER_EDITION" ; then + INSTALLER="ngcp-installer-carrier_${version}_all.deb" + elif "$PRO_EDITION" ; then + INSTALLER="ngcp-installer-pro_${version}_all.deb" + else + INSTALLER="ngcp-installer-ce_${version}_all.deb" + fi +} + +set_repos() { + cat > $TARGET/etc/apt/sources.list << EOF +# Please visit /etc/apt/sources.list.d/ instead. +EOF + + cat > $TARGET/etc/apt/sources.list.d/debian.list << EOF +## custom sources.list, deployed via deployment.sh + +# Debian repositories +deb ${MIRROR} ${DEBIAN_RELEASE} main contrib non-free +deb ${SEC_MIRROR} ${DEBIAN_RELEASE}-security main contrib non-free +deb ${MIRROR} ${DEBIAN_RELEASE}-updates main contrib non-free +EOF + + if [ "$DEBIAN_RELEASE" != "jessie" ] ; then + echo "deb ${DBG_MIRROR} ${DEBIAN_RELEASE}-debug main contrib non-free" >> "$TARGET/etc/apt/sources.list.d/debian.list" + fi + + # support testing rc releases without providing an according installer package ahead + if [ -n "$AUTOBUILD_RELEASE" ] ; then + echo "Running installer with sources.list for $DEBIAN_RELEASE + autobuild release-$AUTOBUILD_RELEASE" + + cat > $TARGET/etc/apt/sources.list.d/sipwise.list << EOF +## custom sources.list, deployed via deployment.sh + +# Sipwise repositories +deb [arch=amd64] ${SIPWISE_REPO_TRANSPORT}://${SIPWISE_REPO_HOST}/autobuild/release/release-${AUTOBUILD_RELEASE} release-${AUTOBUILD_RELEASE} main +EOF + fi +} + +get_network_devices () { + # get list of available network devices (excl. some known-to-be-irrelevant ones, also see MT#8297) + net_devices=$(tail -n +3 /proc/net/dev | awk -F: '{print $1}'| sed "s/\s*//" | grep -ve '^vmnet' -ve '^vboxnet' -ve '^docker' -ve '^usb' | sort -u) + + NETWORK_DEVICES="" + for network_device in $net_devices $DEFAULT_INSTALL_DEV $INTERNAL_DEV $EXTERNAL_DEV ; do + # avoid duplicates + echo "$NETWORK_DEVICES" | grep -wq "$network_device" || NETWORK_DEVICES="$NETWORK_DEVICES $network_device" + done + export NETWORK_DEVICES + unset net_devices +} + +gen_installer_config () { + mkdir -p "${TARGET}/etc/ngcp-installer/" + + # We are installing Carrier using DHCP but configure network.yml on static IPs + # as a result we cannot use "ip route show dev $DEFAULT_INSTALL_DEV" + if "$CARRIER_EDITION" ; then + if [ -n "$EXT_GW" ]; then + GW="$EXT_GW" + else + echo "Last resort, guesting gateway for external IP as first IP in EADDR" + GW=$(echo "$EADDR" | awk -F. '{print $1"."$2"."$3".1"}') + fi + else + GW="$(ip route show dev $DEFAULT_INSTALL_DEV | awk '/^default via/ {print $3}')" + fi + + if "$CARRIER_EDITION" ; then + cat > ${TARGET}/etc/ngcp-installer/config_deploy.inc << EOF +CROLE="${CROLE}" +FILL_APPROX_CACHE="${FILL_APPROX_CACHE}" +VLAN_BOOT_INT="${VLAN_BOOT_INT}" +VLAN_SSH_EXT="${VLAN_SSH_EXT}" +VLAN_WEB_EXT="${VLAN_WEB_EXT}" +VLAN_SIP_EXT="${VLAN_SIP_EXT}" +VLAN_SIP_INT="${VLAN_SIP_INT}" +VLAN_HA_INT="${VLAN_HA_INT}" +VLAN_RTP_EXT="${VLAN_RTP_EXT}" +EOF + fi + + if "$PRO_EDITION" ; then + get_network_devices + cat >> ${TARGET}/etc/ngcp-installer/config_deploy.inc << EOF +HNAME="${ROLE}" +IP1="${IP1}" +IP2="${IP2}" +IP_HA_SHARED="${IP_HA_SHARED}" +EIFACE="${EIFACE}" +EADDR="${EADDR}" +MCASTADDR="${MCASTADDR}" +DPL_MYSQL_REPLICATION="${DPL_MYSQL_REPLICATION}" +TARGET_HOSTNAME="${TARGET_HOSTNAME}" +DEFAULT_INSTALL_DEV="${DEFAULT_INSTALL_DEV}" +INTERNAL_DEV="${INTERNAL_DEV}" +GW="${GW}" +EXTERNAL_DEV="${EXTERNAL_DEV}" +NETWORK_DEVICES="${NETWORK_DEVICES}" +DEFAULT_INTERNAL_NETMASK="${DEFAULT_INTERNAL_NETMASK}" +# I would like to delete ${DEFAULT_INTERNAL_NETMASK} and use ${INTERNAL_NETMASK} into installer, +# Lets test we have INTERNAL_NETMASK==DEFAULT_INTERNAL_NETMASK for CE/PRO/Carrier (in installer) +# and switch code to INTERNAL_NETMASK then. +INTERNAL_NETMASK="${INTERNAL_NETMASK}" +EXTERNAL_NETMASK="${EXTERNAL_NETMASK}" +RETRIEVE_MGMT_CONFIG="${RETRIEVE_MGMT_CONFIG}" +MANAGEMENT_IP="${MANAGEMENT_IP}" +EOF + fi + + cat >> ${TARGET}/etc/ngcp-installer/config_deploy.inc << EOF +FORCE=yes +SKIP_SOURCES_LIST="${SKIP_SOURCES_LIST}" +ADJUST_FOR_LOW_PERFORMANCE="${ADJUST_FOR_LOW_PERFORMANCE}" +ENABLE_VM_SERVICES="${ENABLE_VM_SERVICES}" +SIPWISE_REPO_HOST="${SIPWISE_REPO_HOST}" +DEBIAN_REPO_TRANSPORT="${DEBIAN_REPO_TRANSPORT}" +SIPWISE_REPO_TRANSPORT="${SIPWISE_REPO_TRANSPORT}" +NAMESERVER="$(awk '/^nameserver/ {print $2}' /etc/resolv.conf)" +NGCP_PPA="${NGCP_PPA}" +DEBUG_MODE="${DEBUG_MODE}" +NGCP_INIT_SYSTEM="${NGCP_INIT_SYSTEM}" +EOF + + cat "${TARGET}/etc/ngcp-installer/config_deploy.inc" > /tmp/ngcp-installer-cmdline.log +} + +if "$NGCP_INSTALLER" ; then + # set INSTALLER_PATH and INSTALLER depending on release/version + get_installer_path + + # generate debian/sipwise repos + set_repos + + set_deploy_status "ngcp-installer" + + # install ngcp-installer + logit "ngcp-installer: $INSTALLER" + cat << EOT | grml-chroot $TARGET /bin/bash +wget ${INSTALLER_PATH}/${INSTALLER} +dpkg -i $INSTALLER +EOT + + # generate installer configs + gen_installer_config + + # generate ngcp-installer run script + cat > "${TARGET}/tmp/ngcp-installer-deployment.sh" << "EOT" +#!/bin/bash +echo "Running ngcp-installer via grml-chroot." | tee -a /tmp/ngcp-installer-debug.log +ngcp-installer 2>&1 | tee -a /tmp/ngcp-installer-debug.log +RC=${PIPESTATUS[0]} +if [ "${RC}" = "0" ] ; then + echo "OK, ngcp-installer finished with exit code '${RC}', continue netscript deployment." | tee -a /tmp/ngcp-installer-debug.log +else + echo "ERROR: Fatal error while running ngcp-installer (exit code '${RC}')!" | tee -a /tmp/ngcp-installer-debug.log >&2 + exit ${RC} +fi +EOT + + # execute ngcp-installer + if grml-chroot "${TARGET}" /bin/bash /tmp/ngcp-installer-deployment.sh ; then + logit "installer: success" + else + logit "installer: error" + die "Error during installation of ngcp. Find details at: ${TARGET}/tmp/ngcp-installer.log ${TARGET}/tmp/ngcp-installer-debug.log" + fi + + # upload db dump only if we're deploying a trunk version + if $TRUNK_VERSION && checkBootParam ngcpupload ; then + set_deploy_status "prepare_translations" + grml-chroot $TARGET apt-get -y install ngcp-dev-tools + if ! grml-chroot $TARGET ngcp-prepare-translations ; then + die "Error: Failed to prepare ngcp-panel translations. Exiting." + fi + set_deploy_status "ngcp-installer" + fi + + NGCP_SERVICES_FILE="${TARGET}/usr/share/ngcp-system-tools/ngcp.inc" + if ! [ -r "$NGCP_SERVICES_FILE" ]; then + die "Error: File $NGCP_SERVICES_FILE not found. Exiting." + fi + + # make sure services are stopped + . "$NGCP_SERVICES_FILE" + for service in ${HA_NGCP_SERVICES} ${NGCP_SERVICES} ${NON_NGCP_SERVICES} ; do + if [ -f "${TARGET}/etc/init.d/${service}" ] ; then + echo "Stopping ${service} ..." + grml-chroot ${TARGET} "/etc/init.d/${service}" stop || true + fi + done + + # nuke files + find "${TARGET}/var/log" -type f -size +0 -not -name \*.ini -exec sh -c ":> \${1}" sh {} \; + :>$TARGET/var/run/utmp + :>$TARGET/var/run/wtmp + + # make a backup of the installer logfiles for later investigation + if [ -r "${TARGET}"/tmp/ngcp-installer.log ] ; then + cp "${TARGET}"/tmp/ngcp-installer.log "${TARGET}"/var/log/ + fi + if [ -r "${TARGET}"/tmp/ngcp-installer-debug.log ] ; then + cp "${TARGET}"/tmp/ngcp-installer-debug.log "${TARGET}"/var/log/ + fi + if [ -r /tmp/grml-debootstrap.log ] ; then + cp /tmp/grml-debootstrap.log "${TARGET}"/var/log/ + fi + + { + echo "# deployment.sh running on $(date)" + echo "SCRIPT_VERSION=${SCRIPT_VERSION}" + echo "CMD_LINE=\"${CMD_LINE}\"" + echo "NGCP_INSTALLER_CMDLINE=\"TRUNK_VERSION=$TRUNK_VERSION SKIP_SOURCES_LIST=$SKIP_SOURCES_LIST ngcp-installer $ROLE $IP1 $IP2 $EADDR $EIFACE $IP_HA_SHARED\"" + } > "${TARGET}"/var/log/deployment.log + +fi + +case "$DEBIAN_RELEASE" in + stretch) + set_custom_grub_boot_options + ;; +esac + +if "$CARRIER_EDITION" ; then + echo "Nothing to do on Carrier, /etc/network/interfaces was already set up." +elif ! "$NGCP_INSTALLER" ; then + echo "Not modifying /etc/network/interfaces as installing plain Debian." +elif "$DHCP" ; then + cat > $TARGET/etc/network/interfaces << EOF +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). +# The loopback network interface +auto lo +iface lo inet loopback + +# The primary network interface +auto $EXTERNAL_DEV +iface $EXTERNAL_DEV inet dhcp +EOF + # make sure internal network is available even with external + # device using DHCP + if "$PRO_EDITION" ; then + cat >> $TARGET/etc/network/interfaces << EOF + +auto $INTERNAL_DEV +iface $INTERNAL_DEV inet static + address $INTERNAL_IP + netmask $INTERNAL_NETMASK + +EOF + fi +else + # assume host system has a valid configuration + if "$PRO_EDITION" && "$VLAN" ; then + cat > $TARGET/etc/network/interfaces << EOF +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). +# The loopback network interface +auto lo +iface lo inet loopback + +auto vlan${VLANID} +iface vlan${VLANID} inet static + address $(ifdata -pa $EXTERNAL_DEV) + netmask $(ifdata -pn $EXTERNAL_DEV) + gateway $(route -n | awk '/^0\.0\.0\.0/{print $2; exit}') + dns-nameservers $(awk '/^nameserver/ {print $2}' /etc/resolv.conf | xargs echo -n) + vlan-raw-device $VLANIF + +auto $INTERNAL_DEV +iface $INTERNAL_DEV inet static + address $INTERNAL_IP + netmask $INTERNAL_NETMASK + +# Example: +# allow-hotplug eth0 +# iface eth0 inet static +# address 192.168.1.101 +# netmask 255.255.255.0 +# network 192.168.1.0 +# broadcast 192.168.1.255 +# gateway 192.168.1.1 +# # dns-* options are implemented by the resolvconf package, if installed +# dns-nameservers 195.58.160.194 195.58.161.122 +# dns-search sipwise.com +EOF + elif "$PRO_EDITION" && "$BONDING" ; then + cat > $TARGET/etc/network/interfaces << EOF +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). +# The loopback network interface +auto lo +iface lo inet loopback + +auto bond0 +iface bond0 inet static + bond-slaves $EXTERNAL_DEV $INTERNAL_DEV + bond_mode 802.3ad + bond_miimon 100 + bond_lacp_rate 1 + address $(ifdata -pa $EXTERNAL_DEV) + netmask $(ifdata -pn $EXTERNAL_DEV) + gateway $(route -n | awk '/^0\.0\.0\.0/{print $2; exit}') + dns-nameservers $(awk '/^nameserver/ {print $2}' /etc/resolv.conf | xargs echo -n) + +# additional possible bonding mode +# auto bond0 +# iface bond0 inet manual +# bond-slaves eth0 eth1 +# bond_mode active-backup +# bond_miimon 100 + +# Example: +# allow-hotplug eth0 +# iface eth0 inet static +# address 192.168.1.101 +# netmask 255.255.255.0 +# network 192.168.1.0 +# broadcast 192.168.1.255 +# gateway 192.168.1.1 +# # dns-* options are implemented by the resolvconf package, if installed +# dns-nameservers 195.58.160.194 195.58.161.122 +# dns-search sipwise.com +EOF + elif "$PRO_EDITION" ; then # no bonding but pro-edition + cat > $TARGET/etc/network/interfaces << EOF +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). +# The loopback network interface +auto lo +iface lo inet loopback + +auto $EXTERNAL_DEV +iface $EXTERNAL_DEV inet static + address $(ifdata -pa $EXTERNAL_DEV) + netmask $(ifdata -pn $EXTERNAL_DEV) + gateway $(route -n | awk '/^0\.0\.0\.0/{print $2; exit}') + dns-nameservers $(awk '/^nameserver/ {print $2}' /etc/resolv.conf | xargs echo -n) + +auto $INTERNAL_DEV +iface $INTERNAL_DEV inet static + address $INTERNAL_IP + netmask $INTERNAL_NETMASK + +# Example: +# allow-hotplug eth0 +# iface eth0 inet static +# address 192.168.1.101 +# netmask 255.255.255.0 +# network 192.168.1.0 +# broadcast 192.168.1.255 +# gateway 192.168.1.1 +# # dns-* options are implemented by the resolvconf package, if installed +# dns-nameservers 195.58.160.194 195.58.161.122 +# dns-search sipwise.com +EOF + else # ce edition + cat > $TARGET/etc/network/interfaces << EOF +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). +# The loopback network interface +auto lo +iface lo inet loopback + +auto $EXTERNAL_DEV +iface $EXTERNAL_DEV inet static + address $(ifdata -pa $EXTERNAL_DEV) + netmask $(ifdata -pn $EXTERNAL_DEV) + gateway $(route -n | awk '/^0\.0\.0\.0/{print $2; exit}') + dns-nameservers $(awk '/^nameserver/ {print $2}' /etc/resolv.conf | xargs echo -n) + +### Further usage examples + +## Enable IPv6 autoconfiguration: +# auto eth1 +# iface eth1 inet6 manual +# up ifconfig eth1 up + +## Specific manual configuration: +# allow-hotplug eth2 +# iface eth2 inet static +# address 192.168.1.101 +# netmask 255.255.255.0 +# network 192.168.1.0 +# broadcast 192.168.1.255 +# gateway 192.168.1.1 +# # dns-* options are implemented by the resolvconf package, if installed +# dns-nameservers 195.58.160.194 195.58.161.122 +# dns-search sipwise.com +EOF + fi +fi # if $DHCP + +generate_etc_hosts() { + + # finalise hostname configuration + cat > $TARGET/etc/hosts << EOF +127.0.0.1 localhost + +# The following lines are desirable for IPv6 capable hosts +::1 ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters + +EOF + + # append hostnames of sp1/sp2 so they can talk to each other + # in the HA setup + if "$PRO_EDITION" ; then + cat >> $TARGET/etc/hosts << EOF +$IP1 sp1 +$IP2 sp2 +$IP_HA_SHARED sp +EOF + else + # otherwise 'hostname --fqdn' does not work and causes delays with exim4 startup + cat >> $TARGET/etc/hosts << EOF +# required for FQDN, please adjust if needed +127.0.0.2 $TARGET_HOSTNAME. $TARGET_HOSTNAME +EOF + fi + +} + +fake_uname() { + cat > "${TARGET}/tmp/uname.c" << EOF +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef UTS_RELEASE +#define UTS_RELEASE "0.0.0" +#endif + +#ifndef RTLD_NEXT +#define RTLD_NEXT ((void *) -1l) +#endif + +typedef int (*uname_t) (struct utsname * buf); + +static void *get_libc_func(const char *funcname) +{ + void *func; + char *error; + + func = dlsym(RTLD_NEXT, funcname); + if ((error = dlerror()) != NULL) { + fprintf(stderr, "Can't locate libc function \`%s' error: %s", funcname, error); + _exit(EXIT_FAILURE); + } + return func; +} + +int uname(struct utsname *buf) +{ + int ret; + char *env = NULL; + uname_t real_uname = (uname_t) get_libc_func("uname"); + + ret = real_uname((struct utsname *) buf); + strncpy(buf->release, ((env = getenv("UTS_RELEASE")) == NULL) ? UTS_RELEASE : env, 65); + return ret; +} +EOF + + grml-chroot "$TARGET" gcc -shared -fPIC -ldl /tmp/uname.c -o /tmp/fake-uname.so || die 'Failed to build fake-uname.so' + + # avoid "ERROR: ld.so: object '/tmp/fake-uname.so' from LD_PRELOAD cannot be preloaded: ignored." + # messages caused by the host system when running grml-chroot process + cp "$TARGET"/tmp/fake-uname.so /tmp/fake-uname.so +} + +vagrant_configuration() { + # bzip2, linux-headers-amd64 and make are required for VirtualBox Guest Additions installer + # less + sudo are required for Vagrant itself + echo "Installing software for VirtualBox Guest Additions installer" + # there's no linux-headers-amd64 package in squeeze: + case "$DEBIAN_RELEASE" in + squeeze) local linux_headers_package="linux-headers-2.6-amd64" ;; + *) local linux_headers_package="linux-headers-amd64" ;; + esac + if ! chroot "$TARGET" apt-get -y install bzip2 less ${linux_headers_package} make sudo ; then + die "Error: failed to install 'bzip2 less ${linux_headers_package} make sudo' packages." + fi + + vagrant_ssh_pub_key='/var/tmp/id_rsa_sipwise.pub' + echo "Checking out ngcp-vmbuilder git repository" + if ! wget -O "${vagrant_ssh_pub_key}" http://builder.mgm.sipwise.com/vagrant-ngcp/id_rsa_sipwise.pub ; then + die "Error: failed to wget public Sipwise SSH key for Vagrant boxes" + fi + + if "$NGCP_INSTALLER" ; then + SIPWISE_HOME="/var/sipwise" + + # TODO: move PATH adjustment to ngcp-installer (ngcpcfg should have a template here) + if ! grep -q '^# Added for Vagrant' "${TARGET}/${SIPWISE_HOME}/.profile" 2>/dev/null ; then + echo "Adjusting PATH configuration for user Sipwise" + echo "# Added for Vagrant" >> "${TARGET}/${SIPWISE_HOME}/.profile" + echo "PATH=\$PATH:/sbin:/usr/sbin" >> "${TARGET}/${SIPWISE_HOME}/.profile" + fi + + echo "Adjusting ssh configuration for user sipwise (add Vagrant SSH key)" + mkdir -p "${TARGET}/${SIPWISE_HOME}/.ssh/" + cat "${vagrant_ssh_pub_key}" >> "${TARGET}/${SIPWISE_HOME}/.ssh/sipwise_vagrant_key" + chroot "${TARGET}" chown sipwise:sipwise "${SIPWISE_HOME}/.ssh" "${SIPWISE_HOME}/.ssh/sipwise_vagrant_key" + chroot "${TARGET}" chmod 0600 "${SIPWISE_HOME}/.ssh/sipwise_vagrant_key" + fi + + echo "Adjusting ssh configuration for user root" + mkdir -p "${TARGET}/root/.ssh/" + cat "${vagrant_ssh_pub_key}" >> "${TARGET}/root/.ssh/sipwise_vagrant_key" + chroot "${TARGET}" chmod 0600 /root/.ssh/sipwise_vagrant_key + case "${DEBIAN_RELEASE}" in + squeeze) + sed -i 's|^[#\s]*AuthorizedKeysFile.*$|AuthorizedKeysFile %h/.ssh/sipwise_vagrant_key|g' "${TARGET}/etc/ssh/sshd_config" + ;; + *) + sed -i 's|^[#\s]*\(AuthorizedKeysFile.*\)$|\1 %h/.ssh/sipwise_vagrant_key|g' "${TARGET}/etc/ssh/sshd_config" + ;; + esac + + # see https://github.com/mitchellh/vagrant/issues/1673 + # and https://bugs.launchpad.net/ubuntu/+source/xen-3.1/+bug/1167281 + if ! grep -q 'adjusted for Vagrant' "${TARGET}/root/.profile" ; then + echo "Adding workaround for annoying bug 'stdin: is not a tty' Vagrant message" + sed -ri -e "s/mesg\s+n/# adjusted for Vagrant\ntty -s \&\& mesg n/" "${TARGET}/root/.profile" + fi + + install_vbox_iso + + # required for fake_uname and VBoxLinuxAdditions.run + grml-chroot $TARGET apt-get -y install libc6-dev gcc + fake_uname + + # shellcheck disable=SC2010 + KERNELHEADERS=$(basename "$(ls -d ${TARGET}/usr/src/linux-headers*amd64 | grep -v -- -rt-amd64 | sort -u -r -V | head -1)") + if [ -z "$KERNELHEADERS" ] ; then + die "Error: no kernel headers found for building the VirtualBox Guest Additions kernel module." + fi + KERNELVERSION=${KERNELHEADERS##linux-headers-} + if [ -z "$KERNELVERSION" ] ; then + die "Error: no kernel version could be identified." + fi + + if [ ! -r "$vbox_isofile" ] ; then + die "Error: could not find $vbox_isofile" + fi + + mkdir -p "${TARGET}/media/cdrom" + mountpoint "${TARGET}/media/cdrom" >/dev/null && umount "${TARGET}/media/cdrom" + mount -t iso9660 "${vbox_isofile}" "${TARGET}/media/cdrom/" + UTS_RELEASE=$KERNELVERSION LD_PRELOAD=/tmp/fake-uname.so grml-chroot "$TARGET" /media/cdrom/VBoxLinuxAdditions.run --nox11 + tail -10 "${TARGET}/var/log/VBoxGuestAdditions.log" + umount "${TARGET}/media/cdrom/" + + # work around regression in virtualbox-guest-additions-iso 4.3.10 + if [ -d ${TARGET}/opt/VBoxGuestAdditions-4.3.10 ] ; then + echo "Installing VBoxGuestAddition symlink to work around vbox 4.3.10 issue" + ln -s /opt/VBoxGuestAdditions-4.3.10/lib/VBoxGuestAdditions ${TARGET}/usr/lib/VBoxGuestAdditions + fi + + # VBoxLinuxAdditions.run chooses /usr/lib64 as soon as this directory exists, which + # is the case for our PRO systems shipping the heartbeat-2 package; then the + # symlink /sbin/mount.vboxsf points to the non-existing /usr/lib64/VBoxGuestAdditions/mount.vboxsf + # file instead of pointing to /usr/lib/x86_64-linux-gnu/VBoxGuestAdditions/mount.vboxsf + if ! chroot "$TARGET" readlink -f /sbin/mount.vboxsf ; then + echo "Installing mount.vboxsf symlink to work around /usr/lib64 issue" + ln -sf /usr/lib/x86_64-linux-gnu/VBoxGuestAdditions/mount.vboxsf ${TARGET}/sbin/mount.vboxsf + fi + + # MACs are different on buildbox and on local VirtualBox + # see http://ablecoder.com/b/2012/04/09/vagrant-broken-networking-when-packaging-ubuntu-boxes/ + echo "Removing /etc/udev/rules.d/70-persistent-net.rules" + rm -f "${TARGET}/etc/udev/rules.d/70-persistent-net.rules" + + if [ -d "${TARGET}/etc/.git" ]; then + echo "Commit /etc/* changes using etckeeper" + chroot "$TARGET" etckeeper commit "Vagrant/VirtualBox changes on /etc/*" + fi +} + +if "$CARRIER_EDITION" ; then + echo "Nothing to do on Carrier, /etc/hosts was already set up." +else + echo "Generating /etc/hosts" + generate_etc_hosts +fi + +if "$VAGRANT" ; then + echo "Bootoption vagrant present, executing vagrant_configuration." + vagrant_configuration +fi + +if [ -n "$PUPPET" ] ; then + +check_puppet_rc () { + local _puppet_rc="$1" + local _expected_rc="$2" + + if [ "${_puppet_rc}" != "${_expected_rc}" ] ; then + # an exit code of '0' happens for 'puppet agent --enable' only, + # an exit code of '2' means there were changes, + # an exit code of '4' means there were failures during the transaction, + # an exit code of '6' means there were both changes and failures. + set_deploy_status "error" + fi +} + +check_puppet_rerun() { + local repeat=1 + + if ! checkBootParam nopuppetrepeat && [ "$(get_deploy_status)" = "error" ] ; then + echo "Do you want to [r]epeat puppet run or [c]ontinue?" + while true; do + read a + case "${a,,}" in + r) + echo "Repeating puppet run." + repeat=0 + set_deploy_status "puppet" + break + ;; + c) + echo "Continue without repeating puppet run." + set_deploy_status "puppet" + break + ;; + * ) echo -n "Please answer 'r' to repeat or 'c' to continue: " ;; + esac + unset a + done + fi + + return "${repeat}" +} + +check_puppetserver_time() { + while true; do + offset=$(ntpdate -q "$PUPPET_SERVER" | sed -n '1s/.*offset \(.*\),.*/\1/p' | tr -d -) + seconds=${offset%.*} + if (( seconds < 10 )) ; then + echo "All OK. Time offset between $PUPPET_SERVER and current server is $seconds seconds only." + break + elif checkBootParam nopuppetrepeat ; then + echo "WARNING: time offset between $PUPPET_SERVER and current server is $seconds seconds." + echo "(ignoring due to boot option nopuppetrepeat)" + break + else + echo "WARNING: time difference between the current server and $PUPPET_SERVER is ${seconds} seconds (bigger than 10 seconds)." + echo "Please synchronize time and press any key to recheck or [c]ontinue with puppet run." + read a + case "${a,,}" in + c) + echo "Continue ignoring time offset check." + break + ;; + * ) echo -n "Rechecking the offset..." ;; + esac + unset a + fi + done +} + +puppet_install_from_git () { + local repeat + + : "${PUPPET_GIT_REPO?ERROR: variable 'PUPPET_GIT_REPO' is NOT defined, cannot continue.}" + : "${PUPPET_LOCAL_GIT?ERROR: variable 'PUPPET_LOCAL_GIT' is NOT defined, cannot continue.}" + : "${PUPPET_GIT_BRANCH?ERROR: variable 'PUPPET_GIT_BRANCH' is NOT defined, cannot continue.}" + + echo "Searching for Hiera rescue device by label '${PUPPET_RESCUE_LABEL}'..." + local PUPPET_RESCUE_DRIVE + PUPPET_RESCUE_DRIVE=$(blkid | grep -E "LABEL=\"${PUPPET_RESCUE_LABEL}" | head -1 | awk -F: '{print $1}') + + if [ -n "${PUPPET_RESCUE_DRIVE}" ] ; then + echo "Found Hiera rescue device: '${PUPPET_RESCUE_DRIVE}'" + else + die "ERROR: No USB device found matching label '${PUPPET_RESCUE_LABEL}', cannot continue!" + fi + + echo "Searching for Hiera rescue device type..." + local DEVICE_TYPE + DEVICE_TYPE=$(blkid | grep -E "LABEL=\"${PUPPET_RESCUE_LABEL}" | head -1 | sed 's/.*TYPE="\(.*\)".*/\1/') + + if [ -n "${DEVICE_TYPE}" ] ; then + echo "Hiera rescue device type is:'${DEVICE_TYPE}'" + else + die "ERROR: Cannot detect device type for device '${PUPPET_RESCUE_LABEL}', cannot continue!" + fi + + echo "Copying data from device '${PUPPET_RESCUE_DRIVE}' (mounted into '${PUPPET_RESCUE_PATH}', type '${DEVICE_TYPE}')" + mkdir -p "${PUPPET_RESCUE_PATH}" + mount -t "${DEVICE_TYPE}" -o ro "${PUPPET_RESCUE_DRIVE}" "${PUPPET_RESCUE_PATH}" + mkdir -m 0700 -p "${TARGET}/etc/puppetlabs/code/hieradata/" + cp -a "${PUPPET_RESCUE_PATH}"/hieradata/* "${TARGET}/etc/puppetlabs/code/hieradata/" + mkdir -p ~/.ssh + cp "${PUPPET_RESCUE_PATH}"/hieradata/defaults.d/id_rsa_r10k ~/.ssh/ + chmod 600 ~/.ssh/id_rsa_r10k + umount -f "${PUPPET_RESCUE_PATH}" + rmdir "${PUPPET_RESCUE_PATH}" + + echo "Cloning Puppet git repository from '${PUPPET_GIT_REPO}' to '${PUPPET_LOCAL_GIT}' (branch '${PUPPET_GIT_BRANCH}')" + echo 'ssh -i ~/.ssh/id_rsa_r10k -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $*' > ssh + chmod +x ssh + if ! GIT_SSH="${PWD}/ssh" git clone --depth 1 -b "${PUPPET_GIT_BRANCH}" "${PUPPET_GIT_REPO}" "${PUPPET_LOCAL_GIT}" ; then + die "ERROR: Cannot clone git repository, see the error above, cannot continue!" + fi + rm "${PWD}/ssh" + + local PUPPET_CODE_PATH + PUPPET_CODE_PATH="/etc/puppetlabs/code/environments/${PUPPET}" + + echo "Creating empty Puppet environment ${TARGET}/${PUPPET_CODE_PATH}" + mkdir -m 0755 -p "${TARGET}/${PUPPET_CODE_PATH}" + + echo "Deploying Puppet code from Git repository to ${TARGET}/${PUPPET_CODE_PATH}" + cp -a "${PUPPET_LOCAL_GIT}"/* "${TARGET}/${PUPPET_CODE_PATH}" + rm -rf "${PUPPET_LOCAL_GIT:?}" + + repeat=true + while $repeat ; do + repeat=false + echo "Initializing Hiera config..." + grml-chroot $TARGET puppet apply --test --modulepath="${PUPPET_CODE_PATH}/modules" \ + -e "include puppet::hiera" 2>&1 | tee -a /tmp/puppet.log + check_puppet_rc "${PIPESTATUS[0]}" "2" + check_puppet_rerun && repeat=true + done + + repeat=true + while $repeat ; do + repeat=false + echo "Running Puppet core deployment..." + grml-chroot $TARGET puppet apply --test --modulepath="${PUPPET_CODE_PATH}/modules" --tags core,apt \ + "${PUPPET_CODE_PATH}/manifests/site.pp" 2>&1 | tee -a /tmp/puppet.log + check_puppet_rc "${PIPESTATUS[0]}" "2" + check_puppet_rerun && repeat=true + done + + repeat=true + while $repeat ; do + repeat=false + echo "Running Puppet main deployment..." + grml-chroot $TARGET puppet apply --test --modulepath="${PUPPET_CODE_PATH}/modules" \ + "${PUPPET_CODE_PATH}/manifests/site.pp" 2>&1 | tee -a /tmp/puppet.log + check_puppet_rc "${PIPESTATUS[0]}" "2" + check_puppet_rerun && repeat=true + done +} + +puppet_install_from_puppet () { + local repeat + + check_puppetserver_time + + repeat=true + while $repeat ; do + repeat=false + echo "Running Puppet core deployment..." + grml-chroot $TARGET puppet agent --test --tags core,apt 2>&1 | tee -a /tmp/puppet.log + check_puppet_rc "${PIPESTATUS[0]}" "2" + check_puppet_rerun && repeat=true + done + + repeat=true + while $repeat ; do + repeat=false + echo "Running Puppet main deployment..." + grml-chroot $TARGET puppet agent --test 2>&1 | tee -a /tmp/puppet.log + check_puppet_rc "${PIPESTATUS[0]}" "2" + check_puppet_rerun && repeat=true + done +} + + set_deploy_status "puppet" + + echo "Rebuilding /etc/hosts" + cat > $TARGET/etc/hosts << EOF +# Generated via deployment.sh +127.0.0.1 localhost + +# The following lines are desirable for IPv6 capable hosts +::1 ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters + +EOF + + echo "Setting hostname to $TARGET_HOSTNAME" + echo "$TARGET_HOSTNAME" > ${TARGET}/etc/hostname + grml-chroot $TARGET hostname -F /etc/hostname + + chroot $TARGET apt-get -y install resolvconf libnss-myhostname + + if [ "$DEBIAN_RELEASE" = "stretch" ] && [ ! -x "${TARGET}/usr/bin/dirmngr" ] ; then + echo "Installing dirmngr on Debian Stretch otherwise 'apt-key adv --recv-keys' is failing to fetch GPG key" + chroot $TARGET apt-get -y install dirmngr + fi + + echo "Installing 'puppet-agent' with dependencies" + cat >> ${TARGET}/etc/apt/sources.list.d/puppetlabs.list << EOF +deb ${DEBIAN_REPO_TRANSPORT}://${DEBIAN_REPO_HOST}/puppetlabs/ ${DEBIAN_RELEASE} main puppet dependencies +EOF + + PUPPET_GPG_KEY="6F6B15509CF8E59E6E469F327F438280EF8D349F" + + TRY=60 + while ! chroot ${TARGET} apt-key adv --recv-keys --keyserver "${GPG_KEY_SERVER}" "${PUPPET_GPG_KEY}" ; do + if [ ${TRY} -gt 0 ] ; then + TRY=$((TRY-5)) + echo "Waiting for gpg keyserver '${GPG_KEY_SERVER}' availability ($TRY seconds)..." + sleep 5 + else + die "Failed to fetch GPG key '${PUPPET_GPG_KEY}' from '${GPG_KEY_SERVER}'" + fi + done + + chroot ${TARGET} apt-get update + chroot ${TARGET} apt-get -y install puppet-agent openssh-server lsb-release ntpdate + + if [ "$DEBIAN_RELEASE" = "stretch" ]; then + chroot ${TARGET} ln -s /proc/self/mounts /etc/mtab || true + fi + + cat > ${TARGET}/etc/puppetlabs/puppet/puppet.conf<< EOF +# This file has been created by deployment.sh +[main] +server=${PUPPET_SERVER} +environment=${PUPPET} +EOF + + if [ -f "${TARGET}/etc/profile.d/puppet-agent.sh" ] ; then + echo "Exporting Puppet 4 new PATH (otherwise /opt/puppetlabs/bin/puppet is not found)" + source "${TARGET}/etc/profile.d/puppet-agent.sh" + fi + + if [ -n "${PUPPET_GIT_REPO}" ] ; then + echo "Installing from Puppet Git repository using 'puppet apply'" + puppet_install_from_git + else + echo "Installing from Puppet server '${PUPPET_SERVER}' using 'puppet agent'" + puppet_install_from_puppet + fi + +fi # if [ -n "$PUPPET" ] ; then + +# make sure we don't leave any running processes +for i in asterisk atd collectd collectdmon dbus-daemon exim4 \ + glusterd glusterfs glusterfsd glusterfs-server haveged monit nscd \ + redis-server snmpd voisniff-ng ; do + killall -9 $i >/dev/null 2>&1 || true +done + +# remove retrieved and generated files +rm -f ${TARGET}/config_*yml +rm -f ${TARGET}/constants_*.yml +rm -f ${TARGET}/ngcp-installer*deb + +if [ -r "${INSTALL_LOG}" ] && [ -d "${TARGET}"/var/log/ ] ; then + cp "${INSTALL_LOG}" "${TARGET}"/var/log/ +fi + +# don't leave any mountpoints +sync +umount ${TARGET}/proc 2>/dev/null || true +umount ${TARGET}/sys 2>/dev/null || true +umount ${TARGET}/dev/pts 2>/dev/null || true +umount ${TARGET}/dev 2>/dev/null || true +chroot ${TARGET} umount -a 2>/dev/null || true +sync + +# unmount chroot - what else? +umount $TARGET || umount -l $TARGET # fall back if a process is still being active + +if "$LVM" ; then + # make sure no device mapper handles are open, otherwise + # rereading partition table won't work + dmsetup remove_all || true +fi + +# make sure /etc/fstab is up2date +if ! blockdev --rereadpt "/dev/${DISK}" ; then + echo "Something on disk /dev/${DISK} (mountpoint $TARGET) seems to be still active, debugging output follows:" + ps auxwww || true +fi + +# party time! who brings the whiskey? +echo "Installation finished. \o/" +echo +echo + +[ -n "$start_seconds" ] && SECONDS="$(( $(cut -d . -f 1 /proc/uptime) - start_seconds))" || SECONDS="unknown" +logit "Successfully finished deployment process [$(date) - running ${SECONDS} seconds]" +echo "Successfully finished deployment process [$(date) - running ${SECONDS} seconds]" + +if [ "$(get_deploy_status)" != "error" ] ; then + set_deploy_status "finished" +fi + +# if ngcpstatus boot option is used wait for a specific so a +# remote host has a chance to check for deploy status "finished", +# defaults to 0 seconds otherwise +sleep "$STATUS_WAIT" + +if "$INTERACTIVE" ; then + exit 0 +fi + +# do not prompt when running in automated mode +if "$REBOOT" ; then + echo "Rebooting system as requested via ngcpreboot" + for key in s u b ; do + echo $key > /proc/sysrq-trigger + sleep 2 + done +fi + +if "$HALT" ; then + echo "Halting system as requested via ngcphalt" + + for key in s u o ; do + echo $key > /proc/sysrq-trigger + sleep 2 + done +fi + +echo "Do you want to [r]eboot or [h]alt the system now? (Press any other key to cancel.)" +unset a +read a +case "$a" in + r) + echo "Rebooting system as requested." + # reboot is for losers + for key in s u b ; do + echo $key > /proc/sysrq-trigger + sleep 2 + done + ;; + h) + echo "Halting system as requested." + # halt(8) is for losers + for key in s u o ; do + echo $key > /proc/sysrq-trigger + sleep 2 + done + ;; + *) + echo "Not halting system as requested. Please do not forget to reboot." + ;; +esac + +## END OF FILE #################################################################1 diff --git a/templates/scripts/main.sh b/templates/scripts/main.sh index 0fdb5b9..a178481 100755 --- a/templates/scripts/main.sh +++ b/templates/scripts/main.sh @@ -8,7 +8,6 @@ export LC_ALL=C working_dir="$(dirname "$0")" scripts_dir="${working_dir}/includes/" keys_dir="${working_dir}/keys/" -netscript_dir="${scripts_dir}/netscript/" RC=0 @@ -141,7 +140,7 @@ deploy() { einfo "Running ${YELLOW}${version}${NORMAL} of deployment.sh..."; eend 0 RC=0 - TARGET_DISK="$TARGET_DISK" /bin/bash "${netscript_dir}/${version}/deployment.sh" || RC=$? + TARGET_DISK="$TARGET_DISK" /bin/bash "${scripts_dir}/deployment.sh" || RC=$? if [ $RC -eq 0 ] ; then if dialog --yes-label Reboot --no-label Exit --yesno "Successfully finished deployment, enjoy your sip:provider system. Reboot system now?" 0 0 ; then reboot