summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Harpin <development@landsofshadow.co.uk>2015-01-24 15:01:33 +0000
committerAlex Harpin <development@landsofshadow.co.uk>2015-02-24 21:50:36 +0000
commit5cf3930a0d7155fd7a91ca68eb56d1fa40f093b7 (patch)
treebb81661aa5fe113e3f623dcd69c467d894443d8b
parente7268a72e4589afc732f1927317b7108727d4f60 (diff)
downloadvyatta-op-5cf3930a0d7155fd7a91ca68eb56d1fa40f093b7.tar.gz
vyatta-op-5cf3930a0d7155fd7a91ca68eb56d1fa40f093b7.zip
vyatta-op: update the system poweroff cli command to be script based
Update the system poweroff command to use the vyatta-poweroff.pl script rather than simply uisng the shutdown command. This allows other actions to be taken on shutdown, including correctly disconnecting SSH clients rather than having them resorting to timing out (Bug #298) Bug #460 http://bugzilla.vyos.net/show_bug.cgi?id=460
-rw-r--r--Makefile.am1
-rwxr-xr-xscripts/vyatta-poweroff.pl189
-rw-r--r--templates/poweroff/at/node.tag/node.def7
-rw-r--r--templates/poweroff/cancel/node.def2
-rw-r--r--templates/poweroff/node.def9
-rw-r--r--templates/poweroff/now/node.def5
6 files changed, 196 insertions, 17 deletions
diff --git a/Makefile.am b/Makefile.am
index d32cc56..410c419 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -60,6 +60,7 @@ sbin_SCRIPTS += scripts/vyatta-regen-unpriv-commands.sh
bin_sudo_users_SCRIPTS = scripts/vyatta-identify-interface.pl
bin_sudo_users_SCRIPTS += scripts/vyatta-delete-log-file.sh
bin_sudo_users_SCRIPTS += scripts/vyatta-reboot.pl
+bin_sudo_users_SCRIPTS += scripts/vyatta-poweroff.pl
bin_sudo_users_SCRIPTS += scripts/vyatta-op-dns-forwarding.pl
bin_sudo_users_SCRIPTS += scripts/vyatta-op-dynamic-dns.pl
bin_sudo_users_SCRIPTS += scripts/vyatta-clear-conntrack
diff --git a/scripts/vyatta-poweroff.pl b/scripts/vyatta-poweroff.pl
new file mode 100755
index 0000000..9103900
--- /dev/null
+++ b/scripts/vyatta-poweroff.pl
@@ -0,0 +1,189 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-poweroff.pl
+#
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Based on the original vyatta-reboot script by Stig Thormodsrud
+#
+# Author: Alex Harpin
+# Date: Jan 2015
+# Description: Script to shutdown or schedule a shutdown
+#
+# **** End License ****
+#
+
+use lib "/opt/vyatta/share/perl5/";
+use Getopt::Long;
+use POSIX;
+use IO::Prompt;
+use Sys::Syslog qw(:standard :macros);
+
+use strict;
+use warnings;
+
+my $poweroff_job_file = '/var/run/poweroff.job';
+
+sub parse_at_output {
+ my @lines = @_;
+
+ foreach my $line (@lines) {
+ if ($line =~ /error/) {
+ return (1, '', '');
+ } elsif ($line =~ /job (\d+) (.*)$/) {
+ return (0, $1, $2);
+ }
+ }
+ return (1, '', '');
+}
+
+sub is_poweroff_pending {
+ if ( ! -f $poweroff_job_file) {
+ return (0, '');
+ }
+ my $job = `cat $poweroff_job_file`;
+ chomp $job;
+ my $line = `atq $job`;
+ if ($line =~ /\d+\s+(.*)\sa root$/) {
+ return (1, $1);
+ } else {
+ return (0, '');
+ }
+}
+
+sub do_poweroff {
+ my $login = shift;
+
+ syslog("warning", "Poweroff now requested by $login");
+ if (!system("sudo /sbin/shutdown -h now")) {
+ exec("sudo /usr/bin/killall sshd");
+ }
+}
+
+sub cancel_poweroff {
+ my ($login, $time) = @_;
+
+ my $job = `cat $poweroff_job_file`;
+ chomp $job;
+ system("atrm $job");
+ system("rm $poweroff_job_file");
+ syslog("warning", "Poweroff scheduled for [$time] - CANCELED by $login");
+}
+
+my ($action, $at_time, $now);
+GetOptions("action=s" => \$action,
+ "at_time=s" => \$at_time,
+ "now!" => \$now,
+);
+
+if (! defined $action) {
+ die "no action specified";
+}
+
+openlog($0, "", LOG_USER);
+my $login = getlogin() || getpwuid($<) || "unknown";
+
+if ($action eq "poweroff") {
+
+ my ($rc, $time) = is_poweroff_pending();
+ if ($rc) {
+ if (defined $now) {
+ cancel_poweroff($login, $time);
+ do_poweroff($login);
+ } else {
+ print "Poweroff already scheduled for [$time]\n";
+ exit 1;
+ }
+ }
+
+ if (defined $now) {
+ do_poweroff($login);
+ } else {
+ if (prompt("Proceed with poweroff? (Yes/No) [No] ", -ynd=>"n")) {
+ do_poweroff($login);
+ } else {
+ print "Poweroff canceled\n";
+ exit 1;
+ }
+ }
+}
+
+if ($action eq "poweroff_at") {
+ if (! -f '/usr/bin/at') {
+ die "Package [at] not installed";
+ }
+
+ if (! defined $at_time) {
+ die "no at_time specified";
+ }
+
+ my ($rc, $rtime) = is_poweroff_pending();
+ if ($rc) {
+ print "Poweroff already scheduled for [$rtime]\n";
+ exit 1;
+ }
+
+ my @lines = `echo true | at $at_time 2>&1`;
+ my ($err, $job, $time) = parse_at_output(@lines);
+ if ($err) {
+ print "Invalid time format [$at_time]\n";
+ exit 1;
+ }
+ system("atrm $job");
+
+ print "\nPoweroff scheduled for $time\n\n";
+ if (!prompt("Proceed with poweroff schedule? [confirm] ", -y1d=>"y")) {
+ print "Poweroff canceled\n";
+ exit 1;
+ }
+
+ @lines = `echo "sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd" | at $at_time 2>&1`;
+ ($err, $job, $time) = parse_at_output(@lines);
+ if ($err) {
+ print "Error: unable to schedule poweroff\n";
+ exit 1;
+ }
+ system("echo $job > $poweroff_job_file");
+ print "\nPoweroff scheduled for $time\n";
+ syslog("warning", "Poweroff scheduled for [$time] by $login");
+
+ exit 0;
+}
+
+if ($action eq "poweroff_cancel") {
+
+ my ($rc, $time) = is_poweroff_pending();
+ if (! $rc) {
+ print "No poweroff currently scheduled\n";
+ exit 1;
+ }
+ cancel_poweroff($login, $time);
+ print "Poweroff canceled\n";
+ exit 0;
+}
+
+if ($action eq "show_poweroff") {
+
+ my ($rc, $time) = is_poweroff_pending();
+ if ($rc) {
+ print "Poweroff scheduled for [$time]\n";
+ exit 0;
+ } else {
+ print "No poweroff currently scheduled\n";
+ }
+ exit 1;
+}
+
+exit 1;
diff --git a/templates/poweroff/at/node.tag/node.def b/templates/poweroff/at/node.tag/node.def
index ccc3b5b..932e04b 100644
--- a/templates/poweroff/at/node.tag/node.def
+++ b/templates/poweroff/at/node.tag/node.def
@@ -1,6 +1,3 @@
help: Poweroff the system at a future time
-allowed: echo -n '<HH:MM>' '<MMDDYY>' '+MM'
-run: if /opt/vyatta/bin/vyatta-gettime.pl $3 >/tmp/shutdown.at
- then (sudo /sbin/shutdown -h $3 &
- disown %?sudo ) >/dev/null 2>&1
- fi
+allowed: echo -n '<HH:MM>' '<MMDDYY>' '<midnight>' '<noon>'
+run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff_at --at_time "$3"
diff --git a/templates/poweroff/cancel/node.def b/templates/poweroff/cancel/node.def
index c08a72d..c45f17a 100644
--- a/templates/poweroff/cancel/node.def
+++ b/templates/poweroff/cancel/node.def
@@ -1,2 +1,2 @@
help: Cancel a pending poweroff
-run: sudo /sbin/shutdown -c
+run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff_cancel
diff --git a/templates/poweroff/node.def b/templates/poweroff/node.def
index 44b8301..ccb7338 100644
--- a/templates/poweroff/node.def
+++ b/templates/poweroff/node.def
@@ -1,9 +1,2 @@
help: Poweroff the system
-run: if [ "$VYATTA_PROCESS_CLIENT" == "gui2_rest" ]
- then
- sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd
- else
- ${vyatta_bindir}/yesno -n "Proceed with poweroff? (Yes/No) [No] " \
- && sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd
- fi
-
+run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff
diff --git a/templates/poweroff/now/node.def b/templates/poweroff/now/node.def
index d9902cb..6b67572 100644
--- a/templates/poweroff/now/node.def
+++ b/templates/poweroff/now/node.def
@@ -1,3 +1,2 @@
-help: Poweroff the system now [disruptive]
-run: sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd
-
+help: Poweroff the system without confirmation
+run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff --now