Hello!

I performed lightweight review of Windows port source code (Windows-v2.6.5-7 
branch). I have some ideas I would like to share with NUT community.

First of all, Frederic did great job to port NUT sources to Windows platform 
and we have the path in dark forest. Unfortunately, the port looks like 
experimental. I think that the next major iteration is required.

Here are many words, sorry about it :)
Denis

REQUIREMENTS
------------
I could not find any requirements for Windows port version of NUT. I have 
arranged some items, which I see currently:

1. Windows port must be reliable and stable. It should provide enough level of 
logging and debugging to have good technical support.

2. Windows port must support all devices and programs, which Linux version does.

3. Windows port must be done for x86 and x64 platforms. The source code 
supports both platforms. To get the binaries, it is enough to configure and 
compile the sources, nothing more.

4. Windows port must support installation via Windows Installer. There should 
be two MSI setups for both platforms or single one with automatic platform 
detection. The setup system should provide selecting the features (programs, 
drivers, etc.).

5. Windows port components (x86, x64) must be compatible with Linux versions in 
any combinations. For example, Windows version of upsmon should be compatible 
with Linux version of upsd and so on. It allows to have mixed environment 
without any problem.

It seems there are no system requirements for minimal supported Windows 
version. As result, no one checks the version of operating system: neither NUT 
programs nor MSI setup. For example, Windows port uses OpenSCManager function, 
but it is available from Windows XP/Windows 2003 only. As result, the programs 
will crash in environment of older operating systems.

I think that minimal supported Windows version must be Windows XP/Windows 2003 
or even more modern one. Setup and source code should check operating system at 
startup.

GIT BRANCHES
------------
As I understand, master and Windows-v2.6.5-7 branches separated in last years 
and they contain different commits. In the end of Windows port implementation 
there should be one single branch for Windows port and Linux version (master). 
After it, Windows and Linux versions will be released simultaneously under 
equal versions.
That is the big question what branch should be used for next development 
iteration of Windows port.

I think Windows port must be stabilized in Windows-v2.6.5-7 branch and then 
merged to master one. Sure, the merge will 100% affect Linux version and may be 
bring some regression. On the other hand, it is single operation and it does 
not look very hard.

PLATFORM ABSTRACTION
--------------------
Current Windows port sources contain mixed Linux and Windows code in form of 
compiler predefines like #ifdef WIN32. It makes the sources unreadable and not 
maintainable.

I think the solution is implementation of abstraction layer that hides platform 
specific from algorithms and business logic. Saying the truth, something like 
abstraction layer already exists in wincompat.c file, but it is not full.

It would be great to have the abstraction layer not for Windows port only but 
for Linux version too. For example, the algorithms call the functions from 
interface like C-header. There are different implementations of this interface 
in static linked libraries. The libraries are building from different source 
code for specified target platform.

-------------                  ---------------
Linux version                  Windows version
----------------------------------------------
    Common algorithms and business logic
----------------------------------------------
         Software abstraction layer
----------------------------------------------
Linux implementation    Windows implementation
--------------------    ----------------------

LOGGING AND DEBUGGING
---------------------
When I tried to install Windows port in my environment, I had some problems to 
understand what is going on and what is wrong: it is quite hard to increase 
logging level and it is uncomfortable to work with Windows Event Log. I think 
that logging architecture should be improved.

Linux version contains several logging function like upslogx, 
upslog_with_errno, upsdebugx, etc. All of them call vupslog function inside. 
This function can write messages into STDERR stream and send them into syslog 
(writing to a log file is not required because Linux has syslogd, logrotation, 
etc.).

Windows port contains the same function. It can write messages into STDERR 
stream too, but as there is no native syslog support in Windows, Windows port 
provides special implementation of syslog function. It sends message via named 
pipe into a service called nut.exe (NUT service). The service writes them into 
Windows Event Log. In other words, NUT service provides simple "syslogd" 
feature.

This solution has different issues.

1. Sure, it is common recommendation to use Windows Event Log in Windows world 
as replacement of Linux syslog. I think it is not proper equivalent: Windows 
Event Log is more complex to use; it designed to log periodical significant 
events, not heavy debugging output; it is not useful for direct logs analysis, 
quite slow and problematic with support of users.

2. If NUT service is not available (stopped or crashed), logging is stopped 
automatically. I think that important software like NUT has to provide more 
reliable logging.

3. Unfortunately, "syslogd" implementation is unstable in Windows port. It eats 
syslog messages periodically and they do not appear in Windows Event Log (I did 
not find the bug yet, but something is wrong with new pipe connections).

4. Design of Windows Event Log bases on event identifiers and message table 
resources. Different notifications should have different Event ID and message 
body. Now, Windows port supports one predefined Event ID for formatted message 
"%1". It means that all messages have equal Event ID. This is not a big 
problem, but removes charm of Windows Event Log: no way to filter Windows port 
events and it is not transparent to external software analyzers. Moreover, 
Windows Event Log locks binaries with message table resources, so, nut.exe file 
becomes locked if somebody is viewing NUT messages in Event Viewer.

5. Currently, mixed NUT environment (Linux version and current Windows port) 
provides mixed logging: syslog and Windows Event Log. The people who use such 
environments will try to have single mechanism (just imagine). They will have 
to install additional software converters from syslog to Windows Event Log or 
vice versa and it looks at least strange.

It seems that "syslogd" feature is elimination candidate and it should be 
removed from NUT service.
I think that Windows port may provide file-based logging instead of "syslogd" 
implementation. Every program may write to their own file or in the common one. 
File logging is more stable; the programs do not depend from "central point" 
availability. Thereby, the users can simply send log files to developers during 
support cases and nothing more.

It would be nice to provide classic implementation of syslog function in 
Windows port (for example, RFC 5424). This is not hard and such support resolve 
mixed NUT environment issue.

On the other hand, Windows administrators are used to looking into Windows 
Event Log for important notifications. It would be great if Windows port can 
additionally write the significant messages to Windows Event Log. Every program 
may write them directly in special points of the source code. The messages can 
be located in resource DLL module to avoid "lock" problem.

I suggests the following logging architecture:

Linux version          Windows version
-------------------    ----------------------------
STDERR (no changes)    STDERR (no changes)                 
syslog (no changes)    syslog (new implementation)
                       filelog (new implementation)
                       Windows Event Log (redesign)

WINDOWS PORT ARCHITECTURE
-------------------------
NUT drivers are daemons in Linux version. They are starting and are stopping 
via controller called upsdrvctl (it is not daemon). Network server (upsd) and 
monitoring client (upsmon) are daemons too. Special "init.d" scripts start and 
stop all the programs in required order.

Linux architecture is following:

---------------------------------
         upsmon (daemon)
---------------------------------
          upsd (daemon)
---------------------------------
        Drivers (daemons)
apcsmart  blazer  ...  usbhid-ups
--------  ------  ---  ----------

In contrast to Linux version, Windows port contains NUT service that is 
"central point". The main idea of NUT service is providing functions like 
"syslogd" (I described it above) and "init.d", because their equivalents are 
absent in Windows world.

Drivers, network server and monitoring client are implemented as console 
applications. The service just starts and stops them as hidden processes in 
required order.

Windows port architecture is following:

---------------------------------
          nut (service)
---------------------------------
  upsmon (console application)
---------------------------------
   upsd (console application)
---------------------------------
 Drivers (console applications)
apcsmart  blazer  ...  usbhid-ups
--------  ------  ---  ----------

This design has some issues.

1. NUT service does not control the programs it has started. It is just a kind 
of starter. In the case of any failure (for example, upsd has crashed or 
terminated unexpectedly), the service does not restart failed program and 
thinks that everything is OK, but the system becomes unavailable. I have seen 
such behavior several times and I think that Windows port has to provide the 
mechanisms making the whole system more stable (watchdogs, etc.) because 
functionality of NUT is very important. For example, NUT service can be 
watchdog for all programs it has started.

2. Then upsmon executing shutdown procedure, it sends stop signal to NUT 
service and the service will stop everything it has started before, including 
upsmon. Therefore, it looks like a scheme where no main component is but 
chaotic calls are. It cannot be stable by default. What will be if NUT service 
is stopped? It seems nothing good.

This is common recommendation to port Linux daemons to Windows services. I 
think that upsd and upsmon should be implemented as Windows services (sure, 
they can be started as usual applications manually). As result, NUT service is 
not required anymore and it can be discarded.

Such scheme has many advantages:

1. It moves the responsibility of starting and stopping upsd and upsmon from 
NUT service to operating system.

2. Windows provides service recovery feature: in the case of failure, system 
will restart the service automatically. Service recovery function is a kind of 
watchdog I have told before. It will raise product stability and availability.

3. Additionally, the users will get standard system notifications and easy way 
to control and check what is running or not (via Control Panel).

As there are many drivers, there is no reason to implement them as services. 
They can stay as the simple console applications.

To control the drivers, the following function are required:

1. Start and stop the drivers at the operating system startup/shutdown (as 
upsdrvctl controller does).

2. Provide watchdog function for started driver. If driver process is finished 
by unknown reasons, it will be restarted automatically.

I think a new service should be implemented for these functions or it is 
possible to extend upsdrvctl source code to be as service. Another way is 
integrate the functions into upsd service, but it is quite different from Linux 
version.

The setup can register all the services in operating system. Moreover, it may 
create the dependencies between services and the system will start and stop 
them in required order. As result, there is no necessity to "init.d" function 
in NUT service.

New Windows port architecture can look like:

---------------------------------
        upsmon (service)
---------------------------------
         upsd (service)
---------------------------------
  Drivers controller (service)
---------------------------------
 Drivers (console applications)
apcsmart  blazer  ...  usbhid-ups
--------  ------  ---  ----------

CONFIG FILES
------------
Some parameters in configuration files must contain double backslashes. For 
example, "\\\\.\\COM1" should be used instead of "\\.\COM1". I am not sure, but 
configuration files parsing looks like a candidate to improve in Windows 
version. It can be moved to abstraction layer I have described above.

SETUP AND BINARIES
------------------
I think that currently used solution based on WIX is the best. I have found 
some issues, they are not critical, but should be fixed in future.

1. It seems that Windows port releases have been built under MinGW in Windows 
environment. Probably, the first versions were based at MSYS (not MINGW32), 
because setup contains files like msys-*.dll. Now, they can be removed from 
setup (bin/sbin directories), because no one uses them.

2. Windows port has been built with SSL support, because some binaries require 
libeay32.dll and ssleay32.dll. These files should be added to setup (bin/sbin 
directories).

3. upsmon depends on libgcc_s_dw2-1.dll file, but it missed in sbin directory 
and should be added to setup too.

4. bin directory contains upssched-cmd file without extension. It is WIN32 
executable file and there is its duplicate in sbin directory called 
upssched.exe. As result, upssched-cmd file should be removed. Unfortunately, I 
didn’t check what is the right place of upssched.exe file, may be it should be 
relocated too.

5. The setup contains lib directory with libupsclient.a and libupsclient.la 
files. I think they are not interesting for most of users and can be removed.

6. When I tried to build Windows port branch, I have found that neon and 
net-snmp libraries can be linked statically. Currently, they represent as 
dynamic libraries with quite big size and they are exporting many useless 
functions. I could reduce the setup size using static linking during my 
experiments.

7. The installed executable files should have VERSIONINFO resource by Windows 
Installer rules. I think it is easy to add proper version and description to 
every executable file.

8. I am not sure that StartService.bat/ StopService.bat files are necessary. 
They just start and stop NUT service. These actions can be performed via 
Control Panel.

9. Binary files contain debug information that can be stripped. It will 
significantly decrease setup file.

I told before about one single setup with automatic Windows platform detection 
(x86 or x64). Current setup installs all files at once without any 
customization. The main idea is to group the files to drivers, client files and 
server ones. After platform detection, the setup will ask the user about 
working mode (standalone, netserver, netclient).

If netclient mode is selected, the setup will install the client files only 
(upsmon, etc.).

For netserver mode, the setup will install the server files (upsd, etc.). The 
client files can be optionally installed by additional user select.

For standalone mode, the setup will install both client and server files.

The most important thing is that netserver and standalone modes require driver 
installation. For these modes, the user can select which drivers he needs or 
install all. Also, the setup can provide automatic detection of available 
devices via nut-scanner.

In the end of installation, the setup writes selected configuration into *.conf 
files, registers all necessary services and starts them. As result, the product 
is ready to use.
_______________________________________________
Nut-upsdev mailing list
Nut-upsdev@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev

Reply via email to