Skip to content

Commit f04db0c

Browse files
authored
Merge pull request #2753 from jimklimov/issue-1803
Revise `upslog` service integration, allow to limit loop count, use it in NIT
2 parents 8bc2bdd + 1d8bf92 commit f04db0c

File tree

7 files changed

+96
-13
lines changed

7 files changed

+96
-13
lines changed

NEWS.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ https://github.com/networkupstools/nut/milestone/11
309309
as "OTHER" notification type (whenever the set of such tokens appears
310310
or changes) or "NOTOTHER" when they disappear. [#415]
311311
312+
- upslog:
313+
* Added support for limiting the loop count. Using in NIT (NUT Integration
314+
Test) suite for double profit (checking the tool and fallback in NIT).
315+
* Added systemd and SMF service integration. [#1803]
316+
312317
- More systemd integration:
313318
* Introduced a `nut-sleep.service` unit which stops `nut.target` when a
314319
system sleep was requested, and starts it when the sleep is finished.

UPGRADING.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ Changes from 2.8.2 to 2.8.3
7070
For fallback with older systemd, a `nut-sleep.service` is provided now.
7171
[#1070, #2596, #2597]
7272
73+
- Added systemd and SMF service integration for `upslog` as a `nut-logger`
74+
service (disabled by default, needs a `upslog.conf` file to deliver the
75+
`UPSLOG_ARGS=...` setting for actual monitoring and logging). [#1803]
76+
7377
- Handling of per-UPS `ALARM` state was introduced to `upsmon`, allowing it
7478
to optionally treat it as a factor in deciding that the device is in a
7579
"critical" state (polled more often, assumed dead if communications are

clients/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ upsc_SOURCES = upsc.c upsclient.h
7979
upscmd_SOURCES = upscmd.c upsclient.h
8080
upsrw_SOURCES = upsrw.c upsclient.h
8181
upslog_SOURCES = upslog.c upsclient.h upslog.h
82+
upslog_LDADD = $(LDADD_FULL)
8283
upsmon_SOURCES = upsmon.c upsmon.h upsclient.h
8384
upsmon_LDADD = $(LDADD_FULL)
8485
if HAVE_WINDOWS_SOCKETS

clients/upslog.c

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@
3939
#include "timehead.h"
4040
#include "nut_stdint.h"
4141
#include "upslog.h"
42+
#include "str.h"
4243

4344
#ifdef WIN32
4445
#include "wincompat.h"
4546
#endif
4647

4748
static int reopen_flag = 0, exit_flag = 0;
49+
static size_t max_loops = 0;
4850
static char *upsname;
4951
static UPSCONN_t *ups;
5052

@@ -78,7 +80,8 @@ static void reopen_log(void)
7880
{
7981
for (monhost_ups_current = monhost_ups_anchor;
8082
monhost_ups_current != NULL;
81-
monhost_ups_current = monhost_ups_current->next) {
83+
monhost_ups_current = monhost_ups_current->next
84+
) {
8285
if (monhost_ups_current->logfile == stdout) {
8386
upslogx(LOG_INFO, "logging to stdout");
8487
return;
@@ -153,6 +156,7 @@ static void help(const char *prog)
153156
printf(" -f <format> - Log format. See below for details.\n");
154157
printf(" - Use -f \"<format>\" so your shell doesn't break it up.\n");
155158
printf(" -i <interval> - Time between updates, in seconds\n");
159+
printf(" -d <count> - Exit after specified amount of updates\n");
156160
printf(" -l <logfile> - Log file name, or - for stdout (foreground by default)\n");
157161
printf(" -F - stay foregrounded even if logging into a file\n");
158162
printf(" -B - stay backgrounded even if logging to stdout\n");
@@ -434,7 +438,7 @@ static void run_flist(struct monhost_ups *monhost_ups_print)
434438
int main(int argc, char **argv)
435439
{
436440
int interval = 30, i, foreground = -1;
437-
size_t monhost_len = 0;
441+
size_t monhost_len = 0, loop_count = 0;
438442
const char *prog = xbasename(argv[0]);
439443
time_t now, nextpoll = 0;
440444
const char *user = NULL;
@@ -446,7 +450,7 @@ int main(int argc, char **argv)
446450

447451
print_banner_once(prog, 0);
448452

449-
while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FBm:")) != -1) {
453+
while ((i = getopt(argc, argv, "+hs:l:i:d:f:u:Vp:FBm:")) != -1) {
450454
switch(i) {
451455
case 'h':
452456
help(prog);
@@ -501,6 +505,31 @@ int main(int argc, char **argv)
501505
interval = atoi(optarg);
502506
break;
503507

508+
case 'd':
509+
{ /* scoping */
510+
unsigned long ul = 0;
511+
if (str_to_ulong(optarg, &ul, 10)) {
512+
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
513+
# pragma GCC diagnostic push
514+
#endif
515+
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS
516+
# pragma GCC diagnostic ignored "-Wtype-limits"
517+
#endif
518+
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE
519+
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
520+
#endif
521+
if (ul < SIZE_MAX)
522+
max_loops = (size_t)ul;
523+
else
524+
upslogx(LOG_ERR, "Invalid max loops");
525+
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
526+
# pragma GCC diagnostic pop
527+
#endif
528+
} else
529+
upslogx(LOG_ERR, "Invalid max loops");
530+
}
531+
break;
532+
504533
case 'f':
505534
logformat = optarg;
506535
break;
@@ -594,7 +623,8 @@ int main(int argc, char **argv)
594623

595624
for (monhost_ups_current = monhost_ups_anchor;
596625
monhost_ups_current != NULL;
597-
monhost_ups_current = monhost_ups_current->next) {
626+
monhost_ups_current = monhost_ups_current->next
627+
) {
598628
printf("logging status of %s to %s (%is intervals)\n",
599629
monhost_ups_current->monhost, monhost_ups_current->logfn, interval);
600630
if (upscli_splitname(monhost_ups_current->monhost, &(monhost_ups_current->upsname), &(monhost_ups_current->hostname), &(monhost_ups_current->port)) != 0) {
@@ -668,7 +698,8 @@ int main(int argc, char **argv)
668698

669699
for (monhost_ups_current = monhost_ups_anchor;
670700
monhost_ups_current != NULL;
671-
monhost_ups_current = monhost_ups_current->next) {
701+
monhost_ups_current = monhost_ups_current->next
702+
) {
672703
ups = monhost_ups_current->ups; /* XXX Not ideal */
673704
upsname = monhost_ups_current->upsname; /* XXX Not ideal */
674705
/* reconnect if necessary */
@@ -683,14 +714,23 @@ int main(int argc, char **argv)
683714
upscli_disconnect(ups);
684715
}
685716
}
717+
718+
if (max_loops > 0) {
719+
loop_count++;
720+
if (loop_count >= max_loops || loop_count > (SIZE_MAX - 1)) {
721+
upslogx(LOG_INFO, "%" PRIuSIZE " loops have elapsed", max_loops);
722+
exit_flag = 1;
723+
}
724+
}
686725
}
687726

688727
upslogx(LOG_INFO, "Signal %d: exiting", exit_flag);
689728
upsnotify(NOTIFY_STATE_STOPPING, "Signal %d: exiting", exit_flag);
690729

691730
for (monhost_ups_current = monhost_ups_anchor;
692731
monhost_ups_current != NULL;
693-
monhost_ups_current = monhost_ups_current->next) {
732+
monhost_ups_current = monhost_ups_current->next
733+
) {
694734

695735
if (monhost_ups_current->logfile != stdout)
696736
fclose(monhost_ups_current->logfile);

docs/man/upslog.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ Wait this many seconds between polls. This defaults to 30 seconds.
7171
If you require tighter timing, you should write your own logger using
7272
the linkman:upsclient[3] library.
7373

74+
*-d* 'count'::
75+
76+
Exit after specified amount of updates. Default is 0 for infinite loop
77+
(until interrupted otherwise).
78+
7479
*-l* 'logfile'::
7580

7681
Store the results in this file.

scripts/systemd/nut-logger.service.in

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ Wants=nut-server.service
2323
# Requires=network-online.target
2424
# After=network-online.target
2525
PartOf=nut.target
26-
Before=nut.target ### not enabled by default, but ordered if enabled by user
26+
### not enabled by default, but ordered if enabled by user:
27+
Before=nut.target
2728

2829
Documentation=man:upslog(8)
2930
Documentation=@NUT_WEBSITE_BASE@/docs/man/upslog.html
@@ -40,10 +41,12 @@ EnvironmentFile=-@CONFPATH@/nut.conf
4041
EnvironmentFile=@CONFPATH@/upslog.conf
4142
SyslogIdentifier=%N
4243
ExecStartPre=-@SYSTEMD_TMPFILES_PROGRAM@ --create @systemdtmpfilesdir@/nut-common-tmpfiles.conf
43-
ExecStartPre=/bin/test -n "${UPSLOG_ARGS-}"
44-
ExecStart=@SBINDIR@/upslog @SYSTEMD_DAEMON_ARGS_UPSLOG@ $UPSLOG_ARGS
44+
ExecStartPre=/bin/test -n "${UPSLOG_ARGS}"
45+
ExecStart=@BINDIR@/upslog @SYSTEMD_DAEMON_ARGS_UPSLOG@ $UPSLOG_ARGS
4546
# NOTE: SIGHUP is supported to re-open the log file,
46-
# which is the default systemd ReloadSignal
47+
# which is the default systemd ReloadSignal (only
48+
# sent by systemd 253 and newer)
49+
ExecReload=/bin/kill -HUP $MAINPID
4750
PIDFile=@PIDPATH@/upslog.pid
4851
# With this program, the PID file always exists and "kill -TERM" in particular
4952
# can be used from command-line or some legacy scripts, it causes a clean and

tests/NIT/nit.sh

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
# ksh, busybox sh...)
3535
#
3636
# Copyright
37-
# 2022-2024 Jim Klimov <jimklimov+nut@gmail.com>
37+
# 2022-2025 Jim Klimov <jimklimov+nut@gmail.com>
3838
#
3939
# License: GPLv2+
4040

@@ -356,6 +356,11 @@ if [ "`id -u`" = 0 ]; then
356356
fi
357357

358358
stop_daemons() {
359+
if [ -n "$PID_UPSMON" ] ; then
360+
log_info "Stopping test daemons: upsmon via command"
361+
upsmon -c stop
362+
fi
363+
359364
if [ -n "$PID_UPSD$PID_UPSMON$PID_DUMMYUPS$PID_DUMMYUPS1$PID_DUMMYUPS2" ] ; then
360365
log_info "Stopping test daemons"
361366
kill -15 $PID_UPSD $PID_UPSMON $PID_DUMMYUPS $PID_DUMMYUPS1 $PID_DUMMYUPS2 2>/dev/null || return 0
@@ -1189,7 +1194,17 @@ testcase_sandbox_upsc_query_bogus() {
11891194
testcase_sandbox_upsc_query_timer() {
11901195
log_separator
11911196
log_info "[testcase_sandbox_upsc_query_timer] Test that dummy-ups TIMER action changes the reported state"
1192-
# Driver is set up to flip ups.status every 5 sec, so check every 3
1197+
1198+
# Driver is set up to flip ups.status every 5 sec, so check every 3 sec
1199+
# with upsc, but we can follow with upslog more intensively. New process
1200+
# launches can lag a lot on very busy SUTs; hopefully still-running ones
1201+
# are more responsive in this regard.
1202+
log_info "Starting upslog daemon"
1203+
rm -f "${NUT_STATEPATH}/upslog-dummy.log" || true
1204+
# Start as foregrounded always, so we have a PID to kill easily:
1205+
upslog -F -i 1 -d 30 -m "dummy@localhost:${NUT_PORT},${NUT_STATEPATH}/upslog-dummy.log" &
1206+
PID_UPSLOG="$!"
1207+
11931208
# TODO: Any need to convert to runcmd()?
11941209
OUT1="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "[testcase_sandbox_upsc_query_timer] upsd does not respond on port ${NUT_PORT} ($?): $OUT1" ; sleep 3
11951210
OUT2="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "[testcase_sandbox_upsc_query_timer] upsd does not respond on port ${NUT_PORT} ($?): $OUT2"
@@ -1211,14 +1226,24 @@ testcase_sandbox_upsc_query_timer() {
12111226
fi
12121227
fi
12131228
fi
1214-
if echo "$OUT1$OUT2$OUT3$OUT4$OUT5" | grep "OB" && echo "$OUT1$OUT2$OUT3$OUT4$OUT5" | grep "OL" ; then
1229+
1230+
log_info "Stopping upslog daemon"
1231+
kill -15 $PID_UPSLOG 2>/dev/null || true
1232+
wait $PID_UPSLOG || true
1233+
1234+
if (grep " [OB] " "${NUT_STATEPATH}/upslog-dummy.log" && grep " [OL] " "${NUT_STATEPATH}/upslog-dummy.log") \
1235+
|| (grep " \[OB\] " "${NUT_STATEPATH}/upslog-dummy.log" && grep " \[OL\] " "${NUT_STATEPATH}/upslog-dummy.log") \
1236+
|| (echo "$OUT1$OUT2$OUT3$OUT4$OUT5" | grep "OB" && echo "$OUT1$OUT2$OUT3$OUT4$OUT5" | grep "OL") \
1237+
; then
12151238
log_info "[testcase_sandbox_upsc_query_timer] PASSED: ups.status flips over time"
12161239
PASSED="`expr $PASSED + 1`"
12171240
else
12181241
log_error "[testcase_sandbox_upsc_query_timer] ups.status did not flip over time"
12191242
FAILED="`expr $FAILED + 1`"
12201243
FAILED_FUNCS="$FAILED_FUNCS testcase_sandbox_upsc_query_timer"
12211244
fi
1245+
1246+
#rm -f "${NUT_STATEPATH}/upslog-dummy.log" || true
12221247
}
12231248

12241249
isTestablePython() {

0 commit comments

Comments
 (0)