Skip to content

Commit

Permalink
drivers/main.{c,h}, docs: introduce shutdown.default INSTCMD concep…
Browse files Browse the repository at this point in the history
…t and upsdrv_shutdown_default() shared method [networkupstools#2670]

Signed-off-by: Jim Klimov <[email protected]>
  • Loading branch information
jimklimov committed Nov 19, 2024
1 parent 2d9926d commit cc55e5a
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 5 deletions.
4 changes: 3 additions & 1 deletion NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ it is getting set at all in "killpower" vs. other cases, based on new
`handling_upsdrv_shutdown` internal flag.
+
NOTE: during this overhaul, many older drivers got their first ever supported
INSTCMD such as `shutdown.return`, `shutdown.stayoff` or `load.off`. [#2670]
INSTCMD such as `shutdown.return`, `shutdown.stayoff` or `load.off`. Default
logic that was previously the content of `upsdrv_shutdown()` methods was often
relocated into new `shutdown.default` INSTCMD definitions. [#2670]
- common code:
* introduced a `NUT_DEBUG_SYSLOG` environment variable to tweak activation
Expand Down
3 changes: 2 additions & 1 deletion docs/man/ups.conf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ The default value for this parameter is 0.
Optional. Comma-separated list of instant command name(s) to send to
the UPS when you request its shutdown.
+
Default value is built into each driver (where supported).
Default logic is built into each driver (where supported) and can be
referenced here as the `shutdown.default` value.
+
The primary use-case is for devices whose drivers "natively" support
trying several commands, but the built-in order of those calls a
Expand Down
7 changes: 7 additions & 0 deletions docs/nut-names.txt
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,13 @@ Instant commands
| load.on | Turn on the load immediately
| load.off.delay | Turn off the load possibly after a delay
| load.on.delay | Turn on the load possibly after a delay
| shutdown.default | Run default driver-defined (device-specific)
routine, primarily intended for emergency
poweroff performed as part of FSD handling;
often an alias to other `shutdown.*` and/or
`load.off` operations or a chain to try
several of those. See also `sdcommands` in
common driver options.
| shutdown.return | Turn off the load possibly after a delay
and return when power is back
| shutdown.stayoff | Turn off the load possibly after a delay
Expand Down
56 changes: 53 additions & 3 deletions drivers/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,16 +771,20 @@ void addvar(int vartype, const char *name, const char *desc)
* by the device, or STAT_INSTCMD_INVALID if none succeeded.
* If cmdused is not NULL, it is populated by the command
* string which succeeded (or NULL if none), and the caller
* should free() it eventually.
* should free() it eventually. This method also frees any
* non-NULL *cmdused, so it should be pre-initialized to NULL.
*/
int do_loop_shutdown_commands(const char *sdcmds, char **cmdused) {
int cmdret = STAT_INSTCMD_UNKNOWN;
char *buf = NULL, *s = NULL;

upsdebugx(1, "%s(%s)...", __func__, NUT_STRARG(sdcmds));

if (cmdused)
if (cmdused) {
if (*cmdused)
free(*cmdused);
*cmdused = NULL;
}

if (!sdcmds || !*sdcmds) {
upsdebugx(1, "This driver or its configuration did not pass any instant commands to run");
Expand All @@ -798,7 +802,15 @@ int do_loop_shutdown_commands(const char *sdcmds, char **cmdused) {
continue;
if ((cmdret = upsh.instcmd(s, NULL)) == STAT_INSTCMD_HANDLED) {
/* Shutdown successful */
if (cmdused)

/* Note: If we are handling "shutdown.default" here,
* it is anticipated that it calls some other INSTCMD
* as the implementation, and that could set a value
* which we actually want to keep and tell the caller.
* We had freed *cmdused above, so it if is not empty
* here - something during the handling populated it.
*/
if (cmdused && !(*cmdused))
*cmdused = xstrdup(s);
upsdebugx(1, "%s(): command '%s' was handled successfully", __func__, NUT_STRARG(s));
goto done;
Expand Down Expand Up @@ -836,6 +848,44 @@ int loop_shutdown_commands(const char *sdcmds_default, char **cmdused) {
}
}

/* Common and default implementation of upsdrv_shutdown() in most drivers,
* unless they do something that can not be made instcmd("shutdown.default")
*/
int upsdrv_shutdown_default(const char *sdcmds_default, char **cmdused) {
char *sdcmd_used = NULL;
int sdret = loop_shutdown_commands(
sdcmds_default ? sdcmds_default : "shutdown.default",
&sdcmd_used);

if (cmdused) {
if (*cmdused)
free(*cmdused);
*cmdused = NULL;
}

if (sdret == STAT_INSTCMD_HANDLED) {
upslogx(LOG_INFO, "UPS [%s]: shutdown request was successful with '%s'",
NUT_STRARG(upsname), NUT_STRARG(sdcmd_used));

/* Pass it up to caller? */
if (cmdused) {
*cmdused = sdcmd_used;
} else {
if (sdcmd_used)
free(sdcmd_used);
}
} else if (!upsh.instcmd) {
upslogx(LOG_ERR, "UPS [%s]: shutdown not supported", NUT_STRARG(upsname));
} else {
upslogx(LOG_ERR, "UPS [%s]: shutdown request(s) failed", NUT_STRARG(upsname));
}

if (handling_upsdrv_shutdown > 0)
set_exit_flag(sdret == STAT_INSTCMD_HANDLED ? EF_EXIT_SUCCESS : EF_EXIT_FAILURE);

return sdret;
}

/* handle instant commands common for all drivers */
int main_instcmd(const char *cmdname, const char *extra, conn_t *conn) {
char buf[SMALLBUF];
Expand Down
8 changes: 8 additions & 0 deletions drivers/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ int do_loop_shutdown_commands(const char *sdcmds, char **cmdused);
*/
int loop_shutdown_commands(const char *sdcmds_default, char **cmdused);

/*
* Effectively call loop_shutdown_commands("shutdown.default") (which in turn
* probably calls some other INSTCMD, but may be using a more custom logic),
* and report how that went.
* Depending on run-time circumstances, probably set_exit_flag() too.
*/
int upsdrv_shutdown_default(const char *sdcmds_default, char **cmdused);

/* handle instant commands common for all drivers
* (returns STAT_INSTCMD_* state values per enum in upshandler.h)
*/
Expand Down

0 comments on commit cc55e5a

Please sign in to comment.