1d5afb2caSAndrew Geissler #pragma once 2d5afb2caSAndrew Geissler 33ccb3adbSEd Tanous #include "app.hpp" 43ccb3adbSEd Tanous #include "dbus_singleton.hpp" 57a1dbc48SGeorge Liu #include "dbus_utility.hpp" 63ccb3adbSEd Tanous #include "error_messages.hpp" 73ccb3adbSEd Tanous #include "ethernet.hpp" 83ccb3adbSEd Tanous #include "query.hpp" 93ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 10033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 113ccb3adbSEd Tanous #include "utils/json_utils.hpp" 12033f1e4dSEd Tanous 13ef4c65b7SEd Tanous #include <boost/url/format.hpp> 141e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 15d5afb2caSAndrew Geissler 167a1dbc48SGeorge Liu #include <array> 17d5afb2caSAndrew Geissler #include <optional> 187a1dbc48SGeorge Liu #include <string_view> 19d5afb2caSAndrew Geissler #include <utility> 20d5afb2caSAndrew Geissler 2188a8a174SEd Tanous namespace redfish 22d5afb2caSAndrew Geissler { 23d5afb2caSAndrew Geissler 24d5afb2caSAndrew Geissler /** 25cc0bb6f2SAndrew Geissler * @brief Retrieves hypervisor state properties over dbus 26cc0bb6f2SAndrew Geissler * 27cc0bb6f2SAndrew Geissler * The hypervisor state object is optional so this function will only set the 28cc0bb6f2SAndrew Geissler * state variables if the object is found 29cc0bb6f2SAndrew Geissler * 30ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 31cc0bb6f2SAndrew Geissler * 32cc0bb6f2SAndrew Geissler * @return None. 33cc0bb6f2SAndrew Geissler */ 34ac106bf6SEd Tanous inline void 35ac106bf6SEd Tanous getHypervisorState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 36cc0bb6f2SAndrew Geissler { 3762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor state information."); 381e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 391e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Hypervisor", 401e1e598dSJonathan Doman "/xyz/openbmc_project/state/hypervisor0", 411e1e598dSJonathan Doman "xyz.openbmc_project.State.Host", "CurrentHostState", 42ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 431e1e598dSJonathan Doman const std::string& hostState) { 44cc0bb6f2SAndrew Geissler if (ec) 45cc0bb6f2SAndrew Geissler { 4662598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 47cc0bb6f2SAndrew Geissler // This is an optional D-Bus object so just return if 48cc0bb6f2SAndrew Geissler // error occurs 49cc0bb6f2SAndrew Geissler return; 50cc0bb6f2SAndrew Geissler } 51cc0bb6f2SAndrew Geissler 5262598e31SEd Tanous BMCWEB_LOG_DEBUG("Hypervisor state: {}", hostState); 53cc0bb6f2SAndrew Geissler // Verify Host State 541e1e598dSJonathan Doman if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") 55cc0bb6f2SAndrew Geissler { 56ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "On"; 57ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 58cc0bb6f2SAndrew Geissler } 591e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 601e1e598dSJonathan Doman "Quiesced") 61cc0bb6f2SAndrew Geissler { 62ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "On"; 63ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Quiesced"; 64cc0bb6f2SAndrew Geissler } 651e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 661e1e598dSJonathan Doman "Standby") 67cc0bb6f2SAndrew Geissler { 68ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "On"; 69ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 70cc0bb6f2SAndrew Geissler } 711e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 721e1e598dSJonathan Doman "TransitioningToRunning") 73cc0bb6f2SAndrew Geissler { 74ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "PoweringOn"; 75ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Starting"; 76cc0bb6f2SAndrew Geissler } 771e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 781e1e598dSJonathan Doman "TransitioningToOff") 79cc0bb6f2SAndrew Geissler { 80ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "PoweringOff"; 81ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 82cc0bb6f2SAndrew Geissler } 83002d39b4SEd Tanous else if (hostState == "xyz.openbmc_project.State.Host.HostState.Off") 84cc0bb6f2SAndrew Geissler { 85ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "Off"; 86ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Disabled"; 87cc0bb6f2SAndrew Geissler } 88cc0bb6f2SAndrew Geissler else 89cc0bb6f2SAndrew Geissler { 90ac106bf6SEd Tanous messages::internalError(asyncResp->res); 91cc0bb6f2SAndrew Geissler return; 92cc0bb6f2SAndrew Geissler } 931e1e598dSJonathan Doman }); 94cc0bb6f2SAndrew Geissler } 95cc0bb6f2SAndrew Geissler 96cc0bb6f2SAndrew Geissler /** 974fbaf64aSAndrew Geissler * @brief Populate Actions if any are valid for hypervisor object 984fbaf64aSAndrew Geissler * 994fbaf64aSAndrew Geissler * The hypervisor state object is optional so this function will only set the 1004fbaf64aSAndrew Geissler * Action if the object is found 1014fbaf64aSAndrew Geissler * 102ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 1034fbaf64aSAndrew Geissler * 1044fbaf64aSAndrew Geissler * @return None. 1054fbaf64aSAndrew Geissler */ 1068d1b46d7Szhanghch05 inline void 107ac106bf6SEd Tanous getHypervisorActions(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1084fbaf64aSAndrew Geissler { 10962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor actions."); 1102b73119cSGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1112b73119cSGeorge Liu "xyz.openbmc_project.State.Host"}; 1122b73119cSGeorge Liu dbus::utility::getDbusObject( 1132b73119cSGeorge Liu "/xyz/openbmc_project/state/hypervisor0", interfaces, 114ac106bf6SEd Tanous [asyncResp]( 1152b73119cSGeorge Liu const boost::system::error_code& ec, 1164fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1174fbaf64aSAndrew Geissler objInfo) { 1184fbaf64aSAndrew Geissler if (ec) 1194fbaf64aSAndrew Geissler { 12062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 1214fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1224fbaf64aSAndrew Geissler // error occurs 1234fbaf64aSAndrew Geissler return; 1244fbaf64aSAndrew Geissler } 1254fbaf64aSAndrew Geissler 12626f6976fSEd Tanous if (objInfo.empty()) 1274fbaf64aSAndrew Geissler { 1284fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1294fbaf64aSAndrew Geissler // if there is no instance found 1304fbaf64aSAndrew Geissler return; 1314fbaf64aSAndrew Geissler } 1324fbaf64aSAndrew Geissler 1334fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1344fbaf64aSAndrew Geissler { 1354fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1364fbaf64aSAndrew Geissler // error 137ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1384fbaf64aSAndrew Geissler return; 1394fbaf64aSAndrew Geissler } 1404fbaf64aSAndrew Geissler 1414fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 142613dabeaSEd Tanous nlohmann::json& reset = 143ac106bf6SEd Tanous asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]; 144613dabeaSEd Tanous reset["target"] = 145613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"; 146613dabeaSEd Tanous reset["@Redfish.ActionInfo"] = 147613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 1482b73119cSGeorge Liu }); 1494fbaf64aSAndrew Geissler } 1504fbaf64aSAndrew Geissler 151d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 152711ac7a9SEd Tanous const std::string& ethIfaceId, 153711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 15477179532SEd Tanous EthernetInterfaceData& ethData, std::vector<IPv4AddressData>& ipv4Config) 155d5afb2caSAndrew Geissler { 156d5afb2caSAndrew Geissler bool idFound = false; 157d5afb2caSAndrew Geissler for (const auto& objpath : dbusData) 158d5afb2caSAndrew Geissler { 159d5afb2caSAndrew Geissler for (const auto& ifacePair : objpath.second) 160d5afb2caSAndrew Geissler { 161d5afb2caSAndrew Geissler if (objpath.first == 162d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId) 163d5afb2caSAndrew Geissler { 164d5afb2caSAndrew Geissler idFound = true; 165d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 166d5afb2caSAndrew Geissler { 167d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 168d5afb2caSAndrew Geissler { 169d5afb2caSAndrew Geissler if (propertyPair.first == "MACAddress") 170d5afb2caSAndrew Geissler { 171d5afb2caSAndrew Geissler const std::string* mac = 172d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 173d5afb2caSAndrew Geissler if (mac != nullptr) 174d5afb2caSAndrew Geissler { 17582695a5bSJiaqing Zhao ethData.macAddress = *mac; 176d5afb2caSAndrew Geissler } 177d5afb2caSAndrew Geissler } 178d5afb2caSAndrew Geissler } 179d5afb2caSAndrew Geissler } 180d5afb2caSAndrew Geissler else if (ifacePair.first == 181d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface") 182d5afb2caSAndrew Geissler { 183d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 184d5afb2caSAndrew Geissler { 185d5afb2caSAndrew Geissler if (propertyPair.first == "DHCPEnabled") 186d5afb2caSAndrew Geissler { 187d5afb2caSAndrew Geissler const std::string* dhcp = 188d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 189d5afb2caSAndrew Geissler if (dhcp != nullptr) 190d5afb2caSAndrew Geissler { 19182695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcp; 192d5afb2caSAndrew Geissler break; // Interested on only "DHCPEnabled". 193d5afb2caSAndrew Geissler // Stop parsing since we got the 194d5afb2caSAndrew Geissler // "DHCPEnabled" value. 195d5afb2caSAndrew Geissler } 196d5afb2caSAndrew Geissler } 197d5afb2caSAndrew Geissler } 198d5afb2caSAndrew Geissler } 199d5afb2caSAndrew Geissler } 200d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor/" + 201d5afb2caSAndrew Geissler ethIfaceId + "/ipv4/addr0") 202d5afb2caSAndrew Geissler { 20377179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 204d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Object.Enable") 205d5afb2caSAndrew Geissler { 2069eb808c1SEd Tanous for (const auto& property : ifacePair.second) 207d5afb2caSAndrew Geissler { 208d5afb2caSAndrew Geissler if (property.first == "Enabled") 209d5afb2caSAndrew Geissler { 210d5afb2caSAndrew Geissler const bool* intfEnable = 211d5afb2caSAndrew Geissler std::get_if<bool>(&property.second); 212d5afb2caSAndrew Geissler if (intfEnable != nullptr) 213d5afb2caSAndrew Geissler { 214d5afb2caSAndrew Geissler ipv4Address.isActive = *intfEnable; 215d5afb2caSAndrew Geissler break; 216d5afb2caSAndrew Geissler } 217d5afb2caSAndrew Geissler } 218d5afb2caSAndrew Geissler } 219d5afb2caSAndrew Geissler } 220d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.IP") 221d5afb2caSAndrew Geissler { 2229eb808c1SEd Tanous for (const auto& property : ifacePair.second) 223d5afb2caSAndrew Geissler { 224d5afb2caSAndrew Geissler if (property.first == "Address") 225d5afb2caSAndrew Geissler { 226d5afb2caSAndrew Geissler const std::string* address = 227d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 228d5afb2caSAndrew Geissler if (address != nullptr) 229d5afb2caSAndrew Geissler { 230d5afb2caSAndrew Geissler ipv4Address.address = *address; 231d5afb2caSAndrew Geissler } 232d5afb2caSAndrew Geissler } 233d5afb2caSAndrew Geissler else if (property.first == "Origin") 234d5afb2caSAndrew Geissler { 235d5afb2caSAndrew Geissler const std::string* origin = 236d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 237d5afb2caSAndrew Geissler if (origin != nullptr) 238d5afb2caSAndrew Geissler { 239d5afb2caSAndrew Geissler ipv4Address.origin = 240d5afb2caSAndrew Geissler translateAddressOriginDbusToRedfish(*origin, 241d5afb2caSAndrew Geissler true); 242d5afb2caSAndrew Geissler } 243d5afb2caSAndrew Geissler } 244d5afb2caSAndrew Geissler else if (property.first == "PrefixLength") 245d5afb2caSAndrew Geissler { 246d5afb2caSAndrew Geissler const uint8_t* mask = 247d5afb2caSAndrew Geissler std::get_if<uint8_t>(&property.second); 248d5afb2caSAndrew Geissler if (mask != nullptr) 249d5afb2caSAndrew Geissler { 250d5afb2caSAndrew Geissler // convert it to the string 251d5afb2caSAndrew Geissler ipv4Address.netmask = getNetmask(*mask); 252d5afb2caSAndrew Geissler } 253d5afb2caSAndrew Geissler } 254889ff694SAsmitha Karunanithi else if (property.first == "Type" || 255889ff694SAsmitha Karunanithi property.first == "Gateway") 256889ff694SAsmitha Karunanithi { 257889ff694SAsmitha Karunanithi // Type & Gateway is not used 258889ff694SAsmitha Karunanithi continue; 259889ff694SAsmitha Karunanithi } 260d5afb2caSAndrew Geissler else 261d5afb2caSAndrew Geissler { 26262598e31SEd Tanous BMCWEB_LOG_ERROR( 26362598e31SEd Tanous "Got extra property: {} on the {} object", 26462598e31SEd Tanous property.first, objpath.first.str); 265d5afb2caSAndrew Geissler } 266d5afb2caSAndrew Geissler } 267d5afb2caSAndrew Geissler } 268d5afb2caSAndrew Geissler } 269d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 270d5afb2caSAndrew Geissler { 271d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 272d5afb2caSAndrew Geissler // need to check eth number 273d5afb2caSAndrew Geissler if (ifacePair.first == 274d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 275d5afb2caSAndrew Geissler { 276d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 277d5afb2caSAndrew Geissler { 278d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 279d5afb2caSAndrew Geissler { 280d5afb2caSAndrew Geissler const std::string* hostName = 281d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 282d5afb2caSAndrew Geissler if (hostName != nullptr) 283d5afb2caSAndrew Geissler { 28482695a5bSJiaqing Zhao ethData.hostName = *hostName; 285d5afb2caSAndrew Geissler } 286d5afb2caSAndrew Geissler } 287d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 288d5afb2caSAndrew Geissler { 289d5afb2caSAndrew Geissler const std::string* defaultGateway = 290d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 291d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 292d5afb2caSAndrew Geissler { 29382695a5bSJiaqing Zhao ethData.defaultGateway = *defaultGateway; 294d5afb2caSAndrew Geissler } 295d5afb2caSAndrew Geissler } 296d5afb2caSAndrew Geissler } 297d5afb2caSAndrew Geissler } 298d5afb2caSAndrew Geissler } 299d5afb2caSAndrew Geissler } 300d5afb2caSAndrew Geissler } 301d5afb2caSAndrew Geissler return idFound; 302d5afb2caSAndrew Geissler } 303d5afb2caSAndrew Geissler /** 304d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 305d5afb2caSAndrew Geissler * Interface Object from Settings Manager 306d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 307d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 308d5afb2caSAndrew Geissler * into JSON 309d5afb2caSAndrew Geissler */ 310d5afb2caSAndrew Geissler template <typename CallbackFunc> 311d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 312d5afb2caSAndrew Geissler CallbackFunc&& callback) 313d5afb2caSAndrew Geissler { 3145eb468daSGeorge Liu sdbusplus::message::object_path path("/"); 3155eb468daSGeorge Liu dbus::utility::getManagedObjects( 3165eb468daSGeorge Liu "xyz.openbmc_project.Settings", path, 317f94c4ecfSEd Tanous [ethIfaceId{std::string{ethIfaceId}}, 318f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 3198b24275dSEd Tanous const boost::system::error_code& ec, 320711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& resp) { 321d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 32277179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 3238b24275dSEd Tanous if (ec) 324d5afb2caSAndrew Geissler { 325d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 326d5afb2caSAndrew Geissler return; 327d5afb2caSAndrew Geissler } 328d5afb2caSAndrew Geissler 32989492a15SPatrick Williams bool found = extractHypervisorInterfaceData(ethIfaceId, resp, ethData, 33089492a15SPatrick Williams ipv4Data); 331d5afb2caSAndrew Geissler if (!found) 332d5afb2caSAndrew Geissler { 33362598e31SEd Tanous BMCWEB_LOG_INFO("Hypervisor Interface not found"); 334d5afb2caSAndrew Geissler } 335d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 3365eb468daSGeorge Liu }); 337d5afb2caSAndrew Geissler } 338d5afb2caSAndrew Geissler 339d5afb2caSAndrew Geissler /** 340d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 341d5afb2caSAndrew Geissler * 342ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 343d5afb2caSAndrew Geissler * @param[in] ipv4Address Address from the incoming request 344d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 345d5afb2caSAndrew Geissler * 346d5afb2caSAndrew Geissler * @return None. 347d5afb2caSAndrew Geissler */ 348ac106bf6SEd Tanous inline void setHypervisorIPv4Address( 349ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 350ac106bf6SEd Tanous const std::string& ethIfaceId, const std::string& ipv4Address) 351d5afb2caSAndrew Geissler { 35262598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor IPaddress : {} on Iface: {}", 35362598e31SEd Tanous ipv4Address, ethIfaceId); 354*d82b5e1fSAsmitha Karunanithi 355*d82b5e1fSAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Settings", 356*d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + 357*d82b5e1fSAsmitha Karunanithi "/ipv4/addr0", 358*d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.IP", "Address", 359*d82b5e1fSAsmitha Karunanithi "IPv4StaticAddresses/1/Address", ipv4Address); 360d5afb2caSAndrew Geissler } 361d5afb2caSAndrew Geissler 362d5afb2caSAndrew Geissler /** 363d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 364d5afb2caSAndrew Geissler * 365ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 366d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 367d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 368d5afb2caSAndrew Geissler * 369d5afb2caSAndrew Geissler * @return None. 370d5afb2caSAndrew Geissler */ 3718d1b46d7Szhanghch05 inline void 372ac106bf6SEd Tanous setHypervisorIPv4Subnet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3738d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 374d5afb2caSAndrew Geissler { 37562598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor subnet : {} on Iface: {}", subnet, 37662598e31SEd Tanous ethIfaceId); 377d5afb2caSAndrew Geissler 378*d82b5e1fSAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Settings", 379*d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + 380*d82b5e1fSAsmitha Karunanithi "/ipv4/addr0", 381*d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.IP", "PrefixLength", 382*d82b5e1fSAsmitha Karunanithi "IPv4StaticAddresses/1/SubnetMask", subnet); 383d5afb2caSAndrew Geissler } 384d5afb2caSAndrew Geissler 385d5afb2caSAndrew Geissler /** 386d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 387d5afb2caSAndrew Geissler * 388ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 389d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 390d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 391d5afb2caSAndrew Geissler * 392d5afb2caSAndrew Geissler * @return None. 393d5afb2caSAndrew Geissler */ 394ac106bf6SEd Tanous inline void setHypervisorIPv4Gateway( 395ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 396d5afb2caSAndrew Geissler const std::string& gateway) 397d5afb2caSAndrew Geissler { 39862598e31SEd Tanous BMCWEB_LOG_DEBUG( 39962598e31SEd Tanous "Setting the DefaultGateway to the last configured gateway"); 400d5afb2caSAndrew Geissler 401*d82b5e1fSAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Settings", 402*d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 403*d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 404*d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 405*d82b5e1fSAsmitha Karunanithi "DefaultGateway", "IPv4StaticAddresses/1/Gateway", gateway); 406d5afb2caSAndrew Geissler } 407d5afb2caSAndrew Geissler 408d5afb2caSAndrew Geissler /** 409d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 410d5afb2caSAndrew Geissler * 411d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 412d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 413d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 414d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 415d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 416d5afb2caSAndrew Geissler * 417d5afb2caSAndrew Geissler * @return None 418d5afb2caSAndrew Geissler */ 4198d1b46d7Szhanghch05 inline void 4208d1b46d7Szhanghch05 createHypervisorIPv4(const std::string& ifaceId, uint8_t prefixLength, 4218d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4228d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 423d5afb2caSAndrew Geissler { 424d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 425d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 426d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 427d5afb2caSAndrew Geissler } 428d5afb2caSAndrew Geissler 429d5afb2caSAndrew Geissler /** 430d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 431d5afb2caSAndrew Geissler * 432d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 433d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 434d5afb2caSAndrew Geissler * 435d5afb2caSAndrew Geissler * @return None 436d5afb2caSAndrew Geissler */ 4378d1b46d7Szhanghch05 inline void 4388d1b46d7Szhanghch05 deleteHypervisorIPv4(const std::string& ifaceId, 4398d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 440d5afb2caSAndrew Geissler { 441d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 442d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 443d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 444d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 445d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 446d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 447d5afb2caSAndrew Geissler } 448d5afb2caSAndrew Geissler 44977179532SEd Tanous inline void parseInterfaceData(nlohmann::json& jsonResponse, 45077179532SEd Tanous const std::string& ifaceId, 451d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 45277179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) 453d5afb2caSAndrew Geissler { 454d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 455ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 456ef4c65b7SEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", ifaceId); 457d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 45882695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 459d5afb2caSAndrew Geissler 46082695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 461d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 46282695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 463d5afb2caSAndrew Geissler 464d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 465d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 466d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 467d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 4689eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 469d5afb2caSAndrew Geissler { 470d5afb2caSAndrew Geissler if (ipv4Config.isActive) 471d5afb2caSAndrew Geissler { 4721476687dSEd Tanous nlohmann::json::object_t ipv4; 4731476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 4741476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 4751476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 4761476687dSEd Tanous ipv4["Gateway"] = ethData.defaultGateway; 477d5afb2caSAndrew Geissler 478d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 479d5afb2caSAndrew Geissler { 4801476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 481d5afb2caSAndrew Geissler } 482b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 483d5afb2caSAndrew Geissler } 484d5afb2caSAndrew Geissler } 485d5afb2caSAndrew Geissler } 486d5afb2caSAndrew Geissler 48777179532SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, bool ipv4DHCPEnabled, 4888d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 489d5afb2caSAndrew Geissler { 4907e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 491*d82b5e1fSAsmitha Karunanithi 492*d82b5e1fSAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Settings", 493*d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 494*d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor") / 495*d82b5e1fSAsmitha Karunanithi ifaceId, 496*d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface", 497*d82b5e1fSAsmitha Karunanithi "DHCPEnabled", "DHCPv4/DHCPEnabled", dhcp); 498d5afb2caSAndrew Geissler 499d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 500d5afb2caSAndrew Geissler // of the DHCPEnabled property 501d5afb2caSAndrew Geissler std::string origin; 502e05aec50SEd Tanous if (!ipv4DHCPEnabled) 503d5afb2caSAndrew Geissler { 504d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 505d5afb2caSAndrew Geissler } 506d5afb2caSAndrew Geissler else 507d5afb2caSAndrew Geissler { 508d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 509d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 510d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 511d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 512d5afb2caSAndrew Geissler } 513*d82b5e1fSAsmitha Karunanithi 514*d82b5e1fSAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Settings", 515*d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor/" + ifaceId + 516*d82b5e1fSAsmitha Karunanithi "/ipv4/addr0", 517*d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.IP", "Origin", 518*d82b5e1fSAsmitha Karunanithi "IPv4StaticAddresses/1/AddressOrigin", origin); 519d5afb2caSAndrew Geissler } 520d5afb2caSAndrew Geissler 5217e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 5227e860f15SJohn Edward Broadbent const std::string& ifaceId, const nlohmann::json& input, 5237e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 524d5afb2caSAndrew Geissler { 5257e860f15SJohn Edward Broadbent if ((!input.is_array()) || input.empty()) 526d5afb2caSAndrew Geissler { 5272e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 5287e860f15SJohn Edward Broadbent "IPv4StaticAddresses"); 529d5afb2caSAndrew Geissler return; 530d5afb2caSAndrew Geissler } 531d5afb2caSAndrew Geissler 5327e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 5337e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 5347e860f15SJohn Edward Broadbent // address 5357e860f15SJohn Edward Broadbent const nlohmann::json& thisJson = input[0]; 5367e860f15SJohn Edward Broadbent 5377e860f15SJohn Edward Broadbent if (!thisJson.is_null() && !thisJson.empty()) 5387e860f15SJohn Edward Broadbent { 539f8fe53e7SEd Tanous // For the error string 540f8fe53e7SEd Tanous std::string pathString = "IPv4StaticAddresses/1"; 5417e860f15SJohn Edward Broadbent std::optional<std::string> address; 5427e860f15SJohn Edward Broadbent std::optional<std::string> subnetMask; 5437e860f15SJohn Edward Broadbent std::optional<std::string> gateway; 5447e860f15SJohn Edward Broadbent nlohmann::json thisJsonCopy = thisJson; 5457e860f15SJohn Edward Broadbent if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 5467e860f15SJohn Edward Broadbent address, "SubnetMask", subnetMask, "Gateway", 5477e860f15SJohn Edward Broadbent gateway)) 5487e860f15SJohn Edward Broadbent { 549f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 5507e860f15SJohn Edward Broadbent pathString); 5517e860f15SJohn Edward Broadbent return; 5527e860f15SJohn Edward Broadbent } 5537e860f15SJohn Edward Broadbent 5547e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 5557e860f15SJohn Edward Broadbent bool errorInEntry = false; 5567e860f15SJohn Edward Broadbent if (address) 5577e860f15SJohn Edward Broadbent { 558033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 5597e860f15SJohn Edward Broadbent { 5607e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *address, 5617e860f15SJohn Edward Broadbent pathString + "/Address"); 5627e860f15SJohn Edward Broadbent errorInEntry = true; 5637e860f15SJohn Edward Broadbent } 5647e860f15SJohn Edward Broadbent } 5657e860f15SJohn Edward Broadbent else 5667e860f15SJohn Edward Broadbent { 5677e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Address"); 5687e860f15SJohn Edward Broadbent errorInEntry = true; 5697e860f15SJohn Edward Broadbent } 5707e860f15SJohn Edward Broadbent 5717e860f15SJohn Edward Broadbent if (subnetMask) 5727e860f15SJohn Edward Broadbent { 573033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 574033f1e4dSEd Tanous &prefixLength)) 5757e860f15SJohn Edward Broadbent { 5767e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *subnetMask, 5777e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 5787e860f15SJohn Edward Broadbent errorInEntry = true; 5797e860f15SJohn Edward Broadbent } 5807e860f15SJohn Edward Broadbent } 5817e860f15SJohn Edward Broadbent else 5827e860f15SJohn Edward Broadbent { 5837e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, 5847e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 5857e860f15SJohn Edward Broadbent errorInEntry = true; 5867e860f15SJohn Edward Broadbent } 5877e860f15SJohn Edward Broadbent 5887e860f15SJohn Edward Broadbent if (gateway) 5897e860f15SJohn Edward Broadbent { 590033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 5917e860f15SJohn Edward Broadbent { 5927e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *gateway, 5937e860f15SJohn Edward Broadbent pathString + "/Gateway"); 5947e860f15SJohn Edward Broadbent errorInEntry = true; 5957e860f15SJohn Edward Broadbent } 5967e860f15SJohn Edward Broadbent } 5977e860f15SJohn Edward Broadbent else 5987e860f15SJohn Edward Broadbent { 5997e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Gateway"); 6007e860f15SJohn Edward Broadbent errorInEntry = true; 6017e860f15SJohn Edward Broadbent } 6027e860f15SJohn Edward Broadbent 6037e860f15SJohn Edward Broadbent if (errorInEntry) 6047e860f15SJohn Edward Broadbent { 6057e860f15SJohn Edward Broadbent return; 6067e860f15SJohn Edward Broadbent } 6077e860f15SJohn Edward Broadbent 60862598e31SEd Tanous BMCWEB_LOG_DEBUG("Calling createHypervisorIPv4 on : {},{}", ifaceId, 60962598e31SEd Tanous *address); 6107e860f15SJohn Edward Broadbent createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address, 6117e860f15SJohn Edward Broadbent asyncResp); 6127e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 6137e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 6147e860f15SJohn Edward Broadbent } 6157e860f15SJohn Edward Broadbent else 6167e860f15SJohn Edward Broadbent { 6177e860f15SJohn Edward Broadbent if (thisJson.is_null()) 6187e860f15SJohn Edward Broadbent { 6197e860f15SJohn Edward Broadbent deleteHypervisorIPv4(ifaceId, asyncResp); 6207e860f15SJohn Edward Broadbent } 6217e860f15SJohn Edward Broadbent } 6227e860f15SJohn Edward Broadbent } 6237e860f15SJohn Edward Broadbent 62488a8a174SEd Tanous inline void handleHypervisorHostnamePatch( 62588a8a174SEd Tanous const std::string& hostName, 6267e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6277e860f15SJohn Edward Broadbent { 6287e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 6297e860f15SJohn Edward Broadbent { 6307e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 6317e860f15SJohn Edward Broadbent "HostName"); 6327e860f15SJohn Edward Broadbent return; 6337e860f15SJohn Edward Broadbent } 6347e860f15SJohn Edward Broadbent 6357e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 636*d82b5e1fSAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Settings", 637*d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 638*d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 639*d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 640*d82b5e1fSAsmitha Karunanithi "HostName", "HostName", hostName); 6417e860f15SJohn Edward Broadbent } 6427e860f15SJohn Edward Broadbent 6437e860f15SJohn Edward Broadbent inline void 64477179532SEd Tanous setIPv4InterfaceEnabled(const std::string& ifaceId, bool isActive, 6457e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6467e860f15SJohn Edward Broadbent { 647*d82b5e1fSAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Settings", 648*d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor/" + ifaceId + 649*d82b5e1fSAsmitha Karunanithi "/ipv4/addr0", 650*d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Object.Enable", "Enabled", 651*d82b5e1fSAsmitha Karunanithi "InterfaceEnabled", isActive); 6527e860f15SJohn Edward Broadbent } 6537e860f15SJohn Edward Broadbent 654f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceCollectionGet( 655f40448e5SGunnar Mills App& app, const crow::Request& req, 656f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 657f40448e5SGunnar Mills { 658f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 659f40448e5SGunnar Mills { 660f40448e5SGunnar Mills return; 661f40448e5SGunnar Mills } 662f40448e5SGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 663f40448e5SGunnar Mills "xyz.openbmc_project.Network.EthernetInterface"}; 664f40448e5SGunnar Mills 665f40448e5SGunnar Mills dbus::utility::getSubTreePaths( 666f40448e5SGunnar Mills "/xyz/openbmc_project/network/hypervisor", 0, interfaces, 667f40448e5SGunnar Mills [asyncResp]( 6688b24275dSEd Tanous const boost::system::error_code& ec, 669f40448e5SGunnar Mills const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) { 6708b24275dSEd Tanous if (ec) 671f40448e5SGunnar Mills { 672f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "System", "hypervisor"); 673f40448e5SGunnar Mills return; 674f40448e5SGunnar Mills } 675f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 676f40448e5SGunnar Mills "#EthernetInterfaceCollection." 677f40448e5SGunnar Mills "EthernetInterfaceCollection"; 678f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 679f40448e5SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 680f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet " 681f40448e5SGunnar Mills "Interface Collection"; 682f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 683f40448e5SGunnar Mills "Collection of Virtual Management " 684f40448e5SGunnar Mills "Interfaces for the hypervisor"; 685f40448e5SGunnar Mills 686f40448e5SGunnar Mills nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 687f40448e5SGunnar Mills ifaceArray = nlohmann::json::array(); 688f40448e5SGunnar Mills for (const std::string& iface : ifaceList) 689f40448e5SGunnar Mills { 690f40448e5SGunnar Mills sdbusplus::message::object_path path(iface); 691f40448e5SGunnar Mills std::string name = path.filename(); 692f40448e5SGunnar Mills if (name.empty()) 693f40448e5SGunnar Mills { 694f40448e5SGunnar Mills continue; 695f40448e5SGunnar Mills } 696f40448e5SGunnar Mills nlohmann::json::object_t ethIface; 697ef4c65b7SEd Tanous ethIface["@odata.id"] = boost::urls::format( 698ef4c65b7SEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", name); 699b2ba3072SPatrick Williams ifaceArray.emplace_back(std::move(ethIface)); 700f40448e5SGunnar Mills } 701f40448e5SGunnar Mills asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 702f40448e5SGunnar Mills }); 703f40448e5SGunnar Mills } 704f40448e5SGunnar Mills 705f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceGet( 706f40448e5SGunnar Mills App& app, const crow::Request& req, 707f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 708f40448e5SGunnar Mills { 709f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 710f40448e5SGunnar Mills { 711f40448e5SGunnar Mills return; 712f40448e5SGunnar Mills } 713f40448e5SGunnar Mills getHypervisorIfaceData( 714f40448e5SGunnar Mills id, [asyncResp, ifaceId{std::string(id)}]( 71577179532SEd Tanous bool success, const EthernetInterfaceData& ethData, 71677179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) { 717f40448e5SGunnar Mills if (!success) 718f40448e5SGunnar Mills { 719f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 720f40448e5SGunnar Mills ifaceId); 721f40448e5SGunnar Mills return; 722f40448e5SGunnar Mills } 723f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 72493bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 725f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface"; 726f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 727f40448e5SGunnar Mills "Hypervisor's Virtual Management Ethernet Interface"; 728f40448e5SGunnar Mills parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData, 729f40448e5SGunnar Mills ipv4Data); 730f40448e5SGunnar Mills }); 731f40448e5SGunnar Mills } 732f40448e5SGunnar Mills 7338d8c30c3SGunnar Mills inline void handleHypervisorSystemGet( 7348d8c30c3SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7358d8c30c3SGunnar Mills { 7368d8c30c3SGunnar Mills sdbusplus::asio::getProperty<std::string>( 7378d8c30c3SGunnar Mills *crow::connections::systemBus, "xyz.openbmc_project.Settings", 7388d8c30c3SGunnar Mills "/xyz/openbmc_project/network/hypervisor", 7398d8c30c3SGunnar Mills "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 7408d8c30c3SGunnar Mills [asyncResp](const boost::system::error_code& ec, 7418d8c30c3SGunnar Mills const std::string& /*hostName*/) { 7428d8c30c3SGunnar Mills if (ec) 7438d8c30c3SGunnar Mills { 7448d8c30c3SGunnar Mills messages::resourceNotFound(asyncResp->res, "System", "hypervisor"); 7458d8c30c3SGunnar Mills return; 7468d8c30c3SGunnar Mills } 74762598e31SEd Tanous BMCWEB_LOG_DEBUG("Hypervisor is available"); 7488d8c30c3SGunnar Mills 7498d8c30c3SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 7508d8c30c3SGunnar Mills "#ComputerSystem.v1_6_0.ComputerSystem"; 7518d8c30c3SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 7528d8c30c3SGunnar Mills "/redfish/v1/Systems/hypervisor"; 7538d8c30c3SGunnar Mills asyncResp->res.jsonValue["Description"] = "Hypervisor"; 7548d8c30c3SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor"; 7558d8c30c3SGunnar Mills asyncResp->res.jsonValue["Id"] = "hypervisor"; 7568d8c30c3SGunnar Mills asyncResp->res.jsonValue["SystemType"] = "OS"; 7578d8c30c3SGunnar Mills nlohmann::json::array_t managedBy; 7588d8c30c3SGunnar Mills nlohmann::json::object_t manager; 7598d8c30c3SGunnar Mills manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 760ad539545SPatrick Williams managedBy.emplace_back(std::move(manager)); 7618d8c30c3SGunnar Mills asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); 7628d8c30c3SGunnar Mills asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 7638d8c30c3SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 7648d8c30c3SGunnar Mills getHypervisorState(asyncResp); 7658d8c30c3SGunnar Mills getHypervisorActions(asyncResp); 7668d8c30c3SGunnar Mills // TODO: Add "SystemType" : "hypervisor" 7678d8c30c3SGunnar Mills }); 7688d8c30c3SGunnar Mills } 7698d8c30c3SGunnar Mills 770f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfacePatch( 771f40448e5SGunnar Mills App& app, const crow::Request& req, 772f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 773f40448e5SGunnar Mills const std::string& ifaceId) 774f40448e5SGunnar Mills { 775f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 776f40448e5SGunnar Mills { 777f40448e5SGunnar Mills return; 778f40448e5SGunnar Mills } 779f40448e5SGunnar Mills std::optional<std::string> hostName; 780f40448e5SGunnar Mills std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses; 781f40448e5SGunnar Mills std::optional<nlohmann::json> ipv4Addresses; 782f40448e5SGunnar Mills std::optional<nlohmann::json> dhcpv4; 783f40448e5SGunnar Mills std::optional<bool> ipv4DHCPEnabled; 784f40448e5SGunnar Mills 785f40448e5SGunnar Mills if (!json_util::readJsonPatch(req, asyncResp->res, "HostName", hostName, 786f40448e5SGunnar Mills "IPv4StaticAddresses", ipv4StaticAddresses, 787f40448e5SGunnar Mills "IPv4Addresses", ipv4Addresses, "DHCPv4", 788f40448e5SGunnar Mills dhcpv4)) 789f40448e5SGunnar Mills { 790f40448e5SGunnar Mills return; 791f40448e5SGunnar Mills } 792f40448e5SGunnar Mills 793f40448e5SGunnar Mills if (ipv4Addresses) 794f40448e5SGunnar Mills { 795f40448e5SGunnar Mills messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 796f40448e5SGunnar Mills return; 797f40448e5SGunnar Mills } 798f40448e5SGunnar Mills 799f40448e5SGunnar Mills if (dhcpv4) 800f40448e5SGunnar Mills { 801f40448e5SGunnar Mills if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 802f40448e5SGunnar Mills ipv4DHCPEnabled)) 803f40448e5SGunnar Mills { 804f40448e5SGunnar Mills return; 805f40448e5SGunnar Mills } 806f40448e5SGunnar Mills } 807f40448e5SGunnar Mills 808f40448e5SGunnar Mills getHypervisorIfaceData( 8095a39f77aSPatrick Williams ifaceId, [asyncResp, ifaceId, hostName = std::move(hostName), 8105a39f77aSPatrick Williams ipv4StaticAddresses = std::move(ipv4StaticAddresses), 8115a39f77aSPatrick Williams ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)]( 8125a39f77aSPatrick Williams bool success, const EthernetInterfaceData& ethData, 81377179532SEd Tanous const std::vector<IPv4AddressData>&) { 814f40448e5SGunnar Mills if (!success) 815f40448e5SGunnar Mills { 816f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 817f40448e5SGunnar Mills ifaceId); 818f40448e5SGunnar Mills return; 819f40448e5SGunnar Mills } 820f40448e5SGunnar Mills 821f40448e5SGunnar Mills if (ipv4StaticAddresses) 822f40448e5SGunnar Mills { 823f40448e5SGunnar Mills const nlohmann::json& ipv4Static = *ipv4StaticAddresses; 824f40448e5SGunnar Mills if (ipv4Static.begin() == ipv4Static.end()) 825f40448e5SGunnar Mills { 8262e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, ipv4Static, 827f40448e5SGunnar Mills "IPv4StaticAddresses"); 828f40448e5SGunnar Mills return; 829f40448e5SGunnar Mills } 830f40448e5SGunnar Mills 831f40448e5SGunnar Mills // One and only one hypervisor instance supported 832f40448e5SGunnar Mills if (ipv4Static.size() != 1) 833f40448e5SGunnar Mills { 834f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, ipv4Static, 835f40448e5SGunnar Mills "IPv4StaticAddresses"); 836f40448e5SGunnar Mills return; 837f40448e5SGunnar Mills } 838f40448e5SGunnar Mills 839f40448e5SGunnar Mills const nlohmann::json& ipv4Json = ipv4Static[0]; 840f40448e5SGunnar Mills // Check if the param is 'null'. If its null, it means 841f40448e5SGunnar Mills // that user wants to delete the IP address. Deleting 842f40448e5SGunnar Mills // the IP address is allowed only if its statically 843f40448e5SGunnar Mills // configured. Deleting the address originated from DHCP 844f40448e5SGunnar Mills // is not allowed. 845f40448e5SGunnar Mills if ((ipv4Json.is_null()) && 846f40448e5SGunnar Mills (translateDhcpEnabledToBool(ethData.dhcpEnabled, true))) 847f40448e5SGunnar Mills { 84862598e31SEd Tanous BMCWEB_LOG_INFO("Ignoring the delete on ipv4StaticAddresses " 84962598e31SEd Tanous "as the interface is DHCP enabled"); 850f40448e5SGunnar Mills } 851f40448e5SGunnar Mills else 852f40448e5SGunnar Mills { 853f40448e5SGunnar Mills handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, asyncResp); 854f40448e5SGunnar Mills } 855f40448e5SGunnar Mills } 856f40448e5SGunnar Mills 857f40448e5SGunnar Mills if (hostName) 858f40448e5SGunnar Mills { 859f40448e5SGunnar Mills handleHypervisorHostnamePatch(*hostName, asyncResp); 860f40448e5SGunnar Mills } 861f40448e5SGunnar Mills 862f40448e5SGunnar Mills if (dhcpv4) 863f40448e5SGunnar Mills { 864f40448e5SGunnar Mills setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 865f40448e5SGunnar Mills } 866f40448e5SGunnar Mills 867f40448e5SGunnar Mills // Set this interface to disabled/inactive. This will be set 868f40448e5SGunnar Mills // to enabled/active by the pldm once the hypervisor 869f40448e5SGunnar Mills // consumes the updated settings from the user. 870f40448e5SGunnar Mills setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 871f40448e5SGunnar Mills }); 872f40448e5SGunnar Mills asyncResp->res.result(boost::beast::http::status::accepted); 873f40448e5SGunnar Mills } 874f40448e5SGunnar Mills 875a5d0cedbSGunnar Mills inline void handleHypervisorResetActionGet( 876a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 877a5d0cedbSGunnar Mills { 878a5d0cedbSGunnar Mills // Only return action info if hypervisor D-Bus object present 879a5d0cedbSGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 880a5d0cedbSGunnar Mills "xyz.openbmc_project.State.Host"}; 881a5d0cedbSGunnar Mills dbus::utility::getDbusObject( 882a5d0cedbSGunnar Mills "/xyz/openbmc_project/state/hypervisor0", interfaces, 883a5d0cedbSGunnar Mills [asyncResp]( 884a5d0cedbSGunnar Mills const boost::system::error_code& ec, 885a5d0cedbSGunnar Mills const std::vector<std::pair<std::string, std::vector<std::string>>>& 886a5d0cedbSGunnar Mills objInfo) { 887a5d0cedbSGunnar Mills if (ec) 888a5d0cedbSGunnar Mills { 88962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 890a5d0cedbSGunnar Mills 891a5d0cedbSGunnar Mills // No hypervisor objects found by mapper 892a5d0cedbSGunnar Mills if (ec.value() == boost::system::errc::io_error) 893a5d0cedbSGunnar Mills { 894a5d0cedbSGunnar Mills messages::resourceNotFound(asyncResp->res, "hypervisor", 895a5d0cedbSGunnar Mills "ResetActionInfo"); 896a5d0cedbSGunnar Mills return; 897a5d0cedbSGunnar Mills } 898a5d0cedbSGunnar Mills 899a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 900a5d0cedbSGunnar Mills return; 901a5d0cedbSGunnar Mills } 902a5d0cedbSGunnar Mills 903a5d0cedbSGunnar Mills // One and only one hypervisor instance supported 904a5d0cedbSGunnar Mills if (objInfo.size() != 1) 905a5d0cedbSGunnar Mills { 906a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 907a5d0cedbSGunnar Mills return; 908a5d0cedbSGunnar Mills } 909a5d0cedbSGunnar Mills 910a5d0cedbSGunnar Mills // The hypervisor object only support the ability to 911a5d0cedbSGunnar Mills // turn On The system object Action should be utilized 912a5d0cedbSGunnar Mills // for other operations 913a5d0cedbSGunnar Mills 914a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 915a5d0cedbSGunnar Mills "#ActionInfo.v1_1_2.ActionInfo"; 916a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 917a5d0cedbSGunnar Mills "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 918a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 919a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 920a5d0cedbSGunnar Mills nlohmann::json::array_t parameters; 921a5d0cedbSGunnar Mills nlohmann::json::object_t parameter; 922a5d0cedbSGunnar Mills parameter["Name"] = "ResetType"; 923a5d0cedbSGunnar Mills parameter["Required"] = true; 924a5d0cedbSGunnar Mills parameter["DataType"] = "String"; 925a5d0cedbSGunnar Mills nlohmann::json::array_t allowed; 926ad539545SPatrick Williams allowed.emplace_back("On"); 927a5d0cedbSGunnar Mills parameter["AllowableValues"] = std::move(allowed); 928ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 929a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 930a5d0cedbSGunnar Mills }); 931a5d0cedbSGunnar Mills } 932a5d0cedbSGunnar Mills 933a5d0cedbSGunnar Mills inline void handleHypervisorSystemResetPost( 934a5d0cedbSGunnar Mills App& app, const crow::Request& req, 935a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 936a5d0cedbSGunnar Mills { 937a5d0cedbSGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 938a5d0cedbSGunnar Mills { 939a5d0cedbSGunnar Mills return; 940a5d0cedbSGunnar Mills } 941a5d0cedbSGunnar Mills std::optional<std::string> resetType; 942a5d0cedbSGunnar Mills if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 943a5d0cedbSGunnar Mills { 944a5d0cedbSGunnar Mills // readJson adds appropriate error to response 945a5d0cedbSGunnar Mills return; 946a5d0cedbSGunnar Mills } 947a5d0cedbSGunnar Mills 948a5d0cedbSGunnar Mills if (!resetType) 949a5d0cedbSGunnar Mills { 950a5d0cedbSGunnar Mills messages::actionParameterMissing(asyncResp->res, "ComputerSystem.Reset", 951a5d0cedbSGunnar Mills "ResetType"); 952a5d0cedbSGunnar Mills return; 953a5d0cedbSGunnar Mills } 954a5d0cedbSGunnar Mills 955a5d0cedbSGunnar Mills // Hypervisor object only support On operation 956a5d0cedbSGunnar Mills if (resetType != "On") 957a5d0cedbSGunnar Mills { 958a5d0cedbSGunnar Mills messages::propertyValueNotInList(asyncResp->res, *resetType, 959a5d0cedbSGunnar Mills "ResetType"); 960a5d0cedbSGunnar Mills return; 961a5d0cedbSGunnar Mills } 962a5d0cedbSGunnar Mills 963a5d0cedbSGunnar Mills std::string command = "xyz.openbmc_project.State.Host.Transition.On"; 964a5d0cedbSGunnar Mills 9659ae226faSGeorge Liu sdbusplus::asio::setProperty( 9669ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.State.Hypervisor", 9679ae226faSGeorge Liu "/xyz/openbmc_project/state/hypervisor0", 9689ae226faSGeorge Liu "xyz.openbmc_project.State.Host", "RequestedHostTransition", command, 969a5d0cedbSGunnar Mills [asyncResp, resetType](const boost::system::error_code& ec) { 970a5d0cedbSGunnar Mills if (ec) 971a5d0cedbSGunnar Mills { 97262598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 973a5d0cedbSGunnar Mills if (ec.value() == boost::asio::error::invalid_argument) 974a5d0cedbSGunnar Mills { 975a5d0cedbSGunnar Mills messages::actionParameterNotSupported(asyncResp->res, 976a5d0cedbSGunnar Mills *resetType, "Reset"); 977a5d0cedbSGunnar Mills return; 978a5d0cedbSGunnar Mills } 979a5d0cedbSGunnar Mills 980a5d0cedbSGunnar Mills if (ec.value() == boost::asio::error::host_unreachable) 981a5d0cedbSGunnar Mills { 982a5d0cedbSGunnar Mills messages::resourceNotFound(asyncResp->res, "Actions", "Reset"); 983a5d0cedbSGunnar Mills return; 984a5d0cedbSGunnar Mills } 985a5d0cedbSGunnar Mills 986a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 987a5d0cedbSGunnar Mills return; 988a5d0cedbSGunnar Mills } 989a5d0cedbSGunnar Mills messages::success(asyncResp->res); 9909ae226faSGeorge Liu }); 991a5d0cedbSGunnar Mills } 992a5d0cedbSGunnar Mills 9937e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 9947e860f15SJohn Edward Broadbent { 9957e860f15SJohn Edward Broadbent /** 9967e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 9977e860f15SJohn Edward Broadbent * Hypervisor Interface 9987e860f15SJohn Edward Broadbent */ 9997e860f15SJohn Edward Broadbent 10007e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 1001ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 1002f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 1003f40448e5SGunnar Mills handleHypervisorEthernetInterfaceCollectionGet, std::ref(app))); 10047e860f15SJohn Edward Broadbent 10057e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 10067e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 1007ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 1008f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 1009f40448e5SGunnar Mills handleHypervisorEthernetInterfaceGet, std::ref(app))); 1010d5afb2caSAndrew Geissler 10117e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 10127e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 1013ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 1014f40448e5SGunnar Mills .methods(boost::beast::http::verb::patch)(std::bind_front( 1015f40448e5SGunnar Mills handleHypervisorEthernetInterfacePatch, std::ref(app))); 10164fbaf64aSAndrew Geissler 10177e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 10184fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/") 1019ed398213SEd Tanous .privileges(redfish::privileges::postComputerSystem) 10207e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1021a5d0cedbSGunnar Mills std::bind_front(handleHypervisorSystemResetPost, std::ref(app))); 10224fbaf64aSAndrew Geissler } 102388a8a174SEd Tanous } // namespace redfish 1024