Skip to content

Commit

Permalink
nut-scanner: detect and configure NUT simulation devices (#2246)
Browse files Browse the repository at this point in the history
* nut-scanner: detect and configure NUT simlation devices

Provide an additional nut-scanner "-n | --nut_simulation_scan"
option to detect and configure dummy simulation (.dev & .seq)
from the default $sysconfdir.

Also advertise NUT Simulation Devices in HCL.

This should standardize and streamline the use of nut-scanner
as an automatic detection and configuration tool.

Closes: #/issues/2242

Signed-off-by: Arnaud Quette <[email protected]>
  • Loading branch information
aquette authored Dec 22, 2023
1 parent e70e8dd commit 3eb96fe
Show file tree
Hide file tree
Showing 16 changed files with 241 additions and 11 deletions.
2 changes: 2 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ https://github.com/networkupstools/nut/milestone/10
* Added generation of FreeBSD/pfSense quirks for USB devices supported
by NUT (may get installed to `$datadir` e.g. `/usr/local/share/nut`
and need to be pasted into your `/boot/loader.conf.local`). [#2159]
* nut-scanner can now discover NUT simulated devices (.dev & .seq files)
located in your sysconfig directory
* nut-scanner now report 'dummy-ups' as driver when scanning NUT with
Old or Avahi method.

Expand Down
1 change: 1 addition & 0 deletions data/driver.list.in
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,7 @@
"Numeric" "ups" "2" "Digital 800 plus" "USB" "nutdrv_qx or blazer_usb"

"NUT" "ups" "5" "all supported NUT devices, through remote upsd" "" "dummy-ups"
"NUT" "ups" "5" "Simulated devices" "" "dummy-ups"

"Oneac" "ups" "1" "ON400" "advanced interface" "oneac"
"Oneac" "ups" "1" "ON600" "advanced interface" "oneac"
Expand Down
11 changes: 11 additions & 0 deletions docs/developer-guide.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ Here is an example to setup a device simulation:

For more information, refer to linkman:dummy-ups[8] manual page.

[[dev-simu-disco]]

Simulated devices discovery
---------------------------

Any simulation file that is saved in the sysconfig directory can be
automatically discovered and configured using nut-scanner:
+
$ nut-scanner -n
$ nut-scanner --nut_simulation_scan
+

[[dev-recording]]

Expand Down
3 changes: 3 additions & 0 deletions docs/man/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ SRC_DEV_PAGES = \
nutscan_scan_usb.txt \
nutscan_scan_xml_http_range.txt \
nutscan_scan_nut.txt \
nutscan_scan_nut_simulation.txt \
nutscan_scan_avahi.txt \
nutscan_scan_ipmi.txt \
nutscan_scan_eaton_serial.txt \
Expand Down Expand Up @@ -291,6 +292,7 @@ MAN3_DEV_PAGES = \
nutscan_scan_usb.3 \
nutscan_scan_xml_http_range.3 \
nutscan_scan_nut.3 \
nutscan_scan_nut_simulation.3 \
nutscan_scan_avahi.3 \
nutscan_scan_ipmi.3 \
nutscan_scan_eaton_serial.3 \
Expand Down Expand Up @@ -360,6 +362,7 @@ HTML_DEV_MANS = \
nutscan_scan_usb.html \
nutscan_scan_xml_http_range.html \
nutscan_scan_nut.html \
nutscan_scan_nut_simulation.html \
nutscan_scan_avahi.html \
nutscan_scan_ipmi.html \
nutscan_scan_eaton_serial.html \
Expand Down
3 changes: 3 additions & 0 deletions docs/man/nut-scanner.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ interfaces to retrieve XML/HTTP capable devices. No IP required in this mode.
*-O* | *--oldnut_scan*::
Scan NUT devices (i.e. upsd daemon) on IP ranging from 'start IP' to 'end IP'.

*-n* | *--nut_simulation_scan*::
Scan NUT simulated devices (.dev files in $CONFPATH).

*-A* | *--avahi_scan*::
Scan NUT servers using Avahi request on the current network interfaces.
No IP required.
Expand Down
7 changes: 4 additions & 3 deletions docs/man/nutscan_init.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ This depends on the libraries installed on the system:
nutscan_avail_avahi = 1 : AVAHI scan is available
nutscan_avail_ipmi = 1 : IPMI scan is available
nutscan_avail_nut = 1 : Old NUT method is available
nutscan_avail_nut_simulation = 1 : NUT simulation devices method is available
nutscan_avail_snmp = 1 : SNMP method is available
nutscan_avail_usb = 1 : USB method is available
nutscan_avail_xml_http = 1 : XML HTTP method is available
Expand All @@ -44,9 +45,9 @@ SEE ALSO

linkman:nutscan_init[3], linkman:nutscan_scan_usb[3],
linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_xml_http_range[3],
linkman:nutscan_scan_nut[3], linkman:nutscan_scan_avahi[3],
linkman:nutscan_scan_ipmi[3], linkman:nutscan_display_ups_conf[3],
linkman:nutscan_display_sanity_check[3],
linkman:nutscan_scan_nut[3], linkman:nutscan_scan_nut_simulation[3],
linkman:nutscan_scan_avahi[3], linkman:nutscan_scan_ipmi[3],
linkman:nutscan_display_ups_conf[3], linkman:nutscan_display_sanity_check[3],
linkman:nutscan_display_sanity_check_serial[3],
linkman:nutscan_display_ups_conf_with_sanity_check[3],
linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3],
Expand Down
47 changes: 47 additions & 0 deletions docs/man/nutscan_scan_nut_simulation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
NUTSCAN_SCAN_NUT_SIMULATION(3)
==============================

NAME
----

nutscan_scan_nut_simulation - Scan your sysconfig directory for NUT simulation devices.

SYNOPSIS
--------

#include <nut-scan.h>
#include <unistd.h> /* useconds_t */

nutscan_device_t * nutscan_scan_nut_simulation();

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

The *nutscan_scan_nut_simulation()* function try to detect available NUT
simulation devices, by finding .dev and .seq files in your sysconfig
directory.

You MUST call linkman:nutscan_init[3] before using this function.

RETURN VALUE
------------

The *nutscan_scan_nut_simulation()* function returns a pointer to a
`nutscan_device_t` structure containing all found devices or NULL if an
error occurs or no device is found.

SEE ALSO
--------

linkman:nutscan_init[3],
linkman:nutscan_scan_usb[3], linkman:nutscan_scan_xml_http_range[3],
linkman:nutscan_scan_snmp[3], linkman:nutscan_scan_avahi[3],
linkman:nutscan_scan_ipmi[3], linkman:nutscan_scan_nut[3],
linkman:nutscan_display_sanity_check[3],
linkman:nutscan_display_sanity_check_serial[3],
linkman:nutscan_display_ups_conf_with_sanity_check[3],
linkman:nutscan_display_ups_conf[3],
linkman:nutscan_display_parsable[3], linkman:nutscan_new_device[3],
linkman:nutscan_free_device[3], linkman:nutscan_add_option_to_device[3],
linkman:nutscan_add_device_to_device[3], linkman:nutscan_scan_eaton_serial[3],
linkman:nutscan_cidr_to_ip[3]
2 changes: 1 addition & 1 deletion tools/nut-scanner/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ if WITH_NUT_SCANNER
bin_PROGRAMS = nut-scanner
lib_LTLIBRARIES = libnutscan.la
endif
libnutscan_la_SOURCES = scan_nut.c scan_ipmi.c \
libnutscan_la_SOURCES = scan_nut.c scan_nut_simulation.c scan_ipmi.c \
nutscan-device.c nutscan-ip.c nutscan-display.c \
nutscan-init.c scan_usb.c scan_snmp.c scan_xml_http.c \
scan_avahi.c scan_eaton_serial.c nutscan-serial.c
Expand Down
6 changes: 4 additions & 2 deletions tools/nut-scanner/nut-scan.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/*
* Copyright (C)
* 2011 - EATON
* 2012 - Arnaud Quette <[email protected]>
* 2012 - 2024 Arnaud Quette <[email protected]>
* 2016 - EATON - IP addressed XML scan
* 2016-2021 - EATON - Various threads-related improvements
* 2016 - 2021 - EATON - Various threads-related improvements
* 2023 - Jim Klimov <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -155,6 +155,8 @@ nutscan_device_t * nutscan_scan_xml_http_range(const char *start_ip, const char

nutscan_device_t * nutscan_scan_nut(const char * startIP, const char * stopIP, const char * port, useconds_t usec_timeout);

nutscan_device_t * nutscan_scan_nut_simulation();

nutscan_device_t * nutscan_scan_avahi(useconds_t usec_timeout);

nutscan_device_t * nutscan_scan_ipmi(const char * startIP, const char * stopIP, nutscan_ipmi_t * sec);
Expand Down
46 changes: 43 additions & 3 deletions tools/nut-scanner/nut-scanner.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011 - 2012 Arnaud Quette <[email protected]>
* Copyright (C) 2011 - 2024 Arnaud Quette <[email protected]>
* Copyright (C) 2016 Michal Vyskocil <[email protected]>
* Copyright (C) 2016 - 2023 Jim Klimov <[email protected]>
*
Expand Down Expand Up @@ -61,7 +61,7 @@

#define ERR_BAD_OPTION (-1)

static const char optstring[] = "?ht:T:s:e:E:c:l:u:W:X:w:x:p:b:B:d:L:CUSMOAm:QNPqIVaD";
static const char optstring[] = "?ht:T:s:e:E:c:l:u:W:X:w:x:p:b:B:d:L:CUSMOAm:QnNPqIVaD";

#ifdef HAVE_GETOPT_LONG
static const struct option longopts[] = {
Expand Down Expand Up @@ -89,6 +89,7 @@ static const struct option longopts[] = {
{ "xml_scan", no_argument, NULL, 'M' },
{ "oldnut_scan", no_argument, NULL, 'O' },
{ "avahi_scan", no_argument, NULL, 'A' },
{ "nut_simulation_scan", no_argument, NULL, 'n' },
{ "ipmi_scan", no_argument, NULL, 'I' },
{ "disp_nut_conf_with_sanity_check", no_argument, NULL, 'Q' },
{ "disp_nut_conf", no_argument, NULL, 'N' },
Expand Down Expand Up @@ -147,6 +148,14 @@ static void * run_nut_old(void *arg)
return NULL;
}

static void * run_nut_simulation(void *arg)
{
NUT_UNUSED_VARIABLE(arg);

dev[TYPE_NUT_SIMULATION] = nutscan_scan_nut_simulation();
return NULL;
}

static void * run_avahi(void *arg)
{
NUT_UNUSED_VARIABLE(arg);
Expand Down Expand Up @@ -203,6 +212,7 @@ static void show_usage(void)
} else {
printf("* Options for NUT devices (avahi method) scan not enabled: library not detected.\n");
}
printf(" -n, --nut_simulation_scan: Scan for NUT simulated devices (.dev files in $CONFPATH).\n");
if (nutscan_avail_ipmi) {
printf(" -I, --ipmi_scan: Scan IPMI devices.\n");
} else {
Expand Down Expand Up @@ -360,6 +370,7 @@ int main(int argc, char *argv[])
int allow_snmp = 0;
int allow_xml = 0;
int allow_oldnut = 0;
int allow_nut_simulation = 0;
int allow_avahi = 0;
int allow_ipmi = 0;
int allow_eaton_serial = 0; /* MUST be requested explicitly! */
Expand Down Expand Up @@ -641,6 +652,9 @@ int main(int argc, char *argv[])
}
allow_avahi = 1;
break;
case 'n':
allow_nut_simulation = 1;
break;
case 'I':
if (!nutscan_avail_ipmi) {
goto display_help;
Expand Down Expand Up @@ -737,7 +751,7 @@ int main(int argc, char *argv[])
upsdebugx(1, "Extracted IP address range from CIDR net/mask: %s => %s", start_ip, end_ip);
}

if (!allow_usb && !allow_snmp && !allow_xml && !allow_oldnut &&
if (!allow_usb && !allow_snmp && !allow_xml && !allow_oldnut && !allow_nut_simulation &&
!allow_avahi && !allow_ipmi && !allow_eaton_serial
) {
allow_all = 1;
Expand All @@ -748,6 +762,7 @@ int main(int argc, char *argv[])
allow_snmp = 1;
allow_xml = 1;
allow_oldnut = 1;
allow_nut_simulation = 1;
allow_avahi = 1;
allow_ipmi = 1;
/* BEWARE: allow_all does not include allow_eaton_serial! */
Expand Down Expand Up @@ -832,6 +847,22 @@ int main(int argc, char *argv[])
upsdebugx(1, "NUT bus (old) SCAN: not requested, SKIPPED");
}

if (allow_nut_simulation && nutscan_avail_nut_simulation) {
upsdebugx(quiet, "Scanning NUT simulation devices.");
#ifdef HAVE_PTHREAD
upsdebugx(1, "NUT simulation devices SCAN: starting pthread_create with run_nut_simulation...");
if (pthread_create(&thread[TYPE_NUT_SIMULATION], NULL, run_nut_simulation, NULL)) {
upsdebugx(1, "pthread_create returned an error; disabling this scan mode");
nutscan_avail_nut_simulation = 0;
}
#else
upsdebugx(1, "NUT simulation devices SCAN: no pthread support, starting nutscan_scan_nut_simulation...");
dev[TYPE_NUT_SIMULATION] = nutscan_scan_nut_simulation(timeout);
#endif /* HAVE_PTHREAD */
} else {
upsdebugx(1, "NUT simulation devices SCAN: not requested, SKIPPED");
}

if (allow_avahi && nutscan_avail_avahi) {
upsdebugx(quiet, "Scanning NUT bus (avahi method).");
#ifdef HAVE_PTHREAD
Expand Down Expand Up @@ -898,6 +929,10 @@ int main(int argc, char *argv[])
upsdebugx(1, "NUT bus (old) SCAN: join back the pthread");
pthread_join(thread[TYPE_NUT], NULL);
}
if (allow_nut_simulation && nutscan_avail_nut_simulation && thread[TYPE_NUT_SIMULATION]) {
upsdebugx(1, "NUT simulation devices SCAN: join back the pthread");
pthread_join(thread[TYPE_NUT_SIMULATION], NULL);
}
if (allow_avahi && nutscan_avail_avahi && thread[TYPE_AVAHI]) {
upsdebugx(1, "NUT bus (avahi) SCAN: join back the pthread");
pthread_join(thread[TYPE_AVAHI], NULL);
Expand Down Expand Up @@ -934,6 +969,11 @@ int main(int argc, char *argv[])
upsdebugx(1, "SCANS DONE: free resources: NUT bus (old)");
nutscan_free_device(dev[TYPE_NUT]);

upsdebugx(1, "SCANS DONE: display results: NUT simulation devices");
display_func(dev[TYPE_NUT_SIMULATION]);
upsdebugx(1, "SCANS DONE: free resources: NUT simulation devices");
nutscan_free_device(dev[TYPE_NUT_SIMULATION]);

upsdebugx(1, "SCANS DONE: display results: NUT bus (avahi)");
display_func(dev[TYPE_AVAHI]);
upsdebugx(1, "SCANS DONE: free resources: NUT bus (avahi)");
Expand Down
3 changes: 3 additions & 0 deletions tools/nut-scanner/nutscan-device.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2011 - 2024 Arnaud Quette (Design and part of implementation)
* Copyright (C) 2011 - EATON
*
* This program is free software; you can redistribute it and/or modify
Expand All @@ -19,6 +20,7 @@
/*! \file nutscan-device.c
\brief manipulation of a container describing a NUT device
\author Frederic Bohe <[email protected]>
\author Arnaud Quette <[email protected]>
*/
#include "config.h" /* must be the first header */

Expand All @@ -32,6 +34,7 @@ const char * nutscan_device_type_strings[TYPE_END - 1] = {
"SNMP",
"XML",
"NUT",
"NUT_SIMULATION",
"IPMI",
"Avahi",
"serial",
Expand Down
3 changes: 3 additions & 0 deletions tools/nut-scanner/nutscan-device.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2011 - 2024 Arnaud Quette (Design and part of implementation)
* Copyright (C) 2011 - EATON
*
* This program is free software; you can redistribute it and/or modify
Expand All @@ -19,6 +20,7 @@
/*! \file nutscan-device.h
\brief definition of a container describing a NUT discovered device
\author Frederic Bohe <[email protected]>
\author Arnaud Quette <[email protected]>
*/

#ifndef SCAN_DEVICE
Expand Down Expand Up @@ -46,6 +48,7 @@ typedef enum nutscan_device_type {
TYPE_SNMP,
TYPE_XML,
TYPE_NUT,
TYPE_NUT_SIMULATION,
TYPE_IPMI,
TYPE_AVAHI,
TYPE_EATON_SERIAL,
Expand Down
8 changes: 8 additions & 0 deletions tools/nut-scanner/nutscan-init.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2011 - 2024 Arnaud Quette (Design and part of implementation)
* Copyright (C) 2011-2021 - EATON
*
* This program is free software; you can redistribute it and/or modify
Expand All @@ -20,6 +21,7 @@
\brief init functions for nut scanner library
\author Frederic Bohe <[email protected]>
\author Arnaud Quette <[email protected]>
\author Arnaud Quette <[email protected]>
*/

#include "common.h"
Expand All @@ -39,6 +41,7 @@
int nutscan_avail_avahi = 0;
int nutscan_avail_ipmi = 0;
int nutscan_avail_nut = 0;
int nutscan_avail_nut_simulation = 1;
#ifdef WITH_SNMP_STATIC
int nutscan_avail_snmp = 1;
#else
Expand Down Expand Up @@ -357,6 +360,11 @@ void nutscan_init(void)
__func__, nutscan_avail_nut ? "succeeded" : "failed", "NUT Client library");
/* end of libupsclient for "old NUT" (vs. Avahi) protocol */


/* start of "NUT Simulation" - unconditional */
/* no need for additional library */
nutscan_avail_nut = 1;

This comment has been minimized.

Copy link
@jimklimov

jimklimov May 17, 2024

Member

@aquette : Is this intentional or a typo?

Shouldn't this be nutscan_avail_nut_simulation?

And is it at all needed here, if initialized to 1 above ... or maybe for generic approach, rather pre-init them all to 0 above and to 1 here if not libs are needed (also SNMP where built static, e.g. mingw with no libsnmp packages)?

CC issues #2242 and PR #2246

This comment has been minimized.

Copy link
@aquette

aquette via email May 18, 2024

Author Member

This comment has been minimized.

Copy link
@jimklimov

jimklimov May 18, 2024

Member

Ok, posted my take on this as PR #2449


}

void nutscan_free(void)
Expand Down
3 changes: 3 additions & 0 deletions tools/nut-scanner/nutscan-init.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2011 - 2024 Arnaud Quette (Design and part of implementation)
* Copyright (C) 2011 - EATON
*
* This program is free software; you can redistribute it and/or modify
Expand All @@ -19,6 +20,7 @@
/*! \file nutscan-init.h
\brief initialisation data
\author Frederic Bohe <[email protected]>
\author Arnaud Quette <[email protected]>
*/

#ifndef SCAN_INIT
Expand All @@ -33,6 +35,7 @@ extern "C" {
extern int nutscan_avail_avahi;
extern int nutscan_avail_ipmi;
extern int nutscan_avail_nut;
extern int nutscan_avail_nut_simulation;
extern int nutscan_avail_snmp;
extern int nutscan_avail_usb;
extern int nutscan_avail_xml_http;
Expand Down
Loading

0 comments on commit 3eb96fe

Please sign in to comment.