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-01-24 20:23:12 +0000
commit119a0b0d12dea51d1a5032552dbe8944308276ca (patch)
tree9952bc3cbafb22efd03656c14e95db3dd9d4fd93
parentf4485f4c2beac42a1cdbde35f900440416e1c5ae (diff)
downloadvyatta-op-119a0b0d12dea51d1a5032552dbe8944308276ca.tar.gz
vyatta-op-119a0b0d12dea51d1a5032552dbe8944308276ca.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