[Redfish] Add FQDN and IPv6Address in NetworkProtocol and EthernetInterface

FQDN and IPv6Address are mandatory properties in OCP profile.

Tested:
GET /redfish/v1/Managers/bmc/NetworkProtocol HTTP/1.1
Response:
{
    "@odata.context": "/redfish/v1/$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol",
    "@odata.id": "/redfish/v1/Managers/bmc/NetworkProtocol",
    "@odata.type": "#ManagerNetworkProtocol.v1_4_0.ManagerNetworkProtocol",
    "Description": "Manager Network Service",
    "FQDN": <host name>.<domain name>,
    "HTTPS": {
        "Port": 443,
        "ProtocolEnabled": true
    },
    "HostName": <host name>,
    ...
}

GET /redfish/v1/Managers/bmc/EthernetInterfaces/eth0 HTTP/1.1
Response:
{
    "@odata.context": "/redfish/v1/$metadata#EthernetInterface.EthernetInterface",
    "@odata.id": "/redfish/v1/Managers/bmc/EthernetInterfaces/eth0",
    "@odata.type": "#EthernetInterface.v1_4_1.EthernetInterface",
    ...
    "FQDN": <host name>.<domain name>,
    "HostName": <host name>,
    ...
    "IPv6Addresses": [],
    ...
}

Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
Change-Id: I0ca8f98523cbcfc935e0ac3bbf93f87762ff183b
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index c4f60a9..2375d68 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -100,6 +100,7 @@
     std::string mac_address;
     std::vector<std::uint32_t> vlan_id;
     std::vector<std::string> nameservers;
+    std::vector<std::string> domainnames;
 };
 
 // Helper function that changes bits netmask notation (i.e. /24)
@@ -236,6 +237,17 @@
                                 ethData.DHCPEnabled = *DHCPEnabled;
                             }
                         }
+                        else if (propertyPair.first == "DomainName")
+                        {
+                            const std::vector<std::string> *domainNames =
+                                sdbusplus::message::variant_ns::get_if<
+                                    std::vector<std::string>>(
+                                    &propertyPair.second);
+                            if (domainNames != nullptr)
+                            {
+                                ethData.domainnames = std::move(*domainNames);
+                            }
+                        }
                     }
                 }
             }
@@ -1498,6 +1510,11 @@
         if (!ethData.hostname.empty())
         {
             json_response["HostName"] = ethData.hostname;
+            if (!ethData.domainnames.empty())
+            {
+                json_response["FQDN"] =
+                    ethData.hostname + "." + ethData.domainnames[0];
+            }
         }
 
         json_response["VLANs"] = {
diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp
index 23965fa..74d742f 100644
--- a/redfish-core/lib/network_protocol.hpp
+++ b/redfish-core/lib/network_protocol.hpp
@@ -71,8 +71,10 @@
          {"phosphor-ipmi-net.socket", "/org/freedesktop/systemd1/unit/"
                                       "phosphor_2dipmi_2dnet_2esocket"}}};
 
-inline void extractNTPServersData(const GetManagedObjects& dbus_data,
-                                  std::vector<std::string>& ntpData)
+inline void
+    extractNTPServersAndDomainNamesData(const GetManagedObjects& dbus_data,
+                                        std::vector<std::string>& ntpData,
+                                        std::vector<std::string>& dnData)
 {
     for (const auto& obj : dbus_data)
     {
@@ -96,6 +98,17 @@
                                 ntpData = std::move(*ntpServers);
                             }
                         }
+                        else if (propertyPair.first == "DomainName")
+                        {
+                            const std::vector<std::string>* domainNames =
+                                sdbusplus::message::variant_ns::get_if<
+                                    std::vector<std::string>>(
+                                    &propertyPair.second);
+                            if (domainNames != nullptr)
+                            {
+                                dnData = std::move(*domainNames);
+                            }
+                        }
                     }
                 }
             }
@@ -111,16 +124,18 @@
             const boost::system::error_code error_code,
             const GetManagedObjects& dbus_data) {
             std::vector<std::string> ntpServers;
+            std::vector<std::string> domainNames;
 
             if (error_code)
             {
-                callback(false, ntpServers);
+                callback(false, ntpServers, domainNames);
                 return;
             }
 
-            extractNTPServersData(dbus_data, ntpServers);
+            extractNTPServersAndDomainNamesData(dbus_data, ntpServers,
+                                                domainNames);
 
-            callback(true, ntpServers);
+            callback(true, ntpServers, domainNames);
         },
         "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
@@ -207,23 +222,34 @@
             asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false;
         }
 
-        asyncResp->res.jsonValue["HostName"] = getHostName();
+        std::string hostName = getHostName();
+
+        asyncResp->res.jsonValue["HostName"] = hostName;
 
         getNTPProtocolEnabled(asyncResp);
 
         // TODO Get eth0 interface data, and call the below callback for JSON
         // preparation
-        getEthernetIfaceData(
-            [this, asyncResp](const bool& success,
-                              const std::vector<std::string>& ntpServers) {
-                if (!success)
+        getEthernetIfaceData([this, hostName, asyncResp](
+                                 const bool& success,
+                                 const std::vector<std::string>& ntpServers,
+                                 const std::vector<std::string>& domainNames) {
+            if (!success)
+            {
+                messages::resourceNotFound(asyncResp->res, "EthernetInterface",
+                                           "eth0");
+                return;
+            }
+            asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
+            if (hostName.empty() == false)
+            {
+                asyncResp->res.jsonValue["FQDN"] = hostName;
+                if (domainNames.empty() == false)
                 {
-                    messages::resourceNotFound(asyncResp->res,
-                                               "EthernetInterface", "eth0");
-                    return;
+                    asyncResp->res.jsonValue["FQDN"] += "." + domainNames[0];
                 }
-                asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
-            });
+            }
+        });
 
         crow::connections::systemBus->async_method_call(
             [asyncResp](const boost::system::error_code ec,
@@ -293,7 +319,6 @@
                                 // exceptions
                                 long port =
                                     std::strtol(portStr.c_str(), &endPtr, 10);
-
                                 if (*endPtr != '\0' || portStr.empty())
                                 {
                                     // Invalid value