system: Configure eth1 interface (on running system)

This commit is a part of implementation of network configuration for eth1
interface through Sysrepo and velia-system. It implements
/czechlight-system:networking/standalone-eth1 presence container in
running datastore.

If the presence container is missing, the network configuration for eth1
interface resets to the "old" default configuration of eth1, i.e., add
it to the br0 bridge.
If the container is present, the interface is removed from the bridge and
its IP address is obtained via DHCP.

The network is managed by systemd-networkd thus we implement the changes
via systemd-networkd network files [1]. The files can be placed in /etc,
/run and /usr directories (and they take precedence in this order). We
place the new network file in the /run directory and reload network
configuration via networkctl reload.

There is a slight catch in removing the interface from a bridge.
Apparently, systemd-networkd does not remove an interface from a bridge
if the new configuration does not contain Bridge settings [2].
However, bringing the interface down and then reloading the new
configuration apparently works.

[1] https://www.freedesktop.org/software/systemd/man/systemd.network.html
[2] https://github.com/systemd/systemd/issues/8190

Change-Id: I8940985a88903c17ea61e55aced67b17fba4656a
diff --git a/src/main-system.cpp b/src/main-system.cpp
index 77f5e4f..d74c45c 100644
--- a/src/main-system.cpp
+++ b/src/main-system.cpp
@@ -6,9 +6,11 @@
 #include "main.h"
 #include "system/Firmware.h"
 #include "system/Authentication.h"
+#include "system/Network.h"
 #include "system_vars.h"
 #include "system/IETFSystem.h"
 #include "utils/exceptions.h"
+#include "utils/exec.h"
 #include "utils/journal.h"
 #include "utils/log-init.h"
 
@@ -82,6 +84,30 @@
 
         auto dbusConnection = sdbus::createConnection(); // second connection for RAUC (for calling methods).
         dbusConnection->enterEventLoopAsync();
+
+        // initialize czechlight-system:networking
+        const std::filesystem::path runtimeNetworkDirectory("/run/systemd/network");
+        std::filesystem::create_directories(runtimeNetworkDirectory);
+        auto sysrepoNetworkRunning = velia::system::Network(srSess, runtimeNetworkDirectory, [](const std::vector<std::string>& reconfiguredInterfaces) {
+            auto log = spdlog::get("system");
+
+            /* Bring all the updated interfaces down (they will later be brought up by executing `networkctl reload`).
+             *
+             * This is required when transitioning from bridge to DHCP configuration. systemd-networkd apparently does not reset many
+             * interface properties when reconfiguring the interface into new "bridge-less" configuration (the interface stays in the
+             * bridge and it also does not obtain link local address).
+             *
+             * This doesn't seem to be required when transitioning from DHCP to bridge configuration. It's just a "precaution" because
+             * there might be hidden some caveats that I am unable to see now (some leftover setting). Bringing the interface
+             * down seems to reset the interface (and it is something we can afford in the interface reconfiguration process).
+             */
+            for (const auto& interfaceName : reconfiguredInterfaces) {
+                velia::utils::execAndWait(log, NETWORKCTL_EXECUTABLE, {"down", interfaceName}, "");
+            }
+
+            velia::utils::execAndWait(log, NETWORKCTL_EXECUTABLE, {"reload"}, "");
+        });
+
         auto sysrepoFirmware = velia::system::Firmware(srConn, *g_dbusConnection, *dbusConnection);
 
         auto srSess2 = std::make_shared<sysrepo::Session>(srConn);