From 8575291412d87c4344e44079e33d2aeff9e417a3 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 6 Jul 2020 14:20:44 +0200 Subject: [ldap/systemctl] Wrapper script, systemd-ize ldadp handling --- scripts/ldadp-launcher | 126 ++++++++++----------- scripts/systemctl | 59 ++++++++++ .../openslx/taskmanager/tasks/LdadpLauncher.java | 17 ++- .../openslx/taskmanager/tasks/MountVmStore.java | 1 - .../org/openslx/taskmanager/tasks/Systemctl.java | 56 +-------- 5 files changed, 138 insertions(+), 121 deletions(-) create mode 100755 scripts/systemctl diff --git a/scripts/ldadp-launcher b/scripts/ldadp-launcher index 6cd0c3f..f233900 100755 --- a/scripts/ldadp-launcher +++ b/scripts/ldadp-launcher @@ -1,12 +1,33 @@ #!/bin/bash +set -x +exec 2> /tmp/pops + if [ $# -lt 2 ]; then echo "Invalid parameter count: '$#'" >&2 exit 1 fi -BASE="$1" -shift +BASE="/opt/ldadp" +MODE="start" +while [ $# -gt 0 ]; do + var="$1" + shift + case "$var" in + --check) MODE="check" ;; + --start) MODE="start" ;; + --restart) MODE="restart" ;; + --base) + BASE="$1" + shift + ;; + --) break ;; + --*) + echo "Unknown option '$var'" >&2 + exit 1 + ;; + esac +done if [ -z "$BASE" ] || [ ! -r "$BASE" ] || [ ! -d "$BASE" ]; then echo "Basedir invalid: '$BASE'" >&2 @@ -14,8 +35,6 @@ if [ -z "$BASE" ] || [ ! -r "$BASE" ] || [ ! -d "$BASE" ]; then fi cd "$BASE" -[ "x$1" == "x--" ] && shift - # At this point $@ should only be ldadp instance ids inArray () { @@ -26,71 +45,52 @@ inArray () { return 1 } -isInstance () { - if [ $# -ne 1 ]; then - echo "isInstance needs 1 param, got $#" >&2 - return 0 - fi - [ -L "/proc/$1/exe" ] && [ -r "/proc/$1/exe" ] && [[ "$(readlink -f "/proc/$1/exe")" == *ldadp ]] && return 0 - return 1 -} +RETVAL=0 -launch () { - local CONFIG="${BASE}/configs/${1}.cfg" - if [ ! -r "$CONFIG" ]; then - echo "Told to start ldadp for module '${1}', but no config file found!" >&2 - return 1 - fi - echo "Launching #$1" - local LOGFILE="/var/log/ldadp/${1}.log" - if [ ! -w "/var/log/ldadp" ] || [ -e "$LOGFILE" -a ! -w "$LOGFILE" ]; then - LOGFILE="/dev/null" - elif [ -s "$LOGFILE" ]; then - TFILE=$(mktemp) - tail -n 50 "$LOGFILE" > "$TFILE" - echo "----- Starting $(date) -------" >> "$TFILE" - cat "$TFILE" > "$LOGFILE" # Use cat to preserve permissions of $LOGFILE - rm -f -- "$TFILE" - fi - "${BASE}/ldadp" -n "$CONFIG" >> "$LOGFILE" 2>&1 & - local P=$! - sleep 1 - if ! kill -0 "$P" 2>/dev/null; then - echo "...FAILED to launch #$1" >&2 - return 1 - fi - echo -n "$P" > "${BASE}/pid/${1}" - return 0 -} +if [ "$MODE" = "check" ]; then + # Dump list of known instances + systemctl list-units --state=loaded --no-legend | awk '{if ($1 ~ /^ldadp@.*\.service$/) print $1 " " $4}' + exit "$RETVAL" +elif [ "$MODE" = "restart" ]; then + # Restart only the given ID(s) + for id in "$@"; do + if ! [ -r "${BASE}/configs/${id}.cfg" ]; then + echo "Told to start ldadp for module '${id}', but no config file found; skipping." >&2 + continue + fi + name="ldadp@${id}.service" + wanted+=( "${name}" ) + echo "Restarting $name" + systemctl restart "$name" || RETVAL=1 + done + exit "$RETVAL" +fi -RETVAL=0 +# Regular Start/Stop logic -for FILE in $(find "$BASE/pid" -type f -regextype posix-extended -regex "(^|.*/)[0-9]+$"); do - ID=$(basename $FILE) - PID=$(<$FILE) - if ! [[ "$PID" =~ ^[0-9]+$ ]]; then - echo "Invalid PID file: '$FILE'" - unlink "$FILE" - fi - inArray $ID "$@" && isInstance $PID && continue # Should be running, is running, nothing to do - # - unlink "$FILE" - if isInstance $PID; then - # Is running, should not, kill - kill $PID - sleep 1 - isInstance $PID && kill -9 $PID +# Get loaded instances +declare -a known wanted +known=( $(systemctl list-units --state=loaded --no-legend | awk '{if ($1 ~ /^ldadp@.*\.service$/) print $1}') ) + +# Prepare names of wanted services and launch them +for id in "$@"; do + if ! [ -r "${BASE}/configs/${id}.cfg" ]; then + echo "Told to start ldadp for module '${id}', but no config file found; skipping." >&2 + continue fi + name="ldadp@${id}.service" + wanted+=( "${name}" ) + echo "Starting $name" + systemctl enable "$name" + systemctl start "$name" || RETVAL=1 done -while [ $# -gt 0 ]; do - ID=$1 - shift - FILE="${BASE}/pid/${ID}" - [ -r "$FILE" ] && isInstance $(<$FILE) && continue - launch $ID - RET=$? - [ "$RET" != "0" ] && RETVAL=1 +# Now stop the ones we don't need anymore +for name in "${known[@]}"; do + inArray "$name" "${wanted[@]}" && continue + echo "Stopping $name" + systemctl disable "$name" + systemctl stop "$name" done exit "$RETVAL" diff --git a/scripts/systemctl b/scripts/systemctl new file mode 100755 index 0000000..e3afe73 --- /dev/null +++ b/scripts/systemctl @@ -0,0 +1,59 @@ +#!/bin/bash + +op="$1" +shift + +if [ $# -eq 0 ]; then + echo "No service name given" >&2 + exit 1 +fi + +declare -A services + +services["dmsd"]="start stop restart" +services["lighttpd"]="restart" +services["taskmanager"]="restart" +services["dnbd3-server"]="start stop restart" +services["dnbd3-master-proxy"]="start stop restart" +services["tftpd-hpa"]="start stop restart" +services["ldadp@"]="start stop restart" + +one_ok= +one_fail= +cmpop="${op##*-}" +for service in "$@"; do + ok= + [[ "$op" =~ ^(is-active|status|cat)$ ]] && ok=1 + str="${service%.service}" + noa="${str%%@*}" + [[ "$noa" != "$str" ]] && str="${noa}@" + if [ -z "$ok" ] && [ -n "${services["$str"]}" ]; then + for verb in ${services["$str"]}; do + if [[ "$cmpop" == "$verb" ]]; then + ok=1 + break + fi + done + fi + if [ -n "$ok" ]; then + if systemctl "$op" "$service"; then + one_ok=1 + else + one_fail=1 + [[ "$op" != "status" ]] && systemctl status "$service" + fi + else + echo "Operation '$op' not allowed on '$service'" >&2 + one_fail=1 + fi +done + + +if [ -n "$one_fail" ] && [ -n "$one_ok" ]; then + exit 1 +elif [ -n "$one_fail" ]; then + exit 2 +fi + +exit 0 + diff --git a/src/main/java/org/openslx/taskmanager/tasks/LdadpLauncher.java b/src/main/java/org/openslx/taskmanager/tasks/LdadpLauncher.java index cb648b9..d1550c5 100644 --- a/src/main/java/org/openslx/taskmanager/tasks/LdadpLauncher.java +++ b/src/main/java/org/openslx/taskmanager/tasks/LdadpLauncher.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicReference; import org.openslx.satserver.util.Constants; +import org.openslx.satserver.util.Util; import org.openslx.taskmanager.api.SystemCommandTask; import com.google.gson.annotations.Expose; @@ -14,6 +15,9 @@ public class LdadpLauncher extends SystemCommandTask { @Expose private int[] ids = null; + + @Expose + private String command; private Output status = new Output(); @@ -27,13 +31,16 @@ public class LdadpLauncher extends SystemCommandTask status.addMessage( "No ids passed to task." ); return false; } + if ( Util.isEmpty( command ) ) { + command = "start"; + } return true; } @Override protected String[] initCommandLine() { - if ( !isRunning.compareAndSet( null, this ) ) { + if ( !command.equals( "check" ) && !isRunning.compareAndSet( null, this ) ) { LdadpLauncher other = isRunning.get(); if ( other != null && !Arrays.equals( this.ids, other.ids ) ) { status.addMessage( "Another operation is already in progress." ); @@ -44,14 +51,14 @@ public class LdadpLauncher extends SystemCommandTask args.addAll( Arrays.asList( new String[] { "/usr/bin/sudo", "-n", - "-u", "ldadp", Constants.BASEDIR + "/scripts/ldadp-launcher", - "/opt/ldadp", + "-u", "root", Constants.BASEDIR + "/scripts/ldadp-launcher", + "--" + command, "--" } ) ); for ( int i = 0; i < ids.length; ++i ) { args.add( Integer.toString( this.ids[i] ) ); } - this.timeoutSeconds = 8; + this.timeoutSeconds = 16; return args.toArray( new String[ args.size() ] ); } @@ -65,7 +72,7 @@ public class LdadpLauncher extends SystemCommandTask @Override protected void processStdOut( String line ) { - //status.addMessage( line ); + status.addMessage( line ); } @Override diff --git a/src/main/java/org/openslx/taskmanager/tasks/MountVmStore.java b/src/main/java/org/openslx/taskmanager/tasks/MountVmStore.java index e0a998a..2a46a10 100644 --- a/src/main/java/org/openslx/taskmanager/tasks/MountVmStore.java +++ b/src/main/java/org/openslx/taskmanager/tasks/MountVmStore.java @@ -7,7 +7,6 @@ import org.openslx.satserver.util.Constants; import org.openslx.satserver.util.Util; import org.openslx.taskmanager.api.SystemCommandTask; -import com.btr.proxy.util.Logger; import com.google.gson.annotations.Expose; public class MountVmStore extends SystemCommandTask diff --git a/src/main/java/org/openslx/taskmanager/tasks/Systemctl.java b/src/main/java/org/openslx/taskmanager/tasks/Systemctl.java index 7b09a39..bce52c9 100644 --- a/src/main/java/org/openslx/taskmanager/tasks/Systemctl.java +++ b/src/main/java/org/openslx/taskmanager/tasks/Systemctl.java @@ -1,8 +1,5 @@ package org.openslx.taskmanager.tasks; -import java.util.ArrayList; -import java.util.List; - import org.openslx.taskmanager.api.SystemCommandTask; import com.google.gson.annotations.Expose; @@ -23,56 +20,11 @@ public class Systemctl extends SystemCommandTask @Override protected String[] initCommandLine() { - boolean allowAll = false; - boolean asRoot = true; - // Check if operation is allowed - switch ( operation ) { - case "start": - case "stop": - case "enable": - case "disable": - case "restart": - case "status": - break; - case "show": - case "is-active": - allowAll = true; - asRoot = false; - break; - default: - status.addMsg( "Unknown operation: " + operation ); - return null; - } - if ( !allowAll ) { - // Check if service is allowed - switch ( service ) { - case "dmsd": - case "dnbd3-server": - break; - case "taskmanager": - case "lighttpd": - if ( !operation.equals( "restart" ) ) { - status.addMsg( "Error: Service " + service + " can only be restarted." ); - return null; - } - break; - default: - status.addMsg( "Unknown service: " + operation ); - return null; - } - } - List params = new ArrayList<>(); - if ( asRoot ) { - params.add( "/usr/bin/sudo" ); - params.add( "-n" ); - params.add( "-u" ); - params.add( "root" ); - } - params.add( "/bin/systemctl" ); - params.add( operation ); - params.add( service ); this.timeoutSeconds = 15; - return params.toArray( new String[ params.size() ] ); + return new String[] { "/usr/bin/sudo", + "-n", "-u", "root", + "/opt/taskmanager/scripts/systemctl", + operation, service }; } private boolean errorIfNull( String check, String message ) -- cgit v1.2.3-55-g7522