Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8dae3b5
drivers/, docs/: introduce failover driver
sebastiankuttnig May 19, 2025
5855e6e
server/netget.c: rewrite upstream prefix for proxying drivers
sebastiankuttnig May 19, 2025
fe08563
NEWS.adoc: introduce failover driver
sebastiankuttnig May 19, 2025
bf3b9e2
drivers/failover.c, NEWS.adoc: fixes for compiler warnings, add PR nu…
sebastiankuttnig May 19, 2025
961fbc2
drivers/failover.c: add shutdown non-handling
sebastiankuttnig May 19, 2025
6b33157
drivers/failover.c: free parse_port_argument() tmp on premature exit …
sebastiankuttnig May 19, 2025
e5f3631
drivers/failover.c: clean dstate after fsdmode 0, remove now freed va…
sebastiankuttnig May 19, 2025
2fac5e1
drivers/failover.c: preserve which port value failed the argument par…
sebastiankuttnig May 19, 2025
f4d8ab7
drivers/failover.c: make defensive freeing consistent throughout the …
sebastiankuttnig May 19, 2025
2c74214
drivers/failover.c: reword shutdown to be more clear
sebastiankuttnig May 22, 2025
1ad9b26
drivers/failover.c: use NUT_STRARG helper for null checks in various …
sebastiankuttnig May 23, 2025
683559c
drivers/failover.c: use enum for priorities
sebastiankuttnig May 23, 2025
fb3d251
drivers/failover.{c,h}: introduce failover.h for defines, typedefs
sebastiankuttnig May 23, 2025
18ac174
drivers/failover.c: do not fatalx on no connectable drivers, keep try…
sebastiankuttnig May 23, 2025
be52d0b
drivers/failover.c: remove redundant _init() calls for status/alarm
sebastiankuttnig May 23, 2025
f3b1541
drivers/failover.c: show truncation content at end of log message
sebastiankuttnig May 23, 2025
53359b7
drivers/failover.c: safeguard ups_promote_primary against NULL or dou…
sebastiankuttnig May 23, 2025
9f78e4c
docs/man/failover.txt: polish documentation and add rationale
sebastiankuttnig May 23, 2025
022342c
drivers/failover.c: remove progname from non fatal log message
sebastiankuttnig May 23, 2025
a6fda90
docs/man/failover.txt: make hyphens consistent
sebastiankuttnig May 23, 2025
22c8465
docs/man/failover.txt: add note to factor in network or lock-picking …
sebastiankuttnig May 23, 2025
44cabf3
docs/man/failover.txt: add limitations
sebastiankuttnig May 23, 2025
b799a9d
Merge branch 'master' into failover
jimklimov May 23, 2025
5321a55
docs/man/failover.txt: add 3rd party tool use case for rationale
sebastiankuttnig May 23, 2025
953d368
drivers/Makefile.am: add failover.h for dists
sebastiankuttnig May 24, 2025
12e7da4
docs/man/failover.txt: fix incompatible characters
sebastiankuttnig May 24, 2025
825edd2
drivers/failover.c: safer string to numeric conversions, improved arg…
sebastiankuttnig May 26, 2025
2c68099
drivers/failover.c: remove magic -1 from str_arg_to_int(), use INT_MI…
sebastiankuttnig May 26, 2025
95ea397
scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: add support for "dr…
jimklimov May 22, 2025
f001318
Merge branch 'failover' of github.com:sebastiankuttnig/nut into failover
sebastiankuttnig May 26, 2025
3625b15
drivers/failover.c: make csv_arg_to_array() more reusable
sebastiankuttnig May 26, 2025
36204e8
scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: report if other dev…
jimklimov May 26, 2025
962bac4
drivers/failover.c: use str_to_int() also in instcmd()
sebastiankuttnig May 26, 2025
505853f
Merge branch 'master' into failover
sebastiankuttnig May 28, 2025
784ce12
drivers/failover.{c,h}, docs/man/failover.txt: use _sockfn() for one-…
sebastiankuttnig May 28, 2025
ff08659
tests/nut-driver-enumerator-test.sh: reflect recent enumerator change…
sebastiankuttnig May 28, 2025
54c604b
NEWS.adoc: mention NDE change to track inter-driver dependency [#2962]
jimklimov May 28, 2025
89a0db0
docs/man/nut-driver-enumerator.txt: update intro, mention driver-on-d…
jimklimov May 28, 2025
ccaac91
drivers/failover.{c,h}: introduce checkruntime argument
sebastiankuttnig May 28, 2025
c498dd3
docs/man/failover.txt, docs/nut.dict: introduce checkruntime argument
sebastiankuttnig May 28, 2025
d8f171c
drivers/failover.c: minor improvements to order and debug levels
sebastiankuttnig May 28, 2025
9a6f56c
drivers/failover.{c,h}: store runtimes in UPS struct
sebastiankuttnig May 28, 2025
0937f25
drivers/failover.c: improve guarding of ups->status against NULL dere…
sebastiankuttnig May 28, 2025
fb3cac7
drivers/failover.{c,h}: make UPS priorities more readable in code
sebastiankuttnig May 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ https://github.com/networkupstools/nut/milestone/9
support for end-to-end tracked instant commands and also variable updating.
[#2962]

- The `nut-driver-enumerator.sh` script (NDE) now internally tracks dependency
of one driver on another one that should be locally running to serve the
"original" data points (`clone`, `clone-outlet`, `dummy-ups`, `failover`).
It should create soft dependencies between respective service instances
to order their start-up sequence. [#2962]

- NUT Monitor GUI:
* Ported Python 3 version to Qt6, now shipped alongside Qt5 for systems
with either or both, maximizing compatibility with old and new setups.
Expand Down
23 changes: 23 additions & 0 deletions docs/man/failover.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ itself. This mode is for setups where immediate shutdown is warranted,
regardless of anything else, and getting `FSD` out to the clients as fast as
just possible.

*checkruntime*='0|1|2|3'::
Optional. Controls how `battery.runtime` values are used to break ties between
non-fully-online UPS devices **at priority 3 or lower**. Has no effect on
initial priority selection or when `strictfiltering` is enabled. Defaults to 1.

- `0`: *Disabled.* No runtime comparison is done. The first candidate with the
best priority is selected according to the order of the port argument.

- `1`: *Compare `battery.runtime`.* The UPS with the higher value is preferred.
If the value is missing or invalid, the UPS cannot win the tie-break.

- `2`: *Compare `battery.runtime.low`.* The UPS with the higher value is
preferred. If the value is missing or invalid, the UPS cannot win the tie-break.
Comment on lines +126 to +127
Copy link
Member

@jimklimov jimklimov May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how useful this one is for such comparisons, being a fixed value that may be (derived from) a user setting:

Remaining battery runtime when UPS switches to LB (seconds)

It may also be irrelevant if e.g. upssched is used with upsmon for a custom shutdown strategy like "if OB took longer than 5 min to recover from" regardless of battery charge/runtime remaining.

But for some users their (own or device's) setting may be a measure of UPS reliability, so why not.

Copy link
Contributor Author

@sebastiankuttnig sebastiankuttnig May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I understood this as: this is the seconds left (timer) before the UPS switches to LB. Want me to remove it?

Copy link
Member

@jimklimov jimklimov May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it can stay, just needed a second glance at usefulness. This can be a factor for some shutdown scenarios - "this UPS will give me a 5-minute FSD window to shut down gracefully (because that's when it becomes OB+LB)", although for specifically shutdowns with upsmon - more likely the "real" driver would be consulted as one of several supplies, than the failover one. But as you said, for single-UPS clients this may still be relevant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks for the double check. 👍


- `3`: *Compare both variables strictly.* The UPS is preferred only if it has
both a higher `battery.runtime` and `battery.runtime.low` value. If either is
missing or invalid, the UPS cannot win the tie-break.

*strictfiltering*='0|1':: Optional. If set to 1, only UPS drivers matching the
configured status filters are considered for promotion to primary. If set to 0,
the hard-coded default logic is also considered when no status filters match
Expand Down Expand Up @@ -250,6 +268,11 @@ When using `failover` for redundancy between multiple UPS drivers connected to
the same underlying UPS device, data is not multiplexed between the drivers. As
a result, some data points may be available in some drivers but not in others.

For `checkruntime` considerations, the unit of both `battery.runtime` and
`battery.runtime.low` is assumed to be **seconds**. UPS drivers that report
these values using different units are considered non-compliant with the NUT
variable standards and should be reported to the NUT developers as faulty.

Copy link
Member

@jimklimov jimklimov May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General note for posterity: not all NUT drivers provide a battery.runtime, some might only have a battery.charge (or neither estimate/measurement).

For the purpose here, comparing charges is probably rather useless (unless the UPSes have similar capacity so runtimes would happen to compare similarly); but it may be productive to eventually focus on generalizing the runtimecal fallback, for these time numbers to be available in all/most drivers => #2420

AUTHOR
------

Expand Down
37 changes: 27 additions & 10 deletions docs/man/nut-driver-enumerator.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,24 @@ SYNOPSIS
DESCRIPTION
-----------

*nut-driver-enumerator.sh* implements the set-up and querying of the
mapping between NUT driver configuration sections for each individual
monitored device, and the operating system service management framework
service instances into which such drivers are wrapped for independent
execution and management (on platforms where NUT currently supports
this integration -- currently this covers Linux distributions with
systemd and systems derived from Solaris 10 codebase, including
proprietary Sun/Oracle Solaris and numerous open-source illumos
distributions with SMF). It may be not installed in packaging for
other operating systems.
The *nut-driver-enumerator.sh* (also known as "NDE") script implements the
set-up and querying of the mapping between NUT driver configuration sections
for each individual monitored device, and the service instances of an
operating system service management framework (on platforms where NUT already
supports this integration -- currently this covers Linux distributions with
systemd and systems derived from Solaris 10 codebase, including proprietary
Sun/Oracle Solaris and numerous open-source illumos distributions with SMF),
into which such drivers are wrapped for independent execution and management.
It may be not installed in packaging for other operating systems.

With each NUT driver represented as a separate service instance, dependencies
can be defined (e.g. networked drivers must start after the network ability
appears in the OS, but USB/Serial drivers should not wait for that), and they
can fail or be brought into maintenance independently (unlike a monolithic
service based on linkman:upsdrvctl[8] requiring everything configured to be
started). For a few special drivers like linkman:dummy-ups[8], linkman:clone[8],
linkman:clone-outlet[8], and linkman:failover[8] this may also involve a
dependency between service instances of different NUT drivers themselves.

This script provides a uniform interface for further NUT tools
such as linkman:upsdrvsvcctl[8] to implement their logic as
Expand All @@ -42,6 +50,15 @@ hides is the difference of rules for valid service instance names
in various frameworks, as well as system tools and naming patterns
involved.

Depending on the platform, the script may also be wrapped by different service
unit types to run automatically (e.g. upon system start-up, or regularly to
pick up changes of linkman:ups.conf[5] soon after it is edited, or integrated
with a file system monitor to be triggered when the configuration is changed).
Some of these modes make sense for use-cases with a rarely (if ever) changing
population of power devices, e.g. a home or small-office UPS monitored same
way for years at a time; others can help automate a data-center monitoring
system where device deployments (or discovery) can be much more dynamic.

COMMANDS
--------

Expand Down
3 changes: 2 additions & 1 deletion docs/nut.dict
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
personal_ws-1.1 en 3517 utf-8
personal_ws-1.1 en 3518 utf-8
AAC
AAS
ABI
Expand Down Expand Up @@ -1756,6 +1756,7 @@ cgroup
cgroupsv
chargetime
charset
checkruntime
checksum
checksums
chgrp
Expand Down
Loading