]> rtime.felk.cvut.cz Git - novaboot.git/blobdiff - server/novaboot-shell
server: Refactor delayed power-off logic
[novaboot.git] / server / novaboot-shell
index c35ff7e8b4a4a9df726163294db60977c557daec..5e8621adf3b37689b4cdd375c188fa304f7e9134 100755 (executable)
@@ -15,6 +15,7 @@ Target commands:
 - on
 - off
 - rsync ...
+- get-config
 
 Management commands:
 - help
@@ -55,7 +56,7 @@ exec_shell() {
     if ! tty > /dev/null; then
        echo "novaboot-shell: Consider starting the shell with 'ssh -t'"
     fi
-    exec /bin/bash || exec /bin/sh
+    exec /usr/bin/env bash || exec /bin/sh
 }
 
 lock_queue() {
@@ -77,9 +78,7 @@ print_queue() {
 
 locked() {
     print_queue
-    no_fork=
-    #flock -h 2>&1 | grep -q -e "--no-fork" && no_fork=--no-fork
-    exec flock $no_fork "$RUN_DIR" "$@"
+    exec flock --no-fork "$RUN_DIR" "$@"
 }
 
 unlocked() {
@@ -90,18 +89,57 @@ read_config() {
     . "${NOVABOOT_SHELL_CONFIG:-$HOME/.novaboot-shell}"
 }
 
+power() {
+    local cmd
+    case "$1" in
+       "on")  cmd="${on_cmd:?}";;
+       "off") cmd="${off_cmd:?}";;
+       *) die "Unexpected power parameter";;
+    esac
+
+    if [ "$PPID" -ne 1 ] && systemctl --user is-enabled --quiet novaboot-delayed-power-off.service; then
+        case "$1" in
+            "on") systemctl --user start novaboot-delayed-power-off.service;;
+            "off") sudo novaboot-power off;;
+        esac
+    else
+       eval "$cmd"
+    fi
+}
+
+run_console() {
+    trap "rm -f $RUN_DIR/ppid" EXIT
+    echo $NOVABOOT_PPID > $RUN_DIR/ppid
+    echo 'novaboot-shell: Connected'
+    # TODO: $reset_begin_cmd
+    [ -n "${on_cmd}" ] && power on
+    eval "$1"
+}
+
+# Run novaboot with the same configuration as specified in
+# ~/.novaboot-shell, but allow the caller to extend of override them
+# via parameters of this function.
+run_novaboot() {
+    nbscript=$1
+    shift
+    OLD_IFS=$IFS
+    # Split $target_config below by newlines, not by words
+    IFS="
+"
+    novaboot "$nbscript" $target_config --server="$HOME/tftproot" --reset-cmd="${reset_cmd:?}" --remote-cmd="${console_cmd:?}" "$@"
+    IFS=$OLD_IFS
+}
+
 # run_subcommand should be called only after permission checks and/or locking
 run_subcommand() {
     read_config
     case "$*" in
+       "default")
+           run_console "${default_cmd:-${console_cmd:?}}";;
        "console")
-           trap "rm -f $RUN_DIR/ppid" EXIT
-           echo $NOVABOOT_PPID > $RUN_DIR/ppid
-           echo 'novaboot-shell: Connected'
-           # TODO: $reset_begin_cmd
-           eval exec "${console_cmd:?}";;
+           run_console "${console_cmd:?}";;
        "reset")
-           eval exec "${reset_cmd:?}";;
+           eval "${reset_cmd:?}";;
        "rsync --server "*" . .")
            if ! [ $# -eq 5 -o \( $# -eq 6 -a "$4" = '--log-format=X' \) ]; then
                die "Unexpected rsync invocation: $*"
@@ -110,9 +148,13 @@ run_subcommand() {
            cd "$HOME/tftproot"
            exec "$@";;
        "on")
-           eval exec "${on_cmd:?}";;
+           power on
+           exit;;
        "off")
-           eval exec "${off_cmd:?}";;
+           power off
+           exit;;
+       *)
+           die "Unknown command: $*";;
     esac
 }
 
@@ -126,7 +168,7 @@ main() {
     NB_ADMIN=
     if [ "$1" = "user" ]; then
        # Get user name encoded in ~/.ssh/authorized_keys
-       NB_USER="$2";
+       export NB_USER="$2";
        [ "$3" = "admin" ] && NB_ADMIN=1
        set -- $SSH_ORIGINAL_COMMAND
     fi
@@ -146,7 +188,8 @@ main() {
 
     case "$1" in
        # Commands allowed at any time
-       "console"|"") locked $0 console;;
+       "") locked $0 default;;
+       "console") locked $0 console;;
        "get-config") read_config && echo -n "${target_config}"; exit;;
        "add-key") shift; add_key "$@"; exit;;
        "shell") exec_shell; exit;;
@@ -167,167 +210,15 @@ main() {
     esac
 }
 
-RUN_DIR="$HOME"
+if [ -d "$HOME" ]; then
+    RUN_DIR="$HOME"
+else
+    RUN_DIR="/tmp/novaboot-shell@$USER"
+    mkdir -p "$RUN_DIR"
+fi
 
-if [ -z "$NOVABOOT_ID" ]; then
+if [ -z "$NOVABOOT_ID" ] && [ "$PPID" -ne 1 ]; then
     main "$@"
 else
     run_subcommand "$@"
 fi
-exit
-
-: <<EOF
-=encoding utf8
-
-=head1 NAME
-
-novaboot-shell - provides novaboot with unified SSH-based interface for controlling target hardware
-
-=head1 SYNOPSIS
-
-B<novaboot-shell> -c "[command [arguments...]]"
-
-B<novaboot-shell> [command [arguments...]]
-
-B<ssh target@server> [command [arguments...]]
-
-=head1 DESCRIPTION
-
-B<novaboot-shell> provides L<novaboot(1)> with a unified SSH-based
-interface for controlling the target hardware. This simplifies
-client-side configuration, because clients typically need only the
-I<-ssh=...> option. B<novaboot-shell> is typically configured as a
-login shell of special user accounts associated with target hardware.
-It ensures that users can perform only a limited set of actions (see
-L</COMMANDS> below) with the target and have no shell access on the
-server.
-
-=head1 COMMANDS
-
-=over 8
-
-=item console
-
-Connect to target console (usually serial line). When somebody is
-connected to the console, other users are blocked from controlling the
-target. Blocked users see a message indicating who blocks them.
-
-The user connected to the console is able to invoke other commands
-such as L</reset>, but only when the command is invoked via the same
-SSH connection. This can be accomplished by using SSH connection
-sharing, which is what L<novaboot(1)> uses (see I<-M> and I<-S> in
-L<ssh(1)>).
-
-This is the default command when no command is specified on command
-line.
-
-=item reset
-
-Reset the target hardware.
-
-=item on
-
-Power on the target hardware.
-
-=item off
-
-Power off the target hardware.
-
-=item rsync [...]
-
-This command is not meant to be invoked directly by the user. It
-allows using L<rsync(1)> to copy files to the target, perhaps for TFTP
-server. The rsync command must be invoked as: C<rsync ...
-target@server:>, i.e. without specifying destination path. The files
-will be stored into I<$HOME/tftproot>.
-
-=item user <uernamename> [admin]
-
-User command is meant to be used with C<command=> option in SSH's
-L<authorized_keys(5)> file. It allows the shell to display
-human-readable names when printing information about who blocks the
-target. Then, the real command is taken from SSH_ORIGINAL_COMMAND
-environment variable.
-
-When "admin" is specified after the user name, this user is considered
-an administrator and is allowed to run L</add-key> and L</shell>
-commands.
-
-=back
-
-=head2 Administration commands
-
-Only administrators (see L</user>) are allowed to execute these
-commands.
-
-=over 8
-
-=item add-key <username>
-
-Reads the SSH public key from standard input and adds it into in
-F<~/.ssh/authorized_keys>.
-
-Example: C<ssh target@server add-key johndoe < john_rsa.pub>
-
-=item shell
-
-Runs shell on the server. Useful for editing configuration file. It is
-better used with allocated pseudo-terminal.
-
-Example: C<ssh -t target@server shell>
-
-=back
-
-=head1 CONFIGURATION FILE
-
-B<novaboot-shell> reads configuration file from
-F<$HOME/.novaboot-shell>. It should define values for the following
-variables in the SH syntax.
-
-=over 8
-
-=item console_cmd
-
-Command to C<exec> that connects to target's console.
-
-=item reset_cmd
-
-Command to C<exec> that resets the Target.
-
-=item on_cmd
-
-Command to C<exec> that powers the target on.
-
-=item off_cmd
-
-Command to C<exec> that powers the target off.
-
-=item target_config
-
-Novaboot command line options that specify which boot loader is used
-by the target (L<novaboot(1)> rejects other, possibly dangerous, options).
-Each option is on its own line and no quoting, escaping or stripping
-is performed on the values.
-
-Example:
-
-  target_config="\
-  --uboot=(uboot)
-  --uboot-init=setenv serverip 192.168.1.1; setenv ipaddr 192.168.1.10
-  --uboot-addr=kernel=0x8100000
-  --uboot-addr=fdt=0x83000000
-  --uboot-addr=ramdisk=0x83100000
-  "
-
-
-=back
-
-=head1 AUTHORS
-
-Michal Sojka <sojkam1@fel.cvut.cz>
-
-Latest version can be found at
-L<https://github.com/wentasah/novaboot>.
-
-=cut
-EOF