Skip to content

Commit

Permalink
clients/upslog.c, docs/man/upslog.txt, NEWS.adoc: handle "*" as UPS n…
Browse files Browse the repository at this point in the history
…ame to query for currently served devices

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
  • Loading branch information
jimklimov committed Jan 6, 2025
1 parent d80e8fb commit 67096d3
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
2 changes: 2 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ https://github.com/networkupstools/nut/milestone/11
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.
* The `upsname` in the `system=upsname[@hostname[:port]]` parameter may
be an asterisk `*` to query for devices currently served by the hostname.
* Same log file may safely be used in different logging tuples (it is
then recommended to use `%UPSHOST%` in a custom formatting string).
* Fixed printing of `%UPSHOST%` when multiple systems are being logged.
Expand Down
109 changes: 108 additions & 1 deletion clients/upslog.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ static void reopen_log(void)
p != NULL;
p = p->next
) {
/* Never opened, e.g. removed asterisk entry */
if (!p->logfile)
continue;

if (p->logfile == stdout) {
upslogx(LOG_INFO, "logging to stdout");
continue;
Expand Down Expand Up @@ -693,7 +697,7 @@ int main(int argc, char **argv)
fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s <system> -l <logfile>, or use -m <ups,logfile>");

/* Split the system specs in a common fashion for tuples and legacy args */
for (monhost_ups_current = monhost_ups_anchor;
for (monhost_ups_current = monhost_ups_anchor, monhost_ups_prev = NULL;
monhost_ups_current != NULL;
monhost_ups_current = monhost_ups_current->next
) {
Expand All @@ -707,8 +711,111 @@ int main(int argc, char **argv)
NUT_STRARG(monhost_ups_current->hostname),
monhost_ups_current->port
);

/* Revise the list if some UPS name was an asterisk
* (query the data server) */
if (!strcmp(monhost_ups_current->upsname, "*")) {
/* following list_upses() from upsc.c */
int ret;
size_t numq, numa, found = 0;
const char *query[4];
char **answer;
UPSCONN_t *conn = NULL;

query[0] = "UPS";
numq = 1;

upslogx(LOG_INFO, "Querying %s:%" PRIu16 " for currently served devices",
NUT_STRARG(monhost_ups_current->hostname),
monhost_ups_current->port
);

conn = xmalloc(sizeof(*conn));
if (upscli_connect(conn, monhost_ups_current->hostname, monhost_ups_current->port, UPSCLI_CONN_TRYSSL) < 0) {
fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(conn));
}

ret = upscli_list_start(conn, numq, query);
if (ret < 0) {
/* check for an old upsd */
if (upscli_upserror(conn) == UPSCLI_ERR_UNKCOMMAND) {
fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query");
}

fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(conn));
}

while (upscli_list_next(conn, numq, query, &numa, &answer) == 1) {
struct monhost_ups *mu = NULL;
char buf[LARGEBUF];

/* UPS <upsname> <description> */
if (numa < 3) {
fatalx(EXIT_FAILURE, "Error: insufficient data (got %" PRIuSIZE " args, need at least 3)", numa);
}

found++;
upsdebugx(1, "FOUND: %s: %s", answer[1], answer[2]);

mu = xmalloc(sizeof(struct monhost_ups));
snprintf(buf, sizeof(buf), "%s@%s:%" PRIu16,
answer[1],
monhost_ups_current->hostname,
monhost_ups_current->port);
mu->monhost = xstrdup(buf);
mu->upsname = xstrdup(answer[1]);
mu->hostname = xstrdup(monhost_ups_current->hostname);
mu->port = monhost_ups_current->port;
mu->ups = NULL;
mu->logtarget = monhost_ups_current->logtarget;
mu->next = monhost_ups_current->next;
monhost_ups_current->next = mu;
monhost_len++;
}

upscli_disconnect(conn);
free(conn);
conn = NULL;

if (!found) {
upslogx(LOG_WARNING, "Data server at %s:%" PRIu16
" does not currently serve any devices",
NUT_STRARG(monhost_ups_current->hostname),
monhost_ups_current->port
);
}

/* Remove the entry with asterisk */
if (monhost_ups_prev) {
monhost_ups_prev->next = monhost_ups_current->next;
/* monhost_ups_prev remains as it was */
free(monhost_ups_current);
monhost_ups_current = monhost_ups_prev;
} else {
/* This is the first entry, anchor */
monhost_ups_anchor = monhost_ups_current->next;
monhost_ups_prev = NULL;
free(monhost_ups_current);
monhost_ups_current = monhost_ups_anchor;
}
monhost_len--;

if (!monhost_ups_current || !monhost_len) {
/* Our list ended up empty,
* no "next" to loop into */
fatalx(EXIT_FAILURE, "Queries failed to find anything");
}
} else {
/* No asterisk, usual spec */
monhost_ups_prev = monhost_ups_current;
}
}

/* might happen if we only queried remote hosts and found nothing,
* just in case we missed something above */
if (!monhost_len || !monhost_ups_anchor)
fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s <system> -l <logfile>, or use -m <ups,logfile>");

/* Report the logged systems, open the log files as needed */
for (monhost_ups_current = monhost_ups_anchor;
monhost_ups_current != NULL;
Expand Down
4 changes: 4 additions & 0 deletions docs/man/upslog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ upslog will run in the background, regardless of logging target or debugging.
Monitor this UPS. The format for this option is
+upsname[@hostname[:port]]+. The default hostname is "localhost".
+
The upsname may be an asterisk `*` to query UPSes currently served by hostname.
+
Requires that the `-l <logfile>` option is also used for the single-system
logging. Can be used with the `-m <tuple>`, will be added to the list.

Expand All @@ -108,6 +110,8 @@ specification, separated by commas. An example would be:
upsname@hostname:9999,/var/log/nut/cps.log
----
+
The upsname may be an asterisk `*` to query UPSes currently served by hostname.
+
Tuples may specify `-` as the logfile, to emit messages on `stdout`
(e.g. to be collected by the system journal for services).
+
Expand Down

0 comments on commit 67096d3

Please sign in to comment.