Table of Contents
The primary goal of the Network UPS Tools (NUT) project is to provide support for Power Devices, such as Uninterruptible Power Supplies, Power Distribution Units and Solar Controllers.
This document intends to report high-level changes delivered by NUT project releases, as well as practical nuances for packagers and end-users who would be upgrading their NUT deployments.
It DOES NOT intend to detail the change log: it is very large and complicated to render properly, so is better served by another document artifact.
If you wish to discover how everything came together, have a look at the Project History.
If you’re upgrading from an earlier version, see the UPGRADING.adoc file.
Please note that web and source document links, product and service names listed in historic entries of past releases may no longer be relevant.
For a complete and more detailed list of changes, please refer to the ChangeLog file (generated for release archives), or to the Git version control history for "live" codebase.
https://github.com/networkupstools/nut/milestone/11
Fix fallout of development in NUT v2.8.0 and/or v2.8.1 and/or v2.8.2:
NUT_DEBUG_LEVEL
and "-D" CLI option handling to start of
driver programs for issue #2259 in NUT v2.8.2 release misfired with
regard to data-dump mode (it no longer caused foreground by default).
[#2408]
nut-driver-enumerator.sh
improvements misfired in v2.8.2 release
with an overlooked bit of shell syntax, and caused nut-driver@upsname
instances to not auto-restart when ups.conf
is edited. [#682, #2410]
nut-scanner
in v2.8.2
broke detection of (in-)ability to find and query "Old NUT" servers via
libupsclient.so
(internal flag got always enabled). [#2246]
upsmon
v2.8.1 setting of OFFDURATION
[PR #2108, issue #2104,
revisiting PR #2055, issue #2044] was overly zealous and impacted also
the OB
state in cases where communications to the data server were
severed and DEADTIME
setting was not honored. [PR #2462, issue #2454]
drivername -c reload
(e.g. facilitated by nut-driver-enumerator
script and service when editing ups.conf
) led to disconnected Unix
sockets and a tight polling loop that hogged CPU. While the underlying
bug is ancient, it took recent development to hit it as a practical
regression. [issue #1904, issue #2484]
localtime_r()
and gmtime_r()
for some platform builds where
a *_s()
variant was available was not handled correctly. [PR #2583]
allow_killpower
did not actually work as an
ups.conf
flag (only as a protocol command). [issue #2605, PR #2606]
upsdrvquery.c
code was not complete for the case of indefinite
select()
wait timeout. Now upsdrvquery_read_timeout()
fixed private
use of struct timeval={-1,-1}
as a trigger to select(..., NULL)
,
as logged in one part of code and not handled in the other, for the
indefinite wait [#1922, #2392, #2686, #2670]
disable_fix_report_desc
option introduced for usbhid-ups
driver
since NUT v2.8.1 was not applied for early dialog with the device while
its report descriptors were being discovered. Now this flag, as well as
interruptsize
and interruptonly
, are considered before we first try
to open the USB device handle. [#1575, #1512]
cps_fix_report_desc()
we intended to fix-up input and output voltages
in certain cases against high voltage transfer, we only fixed-up one of
them. [#1245]
upsd
should now handle TRACKING
value of STAT_CONVERSION_FAILED
introduced in NUT v2.8.2 for the socket protocol (between driver and
data server), by returning "ERR INVALID-ARGUMENT", so there is no change
for the network protocol definition. [#2182]
configure --enable-inplace-runtime
option added in NUT v2.8.1 should
now also try to detect and set default values for the --with-drvpath
,
--with-cgipath
, --datadir
and --libdir
options to more closely match
a packaged setup and avoid confusion with e.g. two incompatible NUT client
libraries in system default search path. [#2895]
docs/qa-guide.adoc
), accompanied by new chapters written and detailed
for this subject; the chapter about ci_build.sh
script became a separate
ci_build.adoc
document included into the new document. Overall, this guide
intended to help the current and future maintainers of NUT itself, as well
as to inspire any other projects that investigate similar solutions. [#2832]
SEMVER, know thyself!
VERSION_DEFAULT
file, among provisions for packager tuning. [#1949]
docs/nut-versioning.adoc
NUT_WEBSITE_BASE
dependent on codebase maturity
(development or release snapshot); many programs now display such
references in their command-line usage help, method suggest_doc_links()
was introduced for this purpose. [issue #722, PR #2733]
A technologically and practically interesting revamp of NUT mesh of
automake (Makefile.am
)
recipes was completed, allowing for a more parallelizable build routine
on multi-CPU machines — utilizing more cores and completing in less
"wall-clock" time that the standard SUBDIRS
driven approach — when
running make -j (N)
from the project root directory to build everything
enabled by the configure
script.
This was tested with several (GNU, BSD, Sun) implementations of the
"make" program on the few dozen platforms that NUT CI farm tests on.
Notably, GNU make 4.x and newer seems to process parallel high-level
goals and sub-make
runs better than the competition (including GNU
make 3.x).
It is not a radical rewrite like some other research suggested, and so retains
the general structure and certain benefits and flexibility of that standard
automake
approach, including developer build workflows with a bespoke
Makefile
in every significant directory. This also retains (and builds
upon) the benefits of older work done in NUT, for builds in one directory
to depend on libraries and other artifacts built (once) in another.
Overall, NUT CI farm build times got 25%+ shorter (which is important as some scenarios had hit the 1-hour timeout imposed by providers of free CI hosting coupled with the weak machines provided in their free layer), and we suppose this is an interesting case for other projects to draw inspiration from for their recipe refactoring. [PR #2825]
make spellcheck
rule now also benefits from the
rewritten recipes, as detailed above, to visit directories with text files
in parallel. Overall, these changes may save time on multi-CPU systems, if
compared to a sequential walk of all texts (or their directories) as was
done before. [#2871]
The make dist
goal now takes more care to require availability of the man
pages to put into the prepared distribution archive. These may come either
from the current build, or inherited from its sources (if using a tarball
initially) on a platform without tooling required for man page generation.
This requirement compromises usability of make distcheck
on platforms without
such tools from sources without pre-built man pages (e.g. builds from git),
so a couple of new goals were introduced in PR #2842:
- make distcheck-fake-man
generates placeholder files named like pre-built
man pages for any missing files, just for the purpose of constructing
a sane-looking dist archive to distcheck
strictly otherwise;
- make distcheck-ci
is routed to distcheck
or distcheck-fake-man
based on build circumstances (ability to build man pages or presence
of pre-built pages, or lack of either);
- Similarly, make dist-ci
is routed to provide a strict or faked tarball;
- Earlier defined goals like distcheck-light
or distcheck-valgrind
now
take advantage of these mechanisms to also produce usable dist archives
for their relaxed or purpose-specific tests.
Revised behaviors for the upsnotify()
common code introduced in recent NUT
releases (integrating with service management frameworks, etc.):
port
, invalid trailing
keywords…)
NUT_QUIET_INIT_UPSNOTIFY
envvar).
upsd
, upsmon
: reduce "scary noise" about failure to fopen()
the PID file (which most of the time means that no previous instance of
the daemon was running to potentially conflict with), especially useless
since in recent NUT releases the verdicts from sendsignal*()
methods
are analyzed and lead to layman worded situation reports in these programs.
[issue #1782, PR #2384]
-FF
command-line option (e.g. wrapped into the
systemd units to stay "foregrounded" and save a PID file anyway) should
now also handle an existing PID file to interact with the earlier instance
of the driver program, if still running (e.g. started manually). [#2384]
-k
CLI option) should
now try harder to kill off a daemonized sibling, if it still runs (and
did not handle a driver.killpower
INSTCMD well). [#2666]
driver.exit
command for a protocol equivalent of sending a SIGTERM
, e.g. when
a newer instance of the driver program tries to start. [#1903, #2392]
NUT_QUIET_INIT_BANNER
envvar (presence or "true" value) can now
prevent the tool name and NUT version banner from being unilaterally
printed out when NUT programs start. [issues #1789 vs. #316; #2573]
NUT_QUIET_INIT_LISTENER
envvar (presence or "true" value) can
prevent the socket name from being unilaterally printed out when NUT
drivers start. [#2764]
The upsdrvctl
tool improvements:
nut-driver-enumerator
would
conflict with manually-executed driver programs. This warning can
be hushed by exporting a NUT_QUIET_INIT_NDE_WARNING
environment
variable with any value.
upsdrvctl
with a list
operation (or -l
option) to report
manageable device configuration names (possible <ups>
arguments to
start
, stop
etc. operations), or to confirm a single name that it
is known, and a status
operation for more information. [#2567]
maxstartdelay
at the level of driver section in
ups.conf
; added support of maxretry
and retrydelay
at this
level; bumped the default maxstartdelay
from 45 to 75 seconds to
accommodate for longer device initialization (e.g. due to support of
more Megatec Qx dialects by nutdrv_qx
). [#2885, #2888]
riello_ser
updates:
localcalculation
option to compute battery.runtime
and
battery.charge
if the device provides bogus values [issue #2390,
following in the footsteps of #1692, #1685 done for riello_usb
]
(similar to runtimecal
in some other drivers, may be refactored
to that configuration and logic model in later NUT releases)
apcsmart
updates:
strncpy()
and avoid potential overflows that are
possible with strcpy()
used before. [PR #2564]
nutdrv_qx
updates:
1a86:7523
)
as known supported by nutdrv_qx
(Megatec protocol) since at least
NUT v2.7.4 release. [#2395]
innovart31
protocol support for Innova RT 3/1 UPSes. [#2712, #2798]
q2
and q6
protocol support; currently also based/tested
on Innova devices, but other models than RT 3/1. [#2798]
gtec
subdriver and protocol, tested over USB with a
Gtec ZP120N device. [#2818]
hunnox_protocol()
to honour the optional novendor
setting for
devices that are confused by such query, e.g. DEXP LCD EURO 1200VA. [#2839]
battery.runtime
value. [#2765]
GPIO drivers:
WITH_LIBGPIO_VERSION
C macro (in
config.h
) to differentiate the library variants. [issue #2833]
New NUT drivers:
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]
liebert-gxe
: added new driver with support for Liebert GXE Series UPS
(serial or USB posing as a serial port). [#2629]
nhs_ser
: added new driver for numerous NHS Nobreaks, senoidal line — UPS
models with serial port, made by NHS Sistemas Eletronicos LTDA and popular
in Brazil. Currently this driver only builds on Linux. [#2692]
phoenixcontact_modbus
driver: Introduced Phoenix Contact QUINT4-UPS/24DC
management (only new modbus addresses). [#2689, #2716]
scripts/external_apis
with an example script integrating a
non-native protocol with NUT (as live-stream input for dummy-ups
NUT driver to publish further); that example can be installed using
configure --enable-extapi-enphase
. [issue #2807, PR #2813]
usbhid-ups
and netxml-ups
updated to handle "No battery installed!"
alarm also to set the RB
(Replace Battery) value in ups.status
.
This may cause dual triggering of notifications (as an ALARM
generally
and as an important REPLBATT
status in particular) in upsmon
, but
better safe than sorry. [#415]
usbhid-ups
updates:
onlinedischarge_log_throttle_hovercharge
in the NUT
v2.8.2 release was found to be incomplete. [#2423, follow-up to #2215]
interrupt_pipe_no_events_tolerance=N
setting to
optionally prevent UPS lockup, indicated by continuous "Got 0 HID Objects"
situation as a clue, by reconnecting on stale data. Note that while some
devices just report information upon subsequent poll and just have nothing
urgent to declare with an USB interrupt, others (e.g. APC BXnnnnMI) were
seen to lock up until a full connection restart. [#2671, #2681]
lbrb_log_delay_sec=N
setting to delay propagation of
LB
or LB+RB
state (buggy with APC BXnnnnMI devices circa 2023-2024).
This may work better with flags like onlinedischarge_calibration
and
lbrb_log_delay_without_calibrating
for some devices. [#2347]
possibly_supported()
message method for devices
with VendorID=0x06da
(Phoenixtec), seen in some models supported by
MGE HID or Liebert HID, updated to suggest trying nutdrv_qx
. [#334]
mge_model_names[]
was extended for Eaton 9E, 5PX and 5SC
series (largely guessing, feedback and PRs for adaptation to actual
string values reported by devices via USB are welcome), so these devices
would now report battery.voltage
and battery.voltage.nominal
.
Also a device from 5S series (5S1200AU) was tested, although it identifies
as an "Ellipse PRO" in USB metadata. [#2380]
ups.beeper.status
support for Masterpower MF-UPS650VA using the
MGE HID subdriver. [#2662]
0x09D6:0x0001
devices using the MGE HID subdriver
assuming devices made by KSTAR (alternately using MGE vendor ID). [#2661]
powercom-hid
subdriver sent UPS shutdown commands in wrong byte order,
at least for devices currently in the field. A toggle was added to set
the old behavior (if some devices do need it), while a fix is applied
by default: powercom_sdcmd_byte_order_fallback
. [PR #2480]
cps-hid
subdriver now supports more variables, as available on e.g.
CP1350EPFCLCD model, including temperature. [PRs #2540, #2711]
pollonly
flag and default a shorter pollfreq
for CPS devices, to try avoiding device-driven timeouts. [#1689]
Also adjust default offdelay
and ondelay
to reasonable values,
and warn the users with CPS devices if their configured values are
not multiples of 60. [#432, #1394]
cps-hid
subdriver, cps_fix_report_desc()
method should now handle
mismatched LogMax
ranges for input and output voltages, whose USB Report
Descriptors are wrongly encoded by some firmware versions. [#1512]
cps-hid
subdriver, try to fix frequency scaling based on the values
we see from the device and/or configuration overrides (low, nominal, high)
so 499.0 Hz
reading that comes from some firmware versions gets reported
properly as 49.9Hz
. [#2717]
usb_communication_subdriver_t
) are now set back to
their default values during enumeration after probing each subdriver.
Having an unrelated device connected with a VID:PID matching the
arduino-hid
subdriver prevented use of an actual usb-hid
device due to
changes made to this struct during probe. [#2611]
USB-capable drivers generally:
(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]
nut_usb_get_string()
method which can do a
fallback en_US
query for devices which report a broken "langid" language
identifier value. This notably manifested in inability to query the device
Manufacturer, Model and Serial Number values with some buggy device firmware
or hardware. [PR #2604, issues #1925, #414]
usbhid-ups
driver; but should also apply out of the box to same
discovery logic in blazer_usb
, nutdrv_qx
, riello_usb
and
tripplite_usb
drivers.
nut-scanner
and libnutscan
. [issue #2615]
richcomm_usb
,
nutdrv_atcl_usb
) and for general code to collect string readings and
other data points, and to configure the fallback locale or choose one
if several are served by the device. [issues #2613, #2614, #2615]
LIBUSB_DEBUG=INTEGER
setting in ups.conf
(as well as an environment variable that can be generally set via
nut.conf
or service unit methods or init script), to enable
troubleshooting of LibUSB itself. [issue #2616]
assumed_LogMax
(typically when firmware
encoding logic is wrong, and -1
is resolved by parser). [#1512, #1040]
snmp-ups
updates:
baytech-rpc3nc-mib
serving same basic data points as were available in baytech-mib.c
,
but checking for a different model OID subtree and different OIDs for
the device model information. [#2779]
netvision-mib
: sync netvision_output_info
with currently
available SOCOMECUPS-MIB.txt
. [#2803]
mge-utalk
driver will no longer set non-standard status values COMMFAULT
and ALARM
(for a specific status bit); instead, it will set modern
ups.alarm
with values COMMFAULT
and/or DEVICEALARM
(and raise
an ALARM
in ups.status
for either, as standard alarms go). [#2708]
hwmon_ina219
specifically
made for Texas Instruments INA219 chip as exposed in the Linux "hwmon"
subsystem of its "sysfs" interface (and talking I2C under the hood), this
approach seems to have good potential to expand into covering more devices
and perhaps platforms. [#2430]
Introduced ECO
status concept for "ECO mode" (or "High Efficiency" mode,
or "Energy Saver System"…) as named and defined by hardware vendors.
One common aspect is that this is a balance of electrical efficiency vs.
robust outage protection (which may be overkill for IT equipment whose
PSU can survive several milliseconds on capacitors alone) which can be
selected at run-time. Previously such choice was made at the time of
purchase, with the UPSes only supporting some one protection strategy.
[issue #2495, PR #2637]
upsmon
client with ability to report entering and exiting
the ECO mode if reported by the driver;
usbhid-ups
driver.
Introduced handling for the ALARM
status, which already existed as a
common denominator for devices seen with active ups.alarm
variables.
UPS devices in an ALARM
status are generally considered volatile and
may be considered critical/dead by the upsmon
client earlier than in
other statuses (e.g. in no-communication situations). It has to be noted
that there is no common standard for what constitutes an alarm and such
alarm states were also previously observed for less severe reasons. This
depends on the manufacturer/device-specific implementation in the driver.
[issues #415, #2657, PR #2658]
upsmon
client with ability to report entering and exiting
the ALARM status if reported by the driver;
upsmon
client with setting to toggle whether an ALARM
status can prompt the UPS to become critical in certain situations.
upsmon
client can now also report entering and exiting the OVER
(UPS overloaded), TRIM
and BOOST
(adjusting for bad input voltage)
states. A setting OVERDURATION
was introduced to define a timeout
after which a non-communicating UPS that was last seen in state OVER
should be considered critical (or not). [PR #1074, issue #2877]
upssched
timer handler that can be called from upsmon
as its
NOTIFYCMD
to not report confusing environment variable values of
NOTIFYTYPE
and UPSNAME
from the original call when a timer eventually
fires — these values are irrelevant at that distant future. The NIT (NUT
Integration Tests) suite was extended to configure and call this tool,
facilitating its development and troubleshooting. Also the upssched
timer daemon part can now save its PID file (so that NIT can terminate
it after tests). [#2890]
New libupsclient
API methods added:
upscli_str_add_unique_token()
and upscli_str_contains_token()
,
to help C NUT clients process ups.status
and similarly structured
strings same way as NUT core code base. [#2852, #2859]
upscli_connect()
was previously always blocking; now this is sort of
optional, with new upscli_set_default_connect_timeout()
able to change
the implicit timeout from default zero (meaning blocking) to a positive
value (or back to 0). Several NUT clients (upsc
, upscmd
, upsrw
,
upslog
, upsmon
, upsimage
, upsset
and upsstats
) were updated
to default with a 10-second timeout in case of name resolution lags or
unresponsive hosts (notably a problem with upsmon
contacting many
remote systems at once). The NUT_DEFAULT_CONNECT_TIMEOUT
environment
variable can be used to modify this timeout for all clients. Further
new methods here include upscli_get_default_connect_timeout()
to
retrieve a copy of the last stored timeout, and
upscli_init_default_connect_timeout()
to initialize the value from
a number of sources with different priorities. [#2847]
libupsclient
now include nut_debug_level*
so
that NUT clients can be usefully debugged (e.g. using NUT_DEBUG_LEVEL
environment variable). [#2847]
upscmd
, upsrw
, upsimage
, upsset
,
upsstats
, and upslog
(during reconnection), did not UPSCLI_CONN_TRYSSL
so went plaintext even when secure connections were possible. Fixed to at
least try being secure, same way as upsc
does for a long time. [#2847]
upsmon
updates:
POWERDOWNFLAG
must be explicitly set in the
configuration file, there is no built-in default in the binary program
(the settings facilitated by the configure
script during build "only"
impact the upsmon.conf.sample
, init-scripts and similar files generated
from templates). [issue #321, PR #2383]
OBLBDURATION
(seconds) setting to optionally delay raising
the alarm for immediate shutdown in critical situation. [#321]
parse_status()
by not checking further strings if we had
a match; report unexpected tokens in debug log. [#415]
do_notify()
method to support formatting strings
with two %s
placeholders, to use if certain use-cases pass any extra
information (e.g. not just "we have alarms" but their values too). [#415]
ups.status
tokens, reporting them
as "OTHER" notification type (whenever the set of such tokens appears
or changes) or "NOTOTHER" when they disappear. [#415]
upslog
updates:
-s <system>
and -l <logfile>
) along with newer tuple(s) for multiple-system logging
(repeatable -m <system,logfile>
), previously the single-system options
were overridden by the tuple(s); now they become part of the list.
upsname
in the system=upsname[@hostname[:port]]
parameter may
be an asterisk *
to query for devices currently served by the hostname.
%UPSHOST%
in a custom formatting string).
%UPSHOST%
when multiple systems are being logged.
%t
for a TAB character can now be used in the formatting string.
-N
to prefix %UPSHOST%%t
before the format string (whether
default or custom). Useful when logging many systems into same target.
-D
for debugging (and foregrounding by default), like with
other NUT daemons.
More systemd integration:
nut-sleep.service
unit which stops nut.target
when a
system sleep was requested, and starts it when the sleep is finished.
This helps avoid NUT shutting down a woken-up system just because its
power state was critical before the sleep (called as a SHUTDOWNCMD
implementation by the end-user), and a next-read timestamp was not seen
(deemed to be a stale UPS, meaning lost communications during critical
state, so must go down ASAP). While not as elegant as native systemd
"inhibitor interface" support, this approach does work. [#1833, #1070]
upsmon
client via new
Inhibit()
method in common.c
. [#1070]
upsmon
would behave better in face of any significant and unexpected clock
jumps (on POSIX builds so far), even if they are not suspend/hibernate
events (or they were but we could not have an inhibit lock). Now they
should be handled similar (avoid stale UPS data and rash decisions)
for summer/winter time change on non-UTC deployments, a debugger
suspending the upsmon
process, etc. [#2597]
nut-udev-settle.service
was introduced to replace dependency on the
systemd-udev-settle.service
which is deprecated and causes warnings on
some systems. It was shown to benefit NUT use-cases however. [#2638]
gamatronic
driver revised for safer memory operations; this was reported
to have fixed a Segmentation Fault seen in earlier NUT releases with
some of the devices supported by this driver. [#2427]
upsd
updates:
upsd_cleanup()
is now traced, to more easily see that the daemon is
exiting (and/or start-up has aborted due to configuration or run-time
issues). Warning about "world readable" files clarified. [#2417]
LISTEN
on an invalid host name (e.g. localhost:3493
or
1.2.3.4/24
) is now logged in a more actionable manner. [#2665]
nut-scanner
updates:
The tool relies on dynamic loading of shared objects (library files)
orchestrated at run-time rather than pre-compiled, to avoid excessively
huge package footprints. This however relies on knowing (or sufficiently
safely guessing) the library file names to use, and short libname.so
is not ubiquitously available. With the new m4
macro AX_REALPATH_LIB
we can store and try to use the file name which was present on the build
system, while we search for a suitable library. [#2431]
A different but functionally equivalent trick is done for libupsclient
during a NUT build.
* Fixed support for IPv6 addresses (passed in square brackets) for both
-s
start/-e
end command-line options, and for -m cidr/mask
option.
[issue #2512, PR #2518]
* Newly added support to scan several IP addresses (single or ranges)
with the same call, by repeating command-line options; also -m auto{,4,6}
can be specified (once) to select IP (all, IPv4, IPv6) address ranges of
configured local network interfaces.
An /ADDRLEN
suffix can be added to the option, to filter out discovered
subnets with too many bits available for the host address part (avoiding
millions of scans in the extreme cases).
[issue #2244, issue #2511, PR #2509, PR #2513, PR #2517]
* Implemented parallel scanning for IPMI bus, otherwise default scan for
all supported buses with -m auto
takes unbearably long. [#2523]
* Bumped version of libnutscan
to 2.6.0, it now includes a few more
methods and symbols from libcommon
. [issue #2244, PR #2509]
* Do not actively suggest vendor(id)
, product(id)
, and serial
options
for bcmxcp_usb
, richcomm_usb
and nutdrv_atcl_usb
drivers for now
[#1763, #1764, #1768, #2580]
All drivers should now support the optional sdcommands
setting with
a site-local list of instant commands to handle upsdrv_shutdown()
,
which may be useful in cases when the driver’s built-in commands
(or their order) do not meet the goals of particular NUT deployment.
This can also help with shutdown endgame testing, using a mock command like
starting the beeper (where supported) to verify that the UPS communications
happen as expected, without compromising the load connected to the UPS.
Also defined EF_EXIT_SUCCESS
and EF_EXIT_FAILURE
in include/common.h
to avoid magic numbers in code like set_exit_flag(-2)
, and revised whether
it is getting set at all in "killpower" vs. other cases, based on new
handling_upsdrv_shutdown
internal flag.
during this overhaul, many older drivers got their first ever supported
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:
upscli_splitname()
should now recognize upsname:port
typos (missing
the @hostname
part) and error out gracefully.
NUT_DEBUG_SYSLOG
environment variable to tweak activation
of syslog message emission (and related detachment of stderr
when
backgrounding), primarily useful for NIT and perhaps systemd. Most
methods relied on logging bits being set, so this change aims to be
minimally invasive to impact setting of those bits (or not) in the
first place. [#2394]
root
-owned daemons now use not the hard-coded PIDPATH
value set
by the configure
script during build, but can override it with a
NUT_PIDPATH
environment variable in certain use-cases (such as
tests). [#2407]
STATEPATH
via ups.conf
to match upsd
custom configuration ability; the data server would prefer the value
from ups.conf
over the one in upsd.conf
, if both are present.
Note that NUT_STATEPATH
environment variable trumps both. [issue #694]
progname
string defined in the respective NUT
source file, so a boolean NUT_IGNORE_CHECKPROCNAME
environment
variable support was added to optionally disable this verification.
Also the NUT daemons should request to double-check against their
run-time process name (if it can be detected). [issue #2463]
m4
macros to check during configure
phase for the
platform, and a nut_bool.h
header with nut_bool_t
type to use
during build, to avoid the numerous definitions of Boolean types
and values (or macros) in the NUT codebase. [issue #1176, issue #31]
distcheck-something
targets did not inherit DISTCHECK_FLAGS
properly. [#2541]
status_get()
in NUT driver state API, to check if a status
token string had been set recently, and to avoid duplicate settings;
fixed status_set()
for multi-token arguments. [PR #2565, issue #2708]
LOGOUT
command for cleaner
disconnection handling. [#2572]
clang-18
and newer revisions of
gcc-13
+ whose static analyzers on NUT CI farm complained about some
imperfections after adding newer OS revisions to the population of
build agents. [#2585, #2588]
clang-19
brought new findings about mismatched formatting
strings and int
-ish parameters of respective methods.
Overall, had to change formatting strings in some cases, variable types
in others (e.g. flags or notification types do not make sense as signed)
and added casting in a few places that remained, because:
%x
style formatting requires an unsigned int
variable
int
by default
uint16_t
, done in some
cases, are up-scaled into int
by default
char
's, unsigned
or not, seem to be also up-scaled into int
docs/nut-names.txt
with items defined by 42ITy NUT fork. [#2339]
configure
script to use default (target-specific) values of
CFLAGS
, LIBS
etc. when probing relevant settings for each third-party
dependency; as a consequence, on systems that support building for many
targets, we check relevant build-ability for that target and not for the
building system itself. [issue #2673, PR #2675]
scripts/valgrind
with a helper script and suppression file to
ignore common third-party problems. [#2511]
configure --with-valgrind=PATH
vs. detection of its usability;
fixed some portability issues with detection of usability per se, tried
--with-valgrind=auto
the default to auto-detect and use the feature
(in tests) wherever possible, but too many NUT CI farm agents disagreed;
so for now the default is no
. [#2823]
stdout
buffer immediately for sane logging (especially on Windows). [PR #2699]
nut.exe
(the NUT for Windows wrapper for all-in-one service)
to be more helpful with command-line use (report that it failed to start
as a service, have a help message, pass debug verbosity to launched NUT
programs…) and add a man page for it. [issue #2432, PR #2446]
scripts/Windows/build-mingw-nut.sh
helper script was extended to
use nut_build_${ARCH}
and nut_install_${ARCH}
directories by default,
with the older nut_build
and nut_install
short names becoming just a
symbolic link to the latest executed build: this should help compare the
differences of 32/64-bit builds, without them stepping on each other’s toes.
NUT binding for Python and the NUT-Monitor
Python UI client updates:
PyNUTClient
module should no longer rely on presence of a telnetlib
module in the build or execution environment (deprecated in Python 3.11,
removed since Python 3.13). [issue #2183, PR #2792]
PyNUTClient
module tarball should now use a
lower-cased file name (and immediate versioned directory name inside) to
match the requirements of PEP-0625.
The Python module name (and its directory) should remain camel-cased. [#2773]
NUT-Monitor
Python UI client.
NUT-Monitor
Python UI client itself was revised to report the
PACKAGE_VERSION
and NUT_WEBSITE_BASE
strings in the "About" dialog
contents; localization support for the dialog and some other resources
was revised to work in Py3Qt5 variant of the script. [#722]
Documentation recipe updates:
Enabled installation of built single-file PDF and HTML (including man
page renditions) under the configured docdir
. It seems that previously
they were only built (if requested) but not installed via make
, unlike
the common man pages which are delivered automatically. [#2445]
The html-chunked
documents are currently still not installed.
./configure --with-doc=man=dist-auto
to use the
distributed manual page files if present; only fall back to (re-)building
them if we can. [#2473]
make distcheck-light-man
recipe to require verification that
the manual page files can be built using the prepared "tarball" archive.
[#2473]
Revised the documentation building recipes, with the goal to avoid
building the ChangeLog
products and their intermediate files more
than once (but still react to git
metadata changes during development),
and to sanity-check the resulting final document (currently only for
html-single
mode).
As part of this, the CHANGELOG_REQUIRE_GROUP_BY_DATE_AUTHOR
setting was
added (for make
calls and used by tools/gitlog2changelog.py.in
script), and it defaults to true
allowing for better ordered documents
at the cost of some memory during document generation. [#2510]
* Updated man page generation with configure
script options to specify
that manual section codes on the target platform differ from (Linux-based)
defaults hard-coded into page sources; this should allow to simplify NUT
packaging recipe maintenance in those diverse distributions (no more need
to update patches for changed or added documentation sources).
* Lines in first section of NUT configuration report (which can optionally
remain as config.nut_report_feature.log
and be installed into shared
documentation of a NUT package) are now better grouped as miscellaneous
features and detection results, then drivers and programs/tools. [#2676]
common/Makefile.am
build product for a new internal library
libcommonstr.la
which allows a smaller selection of helper methods
for tools like nut-scanner
which do not need the full libcommon.la
nor libcommonclient.la
. [#2478, #2491]
drivers/Makefile.am
build product for a new internal library
libserial-nutscan.la
to simplify tools/nut-scanner/Makefile.am
recipes.
[#2490]
snmp-ups
and netxml-ups
drivers now explicitly brings linker
dependency on chosen SSL libraries. [#2479]
configure --with-modbus+usb
option to require an USB-capable
libmodbus, and defaulted a couple of specific situations as if this was
required (implicitly): configure --with-modbus --with-usb
and
either --with-drivers=*apc_modbus*
(actually implies --with-modbus
)
or --with-modbus-includes=... --with-modbus-libs=...
as a way to avoid surprises with custom NUT builds aiming to have an
USB-capable apc_modbus
driver (currently this requires a custom-built
libmodbus). Also fixed (re-)detection of libmodbus RTU USB support with
static libmodbus builds. [#2666]
phoenixcontact_modbus
, generic_modbus
,
huawei-ups2000
, socomec_jbus
, adelsystem_cbi
, apc_modbus
) should
now report whether the library is linked dynamically or statically — this
can help in troubleshooting (especially of apc_modbus
which may be using
a custom build of the library not delivered by the operating system). [#2897]
Brought keyword dictionaries of nutconf
and augeas
NUT configuration
file parsers up to date; restored automated checks for augeas
lenses.
[issue #657, issue #2294]
Some known issues remain with augeas lens definitions, so currently they should be able to parse common simple use-cases but not certain types of more complex configurations (e.g. some line patterns that involve too many double-quote characters) which are valid for NUT proper. [#657]
pkg-config
program
should now ignore host *.pc
files and avoid confusion.
m4
/configure.ac
sources updated to handle a much larger build scope on MacOS. Also
migrated the builders to Apple Silicon from x86 (deprecated by CircleCI).
Disabled HOMEBREW_NO_AUTO_UPDATE
to gain 40 min per build at cost of
slightly older environment. [#2502, #1579]
scripts/fuse/execfuse-nut
now. [#2591]
make install-as-root
to create directories not directly
populated by make install
and NUT build artifacts, apply permissions
and (on some platforms) restart services involved with NUT. [#1298]
https://github.com/networkupstools/nut/milestone/10
Fix fallout of development in NUT v2.8.0 and/or v2.8.1:
INSTCMD
processing of commands without parameters nor
TRACKING
identifier. [#2155]
upsmon
recognition of CAL
state could linger after the calibration
activity was completed by the hardware, which led to mis-processing of
shutdown triggers. Also, notification was added to report "finished
calibration". [issue #2168, PR #2169]
upsmon
recognition of OFF
state as a trigger for FSD (forced shut
down) criticality considered also the input line state, which may be
an independently evolving circumstance. [issue #2278, PR #2279]
upsmon
support for POLLFAIL_LOG_THROTTLE_MAX
did not neuter the
applied setting when live-reloading configuration, so commenting it
away in upsmon.conf
did not have the effect of resetting the logging
frequency to default. It also did not reset the counters to certainly
follow the new configuration for existing faults. [issue #2207, PR #2209]
upsmon
support for POLLFAIL_LOG_THROTTLE_MAX
had an off-by-one error
(e.g. reporting "Data stale" or "Driver not connected" every 30 sec with
POLLFAIL_LOG_THROTTLE_MAX 5
and POLLFREQ 5
settings). [#2207]
user=root
in their configuration) failed to apply group ownership and permissions
to their Unix socket file for interaction with the local data server.
[#2185, #2096]
scripts/python/app/NUT-Monitor
referenced py3qt3
instead of the correct py3qt5
. It also tries to check both py2gtk2
and py3qt5
implementations verbosely, even if one is not installed.
[#2199, #2201]
DesktopFileName
in scripts/python/app/NUT-Monitor-py3qt5
,
this binds the application with the desktop file and allow the Open
Desktop compatible implementation to display the proper icon and
application name. [#2205]
apc_modbus
strictly required USB support even if
building NUT without it. [#2262]
CFLAGS
and CXXFLAGS
should again be honoured. [PR #2306]
configure
script option --with-debuginfo
. Note that default autoconf
behavior usually embeds moderate optimizations and debug information on
its own. [PR #2310]
usbhid-ups
subdriver belkin-hid
which in practice
relied on the broken older behavior; more details in its entry below.
[PR #2371]
nut-usbinfo.pl, nut-scanner and libnutscan:
libnutscan
was bumped from 2.2.0 to 2.5.0
during evolution of this NUT release.
alt_driver_names
in nutscan_device_t
structure
for ability to suggest a comment with other possibly compatible driver
names in configuration snippets generated by nut-scanner
; practical
support implemented for USB connected drivers.
comment_tag
and a method to nutscan_add_commented_option_to_device()
, instead of
hacks in prepared config data which broke some use-cases. [#2221]
-U
for USB scan can now be specified several times
to increase the detail level about hardware link to the device (this was
previously always suggested, but may be not reliable if USB enumeration
gets changed over time). [#2221]
$datadir
e.g. /usr/local/share/nut
and need to be pasted into your /boot/loader.conf.local
). [#2159]
nutdevN
device section names
when called separately to scan different media buses (one at a time).
Now the "bus" name would be embedded (e.g. non-colliding nutdev-usb1
and nutdev-snmp1
). [#2247]
.dev
and .seq
files) located in your sysconfig directory, and prepare configuration
sections with the simulation driver (currently dummy-ups
). [#2246]
dummy-ups
as driver when scanning NUT "bus"
with Old or Avahi method. [#2236, #2245]
ALLOW_NOT_ALL_LISTENERS
setting was added to control this behavior. [#723]
NUT CI improvements:
ccache
namespace concept, where possible. [#2256]
--without-usb
. [#2263]
libgd
discovery (for CGI etc. builds). [#2287]
aspell
TeX module detection more reliable. [#2206]
main driver core codebase:
nutdrv_qx
built for serial-only support), and built
in fact without USB support but used for USB devices, with some more
information to make troubleshooting easier. [issue #2259, PR #2260]
-D
CLI option and/or
the NUT_DEBUG_LEVEL
environment variable now check those earlier in
their life-time, so that initialization routine can be debugged. [#2259]
usb_config_index
usb_hid_rep_index
, usb_hid_desc_index
, usb_hid_ep_in
and
usb_hid_ep_out
hardware connection settings via ups.conf
options.
This is treated as experimental, not all code paths may be actually
using such values from struct usb_communication_subdriver_t
rather
than hard-coded defaults. Discovery of correct values is up to the
user at the moment (using lsusb
, internet search, luck…) [#2149]
nut-driver-enumerator (NDE) service/script:
--daemon-after
variant which parses the configuration once before
daemonization and this has a chance to fail while not forked off, as
well as to allow only completing the service unit initialization when
everything is actually ready to work (so further dependencies can start
at the proper time). [#682]
ups.conf
. [PR #2297, issues #2282 and #2258]
snmp-ups driver:
usbhid-ups driver:
arduino-hid
subdriver was enhanced from "initial bare bones" experimental
set of mapped data points to support some 20 more mappings to make it more
useful as an UPS driver, not just a controller developer sandbox. [#2188]
cps-hid
subdriver now supports devices branded as Cyber Energy and built
by cooperation with Cyber Power Systems. [#2312]
belkin-hid
subdriver now supports Liebert PSI5 devices which have a
different numeric reading scale than earlier handled models. [issue #2271,
PR #2272, PR #2369] Generally the wrong-scale processing was addressed,
including a regression in NUT v2.8.0 which led to zero values
in voltage data points which NUT v2.7.4 reported well [#2371]
onlinedischarge
configuration flag name was too ambiguous and got
deprecated (will be supported but no longer promoted by documentation),
introducing onlinedischarge_onbattery
as the meaningful alias. [#2213]
OL+DISCHRG
state should now be throttled
(see the driver manual page for more details) [#2214, #2215]:
battery.charge
is available, make the message when entering the
state and then only if the charge differs from that when we posted
the earlier message (e.g. really discharging) and is under
onlinedischarge_log_throttle_hovercharge
value (defaults to 100%);
onlinedischarge_log_throttle_sec
, by default 30 sec if battery.charge
is not reported by the device (should be frequent by default, in case
the UPS-reported state combination does reflect a bad power condition).
nutdrv_qx driver:
battery_voltage_reports_one_pack
configuration flag
introduced in NUT v2.8.1. [originally by PR #1279; fixed by PR #2324,
issue #2325]
tools/gitlog2changelog.py.in
script was revised, in particular to
convert section titles (with contributor names coming from Git metadata)
into plain ASCII character set, for dblatex
versions which do not allow
diacritics and other kinds of non-trivial characters in sections. This can
cause successful builds of ChangeLog.pdf
file on more platforms, but at
expense of a semi-cosmetic difference in those names. [PR #2360, PR #2366]
https://github.com/networkupstools/nut/milestone/8
*.adoc
pattern
to facilitate automatic rendering in GitHub and IDE GUIs, and adding recipe
support for GitHub issue/PR links. This NEWS
file is now proper asciidoc
rendered into release-notes.pdf
(and HTML versions). [issue #1953, PR #2048]
Internally, the documents would use a new way to define cross-linking to
other pages and their chapters, to facilitate different renderers (including
GitHub UI), and file names created for "chunked HTML" documentation format
will no longer have the "chapter number, section number" format which is
not easy to maintain over time with independent builds of documentation
in NUT and the actual and historic snapshots for nut-website for example.
Chapter/Section names will be adapted to produce "chunked HTML" file names
instead. Documentation links rendered in GitHub UI should point to the HTML
pages served by a current iteration of the NUT website. [PR #226, PR #669]
configure --enable-spellcheck
toggle should add spelling checks
to make check
(by default, if tools are available) to facilitate quicker
acceptance of contributions. [#2067]
Published a new maintainer GPG key to sign tags and release artifacts, and possibly git commits as well, as part of solution for issue #1410. You can pull it from common OpenPGP servers with the following command:
:; gpg --recv-key DE0184DA7043DCF7 gpg: key DE0184DA7043DCF7: public key "Jim Klimov (Doing FOSS since last millennium) <jimklimov@gmail.com>" imported gpg: Total number processed: 1 gpg: imported: 1
as part of https://github.com/networkupstools/nut/issues/1410 solution.
Bug fixes for fallout possible due to "fightwarn" effort and other evolution in NUT v2.8.0 release:
upsdebugx()
and similar methods were converted to macros in #685
to avoid useless data manipulations and requests for logged information,
whose results would be ignored instantly because the debug level is
too low. As issue #1455 and PR #1495 found, in two cases the called
commands did "meaningfully" modify data — so without debug logs the
program misbehaved. A known regression for upscode2
driver; might
be or not be a problem with upsd
server in NUT v2.8.0 release,
fixed for NUT v2.8.1.
cyberpower-mib
(for snmp-ups
driver) sources was
arranged in NUT v2.8.0 release in a way that precluded the driver
logic from looking at all of its entries. Also a fix for instant
command definitions had in fact broken them due to other development.
Regressions fixed for NUT v2.8.1 [#1432, #2029]
dummy-ups
driver for NUT
v2.8.0 release misfired on some platforms. Regression fixed for NUT
v2.8.1 [#1420]
configure
script for custom builds [#1467]
upsdrvctl
can pass debugging level through to the launched
driver(s), they would by default stay in the foreground. This can
complicate (or simplify, when intentional) the management of service
instances. Now there are explicit upsdrvctl
options for choosing
this (-F
/-B
), although default behavior is retained. Note that
explicit foregrounding mode also keeps upsdrvctl
tool from exiting
and would not wait for one driver to complete initialization before
starting another in case of mass-management loop to start all drivers
(without specifying the single device) [#1759, #1806, #1875]
apcsmart
and apcsmart-old
handled invalid data too zealously
and aborted instead of skipping over it, like they did before [#2015]
riello_ser
and riello_usb
misfired [#2137]
libupsclient
parser of device
and host names to crash upon bad inputs (e.g. poorly resolved environment
variables in scripts). Now it should fail more gracefully [#2052]
configure --enable-inplace-runtime
option should set default values
for --sysconfdir
, --with-user
and --with-group
options to match an
existing NUT deployment — for users who are trying if a custom build
of recent codebase solves their practical issues. For "quick tests", a
shortcut operation ./ci_build.sh inplace
was added [#1714]
NUT_DEBUG_PID
envvar (presence) support was added to add current
process ID to tags with debug-level identifiers. This may be useful
when many NUT daemons write to the same console or log file. [#2118]
nutdrv_qx updates:
battery_voltage_reports_one_pack
driver option was added for devices
which "natively" report a battery.voltage
for a single battery pack or
cell, not for the whole assembly [#1279]
voltronic_qs_protocol
should now accept both "V" (as before)
and newly "H" dialects, which otherwise seem interchangeable [#1623]
armac
subdriver was enhanced to support devices with a different
response pattern than previously expected per initial contribution.
It was tested to work with Vultech V2000 and Armac PF1 series. [#1978]
nutdrv_qx and blazer updates:
usbhid-ups updates:
subdriver
configuration option, to select the
USB HID subdriver for the device manually where automatic match
does not suffice (e.g. new devices for which no vendorid
/productid
pair was built into any driver, or for different-capability devices
with same interface chips, notably "phoenixtec/liebert" and "mge") [#1369]
powerfactor
without a namespace (bug
in 2.8.0 release), fixed to outlet.powerfactor
usbhid-ups
driver should now reconnect if libusb
returned a
memory allocation error [#1422] (seen as "Can’t retrieve Report 0a:
Resource temporarily unavailable"), which can cause practical problems
in the field — the driver otherwise interpreted the situation as
ups.status
being OL OFF
and cut the power supply.
UPS.Battery.ManufacturerDate
to map
to battery.mfr.date
(not battery.date
which is the maintenance
replacement date) [#1644]
onlinedischarge_calibration
option for UPSes that report
OL+DISCHRG
when they are in calibration mode [#2104]
riello_usb updates:
upsid
to match the
specific device (not all firmware/hardware models support this) [#2075]
apcupsd-ups:
apc_modbus driver was introduced, to cover the feature gap between existing NUT drivers for APC hardware and the actual USB-connected devices (or their firmwares) released since roughly 2010, which deprecated standard USB HID support in favor of Modbus-based protocol which is used across the board (also with their network management cards). The new driver can monitor APC UPS devices over TCP and Serial connections, as well as USB with a patched libmodbus (check https://github.com/EchterAgo/libmodbus/commits/rtu_usb for now, PR pending). [#139, #2063]
dummy-ups:
repeater_disable_strict_start
option to disable the driver
exiting upon encountering any kind of error at startup (as repeater).
This option should allow for collective upsdrvctl
startup despite
individual target UPS to be repeated or upsd
not having come up yet.
[#2132]
NUT for Windows:
scripts/Windows/build-mingw-nut.sh
[#1489]
ci_build.sh
script and
Makefile
checks as used across the board for local developer builds,
Linux/illumos/FreeBSD/OpenBSD/… on dedicated NUT CI farm on Fosshost,
and MacOS on CircleCI [#1552]
snmp-ups updates:
ups.status
) between
Eaton UPSs, and rename mibs from pw
to eaton_pw_nm2
, and from
pxgx_ups
to eaton_pxg_ups
[#1715]
baytech-mib.c
subdriver: fixed baytech_outlet_status_info[]
set
of valid outlet status values [#1871]
cyberpower-mib.c
subdriver: support devices which report the shorter
Vendor OID as their sysOID, e.g. "CyberPower PowerPanel Personal" [#1997]
and support more data points including hardware status alarms [#1982]
bestfortress
driver shutdown handling was fixed to use a non-trivial
default timeout [#1820]
optiups
driver only gave accurate voltage information with 120VAC
models and assumed a 12V battery when calculating capacity. There is
a protocol command that gives a (fixed) voltage which correlates with
the voltage selection DIP switches on the back of the UPS, taking into
account whether it is a 120 or 240VAC model. Likewise, now the battery
capacity fix is applied globally, based on whether or not the battery
voltage is greater than 20V. [#2089]
GPIO drivers [#1855]:
generic_gpio_libgpiod
driver using libgpiod
backend was added
(defaults to be required on Linux, optional on other platforms)
make install
of PyNUT module and NUT-Monitor desktop
application [#1462, #1504]
riello_usb
and richcomm_usb
[#1763] and updated man pages
of all USB drivers using these options to include the same description
[#1766]
allow_duplicates
flag for common USB matching options which
may help monitor several related no-name devices (although without knowing
reliably which one is which… better than nothing) [#1756]
nut-scanner
program should now suggest same configuration fields as
those used by common USB matching options in (most of the) drivers, e.g.
adding "device" to the generated configuration section [#1790]
SIGTERM
quickly are now retried with
SIGKILL
[#1424]
driver.state
to help readers determine
whether it is initializing, reconnecting, or running regular loops [#1767]
LD_LIBRARY_PATH
as a preferred possible override
to built-in paths (note that most operating systems advise against setting
this variable unless troubleshooting, although other systems rely on it)
[#805]
upsdebugx()
should now be less
limited in the sizes of messages that they can print, such as path names
that may be quite long. Note that the OS methods manipulating the strings,
and receivers such as logging systems, may still impose limits of their own.
nut-scanner
usage and debug printouts now include the loadable library
search paths, to help troubleshooting especially in multi-platform builds;
pre-filtering of the built-in paths was introduced (to walk only existing
and unique directory names) [#317]
lt_dlopen()
implementation on the current
platform would find library files better [#805]
libltdl
in configure
script updated with fallback code to
find it on systems that deliver the library to /usr/local/lib
(e.g. on
FreeBSD) [#1577]
configure --with-nut-scanner
toggle was added, specifically
so that build environments requesting --with-all
but lack libltdl
would
abort and require either to install the dependency or explicitly forfeit
the tool (some distro packages missed it quietly in the past) [#1560]
nut-scanner
program should now by default warn about serial numbers
which do not make much sense (are duplicate, empty, all same character, etc)
[#1810]
usb_resetter
script
has been contributed to scripts/usb_resetter
(the script itself is tracked
externally on GitHub), along with a configuration example for Linux+systemd
[#1887]
Some fixes for builds on older OSes with less functional default system
shell interpreters - now autogen.sh
supports a CONFIG_SHELL
envvar
to inject its value into generated configure
script [#1736]
grep
with -E
support on Solaris as detailed
in https://github.com/networkupstools/nut/issues/1736 comments)
configure
script, reference init-script and packaging templates updated
to eradicate @PIDPATH@/nut
ambiguity in favor of @ALTPIDPATH@
for the
unprivileged processes vs. @PIDPATH@
for those running as root [#1719]
configure
script enhanced: --with-unmapped-data-points
option allows
to build SNMP and USB-HID subdrivers with entries discovered by the scripts
which generated them from data walks, but developers did not rename yet
to NUT mappings conforming to docs/nut-names.txt standards [#1699]
PyNUT.py version bumped to 1.5.0 with some improvements:
ListClients()
method fixed (was broken in many ways), and is now
CI-tested [#549]
DeviceLogin()
method added (mostly as aid to CI-test ListClients()
in a practically relevant manner, so far)
nutclient C++ library:
listDeviceClients()
and deviceGetClients(dev)
to Client
classes, and Device::getClients()
to match PyNUT capabilities [#549]
libnutclientstub
which is an
implementation of a NUT TCP client in C++ with in-memory data store.
upsclient C library:
NUT_QUIET_INIT_SSL
environment variable to hide
the infamous "Init SSL without certificate database" warning [#1662]
upsd.conf
listing of LISTEN
addresses was previously inverted
(the last listed address was applied first), which was counter-intuitive
and fixed for this release [#2012]
upsd
configured to listen on IPv6 addresses should handle only
IPv6 (and not IPv4-mappings) to avoid surprises and insecurity; it
will now warn if a host name resolves to several addresses (and will only
listen on the first hit, as before in such cases) [#2012]
LISTEN *
directives became specified, to try
handling both IPv4 and IPv6 "any" address (subject to upsd
CLI options
to only choose one, and to OS abilities). When both address families are
enabled, the upsd
data server will first try to open an IPv6 socket
asking for disabled IPv4-mapped IPv6 address support (if the OS honors
that), and then an IPv4 socket (which may fail if the IPv6 socket already
covers it anyway); in other words, you can end up with one or two separate
listening sockets. [#2012]
upsmon client changes include:
upsmon
behavior [#1761, #1680…], including new
ability to configure default POWERDOWNFLAG location — packagers are
encouraged to pick optimal location for their distributions (which
remains mounted at least read-only late in shutdown) and a new optional
POLLFAIL_LOG_THROTTLE_MAX setting [#529, #506]
upsmon
should now recognize OFF
and BYPASS
flags in ups.status
and report that these states begin or end. The OFF
state usually means
than an administrative action happened to power off the load, but the UPS
device is still alive and communicating (USB, SNMP, etc.); corresponding
MONITOR
'ed amount of power sources are considered not being "fed" for
the power value calculation purposes. The BYPASS
state is now treated
similarly to ONBATT
: currently this UPS "feeds" its load, but if later
communications fail, it is considered dead. This may have unintended
consequences for devices (or NUT drivers) that do not report these modes
correctly (e.g. an APC calibration routine seems to start with a few
seconds of "OFF" state), so the reported status is only considered as a
loss of feed if it persists for more than OFFDURATION
seconds. [#2044,
#2104]
SHUTDOWNEXIT no
configuration toggle for systems which
require a long time to stop their workload such as virtual machines.
Since the disconnection of a "secondary" client is treated by the
"primary" system as permission to proceed with its own shutdown and
power-off for the UPS, the original (now merely default) behavior to
call SHUTDOWNCMD
and immediately exit could be counter-productive.
An optional delay can also be introduced. [#2133]
upsmon
.
Extended Linux systemd support with optional notifications about daemon state (READY, RELOADING, STOPPING) and watchdog keep-alive messages [#1590]
NUT_QUIET_INIT_UPSNOTIFY=true
environment variable in init-scripts on platforms where such frameworks
are not expected. [#2136]
nut-server.service
as upsd.service
, and nut-monitor.service
as
upsmon.service
(so simple systemctl reload upsd
can work) [#1777]
BROADCAST (num)
keyword,
and a NOBROADCAST
as a shortcut for BROADCAST 0
. This allows clients
to toggle whether they want to receive send_to_all()
updates from a
driver, or only answers to requests they send [#1914]
make sockdebug
for easier developer access to the tool;
also if configure --with-dev
is in effect, it would now be installed to
the configured libexec
location. A man page was also added. [#1936]
Numerous daemons (upsd
, upsmon
, drivers, upsdrvctl
, upssched
)
which accepted -D
option for debug setting previously, now can also
honour a NUT_DEBUG_LEVEL=NUM
environment variable if no -D
arguments
were provided. Unlike those arguments, the environment variable does
not enforce that daemons run in foreground mode by default [#1915]
upssched
with enabled
debug does not stop reporting on stderr
! [#1965]
upssched
was discovered and fixed, where it ran a tight loop
stressing the CPU; it was presumably introduced between NUT v2.7.4 and
v2.8.0 releases [#1964, #1965]
# Set verbosity level 6: :; upsrw -s driver.debug=6 UPS # Set verbosity level 0 to disable the noise (even if debug_min is set): :; upsrw -s driver.debug=0 UPS1@localhost # Un-set the protocol override, honour CLI or config-file settings again: :; upsrw -s driver.debug=-1 remoteUPS@1.2.3.4
+
and a driver.killpower
instant command (for safety, must be unlocked by
driver.flag.allow_killpower
protocol setting or allow_killpower
configuration flag), which is now the first choice for driver -k
operations [#1917, #1923]
ups.conf
reloading in NUT drivers,
with a driver.reload-with-error
instant command (more commands and
signal handling may be available depending on platform), with a goal
of changing inconsequential settings like debug_min
for a running
driver. This can also benefit the drivers on systems managed by real-time
nut-driver-enumerator
and for simpler changes the drivers get only
reloaded and not redefined and restarted. Reload signals should also
be reasonably supported with upsdrvctl
tool. Relevant CLI options
for -c CMD
handing were added to drivers and upsdrvctl
, although
their availability may vary between operating systems [#1903, #1914, #1924]
SIGURG
(or SIGWINCH
on systems that lack
the former) on POSIX platforms to dump their current state information
and move on. Such report goes to stdout
of the driver process (may
be disconnected when background mode is used) — this can help with
troubleshooting [#1907]
main.c
code were enhanced to produce a libdummy_mockdrv.la
helper library during build (not intended to be installed nor distributed),
in order to facilitate creation of test programs which behave like a driver
[#1855]
size_t
, ssize_t
, uint16_t
,
time_t
etc.) in third-party client code that earlier sufficed to only
include NUT headers. Sort of regression by NUT 2.8.0 (note those consumers
still have to re-declare some numeric variable types used) [#1638, #1615]
COPYING
file was updated with licenses and attribution for certain
source code files and blocks coming from the Internet originally [#1758]
tools/gitlog2changelog.py.in
script was revised, in particular to
generate the ChangeLog
file more consistently with different versions
of Python interpreter, and without breaking the long file paths in the
resulting mark-up text [#1945, #1955]
Earlier discussions (mailing list threads, GitHub issues, etc.) could refer to this change set (too long in the making) as NUT 2.7.5.
DISABLE_WEAK_SSL=true
in upsd.conf to disable older/weaker
SSL/TLS protocols and ciphers: when NUT is built against relatively recent
versions of OpenSSL or NSS it will be restricted to TLSv1.2 or better.
For least-surprise, currently defaults to false
and complains in log
[PR #1043]
ALLOW_NO_DEVICE=true
(as an upsd.conf flag or environment
variable passed from caller of the program), to allow starting the data
server initially without any device configurations and reloading it later
to apply config changes on the fly [PR #766]
debug_min=NUM
setting (ups.conf, upsd.conf, upsmon.conf)
to specify the minimum debug verbosity for daemons. This allows "in-vivo"
troubleshooting of service daemons without editing init scripts or service
unit definitions.
synchronous
setting, which is the
new default now: auto
. Initially after driver start-up this mode
acts as the older default off
, but would fall back to on
in case
the driver fails to send reports to upsd
by overflowing the socket
buffer in async mode — so the next connections of this driver uptime
would be synchronized (potentially slower, but safer — blocking on
writes to the data server). This adaptation would primarily impact
and benefit devices with many (hundreds of) data points, such as
ePDUs and daisy chains. [issue #1309, PR #1315]
-F
/-B
), although default
behavior is retained. This change is used for simplified service unit
definitions.
Improvements for device discovery or driver "lock-picking", including general support for:
-s
option), to monitor a device which is not
detailed or mentioned in ups.conf
NUT_ALTPIDPATH
and NUT_STATEPATH
environment variables to override
the paths built into the driver binary [PR #473 and #507]
-d
option), to poll a device for one or
few (update_count ) loops, report discovered values (dump the data
tree in upsc-like format), and exit. This complements the nut-scanner
for finding and identifying devices.
support for new devices:
nutdrv_qx: several subdrivers added or improved, including:
snr
subdriver
in their ups.conf
settings because of USB chip using the same
values of VendorID/ProductID as fabula_subdriver, fuji_subdriver,
and krauler_subdriver.
add devices to HCL/DDL:
NUT-Monitor
name is retained for wrapper
script which calls one of these, such that the current system can execute
[PRs #1310, #1354]
usbhid-ups:
onlinedischarge
option for UPSes that report OL+DISCHRG
when wall power is lost [PR #811]
battery.mfr.date
for APC HID UPS [PR #1318]
snmp-ups:
input.phase.shift
variable
ondelay
(ups.delay.start
) and offdelay
(ups.delay.shutdown
) as timeticks support [PR #276]
nut-scanner: various improvements, including:
nobt
config parameter to skip battery check
on initialization/startup [PR #1256]
netxml-ups:
systemd support improvements:
PROTVER
as alias to NETVER
to report the protocol version in use.
Note that NUT codebase itself does not use this value and handles commands
and reported errors individually [issue #1347]
mode
as a driver argument, and separates the
notion of dummy-once
(new default for *.dev
files that do not change)
vs. dummy-loop
(legacy default for *.seq
and others) [issue #1385]
new protocol variables:
input.phase.shift
outlet.N.name
outlet.N.type
battery.voltage.cell.max
, battery.voltage.cell.min
battery.temperature.cell.max
, battery.temperature.cell.min
battery.status
battery.capacity.nominal
battery.date.maintenance
(and clarified purpose of battery.date
)
battery.packs.external
(and clarified purpose of battery.packs
)
experimental.*
namespace introduced [PR #1046] to facilitate
introduction of NUT drivers and their data points for which we do
not yet have concepts, or which the original driver contributors
did not map well per suitable NUT standards: this allows to balance
having those drivers available in the project vs. least surprise
for when the explicitly experimental names are changed to something
stable and standardized.
Proposed to track Date and Time values (still as "opaque strings") preferably in representations compatible to ISO-8601/RFC-3339 [PR #1076] (standards update; changes to actual codebase to be applied in the future)
Master/Slave terminology was deprecated in favor of Primary/Secondary
modes of upsmon
client:
upsd.users
and
upsmon.conf
) are supported as backwards-compatible settings,
but the obsoleted values are no longer documented.
upsmon
now
first trying to elevate privileges with PRIMARY <ups>
request,
and falling back to MASTER <ups>
just in case it talks to an
older build of an upsd
server.
net_master()
(as handler for MASTER
net command) in header and
C code for the sake of existing linked binaries, and returns the
OK MASTER-GRANTED
line to the older client that invoked it.
net_primary()
(as handler for PRIMARY
net command)
calls the exact same application logic, but returns OK PRIMARY-GRANTED
line to the client.
Build fixes:
pkg-config
to detect dependencies at configure time, as
well as fail-safe detection of presence of pkg-config (and its macros)
to survive and build without it too
upsdebugx()
were refactored as macros so there
is slightly less overhead when logging is disabled [PRs #685 and #1100]
--with-dev
and so may impact upsclient
and nutclient
(C++) consumers.
At the very least, binaries for those consumers should be rebuilt to remain
stable with NUT 2.8.0 and not mismatch int-type sizes and other arguments.
NUT command and variable naming scheme:
support for new devices:
snmp-ups:
Eaton:
macosx-ups:
nutdrv_qx:
nut-scanner:
solis:
usbhid-ups:
systemdsystemunitdir
nutdrv_qx:
tripplite_usb:
Eaton:
support for new devices:
support for new devices:
There was no public NUT 2.7.0 release.
usbhid-ups: final fix for APC Back UPS ES. APC Back UPS ES devices have buggy firmware, and this version does not cause a regression. The max_report variable should be set automatically based on the USB identification values.
maxreport
flag for usbhid-ups
driver, and as a
max_report_size
setting in code, as of NUT v2.8.2 release.
macosx-ups: new OS X Power Sources meta-driver
support for new devices:
Space
to ~
(Reported by Sebastian Pohle, Alioth bug #313636, CVE-2012-2944)
A separate patch, which applies to any faulty version, is also available:
http://trac.networkupstools.org/projects/nut/changeset/3633
For more information, refer to the Common Vulnerabilities and Exposures:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-2944
support for new devices:
support for new devices:
NUT now provides a tool, called nut-scanner, to discover supported devices, both local and remote. nut-scanner will help to ease the configuration step, and power infrastructure discovery. This development, sponsored by Eaton, supports the following methods:
support for new devices:
support for new devices:
Per original semantic versioning, there were no public NUT 2.5.x releases.
--with-doc
option help of configure
script, and
docs/configure.txt for more information.
support for new devices:
support for new devices:
support for new devices:
Per original semantic versioning, there were no public NUT 2.3.x releases.
preliminary support for Power Distribution Units (PDUs): NUT can now support PDUs, either natively (ie using NUT snmp-ups driver), or through a binding to the Powerman daemon. The list of supported PDUs is already quite long, including:
support for new devices:
support for new devices:
Per original semantic versioning, there were no public NUT 2.1.x releases.
support for new devices:
This release is a backport of the development version. Many changes have already been backported previously. Thus it is more a synchronization release, though it includes many bugfixes and support for new models.
support for new devices:
The fentonups driver now recognizes several more Megatec protocol units:
MONITOR ups-1@host-1 ... MONITOR ups-1@host-2 ... MONITOR ups-2@host-2 ... MONITOR ups-3@host-3 ...
More ancient history is not covered in detail here.
You can see docs/history.txt for more details.
This file lists changes that affect users who installed older versions of this software. When upgrading from an older version, be sure to check this file to see if you need to make changes to your system.
For packaging (OS distribution or in-house) it is recommended to
primarily ./configure --with-all
and then excise --without-something
explicitly for items not supported on your platform, so you do not miss
out on new NUT features as they come with new releases. Some may require
that you update your build environment with new third-party dependencies,
so a broken build of a new NUT release would let you know how to act.
This is a good time to point out that for stricter packaging systems, it may
be beneficial to add --enable-option-checking=fatal
to the ./configure
command line, in order to quickly pick up any other removed option flags.
VERSION_DEFAULT
file, so it can be used without git. Certain distros
can benefit from a VERSION_FORCED
file or a NUT_VERSION_FORCED
environment variable exported from their build system, e.g. via
echo NUT_VERSION_FORCED=1.1.1 > VERSION_FORCED
. Unfortunately, some
appliances tag all software the same with their firmware version;
if this is required, a (NUT_)VERSION_FORCED_SEMVER envvar or file can
help identify the actual NUT release version triplet used on the box.
Please use it, it immensely helps with community troubleshooting!
Documentation about this would be maintained in docs/nut-versioning.adoc
[issue #1949]
nut-systemd.preset
file to enable or
disable certain NUT units by default; its comments document each choice.
[issue #2721]
nut-udev-settle.service
was introduced to replace dependency on the
systemd-udev-settle.service
which is deprecated and causes warnings on
some systems. It was shown to benefit NUT use-cases however. [#2638]
make package
should now separate the
PACKAGE_VERSION
from the platform-dependent prefix by a dash character
in the ultimate package file name. Previously they were glued together
for some platform targets (HPUX, Solaris). Solaris SVR4 package file names
should new differentiate i386
vs. amd64
and sparc
vs. sparcv9
,
depending on target_cpu
of the build. If you had any scripts relying
on the older pattern, they may have to be updated.
make dist
goal now takes more care to require availability of the
man pages to put into the prepared distribution archive. Development and CI
builds on platforms unable to fulfill this goal can use make distcheck-ci
(and make dist-ci
) to fake presence of pre-built man pages with placeholder
files, to complete other aspects of distcheck
validation. [#2842]
PyNUTClient
module tarball should now use a
lower-cased file name (and immediate versioned directory name inside) to
match the requirements of PEP-0625.
The Python module name (and its directory) should remain camel-cased.
OS distribution package recipes that deliver the module separately (e.g.
as part of Python ecosystem rather than NUT) may have to adjust. [#2773]
make install
should now deliver also xx_YY.UTF-8
pattern named symbolic links to the
short-named directories and files involved, since some platforms insist
on having those for translations to be found — this should be reflected
in OS packaging recipes as well. [#2845]
New libupsclient
API methods added:
upscli_str_add_unique_token()
and upscli_str_contains_token()
,
to help C NUT clients process ups.status
and similarly structured
strings same way as NUT core code base. [#2852, #2859]
upscli_set_default_connect_timeout()
to modify the internal timeout
used by upscli_connect()
(default 0 still means blocking connections,
positive values should time-limit the connection attempts), and
upscli_get_default_connect_timeout()
to retrieve its copy. [#2847]
libupsclient
and libnutscan
export more symbols now,
and so were bumped to new "current" numbers; this may impact the naming
of shared object files to be delivered by updated packaging. [#2895]
upsc
, upscmd
, upsrw
, upslog
, upsmon
,
upsimage
, upsset
and upsstats
) were updated to default with a 10-second
connection establishment timeout in case of name resolution lags or
unresponsive hosts (notably a problem with upsmon
contacting many remote
systems at once). This may potentially impact NUT deployments which somehow
relied on the blocking behavior of these clients; you can use the
NUT_DEFAULT_CONNECT_TIMEOUT
environment variable to fix this. [#2847]
upscmd
, upsrw
, upsimage
, upsset
,
upsstats
, and upslog
(during reconnection), did not UPSCLI_CONN_TRYSSL
so went plaintext even when secure connections were possible. Fixed to at
least try being secure, same way as upsc
does for a long time. This may
cause console or log messages when SSL can not be initialized, you can use
the NUT_QUIET_INIT_SSL
environment variable to suppress them where the
cryptography is known to be not set up, so the warnings bring no value. [#2847]
lib/*.pc.in
: propagate -R/PATH
(or equivalent — as detected by the
configure
script for the currently used compiler and linker toolkits)
in pkg-config
metadata pointing to NUT library installation location
(by default not in system prefix) to help third-party clients link with us
automatically. If this causes issues, --disable-ldflags-nut-rpath(-cxx)
options (or --enable...="..."
with specific linker arguments) can help.
[#2782, #2865]
configure
script options to specify that
manual sections on the target platform differ from (Linux-based) defaults
hard-coded into page sources; this should allow to simplify NUT packaging
recipe maintenance in distributions (no more updating patches for changed
or added documentation sources)
upsmon
should now integrate natively with systemd-driven OS sleep events
(built with systemd version 221 or newer "inhibitor interface"), so various
hacks previously packaged into /usr/lib/systemd/system-sleep/
scripts or
units requiring/conflicting with the sleep.target
may be obsolete.
For fallback with older systemd, a nut-sleep.service
is provided now.
[#1070, #2596, #2597]
upslog
as a nut-logger
service (disabled by default, needs a upslog.conf
file to deliver the
UPSLOG_ARGS=...
setting for actual monitoring and logging). [#1803]
ALARM
state was introduced to upsmon
, allowing it
to optionally treat it as a factor in deciding that the device is in a
"critical" state (polled more often, assumed dead if communications are
lost). Since it is up to devices and their NUT drivers what they would
raise as an alarm (might be something as mundane as ECO mode being active),
some alarms can contribute to unwanted/early shutdowns. For this reason
a 0|1
setting ALARMCRITICAL
was introduced into upsmon.conf
(default
is 1
), for such users to be able to prevent their upsmon
from treating
the ALARM
status as overly severe when it is not in fact. [#2658, #415]
usbhid-ups
and netxml-ups
updated to handle "No battery installed!"
alarm also to set the RB
(Replace Battery) value in ups.status
.
This may cause dual triggering of notifications (as an ALARM
generally
and as an important REPLBATT
status in particular) in upsmon
, but
better safe than sorry. [#415]
usbhid-ups
subdriver PowerCOM HID
seemingly sent UPS shutdown
and
stayoff
commands in wrong byte order, at least for devices currently
in the field. Driver now sends the commands in a way that satisfies new
devices; just in case a flag toggle powercom_sdcmd_byte_order_fallback
was added to set the old behavior (if some devices do need it). [PR #2480]
usbhid-ups
subdriver CyberPower HID
default pollfreq
sped up to
12 seconds (common default is 30 seconds). Feedback is welcome if this
improves connection stability or overwhelms the UPS controller instead.
[issue #1689, PR #2718]
usbhid-ups
subdriver CyberPower HID
default offdelay
is set to 60
and ondelay
to 120 seconds, in accordance with man page suggestions;
users with custom settings not divisible by 60 will be loudly warned. [#1394]
snmp-ups
subdriver netvision-mib
: synchronized netvision_output_info
with the currently available SOCOMECUPS-MIB.txt
; this can impact some
other devices using that MIB (negatively, if the older mappings were
indeed correct for any practical cases, and were not a typo). [#2803]
nutdrv_qx
fixed hunnox_protocol()
to honour the optional novendor
setting for devices that are confused by such query (e.g. DEXP LCD EURO
1200VA); it may be remotely possible that some other devices could begin
to misbehave due to this fix — please let us know then. [#2839]
mge-utalk
driver will no longer set non-standard status values COMMFAULT
and ALARM
(for a specific status bit); instead, it will set modern
ups.alarm
with values COMMFAULT
and/or DEVICEALARM
(and raise
an ALARM
in ups.status
for either, as standard alarms go). If your
clients (e.g. custom parsing scripts) for devices supported by this driver
depended on those non-standard tokens in ups.status
, they would have to
be updated to handle the new token values in ups.alarm
instead. [#2708]
lbrb_log_delay_sec=N
setting to delay propagation of
LB
or LB+RB
state (buggy with APC BXnnnnMI devices/firmwares issued
circa 2023-2024 which flood the logs with spurious LOWBATT and REPLACEBATT
events). This may work better for some devices when combined with flags
like onlinedischarge_calibration
and lbrb_log_delay_without_calibrating
.
[#2347]
docdir
. It seems previously they were only
built (if requested) but not installed via make
, unlike the common man
pages which are delivered automatically. Packaging recipes can likely
be simplified now. [#2445]
NUT_DEBUG_SYSLOG
environment variable was introduced to tweak activation
of syslog message emission (and related detachment of stderr
when daemons
are backgrounding), which can be useful for systemd service units. It can be
set via nut.conf
file for all standard consumers, or patched/dropped-in to
systemd unit definitions specifically (less recommended, but may be easier
to package). The positive effect would be avoiding duplicate logging as both
syslog
and stderr
ending up in the same journal. [#2394]
CHANGELOG_REQUIRE_GROUP_BY_DATE_AUTHOR
setting was added (for make
calls and used by tools/gitlog2changelog.py.in
script), and it defaults
to true
allowing for better ordered documents at the cost of some memory
during document generation. Resource-constrained builders (working from
a Git workspace, not tarball archives) may have to set it to false
when
calling make
for NUT. [#2510]
STATEPATH
via ups.conf
to match upsd
custom configuration ability; in fact, the data server would prefer the
value from ups.conf
over the one in upsd.conf
, if both are present.
Note that NUT_STATEPATH
environment variable trumps both. [issue #694]
nut-scanner
, which dynamically load shared libraries
at run-time without persistent pre-linking, should now know the library
file names that were present during build (likely encumbered with version
suffixes), and prefer them over plain libname.so
patterns used previously
(which on some platforms are only delivered by development packages as
symlinks). Packaging recipes can likely be simplified now: some distros
certainly did patch NUT source to similar effect). [#2431]
nut-scanner
and symbols that its libnutscan.so
delivers have caused a library version bump. New methods have been added
and one structure (nutscan_ipmi_t
) updated in a (hopefully) backwards
compatible manner. [PR #2523, issue #2244 and numerous PRs for it]
nutconf
tool added to main codebase with NUT v2.8.2 release could be
packaged as a single program (with just a dependency on libnutscan
), e.g.
the library code with configuration file processing logic was built into it.
Starting with NUT v2.8.3, the libnutconf
may optionally be built as a
standalone shared library, to deliver for development of integrations using
--with-dev-libnutconf
option. In this case the nutconf
tool program would
also depend on it for run-time linking. This may have to be considered in
packaging recipes. [#2828]
sendsignalpid()
and sendsignalfn()
methods,
which can impact NUT forks which build using libcommon.la
and similar
libraries. Added new last argument with const char *progname
(may be
NULL
) to check that we are signalling an expected program name when we
work with a PID. With the same effort, NUT programs which deal with PID
files to send signals (upsd
, upsmon
, drivers and upsdrvctl
) would
now default to a safety precaution — checking that the running process
with that PID has the expected program name (on platforms where we can
determine one). This might introduce regressions for heavily customized
NUT builds (e.g. embedded in NAS or similar devices) whose binary file
names differ significantly from a progname
defined in the respective
NUT source file, so a boolean NUT_IGNORE_CHECKPROCNAME
environment
variable support was added to optionally disable this verification.
Also the NUT daemons should request to double-check against their
run-time process name (if it can be detected). [issue #2463]
More environment variable support was added to NUT programs, primarily
aimed at wrappers such as init scripts and service unit definitions,
allowing to tweak what (and whether) they write into debug traces, and
so "make noise" or "bring invaluable insights" to logs or terminal;
they can generally be used for services and init scripts via nut.conf
:
configure
script option to build --with-modbus+usb
was added to
let the caller insist on the use of USB-capable libmodbus (or fail the
NUT build attempt). Certain build arguments can default this option to
become enabled (implicitly): configure --with-modbus --with-usb
and
either --with-drivers=*apc_modbus*
(actually implies --with-modbus
)
or --with-modbus-includes=... --with-modbus-libs=...
as a way to avoid surprises with custom NUT builds aiming to have an
USB-capable apc_modbus
driver (currently this requires a custom-built
libmodbus, can be a static build to avoid conflicts with OS). [#2666]
configure
script option to --enable-NUT_STRARG-always
was added
to enable the NUT_STRARG
macro (to handle NULL
string printing)
even if system libraries seem to safely support this behavior natively.
This should primarily help against overly zealous static analysis tools
in recent compiler generations. [#2585]
language standard revision via
CFLAGS
and CXXFLAGS
should again be honoured. There was a mishap
with the m4
scripting for autoconf
which could have caused use of
C11/C
11 if compiler supported it, regardless of a request. [PR #2306]
$datadir
e.g. /usr/local/share/nut
and need to be pasted into your /boot/loader.conf.local
). [#2159]
bus
, busport
and device
values when generating device configurations by default. They may
appear as comments, or enabled by specifying the -U
command-line
option several times. [#2221]
tools/gitlog2changelog.py.in
script was revised, in particular to
convert section titles (with contributor names) into plain ASCII character
set, for dblatex
versions which do not allow diacritics and other kinds
of non-trivial characters in sections. A number of other projects seem to
use the NUT version of the script, and are encouraged to look at related
changes in configure.ac
and Makefile.am
recipes. [PR #2360, PR #2366]
*.adoc
pattern. Newly, a release-notes.pdf
and HTML
equivalents are generated. Packages which deliver documentation may need
to update the lists of files to ship. [#1953] Developers may be impacted
by new configure --enable-spellcheck
toggle (should add spelling checks
to make check
by default, if tools are available) to facilitate quicker
acceptance of contributions. Packaging systems may now want to explicitly
disable it, if it blocks package building (pull requests to update the
docs/nut.dict
are a better and welcome solution). [#2067]
Several improvements regarding simultaneous support of USB devices that were previously deemed "identical" and so NUT driver instances did not start for all of them:
ups.conf
options for that [#1763], and man pages were
updated to reflect that [#1766];
nut-scanner
tool should suggest these options in its generated
device configuration [#1790]: hopefully these would now suffice for
sufficiently unique combinations;
nut-scanner
tool should also suggest sanity-check violations
as comments in its generated device configuration [#1810], e.g. bogus
or duplicate serial number values;
allow_duplicates
flag (caveat emptor!) which may help monitor several related no-name
devices on systems that do not discern "bus" and "device" values
(although without knowing reliably which one is which… sometimes it
is better than nothing) [#1756].
int
type). Now such
entities are named TYPE_FD
, TYPE_FD_SER
or TYPE_FD_SOCK
with some
helper macros to name and determine "invalid" values (closed file, etc.)
Some of these changes happened in NUT header files, and at this time it
was not investigated whether the set of files delivered for third-party
code integration (e.g. C/C++ projects binding with libnutclient
or
`libupsclient) is consistent or requires additional definitions/files.
If something gets broken by this, it is a bug to address in future [#1556]
Further revision of public headers delivered by NUT was done, particularly
to address lack of common data types (size_t
, ssize_t
, uint16_t
,
time_t
etc.) in third-party client code that earlier sufficed to only
include NUT headers. Sort of regression by NUT 2.8.0 (note those consumers
still have to re-declare some numeric variable types used) [#1638]
make install
of PyNUT module and NUT-Monitor desktop
application — such activity was earlier done by packages directly; now
the packaging recipes may use NUT source-code facilities and package just
symlinks as relevant for each distro separately [#1462, #1504]
upsd.conf
listing of LISTEN
addresses was previously inverted
(the last listed address was applied first), which was counter-intuitive
and fixed for this release. If user configurations somehow relied on this
order (e.g. to prioritize IPv6 vs. IPv4 listeners), configuration changes
may be needed. [#2012]
upsd
configured to listen on IPv6 addresses should handle only
IPv6 (and not IPv4-mappings like it might have done before) to avoid
surprises and insecurity — if user configurations somehow relied on
this dual support, configuration changes may be needed to specify both
desired IP addresses. Note that the daemon logs will now warn if a
host name resolves to several addresses (and will only listen on the
first hit, as it did before in such cases). [#2012]
LISTEN *
directives became specified, to try
handling both IPv4 and IPv6 "any" address (subject to upsd
CLI options
to only choose one, and to OS abilities). This use-case may be practically
implemented as a single IPv6 socket on systems with enabled and required
IPv4-mapped IPv6 address support, or as two separate listening sockets -
logged messages to this effect (e.g. inability to listen on IPv4 after
opening IPv6) are expected on some platforms. End-users may also want to
reconfigure their upsd.conf
files to remove some now-redundant LISTEN
lines. [#2012]
make sockdebug
for easier developer access to the tool;
also if configure --with-dev
is in effect, it would now be installed to
the configured libexec
location. A man page was also added. [#1936]
--with-gpio
configure script option) -
this may impact packaging decisions on some (currently Linux released 2018+)
distributions going forward [#1855]
configure --with-nut-scanner
toggle was added, specifically
so that build environments requesting --with-all
but lacking libltdl
would abort and require the packager either to install the dependency
or explicitly forfeit building the tool (some distro packages missed it
quietly in the past) [#1560]
upsdebugx_report_search_paths()
method in NUT common code was added,
and exposed in libnutscan.so
builds in particular - API version for the
public library was bumped [#317]
Some environment variable support was added to NUT programs, primarily aimed at wrappers such as init scripts and service unit definitions, allowing to tweak what (and whether) they write into debug traces, and so "make noise" or "bring invaluable insights" to logs or terminal:
NUT_DEBUG_LEVEL=NUM
envvar allows to temporarily boost debugging
of many daemons (upsd
, upsmon
, drivers, upsdrvctl
, upssched
)
without changes to configuration files or scripted command lines. [#1915]
NUT_DEBUG_PID
envvar (presence) support was added to add current
process ID to tags with debug-level identifiers. This may be useful
when many NUT daemons write to the same console or log file, such as
in containers/plugins for Home Assistant, storage appliances, etc. [#2118]
NUT_QUIET_INIT_SSL
envvar (presence or "true" value) prevents
libupsclient
consumers (notoriously upsc
) from reporting whether
they have initialized SSL support. [#1662]
NUT_QUIET_INIT_UPSNOTIFY
envvar (presence or "true" value)
prevents daemons which can notify service management frameworks (such
as systemd) about passing their lifecycle milestones, to not report
loudly if they could not do so (e.g. running on a system without a
framework, or misconfigured so they could not report and the OS would
restart the false-positively "unresponsive" service). [#2136]
configure
script, reference init-script and packaging templates updated
to eradicate @PIDPATH@/nut
ambiguity in favor of @ALTPIDPATH@
for the
unprivileged processes vs. @PIDPATH@
for those running as root [#1719]
configure
script can now be retained and installed by using the
--enable-keep_nut_report_feature
option; packagers are welcome to make
use of this, to better keep track of their deliveries [#1826, #1708]
Renamed generated nut-common.tmpfiles(.in) ⇒ nut-common-tmpfiles.conf(.in) to install a /usr/lib/systemd-tmpfiles/*.conf pattern [#1755]
WatchdogSec=
values are currently NOT pre-set into systemd
unit file templates provided by NUT, this is an exercise for end-users
based on sizing of their deployments and performance of monitoring station
[#1590, #1777]
mibs
)
were renamed: pw
is now eaton_pw_nm2
, and pxgx_ups
is eaton_pxg_ups
[#1715]
tools/gitlog2changelog.py.in
script was revised, in particular to
generate the ChangeLog
file more consistently with different versions
of Python interpreter, and without breaking the long file paths in the
resulting mark-up text. Due to this, a copy of this file distributed with
NUT release archives is expected to considerably differ on first glance
from its earlier released versions (not just adding lines for the new
release, but changing lines in the older releases too) [#1945, #1955]
nut-driver@instances
and the nut-driver-enumerator
to manage their population), as well as
updated Python 2 and Python 3 support (again, maybe dictating different
package groups) as detailed below.
--with-dev
and so may impact upsclient
and nutclient
(C++) consumers.
At the very least, binaries for those consumers should be rebuilt to remain
stable with NUT 2.8.0 and not mismatch int-type sizes and other arguments.
nutdrv_qx
framework
for USB and Serial connected devices, not as updates/clones of older e.g.
blazer
family and bestups
. Sources, man pages and start-up messages
of such older drivers were marked with "OBSOLETION WARNING".
do_convert_deci
flag. See
docs/man/netxml-ups.txt for details.
pkg-config
by
default (if present), rather than net-snmp-config(-32|-64)
script(s) as
the only option available previously. The scripts tend to specify a lot
of options (sometimes platform-specific) in suggested CFLAGS
and LIBS
compared to the packaged pkg-config
information which also works and is
more portable. If this change bites your distribution, please bring it up
in https://github.com/networkupstools/nut/issues or better yet, post a PR.
Also note that ./configure --with-netsnmp-config(=yes)
should set up the
preference of the detected script over pkg-config
information, if both
are available, and --with-netsnmp-config=/path/name
would as well.
dummy-ups can now specify mode
as a driver argument, and separates the
notion of dummy-once
(new default for \*.dev
files that do not change)
vs. dummy-loop
(legacy default for *.seq
and others) [issue #1385]
*.dev
files to work as a looping sequence with a TIMER
keywords to change
values slowly; now such files should get processed to the end once.
Specify mode=dummy-loop
driver option or rename the data file used
in the port
option for legacy behavior.
Use/Test-cases which modified such files content externally should
not be impacted.
Python: scripts have been updated to work with Python 3 as well as 2.
NUT-Monitor
script
and nut-monitor.desktop
) are still delivered, but now cover a wrapper
script which detects the environment capabilities and launches the best
suitable UI implementation (if both are available).
[D#]
prefix to log entries with level > 0
so if any scripts or other tools relied on parsing those messages
making some assumptions, they should be updated
TRACKING
ID to be used with
an INSTCMD
or SET VAR
requests; for details see docs/net-protocol.txt
and docs/sock-protocol.txt
--with-augeas-lenses-dir
configure option.
killall -SIGUSR1 upslog
to any OB/OL script actions. This will force
upslog to write a log entry to catch short power transients.
upsd
forks, to work around issues in the
NSS library.
ACCESS is no longer supported in upsd.conf. Use ACCEPT and REJECT.
Old way:
ACCESS grant all adminbox ACCESS grant all webserver ACCESS deny all all
New way:
ACCEPT adminbox ACCEPT webserver REJECT all
Note that ACCEPT and REJECT can take multiple arguments, so this will also work:
ACCEPT adminbox webserver REJECT all
This page is an attempt to document how everything came together.
The Network UPS Tools team would like to warmly thank Russell Kroll.
Russell initially started this project, maintaining and improving it for over 8 years (1996 — mid 2005).
APC’s Powerchute was running on kadets.d20.co.edu (a BSD/OS box) with
SCO binary emulation. Early test versions ran in cron, pulled status
from the log files and wrote them to a .plan file. You could see the
results by fingering pwrchute@kadets.d20.co.edu
while it lasted:
Last login Sat May 11 21:33 (MDT) on ttyp0 from intrepid.rmi.net Plan: Welcome to the UPS monitor service at kadets.d20.co.edu. The Smart-UPS attached to kadets generated a report at 14:24:01 on 05/17/96. During the measured period, the following data points were taken: Voltage ranged from 115.0 VAC to 116.3 VAC. The UPS generated 116.3 VAC at 60.00 Hz. The battery level was at 27.60 volts. The load placed on the UPS was 024.9 percent. UPS temperature was measured at 045.0 degrees Celsius. Measurements are taken every 10 minutes by the upsd daemon. This report is generated by a script written by Russell Kroll<rkroll@kadets>. Modified for compatibility with the BSD/OS cron daemon by Neil Schroeder
This same status data could also be seen with a web browser, since we had rigged up a CGI wrapper script which called finger.
Initial tests with a freestanding non-daemon program provided a few basic status registers from the UPS. The 940-0024C cable was not yet understood, so this happened over the [attachment:apcevilhack.jpg evil two-wire serial hack].
Communicating with SMART-UPS 700 S/N WS9643050926 [10/17/96] Input voltage range: 117.6 VAC - 118.9 VAC Load is 010.9% of capacity, battery is charged to 100.0% of capacity
Note that today’s apcsmart driver still displays the serial number when it starts, since it is derived from this original code.
The first split daemon/client code was written. upsd spoke directly to the UPS (APC Smart models only) and communicated with upsc by sending binary structures in UDP datagrams.
The first CGI interface existed, but it was all implemented with shell scripts. The main script would call upsc to retrieve status values. Then it would cat a template file through sed to plug them into the page.
upsstats actually has since returned to using templates, despite having a period in the middle when it used hardcoded HTML.
The images were also created with shell scripts. Each script would call upsc to get the right value (utility, upsload, battcap). It then took the value, plugged it into a command file with sed, and passed that into fly, a program which used an interpreted language to create images. fly actually uses gd, just like upsimage does today.
This code later evolved into Smart UPS Tools 0.10.
Version 0.10 was released on March 10, 1998. It used the same design as the pre-release prototype. This made expansion difficult as the binary structure used for network communications would break any time a new variable was added. Due to byte-ordering and struct alignment issues, the code usually couldn’t talk over the network to a system with a different architecture. It was also hopelessly bound to one type of UPS hardware.
Five more releases followed with this design followed. The last was 0.34, released October 27, 1998.
Following a long period of inactivity and two months of prerelease testing versions, 0.40.0 was released on June 5, 1999. It featured a complete redesign and rewrite of all of the code. The layering was now in three pieces, with the single driver (smartups) separate from the server (upsd).
Clients remained separate as before and still used UDP to talk to the server, but they now used a text-based protocol instead of the brittle binary structs. A typical request like "REQ UTILITY" would be answered with "ANS UTILITY 120.0".
The ups-trust425-625 driver appeared shortly after the release of 0.40.0, marking the first expansion beyond APC hardware.
Over the months that followed, the backupspro driver would be forked from the smartups driver to handle the APC Back-UPS Pro line. Then the backups driver was written to handle the APC Back-UPS contact-closure models. These drivers would later be renamed and recombined, with smartups and backupspro becoming apcsmart, and backups became genericups.
The drivers stored status data in an array. At first, they passed this data to upsd by saving it to a file. upsd would reread this file every few seconds to keep a copy for itself. This was later expanded to allow shared memory mode, where only a stub would remain on the disk. The drivers and server then passed data through the shared memory space.
upsd picked up the ability to monitor multiple drivers on the system, and the "upsname@hostname" scheme was born. Access controls were added, and then the network code was expanded to allow TCP communications, which at this point were on port 3305.
Several visitors to the web page and subscribers to the mailing lists provided suggestions to rename the project. The old name no longer accurately described it, and it was perilously close to APC’s "Smart-UPS" trademark. Rather than risk problems in the future, the name was changed. Kern Sibbald provided the winner: Network UPS Tools, which captures the essence of the project and makes for great short tarball filenames: nut-x.y.z.tar.gz.
The new name was first applied to 0.42.0, released October 31, 1999.
This is also when the web pages moved from the old
http://www.exploits.org/~rkroll/smartupstools/
URL to the replacement
at http://www.exploits.org/nut/
to coincide with the name change.
More drivers were written and the hardware support continued to grow. upsmon picked up the concepts of what is now known as "primary" and "secondary", and could now handle environments where multiple systems get power from a single UPS.
Manager mode was added to allow changing the value of read/write variables in certain UPS models.
Up to this point, all of the drivers compiled into freestanding programs, each providing their own implementation of main(). This meant they all had to check the incoming arguments and act uniformly. Unfortunately, not all of the programs behaved the same way, and it was hard to document and use consistently. It also meant that startup scripts had to be edited depending on what kind of hardware was attached.
Starting in 0.45.0, released June 11, 2001, there was a new common core for
all drivers called main.c
. It provided the main function and called back to
the upsdrv_*
functions provided by the hardware-specific part of the drivers.
This allowed driver authors to focus on the UPS hardware without worrying about
the housekeeping stuff that needs to happen.
This new design provided an obvious way to configure drivers from one file, and
so ups.conf
was born. This eventually spawned upsdrvctl, and now all drivers
based on this common core could be started or stopped with one command. Startup
scripts now could contain "upsdrvctl start", and it didn’t matter what kind of
hardware or how many UPSes you had on one system.
Interestingly, at the end of this month, Arnaud Quette entered the UPS world, as a subcontractor of the now defunct MGE UPS SYSTEMS. This marked the start of a future successful collaboration.
During the 0.45.x series, both the old standalone drivers and the ones which had been converted to the common core were released together. Before the release of 0.50.0 on May 24, 2002, all of the old drivers were removed. While this shrank the list of supported hardware, it set the precedent for removing code which isn’t receiving regular maintenance. The assumption is that the code will be brought back up to date by someone if they actually need it. Otherwise, it’s just dead weight in the tree.
This change meant that all remaining drivers could be controlled with the
upsdrvctl
and ups.conf
, allowing the documentation to be greatly
simplified. There was no longer any reason to say "do this, unless you
have this driver, then do this".
IANA granted an official port number to the project, and the network code
switched to port 3493. It had previously been on 3305 which is assigned to
odette-ftp
. 3305 was probably picked in 1997 because it was the fifth
project to spawn from some common UDP server code.
After 0.50.1, the 0.99 tree was created to provide a tree which would receive nothing but bug fixes in preparation for the release of 1.0. As it turned out, very few things required fixing, and there were only three releases in this tree.
After nearly 5 years of having a 0.x version number, 1.0.0 was released on August 19, 2002. This milestone meant that all of the base features that you would expect to find were intact: good hardware support, a network server with security controls, and system shutdowns that worked.
The design was showing signs of wear from the rapid expansion, but this was intentionally ignored for the moment. The focus was on getting a good version out that would provide a reasonable base while the design issues could be addressed in the future, and I’m confident that we succeeded.
One day after the release of 1.0.0, 1.1.0 started the new development tree.
During that development cycle, the CGI programs were rewritten to use template
files instead of hard-coded HTML, thus bringing back the flexibility of the
original unreleased prototype from 5 years before. The multimon
was removed
from the tree, as the new upsstats
could do both jobs by loading different
templates.
A new client library called upsclient was created, and it replaced upsfetch. This new library only supported TCP connections, and used an opaque context struct to keep state for each connection. As a result, client programs could now do things that used multiple connections without any conflicts. This was done primarily to allow OpenSSL support, but there were other benefits from the redesign.
upsd and the clients could now use OpenSSL for basic authentication and encryption, but this was not included by default. This was provided as a bonus feature for those users who cared to read about it and enable the option, as the initial setup was complex.
After the 1.1 tree was frozen and deemed complete, it became the second stable tree with the release of 1.2.0 on November 5, 2002.
Following an extended period with no development tree, 1.3.0 got things moving again on April 13, 2003. The focus of this tree was to rewrite the driver-server communication layer and replace the static naming scheme for variables and commands.
Up to this point, all variables had names like STATUS, UTILITY, and OUTVOLT. They had been created as drivers were added to the tree, and there was little consistency. For example, it probably should have been INVOLT and OUTVOLT, but there was no OUTVOLT originally, so UTILITY was all we had. This same pattern repeated with ACFREQ — is it incoming or outgoing? — and many more.
To solve this problem, all variables and commands were renamed to a hierarchical scheme that had obvious grouping. STATUS became ups.status. UTILITY turned into input.voltage, and OUTVOLT is output.voltage. ACFREQ is input.frequency, and the new output.frequency is also now supported. Every other variable or command was renamed in this fashion.
These variables had been shared between the drivers and upsd as values. That is, for each name like STATUS, there was a #define somewhere in the tree with an INFO_ prefix that gave it a number. INFO_STATUS was 0x0006, INFO_UTILITY was 0x0004, and so on, with each name having a matching number. This number was stored in an int within a structure which was part of the array that was either written to disk or shared memory.
That structure had several restrictions on expansion and was dropped as the data sharing method between the drivers and the server. It was replaced by a new system of text-based messages over Unix domain sockets. Drivers now accepted a short list of commands from upsd, and would push out updates asynchronously. upsd no longer had to poll the state files or shared memory. It could just select all of the driver and client fds and act on events.
At the same time, the network protocol on port 3493 was overhauled to take advantage of the new naming scheme. The existing "REQ STATUS@su700", "ANS STATUS@su700 OL" scheme was showing signs of age, and it really only supported the UPS name (@su700) as an afterthought. The new protocol would now use commands like GET and LIST, leading to exchanges like "GET VAR su700 ups.status" and "VAR su700 ups.status OL". These responses contain enough data to stand alone, so clients can now handle them asynchronously.
On July 25, 2003, 1.4.0 was released. It contained support for both the old "REQ" style protocol (with names like STATUS), and the new "GET" style protocol (with names like ups.status). This tree is provided to bridge the gap between all of the old releases and the upcoming 2.0.
2.0 will be released without support for the old REQ/STATUS protocol. The hope is that client authors and those who have implemented their own monitoring software will use the 1.4 cycle to change to the new protocol. The 1.4 releases contain a lot of compatibility code to make sure both work at the same time.
1.5.0 forked from 1.4.0 and was released on July 29, 2003. The first changes were to throw out anything which was providing compatibility with the older versions of the software. This means that 1.5 and the eventual 2.0 will not talk to anything older than 1.4.
This tree continues to evolve with new serial routines for the drivers which are intended to replace the aging upscommon code which dates back to the early 0.x releases. The original routines would call alarm and read in a tight loop while fetching characters. The new functions are much cleaner, and wait for data with select. This makes for much cleaner code and easier strace/ktrace logs, since the number of syscalls has been greatly reduced.
There has also been a push to make sure the data from the UPS is well-formed and is actually usable before sending updates out to upsd. This started during 1.3 as drivers were adapted to use the dstate functions and the new variable/command names. Some drivers which were not converted to the new naming scheme or didn’t do sanity checks on the incoming UPS data from the serial port were dropped from the tree.
This tree was released as 2.0.0.
The old network code spans a range from about 0.41.1 when TCP support was introduced up to the recent 1.4 series. It used variable names like STATUS, UTILITY, and LOADPCT. Many of these names go back to the earliest prototypes of this software from 1997. At that point there was no way to know that so many drivers would come along and introduce so many new variables and commands. The resulting mess grew out of control over the years.
During the 1.3 development cycle, all variables and instant commands were renamed to fit into a tree-like structure. There are major groups, like input, output and battery. Members of those groups have been arranged to make sense - input.voltage and output.voltage compliment each other. The old names were UTILITY and OUTVOLT. The benefits in this change are obvious.
The 1.4 clients can talk to either type of server, and can handle either naming scheme. 1.4 servers have a compatibility mode where they can answer queries for both names, even though the drivers are internally using the new format.
When 1.4 clients talk to 1.4 or 2.0 (or more recent) servers, they will use the new names.
Here’s a table to make it easier to visualize:
Server version | ||||
---|---|---|---|---|
Client version | 1.0 | 1.2 | 1.4 | 2.0+ |
1.0 | yes | yes | yes | no |
1.2 | yes | yes | yes | no |
1.4 | yes | yes | yes | yes |
2.0+ | no | no | yes | yes |
Version 2.0, and more recent, do not contain backwards compatibility for the old protocol and variable/command names. As a result, 2.0 clients can’t talk to anything older than a 1.4 server. If you ask a 2.0 client to fetch "STATUS", it will fail. You’ll have to ask for "ups.status" instead.
Authors of separate monitoring programs should have used the 1.4 series to write support for the new variables and command names. Client software can easily support both versions as long as they like. If upsd returns ERR UNKNOWN-COMMAND to a GET request, you need to use REQ.
The bandwidth demands of a project like this have slowly been forcing me to offload certain parts to other servers. The download links have pointed offsite for many months, and other large things like certain UPS protocols have followed. As the traffic grows, it’s clear that having the project attached to exploits.org is not going to work.
The solution was to register a new domain and set up mirrors. There are two
initial web servers, with more on the way. The main project URL has changed
from http://www.exploits.org/nut/
to https://www.networkupstools.org.
The actual content is hosted on various mirrors which are updated regularly
with rsync, so the days of dribbling bits through my DSL should be over.
This is also when all of the web pages were redesigned to have a simpler look with fewer links on the left side. The old web pages used to have 30 or more links on the top page, and most of them vanished when you dropped down one level. The links are now constant on the entire site, and the old links now live in their own groups in separate directories.
The year 2004 was marked by a release slowdown, since Russell was busy with personal subjects. But the patches queue was still growing quickly.
At that time, the development process was still centralized. There was no revision control system (like the current Subversion repository), nor trackers to interact with NUT development. Russell was receiving all the patches and requests, and doing all the work on his own, including releases.
Russell was more and more thinking about giving the project leadership to Arnaud Quette, which finally happened with the 2.0.1 release in February 2005.
This marked a new era for NUT…
First, Arnaud aimed at opening up the development by creating a project on the Debian Alioth Forge. This allowed to build the team of hackers that Russell dreamed about. It also allows to ensure NUT’s continuation, whatever happens to the leader. And that would most of all boost the projects contributions.