Description
Dear fellows,
I'm happy to finally be able to provide a RFC for this long awaited feature!
(esp. @clepple , @zykh , @jimklimov)
From docs/net-protocol.txt, Future ideas -> Command status:
After sending an INSTCMD or SET, a client will eventually be able to poll to see whether it was completed successfully by the driver.
Proposal:
-
Add a new "CMDSET_STATUS" command in the network protocol to enable/disable
the feature and provide status tracking information upon request:-
docs/net-protocol.txt additions
SET CMDSET_STATUS
Form: SET CMDSET_STATUS "<value>" SET CMDSET_STATUS ON SET CMDSET_STATUS OFF Response: OK ERR INVALID-ARGUMENT (if "value" is not "ON" or "OFF") ERR USERNAME-REQUIRED (if not yet authenticated) ERR PASSWORD-REQUIRED (if not yet authenticated) GET CMDSET_STATUS
Form:
GET CMDSET_STATUS (activation status of CMDSET_STATUS) GET CMDSET_STATUS [<status_id>] (execution status of a command / setvar) GET CMDSET_STATUS 1bd31808-cb49-4aec-9d75-d056e6f018d2
Response:
PENDING (command execution is pending) SUCCESS (command was successfully executed) ERR UNKNOWN (command execution failed with unknown error) ERR INVALID-ARGUMENT (command execution failed due to missing or invalid argument) ERR FAILED (command execution failed)
-
-
whenever CMDSET_STATUS is enabled, and a valid command / setvar is received by upsd,
upsd will allocate an ID (UUID v4 random, see below notes) and forward to driver
the request with the additional STATUS_ID tag and ID parameter-
docs/sock-protocol.txt additions
Commands sent by the server
INSTCMD
INSTCMD <cmdname> [cmdparam] [STATUS_ID <ID>] INSTCMD panel.test.start INSTCMD load.off 10 INSTCMD load.on 10 STATUS_ID 1bd31808-cb49-4aec-9d75-d056e6f018d2
-
NOTE:
- cmdparam is an additional and optional parameter for the command,
- "STATUS_ID " can be provided to track commands execution status, if
CMDSET_STATUS was set to ON on upsd. In this case, driver will later return
the execution status, using STATUS_ID
-
-
driver receives the cmd / setvar request from upsd. Then, upon completion of
this action, driver sends back the status with the ID (using CMDSET_STATUS) and
forgets about it (managed at the dstate level and not provided to upshandlers)-
docs/sock-protocol.txt additions
Commands used by the drivers
CMDSET_STATUS
CMDSET_STATUS <ID> <value> This is sent in response to an INSTCMD or SET VAR that includes a STATUS_ID, upon completion of request execution by the driver. <value> is the integer return value from the driver handlers instcmd and setvar (see drivers/upshandler.h). The server is in charge of translating these codes into strings, as per docs/net-protocol.txt GET CMDSET_STATUS.
-
-
upsd receives the status of the command / settings and updates the matching
status tracking entry -
upsd deletes tracked IDs upon time based (execution timestamp + CMDSETSTATUSDELAY in upsd.conf)
Notes:
-
A working implementation is available as https://github.com/networkupstools/nut/tree/cmdset_status
-
This work is sponsored by Eaton
-
I'm not fan of the CMDSET_STATUS name, but had no better idea apart from
STATUS_TRACKING / STATUS_ID. Comments and proposal welcome! -
the modifications are:
- non regressive: if CMDSET_STATUS is not enabled, the protocol will behave as
usual. Hence, existing implementation will not be altered - not impacting other clients: though the tracking structure is global (to
avoid loss of info when clients disconnect), only client that enabled
CMDSET_STATUS will receive the ID and be able to query the status info - mainly supported by upsd, its sstate and netcmds layer
- limited to dstate for drivers. No other modification are
needed in the drivers or elsewhere
- non regressive: if CMDSET_STATUS is not enabled, the protocol will behave as
-
ID generation: I've selected UUID v4 (random) to ensure uniqueness of the
generated ID. For now, I've added a basic implementation in the code, but it's
limited in OS scope, which I plan to address more cleanly. My requirements are:- support all our OS scope (Linux, Windows, Mac, Unix inc. BSD and Solaris,
HP-UX, AIX, ...) - no external dependency (embedded / homebrew implementation)
- Possible UUID approaches:
- https://github.com/spc476/SPCUUID
- https://github.com/rxi/uuid4 (tiny, embeddable, MIT license, Linux/Mac/FreeBSD/Win support)
- http://www.ossp.org/pkg/lib/uuid/
- libuuid (from e2fsprogs) (Linux only)
- homebrew implem (using /dev/urandom, fallback on random/rand/...)
- support all our OS scope (Linux, Windows, Mac, Unix inc. BSD and Solaris,
-
There are other remainders to be addressed for a full completion, but which can be separe work):
- Augeas completion for CMDSETSTATUSDELAY
- upscmd
- upsrw
- libnutclient (@boricj will very probably handle this)
- Python
- Perl
- jNUT (@EmilienKia)
- anything I missed?
Testing procedure:
- retrieve and compile the branch https://github.com/networkupstools/nut/tree/cmdset_status
- configure a device in ups.conf and a user in upsd.users
- launch the driver and upsd
- open a telnet using
telnet localhost 3493
- authenticate using
USERNAME "username from upsd.users"
PASSWORD "password from upsd.users"
- check if status tracking is enabled:
GET CMDSET_STATUS
will return:
OFF
- enable status tracking using:
SET CMDSET_STATUS ON
- issue an instant command or variable setting. For example:
INSTCMD myups load.off
You will receive back an "OK" answer with a status ID:
OK d6470a8e-4521-411c-beef-69cc9b33a94b
- Ask for the status of this command using:
GET CMDSET_STATUS d6470a8e-4521-411c-beef-69cc9b33a94b
- You will receive an answer like:
SUCCESS