Skip to content

Commit

Permalink
Merge pull request #2618 from jimklimov/man-clone
Browse files Browse the repository at this point in the history
Add man page for `clone-outlet` driver
  • Loading branch information
jimklimov authored Sep 11, 2024
2 parents 5e569d6 + 16f1f89 commit 45b74b3
Show file tree
Hide file tree
Showing 8 changed files with 456 additions and 75 deletions.
8 changes: 4 additions & 4 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ https://github.com/networkupstools/nut/milestone/11
as known supported by `nutdrv_qx` (Megatec protocol) since at least
NUT v2.7.4 release [#2395]
- bicker_ser: added new driver for Bicker 12/24Vdc UPS via RS-232 serial
communication protocol, which supports any UPS shipped with the PSZ-1053
extension module. [PR #2448]
- usbhid-ups updates:
* Support of the `onlinedischarge_log_throttle_hovercharge` in the NUT
v2.8.2 release was found to be incomplete. [#2423, follow-up to #2215]
Expand All @@ -150,10 +154,6 @@ https://github.com/networkupstools/nut/milestone/11
* `cps-hid` subdriver now supports more variables, as available on e.g.
CP1350EPFCLCD model. [PR #2540]
- bicker_ser: added new driver for Bicker 12/24Vdc UPS via RS-232 serial
communication protocol, which supports any UPS shipped with the PSZ-1053
extension module. [PR #2448]
- USB drivers could log `(nut_)libusb_get_string: Success` due to either
reading an empty string or getting a success code `0` from libusb.
This difference should now be better logged, and not into syslog. [#2399]
Expand Down
46 changes: 37 additions & 9 deletions docs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,10 @@ ASPELL_OUT_NOTERRORS = (^[ \t]*[\*\@]|^$$)
SPELLCHECK_RECIPE_DEBUG_STREAM = /dev/null
#SPELLCHECK_RECIPE_DEBUG_STREAM = &2

# Note: if we do an interactive spell-check, it updates "nut.dict"
# timestamp even if contents remain. If the caller left a copy of
# the file as "$(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting",
# and the dictionary was not in fact modified, restore the timestamp.
$(SPELLCHECK_BUILDDIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE) $(abs_top_srcdir)/docs/Makefile.am $(abs_srcdir)/$(NUT_SPELL_DICT)
@LANG=C; LC_ALL=C; export LANG; export LC_ALL; \
if test x"$(SPELLCHECK_SRC_ONE)" = x ; then echo "SKIP: Bogus spellcheck call for empty target filename (with make target $@ from `pwd`)" >&2 ; exit 0; fi; \
Expand Down Expand Up @@ -686,7 +690,15 @@ $(SPELLCHECK_BUILDDIR)/$(SPELLCHECK_SRC_ONE)-spellchecked: $(SPELLCHECK_SRCDIR)/
*/) ;; \
*) REPORT_SRCDIR="$${REPORT_SRCDIR}/" ;; \
esac ; \
echo " ASPELL Spell checking on $${REPORT_PREFIX}$${REPORT_SRCDIR}$${REPORT_SRC_ONE}"; \
if [ x"$(SPELLCHECK_INTERACTIVE)" = xtrue ] ; then \
echo " ASPELL Spell checking (interactively) on $${REPORT_PREFIX}$${REPORT_SRCDIR}$${REPORT_SRC_ONE}"; \
LANG=$(ASPELL_ENV_LANG) LC_ALL=$(ASPELL_ENV_LANG) $(ASPELL) check $(ASPELL_NUT_COMMON_ARGS) '$(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE)' || exit ; \
if [ -s $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting ] && [ -s $(abs_srcdir)/$(NUT_SPELL_DICT) ] && diff $(abs_srcdir)/$(NUT_SPELL_DICT) $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting >/dev/null ; then \
touch -r $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting $(abs_srcdir)/$(NUT_SPELL_DICT) ; \
fi ; \
else \
echo " ASPELL Spell checking on $${REPORT_PREFIX}$${REPORT_SRCDIR}$${REPORT_SRC_ONE}"; \
fi ; \
OUT="`(sed 's,^\(.*\)$$, \1,' | $(ASPELL) -a $(ASPELL_NUT_TEXMODE_ARGS) $(ASPELL_NUT_COMMON_ARGS) 2>&1) < '$(SPELLCHECK_SRCDIR)/$(SPELLCHECK_SRC_ONE)'`" \
&& { if test -n "$$OUT" ; then OUT="`echo "$$OUT" | $(EGREP) -b -v '$(ASPELL_OUT_NOTERRORS)' `" ; fi; \
test -z "$$OUT" ; } \
Expand Down Expand Up @@ -757,17 +769,33 @@ $(abs_builddir)/$(NUT_SPELL_DICT).sorted: $(abs_srcdir)/$(NUT_SPELL_DICT)

DISTCLEANFILES = $(NUT_SPELL_DICT).bak-pre-sorting .$(NUT_SPELL_DICT).sorted $(NUT_SPELL_DICT).sorted

# NOTE: In "make SPELLCHECK_INTERACTIVE=true ${docsrc}-spellchecked",
# after an interactive "aspell check" we follow-up by a run of usual
# non-interactive spell-checker to verify that the developer actually
# has fixed all of the files that the tool had concerns about, and
# that the touch-file is updated if the file is okay (to speed up
# any future re-runs). We also must update all relevant *-spellchecked
# touch-files after "make spellcheck-sortdict" which updates "nut.dict"
# file which is a prerequisite for docs checks.
spellcheck-interactive:
@FAILED="" ; for docsrc in $(SPELLCHECK_SRC); do \
echo "Spell checking on $(SPELLCHECK_SRCDIR)/$$docsrc"; \
LANG=$(ASPELL_ENV_LANG) LC_ALL=$(ASPELL_ENV_LANG) $(ASPELL) check $(ASPELL_NUT_COMMON_ARGS) $(SPELLCHECK_SRCDIR)/$$docsrc || \
FAILED="$$FAILED $(SPELLCHECK_SRCDIR)/$$docsrc"; \
done ; \
if test -n "$$FAILED" ; then \
@cp -pf $(abs_srcdir)/$(NUT_SPELL_DICT) $(abs_builddir)/$(NUT_SPELL_DICT).bak-pre-sorting
+@FAILED="" ; for docsrc in $(SPELLCHECK_SRC); do \
if test "$(SPELLCHECK_ENV_DEBUG)" != no ; then \
echo "ASPELL (INTERACTIVE) MAKEFILE DEBUG: Will see from `pwd` if '$(SPELLCHECK_SRCDIR)/$${docsrc}-spellchecked' is up to date" >&2; \
else true ; fi ; \
$(MAKE) $(AM_MAKEFLAGS) -s -f "$(abs_top_builddir)/docs/Makefile" SPELLCHECK_INTERACTIVE="true" SPELLCHECK_SRC="" SPELLCHECK_SRC_ONE="$${docsrc}" SPELLCHECK_BUILDDIR="$(SPELLCHECK_BUILDDIR)" SPELLCHECK_SRCDIR="$(SPELLCHECK_SRCDIR)" "$(SPELLCHECK_BUILDDIR)/$${docsrc}-spellchecked" \
|| FAILED="$$FAILED $(SPELLCHECK_SRCDIR)/$$docsrc"; \
done ; \
if test -n "$$FAILED" ; then \
echo "FAILED interactive spellcheck for the following sources (relative to `pwd`) using custom dictionary file '$(NUT_SPELL_DICT)': $$FAILED" >&2 ; \
exit 1; \
fi ; exit 0
+$(MAKE) $(AM_MAKEFLAGS) spellcheck-sortdict
fi ; \
$(MAKE) $(AM_MAKEFLAGS) spellcheck-sortdict || exit ; \
for docsrc in $(SPELLCHECK_SRC); do \
if test -e "$(SPELLCHECK_BUILDDIR)/$${docsrc}-spellchecked" ; then \
touch "$(SPELLCHECK_BUILDDIR)/$${docsrc}-spellchecked" ; \
fi ; \
done
@echo "------------------------------------------------------------------------"; \
echo "Custom dictionary file $(NUT_SPELL_DICT) may have been updated now."; \
echo "Use e.g. 'git add -p docs/$(NUT_SPELL_DICT) && git checkout -- docs/$(NUT_SPELL_DICT) && make spellcheck-sortdict && git add -p docs/$(NUT_SPELL_DICT)'"; \
Expand Down
9 changes: 6 additions & 3 deletions docs/man/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,8 @@ SRC_SERIAL_PAGES = \
bicker_ser.txt \
blazer-common.txt \
blazer_ser.txt \
clone.txt \
clone.txt \
clone-outlet.txt \
dummy-ups.txt \
etapro.txt \
everups.txt \
Expand Down Expand Up @@ -534,7 +535,8 @@ MAN_SERIAL_PAGES = \
bestfcom.8 \
bicker_ser.8 \
blazer_ser.8 \
clone.8 \
clone.8 \
clone-outlet.8 \
dummy-ups.8 \
etapro.8 \
everups.8 \
Expand Down Expand Up @@ -584,7 +586,8 @@ HTML_SERIAL_MANS = \
bestfcom.html \
bicker_ser.html \
blazer_ser.html \
clone.html \
clone.html \
clone-outlet.html \
dummy-ups.html \
etapro.html \
everups.html \
Expand Down
197 changes: 197 additions & 0 deletions docs/man/clone-outlet.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
CLONE-OUTLET(8)
===============

NAME
----

clone-outlet - clone an UPS, treating its outlet as if it were an UPS (monitoring only)

SYNOPSIS
--------

*clone-outlet* -h

*clone-outlet* -a 'UPS_NAME' ['OPTIONS']

NOTE: This man page only documents the specific features of the
clone-outlet driver. For information about the core driver, see
linkman:nutupsdrv[8].

DESCRIPTION
-----------

This driver, which sits on top of another driver socket, allows users to group
clients to a particular outlet of a device and deal with this output as if it
were a normal UPS. Unlike the linkman:clone[8] driver or linkman:dummy-ups[8]
in repeater mode, this driver represents a read-only device for monitoring and
shutdowns (it does not accept setting any values or sending instant commands
during run time).

Unlike linkman:dummy-ups[8], this driver does not require a running `upsd`
data server nor use the networked NUT protocol to talk to the "real" driver
(which may be remote in case of `dummy-ups` repeater mode).

This driver does not create a completely new virtual device, but replaces or
extends some of the original readings reported by the "real" driver using
information from the specified outlet, and relays all other readings as they
were.

Remote clients like `upsmon` can `MONITOR` the device entry presented by the
data server with this driver (and the "real" driver) running and published.

A larger deployment with one or more lower-priority devices collected on a
manageable outlet of an UPS or ePDU would likely see several drivers set
up on the system actually capable of interactions with the UPS and running
the NUT data server linkman:upsd[8] (and likely powered by another outlet):

* a "real" driver talking to the UPS;
* a `clone` driver talking to the "real" driver and issuing outlet power-off
(or power-cycle) based on relatively high thresholds for remaining battery
charge and/or runtime of the actual UPS (or explicit instant commands),
with such operations first setting the respective timers for the outlet
on the "real" driver, and the "FSD" flag among states of the virtual UPS
status;
* possibly a `clone-outlet` driver which is read-only and interprets the
outlet timer values as triggers for "FSD" or "OFF" flags reported among
states of the virtual UPS status.

With this approach, the lower-priority systems collected on such outlet
would run the NUT linkman:upsmon[8] client to `MONITOR` the virtual UPS
presented by the read-only `clone-outlet` driver and shut down as soon as
the "FSD" flag is raised (fairly early, based on charge and/or runtime
thresholds configured for that driver) allowing the higher-priority devices
(likely including the NUT server) to enjoy a longer on-battery life.

The `clone` driver responsible for outlet power state changes would not
normally be monitored directly (e.g. to avoid unfortunate direct shutdown
requests from those clients), although it can be (instead of `clone-outlet`)
in sufficiently trusted networks.

EXTRA ARGUMENTS
---------------

This driver supports the following settings:

*port*='drivername-devicename'::
Required. The standard NUT driver `port` setting, here it provides the name
of the local Unix socket (or named Windows pipe) for connection to the "real"
driver.

*prefix*='outlet.N'::
Required. Specify the outlet prefix as known on the original driver.
The subset of data points reported by the "real" UPS driver for the actual device
on this prefix would be reported as data points of the virtual UPS maintained by
this driver.

IMPLEMENTATION
--------------

The port specification in the linkman:ups.conf[5] should reference the
local driver socket (or Windows named pipe) that the "real" UPS driver
is using. For example:

------
[realups]
driver = usbhid-ups
port = auto

[clone-outlet-1]
driver = clone-outlet
port = usbhid-ups-realups
prefix = outlet.1
desc = "Outlet 1 of the Real UPS"
[...]
------

The driver internally interprets "real" driver's information about shutdown
delay and shutdown timer, whole UPS status and this outlet's status, and
relays other data points as they were.

If the outlet supports and reports a delayed power-off, the virtual UPS would
issue an FSD via `ups.status` for its clients to shut down safely.

In more detail:

Given the (required) `prefix` value such as `outlet.1`, the driver would
specifically keep track of `<prefix>.status`, `<prefix>.delay.shutdown`,
and `<prefix>.timer.shutdown` data points reported by the "real" driver.
Numeric values of the `*.shutdown` readings would be noted by this driver,
and the boolean outlet status ("off" or otherwise) will be remembered.
These values will also be re-published by this driver "as is".

The `ups.status` from the "real" driver would be remembered, but not
re-published by this driver immediately. Instead, it would be published
during regular "update info" loop cycles either:

* with the "OFF" state added (if `<prefix>.status` indicates the outlet
is "off"),
* or with the "FSD" state prepended (if `<prefix>.timer.shutdown` is
non-negative and does not exceed the `<prefix>.delay.shutdown` value),
* or "as is" if the outlet power state is "not critical".


IMPORTANT
---------

Unlike a real UPS, you should *not* configure a upsmon primary mode for this
driver. When a upsmon primary sees the OB LB flags and tells the upsd server
it is OK to initiate the shutdown sequence, the server will latch the FSD
status and it will not be possible to restart the systems connected without
restarting the upsd server.

This will be a problem if the power returns after the clone UPS initiated
the shutdown sequence on it's outlet, but returns before the real UPS begins
shutting down. The solution is in the clone driver, that will insert the
FSD flag if needed without the help of a upsmon primary.

CAVEATS
-------

The clone UPS will follow the status on the real UPS driver. You can only
make the clone UPS shutdown earlier than the real UPS driver, not later.
If the real UPS driver initiates a shutdown, the clone-outlet UPS driver
will immediately follow.

Be aware that the commands to shutdown/restart an outlet on the real UPS
drivers are not affected, so if you tell the real UPS driver to shutdown
the outlet of the clone UPS driver immediately, your clients will lose
power without warning. A delayed outlet power-off should propagate as FSD,
and the delay should be sufficiently long to allow for client shutdowns.

If you use service management frameworks like systemd or SMF to manage the
dependencies between driver instances and other units, then you may have
to set up special dependencies (e.g. with systemd "drop-in" snippet files)
to queue your `clone` drivers to start after the "real" device drivers.

//////////////////////////////////////
TODO later: declare the driver as "optional", see
https://github.com/networkupstools/nut/issues/1389
//////////////////////////////////////

AUTHOR
------

Arjen de Korte <[email protected]>

SEE ALSO
--------

linkman:upscmd[1],
linkman:upsrw[1],
linkman:ups.conf[5],
linkman:clone[8],
linkman:nutupsdrv[8]

Dummy driver:
~~~~~~~~~~~~~

The "repeater" mode of 'dummy-ups' driver is in some ways similar to the
'clone' and 'clone-outlet' drivers, by relaying information from a locally
or remotely running "real" device driver (and NUT data server).

linkman:dummy-ups[8]

Internet Resources:
~~~~~~~~~~~~~~~~~~~

The NUT (Network UPS Tools) home page: https://www.networkupstools.org/
Loading

0 comments on commit 45b74b3

Please sign in to comment.