1d5afb2caSAndrew Geissler #pragma once 2d5afb2caSAndrew Geissler 3*3ccb3adbSEd Tanous #include "app.hpp" 4*3ccb3adbSEd Tanous #include "dbus_singleton.hpp" 57a1dbc48SGeorge Liu #include "dbus_utility.hpp" 6*3ccb3adbSEd Tanous #include "error_messages.hpp" 7*3ccb3adbSEd Tanous #include "ethernet.hpp" 8*3ccb3adbSEd Tanous #include "query.hpp" 9*3ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 10033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 11*3ccb3adbSEd 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 26b8983957SEd Tanous namespace redfish::hypervisor 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", 46cc0bb6f2SAndrew Geissler [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."; 1144fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 1154fbaf64aSAndrew Geissler [aResp]( 1164fbaf64aSAndrew Geissler const boost::system::error_code ec, 1174fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1184fbaf64aSAndrew Geissler objInfo) { 1194fbaf64aSAndrew Geissler if (ec) 1204fbaf64aSAndrew Geissler { 1214fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1224fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1234fbaf64aSAndrew Geissler // error occurs 1244fbaf64aSAndrew Geissler return; 1254fbaf64aSAndrew Geissler } 1264fbaf64aSAndrew Geissler 12726f6976fSEd Tanous if (objInfo.empty()) 1284fbaf64aSAndrew Geissler { 1294fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1304fbaf64aSAndrew Geissler // if there is no instance found 1314fbaf64aSAndrew Geissler return; 1324fbaf64aSAndrew Geissler } 1334fbaf64aSAndrew Geissler 1344fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1354fbaf64aSAndrew Geissler { 1364fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1374fbaf64aSAndrew Geissler // error 1384fbaf64aSAndrew Geissler messages::internalError(aResp->res); 1394fbaf64aSAndrew Geissler return; 1404fbaf64aSAndrew Geissler } 1414fbaf64aSAndrew Geissler 1424fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 143613dabeaSEd Tanous nlohmann::json& reset = 144613dabeaSEd Tanous aResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]; 145613dabeaSEd Tanous reset["target"] = 146613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"; 147613dabeaSEd Tanous reset["@Redfish.ActionInfo"] = 148613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 1494fbaf64aSAndrew Geissler }, 1504fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", 1514fbaf64aSAndrew Geissler "/xyz/openbmc_project/object_mapper", 1524fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", "GetObject", 1534fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 1544fbaf64aSAndrew Geissler std::array<const char*, 1>{"xyz.openbmc_project.State.Host"}); 1554fbaf64aSAndrew Geissler } 1564fbaf64aSAndrew Geissler 157d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 158711ac7a9SEd Tanous const std::string& ethIfaceId, 159711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 160d5afb2caSAndrew Geissler EthernetInterfaceData& ethData, 161d5afb2caSAndrew Geissler boost::container::flat_set<IPv4AddressData>& ipv4Config) 162d5afb2caSAndrew Geissler { 163d5afb2caSAndrew Geissler bool idFound = false; 164d5afb2caSAndrew Geissler for (const auto& objpath : dbusData) 165d5afb2caSAndrew Geissler { 166d5afb2caSAndrew Geissler for (const auto& ifacePair : objpath.second) 167d5afb2caSAndrew Geissler { 168d5afb2caSAndrew Geissler if (objpath.first == 169d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId) 170d5afb2caSAndrew Geissler { 171d5afb2caSAndrew Geissler idFound = true; 172d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 173d5afb2caSAndrew Geissler { 174d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 175d5afb2caSAndrew Geissler { 176d5afb2caSAndrew Geissler if (propertyPair.first == "MACAddress") 177d5afb2caSAndrew Geissler { 178d5afb2caSAndrew Geissler const std::string* mac = 179d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 180d5afb2caSAndrew Geissler if (mac != nullptr) 181d5afb2caSAndrew Geissler { 18282695a5bSJiaqing Zhao ethData.macAddress = *mac; 183d5afb2caSAndrew Geissler } 184d5afb2caSAndrew Geissler } 185d5afb2caSAndrew Geissler } 186d5afb2caSAndrew Geissler } 187d5afb2caSAndrew Geissler else if (ifacePair.first == 188d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface") 189d5afb2caSAndrew Geissler { 190d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 191d5afb2caSAndrew Geissler { 192d5afb2caSAndrew Geissler if (propertyPair.first == "DHCPEnabled") 193d5afb2caSAndrew Geissler { 194d5afb2caSAndrew Geissler const std::string* dhcp = 195d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 196d5afb2caSAndrew Geissler if (dhcp != nullptr) 197d5afb2caSAndrew Geissler { 19882695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcp; 199d5afb2caSAndrew Geissler break; // Interested on only "DHCPEnabled". 200d5afb2caSAndrew Geissler // Stop parsing since we got the 201d5afb2caSAndrew Geissler // "DHCPEnabled" value. 202d5afb2caSAndrew Geissler } 203d5afb2caSAndrew Geissler } 204d5afb2caSAndrew Geissler } 205d5afb2caSAndrew Geissler } 206d5afb2caSAndrew Geissler } 207d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor/" + 208d5afb2caSAndrew Geissler ethIfaceId + "/ipv4/addr0") 209d5afb2caSAndrew Geissler { 210d5afb2caSAndrew Geissler std::pair<boost::container::flat_set<IPv4AddressData>::iterator, 211d5afb2caSAndrew Geissler bool> 212d5afb2caSAndrew Geissler it = ipv4Config.insert(IPv4AddressData{}); 213d5afb2caSAndrew Geissler IPv4AddressData& ipv4Address = *it.first; 214d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Object.Enable") 215d5afb2caSAndrew Geissler { 2169eb808c1SEd Tanous for (const auto& property : ifacePair.second) 217d5afb2caSAndrew Geissler { 218d5afb2caSAndrew Geissler if (property.first == "Enabled") 219d5afb2caSAndrew Geissler { 220d5afb2caSAndrew Geissler const bool* intfEnable = 221d5afb2caSAndrew Geissler std::get_if<bool>(&property.second); 222d5afb2caSAndrew Geissler if (intfEnable != nullptr) 223d5afb2caSAndrew Geissler { 224d5afb2caSAndrew Geissler ipv4Address.isActive = *intfEnable; 225d5afb2caSAndrew Geissler break; 226d5afb2caSAndrew Geissler } 227d5afb2caSAndrew Geissler } 228d5afb2caSAndrew Geissler } 229d5afb2caSAndrew Geissler } 230d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.IP") 231d5afb2caSAndrew Geissler { 2329eb808c1SEd Tanous for (const auto& property : ifacePair.second) 233d5afb2caSAndrew Geissler { 234d5afb2caSAndrew Geissler if (property.first == "Address") 235d5afb2caSAndrew Geissler { 236d5afb2caSAndrew Geissler const std::string* address = 237d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 238d5afb2caSAndrew Geissler if (address != nullptr) 239d5afb2caSAndrew Geissler { 240d5afb2caSAndrew Geissler ipv4Address.address = *address; 241d5afb2caSAndrew Geissler } 242d5afb2caSAndrew Geissler } 243d5afb2caSAndrew Geissler else if (property.first == "Origin") 244d5afb2caSAndrew Geissler { 245d5afb2caSAndrew Geissler const std::string* origin = 246d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 247d5afb2caSAndrew Geissler if (origin != nullptr) 248d5afb2caSAndrew Geissler { 249d5afb2caSAndrew Geissler ipv4Address.origin = 250d5afb2caSAndrew Geissler translateAddressOriginDbusToRedfish(*origin, 251d5afb2caSAndrew Geissler true); 252d5afb2caSAndrew Geissler } 253d5afb2caSAndrew Geissler } 254d5afb2caSAndrew Geissler else if (property.first == "PrefixLength") 255d5afb2caSAndrew Geissler { 256d5afb2caSAndrew Geissler const uint8_t* mask = 257d5afb2caSAndrew Geissler std::get_if<uint8_t>(&property.second); 258d5afb2caSAndrew Geissler if (mask != nullptr) 259d5afb2caSAndrew Geissler { 260d5afb2caSAndrew Geissler // convert it to the string 261d5afb2caSAndrew Geissler ipv4Address.netmask = getNetmask(*mask); 262d5afb2caSAndrew Geissler } 263d5afb2caSAndrew Geissler } 264889ff694SAsmitha Karunanithi else if (property.first == "Type" || 265889ff694SAsmitha Karunanithi property.first == "Gateway") 266889ff694SAsmitha Karunanithi { 267889ff694SAsmitha Karunanithi // Type & Gateway is not used 268889ff694SAsmitha Karunanithi continue; 269889ff694SAsmitha Karunanithi } 270d5afb2caSAndrew Geissler else 271d5afb2caSAndrew Geissler { 272d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR 273d5afb2caSAndrew Geissler << "Got extra property: " << property.first 274d5afb2caSAndrew Geissler << " on the " << objpath.first.str << " object"; 275d5afb2caSAndrew Geissler } 276d5afb2caSAndrew Geissler } 277d5afb2caSAndrew Geissler } 278d5afb2caSAndrew Geissler } 279d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 280d5afb2caSAndrew Geissler { 281d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 282d5afb2caSAndrew Geissler // need to check eth number 283d5afb2caSAndrew Geissler if (ifacePair.first == 284d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 285d5afb2caSAndrew Geissler { 286d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 287d5afb2caSAndrew Geissler { 288d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 289d5afb2caSAndrew Geissler { 290d5afb2caSAndrew Geissler const std::string* hostName = 291d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 292d5afb2caSAndrew Geissler if (hostName != nullptr) 293d5afb2caSAndrew Geissler { 29482695a5bSJiaqing Zhao ethData.hostName = *hostName; 295d5afb2caSAndrew Geissler } 296d5afb2caSAndrew Geissler } 297d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 298d5afb2caSAndrew Geissler { 299d5afb2caSAndrew Geissler const std::string* defaultGateway = 300d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 301d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 302d5afb2caSAndrew Geissler { 30382695a5bSJiaqing Zhao ethData.defaultGateway = *defaultGateway; 304d5afb2caSAndrew Geissler } 305d5afb2caSAndrew Geissler } 306d5afb2caSAndrew Geissler } 307d5afb2caSAndrew Geissler } 308d5afb2caSAndrew Geissler } 309d5afb2caSAndrew Geissler } 310d5afb2caSAndrew Geissler } 311d5afb2caSAndrew Geissler return idFound; 312d5afb2caSAndrew Geissler } 313d5afb2caSAndrew Geissler /** 314d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 315d5afb2caSAndrew Geissler * Interface Object from Settings Manager 316d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 317d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 318d5afb2caSAndrew Geissler * into JSON 319d5afb2caSAndrew Geissler */ 320d5afb2caSAndrew Geissler template <typename CallbackFunc> 321d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 322d5afb2caSAndrew Geissler CallbackFunc&& callback) 323d5afb2caSAndrew Geissler { 324d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 325f94c4ecfSEd Tanous [ethIfaceId{std::string{ethIfaceId}}, 326f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 327711ac7a9SEd Tanous const boost::system::error_code error, 328711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& resp) { 329d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 330d5afb2caSAndrew Geissler boost::container::flat_set<IPv4AddressData> ipv4Data; 331d5afb2caSAndrew Geissler if (error) 332d5afb2caSAndrew Geissler { 333d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 334d5afb2caSAndrew Geissler return; 335d5afb2caSAndrew Geissler } 336d5afb2caSAndrew Geissler 337002d39b4SEd Tanous bool found = 338002d39b4SEd Tanous extractHypervisorInterfaceData(ethIfaceId, resp, ethData, ipv4Data); 339d5afb2caSAndrew Geissler if (!found) 340d5afb2caSAndrew Geissler { 341d5afb2caSAndrew Geissler BMCWEB_LOG_INFO << "Hypervisor Interface not found"; 342d5afb2caSAndrew Geissler } 343d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 344d5afb2caSAndrew Geissler }, 345d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", "/", 346d5afb2caSAndrew Geissler "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 347d5afb2caSAndrew Geissler } 348d5afb2caSAndrew Geissler 349d5afb2caSAndrew Geissler /** 350d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 351d5afb2caSAndrew Geissler * 352d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 353d5afb2caSAndrew Geissler * @param[in] ipv4Address Address from the incoming request 354d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 355d5afb2caSAndrew Geissler * 356d5afb2caSAndrew Geissler * @return None. 357d5afb2caSAndrew Geissler */ 3588d1b46d7Szhanghch05 inline void 3598d1b46d7Szhanghch05 setHypervisorIPv4Address(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 360d5afb2caSAndrew Geissler const std::string& ethIfaceId, 361d5afb2caSAndrew Geissler const std::string& ipv4Address) 362d5afb2caSAndrew Geissler { 363d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor IPaddress : " << ipv4Address 364d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 365d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 366d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 367d5afb2caSAndrew Geissler if (ec) 368d5afb2caSAndrew Geissler { 369d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 370d5afb2caSAndrew Geissler return; 371d5afb2caSAndrew Geissler } 372d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress is Set"; 373d5afb2caSAndrew Geissler }, 374d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 375d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 376d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 377d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Address", 378168e20c1SEd Tanous dbus::utility::DbusVariantType(ipv4Address)); 379d5afb2caSAndrew Geissler } 380d5afb2caSAndrew Geissler 381d5afb2caSAndrew Geissler /** 382d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 383d5afb2caSAndrew Geissler * 384d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 385d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 386d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 387d5afb2caSAndrew Geissler * 388d5afb2caSAndrew Geissler * @return None. 389d5afb2caSAndrew Geissler */ 3908d1b46d7Szhanghch05 inline void 3918d1b46d7Szhanghch05 setHypervisorIPv4Subnet(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 3928d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 393d5afb2caSAndrew Geissler { 394d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor subnet : " << subnet 395d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 396d5afb2caSAndrew Geissler 397d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 398d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 399d5afb2caSAndrew Geissler if (ec) 400d5afb2caSAndrew Geissler { 401d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 402d5afb2caSAndrew Geissler return; 403d5afb2caSAndrew Geissler } 404d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "SubnetMask is Set"; 405d5afb2caSAndrew Geissler }, 406d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 407d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 408d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 409d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "PrefixLength", 410168e20c1SEd Tanous dbus::utility::DbusVariantType(subnet)); 411d5afb2caSAndrew Geissler } 412d5afb2caSAndrew Geissler 413d5afb2caSAndrew Geissler /** 414d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 415d5afb2caSAndrew Geissler * 416d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 417d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 418d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 419d5afb2caSAndrew Geissler * 420d5afb2caSAndrew Geissler * @return None. 421d5afb2caSAndrew Geissler */ 4228d1b46d7Szhanghch05 inline void 4238d1b46d7Szhanghch05 setHypervisorIPv4Gateway(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 424d5afb2caSAndrew Geissler const std::string& gateway) 425d5afb2caSAndrew Geissler { 426d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG 427d5afb2caSAndrew Geissler << "Setting the DefaultGateway to the last configured gateway"; 428d5afb2caSAndrew Geissler 429d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 430d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 431d5afb2caSAndrew Geissler if (ec) 432d5afb2caSAndrew Geissler { 433d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 434d5afb2caSAndrew Geissler return; 435d5afb2caSAndrew Geissler } 436d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Default Gateway is Set"; 437d5afb2caSAndrew Geissler }, 438d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 439d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor", 440d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 441d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration", "DefaultGateway", 442168e20c1SEd Tanous dbus::utility::DbusVariantType(gateway)); 443d5afb2caSAndrew Geissler } 444d5afb2caSAndrew Geissler 445d5afb2caSAndrew Geissler /** 446d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 447d5afb2caSAndrew Geissler * 448d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 449d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 450d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 451d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 452d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 453d5afb2caSAndrew Geissler * 454d5afb2caSAndrew Geissler * @return None 455d5afb2caSAndrew Geissler */ 4568d1b46d7Szhanghch05 inline void 4578d1b46d7Szhanghch05 createHypervisorIPv4(const std::string& ifaceId, uint8_t prefixLength, 4588d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4598d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 460d5afb2caSAndrew Geissler { 461d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 462d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 463d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 464d5afb2caSAndrew Geissler } 465d5afb2caSAndrew Geissler 466d5afb2caSAndrew Geissler /** 467d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 468d5afb2caSAndrew Geissler * 469d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 470d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 471d5afb2caSAndrew Geissler * 472d5afb2caSAndrew Geissler * @return None 473d5afb2caSAndrew Geissler */ 4748d1b46d7Szhanghch05 inline void 4758d1b46d7Szhanghch05 deleteHypervisorIPv4(const std::string& ifaceId, 4768d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 477d5afb2caSAndrew Geissler { 478d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 479d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 480d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 481d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 482d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 483d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 484d5afb2caSAndrew Geissler } 485d5afb2caSAndrew Geissler 4867e860f15SJohn Edward Broadbent inline void parseInterfaceData( 487d5afb2caSAndrew Geissler nlohmann::json& jsonResponse, const std::string& ifaceId, 488d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 489d5afb2caSAndrew Geissler const boost::container::flat_set<IPv4AddressData>& ipv4Data) 490d5afb2caSAndrew Geissler { 491d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 492d5afb2caSAndrew Geissler jsonResponse["@odata.id"] = 493d5afb2caSAndrew Geissler "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + ifaceId; 494d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 49582695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 496d5afb2caSAndrew Geissler 49782695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 498d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 49982695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 500d5afb2caSAndrew Geissler 501d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 502d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 503d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 504d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 5059eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 506d5afb2caSAndrew Geissler { 507d5afb2caSAndrew Geissler if (ipv4Config.isActive) 508d5afb2caSAndrew Geissler { 5091476687dSEd Tanous nlohmann::json::object_t ipv4; 5101476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 5111476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 5121476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 5131476687dSEd Tanous ipv4["Gateway"] = ethData.defaultGateway; 514d5afb2caSAndrew Geissler 515d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 516d5afb2caSAndrew Geissler { 5171476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 518d5afb2caSAndrew Geissler } 5191476687dSEd Tanous ipv4Array.push_back(std::move(ipv4)); 520d5afb2caSAndrew Geissler } 521d5afb2caSAndrew Geissler } 522d5afb2caSAndrew Geissler } 523d5afb2caSAndrew Geissler 5247e860f15SJohn Edward Broadbent inline void setDHCPEnabled(const std::string& ifaceId, 5257e860f15SJohn Edward Broadbent const bool& ipv4DHCPEnabled, 5268d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 527d5afb2caSAndrew Geissler { 5287e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 529d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 530d5afb2caSAndrew Geissler [asyncResp](const boost::system::error_code ec) { 531d5afb2caSAndrew Geissler if (ec) 532d5afb2caSAndrew Geissler { 533d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 534d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 535d5afb2caSAndrew Geissler return; 536d5afb2caSAndrew Geissler } 537d5afb2caSAndrew Geissler }, 538d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 539d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ifaceId, 540d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 541d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled", 542168e20c1SEd Tanous dbus::utility::DbusVariantType{dhcp}); 543d5afb2caSAndrew Geissler 544d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 545d5afb2caSAndrew Geissler // of the DHCPEnabled property 546d5afb2caSAndrew Geissler std::string origin; 547e05aec50SEd Tanous if (!ipv4DHCPEnabled) 548d5afb2caSAndrew Geissler { 549d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 550d5afb2caSAndrew Geissler } 551d5afb2caSAndrew Geissler else 552d5afb2caSAndrew Geissler { 553d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 554d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 555d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 556d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 557d5afb2caSAndrew Geissler } 558d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 559d5afb2caSAndrew Geissler [asyncResp](const boost::system::error_code ec) { 560d5afb2caSAndrew Geissler if (ec) 561d5afb2caSAndrew Geissler { 562d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 563d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 564d5afb2caSAndrew Geissler return; 565d5afb2caSAndrew Geissler } 566d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set"; 567d5afb2caSAndrew Geissler }, 568d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 5697e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 570d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 571d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Origin", 572168e20c1SEd Tanous dbus::utility::DbusVariantType(origin)); 573d5afb2caSAndrew Geissler } 574d5afb2caSAndrew Geissler 5757e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 5767e860f15SJohn Edward Broadbent const std::string& ifaceId, const nlohmann::json& input, 5777e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 578d5afb2caSAndrew Geissler { 5797e860f15SJohn Edward Broadbent if ((!input.is_array()) || input.empty()) 580d5afb2caSAndrew Geissler { 5817e860f15SJohn Edward Broadbent messages::propertyValueTypeError(asyncResp->res, input.dump(), 5827e860f15SJohn Edward Broadbent "IPv4StaticAddresses"); 583d5afb2caSAndrew Geissler return; 584d5afb2caSAndrew Geissler } 585d5afb2caSAndrew Geissler 5867e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 5877e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 5887e860f15SJohn Edward Broadbent // address 5897e860f15SJohn Edward Broadbent const nlohmann::json& thisJson = input[0]; 5907e860f15SJohn Edward Broadbent 5917e860f15SJohn Edward Broadbent if (!thisJson.is_null() && !thisJson.empty()) 5927e860f15SJohn Edward Broadbent { 593f8fe53e7SEd Tanous // For the error string 594f8fe53e7SEd Tanous std::string pathString = "IPv4StaticAddresses/1"; 5957e860f15SJohn Edward Broadbent std::optional<std::string> address; 5967e860f15SJohn Edward Broadbent std::optional<std::string> subnetMask; 5977e860f15SJohn Edward Broadbent std::optional<std::string> gateway; 5987e860f15SJohn Edward Broadbent nlohmann::json thisJsonCopy = thisJson; 5997e860f15SJohn Edward Broadbent if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 6007e860f15SJohn Edward Broadbent address, "SubnetMask", subnetMask, "Gateway", 6017e860f15SJohn Edward Broadbent gateway)) 6027e860f15SJohn Edward Broadbent { 6037e860f15SJohn Edward Broadbent messages::propertyValueFormatError( 6047e860f15SJohn Edward Broadbent asyncResp->res, 6057e860f15SJohn Edward Broadbent thisJson.dump(2, ' ', true, 6067e860f15SJohn Edward Broadbent nlohmann::json::error_handler_t::replace), 6077e860f15SJohn Edward Broadbent pathString); 6087e860f15SJohn Edward Broadbent return; 6097e860f15SJohn Edward Broadbent } 6107e860f15SJohn Edward Broadbent 6117e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 6127e860f15SJohn Edward Broadbent bool errorInEntry = false; 6137e860f15SJohn Edward Broadbent if (address) 6147e860f15SJohn Edward Broadbent { 615033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 6167e860f15SJohn Edward Broadbent { 6177e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *address, 6187e860f15SJohn Edward Broadbent pathString + "/Address"); 6197e860f15SJohn Edward Broadbent errorInEntry = true; 6207e860f15SJohn Edward Broadbent } 6217e860f15SJohn Edward Broadbent } 6227e860f15SJohn Edward Broadbent else 6237e860f15SJohn Edward Broadbent { 6247e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Address"); 6257e860f15SJohn Edward Broadbent errorInEntry = true; 6267e860f15SJohn Edward Broadbent } 6277e860f15SJohn Edward Broadbent 6287e860f15SJohn Edward Broadbent if (subnetMask) 6297e860f15SJohn Edward Broadbent { 630033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 631033f1e4dSEd Tanous &prefixLength)) 6327e860f15SJohn Edward Broadbent { 6337e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *subnetMask, 6347e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 6357e860f15SJohn Edward Broadbent errorInEntry = true; 6367e860f15SJohn Edward Broadbent } 6377e860f15SJohn Edward Broadbent } 6387e860f15SJohn Edward Broadbent else 6397e860f15SJohn Edward Broadbent { 6407e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, 6417e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 6427e860f15SJohn Edward Broadbent errorInEntry = true; 6437e860f15SJohn Edward Broadbent } 6447e860f15SJohn Edward Broadbent 6457e860f15SJohn Edward Broadbent if (gateway) 6467e860f15SJohn Edward Broadbent { 647033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 6487e860f15SJohn Edward Broadbent { 6497e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *gateway, 6507e860f15SJohn Edward Broadbent pathString + "/Gateway"); 6517e860f15SJohn Edward Broadbent errorInEntry = true; 6527e860f15SJohn Edward Broadbent } 6537e860f15SJohn Edward Broadbent } 6547e860f15SJohn Edward Broadbent else 6557e860f15SJohn Edward Broadbent { 6567e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Gateway"); 6577e860f15SJohn Edward Broadbent errorInEntry = true; 6587e860f15SJohn Edward Broadbent } 6597e860f15SJohn Edward Broadbent 6607e860f15SJohn Edward Broadbent if (errorInEntry) 6617e860f15SJohn Edward Broadbent { 6627e860f15SJohn Edward Broadbent return; 6637e860f15SJohn Edward Broadbent } 6647e860f15SJohn Edward Broadbent 6657e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Calling createHypervisorIPv4 on : " << ifaceId 6667e860f15SJohn Edward Broadbent << "," << *address; 6677e860f15SJohn Edward Broadbent createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address, 6687e860f15SJohn Edward Broadbent asyncResp); 6697e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 6707e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 6717e860f15SJohn Edward Broadbent } 6727e860f15SJohn Edward Broadbent else 6737e860f15SJohn Edward Broadbent { 6747e860f15SJohn Edward Broadbent if (thisJson.is_null()) 6757e860f15SJohn Edward Broadbent { 6767e860f15SJohn Edward Broadbent deleteHypervisorIPv4(ifaceId, asyncResp); 6777e860f15SJohn Edward Broadbent } 6787e860f15SJohn Edward Broadbent } 6797e860f15SJohn Edward Broadbent } 6807e860f15SJohn Edward Broadbent 6817e860f15SJohn Edward Broadbent inline void 6827e860f15SJohn Edward Broadbent handleHostnamePatch(const std::string& hostName, 6837e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6847e860f15SJohn Edward Broadbent { 6857e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 6867e860f15SJohn Edward Broadbent { 6877e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 6887e860f15SJohn Edward Broadbent "HostName"); 6897e860f15SJohn Edward Broadbent return; 6907e860f15SJohn Edward Broadbent } 6917e860f15SJohn Edward Broadbent 6927e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 6937e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 6947e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec) { 6957e860f15SJohn Edward Broadbent if (ec) 6967e860f15SJohn Edward Broadbent { 6977e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 6987e860f15SJohn Edward Broadbent } 6997e860f15SJohn Edward Broadbent }, 7007e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 7017e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 7027e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 7037e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 704168e20c1SEd Tanous dbus::utility::DbusVariantType(hostName)); 7057e860f15SJohn Edward Broadbent } 7067e860f15SJohn Edward Broadbent 7077e860f15SJohn Edward Broadbent inline void 7087e860f15SJohn Edward Broadbent setIPv4InterfaceEnabled(const std::string& ifaceId, const bool& isActive, 7097e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7107e860f15SJohn Edward Broadbent { 7117e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 7127e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec) { 7137e860f15SJohn Edward Broadbent if (ec) 7147e860f15SJohn Edward Broadbent { 7157e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 7167e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 7177e860f15SJohn Edward Broadbent return; 7187e860f15SJohn Edward Broadbent } 7197e860f15SJohn Edward Broadbent }, 7207e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 7217e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 7227e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 7237e860f15SJohn Edward Broadbent "xyz.openbmc_project.Object.Enable", "Enabled", 724168e20c1SEd Tanous dbus::utility::DbusVariantType(isActive)); 7257e860f15SJohn Edward Broadbent } 7267e860f15SJohn Edward Broadbent 7277e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 7287e860f15SJohn Edward Broadbent { 7297e860f15SJohn Edward Broadbent /** 7307e860f15SJohn Edward Broadbent * Hypervisor Systems derived class for delivering Computer Systems Schema. 7317e860f15SJohn Edward Broadbent */ 7327e860f15SJohn Edward Broadbent 7337e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/") 734ed398213SEd Tanous .privileges(redfish::privileges::getComputerSystem) 7351476687dSEd Tanous .methods(boost::beast::http::verb::get)( 7361476687dSEd Tanous [&app](const crow::Request& req, 7371476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7383ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 73945ca1b86SEd Tanous { 74045ca1b86SEd Tanous return; 74145ca1b86SEd Tanous } 7421e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 743002d39b4SEd Tanous *crow::connections::systemBus, "xyz.openbmc_project.Settings", 7441e1e598dSJonathan Doman "/xyz/openbmc_project/network/hypervisor", 745002d39b4SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 7461e1e598dSJonathan Doman [asyncResp](const boost::system::error_code ec, 7471e1e598dSJonathan Doman const std::string& /*hostName*/) { 7487e860f15SJohn Edward Broadbent if (ec) 7497e860f15SJohn Edward Broadbent { 7507e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, "System", 7517e860f15SJohn Edward Broadbent "hypervisor"); 7527e860f15SJohn Edward Broadbent return; 7537e860f15SJohn Edward Broadbent } 7547e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Hypervisor is available"; 7557e860f15SJohn Edward Broadbent 7567e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.type"] = 7577e860f15SJohn Edward Broadbent "#ComputerSystem.v1_6_0.ComputerSystem"; 7587e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.id"] = 7597e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor"; 7607e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = "Hypervisor"; 7617e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "Hypervisor"; 7627e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Id"] = "hypervisor"; 763056350beSAli Ahmed asyncResp->res.jsonValue["SystemType"] = "OS"; 7641476687dSEd Tanous nlohmann::json::array_t managedBy; 7651476687dSEd Tanous nlohmann::json::object_t manager; 7661476687dSEd Tanous manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 7671476687dSEd Tanous managedBy.push_back(std::move(manager)); 7681476687dSEd Tanous asyncResp->res.jsonValue["Links"]["ManagedBy"] = 7691476687dSEd Tanous std::move(managedBy); 770002d39b4SEd Tanous asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 7711476687dSEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 7727e860f15SJohn Edward Broadbent getHypervisorState(asyncResp); 7737e860f15SJohn Edward Broadbent getHypervisorActions(asyncResp); 7747e860f15SJohn Edward Broadbent // TODO: Add "SystemType" : "hypervisor" 7751e1e598dSJonathan Doman }); 7767e860f15SJohn Edward Broadbent }); 7777e860f15SJohn Edward Broadbent 7787e860f15SJohn Edward Broadbent /** 7797e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 7807e860f15SJohn Edward Broadbent * Hypervisor Interface 7817e860f15SJohn Edward Broadbent */ 7827e860f15SJohn Edward Broadbent 7837e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 784ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 785002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 786002d39b4SEd Tanous [&app](const crow::Request& req, 787002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7883ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 78945ca1b86SEd Tanous { 79045ca1b86SEd Tanous return; 79145ca1b86SEd Tanous } 7927a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 7937e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.EthernetInterface"}; 7947e860f15SJohn Edward Broadbent 7957a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 7967a1dbc48SGeorge Liu "/xyz/openbmc_project/network/hypervisor", 0, interfaces, 797002d39b4SEd Tanous [asyncResp]( 7987a1dbc48SGeorge Liu const boost::system::error_code& error, 799002d39b4SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) { 8007e860f15SJohn Edward Broadbent if (error) 8017e860f15SJohn Edward Broadbent { 8027e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, "System", 8037e860f15SJohn Edward Broadbent "hypervisor"); 8047e860f15SJohn Edward Broadbent return; 8057e860f15SJohn Edward Broadbent } 8067e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.type"] = 8077e860f15SJohn Edward Broadbent "#EthernetInterfaceCollection." 8087e860f15SJohn Edward Broadbent "EthernetInterfaceCollection"; 8097e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.id"] = 8107e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 8110fda0f12SGeorge Liu asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet " 8127e860f15SJohn Edward Broadbent "Interface Collection"; 8137e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = 8147e860f15SJohn Edward Broadbent "Collection of Virtual Management " 8157e860f15SJohn Edward Broadbent "Interfaces for the hypervisor"; 8167e860f15SJohn Edward Broadbent 817002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 8187e860f15SJohn Edward Broadbent ifaceArray = nlohmann::json::array(); 8197e860f15SJohn Edward Broadbent for (const std::string& iface : ifaceList) 8207e860f15SJohn Edward Broadbent { 8217e860f15SJohn Edward Broadbent sdbusplus::message::object_path path(iface); 8227e860f15SJohn Edward Broadbent std::string name = path.filename(); 8237e860f15SJohn Edward Broadbent if (name.empty()) 8247e860f15SJohn Edward Broadbent { 8257e860f15SJohn Edward Broadbent continue; 8267e860f15SJohn Edward Broadbent } 8271476687dSEd Tanous nlohmann::json::object_t ethIface; 8281476687dSEd Tanous ethIface["@odata.id"] = 829002d39b4SEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + name; 8301476687dSEd Tanous ifaceArray.push_back(std::move(ethIface)); 8317e860f15SJohn Edward Broadbent } 832002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 8337a1dbc48SGeorge Liu }); 8347e860f15SJohn Edward Broadbent }); 8357e860f15SJohn Edward Broadbent 8367e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8377e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 838ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 83945ca1b86SEd Tanous .methods(boost::beast::http::verb::get)( 84045ca1b86SEd Tanous [&app](const crow::Request& req, 84145ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8427e860f15SJohn Edward Broadbent const std::string& id) { 8433ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 84445ca1b86SEd Tanous { 84545ca1b86SEd Tanous return; 84645ca1b86SEd Tanous } 847002d39b4SEd Tanous getHypervisorIfaceData( 848002d39b4SEd Tanous id, 849002d39b4SEd Tanous [asyncResp, ifaceId{std::string(id)}]( 850002d39b4SEd Tanous const bool& success, const EthernetInterfaceData& ethData, 851002d39b4SEd Tanous const boost::container::flat_set<IPv4AddressData>& ipv4Data) { 852d5afb2caSAndrew Geissler if (!success) 853d5afb2caSAndrew Geissler { 854002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 855002d39b4SEd Tanous ifaceId); 856d5afb2caSAndrew Geissler return; 857d5afb2caSAndrew Geissler } 858d5afb2caSAndrew Geissler asyncResp->res.jsonValue["@odata.type"] = 859188cb629SJiaqing Zhao "#EthernetInterface.v1_6_0.EthernetInterface"; 860002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface"; 861d5afb2caSAndrew Geissler asyncResp->res.jsonValue["Description"] = 862d5afb2caSAndrew Geissler "Hypervisor's Virtual Management Ethernet Interface"; 863002d39b4SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData, 864002d39b4SEd Tanous ipv4Data); 865d5afb2caSAndrew Geissler }); 8667e860f15SJohn Edward Broadbent }); 867d5afb2caSAndrew Geissler 8687e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8697e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 870ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 871002d39b4SEd Tanous .methods(boost::beast::http::verb::patch)( 872002d39b4SEd Tanous [&app](const crow::Request& req, 8737e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8747e860f15SJohn Edward Broadbent const std::string& ifaceId) { 8753ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 87645ca1b86SEd Tanous { 87745ca1b86SEd Tanous return; 87845ca1b86SEd Tanous } 879d5afb2caSAndrew Geissler std::optional<std::string> hostName; 88064face74SRavi Teja std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses; 881d5afb2caSAndrew Geissler std::optional<nlohmann::json> ipv4Addresses; 882d5afb2caSAndrew Geissler std::optional<nlohmann::json> dhcpv4; 883d5afb2caSAndrew Geissler std::optional<bool> ipv4DHCPEnabled; 884d5afb2caSAndrew Geissler 885002d39b4SEd Tanous if (!json_util::readJsonPatch(req, asyncResp->res, "HostName", hostName, 886002d39b4SEd Tanous "IPv4StaticAddresses", 88715ed6780SWilly Tu ipv4StaticAddresses, "IPv4Addresses", 88815ed6780SWilly Tu ipv4Addresses, "DHCPv4", dhcpv4)) 889d5afb2caSAndrew Geissler { 890d5afb2caSAndrew Geissler return; 891d5afb2caSAndrew Geissler } 892d5afb2caSAndrew Geissler 893d5afb2caSAndrew Geissler if (ipv4Addresses) 894d5afb2caSAndrew Geissler { 895d5afb2caSAndrew Geissler messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 896ff3f835aSRavi Teja return; 897d5afb2caSAndrew Geissler } 898d5afb2caSAndrew Geissler 899d5afb2caSAndrew Geissler if (dhcpv4) 900d5afb2caSAndrew Geissler { 9018d1b46d7Szhanghch05 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 902d5afb2caSAndrew Geissler ipv4DHCPEnabled)) 903d5afb2caSAndrew Geissler { 904d5afb2caSAndrew Geissler return; 905d5afb2caSAndrew Geissler } 906d5afb2caSAndrew Geissler } 907d5afb2caSAndrew Geissler 908d5afb2caSAndrew Geissler getHypervisorIfaceData( 909d5afb2caSAndrew Geissler ifaceId, 9107e860f15SJohn Edward Broadbent [asyncResp, ifaceId, hostName = std::move(hostName), 911d5afb2caSAndrew Geissler ipv4StaticAddresses = std::move(ipv4StaticAddresses), 912d5afb2caSAndrew Geissler ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)]( 913d5afb2caSAndrew Geissler const bool& success, const EthernetInterfaceData& ethData, 914d5afb2caSAndrew Geissler const boost::container::flat_set<IPv4AddressData>&) { 915d5afb2caSAndrew Geissler if (!success) 916d5afb2caSAndrew Geissler { 917002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 918002d39b4SEd Tanous ifaceId); 919d5afb2caSAndrew Geissler return; 920d5afb2caSAndrew Geissler } 921d5afb2caSAndrew Geissler 922d5afb2caSAndrew Geissler if (ipv4StaticAddresses) 923d5afb2caSAndrew Geissler { 924d5afb2caSAndrew Geissler const nlohmann::json& ipv4Static = *ipv4StaticAddresses; 92564face74SRavi Teja if (ipv4Static.begin() == ipv4Static.end()) 92664face74SRavi Teja { 92764face74SRavi Teja messages::propertyValueTypeError( 92864face74SRavi Teja asyncResp->res, 92964face74SRavi Teja ipv4Static.dump( 93064face74SRavi Teja 2, ' ', true, 93164face74SRavi Teja nlohmann::json::error_handler_t::replace), 93264face74SRavi Teja "IPv4StaticAddresses"); 93364face74SRavi Teja return; 93464face74SRavi Teja } 93564face74SRavi Teja 93664face74SRavi Teja // One and only one hypervisor instance supported 93764face74SRavi Teja if (ipv4Static.size() != 1) 93864face74SRavi Teja { 93964face74SRavi Teja messages::propertyValueFormatError( 94064face74SRavi Teja asyncResp->res, 94164face74SRavi Teja ipv4Static.dump( 94264face74SRavi Teja 2, ' ', true, 94364face74SRavi Teja nlohmann::json::error_handler_t::replace), 94464face74SRavi Teja "IPv4StaticAddresses"); 94564face74SRavi Teja return; 94664face74SRavi Teja } 94764face74SRavi Teja 948d5afb2caSAndrew Geissler const nlohmann::json& ipv4Json = ipv4Static[0]; 9497e860f15SJohn Edward Broadbent // Check if the param is 'null'. If its null, it means 9507e860f15SJohn Edward Broadbent // that user wants to delete the IP address. Deleting 9517e860f15SJohn Edward Broadbent // the IP address is allowed only if its statically 9527e860f15SJohn Edward Broadbent // configured. Deleting the address originated from DHCP 9537e860f15SJohn Edward Broadbent // is not allowed. 954d5afb2caSAndrew Geissler if ((ipv4Json.is_null()) && 955002d39b4SEd Tanous (translateDhcpEnabledToBool(ethData.dhcpEnabled, true))) 956d5afb2caSAndrew Geissler { 957d5afb2caSAndrew Geissler BMCWEB_LOG_INFO 958d5afb2caSAndrew Geissler << "Ignoring the delete on ipv4StaticAddresses " 959d5afb2caSAndrew Geissler "as the interface is DHCP enabled"; 960d5afb2caSAndrew Geissler } 961d5afb2caSAndrew Geissler else 962d5afb2caSAndrew Geissler { 963d5afb2caSAndrew Geissler handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, 964d5afb2caSAndrew Geissler asyncResp); 965d5afb2caSAndrew Geissler } 966d5afb2caSAndrew Geissler } 967d5afb2caSAndrew Geissler 968d5afb2caSAndrew Geissler if (hostName) 969d5afb2caSAndrew Geissler { 970d5afb2caSAndrew Geissler handleHostnamePatch(*hostName, asyncResp); 971d5afb2caSAndrew Geissler } 972d5afb2caSAndrew Geissler 973d5afb2caSAndrew Geissler if (dhcpv4) 974d5afb2caSAndrew Geissler { 975d5afb2caSAndrew Geissler setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 976d5afb2caSAndrew Geissler } 977d5afb2caSAndrew Geissler 9787e860f15SJohn Edward Broadbent // Set this interface to disabled/inactive. This will be set 9797e860f15SJohn Edward Broadbent // to enabled/active by the pldm once the hypervisor 9807e860f15SJohn Edward Broadbent // consumes the updated settings from the user. 981d5afb2caSAndrew Geissler setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 982d5afb2caSAndrew Geissler }); 9838d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::accepted); 9847e860f15SJohn Edward Broadbent }); 9854fbaf64aSAndrew Geissler 9867e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/ResetActionInfo/") 987ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 9887e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 98945ca1b86SEd Tanous [&app](const crow::Request& req, 9907e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9913ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 99245ca1b86SEd Tanous { 99345ca1b86SEd Tanous return; 99445ca1b86SEd Tanous } 9954fbaf64aSAndrew Geissler // Only return action info if hypervisor D-Bus object present 9964fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 997002d39b4SEd Tanous [asyncResp](const boost::system::error_code ec, 9984fbaf64aSAndrew Geissler const std::vector<std::pair< 9994fbaf64aSAndrew Geissler std::string, std::vector<std::string>>>& objInfo) { 10004fbaf64aSAndrew Geissler if (ec) 10014fbaf64aSAndrew Geissler { 10024fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 10034fbaf64aSAndrew Geissler 10044fbaf64aSAndrew Geissler // No hypervisor objects found by mapper 10054fbaf64aSAndrew Geissler if (ec.value() == boost::system::errc::io_error) 10064fbaf64aSAndrew Geissler { 1007002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "hypervisor", 10084fbaf64aSAndrew Geissler "ResetActionInfo"); 10094fbaf64aSAndrew Geissler return; 10104fbaf64aSAndrew Geissler } 10114fbaf64aSAndrew Geissler 10124fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 10134fbaf64aSAndrew Geissler return; 10144fbaf64aSAndrew Geissler } 10154fbaf64aSAndrew Geissler 10164fbaf64aSAndrew Geissler // One and only one hypervisor instance supported 10174fbaf64aSAndrew Geissler if (objInfo.size() != 1) 10184fbaf64aSAndrew Geissler { 10194fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 10204fbaf64aSAndrew Geissler return; 10214fbaf64aSAndrew Geissler } 10224fbaf64aSAndrew Geissler 10237e860f15SJohn Edward Broadbent // The hypervisor object only support the ability to 10247e860f15SJohn Edward Broadbent // turn On The system object Action should be utilized 10257e860f15SJohn Edward Broadbent // for other operations 10261476687dSEd Tanous 10271476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 10281476687dSEd Tanous "#ActionInfo.v1_1_2.ActionInfo"; 10291476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10301476687dSEd Tanous "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 10311476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 10321476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 10331476687dSEd Tanous nlohmann::json::array_t parameters; 10341476687dSEd Tanous nlohmann::json::object_t parameter; 10351476687dSEd Tanous parameter["Name"] = "ResetType"; 10361476687dSEd Tanous parameter["Required"] = true; 10371476687dSEd Tanous parameter["DataType"] = "String"; 10381476687dSEd Tanous nlohmann::json::array_t allowed; 10391476687dSEd Tanous allowed.push_back("On"); 10401476687dSEd Tanous parameter["AllowableValues"] = std::move(allowed); 10411476687dSEd Tanous parameters.push_back(std::move(parameter)); 1042002d39b4SEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 10434fbaf64aSAndrew Geissler }, 10444fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", 10454fbaf64aSAndrew Geissler "/xyz/openbmc_project/object_mapper", 10464fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", "GetObject", 10474fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 1048002d39b4SEd Tanous std::array<const char*, 1>{"xyz.openbmc_project.State.Host"}); 10497e860f15SJohn Edward Broadbent }); 10504fbaf64aSAndrew Geissler 10517e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 10524fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/") 1053ed398213SEd Tanous .privileges(redfish::privileges::postComputerSystem) 10547e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 105545ca1b86SEd Tanous [&app](const crow::Request& req, 10567e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10573ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 105845ca1b86SEd Tanous { 105945ca1b86SEd Tanous return; 106045ca1b86SEd Tanous } 10614fbaf64aSAndrew Geissler std::optional<std::string> resetType; 106215ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", 10637e860f15SJohn Edward Broadbent resetType)) 10644fbaf64aSAndrew Geissler { 10654fbaf64aSAndrew Geissler // readJson adds appropriate error to response 10664fbaf64aSAndrew Geissler return; 10674fbaf64aSAndrew Geissler } 10684fbaf64aSAndrew Geissler 10694fbaf64aSAndrew Geissler if (!resetType) 10704fbaf64aSAndrew Geissler { 10714fbaf64aSAndrew Geissler messages::actionParameterMissing( 10724fbaf64aSAndrew Geissler asyncResp->res, "ComputerSystem.Reset", "ResetType"); 10734fbaf64aSAndrew Geissler return; 10744fbaf64aSAndrew Geissler } 10754fbaf64aSAndrew Geissler 10764fbaf64aSAndrew Geissler // Hypervisor object only support On operation 10774fbaf64aSAndrew Geissler if (resetType != "On") 10784fbaf64aSAndrew Geissler { 10794fbaf64aSAndrew Geissler messages::propertyValueNotInList(asyncResp->res, *resetType, 10804fbaf64aSAndrew Geissler "ResetType"); 10814fbaf64aSAndrew Geissler return; 10824fbaf64aSAndrew Geissler } 10834fbaf64aSAndrew Geissler 1084002d39b4SEd Tanous std::string command = "xyz.openbmc_project.State.Host.Transition.On"; 10854fbaf64aSAndrew Geissler 10864fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 10874fbaf64aSAndrew Geissler [asyncResp, resetType](const boost::system::error_code ec) { 10884fbaf64aSAndrew Geissler if (ec) 10894fbaf64aSAndrew Geissler { 10904fbaf64aSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1091002d39b4SEd Tanous if (ec.value() == boost::asio::error::invalid_argument) 10924fbaf64aSAndrew Geissler { 1093002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, 1094002d39b4SEd Tanous *resetType, "Reset"); 10954fbaf64aSAndrew Geissler return; 10964fbaf64aSAndrew Geissler } 10974fbaf64aSAndrew Geissler 1098002d39b4SEd Tanous if (ec.value() == boost::asio::error::host_unreachable) 10994fbaf64aSAndrew Geissler { 1100002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "Actions", 1101002d39b4SEd Tanous "Reset"); 11024fbaf64aSAndrew Geissler return; 11034fbaf64aSAndrew Geissler } 11044fbaf64aSAndrew Geissler 11054fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 11064fbaf64aSAndrew Geissler return; 11074fbaf64aSAndrew Geissler } 11084fbaf64aSAndrew Geissler messages::success(asyncResp->res); 11094fbaf64aSAndrew Geissler }, 11104fbaf64aSAndrew Geissler "xyz.openbmc_project.State.Hypervisor", 11114fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 11124fbaf64aSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 11134fbaf64aSAndrew Geissler "xyz.openbmc_project.State.Host", "RequestedHostTransition", 1114168e20c1SEd Tanous dbus::utility::DbusVariantType{std::move(command)}); 11157e860f15SJohn Edward Broadbent }); 11164fbaf64aSAndrew Geissler } 1117b8983957SEd Tanous } // namespace redfish::hypervisor 1118