#!/bin/bash # Use special param to make sure we're running under bash (in case user does "sh install.sh") [ "x$1" != "x--exec-self" ] && exec /bin/bash "$0" --exec-self "$@" if [ ! -d "/opt/dmsd" ] && [ ! -d "/srv/openslx/www/slx-admin" ]; then echo "This system doesn't look like a bwLehrpool Satellite Server" exit 1 fi TEST1=$(which systemctl) TEST2=$(lsb_release -sc) if [ -z "$TEST1" ] || [ "x$TEST2" != "xjessie" ]; then echo "This Version of the bwLehrpool Satellite Server is too old!" exit 1 fi unset TEST1 TEST2 unset TMPDIR [ -n "$TMPDIR" ] && exit 1 IGNORE_ERRORS= while [ $# -gt 0 ]; do [ "x$1" = "x--ignore-errors" ] && IGNORE_ERRORS=jup shift done readonly IGNORE_ERRORS declare -rg SELFPID=$$ perror () { if [ -n "$IGNORE_ERRORS" ]; then echo -n -e '\033[01;31m[ERROR]\033[00m ' echo "$@" return 0 fi echo -n -e '\033[01;31m[FATAL]\033[00m ' echo "$@" [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ] && rm -rf -- "$TMPDIR" [ "$$" != "$SELFPID" ] && kill "$SELFPID" exit 1 } pwarning () { echo -n -e '\033[01;33m[WARNING]\033[00m ' echo "$@" } if [ "$UID" != "0" ]; then perror "Must be running as root" fi # ** Extract value from text file containing key=value pairs extractfield () { grep -m1 "^\s*$2\b" "$1" | awk -F '=' '{print $2}' | sed 's/\s//g' } # ** Wrap mysql command line client so we're always using the deb-sys-maint credentials mysql () { "$(which mysql)" --defaults-extra-file=/etc/mysql/debian.cnf --default-character-set=utf8 "$@" } # ** Restart given systemd service, warn if it fails but do not bail out restart_service () { if ! systemctl restart "$1"; then pwarning "Could not restart service $1 - !! YOU SHOULD REBOOT THE SERVER !!" systemctl status "$1" fi } # ** Recursively set permissions of given directory to 0755/0644 optionally setting owner/group fixperms () { [ -e "$1" ] || perror "normalize_perms: $1 does not exist" chmod -R a-rw,u+rwX,go+rX "$1" if [ -n "$2" ]; then chown -R "$2" "$1" || pwarning "Could not change owner of $1 to $2" fi } # ** Constants - to be patched by the packaging script declare -rg TARGET_WEBIF_VERSION="%TARGET_WEBIF_VERSION%" declare -rg TGZ_SLXADMIN="%TGZ_SLXADMIN%" declare -rg TGZ_DOZMOD="%TGZ_DOZMOD%" declare -rg TGZ_TASKMANAGER="%TGZ_TASKMANAGER%" declare -rg TGZ_TFTP="%TGZ_TFTP%" declare -rg TGZ_IPXE="%TGZ_IPXE%" declare -rg TGZ_LDADP="%TGZ_LDADP%" declare -rg PAYLOAD_OFFSET="%PAYLOAD_OFFSET%" declare -rg SLXADMIN_FOOTER="%SLXADMIN_FOOTER%" # ** Constants - hardcoded or determined at runtime declare -rg PATH_SLXADMIN="/srv/openslx/www/slx-admin" declare -rg PATH_SLXADMINCACHE="/var/cache/slx-admin" declare -rg PATH_DOZMOD="/opt/dmsd" declare -rg PATH_TASKMANAGER="/opt/taskmanager" declare -rg PATH_TFTP="/srv/openslx/tftp" declare -rg PATH_IPXE="/opt/openslx/ipxe" declare -rg PATH_LDADP="/opt/ldadp" # ** Check if constants have been filled, bail out otherwise if [ -z "$TARGET_WEBIF_VERSION" ] || [[ "$TARGET_WEBIF_VERSION" == %*% ]]; then [ -n "$TGZ_SLXADMIN" ] && perror "Bad upgrader: TARGET_WEBIF_VERSION not set" fi if [ -z "$PAYLOAD_OFFSET" ] || [[ "$PAYLOAD_OFFSET" == %*% ]]; then perror "Bad upgrader: PAYLOAD_OFFSET not set" fi # ********************************************************** # Get current webif version if [ -n "$TGZ_SLXADMIN" ]; then declare -rg CURRENT_WEBIF_VERSION=$(mysql -e 'SELECT value FROM openslx.property WHERE name = "webif-version" LIMIT 1' | tail -n 1) if [ -z "$CURRENT_WEBIF_VERSION" ] || [ "$TARGET_WEBIF_VERSION" = "missing" ] || [ "$CURRENT_WEBIF_VERSION" -le "$TARGET_WEBIF_VERSION" ]; then : # Negate so NaN triggers else branch else perror "This update seems to be older than the server version you're currently running" fi fi # **************** Fix tmpdelete cronjob ******************* if [ -f "/etc/cron.daily/tmpdelete.sh" ]; then [ -f "/etc/cron.daily/tmpdelete" ] || mv "/etc/cron.daily/tmpdelete.sh" "/etc/cron.daily/tmpdelete" rm -f -- "/etc/cron.daily/tmpdelete.sh" fi # ************** Extract payload *************************** declare -rg TMPDIR=$(mktemp -d) [ -z "$TMPDIR" ] && perror "Could not create temporary directory for installer" dd "bs=$PAYLOAD_OFFSET" "if=$0" skip=1 | tar -z -x -C "$TMPDIR" RET=$? [ "$RET" -ne 0 ] && perror "Extracting installer payload failed with exit code $RET" declare -rg FILEDIR="$TMPDIR/files" # ********************************************************** # ********************** Taskmanager *********************** # Do this first in case one of the later updates depends on the taskmanager if [ -n "$TGZ_TASKMANAGER" ]; then [ -e "$TMPDIR/$TGZ_TASKMANAGER" ] || perror "$TGZ_TASKMANAGER missing from payload" echo "* Task manager" echo "Extracting new jar and data" # Replacement trick (see slxadmin) tar -x -C "$PATH_TASKMANAGER" -f "$TMPDIR/$TGZ_TASKMANAGER" || perror "Could not extract $TGZ_TASKMANAGER to $PATH_TASKMANAGER" rm -rf -- "$PATH_TASKMANAGER/data" "$PATH_TASKMANAGER/scripts" "$PATH_TASKMANAGER/plugins" "$PATH_TASKMANAGER/taskmanager.sh" tar -x -C "$PATH_TASKMANAGER" -f "$TMPDIR/$TGZ_TASKMANAGER" fixperms "$PATH_TASKMANAGER" root:root chmod -R a+x "$PATH_TASKMANAGER/scripts" echo "Restarting service" restart_service taskmanager echo "Taskmanager upgrade complete" fi # ************************** IPXE ************************** IPXE_PID= if [ -n "$TGZ_IPXE" ]; then [ -e "$TMPDIR/$TGZ_IPXE" ] || perror "$TGZ_IPXE missing from payload" echo "* iPXE source code" echo "Extracting" rm -rf -- "$PATH_IPXE" mkdir -p "$PATH_IPXE" tar -x -C "$PATH_IPXE" -f "$TMPDIR/$TGZ_IPXE" || perror "Could not extract $TGZ_IPXE to $PATH_IPXE" fixperms "$PATH_IPXE" taskmanager:taskmanager echo "Resetting pxe menu" mysql -e 'UPDATE openslx.property SET value = "invalid" WHERE name = "server-ip"' || pwarning "Could not reset pxe menu status; manual regeneration of menu required" echo "iPXE upgrade complete" # Trigger default compile in the background so the next regen doesn't take too long { cd "$PATH_IPXE/src" && sudo -n -u taskmanager nice -n 10 make -j2 bin/undionly.kkkpxe > /dev/null 2>&1 } & IPXE_PID=$! fi # ************************** SLX-Admin ********************* if [ -n "$TGZ_SLXADMIN" ]; then [ -e "$TMPDIR/$TGZ_SLXADMIN" ] || perror "$TGZ_SLXADMIN missing from payload." echo "* SLX-Admin: $CURRENT_WEBIF_VERSION -> $TARGET_WEBIF_VERSION" # Test archive tar tf "$TMPDIR/$TGZ_SLXADMIN" >/dev/null 2>&1 || perror "Could not read $TGZ_SLXADMIN" rm -rf -- "$PATH_SLXADMIN/"{inc,apis,modules,templates,Mustache,script,style} tar -x -C "$PATH_SLXADMIN" -f "$TMPDIR/$TGZ_SLXADMIN" || perror "Could not extract $TGZ_SLXADMIN to $PATH_SLXADMIN" rm -f -- "$PATH_SLXADMIN/config.php.example" # New config.php supplied if [ -s "$FILEDIR/slxadmin-config.php" ]; then # Get data from old config OLDFOOTER="$(grep -m 1 CONFIG_FOOTER "${PATH_SLXADMIN}/config.php" | awk -F "'" '{print $4}' | sed 's/[ \[\]\(\)]*Update.*$//;s/#/+/g')" SQLPASS=$(grep -m1 '^define.*CONFIG_SQL_PASS.*;' "${PATH_SLXADMIN}/config.php" | awk -F "'" '{print $4}') # Patch config with new features using old mysql password if [ -z "$SQLPASS" ]; then pwarning "Could not extract old slx-admin mysql password - cannot update config :(" else sed "s/%MYSQL_OPENSLX_PASS%/${SQLPASS}/g" "$FILEDIR/slxadmin-config.php" > "${PATH_SLXADMIN}/config.php" fi # Update version info in footer [ -z "$OLDFOOTER" ] && OLDFOOTER="Unknown base version" FOOTER="$SLXADMIN_FOOTER" [[ "$FOOTER" == %*% ]] && FOOTER= if [ -z "$FOOTER" ]; then D=$(stat -c %Y "$0") [ -z "$D" ] && D=$(date +%s) D=$(date -d "@$D" "+%y-%m-%d %H:%M") FOOTER="Unknown $D" fi FOOTER="$OLDFOOTER [Update: ${FOOTER}]" sed -i "s#^.*define.*CONFIG_FOOTER.*\$#define('CONFIG_FOOTER', '${FOOTER}');#" "${PATH_SLXADMIN}/config.php" grep -q 'CONFIG_FOOTER' "${PATH_SLXADMIN}/config.php" || echo "define('CONFIG_FOOTER', '${FOOTER}');" >> "${PATH_SLXADMIN}/config.php" echo "$TARGET_WEBIF_VERSION" > "${PATH_SLXADMIN}/version" fi # Enable modules ( mkdir -p "$PATH_SLXADMIN/modules" cd "$PATH_SLXADMIN/modules" || perror "Cannot cd to slxadmin" for mod in adduser backup baseconfig baseconfig_bwidm baseconfig_bwlp bootstrap_datepicker bootstrap_dialog bootstrap_timepicker bootstrap_multiselect bootstrap_switch dozmod eventlog exams js_chart js_circles js_jqueryui js_moment js_selectize js_vis locations main minilinux news serversetup-bwlp roomplanner session statistics summernote sysconfig syslog systemstatus vmstore webinterface; do name=${mod%%-*} rm -f -- "$name" ln -s "../modules-available/$mod" "$name" || pwarning "Could not activate module '$mod' (alias '$name')" done # Update DB cd "$PATH_SLXADMIN" if ! ./install-all > "$TMPDIR/wwwup.log"; then cat "$TMPDIR/wwwup.log" perror "Updating the web interface database failed" fi if grep -q 'Result: UPDATE_FAILED' "$TMPDIR/wwwup.log"; then cat "$TMPDIR/wwwup.log" perror "Updating the web interface database failed" fi if [ "x$(tail -n -1 "$TMPDIR/wwwup.log")" != "xDone." ]; then cat "$TMPDIR/wwwup.log" pwarning "slxadmin updater didn't finish with 'Done.'" fi ) fixperms "$PATH_SLXADMIN" root:root chmod 0640 "$PATH_SLXADMIN/config.php" chown root:www-data "$PATH_SLXADMIN/config.php" # config.tgz symlink -> db entry if [ -L /srv/openslx/www/boot/default/config.tgz ]; then CONFTGZ=$(readlink /srv/openslx/www/boot/default/config.tgz | sed "s/'/\\\'/g") echo "config.tgz links to '$CONFTGZ'" mysql -e "INSERT IGNORE INTO openslx.configtgz_location (locationid, configid) SELECT 0, configid FROM openslx.configtgz WHERE filepath = '$CONFTGZ' LIMIT 1" \ || pwarning "Could not convert default config.tgz setting - do so manually" rm -f -- /srv/openslx/www/boot/default/config.tgz fi ln -s -f "$PATH_TFTP" "/srv/openslx/www/tftp" || perror "Could not symlink $PATH_TFTP to /srv/openslx/www/tftp" echo "Web interface upgrade complete" mkdir -p "${PATH_SLXADMINCACHE}" fixperms "${PATH_SLXADMINCACHE}" www-data:www-data rm -f -- "/srv/openslx/www/slx-admin/modules-available/baseconfig_bwidm/baseconfig/settings.json" ln -s "${PATH_SLXADMINCACHE}/baseconfig-bwidm_settings.json" /srv/openslx/www/slx-admin/modules-available/baseconfig_bwidm/baseconfig/settings.json || \ pwarning "Could not set link ${PATH_SLXADMINCACHE}/baseconfig-bwidm_settings.json to /srv/openslx/www/slx-admin/modules-available/baseconfig_bwidm/baseconfig/settings.json - do so manually if you need bwIDM login on client computers" fi # ************************* Dozmod ************************* if [ -n "$TGZ_DOZMOD" ]; then [ -e "$TMPDIR/$TGZ_DOZMOD" ] || perror "$TGZ_DOZMOD missing from payload." echo "* bwLehrpool-Suite Server (dmsd)" echo "Adjusting mysql permissions of user sat" mysql -e 'GRANT CREATE, ALTER ON sat.* TO sat@localhost' || perror "Could not GRANT permissions ON sat.* to sat@localhost" mysql -e 'GRANT SELECT ON openslx.location TO sat@localhost' || perror "Could not GRANT permissions ON openslx.location to sat@localhost" echo "Extracting new jar" tar -x -C "$PATH_DOZMOD" -f "$TMPDIR/$TGZ_DOZMOD" || perror "Could not extract $TGZ_DOZMOD to $PATH_DOZMOD" rm -rf -- "$PATH_DOZMOD/bwLehrpoolSuite_Server.jar" "$PATH_DOZMOD/control.sh" "$PATH_DOZMOD/flag" tar -x -C "$PATH_DOZMOD" -f "$TMPDIR/$TGZ_DOZMOD" if mysql -e 'SHOW TABLES' openslx | grep -q '^location$'; then echo "Enabling location feature" sed -i '/^db.location-table\b/d' "$PATH_DOZMOD/config.properties" echo 'db.location-table = openslx.location' >> "$PATH_DOZMOD/config.properties" fi fixperms "$PATH_DOZMOD" root:images echo "Restarting service" restart_service dmsd echo "dmsd upgrade complete" fi # ************************** TFTP ************************** if [ -n "$TGZ_TFTP" ]; then [ -e "$TMPDIR/$TGZ_TFTP" ] || perror "$TGZ_TFTP missing from payload" echo "* TFTP" echo "Extracting" rm -rf -- "$PATH_TFTP/v4" "$PATH_TFTP/v6" "$PATH_TFTP/ipxelinux.0" "$PATH_TFTP/pxelinux.0" mkdir -p "$PATH_TFTP" tar -x -C "$PATH_TFTP" -f "$TMPDIR/$TGZ_TFTP" || perror "Could not extract $TGZ_TFTP to $PATH_TFTP" fixperms "$PATH_TFTP" taskmanager:taskmanager echo "Resetting pxe menu" mysql -e 'UPDATE openslx.property SET value = "invalid" WHERE name = "server-ip"' || pwarning "Could not reset pxe menu status; manual regeneration of menu required" echo "TFTP upgrade complete" fi RESTART_LIGHTY= # ********************** lighttpd config ******************* if [ -e "$FILEDIR/lighttpd.conf" ] && [ -e "/etc/lighttpd/lighttpd.conf" ]; then echo "* Replacing lighttpd.conf" cp "$FILEDIR/lighttpd.conf" "/etc/lighttpd/lighttpd.conf" || perror "Could not replace /etc/lighttpd/lighttpd.conf" RESTART_LIGHTY=ja echo "lighttpd config upgrade complete" fi # ********************** lighttpd php_children ************* echo "* lighttpd: dynamic php children value" echo -n "Looking for lighttpd service file..." if [ -f /lib/systemd/system/lighttpd.service ]; then # service file found, patching dynamic php children value at system start via patchfile if ! grep -q patch_lighttpd_phpchildren /lib/systemd/system/lighttpd.service; then echo -n " found. Patching service file ... " sed -i 's#\[Service\]#\[Service\]\nExecStartPre=\-/usr/local/sbin/patch_lighttpd_phpchildren#g' \ /lib/systemd/system/lighttpd.service || perror "Could not patch service file!" cp "$FILEDIR/patch_lighttpd_phpchildren" /usr/local/sbin || perror "Could not copy patch_lighttpd_phpchildren script!" chmod +x /usr/local/sbin/patch_lighttpd_phpchildren # Just to sleep better in dark nights. echo " done." systemctl daemon-reload RESTART_LIGHTY=ja else echo " patch_lighttpd_phpchildren entry already there, doing nothing." fi else echo " not found. Doing nothing." fi # ************************** PHP *************************** declare -rg PHPINIFILE=/etc/php5/cgi/php.ini if ! grep -q 'upload_max_filesize = 100M' "$PHPINIFILE"; then echo "* Increasing php upload limit" if grep -q -E "^\s*upload_max_filesize" "$PHPINIFILE"; then sed -i -e '/^\s*upload_max_filesize/c\upload_max_filesize = 100M' "$PHPINIFILE" || pwarning "Could not increase PHP upload limit :( (1)" else echo "upload_max_filesize = 100M" >> "$PHPINIFILE" || pwarning "Could not incease PHP upload limit :( (2)" fi RESTART_LIGHTY=ja fi # ************************** LIGHTY ************************ if [ -n "$RESTART_LIGHTY" ]; then echo "* Restarting lighttpd" restart_service lighttpd fi # ********************** atftpd.service ******************** if [ -e "$FILEDIR/atftpd.service" ]; then echo "* Replacing atftpd.service" cp "$FILEDIR/atftpd.service" "/etc/systemd/system/atftpd.service" || perror "Could not replace /etc/systemd/system/atftpd.service" ln -s -f "../atftpd.service" "/etc/systemd/system/multi-user.target.wants/" systemctl daemon-reload restart_service atftpd echo "Service file replaced" fi # ********************** dmsd.service ********************** if [ -e "$FILEDIR/dmsd.service" ]; then echo "* Replacing dmsd.service" cp "$FILEDIR/dmsd.service" "/etc/systemd/system/dmsd.service" || perror "Could not replace /etc/systemd/system/dmsd.service" ln -s -f "../dmsd.service" "/etc/systemd/system/multi-user.target.wants/" systemctl daemon-reload restart_service dmsd echo "Service file replaced" fi # ************************** ldadp ************************* if [ -n "$TGZ_LDADP" ]; then [ -e "$TMPDIR/$TGZ_LDADP" ] || perror "$TGZ_LDADP missing from payload" echo "* LDAP/AD Proxy" OLD=$(md5sum "$PATH_LDADP/ldadp") echo "Extracting new binary" tar -x -C "$PATH_LDADP" -f "$TMPDIR/$TGZ_LDADP" || perror "Could not extract $TGZ_LDADP to $PATH_LDADP" rm -rf -- "$PATH_LDADP/logs" mkdir -p "$PATH_LDADP/configs" "$PATH_LDADP/pid" fixperms "$PATH_LDADP/configs" taskmanager:ldadp chmod -R o-rwx "$PATH_LDADP/configs" fixperms "$PATH_LDADP/pid" ldadp:root mkdir -p "/var/log/ldadp" fixperms "/var/log/ldadp" ldadp:root NEW=$(md5sum "$PATH_LDADP/ldadp") if [ "x$OLD" != "x$NEW" ]; then killall ldadp 2>/dev/null && pwarning "LDAP/AD Proxy was killed. Client logins might not work for a couple of minutes (see Server Status in webif)" fi echo "LDADP upgrade complete" fi # ************************** tmate ************************ if ! which tmate > /dev/null 2>&1; then echo "* Installing tmate" echo "deb http://ftp.debian.org/debian jessie-backports main" > /etc/apt/sources.list.d/10-added_repos.list echo "Running apt update..." if ! apt-get update > "$TMPDIR/apt.log" 2>&1; then cat "$TMPDIR/apt.log" pwarning "Adding backborts repo: update failed" fi echo "Installing package..." if ! apt-get install -y tmate > "$TMPDIR/apt.log" 2>&1; then cat "$TMPDIR/apt.log" pwarning "Could not install tmate. Easy remote assistance will not be available." pwarning "Please check whether repo 'jessie-backports' was added and install by hand." fi echo "Writing config..." cat > /root/.tmate.conf <<-JUSTANOTHERDOC set -g tmate-server-host "tmate.ruf.uni-freiburg.de" set -g tmate-server-port 2222 set -g tmate-server-rsa-fingerprint "d7:d7:06:d0:b6:0d:75:a1:ad:ec:69:18:b3:a3:c0:4a" set -g tmate-server-ecdsa-fingerprint "4f:c9:81:f1:1a:20:7d:6f:97:12:f2:a9:0f:f4:c5:6c" set -g tmate-identity "" JUSTANOTHERDOC if which tmate > /dev/null 2>&1; then echo "tmate installation complete!" fi fi # ************************ sudo config ********************* if [ -s "$FILEDIR/tm-sudo-config" ]; then cp -f "$FILEDIR/tm-sudo-config" "/etc/sudoers.d/taskmanager" || pwarning "Could not update sudo conf for taskmanager" chmod 0440 "/etc/sudoers.d/taskmanager" fi echo -n "Finishing." for i in 1 1 1 1 2 2 3 4 END; do CB=$(sudo -u www-data -n php /srv/openslx/www/slx-admin/api.php cb) [ "x$CB" != "xTrue" ] && break [ "$i" = "END" ] && break echo -n "." sleep $i done count=0 [ -n "$IPXE_PID" ] && while kill -0 "$IPXE_PID" 2>/dev/null; do echo -n "." sleep 2 count=$(( count + 1 )) [ "$count" -gt 5 ] && break done echo ". done!" echo "" echo "Update complete. It is recommended to reboot the server." echo "" exit 0 # File end