Co-Authored-By: Yonas Habteab <yonas.habteab@icinga.com>
Once the new worker process has read the config, it also includes a
`include */include.conf` statement within the config packages root
directory, and from there on we must not allow to delete any stage
directory from the config package. Otherwise, when the worker actually
evaluates that include statement, it will fail to find the directory
where the include file is located, or the `active.conf` file, which is
included from each stage's `include.conf` file, thus causing the worker
fail.
Previously, we used a simple boolean to track the state of the package updates,
and didn't reset it back when the config validation was successful because it was
assumed that if we successfully validated the config beforehand, then the worker
would also successfully reload the config afterwards, and that the old worker would
be terminated. However, this assumption is not always true due to a number of reasons
that I can't even think of right now, but the most obvious one is that after we successfully
validated the config, the config might have changed again before the worker was able
to reload it. If that happens, then the new worker might fail to successfully validate
the config due to the recent changes, in which case the old worker would remain active,
and this flag would still be set to true, causing any subsequent requests to fail with a
`423` until you manually restart the Icinga 2 service.
So, in order to prevent such a situation, we are additionally tracking the last time a reload
failed and allow to bypass the `m_RunningPackageUpdates` flag only if the last reload failed
time was changed since the previous request.
This commit intruduces a small helper class that wraps any writer and
provides a flush operation that performs the corresponding action if the
writer is an AsyncJsonWriter and does nothing otherwise.
Replacing invalid UTF-8 characters beforehand by our selves doesn't make
any sense, the serializer can literally perform the same replacement ops
with the exact same Unicode replacement character (U+FFFD) on its own.
So, why not just use it directly? Instead of wasting memory on a temporary
`String` object to always UTF-8 validate every and each value, we just
use the serializer to directly to dump the replaced char (if any) into
the output writer. No memory waste, no fuss!
The Array, Dictionary, and Namespace types provide a Freeze() method that makes
them read-only. So far, there was the possibility to call some methods with
`overrideFrozen=true` which would then bypass the corresponding check and allow
modification of the data structures nonetheless.
With 24b57f0d3a222835178e88489eabd595755ed883, this possibility was already
removed from the Namespace type. However, for interface compatibility, it kept
the parameter and just ignores it, throwing an exception on any modification on
a frozen instance.
The only place using `overrideFrozen` was processing of the `-D`/`--define`
command line flag that allows setting additional variables in the DSL. At the
time it is evaluated, there are no user-created data structures yet that could
be frozen, so the only frozen objects that could be encountered are Namespaces
(Icinga doesn't freeze other types by itself) and for these, `overrideFrozen`
already has no effect.
Hence, there is no harm in removing `overrideFrozen` altogether. This
simplifies the code and also means that frozen objects are now indeed read-only
without exceptions, allowing further optimizations regarding locking in the
future.
Within the GNU/Linux distribution specific installation guides, the "Set
up Icinga DB" section was only excluded for openSUSE. However, since
there is an openSUSE installation guide within Icinga DB[^0], this is
not consistent. Thus, the if-guard was removed, resulting in this
section being available for each distribution. Windows is already
excluded through an if-guard above.
Some cases for Fedora were missing, which were also added.
[^0]: https://icinga.com/docs/icinga-db/latest/doc/02-Installation/openSUSE/
With Fedora 41, DNF was upgraded to version 5, breaking the command line
API of "dnf config-manager"[^0]. Unfortunately, DNF 5's addrepo does not
work with a simple URL anymore, but requires to construct a .repo file.
Furthermore, no information about trusting the Icinga signing key was
available, resulting in one being unable to install packages. This was
already the case for Fedora 40, still using DNF 4.
Since we are building Icinga DB for Fedora, I have included Icinga DB
documentation for Fedora. Otherwise, this section was empty.
Finally, the icingadb-redis-selinux package was mentioned for
distributions were we started to build SELinux packages for[^1].
[^0]: https://docs.fedoraproject.org/en-US/quick-docs/adding-or-removing-software-repositories-in-fedora/#_adding_repositories
[^1]: https://github.com/Icinga/icingadb/issues/580
CMake 3.15 introduced the `MSVC_RUNTIME_LIBRARY` property as a way to specify
which MSVC runtime library is used and how it is linked. Also with that
release, policy CMP0091 was introduced where the new behavior no longer adds
the corresponding compile flags to the `CMAKE_<LANG>_FLAGS_<CONFIG>` variables.
The new policy was enabled by 7f164bda96341272be385fa1359a26f97eb9d2b4,
resulting in the MSI no longer working on previous Windows Server versions
(2019 for example) as the CMake configuration replaced those compile flags
(lines 3-9 in the same file) which no longer works when they are no longer part
of the string. This commit fixes this regression by setting the
`MSVC_RUNTIME_LIBRARY` property on the icinga-installer target.
I've also added a comment stating my understanding of why this is necessary.
Unfortunately, I couldn't find an explanation of why replacing the /MD with the
/MT flag was done originally in the project history, so it's a bit of
guesswork.
https://cmake.org/cmake/help/latest/policy/CMP0091.htmlhttps://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html
The wait group gets passed to HttpServerConnection, then down to the
HttpHandlers. For those handlers that modify the program state, the
wait group is locked so ApiListener will wait on Stop() for the
request to complete. If the request iterates over config objects,
a further check on the state of the wait group is added to abort early
and not delay program shutdown. In that case, 503 responses will be
sent to the client.
Additionally, in HttpServerConnection, no further requests than the
one already started will be allowed once the wait group is joining.