Re: [Nut-upsdev] Proposal for technique to stop a timer at any moment

2016-07-11 Thread Roger Price

Here is patch 2 of 2.  Roger

diff -rup -x '*.html' -x '*.8' -x '*.5' nut-2.7.4.orig/docs/man/upsd.txt 
nut-2.7.4.dev/docs/man/upsd.txt
--- nut-2.7.4.orig/docs/man/upsd.txt2015-12-29 09:42:34.0 +0100
+++ nut-2.7.4.dev/docs/man/upsd.txt 2016-07-07 10:08:51.939354892 +0200
@@ -119,6 +119,16 @@ administrative functions like SET and IN
 controlled in linkman:upsd.users[5].  UPS definitions are found in
 linkman:ups.conf[5].

+The file /NUT_DEBUG_LEVEL may be used to manage the debugging
+level.  The file content is a single integer which represents the number of
+"-D" options which may be specified on the command line.  If the file is
+created, modified or removed while the upsd process is running, the effect is
+immediate.  It is not necesssary to restart upsd.  If both a "-D" option and
+the NUT_DEBUG_LEVEL file are present, the higher of the two values applies.
+The principal use of this file is in very specific tracing during a test,
+possibly under the control of a script which creates and removes the
+NUT_DEBUG_LEVEL file.
+
 ENVIRONMENT VARIABLES
 -

@@ -131,6 +141,35 @@ ENVIRONMENT VARIABLES
 *upsd* uses a built-in default, which is often `/var/state/ups`.
 The *STATEPATH* directive in linkman:upsd.conf[5] overrides this variable.

+SIGNALS
+---
+
+upsd accepts the following signals:
+
+*SIGINT* *SIGQUIT* *SIGTERM*::
+The upsd process shuts down.
+
+*SIGHUP*::
+The upsd process reloads it's configuration files.
+
+*SIGUSR1*:: 
+upsd remembers the SIGUSR1 signal on behalf of each UPS.  When a

+client such as linkman:upsmon[8] polls upsd for UPS status chnges, the SIGUSR1
+is reported as a status change.  Once reported, upsd discards it's record of
+the signal.  If a further SIGUSR1 is received while a previous SIGUSR1 is
+waiting to be polled, it is discarded.  Any semantics attached to the signal
+are defined by the user, perhaps in a user script called by
+linkman:upssched[8].
+
+*SIGUSR2*:: 
+upsd remembers the SIGUSR2 signal on behalf of each UPS.  When a

+client such as linkman:upsmon[8] polls upsd for UPS status chnges, the SIGUSR2
+is reported as a status change.  Once reported, upsd discards it's record of
+that signal.  If a further SIGUSR2 is received while a previous SIGUSR2 is
+waiting to be polled, it is queued.  Up to eight SIGUSR2 signals may be
+queued; further SIGUSR2 are discarded.  Any semantics attached to the signal 
are
+defined by the user, perhaps in a user script called by linkman:upssched[8].
+
 SEE ALSO
 

diff -rup -x '*.html' -x '*.8' -x '*.5' nut-2.7.4.orig/docs/man/upsmon.conf.txt 
nut-2.7.4.dev/docs/man/upsmon.conf.txt
--- nut-2.7.4.orig/docs/man/upsmon.conf.txt 2015-12-29 13:08:34.0 
+0100
+++ nut-2.7.4.dev/docs/man/upsmon.conf.txt  2016-07-06 22:27:57.514216079 
+0200
@@ -213,6 +213,10 @@ REPLBATT;; The UPS battery is bad and ne

 NOCOMM;; A UPS is unavailable (can't be contacted for monitoring)

+SIGUSR1;; A UPS has received signal SIGUSR1.  What this means is defined 
locally.
+
+SIGUSR2;; A UPS has received signal SIGUSR2.  What this means is defined 
locally.
+
 *NOTIFYFLAG* 'type' 'flag'[\+'flag'][+'flag']...::

 By default, upsmon sends walls global messages to all logged in users)
diff -rup -x '*.html' -x '*.8' -x '*.5' nut-2.7.4.orig/docs/man/upsmon.txt 
nut-2.7.4.dev/docs/man/upsmon.txt
--- nut-2.7.4.orig/docs/man/upsmon.txt  2015-12-29 13:08:34.0 +0100
+++ nut-2.7.4.dev/docs/man/upsmon.txt   2016-07-06 22:28:45.882438409 +0200
@@ -145,6 +145,12 @@ The UPS needs to have its battery replac
 *NOCOMM*::
 The UPS can't be contacted for monitoring.

+*SIGUSR1*::
+The UPS has received a SIGUSR1 signal.  What this means is defined locally.
+
+*SIGUSR2*::
+The UPS has received a SIGUSR2 signal.  What this means is defined locally.
+
 NOTIFY COMMAND
 --

diff -rup -x '*.html' -x '*.8' -x '*.5' 
nut-2.7.4.orig/docs/man/upssched.conf.txt 
nut-2.7.4.dev/docs/man/upssched.conf.txt
--- nut-2.7.4.orig/docs/man/upssched.conf.txt   2015-12-29 09:42:34.0 
+0100
+++ nut-2.7.4.dev/docs/man/upssched.conf.txt2016-07-07 10:28:08.290375907 
+0200
@@ -83,6 +83,15 @@ If a specific UPS (+myups@localhost+) co
 stop the timer before it triggers

AT COMMOK myups@localhost CANCEL-TIMER upsgone
++
+If any UPS received a SIGUSR1 signal, remove the current timer(s) 
+before they trigger

+
+AT SIGUSR1 * CANCEL-TIMER first-warning-timer
+AT SIGUSR1 * CANCEL-TIMER last-warning-timer
+AT SIGUSR1 * CANCEL-TIMER shutdown-timer
++
+It is not an error to cancel a timer which is not running.

 *EXECUTE* 'command';;
 Immediately pass 'command' as an argument to CMDSCRIPT.
diff -rup -x '*.html' -x '*.8' -x '*.5' nut-2.7.4.orig/docs/net-protocol.txt 
nut-2.7.4.dev/docs/net-protocol.txt
--- nut-2.7.4.orig/docs/net-protocol.txt2016-03-08 16:48:26.0 
+0100
+++ nut-2.7.4.dev/docs/net-protocol.txt 2016-06-19 16:32:53.0 +0200
@@ -44,6 +44,7 @@ NUT network 

Re: [Nut-upsdev] Proposal for technique to stop a timer at any moment

2016-07-11 Thread Roger Price

Here is patch 1 of 2.  Roger

diff -rup nut-2.7.4.orig/clients/upsmon.c nut-2.7.4.dev/clients/upsmon.c
--- nut-2.7.4.orig/clients/upsmon.c 2015-12-29 13:08:34.0 +0100
+++ nut-2.7.4.dev/clients/upsmon.c  2016-07-01 09:46:21.567766415 +0200
@@ -525,6 +525,18 @@ static int get_var(utype_t *ups, const c
numq = 2;
}

+   /* Subcommands for polling SIGUSR1, SIGUSR2  RP */
+   if (strcmp(var, "SIGUSR1") == 0) {
+   query[0] = "SIGUSR1";
+   query[1] = ups->upsname;
+   numq = 2;
+   }
+   if (strcmp(var, "SIGUSR2") == 0) {
+   query[0] = "SIGUSR2";
+   query[1] = ups->upsname;
+   numq = 2;
+   }
+
if (!strcmp(var, "status")) {
query[0] = "VAR";
query[1] = ups->upsname;
@@ -1518,7 +1530,25 @@ static void pollups(utype_t *ups)
if (get_var(ups, "status", status, sizeof(status)) == 0) {
clear_alarm();
parse_status(ups, status);
-   return;
+   /* All is well, continue to poll SIGUSR1 RP */
+  set_alarm();
+   if (get_var(ups, "SIGUSR1", status, sizeof(status)) == 0) {
+   clear_alarm();
+   if ( ! (strcmp(status,"0") == 0)) {  /* See K p.53 */
+   /* We have a SIGUSR1 */
+do_notify(ups, NOTIFY_SIGUSR1);
+   }
+   /* All is well, continue to poll SIGUSR2 RP */
+   set_alarm();
+   if (get_var(ups, "SIGUSR2", status, sizeof(status)) == 
0) {
+   clear_alarm();
+   if ( ! (strcmp(status,"0") == 0)) {
+   /* We have a SIGUSR2 */
+   do_notify(ups, NOTIFY_SIGUSR2);
+   }
+   }
+   return;
+   }
}

/* fallthrough: no communications */
diff -rup nut-2.7.4.orig/clients/upsmon.h nut-2.7.4.dev/clients/upsmon.h
--- nut-2.7.4.orig/clients/upsmon.h 2015-12-29 13:08:34.0 +0100
+++ nut-2.7.4.dev/clients/upsmon.h  2016-06-20 11:24:20.494863128 +0200
@@ -68,13 +68,15 @@ typedef struct {
 #define NOTIFY_ONLINE  0   /* UPS went on-line */
 #define NOTIFY_ONBATT  1   /* UPS went on battery  */
 #define NOTIFY_LOWBATT 2   /* UPS went to low battery  */
-#define NOTIFY_FSD 3   /* Master upsmon set FSD flag   */
+#define NOTIFY_FSD 3   /* Master upsmon set FSD flag   */
 #define NOTIFY_COMMOK  4   /* Communication established*/
 #define NOTIFY_COMMBAD 5   /* Communication lost   */
 #define NOTIFY_SHUTDOWN6   /* System shutdown in progress  
*/
 #define NOTIFY_REPLBATT7   /* UPS battery needs to be replaced 
*/
 #define NOTIFY_NOCOMM  8   /* UPS hasn't been contacted in awhile  */
 #define NOTIFY_NOPARENT9   /* privileged parent process died   
*/
+#define NOTIFY_SIGUSR1 10  /* Server received SIGUSR1 RP */
+#define NOTIFY_SIGUSR2 11  /* Server received SIGUSR2 RP */

 /* notify flag values */

@@ -97,13 +99,15 @@ struct {
{ NOTIFY_ONLINE,   "ONLINE",   NULL, "UPS %s on line power", 
NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_ONBATT,   "ONBATT",   NULL, "UPS %s on battery", NOTIFY_SYSLOG 
| NOTIFY_WALL },
{ NOTIFY_LOWBATT,  "LOWBATT",  NULL, "UPS %s battery is low", 
NOTIFY_SYSLOG | NOTIFY_WALL },
-   { NOTIFY_FSD,  "FSD",  NULL, "UPS %s: forced shutdown in 
progress", NOTIFY_SYSLOG | NOTIFY_WALL },
+   { NOTIFY_FSD,   "FSD",  NULL, "UPS %s: forced shutdown in 
progress", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_COMMOK,   "COMMOK",   NULL, "Communications with UPS %s 
established", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_COMMBAD,  "COMMBAD",  NULL, "Communications with UPS %s lost", 
NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_SHUTDOWN, "SHUTDOWN", NULL, "Auto logout and shutdown 
proceeding", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_REPLBATT, "REPLBATT", NULL, "UPS %s battery needs to be 
replaced", NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_NOCOMM,   "NOCOMM",   NULL, "UPS %s is unavailable", 
NOTIFY_SYSLOG | NOTIFY_WALL },
{ NOTIFY_NOPARENT, "NOPARENT", NULL, "upsmon parent process died - shutdown 
impossible", NOTIFY_SYSLOG | NOTIFY_WALL },
+   { NOTIFY_SIGUSR1,  "SIGUSR1",  NULL, "UPS % received SIGUSR1", 
NOTIFY_SYSLOG },  /* No default wall for SIGUSR1 RP */
+   { NOTIFY_SIGUSR2,  "SIGUSR2",  NULL, "UPS % received SIGUSR2", 
NOTIFY_SYSLOG },  /* No default wall for SIGUSR2 RP */
{ 0, NULL, NULL, NULL, 0 }
 };

diff -rup nut-2.7.4.orig/clients/upssched.c nut-2.7.4.dev/clients/upssched.c
--- 

[Nut-upsdev] Proposal for technique to stop a timer at any moment

2016-07-01 Thread Roger Price
Dear list, I would like to propose a set of patches which make it possible 
for a upssched-cmd script to stop a timer at an arbitrary moment. If you 
find this of interest, I will submit a set of patches to 2.7.4.


Roger


Introduction


The comments at the top of upssched.c say << * timers can be cancelled at any 
time before they trigger >>. It would be very useful if this were true, but 
unfortunately as Charles Lepple says in 
https://lists.alioth.debian.org/pipermail/nut-upsuser/2016-June/010177.html << 
...timers are internal to upssched, and the only way to cancel them is through 
an event listed in the configuration file. >>


A general technique for stopping timers would be very useful for those who rely 
on the script upssched-cmd to provide their system shutdown logic.


Proposal


I would like to propose a set of patches which make it possible to stop a timer 
at an arbitrary moment. The technique is very general in nature: it consists of 
sending signals USR1 and USR2 to the UPS's managed by upsd. Process upsd 
remembers the signals on behalf of the UPS's and passes them to upsmon when 
polled.  Signals USR1 and USR2 extend the set of notify types known by upsmon. 
The signal events may lead to notifications and calls of upssched.  In 
upssched.conf the AT declarations are extended to include USR1 and USR2 events, 
thus allowing declarations such as


 AT SIGUSR1 * CANCEL-TIMER shutdown-timer

Such a declaration is activated in upssched-cmd with a Bash command such 
as "killall -SIGUSR1 upsd" .


Patches
---

My patches are generated using command

 diff -rup ./nut-2.7.4 ./nut-2.7.4.dev

where nut-2.7.4 is the directory created when unzipping nut-2.7.4.tar.gz .

Documentation
-

I propose submitting the documentation changes as plain text editorial 
comments.


The NUT User Manual Chapter 7.2. "The advanced approach, using upssched" 
http://networkupstools.org/docs/user-manual.chunked/ar01s07.html#_the_advanced_approach_using_upssched 
is the subject of issue 293 "Improve upssched example in documentation". 
I propose an example showing how to monitor an unreliable UPS.

https://github.com/networkupstools/nut/issues/293

Debugging
-

I find it convenient to be able to turn on/up/down/off the debugging level 
without touching the upsd process.  I do this by setting the required debugging 
depth in optional file /NUT_DEBUG_LEVEL .  I include the required 
patch to common.c - perhaps this technique will be useful to others.


Testing
---

The proposed patches to 2.7.4 have been tested on openSUSE 13.1 Evergreen 
long term support with an Eaton ECO 1600 and a tired MGE Ellipse 1500.


Programming style
-

10 years of my career were spent programming in assembler on large process 
control systems.  I have also programmed in many high level languages such 
as APL, Algol, ML, Prolog, Erlang,.. but never in C.  However I have a 
copy of K, and Stevens' "Programming in the UNIX Environment", and I 
have tried as far as possible, and with the help of the NUT emacs style 
function to follow the NUT C style, although the diff program does not 
make this clear.




___
Nut-upsdev mailing list
Nut-upsdev@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev