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 13d5afb2caSAndrew Geissler #include <boost/container/flat_set.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 21b8983957SEd Tanous // TODO(ed) requestRoutesHypervisorSystems seems to have copy-pasted a 22b8983957SEd Tanous // lot of code, and has a number of methods that have name conflicts with the 23b8983957SEd Tanous // normal ethernet internfaces in ethernet.hpp. For the moment, we'll put 24b8983957SEd Tanous // hypervisor in a namespace to isolate it, but these methods eventually need 25b8983957SEd Tanous // deduplicated 2688a8a174SEd Tanous namespace redfish 27d5afb2caSAndrew Geissler { 28d5afb2caSAndrew Geissler 29d5afb2caSAndrew Geissler /** 30cc0bb6f2SAndrew Geissler * @brief Retrieves hypervisor state properties over dbus 31cc0bb6f2SAndrew Geissler * 32cc0bb6f2SAndrew Geissler * The hypervisor state object is optional so this function will only set the 33cc0bb6f2SAndrew Geissler * state variables if the object is found 34cc0bb6f2SAndrew Geissler * 35cc0bb6f2SAndrew Geissler * @param[in] aResp Shared pointer for completing asynchronous calls. 36cc0bb6f2SAndrew Geissler * 37cc0bb6f2SAndrew Geissler * @return None. 38cc0bb6f2SAndrew Geissler */ 398d1b46d7Szhanghch05 inline void getHypervisorState(const std::shared_ptr<bmcweb::AsyncResp>& aResp) 40cc0bb6f2SAndrew Geissler { 41cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "Get hypervisor state information."; 421e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 431e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Hypervisor", 441e1e598dSJonathan Doman "/xyz/openbmc_project/state/hypervisor0", 451e1e598dSJonathan Doman "xyz.openbmc_project.State.Host", "CurrentHostState", 465e7e2dc5SEd Tanous [aResp](const boost::system::error_code& ec, 471e1e598dSJonathan Doman const std::string& hostState) { 48cc0bb6f2SAndrew Geissler if (ec) 49cc0bb6f2SAndrew Geissler { 50cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 51cc0bb6f2SAndrew Geissler // This is an optional D-Bus object so just return if 52cc0bb6f2SAndrew Geissler // error occurs 53cc0bb6f2SAndrew Geissler return; 54cc0bb6f2SAndrew Geissler } 55cc0bb6f2SAndrew Geissler 561e1e598dSJonathan Doman BMCWEB_LOG_DEBUG << "Hypervisor state: " << hostState; 57cc0bb6f2SAndrew Geissler // Verify Host State 581e1e598dSJonathan Doman if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") 59cc0bb6f2SAndrew Geissler { 60cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 61cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Enabled"; 62cc0bb6f2SAndrew Geissler } 631e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 641e1e598dSJonathan Doman "Quiesced") 65cc0bb6f2SAndrew Geissler { 66cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 67cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Quiesced"; 68cc0bb6f2SAndrew Geissler } 691e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 701e1e598dSJonathan Doman "Standby") 71cc0bb6f2SAndrew Geissler { 72cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 73cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 74cc0bb6f2SAndrew Geissler } 751e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 761e1e598dSJonathan Doman "TransitioningToRunning") 77cc0bb6f2SAndrew Geissler { 78cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "PoweringOn"; 79cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Starting"; 80cc0bb6f2SAndrew Geissler } 811e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 821e1e598dSJonathan Doman "TransitioningToOff") 83cc0bb6f2SAndrew Geissler { 84cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "PoweringOff"; 85cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Enabled"; 86cc0bb6f2SAndrew Geissler } 87002d39b4SEd Tanous else if (hostState == "xyz.openbmc_project.State.Host.HostState.Off") 88cc0bb6f2SAndrew Geissler { 89cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "Off"; 90cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Disabled"; 91cc0bb6f2SAndrew Geissler } 92cc0bb6f2SAndrew Geissler else 93cc0bb6f2SAndrew Geissler { 94cc0bb6f2SAndrew Geissler messages::internalError(aResp->res); 95cc0bb6f2SAndrew Geissler return; 96cc0bb6f2SAndrew Geissler } 971e1e598dSJonathan Doman }); 98cc0bb6f2SAndrew Geissler } 99cc0bb6f2SAndrew Geissler 100cc0bb6f2SAndrew Geissler /** 1014fbaf64aSAndrew Geissler * @brief Populate Actions if any are valid for hypervisor object 1024fbaf64aSAndrew Geissler * 1034fbaf64aSAndrew Geissler * The hypervisor state object is optional so this function will only set the 1044fbaf64aSAndrew Geissler * Action if the object is found 1054fbaf64aSAndrew Geissler * 1064fbaf64aSAndrew Geissler * @param[in] aResp Shared pointer for completing asynchronous calls. 1074fbaf64aSAndrew Geissler * 1084fbaf64aSAndrew Geissler * @return None. 1094fbaf64aSAndrew Geissler */ 1108d1b46d7Szhanghch05 inline void 1118d1b46d7Szhanghch05 getHypervisorActions(const std::shared_ptr<bmcweb::AsyncResp>& aResp) 1124fbaf64aSAndrew Geissler { 1134fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "Get hypervisor actions."; 1142b73119cSGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1152b73119cSGeorge Liu "xyz.openbmc_project.State.Host"}; 1162b73119cSGeorge Liu dbus::utility::getDbusObject( 1172b73119cSGeorge Liu "/xyz/openbmc_project/state/hypervisor0", interfaces, 1184fbaf64aSAndrew Geissler [aResp]( 1192b73119cSGeorge Liu const boost::system::error_code& ec, 1204fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1214fbaf64aSAndrew Geissler objInfo) { 1224fbaf64aSAndrew Geissler if (ec) 1234fbaf64aSAndrew Geissler { 1244fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1254fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1264fbaf64aSAndrew Geissler // error occurs 1274fbaf64aSAndrew Geissler return; 1284fbaf64aSAndrew Geissler } 1294fbaf64aSAndrew Geissler 13026f6976fSEd Tanous if (objInfo.empty()) 1314fbaf64aSAndrew Geissler { 1324fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1334fbaf64aSAndrew Geissler // if there is no instance found 1344fbaf64aSAndrew Geissler return; 1354fbaf64aSAndrew Geissler } 1364fbaf64aSAndrew Geissler 1374fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1384fbaf64aSAndrew Geissler { 1394fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1404fbaf64aSAndrew Geissler // error 1414fbaf64aSAndrew Geissler messages::internalError(aResp->res); 1424fbaf64aSAndrew Geissler return; 1434fbaf64aSAndrew Geissler } 1444fbaf64aSAndrew Geissler 1454fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 146613dabeaSEd Tanous nlohmann::json& reset = 147613dabeaSEd Tanous aResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]; 148613dabeaSEd Tanous reset["target"] = 149613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"; 150613dabeaSEd Tanous reset["@Redfish.ActionInfo"] = 151613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 1522b73119cSGeorge Liu }); 1534fbaf64aSAndrew Geissler } 1544fbaf64aSAndrew Geissler 155d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 156711ac7a9SEd Tanous const std::string& ethIfaceId, 157711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 158d5afb2caSAndrew Geissler EthernetInterfaceData& ethData, 159d5afb2caSAndrew Geissler boost::container::flat_set<IPv4AddressData>& ipv4Config) 160d5afb2caSAndrew Geissler { 161d5afb2caSAndrew Geissler bool idFound = false; 162d5afb2caSAndrew Geissler for (const auto& objpath : dbusData) 163d5afb2caSAndrew Geissler { 164d5afb2caSAndrew Geissler for (const auto& ifacePair : objpath.second) 165d5afb2caSAndrew Geissler { 166d5afb2caSAndrew Geissler if (objpath.first == 167d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId) 168d5afb2caSAndrew Geissler { 169d5afb2caSAndrew Geissler idFound = true; 170d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 171d5afb2caSAndrew Geissler { 172d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 173d5afb2caSAndrew Geissler { 174d5afb2caSAndrew Geissler if (propertyPair.first == "MACAddress") 175d5afb2caSAndrew Geissler { 176d5afb2caSAndrew Geissler const std::string* mac = 177d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 178d5afb2caSAndrew Geissler if (mac != nullptr) 179d5afb2caSAndrew Geissler { 18082695a5bSJiaqing Zhao ethData.macAddress = *mac; 181d5afb2caSAndrew Geissler } 182d5afb2caSAndrew Geissler } 183d5afb2caSAndrew Geissler } 184d5afb2caSAndrew Geissler } 185d5afb2caSAndrew Geissler else if (ifacePair.first == 186d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface") 187d5afb2caSAndrew Geissler { 188d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 189d5afb2caSAndrew Geissler { 190d5afb2caSAndrew Geissler if (propertyPair.first == "DHCPEnabled") 191d5afb2caSAndrew Geissler { 192d5afb2caSAndrew Geissler const std::string* dhcp = 193d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 194d5afb2caSAndrew Geissler if (dhcp != nullptr) 195d5afb2caSAndrew Geissler { 19682695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcp; 197d5afb2caSAndrew Geissler break; // Interested on only "DHCPEnabled". 198d5afb2caSAndrew Geissler // Stop parsing since we got the 199d5afb2caSAndrew Geissler // "DHCPEnabled" value. 200d5afb2caSAndrew Geissler } 201d5afb2caSAndrew Geissler } 202d5afb2caSAndrew Geissler } 203d5afb2caSAndrew Geissler } 204d5afb2caSAndrew Geissler } 205d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor/" + 206d5afb2caSAndrew Geissler ethIfaceId + "/ipv4/addr0") 207d5afb2caSAndrew Geissler { 208d5afb2caSAndrew Geissler std::pair<boost::container::flat_set<IPv4AddressData>::iterator, 209d5afb2caSAndrew Geissler bool> 210d5afb2caSAndrew Geissler it = ipv4Config.insert(IPv4AddressData{}); 211d5afb2caSAndrew Geissler IPv4AddressData& ipv4Address = *it.first; 212d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Object.Enable") 213d5afb2caSAndrew Geissler { 2149eb808c1SEd Tanous for (const auto& property : ifacePair.second) 215d5afb2caSAndrew Geissler { 216d5afb2caSAndrew Geissler if (property.first == "Enabled") 217d5afb2caSAndrew Geissler { 218d5afb2caSAndrew Geissler const bool* intfEnable = 219d5afb2caSAndrew Geissler std::get_if<bool>(&property.second); 220d5afb2caSAndrew Geissler if (intfEnable != nullptr) 221d5afb2caSAndrew Geissler { 222d5afb2caSAndrew Geissler ipv4Address.isActive = *intfEnable; 223d5afb2caSAndrew Geissler break; 224d5afb2caSAndrew Geissler } 225d5afb2caSAndrew Geissler } 226d5afb2caSAndrew Geissler } 227d5afb2caSAndrew Geissler } 228d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.IP") 229d5afb2caSAndrew Geissler { 2309eb808c1SEd Tanous for (const auto& property : ifacePair.second) 231d5afb2caSAndrew Geissler { 232d5afb2caSAndrew Geissler if (property.first == "Address") 233d5afb2caSAndrew Geissler { 234d5afb2caSAndrew Geissler const std::string* address = 235d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 236d5afb2caSAndrew Geissler if (address != nullptr) 237d5afb2caSAndrew Geissler { 238d5afb2caSAndrew Geissler ipv4Address.address = *address; 239d5afb2caSAndrew Geissler } 240d5afb2caSAndrew Geissler } 241d5afb2caSAndrew Geissler else if (property.first == "Origin") 242d5afb2caSAndrew Geissler { 243d5afb2caSAndrew Geissler const std::string* origin = 244d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 245d5afb2caSAndrew Geissler if (origin != nullptr) 246d5afb2caSAndrew Geissler { 247d5afb2caSAndrew Geissler ipv4Address.origin = 248d5afb2caSAndrew Geissler translateAddressOriginDbusToRedfish(*origin, 249d5afb2caSAndrew Geissler true); 250d5afb2caSAndrew Geissler } 251d5afb2caSAndrew Geissler } 252d5afb2caSAndrew Geissler else if (property.first == "PrefixLength") 253d5afb2caSAndrew Geissler { 254d5afb2caSAndrew Geissler const uint8_t* mask = 255d5afb2caSAndrew Geissler std::get_if<uint8_t>(&property.second); 256d5afb2caSAndrew Geissler if (mask != nullptr) 257d5afb2caSAndrew Geissler { 258d5afb2caSAndrew Geissler // convert it to the string 259d5afb2caSAndrew Geissler ipv4Address.netmask = getNetmask(*mask); 260d5afb2caSAndrew Geissler } 261d5afb2caSAndrew Geissler } 262889ff694SAsmitha Karunanithi else if (property.first == "Type" || 263889ff694SAsmitha Karunanithi property.first == "Gateway") 264889ff694SAsmitha Karunanithi { 265889ff694SAsmitha Karunanithi // Type & Gateway is not used 266889ff694SAsmitha Karunanithi continue; 267889ff694SAsmitha Karunanithi } 268d5afb2caSAndrew Geissler else 269d5afb2caSAndrew Geissler { 270d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR 271d5afb2caSAndrew Geissler << "Got extra property: " << property.first 272d5afb2caSAndrew Geissler << " on the " << objpath.first.str << " object"; 273d5afb2caSAndrew Geissler } 274d5afb2caSAndrew Geissler } 275d5afb2caSAndrew Geissler } 276d5afb2caSAndrew Geissler } 277d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 278d5afb2caSAndrew Geissler { 279d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 280d5afb2caSAndrew Geissler // need to check eth number 281d5afb2caSAndrew Geissler if (ifacePair.first == 282d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 283d5afb2caSAndrew Geissler { 284d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 285d5afb2caSAndrew Geissler { 286d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 287d5afb2caSAndrew Geissler { 288d5afb2caSAndrew Geissler const std::string* hostName = 289d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 290d5afb2caSAndrew Geissler if (hostName != nullptr) 291d5afb2caSAndrew Geissler { 29282695a5bSJiaqing Zhao ethData.hostName = *hostName; 293d5afb2caSAndrew Geissler } 294d5afb2caSAndrew Geissler } 295d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 296d5afb2caSAndrew Geissler { 297d5afb2caSAndrew Geissler const std::string* defaultGateway = 298d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 299d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 300d5afb2caSAndrew Geissler { 30182695a5bSJiaqing Zhao ethData.defaultGateway = *defaultGateway; 302d5afb2caSAndrew Geissler } 303d5afb2caSAndrew Geissler } 304d5afb2caSAndrew Geissler } 305d5afb2caSAndrew Geissler } 306d5afb2caSAndrew Geissler } 307d5afb2caSAndrew Geissler } 308d5afb2caSAndrew Geissler } 309d5afb2caSAndrew Geissler return idFound; 310d5afb2caSAndrew Geissler } 311d5afb2caSAndrew Geissler /** 312d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 313d5afb2caSAndrew Geissler * Interface Object from Settings Manager 314d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 315d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 316d5afb2caSAndrew Geissler * into JSON 317d5afb2caSAndrew Geissler */ 318d5afb2caSAndrew Geissler template <typename CallbackFunc> 319d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 320d5afb2caSAndrew Geissler CallbackFunc&& callback) 321d5afb2caSAndrew Geissler { 322d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 323f94c4ecfSEd Tanous [ethIfaceId{std::string{ethIfaceId}}, 324f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 3255e7e2dc5SEd Tanous const boost::system::error_code& error, 326711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& resp) { 327d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 328d5afb2caSAndrew Geissler boost::container::flat_set<IPv4AddressData> ipv4Data; 329d5afb2caSAndrew Geissler if (error) 330d5afb2caSAndrew Geissler { 331d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 332d5afb2caSAndrew Geissler return; 333d5afb2caSAndrew Geissler } 334d5afb2caSAndrew Geissler 335002d39b4SEd Tanous bool found = 336002d39b4SEd Tanous extractHypervisorInterfaceData(ethIfaceId, resp, ethData, ipv4Data); 337d5afb2caSAndrew Geissler if (!found) 338d5afb2caSAndrew Geissler { 339d5afb2caSAndrew Geissler BMCWEB_LOG_INFO << "Hypervisor Interface not found"; 340d5afb2caSAndrew Geissler } 341d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 342d5afb2caSAndrew Geissler }, 343d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", "/", 344d5afb2caSAndrew Geissler "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 345d5afb2caSAndrew Geissler } 346d5afb2caSAndrew Geissler 347d5afb2caSAndrew Geissler /** 348d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 349d5afb2caSAndrew Geissler * 350d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 351d5afb2caSAndrew Geissler * @param[in] ipv4Address Address from the incoming request 352d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 353d5afb2caSAndrew Geissler * 354d5afb2caSAndrew Geissler * @return None. 355d5afb2caSAndrew Geissler */ 3568d1b46d7Szhanghch05 inline void 3578d1b46d7Szhanghch05 setHypervisorIPv4Address(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 358d5afb2caSAndrew Geissler const std::string& ethIfaceId, 359d5afb2caSAndrew Geissler const std::string& ipv4Address) 360d5afb2caSAndrew Geissler { 361d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor IPaddress : " << ipv4Address 362d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 363d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 3645e7e2dc5SEd Tanous [aResp](const boost::system::error_code& ec) { 365d5afb2caSAndrew Geissler if (ec) 366d5afb2caSAndrew Geissler { 367d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 368d5afb2caSAndrew Geissler return; 369d5afb2caSAndrew Geissler } 370d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress is Set"; 371d5afb2caSAndrew Geissler }, 372d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 373d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 374d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 375d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Address", 376168e20c1SEd Tanous dbus::utility::DbusVariantType(ipv4Address)); 377d5afb2caSAndrew Geissler } 378d5afb2caSAndrew Geissler 379d5afb2caSAndrew Geissler /** 380d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 381d5afb2caSAndrew Geissler * 382d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 383d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 384d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 385d5afb2caSAndrew Geissler * 386d5afb2caSAndrew Geissler * @return None. 387d5afb2caSAndrew Geissler */ 3888d1b46d7Szhanghch05 inline void 3898d1b46d7Szhanghch05 setHypervisorIPv4Subnet(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 3908d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 391d5afb2caSAndrew Geissler { 392d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor subnet : " << subnet 393d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 394d5afb2caSAndrew Geissler 395d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 3965e7e2dc5SEd Tanous [aResp](const boost::system::error_code& ec) { 397d5afb2caSAndrew Geissler if (ec) 398d5afb2caSAndrew Geissler { 399d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 400d5afb2caSAndrew Geissler return; 401d5afb2caSAndrew Geissler } 402d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "SubnetMask is Set"; 403d5afb2caSAndrew Geissler }, 404d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 405d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 406d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 407d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "PrefixLength", 408168e20c1SEd Tanous dbus::utility::DbusVariantType(subnet)); 409d5afb2caSAndrew Geissler } 410d5afb2caSAndrew Geissler 411d5afb2caSAndrew Geissler /** 412d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 413d5afb2caSAndrew Geissler * 414d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 415d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 416d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 417d5afb2caSAndrew Geissler * 418d5afb2caSAndrew Geissler * @return None. 419d5afb2caSAndrew Geissler */ 4208d1b46d7Szhanghch05 inline void 4218d1b46d7Szhanghch05 setHypervisorIPv4Gateway(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 422d5afb2caSAndrew Geissler const std::string& gateway) 423d5afb2caSAndrew Geissler { 424d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG 425d5afb2caSAndrew Geissler << "Setting the DefaultGateway to the last configured gateway"; 426d5afb2caSAndrew Geissler 427d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 4285e7e2dc5SEd Tanous [aResp](const boost::system::error_code& ec) { 429d5afb2caSAndrew Geissler if (ec) 430d5afb2caSAndrew Geissler { 431d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 432d5afb2caSAndrew Geissler return; 433d5afb2caSAndrew Geissler } 434d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Default Gateway is Set"; 435d5afb2caSAndrew Geissler }, 436d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 437d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor", 438d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 439d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration", "DefaultGateway", 440168e20c1SEd Tanous dbus::utility::DbusVariantType(gateway)); 441d5afb2caSAndrew Geissler } 442d5afb2caSAndrew Geissler 443d5afb2caSAndrew Geissler /** 444d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 445d5afb2caSAndrew Geissler * 446d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 447d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 448d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 449d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 450d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 451d5afb2caSAndrew Geissler * 452d5afb2caSAndrew Geissler * @return None 453d5afb2caSAndrew Geissler */ 4548d1b46d7Szhanghch05 inline void 4558d1b46d7Szhanghch05 createHypervisorIPv4(const std::string& ifaceId, uint8_t prefixLength, 4568d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4578d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 458d5afb2caSAndrew Geissler { 459d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 460d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 461d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 462d5afb2caSAndrew Geissler } 463d5afb2caSAndrew Geissler 464d5afb2caSAndrew Geissler /** 465d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 466d5afb2caSAndrew Geissler * 467d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 468d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 469d5afb2caSAndrew Geissler * 470d5afb2caSAndrew Geissler * @return None 471d5afb2caSAndrew Geissler */ 4728d1b46d7Szhanghch05 inline void 4738d1b46d7Szhanghch05 deleteHypervisorIPv4(const std::string& ifaceId, 4748d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 475d5afb2caSAndrew Geissler { 476d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 477d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 478d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 479d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 480d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 481d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 482d5afb2caSAndrew Geissler } 483d5afb2caSAndrew Geissler 4847e860f15SJohn Edward Broadbent inline void parseInterfaceData( 485d5afb2caSAndrew Geissler nlohmann::json& jsonResponse, const std::string& ifaceId, 486d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 487d5afb2caSAndrew Geissler const boost::container::flat_set<IPv4AddressData>& ipv4Data) 488d5afb2caSAndrew Geissler { 489d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 490d5afb2caSAndrew Geissler jsonResponse["@odata.id"] = 491eddfc437SWilly Tu crow::utility::urlFromPieces("redfish", "v1", "Systems", "hypervisor", 492eddfc437SWilly Tu "EthernetInterfaces", ifaceId); 493d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 49482695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 495d5afb2caSAndrew Geissler 49682695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 497d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 49882695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 499d5afb2caSAndrew Geissler 500d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 501d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 502d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 503d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 5049eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 505d5afb2caSAndrew Geissler { 506d5afb2caSAndrew Geissler if (ipv4Config.isActive) 507d5afb2caSAndrew Geissler { 5081476687dSEd Tanous nlohmann::json::object_t ipv4; 5091476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 5101476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 5111476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 5121476687dSEd Tanous ipv4["Gateway"] = ethData.defaultGateway; 513d5afb2caSAndrew Geissler 514d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 515d5afb2caSAndrew Geissler { 5161476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 517d5afb2caSAndrew Geissler } 5181476687dSEd Tanous ipv4Array.push_back(std::move(ipv4)); 519d5afb2caSAndrew Geissler } 520d5afb2caSAndrew Geissler } 521d5afb2caSAndrew Geissler } 522d5afb2caSAndrew Geissler 5237e860f15SJohn Edward Broadbent inline void setDHCPEnabled(const std::string& ifaceId, 5247e860f15SJohn Edward Broadbent const bool& ipv4DHCPEnabled, 5258d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 526d5afb2caSAndrew Geissler { 5277e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 528d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 5295e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 530d5afb2caSAndrew Geissler if (ec) 531d5afb2caSAndrew Geissler { 532d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 533d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 534d5afb2caSAndrew Geissler return; 535d5afb2caSAndrew Geissler } 536d5afb2caSAndrew Geissler }, 537d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 538d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ifaceId, 539d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 540d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled", 541168e20c1SEd Tanous dbus::utility::DbusVariantType{dhcp}); 542d5afb2caSAndrew Geissler 543d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 544d5afb2caSAndrew Geissler // of the DHCPEnabled property 545d5afb2caSAndrew Geissler std::string origin; 546e05aec50SEd Tanous if (!ipv4DHCPEnabled) 547d5afb2caSAndrew Geissler { 548d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 549d5afb2caSAndrew Geissler } 550d5afb2caSAndrew Geissler else 551d5afb2caSAndrew Geissler { 552d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 553d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 554d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 555d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 556d5afb2caSAndrew Geissler } 557d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 5585e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 559d5afb2caSAndrew Geissler if (ec) 560d5afb2caSAndrew Geissler { 561d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 562d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 563d5afb2caSAndrew Geissler return; 564d5afb2caSAndrew Geissler } 565d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set"; 566d5afb2caSAndrew Geissler }, 567d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 5687e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 569d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 570d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Origin", 571168e20c1SEd Tanous dbus::utility::DbusVariantType(origin)); 572d5afb2caSAndrew Geissler } 573d5afb2caSAndrew Geissler 5747e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 5757e860f15SJohn Edward Broadbent const std::string& ifaceId, const nlohmann::json& input, 5767e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 577d5afb2caSAndrew Geissler { 5787e860f15SJohn Edward Broadbent if ((!input.is_array()) || input.empty()) 579d5afb2caSAndrew Geissler { 5807e860f15SJohn Edward Broadbent messages::propertyValueTypeError(asyncResp->res, input.dump(), 5817e860f15SJohn Edward Broadbent "IPv4StaticAddresses"); 582d5afb2caSAndrew Geissler return; 583d5afb2caSAndrew Geissler } 584d5afb2caSAndrew Geissler 5857e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 5867e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 5877e860f15SJohn Edward Broadbent // address 5887e860f15SJohn Edward Broadbent const nlohmann::json& thisJson = input[0]; 5897e860f15SJohn Edward Broadbent 5907e860f15SJohn Edward Broadbent if (!thisJson.is_null() && !thisJson.empty()) 5917e860f15SJohn Edward Broadbent { 592f8fe53e7SEd Tanous // For the error string 593f8fe53e7SEd Tanous std::string pathString = "IPv4StaticAddresses/1"; 5947e860f15SJohn Edward Broadbent std::optional<std::string> address; 5957e860f15SJohn Edward Broadbent std::optional<std::string> subnetMask; 5967e860f15SJohn Edward Broadbent std::optional<std::string> gateway; 5977e860f15SJohn Edward Broadbent nlohmann::json thisJsonCopy = thisJson; 5987e860f15SJohn Edward Broadbent if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 5997e860f15SJohn Edward Broadbent address, "SubnetMask", subnetMask, "Gateway", 6007e860f15SJohn Edward Broadbent gateway)) 6017e860f15SJohn Edward Broadbent { 6027e860f15SJohn Edward Broadbent messages::propertyValueFormatError( 6037e860f15SJohn Edward Broadbent asyncResp->res, 6047e860f15SJohn Edward Broadbent thisJson.dump(2, ' ', true, 6057e860f15SJohn Edward Broadbent nlohmann::json::error_handler_t::replace), 6067e860f15SJohn Edward Broadbent pathString); 6077e860f15SJohn Edward Broadbent return; 6087e860f15SJohn Edward Broadbent } 6097e860f15SJohn Edward Broadbent 6107e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 6117e860f15SJohn Edward Broadbent bool errorInEntry = false; 6127e860f15SJohn Edward Broadbent if (address) 6137e860f15SJohn Edward Broadbent { 614033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 6157e860f15SJohn Edward Broadbent { 6167e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *address, 6177e860f15SJohn Edward Broadbent pathString + "/Address"); 6187e860f15SJohn Edward Broadbent errorInEntry = true; 6197e860f15SJohn Edward Broadbent } 6207e860f15SJohn Edward Broadbent } 6217e860f15SJohn Edward Broadbent else 6227e860f15SJohn Edward Broadbent { 6237e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Address"); 6247e860f15SJohn Edward Broadbent errorInEntry = true; 6257e860f15SJohn Edward Broadbent } 6267e860f15SJohn Edward Broadbent 6277e860f15SJohn Edward Broadbent if (subnetMask) 6287e860f15SJohn Edward Broadbent { 629033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 630033f1e4dSEd Tanous &prefixLength)) 6317e860f15SJohn Edward Broadbent { 6327e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *subnetMask, 6337e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 6347e860f15SJohn Edward Broadbent errorInEntry = true; 6357e860f15SJohn Edward Broadbent } 6367e860f15SJohn Edward Broadbent } 6377e860f15SJohn Edward Broadbent else 6387e860f15SJohn Edward Broadbent { 6397e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, 6407e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 6417e860f15SJohn Edward Broadbent errorInEntry = true; 6427e860f15SJohn Edward Broadbent } 6437e860f15SJohn Edward Broadbent 6447e860f15SJohn Edward Broadbent if (gateway) 6457e860f15SJohn Edward Broadbent { 646033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 6477e860f15SJohn Edward Broadbent { 6487e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *gateway, 6497e860f15SJohn Edward Broadbent pathString + "/Gateway"); 6507e860f15SJohn Edward Broadbent errorInEntry = true; 6517e860f15SJohn Edward Broadbent } 6527e860f15SJohn Edward Broadbent } 6537e860f15SJohn Edward Broadbent else 6547e860f15SJohn Edward Broadbent { 6557e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Gateway"); 6567e860f15SJohn Edward Broadbent errorInEntry = true; 6577e860f15SJohn Edward Broadbent } 6587e860f15SJohn Edward Broadbent 6597e860f15SJohn Edward Broadbent if (errorInEntry) 6607e860f15SJohn Edward Broadbent { 6617e860f15SJohn Edward Broadbent return; 6627e860f15SJohn Edward Broadbent } 6637e860f15SJohn Edward Broadbent 6647e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Calling createHypervisorIPv4 on : " << ifaceId 6657e860f15SJohn Edward Broadbent << "," << *address; 6667e860f15SJohn Edward Broadbent createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address, 6677e860f15SJohn Edward Broadbent asyncResp); 6687e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 6697e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 6707e860f15SJohn Edward Broadbent } 6717e860f15SJohn Edward Broadbent else 6727e860f15SJohn Edward Broadbent { 6737e860f15SJohn Edward Broadbent if (thisJson.is_null()) 6747e860f15SJohn Edward Broadbent { 6757e860f15SJohn Edward Broadbent deleteHypervisorIPv4(ifaceId, asyncResp); 6767e860f15SJohn Edward Broadbent } 6777e860f15SJohn Edward Broadbent } 6787e860f15SJohn Edward Broadbent } 6797e860f15SJohn Edward Broadbent 68088a8a174SEd Tanous inline void handleHypervisorHostnamePatch( 68188a8a174SEd Tanous const std::string& hostName, 6827e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6837e860f15SJohn Edward Broadbent { 6847e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 6857e860f15SJohn Edward Broadbent { 6867e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 6877e860f15SJohn Edward Broadbent "HostName"); 6887e860f15SJohn Edward Broadbent return; 6897e860f15SJohn Edward Broadbent } 6907e860f15SJohn Edward Broadbent 6917e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 6927e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 6935e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 6947e860f15SJohn Edward Broadbent if (ec) 6957e860f15SJohn Edward Broadbent { 6967e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 6977e860f15SJohn Edward Broadbent } 6987e860f15SJohn Edward Broadbent }, 6997e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 7007e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 7017e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 7027e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 703168e20c1SEd Tanous dbus::utility::DbusVariantType(hostName)); 7047e860f15SJohn Edward Broadbent } 7057e860f15SJohn Edward Broadbent 7067e860f15SJohn Edward Broadbent inline void 7077e860f15SJohn Edward Broadbent setIPv4InterfaceEnabled(const std::string& ifaceId, const bool& isActive, 7087e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7097e860f15SJohn Edward Broadbent { 7107e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 7115e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7127e860f15SJohn Edward Broadbent if (ec) 7137e860f15SJohn Edward Broadbent { 7147e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 7157e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 7167e860f15SJohn Edward Broadbent return; 7177e860f15SJohn Edward Broadbent } 7187e860f15SJohn Edward Broadbent }, 7197e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 7207e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 7217e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 7227e860f15SJohn Edward Broadbent "xyz.openbmc_project.Object.Enable", "Enabled", 723168e20c1SEd Tanous dbus::utility::DbusVariantType(isActive)); 7247e860f15SJohn Edward Broadbent } 7257e860f15SJohn Edward Broadbent 726*f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceCollectionGet( 727*f40448e5SGunnar Mills App& app, const crow::Request& req, 728*f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 729*f40448e5SGunnar Mills { 730*f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 731*f40448e5SGunnar Mills { 732*f40448e5SGunnar Mills return; 733*f40448e5SGunnar Mills } 734*f40448e5SGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 735*f40448e5SGunnar Mills "xyz.openbmc_project.Network.EthernetInterface"}; 736*f40448e5SGunnar Mills 737*f40448e5SGunnar Mills dbus::utility::getSubTreePaths( 738*f40448e5SGunnar Mills "/xyz/openbmc_project/network/hypervisor", 0, interfaces, 739*f40448e5SGunnar Mills [asyncResp]( 740*f40448e5SGunnar Mills const boost::system::error_code& error, 741*f40448e5SGunnar Mills const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) { 742*f40448e5SGunnar Mills if (error) 743*f40448e5SGunnar Mills { 744*f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "System", "hypervisor"); 745*f40448e5SGunnar Mills return; 746*f40448e5SGunnar Mills } 747*f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 748*f40448e5SGunnar Mills "#EthernetInterfaceCollection." 749*f40448e5SGunnar Mills "EthernetInterfaceCollection"; 750*f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 751*f40448e5SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 752*f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet " 753*f40448e5SGunnar Mills "Interface Collection"; 754*f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 755*f40448e5SGunnar Mills "Collection of Virtual Management " 756*f40448e5SGunnar Mills "Interfaces for the hypervisor"; 757*f40448e5SGunnar Mills 758*f40448e5SGunnar Mills nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 759*f40448e5SGunnar Mills ifaceArray = nlohmann::json::array(); 760*f40448e5SGunnar Mills for (const std::string& iface : ifaceList) 761*f40448e5SGunnar Mills { 762*f40448e5SGunnar Mills sdbusplus::message::object_path path(iface); 763*f40448e5SGunnar Mills std::string name = path.filename(); 764*f40448e5SGunnar Mills if (name.empty()) 765*f40448e5SGunnar Mills { 766*f40448e5SGunnar Mills continue; 767*f40448e5SGunnar Mills } 768*f40448e5SGunnar Mills nlohmann::json::object_t ethIface; 769*f40448e5SGunnar Mills ethIface["@odata.id"] = crow::utility::urlFromPieces( 770*f40448e5SGunnar Mills "redfish", "v1", "Systems", "hypervisor", "EthernetInterfaces", 771*f40448e5SGunnar Mills name); 772*f40448e5SGunnar Mills ifaceArray.push_back(std::move(ethIface)); 773*f40448e5SGunnar Mills } 774*f40448e5SGunnar Mills asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 775*f40448e5SGunnar Mills }); 776*f40448e5SGunnar Mills } 777*f40448e5SGunnar Mills 778*f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceGet( 779*f40448e5SGunnar Mills App& app, const crow::Request& req, 780*f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 781*f40448e5SGunnar Mills { 782*f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 783*f40448e5SGunnar Mills { 784*f40448e5SGunnar Mills return; 785*f40448e5SGunnar Mills } 786*f40448e5SGunnar Mills getHypervisorIfaceData( 787*f40448e5SGunnar Mills id, [asyncResp, ifaceId{std::string(id)}]( 788*f40448e5SGunnar Mills const bool& success, const EthernetInterfaceData& ethData, 789*f40448e5SGunnar Mills const boost::container::flat_set<IPv4AddressData>& ipv4Data) { 790*f40448e5SGunnar Mills if (!success) 791*f40448e5SGunnar Mills { 792*f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 793*f40448e5SGunnar Mills ifaceId); 794*f40448e5SGunnar Mills return; 795*f40448e5SGunnar Mills } 796*f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 797*f40448e5SGunnar Mills "#EthernetInterface.v1_6_0.EthernetInterface"; 798*f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface"; 799*f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 800*f40448e5SGunnar Mills "Hypervisor's Virtual Management Ethernet Interface"; 801*f40448e5SGunnar Mills parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData, 802*f40448e5SGunnar Mills ipv4Data); 803*f40448e5SGunnar Mills }); 804*f40448e5SGunnar Mills } 805*f40448e5SGunnar Mills 806*f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfacePatch( 807*f40448e5SGunnar Mills App& app, const crow::Request& req, 808*f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 809*f40448e5SGunnar Mills const std::string& ifaceId) 810*f40448e5SGunnar Mills { 811*f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 812*f40448e5SGunnar Mills { 813*f40448e5SGunnar Mills return; 814*f40448e5SGunnar Mills } 815*f40448e5SGunnar Mills std::optional<std::string> hostName; 816*f40448e5SGunnar Mills std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses; 817*f40448e5SGunnar Mills std::optional<nlohmann::json> ipv4Addresses; 818*f40448e5SGunnar Mills std::optional<nlohmann::json> dhcpv4; 819*f40448e5SGunnar Mills std::optional<bool> ipv4DHCPEnabled; 820*f40448e5SGunnar Mills 821*f40448e5SGunnar Mills if (!json_util::readJsonPatch(req, asyncResp->res, "HostName", hostName, 822*f40448e5SGunnar Mills "IPv4StaticAddresses", ipv4StaticAddresses, 823*f40448e5SGunnar Mills "IPv4Addresses", ipv4Addresses, "DHCPv4", 824*f40448e5SGunnar Mills dhcpv4)) 825*f40448e5SGunnar Mills { 826*f40448e5SGunnar Mills return; 827*f40448e5SGunnar Mills } 828*f40448e5SGunnar Mills 829*f40448e5SGunnar Mills if (ipv4Addresses) 830*f40448e5SGunnar Mills { 831*f40448e5SGunnar Mills messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 832*f40448e5SGunnar Mills return; 833*f40448e5SGunnar Mills } 834*f40448e5SGunnar Mills 835*f40448e5SGunnar Mills if (dhcpv4) 836*f40448e5SGunnar Mills { 837*f40448e5SGunnar Mills if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 838*f40448e5SGunnar Mills ipv4DHCPEnabled)) 839*f40448e5SGunnar Mills { 840*f40448e5SGunnar Mills return; 841*f40448e5SGunnar Mills } 842*f40448e5SGunnar Mills } 843*f40448e5SGunnar Mills 844*f40448e5SGunnar Mills getHypervisorIfaceData( 845*f40448e5SGunnar Mills ifaceId, 846*f40448e5SGunnar Mills [asyncResp, ifaceId, hostName = std::move(hostName), 847*f40448e5SGunnar Mills ipv4StaticAddresses = std::move(ipv4StaticAddresses), ipv4DHCPEnabled, 848*f40448e5SGunnar Mills dhcpv4 = std::move(dhcpv4)]( 849*f40448e5SGunnar Mills const bool& success, const EthernetInterfaceData& ethData, 850*f40448e5SGunnar Mills const boost::container::flat_set<IPv4AddressData>&) { 851*f40448e5SGunnar Mills if (!success) 852*f40448e5SGunnar Mills { 853*f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 854*f40448e5SGunnar Mills ifaceId); 855*f40448e5SGunnar Mills return; 856*f40448e5SGunnar Mills } 857*f40448e5SGunnar Mills 858*f40448e5SGunnar Mills if (ipv4StaticAddresses) 859*f40448e5SGunnar Mills { 860*f40448e5SGunnar Mills const nlohmann::json& ipv4Static = *ipv4StaticAddresses; 861*f40448e5SGunnar Mills if (ipv4Static.begin() == ipv4Static.end()) 862*f40448e5SGunnar Mills { 863*f40448e5SGunnar Mills messages::propertyValueTypeError( 864*f40448e5SGunnar Mills asyncResp->res, 865*f40448e5SGunnar Mills ipv4Static.dump(2, ' ', true, 866*f40448e5SGunnar Mills nlohmann::json::error_handler_t::replace), 867*f40448e5SGunnar Mills "IPv4StaticAddresses"); 868*f40448e5SGunnar Mills return; 869*f40448e5SGunnar Mills } 870*f40448e5SGunnar Mills 871*f40448e5SGunnar Mills // One and only one hypervisor instance supported 872*f40448e5SGunnar Mills if (ipv4Static.size() != 1) 873*f40448e5SGunnar Mills { 874*f40448e5SGunnar Mills messages::propertyValueFormatError( 875*f40448e5SGunnar Mills asyncResp->res, 876*f40448e5SGunnar Mills ipv4Static.dump(2, ' ', true, 877*f40448e5SGunnar Mills nlohmann::json::error_handler_t::replace), 878*f40448e5SGunnar Mills "IPv4StaticAddresses"); 879*f40448e5SGunnar Mills return; 880*f40448e5SGunnar Mills } 881*f40448e5SGunnar Mills 882*f40448e5SGunnar Mills const nlohmann::json& ipv4Json = ipv4Static[0]; 883*f40448e5SGunnar Mills // Check if the param is 'null'. If its null, it means 884*f40448e5SGunnar Mills // that user wants to delete the IP address. Deleting 885*f40448e5SGunnar Mills // the IP address is allowed only if its statically 886*f40448e5SGunnar Mills // configured. Deleting the address originated from DHCP 887*f40448e5SGunnar Mills // is not allowed. 888*f40448e5SGunnar Mills if ((ipv4Json.is_null()) && 889*f40448e5SGunnar Mills (translateDhcpEnabledToBool(ethData.dhcpEnabled, true))) 890*f40448e5SGunnar Mills { 891*f40448e5SGunnar Mills BMCWEB_LOG_INFO << "Ignoring the delete on ipv4StaticAddresses " 892*f40448e5SGunnar Mills "as the interface is DHCP enabled"; 893*f40448e5SGunnar Mills } 894*f40448e5SGunnar Mills else 895*f40448e5SGunnar Mills { 896*f40448e5SGunnar Mills handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, asyncResp); 897*f40448e5SGunnar Mills } 898*f40448e5SGunnar Mills } 899*f40448e5SGunnar Mills 900*f40448e5SGunnar Mills if (hostName) 901*f40448e5SGunnar Mills { 902*f40448e5SGunnar Mills handleHypervisorHostnamePatch(*hostName, asyncResp); 903*f40448e5SGunnar Mills } 904*f40448e5SGunnar Mills 905*f40448e5SGunnar Mills if (dhcpv4) 906*f40448e5SGunnar Mills { 907*f40448e5SGunnar Mills setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 908*f40448e5SGunnar Mills } 909*f40448e5SGunnar Mills 910*f40448e5SGunnar Mills // Set this interface to disabled/inactive. This will be set 911*f40448e5SGunnar Mills // to enabled/active by the pldm once the hypervisor 912*f40448e5SGunnar Mills // consumes the updated settings from the user. 913*f40448e5SGunnar Mills setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 914*f40448e5SGunnar Mills }); 915*f40448e5SGunnar Mills asyncResp->res.result(boost::beast::http::status::accepted); 916*f40448e5SGunnar Mills } 917*f40448e5SGunnar Mills 918a5d0cedbSGunnar Mills inline void handleHypervisorResetActionGet( 919a5d0cedbSGunnar Mills App& app, const crow::Request& req, 920a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 921a5d0cedbSGunnar Mills { 922a5d0cedbSGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 923a5d0cedbSGunnar Mills { 924a5d0cedbSGunnar Mills return; 925a5d0cedbSGunnar Mills } 926a5d0cedbSGunnar Mills // Only return action info if hypervisor D-Bus object present 927a5d0cedbSGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 928a5d0cedbSGunnar Mills "xyz.openbmc_project.State.Host"}; 929a5d0cedbSGunnar Mills dbus::utility::getDbusObject( 930a5d0cedbSGunnar Mills "/xyz/openbmc_project/state/hypervisor0", interfaces, 931a5d0cedbSGunnar Mills [asyncResp]( 932a5d0cedbSGunnar Mills const boost::system::error_code& ec, 933a5d0cedbSGunnar Mills const std::vector<std::pair<std::string, std::vector<std::string>>>& 934a5d0cedbSGunnar Mills objInfo) { 935a5d0cedbSGunnar Mills if (ec) 936a5d0cedbSGunnar Mills { 937a5d0cedbSGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 938a5d0cedbSGunnar Mills 939a5d0cedbSGunnar Mills // No hypervisor objects found by mapper 940a5d0cedbSGunnar Mills if (ec.value() == boost::system::errc::io_error) 941a5d0cedbSGunnar Mills { 942a5d0cedbSGunnar Mills messages::resourceNotFound(asyncResp->res, "hypervisor", 943a5d0cedbSGunnar Mills "ResetActionInfo"); 944a5d0cedbSGunnar Mills return; 945a5d0cedbSGunnar Mills } 946a5d0cedbSGunnar Mills 947a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 948a5d0cedbSGunnar Mills return; 949a5d0cedbSGunnar Mills } 950a5d0cedbSGunnar Mills 951a5d0cedbSGunnar Mills // One and only one hypervisor instance supported 952a5d0cedbSGunnar Mills if (objInfo.size() != 1) 953a5d0cedbSGunnar Mills { 954a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 955a5d0cedbSGunnar Mills return; 956a5d0cedbSGunnar Mills } 957a5d0cedbSGunnar Mills 958a5d0cedbSGunnar Mills // The hypervisor object only support the ability to 959a5d0cedbSGunnar Mills // turn On The system object Action should be utilized 960a5d0cedbSGunnar Mills // for other operations 961a5d0cedbSGunnar Mills 962a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 963a5d0cedbSGunnar Mills "#ActionInfo.v1_1_2.ActionInfo"; 964a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 965a5d0cedbSGunnar Mills "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 966a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 967a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 968a5d0cedbSGunnar Mills nlohmann::json::array_t parameters; 969a5d0cedbSGunnar Mills nlohmann::json::object_t parameter; 970a5d0cedbSGunnar Mills parameter["Name"] = "ResetType"; 971a5d0cedbSGunnar Mills parameter["Required"] = true; 972a5d0cedbSGunnar Mills parameter["DataType"] = "String"; 973a5d0cedbSGunnar Mills nlohmann::json::array_t allowed; 974a5d0cedbSGunnar Mills allowed.push_back("On"); 975a5d0cedbSGunnar Mills parameter["AllowableValues"] = std::move(allowed); 976a5d0cedbSGunnar Mills parameters.push_back(std::move(parameter)); 977a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 978a5d0cedbSGunnar Mills }); 979a5d0cedbSGunnar Mills } 980a5d0cedbSGunnar Mills 981a5d0cedbSGunnar Mills inline void handleHypervisorSystemResetPost( 982a5d0cedbSGunnar Mills App& app, const crow::Request& req, 983a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 984a5d0cedbSGunnar Mills { 985a5d0cedbSGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 986a5d0cedbSGunnar Mills { 987a5d0cedbSGunnar Mills return; 988a5d0cedbSGunnar Mills } 989a5d0cedbSGunnar Mills std::optional<std::string> resetType; 990a5d0cedbSGunnar Mills if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 991a5d0cedbSGunnar Mills { 992a5d0cedbSGunnar Mills // readJson adds appropriate error to response 993a5d0cedbSGunnar Mills return; 994a5d0cedbSGunnar Mills } 995a5d0cedbSGunnar Mills 996a5d0cedbSGunnar Mills if (!resetType) 997a5d0cedbSGunnar Mills { 998a5d0cedbSGunnar Mills messages::actionParameterMissing(asyncResp->res, "ComputerSystem.Reset", 999a5d0cedbSGunnar Mills "ResetType"); 1000a5d0cedbSGunnar Mills return; 1001a5d0cedbSGunnar Mills } 1002a5d0cedbSGunnar Mills 1003a5d0cedbSGunnar Mills // Hypervisor object only support On operation 1004a5d0cedbSGunnar Mills if (resetType != "On") 1005a5d0cedbSGunnar Mills { 1006a5d0cedbSGunnar Mills messages::propertyValueNotInList(asyncResp->res, *resetType, 1007a5d0cedbSGunnar Mills "ResetType"); 1008a5d0cedbSGunnar Mills return; 1009a5d0cedbSGunnar Mills } 1010a5d0cedbSGunnar Mills 1011a5d0cedbSGunnar Mills std::string command = "xyz.openbmc_project.State.Host.Transition.On"; 1012a5d0cedbSGunnar Mills 1013a5d0cedbSGunnar Mills crow::connections::systemBus->async_method_call( 1014a5d0cedbSGunnar Mills [asyncResp, resetType](const boost::system::error_code& ec) { 1015a5d0cedbSGunnar Mills if (ec) 1016a5d0cedbSGunnar Mills { 1017a5d0cedbSGunnar Mills BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1018a5d0cedbSGunnar Mills if (ec.value() == boost::asio::error::invalid_argument) 1019a5d0cedbSGunnar Mills { 1020a5d0cedbSGunnar Mills messages::actionParameterNotSupported(asyncResp->res, 1021a5d0cedbSGunnar Mills *resetType, "Reset"); 1022a5d0cedbSGunnar Mills return; 1023a5d0cedbSGunnar Mills } 1024a5d0cedbSGunnar Mills 1025a5d0cedbSGunnar Mills if (ec.value() == boost::asio::error::host_unreachable) 1026a5d0cedbSGunnar Mills { 1027a5d0cedbSGunnar Mills messages::resourceNotFound(asyncResp->res, "Actions", "Reset"); 1028a5d0cedbSGunnar Mills return; 1029a5d0cedbSGunnar Mills } 1030a5d0cedbSGunnar Mills 1031a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 1032a5d0cedbSGunnar Mills return; 1033a5d0cedbSGunnar Mills } 1034a5d0cedbSGunnar Mills messages::success(asyncResp->res); 1035a5d0cedbSGunnar Mills }, 1036a5d0cedbSGunnar Mills "xyz.openbmc_project.State.Hypervisor", 1037a5d0cedbSGunnar Mills "/xyz/openbmc_project/state/hypervisor0", 1038a5d0cedbSGunnar Mills "org.freedesktop.DBus.Properties", "Set", 1039a5d0cedbSGunnar Mills "xyz.openbmc_project.State.Host", "RequestedHostTransition", 1040a5d0cedbSGunnar Mills dbus::utility::DbusVariantType{std::move(command)}); 1041a5d0cedbSGunnar Mills } 1042a5d0cedbSGunnar Mills 10437e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 10447e860f15SJohn Edward Broadbent { 10457e860f15SJohn Edward Broadbent /** 10467e860f15SJohn Edward Broadbent * Hypervisor Systems derived class for delivering Computer Systems Schema. 10477e860f15SJohn Edward Broadbent */ 10487e860f15SJohn Edward Broadbent 10497e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/") 1050ed398213SEd Tanous .privileges(redfish::privileges::getComputerSystem) 10511476687dSEd Tanous .methods(boost::beast::http::verb::get)( 10521476687dSEd Tanous [&app](const crow::Request& req, 10531476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 105545ca1b86SEd Tanous { 105645ca1b86SEd Tanous return; 105745ca1b86SEd Tanous } 10581e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1059002d39b4SEd Tanous *crow::connections::systemBus, "xyz.openbmc_project.Settings", 10601e1e598dSJonathan Doman "/xyz/openbmc_project/network/hypervisor", 1061002d39b4SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 10625e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 10631e1e598dSJonathan Doman const std::string& /*hostName*/) { 10647e860f15SJohn Edward Broadbent if (ec) 10657e860f15SJohn Edward Broadbent { 10667e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, "System", 10677e860f15SJohn Edward Broadbent "hypervisor"); 10687e860f15SJohn Edward Broadbent return; 10697e860f15SJohn Edward Broadbent } 10707e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Hypervisor is available"; 10717e860f15SJohn Edward Broadbent 10727e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.type"] = 10737e860f15SJohn Edward Broadbent "#ComputerSystem.v1_6_0.ComputerSystem"; 10747e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.id"] = 10757e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor"; 10767e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = "Hypervisor"; 10777e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "Hypervisor"; 10787e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Id"] = "hypervisor"; 1079056350beSAli Ahmed asyncResp->res.jsonValue["SystemType"] = "OS"; 10801476687dSEd Tanous nlohmann::json::array_t managedBy; 10811476687dSEd Tanous nlohmann::json::object_t manager; 10821476687dSEd Tanous manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 10831476687dSEd Tanous managedBy.push_back(std::move(manager)); 10841476687dSEd Tanous asyncResp->res.jsonValue["Links"]["ManagedBy"] = 10851476687dSEd Tanous std::move(managedBy); 1086002d39b4SEd Tanous asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 10871476687dSEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 10887e860f15SJohn Edward Broadbent getHypervisorState(asyncResp); 10897e860f15SJohn Edward Broadbent getHypervisorActions(asyncResp); 10907e860f15SJohn Edward Broadbent // TODO: Add "SystemType" : "hypervisor" 10911e1e598dSJonathan Doman }); 10927e860f15SJohn Edward Broadbent }); 10937e860f15SJohn Edward Broadbent 10947e860f15SJohn Edward Broadbent /** 10957e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 10967e860f15SJohn Edward Broadbent * Hypervisor Interface 10977e860f15SJohn Edward Broadbent */ 10987e860f15SJohn Edward Broadbent 10997e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 1100ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 1101*f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 1102*f40448e5SGunnar Mills handleHypervisorEthernetInterfaceCollectionGet, std::ref(app))); 11037e860f15SJohn Edward Broadbent 11047e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 11057e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 1106ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 1107*f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 1108*f40448e5SGunnar Mills handleHypervisorEthernetInterfaceGet, std::ref(app))); 1109d5afb2caSAndrew Geissler 11107e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 11117e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 1112ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 1113*f40448e5SGunnar Mills .methods(boost::beast::http::verb::patch)(std::bind_front( 1114*f40448e5SGunnar Mills handleHypervisorEthernetInterfacePatch, std::ref(app))); 11154fbaf64aSAndrew Geissler 11167e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/ResetActionInfo/") 1117ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 11187e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1119a5d0cedbSGunnar Mills std::bind_front(handleHypervisorResetActionGet, std::ref(app))); 11204fbaf64aSAndrew Geissler 11217e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 11224fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/") 1123ed398213SEd Tanous .privileges(redfish::privileges::postComputerSystem) 11247e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1125a5d0cedbSGunnar Mills std::bind_front(handleHypervisorSystemResetPost, std::ref(app))); 11264fbaf64aSAndrew Geissler } 112788a8a174SEd Tanous } // namespace redfish 1128