Write the network configuration in the network file

Change-Id: Ic5ae90fb7b82539b943c4db0bc2eb116ec0d778f
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/configure.ac b/configure.ac
index 0ddf0ad..bbf5c4f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,10 @@
 AS_IF([test "x$NETWORK_CONF_DIR" == "x"], [NETWORK_CONF_DIR="/etc/systemd/network"])
 AC_DEFINE_UNQUOTED([NETWORK_CONF_DIR], ["$NETWORK_CONF_DIR"], [Network configuration directory])
 
+AC_DEFINE(SYSTEMD_BUSNAME, "org.freedesktop.systemd1", [systemd busname.])
+AC_DEFINE(SYSTEMD_PATH, "/org/freedesktop/systemd1", [systemd path.])
+AC_DEFINE(SYSTEMD_INTERFACE, "org.freedesktop.systemd1.Manager", [systemd interface.])
+
 # Create configured output.
 AC_CONFIG_FILES([Makefile test/Makefile])
 AC_OUTPUT
diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
index fc21424..5429bbc 100644
--- a/ethernet_interface.cpp
+++ b/ethernet_interface.cpp
@@ -1,6 +1,7 @@
 #include "config.h"
 #include "ipaddress.hpp"
 #include "ethernet_interface.hpp"
+#include "network_manager.hpp"
 
 #include <phosphor-logging/log.hpp>
 
@@ -30,9 +31,11 @@
 
 EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
                                      const std::string& objPath,
-                                     bool dhcpEnabled) :
+                                     bool dhcpEnabled,
+                                     Manager& parent) :
                                      Ifaces(bus, objPath.c_str(), true),
-                                     bus(bus)
+                                     bus(bus),
+                                     manager(parent)
 
 {
     auto intfName = objPath.substr(objPath.rfind("/") + 1);
@@ -99,6 +102,8 @@
                                 origin,
                                 prefixLength,
                                 gateway)));
+
+    manager.writeToConfigurationFile();
 }
 
 
@@ -232,6 +237,7 @@
          return;
     }
     this->addrs.erase(it);
+    manager.writeToConfigurationFile();
 }
 
 std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
index c755f06..7fb7cf1 100644
--- a/ethernet_interface.hpp
+++ b/ethernet_interface.hpp
@@ -23,6 +23,7 @@
         sdbusplus::xyz::openbmc_project::Network::IP::server::Create>;
 
 using IP = sdbusplus::xyz::openbmc_project::Network::server::IP;
+class Manager; // forward declaration of network manager.
 
 using LinkSpeed = uint16_t;
 using DuplexMode = uint8_t;
@@ -49,10 +50,12 @@
          *  @param[in] bus - Bus to attach to.
          *  @param[in] objPath - Path to attach at.
          *  @param[in] dhcpEnabled - is dhcp enabled(true/false).
+         *  @param[in] parent - parent object.
          */
         EthernetInterface(sdbusplus::bus::bus& bus,
                           const std::string& objPath,
-                          bool dhcpEnabled);
+                          bool dhcpEnabled,
+                          Manager& parent);
 
         /** @brief Function to create ipaddress dbus object.
          *  @param[in] addressType - Type of ip address.
@@ -125,6 +128,9 @@
         /** @brief Persistent sdbusplus DBus bus connection. */
         sdbusplus::bus::bus& bus;
 
+        /** @brief Network Manager object. */
+        Manager& manager;
+
         /** @brief Persistent map of IPAddress dbus objects and their names */
         AddressMap addrs;
 
diff --git a/network_manager.cpp b/network_manager.cpp
index 40fce1d..a5ff5e3 100644
--- a/network_manager.cpp
+++ b/network_manager.cpp
@@ -10,6 +10,7 @@
 #include <bitset>
 #include <experimental/filesystem>
 #include <map>
+#include <fstream>
 
 #include <arpa/inet.h>
 #include <dirent.h>
@@ -48,7 +49,8 @@
                                      phosphor::network::EthernetInterface>
                                      (bus,
                                       objPath.string(),
-                                      false)));
+                                      false,
+                                      *this)));
 
         interfaces[intfInfo.first]->setAddressList(intfInfo.second);
     }
@@ -199,5 +201,67 @@
     return intfMap;
 }
 
+// Need to merge the below function with the code which writes the
+// config file during factory reset.
+//TODO openbmc/openbmc#1751
+void Manager::writeToConfigurationFile()
+{
+    // write all the static ip address in the systemd-network conf file
+
+    using namespace std::string_literals;
+    using AddressOrigin =
+        sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
+    namespace fs = std::experimental::filesystem;
+
+    for (const auto& intf : interfaces)
+    {
+
+        fs::path confPath {NETWORK_CONF_DIR};
+        std::string fileName = "00-bmc-"s + intf.first + ".network"s;
+        confPath /= fileName;
+        std::fstream stream;
+        stream.open(confPath.c_str(), std::fstream::out);
+
+        // Write the device
+        stream << "[" << "Match" << "]\n";
+        stream << "Name=" << intf.first << "\n";
+
+        auto addrs = intf.second->getAddresses();
+
+        // write the network section
+        stream << "[" << "Network" << "]\n";
+        for (const auto& addr : addrs)
+        {
+            if (addr.second->origin() == AddressOrigin::Static)
+            {
+                std::string address = addr.second->address() + "/" + std::to_string(
+                                          addr.second->prefixLength());
+
+                stream << "Address=" << address << "\n";
+                stream << "Gateway=" << addr.second->gateway() << "\n";
+
+            }
+        }
+        stream.close();
+    }
+    restartSystemdNetworkd();
+}
+
+void  Manager::restartSystemdNetworkd()
+{
+    constexpr auto systemdNetworkdService = "systemd-networkd.service";
+
+    auto method = bus.new_method_call(
+                      SYSTEMD_BUSNAME,
+                      SYSTEMD_PATH,
+                      SYSTEMD_INTERFACE,
+                      "RestartUnit");
+
+    method.append(systemdNetworkdService,
+                  "replace");
+
+    bus.call_noreply(method);
+}
+
 }//namespace network
 }//namespace phosphor
diff --git a/network_manager.hpp b/network_manager.hpp
index e8dfa8e..c6ea36c 100644
--- a/network_manager.hpp
+++ b/network_manager.hpp
@@ -74,6 +74,10 @@
 
         void vLAN(IntfName interfaceName, uint16_t id) override;
 
+        /** @brief write the network conf file with the in-memory objects.
+         */
+        void writeToConfigurationFile();
+
         /** @brief Fetch the interface and the ipaddress details
          *         from the system and create the ethernet interraces
          *         dbus object.
@@ -87,6 +91,10 @@
          */
         IntfAddrMap getInterfaceAddrs() const;
 
+        /** @brief Restart the systemd networkd
+         */
+        void restartSystemdNetworkd();
+
         /** @brief Persistent sdbusplus DBus bus connection. */
         sdbusplus::bus::bus& bus;