1d5afb2caSAndrew Geissler #pragma once 2d5afb2caSAndrew Geissler 37e860f15SJohn Edward Broadbent #include <app.hpp> 4d5afb2caSAndrew Geissler #include <boost/container/flat_map.hpp> 5d5afb2caSAndrew Geissler #include <boost/container/flat_set.hpp> 6d5afb2caSAndrew Geissler #include <dbus_singleton.hpp> 7d5afb2caSAndrew Geissler #include <error_messages.hpp> 8*ed398213SEd Tanous #include <registries/privilege_registry.hpp> 9d5afb2caSAndrew Geissler #include <utils/json_utils.hpp> 10d5afb2caSAndrew Geissler 11d5afb2caSAndrew Geissler #include <optional> 12d5afb2caSAndrew Geissler #include <utility> 13d5afb2caSAndrew Geissler #include <variant> 14d5afb2caSAndrew Geissler 15b8983957SEd Tanous // TODO(ed) requestRoutesHypervisorSystems seems to have copy-pasted a 16b8983957SEd Tanous // lot of code, and has a number of methods that have name conflicts with the 17b8983957SEd Tanous // normal ethernet internfaces in ethernet.hpp. For the moment, we'll put 18b8983957SEd Tanous // hypervisor in a namespace to isolate it, but these methods eventually need 19b8983957SEd Tanous // deduplicated 20b8983957SEd Tanous namespace redfish::hypervisor 21d5afb2caSAndrew Geissler { 22d5afb2caSAndrew Geissler 23d5afb2caSAndrew Geissler /** 24cc0bb6f2SAndrew Geissler * @brief Retrieves hypervisor state properties over dbus 25cc0bb6f2SAndrew Geissler * 26cc0bb6f2SAndrew Geissler * The hypervisor state object is optional so this function will only set the 27cc0bb6f2SAndrew Geissler * state variables if the object is found 28cc0bb6f2SAndrew Geissler * 29cc0bb6f2SAndrew Geissler * @param[in] aResp Shared pointer for completing asynchronous calls. 30cc0bb6f2SAndrew Geissler * 31cc0bb6f2SAndrew Geissler * @return None. 32cc0bb6f2SAndrew Geissler */ 338d1b46d7Szhanghch05 inline void getHypervisorState(const std::shared_ptr<bmcweb::AsyncResp>& aResp) 34cc0bb6f2SAndrew Geissler { 35cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "Get hypervisor state information."; 36cc0bb6f2SAndrew Geissler crow::connections::systemBus->async_method_call( 37cc0bb6f2SAndrew Geissler [aResp](const boost::system::error_code ec, 38cc0bb6f2SAndrew Geissler const std::variant<std::string>& hostState) { 39cc0bb6f2SAndrew Geissler if (ec) 40cc0bb6f2SAndrew Geissler { 41cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 42cc0bb6f2SAndrew Geissler // This is an optional D-Bus object so just return if 43cc0bb6f2SAndrew Geissler // error occurs 44cc0bb6f2SAndrew Geissler return; 45cc0bb6f2SAndrew Geissler } 46cc0bb6f2SAndrew Geissler 47cc0bb6f2SAndrew Geissler const std::string* s = std::get_if<std::string>(&hostState); 48cc0bb6f2SAndrew Geissler if (s == nullptr) 49cc0bb6f2SAndrew Geissler { 50cc0bb6f2SAndrew Geissler messages::internalError(aResp->res); 51cc0bb6f2SAndrew Geissler return; 52cc0bb6f2SAndrew Geissler } 53cc0bb6f2SAndrew Geissler 54cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor state: " << *s; 55cc0bb6f2SAndrew Geissler // Verify Host State 56cc0bb6f2SAndrew Geissler if (*s == "xyz.openbmc_project.State.Host.HostState.Running") 57cc0bb6f2SAndrew Geissler { 58cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 59cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Enabled"; 60cc0bb6f2SAndrew Geissler } 61cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 62cc0bb6f2SAndrew Geissler "Quiesced") 63cc0bb6f2SAndrew Geissler { 64cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 65cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Quiesced"; 66cc0bb6f2SAndrew Geissler } 67cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 68cc0bb6f2SAndrew Geissler "Standby") 69cc0bb6f2SAndrew Geissler { 70cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 71cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 72cc0bb6f2SAndrew Geissler } 73cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 74cc0bb6f2SAndrew Geissler "TransitioningToRunning") 75cc0bb6f2SAndrew Geissler { 76cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "PoweringOn"; 77cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Starting"; 78cc0bb6f2SAndrew Geissler } 79cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 80cc0bb6f2SAndrew Geissler "TransitioningToOff") 81cc0bb6f2SAndrew Geissler { 82cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "PoweringOff"; 83cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Enabled"; 84cc0bb6f2SAndrew Geissler } 85cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState.Off") 86cc0bb6f2SAndrew Geissler { 87cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "Off"; 88cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Disabled"; 89cc0bb6f2SAndrew Geissler } 90cc0bb6f2SAndrew Geissler else 91cc0bb6f2SAndrew Geissler { 92cc0bb6f2SAndrew Geissler messages::internalError(aResp->res); 93cc0bb6f2SAndrew Geissler return; 94cc0bb6f2SAndrew Geissler } 95cc0bb6f2SAndrew Geissler }, 96cc0bb6f2SAndrew Geissler "xyz.openbmc_project.State.Hypervisor", 97cc0bb6f2SAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 98cc0bb6f2SAndrew Geissler "org.freedesktop.DBus.Properties", "Get", 99cc0bb6f2SAndrew Geissler "xyz.openbmc_project.State.Host", "CurrentHostState"); 100cc0bb6f2SAndrew Geissler } 101cc0bb6f2SAndrew Geissler 102cc0bb6f2SAndrew Geissler /** 1034fbaf64aSAndrew Geissler * @brief Populate Actions if any are valid for hypervisor object 1044fbaf64aSAndrew Geissler * 1054fbaf64aSAndrew Geissler * The hypervisor state object is optional so this function will only set the 1064fbaf64aSAndrew Geissler * Action if the object is found 1074fbaf64aSAndrew Geissler * 1084fbaf64aSAndrew Geissler * @param[in] aResp Shared pointer for completing asynchronous calls. 1094fbaf64aSAndrew Geissler * 1104fbaf64aSAndrew Geissler * @return None. 1114fbaf64aSAndrew Geissler */ 1128d1b46d7Szhanghch05 inline void 1138d1b46d7Szhanghch05 getHypervisorActions(const std::shared_ptr<bmcweb::AsyncResp>& aResp) 1144fbaf64aSAndrew Geissler { 1154fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "Get hypervisor actions."; 1164fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 1174fbaf64aSAndrew Geissler [aResp]( 1184fbaf64aSAndrew Geissler const boost::system::error_code ec, 1194fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1204fbaf64aSAndrew Geissler objInfo) { 1214fbaf64aSAndrew Geissler if (ec) 1224fbaf64aSAndrew Geissler { 1234fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1244fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1254fbaf64aSAndrew Geissler // error occurs 1264fbaf64aSAndrew Geissler return; 1274fbaf64aSAndrew Geissler } 1284fbaf64aSAndrew Geissler 1294fbaf64aSAndrew Geissler if (objInfo.size() == 0) 1304fbaf64aSAndrew Geissler { 1314fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1324fbaf64aSAndrew Geissler // if there is no instance found 1334fbaf64aSAndrew Geissler return; 1344fbaf64aSAndrew Geissler } 1354fbaf64aSAndrew Geissler 1364fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1374fbaf64aSAndrew Geissler { 1384fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1394fbaf64aSAndrew Geissler // error 1404fbaf64aSAndrew Geissler messages::internalError(aResp->res); 1414fbaf64aSAndrew Geissler return; 1424fbaf64aSAndrew Geissler } 1434fbaf64aSAndrew Geissler 1444fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 1454fbaf64aSAndrew Geissler aResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = { 1464fbaf64aSAndrew Geissler {"target", 1474fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"}, 1484fbaf64aSAndrew Geissler {"@Redfish.ActionInfo", 1494fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/ResetActionInfo"}}; 1504fbaf64aSAndrew Geissler }, 1514fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", 1524fbaf64aSAndrew Geissler "/xyz/openbmc_project/object_mapper", 1534fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", "GetObject", 1544fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 1554fbaf64aSAndrew Geissler std::array<const char*, 1>{"xyz.openbmc_project.State.Host"}); 1564fbaf64aSAndrew Geissler } 1574fbaf64aSAndrew Geissler 158d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 159d5afb2caSAndrew Geissler const std::string& ethIfaceId, const GetManagedObjects& 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 { 182d5afb2caSAndrew Geissler ethData.mac_address = *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 { 198d5afb2caSAndrew Geissler 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 { 216d5afb2caSAndrew Geissler for (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 { 232d5afb2caSAndrew Geissler for (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 } 264d5afb2caSAndrew Geissler else 265d5afb2caSAndrew Geissler { 266d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR 267d5afb2caSAndrew Geissler << "Got extra property: " << property.first 268d5afb2caSAndrew Geissler << " on the " << objpath.first.str << " object"; 269d5afb2caSAndrew Geissler } 270d5afb2caSAndrew Geissler } 271d5afb2caSAndrew Geissler } 272d5afb2caSAndrew Geissler } 273d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 274d5afb2caSAndrew Geissler { 275d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 276d5afb2caSAndrew Geissler // need to check eth number 277d5afb2caSAndrew Geissler if (ifacePair.first == 278d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 279d5afb2caSAndrew Geissler { 280d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 281d5afb2caSAndrew Geissler { 282d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 283d5afb2caSAndrew Geissler { 284d5afb2caSAndrew Geissler const std::string* hostName = 285d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 286d5afb2caSAndrew Geissler if (hostName != nullptr) 287d5afb2caSAndrew Geissler { 288d5afb2caSAndrew Geissler ethData.hostname = *hostName; 289d5afb2caSAndrew Geissler } 290d5afb2caSAndrew Geissler } 291d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 292d5afb2caSAndrew Geissler { 293d5afb2caSAndrew Geissler const std::string* defaultGateway = 294d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 295d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 296d5afb2caSAndrew Geissler { 297d5afb2caSAndrew Geissler ethData.default_gateway = *defaultGateway; 298d5afb2caSAndrew Geissler } 299d5afb2caSAndrew Geissler } 300d5afb2caSAndrew Geissler } 301d5afb2caSAndrew Geissler } 302d5afb2caSAndrew Geissler } 303d5afb2caSAndrew Geissler } 304d5afb2caSAndrew Geissler } 305d5afb2caSAndrew Geissler return idFound; 306d5afb2caSAndrew Geissler } 307d5afb2caSAndrew Geissler /** 308d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 309d5afb2caSAndrew Geissler * Interface Object from Settings Manager 310d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 311d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 312d5afb2caSAndrew Geissler * into JSON 313d5afb2caSAndrew Geissler */ 314d5afb2caSAndrew Geissler template <typename CallbackFunc> 315d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 316d5afb2caSAndrew Geissler CallbackFunc&& callback) 317d5afb2caSAndrew Geissler { 318d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 319d5afb2caSAndrew Geissler [ethIfaceId{std::string{ethIfaceId}}, 320d5afb2caSAndrew Geissler callback{std::move(callback)}](const boost::system::error_code error, 321d5afb2caSAndrew Geissler const GetManagedObjects& resp) { 322d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 323d5afb2caSAndrew Geissler boost::container::flat_set<IPv4AddressData> ipv4Data; 324d5afb2caSAndrew Geissler if (error) 325d5afb2caSAndrew Geissler { 326d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 327d5afb2caSAndrew Geissler return; 328d5afb2caSAndrew Geissler } 329d5afb2caSAndrew Geissler 330d5afb2caSAndrew Geissler bool found = extractHypervisorInterfaceData(ethIfaceId, resp, 331d5afb2caSAndrew Geissler ethData, ipv4Data); 332d5afb2caSAndrew Geissler if (!found) 333d5afb2caSAndrew Geissler { 334d5afb2caSAndrew Geissler BMCWEB_LOG_INFO << "Hypervisor Interface not found"; 335d5afb2caSAndrew Geissler } 336d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 337d5afb2caSAndrew Geissler }, 338d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", "/", 339d5afb2caSAndrew Geissler "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 340d5afb2caSAndrew Geissler } 341d5afb2caSAndrew Geissler 342d5afb2caSAndrew Geissler /** 343d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 344d5afb2caSAndrew Geissler * 345d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 346d5afb2caSAndrew Geissler * @param[in] ipv4Address Address from the incoming request 347d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 348d5afb2caSAndrew Geissler * 349d5afb2caSAndrew Geissler * @return None. 350d5afb2caSAndrew Geissler */ 3518d1b46d7Szhanghch05 inline void 3528d1b46d7Szhanghch05 setHypervisorIPv4Address(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 353d5afb2caSAndrew Geissler const std::string& ethIfaceId, 354d5afb2caSAndrew Geissler const std::string& ipv4Address) 355d5afb2caSAndrew Geissler { 356d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor IPaddress : " << ipv4Address 357d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 358d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 359d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 360d5afb2caSAndrew Geissler if (ec) 361d5afb2caSAndrew Geissler { 362d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 363d5afb2caSAndrew Geissler return; 364d5afb2caSAndrew Geissler } 365d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress is Set"; 366d5afb2caSAndrew Geissler }, 367d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 368d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 369d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 370d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Address", 371d5afb2caSAndrew Geissler std::variant<std::string>(ipv4Address)); 372d5afb2caSAndrew Geissler } 373d5afb2caSAndrew Geissler 374d5afb2caSAndrew Geissler /** 375d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 376d5afb2caSAndrew Geissler * 377d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 378d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 379d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 380d5afb2caSAndrew Geissler * 381d5afb2caSAndrew Geissler * @return None. 382d5afb2caSAndrew Geissler */ 3838d1b46d7Szhanghch05 inline void 3848d1b46d7Szhanghch05 setHypervisorIPv4Subnet(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 3858d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 386d5afb2caSAndrew Geissler { 387d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor subnet : " << subnet 388d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 389d5afb2caSAndrew Geissler 390d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 391d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 392d5afb2caSAndrew Geissler if (ec) 393d5afb2caSAndrew Geissler { 394d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 395d5afb2caSAndrew Geissler return; 396d5afb2caSAndrew Geissler } 397d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "SubnetMask is Set"; 398d5afb2caSAndrew Geissler }, 399d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 400d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 401d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 402d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "PrefixLength", 403d5afb2caSAndrew Geissler std::variant<uint8_t>(subnet)); 404d5afb2caSAndrew Geissler } 405d5afb2caSAndrew Geissler 406d5afb2caSAndrew Geissler /** 407d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 408d5afb2caSAndrew Geissler * 409d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 410d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 411d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 412d5afb2caSAndrew Geissler * 413d5afb2caSAndrew Geissler * @return None. 414d5afb2caSAndrew Geissler */ 4158d1b46d7Szhanghch05 inline void 4168d1b46d7Szhanghch05 setHypervisorIPv4Gateway(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 417d5afb2caSAndrew Geissler const std::string& gateway) 418d5afb2caSAndrew Geissler { 419d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG 420d5afb2caSAndrew Geissler << "Setting the DefaultGateway to the last configured gateway"; 421d5afb2caSAndrew Geissler 422d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 423d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 424d5afb2caSAndrew Geissler if (ec) 425d5afb2caSAndrew Geissler { 426d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 427d5afb2caSAndrew Geissler return; 428d5afb2caSAndrew Geissler } 429d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Default Gateway is Set"; 430d5afb2caSAndrew Geissler }, 431d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 432d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor", 433d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 434d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration", "DefaultGateway", 435d5afb2caSAndrew Geissler std::variant<std::string>(gateway)); 436d5afb2caSAndrew Geissler } 437d5afb2caSAndrew Geissler 438d5afb2caSAndrew Geissler /** 439d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 440d5afb2caSAndrew Geissler * 441d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 442d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 443d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 444d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 445d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 446d5afb2caSAndrew Geissler * 447d5afb2caSAndrew Geissler * @return None 448d5afb2caSAndrew Geissler */ 4498d1b46d7Szhanghch05 inline void 4508d1b46d7Szhanghch05 createHypervisorIPv4(const std::string& ifaceId, uint8_t prefixLength, 4518d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4528d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 453d5afb2caSAndrew Geissler { 454d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 455d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 456d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 457d5afb2caSAndrew Geissler } 458d5afb2caSAndrew Geissler 459d5afb2caSAndrew Geissler /** 460d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 461d5afb2caSAndrew Geissler * 462d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 463d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 464d5afb2caSAndrew Geissler * 465d5afb2caSAndrew Geissler * @return None 466d5afb2caSAndrew Geissler */ 4678d1b46d7Szhanghch05 inline void 4688d1b46d7Szhanghch05 deleteHypervisorIPv4(const std::string& ifaceId, 4698d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 470d5afb2caSAndrew Geissler { 471d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 472d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 473d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 474d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 475d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 476d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 477d5afb2caSAndrew Geissler } 478d5afb2caSAndrew Geissler 4797e860f15SJohn Edward Broadbent inline void parseInterfaceData( 480d5afb2caSAndrew Geissler nlohmann::json& jsonResponse, const std::string& ifaceId, 481d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 482d5afb2caSAndrew Geissler const boost::container::flat_set<IPv4AddressData>& ipv4Data) 483d5afb2caSAndrew Geissler { 484d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 485d5afb2caSAndrew Geissler jsonResponse["@odata.id"] = 486d5afb2caSAndrew Geissler "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + ifaceId; 487d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 488d5afb2caSAndrew Geissler jsonResponse["MACAddress"] = ethData.mac_address; 489d5afb2caSAndrew Geissler 490d5afb2caSAndrew Geissler jsonResponse["HostName"] = ethData.hostname; 491d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 492d5afb2caSAndrew Geissler translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 493d5afb2caSAndrew Geissler 494d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 495d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 496d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 497d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 498d5afb2caSAndrew Geissler for (auto& ipv4Config : ipv4Data) 499d5afb2caSAndrew Geissler { 500d5afb2caSAndrew Geissler if (ipv4Config.isActive) 501d5afb2caSAndrew Geissler { 502d5afb2caSAndrew Geissler 503d5afb2caSAndrew Geissler ipv4Array.push_back({{"AddressOrigin", ipv4Config.origin}, 504d5afb2caSAndrew Geissler {"SubnetMask", ipv4Config.netmask}, 505d5afb2caSAndrew Geissler {"Address", ipv4Config.address}, 506d5afb2caSAndrew Geissler {"Gateway", ethData.default_gateway}}); 507d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 508d5afb2caSAndrew Geissler { 509d5afb2caSAndrew Geissler ipv4StaticArray.push_back( 510d5afb2caSAndrew Geissler {{"AddressOrigin", ipv4Config.origin}, 511d5afb2caSAndrew Geissler {"SubnetMask", ipv4Config.netmask}, 512d5afb2caSAndrew Geissler {"Address", ipv4Config.address}, 513d5afb2caSAndrew Geissler {"Gateway", ethData.default_gateway}}); 514d5afb2caSAndrew Geissler } 515d5afb2caSAndrew Geissler } 516d5afb2caSAndrew Geissler } 517d5afb2caSAndrew Geissler } 518d5afb2caSAndrew Geissler 5197e860f15SJohn Edward Broadbent inline void setDHCPEnabled(const std::string& ifaceId, 5207e860f15SJohn Edward Broadbent const bool& ipv4DHCPEnabled, 5218d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 522d5afb2caSAndrew Geissler { 5237e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 524d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 525d5afb2caSAndrew Geissler [asyncResp](const boost::system::error_code ec) { 526d5afb2caSAndrew Geissler if (ec) 527d5afb2caSAndrew Geissler { 528d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 529d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 530d5afb2caSAndrew Geissler return; 531d5afb2caSAndrew Geissler } 532d5afb2caSAndrew Geissler }, 533d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 534d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ifaceId, 535d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 536d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled", 537d5afb2caSAndrew Geissler std::variant<std::string>{dhcp}); 538d5afb2caSAndrew Geissler 539d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 540d5afb2caSAndrew Geissler // of the DHCPEnabled property 541d5afb2caSAndrew Geissler std::string origin; 542d5afb2caSAndrew Geissler if (ipv4DHCPEnabled == false) 543d5afb2caSAndrew Geissler { 544d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 545d5afb2caSAndrew Geissler } 546d5afb2caSAndrew Geissler else 547d5afb2caSAndrew Geissler { 548d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 549d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 550d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 551d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 552d5afb2caSAndrew Geissler } 553d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 554d5afb2caSAndrew Geissler [asyncResp](const boost::system::error_code ec) { 555d5afb2caSAndrew Geissler if (ec) 556d5afb2caSAndrew Geissler { 557d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 558d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 559d5afb2caSAndrew Geissler return; 560d5afb2caSAndrew Geissler } 561d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set"; 562d5afb2caSAndrew Geissler }, 563d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 5647e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 565d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 566d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Origin", 567d5afb2caSAndrew Geissler std::variant<std::string>(origin)); 568d5afb2caSAndrew Geissler } 569d5afb2caSAndrew Geissler 5707e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 5717e860f15SJohn Edward Broadbent const std::string& ifaceId, const nlohmann::json& input, 5727e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 573d5afb2caSAndrew Geissler { 5747e860f15SJohn Edward Broadbent if ((!input.is_array()) || input.empty()) 575d5afb2caSAndrew Geissler { 5767e860f15SJohn Edward Broadbent messages::propertyValueTypeError(asyncResp->res, input.dump(), 5777e860f15SJohn Edward Broadbent "IPv4StaticAddresses"); 578d5afb2caSAndrew Geissler return; 579d5afb2caSAndrew Geissler } 580d5afb2caSAndrew Geissler 5817e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 5827e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 5837e860f15SJohn Edward Broadbent // address 5847e860f15SJohn Edward Broadbent const nlohmann::json& thisJson = input[0]; 5857e860f15SJohn Edward Broadbent 5867e860f15SJohn Edward Broadbent // For the error string 5877e860f15SJohn Edward Broadbent std::string pathString = "IPv4StaticAddresses/1"; 5887e860f15SJohn Edward Broadbent 5897e860f15SJohn Edward Broadbent if (!thisJson.is_null() && !thisJson.empty()) 5907e860f15SJohn Edward Broadbent { 5917e860f15SJohn Edward Broadbent std::optional<std::string> address; 5927e860f15SJohn Edward Broadbent std::optional<std::string> subnetMask; 5937e860f15SJohn Edward Broadbent std::optional<std::string> gateway; 5947e860f15SJohn Edward Broadbent nlohmann::json thisJsonCopy = thisJson; 5957e860f15SJohn Edward Broadbent if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 5967e860f15SJohn Edward Broadbent address, "SubnetMask", subnetMask, "Gateway", 5977e860f15SJohn Edward Broadbent gateway)) 5987e860f15SJohn Edward Broadbent { 5997e860f15SJohn Edward Broadbent messages::propertyValueFormatError( 6007e860f15SJohn Edward Broadbent asyncResp->res, 6017e860f15SJohn Edward Broadbent thisJson.dump(2, ' ', true, 6027e860f15SJohn Edward Broadbent nlohmann::json::error_handler_t::replace), 6037e860f15SJohn Edward Broadbent pathString); 6047e860f15SJohn Edward Broadbent return; 6057e860f15SJohn Edward Broadbent } 6067e860f15SJohn Edward Broadbent 6077e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 6087e860f15SJohn Edward Broadbent bool errorInEntry = false; 6097e860f15SJohn Edward Broadbent if (address) 6107e860f15SJohn Edward Broadbent { 6117e860f15SJohn Edward Broadbent if (!ipv4VerifyIpAndGetBitcount(*address)) 6127e860f15SJohn Edward Broadbent { 6137e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *address, 6147e860f15SJohn Edward Broadbent pathString + "/Address"); 6157e860f15SJohn Edward Broadbent errorInEntry = true; 6167e860f15SJohn Edward Broadbent } 6177e860f15SJohn Edward Broadbent } 6187e860f15SJohn Edward Broadbent else 6197e860f15SJohn Edward Broadbent { 6207e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Address"); 6217e860f15SJohn Edward Broadbent errorInEntry = true; 6227e860f15SJohn Edward Broadbent } 6237e860f15SJohn Edward Broadbent 6247e860f15SJohn Edward Broadbent if (subnetMask) 6257e860f15SJohn Edward Broadbent { 6267e860f15SJohn Edward Broadbent if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 6277e860f15SJohn Edward Broadbent { 6287e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *subnetMask, 6297e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 6307e860f15SJohn Edward Broadbent errorInEntry = true; 6317e860f15SJohn Edward Broadbent } 6327e860f15SJohn Edward Broadbent } 6337e860f15SJohn Edward Broadbent else 6347e860f15SJohn Edward Broadbent { 6357e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, 6367e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 6377e860f15SJohn Edward Broadbent errorInEntry = true; 6387e860f15SJohn Edward Broadbent } 6397e860f15SJohn Edward Broadbent 6407e860f15SJohn Edward Broadbent if (gateway) 6417e860f15SJohn Edward Broadbent { 6427e860f15SJohn Edward Broadbent if (!ipv4VerifyIpAndGetBitcount(*gateway)) 6437e860f15SJohn Edward Broadbent { 6447e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *gateway, 6457e860f15SJohn Edward Broadbent pathString + "/Gateway"); 6467e860f15SJohn Edward Broadbent errorInEntry = true; 6477e860f15SJohn Edward Broadbent } 6487e860f15SJohn Edward Broadbent } 6497e860f15SJohn Edward Broadbent else 6507e860f15SJohn Edward Broadbent { 6517e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Gateway"); 6527e860f15SJohn Edward Broadbent errorInEntry = true; 6537e860f15SJohn Edward Broadbent } 6547e860f15SJohn Edward Broadbent 6557e860f15SJohn Edward Broadbent if (errorInEntry) 6567e860f15SJohn Edward Broadbent { 6577e860f15SJohn Edward Broadbent return; 6587e860f15SJohn Edward Broadbent } 6597e860f15SJohn Edward Broadbent 6607e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Calling createHypervisorIPv4 on : " << ifaceId 6617e860f15SJohn Edward Broadbent << "," << *address; 6627e860f15SJohn Edward Broadbent createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address, 6637e860f15SJohn Edward Broadbent asyncResp); 6647e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 6657e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 6667e860f15SJohn Edward Broadbent } 6677e860f15SJohn Edward Broadbent else 6687e860f15SJohn Edward Broadbent { 6697e860f15SJohn Edward Broadbent if (thisJson.is_null()) 6707e860f15SJohn Edward Broadbent { 6717e860f15SJohn Edward Broadbent deleteHypervisorIPv4(ifaceId, asyncResp); 6727e860f15SJohn Edward Broadbent } 6737e860f15SJohn Edward Broadbent } 6747e860f15SJohn Edward Broadbent } 6757e860f15SJohn Edward Broadbent 6767e860f15SJohn Edward Broadbent inline void 6777e860f15SJohn Edward Broadbent handleHostnamePatch(const std::string& hostName, 6787e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6797e860f15SJohn Edward Broadbent { 6807e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 6817e860f15SJohn Edward Broadbent { 6827e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 6837e860f15SJohn Edward Broadbent "HostName"); 6847e860f15SJohn Edward Broadbent return; 6857e860f15SJohn Edward Broadbent } 6867e860f15SJohn Edward Broadbent 6877e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 6887e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 6897e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec) { 6907e860f15SJohn Edward Broadbent if (ec) 6917e860f15SJohn Edward Broadbent { 6927e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 6937e860f15SJohn Edward Broadbent } 6947e860f15SJohn Edward Broadbent }, 6957e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 6967e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 6977e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 6987e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 6997e860f15SJohn Edward Broadbent std::variant<std::string>(hostName)); 7007e860f15SJohn Edward Broadbent } 7017e860f15SJohn Edward Broadbent 7027e860f15SJohn Edward Broadbent inline void 7037e860f15SJohn Edward Broadbent setIPv4InterfaceEnabled(const std::string& ifaceId, const bool& isActive, 7047e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7057e860f15SJohn Edward Broadbent { 7067e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 7077e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec) { 7087e860f15SJohn Edward Broadbent if (ec) 7097e860f15SJohn Edward Broadbent { 7107e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 7117e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 7127e860f15SJohn Edward Broadbent return; 7137e860f15SJohn Edward Broadbent } 7147e860f15SJohn Edward Broadbent }, 7157e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 7167e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 7177e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 7187e860f15SJohn Edward Broadbent "xyz.openbmc_project.Object.Enable", "Enabled", 7197e860f15SJohn Edward Broadbent std::variant<bool>(isActive)); 7207e860f15SJohn Edward Broadbent } 7217e860f15SJohn Edward Broadbent 7227e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 7237e860f15SJohn Edward Broadbent { 7247e860f15SJohn Edward Broadbent /** 7257e860f15SJohn Edward Broadbent * Hypervisor Systems derived class for delivering Computer Systems Schema. 7267e860f15SJohn Edward Broadbent */ 7277e860f15SJohn Edward Broadbent 7287e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/") 729*ed398213SEd Tanous .privileges(redfish::privileges::getComputerSystem) 7307e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 7317e860f15SJohn Edward Broadbent [](const crow::Request&, 7327e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7337e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 7347e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec, 7357e860f15SJohn Edward Broadbent const std::variant<std::string>& /*hostName*/) { 7367e860f15SJohn Edward Broadbent if (ec) 7377e860f15SJohn Edward Broadbent { 7387e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, "System", 7397e860f15SJohn Edward Broadbent "hypervisor"); 7407e860f15SJohn Edward Broadbent return; 7417e860f15SJohn Edward Broadbent } 7427e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Hypervisor is available"; 7437e860f15SJohn Edward Broadbent 7447e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.type"] = 7457e860f15SJohn Edward Broadbent "#ComputerSystem.v1_6_0.ComputerSystem"; 7467e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.id"] = 7477e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor"; 7487e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = "Hypervisor"; 7497e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "Hypervisor"; 7507e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Id"] = "hypervisor"; 7517e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = { 7527e860f15SJohn Edward Broadbent {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 7537e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["EthernetInterfaces"] = { 7547e860f15SJohn Edward Broadbent {"@odata.id", "/redfish/v1/Systems/hypervisor/" 7557e860f15SJohn Edward Broadbent "EthernetInterfaces"}}; 7567e860f15SJohn Edward Broadbent getHypervisorState(asyncResp); 7577e860f15SJohn Edward Broadbent getHypervisorActions(asyncResp); 7587e860f15SJohn Edward Broadbent // TODO: Add "SystemType" : "hypervisor" 7597e860f15SJohn Edward Broadbent }, 7607e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 7617e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 7627e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Get", 7637e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.SystemConfiguration", 7647e860f15SJohn Edward Broadbent "HostName"); 7657e860f15SJohn Edward Broadbent }); 7667e860f15SJohn Edward Broadbent 7677e860f15SJohn Edward Broadbent /** 7687e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 7697e860f15SJohn Edward Broadbent * Hypervisor Interface 7707e860f15SJohn Edward Broadbent */ 7717e860f15SJohn Edward Broadbent 7727e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 773*ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 7747e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 7757e860f15SJohn Edward Broadbent [](const crow::Request&, 7767e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7777e860f15SJohn Edward Broadbent const std::array<const char*, 1> interfaces = { 7787e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.EthernetInterface"}; 7797e860f15SJohn Edward Broadbent 7807e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 7817e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code error, 7827e860f15SJohn Edward Broadbent const std::vector<std::string>& ifaceList) { 7837e860f15SJohn Edward Broadbent if (error) 7847e860f15SJohn Edward Broadbent { 7857e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, "System", 7867e860f15SJohn Edward Broadbent "hypervisor"); 7877e860f15SJohn Edward Broadbent return; 7887e860f15SJohn Edward Broadbent } 7897e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.type"] = 7907e860f15SJohn Edward Broadbent "#EthernetInterfaceCollection." 7917e860f15SJohn Edward Broadbent "EthernetInterfaceCollection"; 7927e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.id"] = 7937e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 7947e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = 7957e860f15SJohn Edward Broadbent "Hypervisor Ethernet " 7967e860f15SJohn Edward Broadbent "Interface Collection"; 7977e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = 7987e860f15SJohn Edward Broadbent "Collection of Virtual Management " 7997e860f15SJohn Edward Broadbent "Interfaces for the hypervisor"; 8007e860f15SJohn Edward Broadbent 8017e860f15SJohn Edward Broadbent nlohmann::json& ifaceArray = 8027e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 8037e860f15SJohn Edward Broadbent ifaceArray = nlohmann::json::array(); 8047e860f15SJohn Edward Broadbent for (const std::string& iface : ifaceList) 8057e860f15SJohn Edward Broadbent { 8067e860f15SJohn Edward Broadbent sdbusplus::message::object_path path(iface); 8077e860f15SJohn Edward Broadbent std::string name = path.filename(); 8087e860f15SJohn Edward Broadbent if (name.empty()) 8097e860f15SJohn Edward Broadbent { 8107e860f15SJohn Edward Broadbent continue; 8117e860f15SJohn Edward Broadbent } 8127e860f15SJohn Edward Broadbent 8137e860f15SJohn Edward Broadbent ifaceArray.push_back( 8147e860f15SJohn Edward Broadbent {{"@odata.id", "/redfish/v1/Systems/hypervisor/" 8157e860f15SJohn Edward Broadbent "EthernetInterfaces/" + 8167e860f15SJohn Edward Broadbent name}}); 8177e860f15SJohn Edward Broadbent } 8187e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members@odata.count"] = 8197e860f15SJohn Edward Broadbent ifaceArray.size(); 8207e860f15SJohn Edward Broadbent }, 8217e860f15SJohn Edward Broadbent "xyz.openbmc_project.ObjectMapper", 8227e860f15SJohn Edward Broadbent "/xyz/openbmc_project/object_mapper", 8237e860f15SJohn Edward Broadbent "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 8247e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 0, interfaces); 8257e860f15SJohn Edward Broadbent }); 8267e860f15SJohn Edward Broadbent 8277e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8287e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 829*ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 8307e860f15SJohn Edward Broadbent .methods( 8317e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request&, 8327e860f15SJohn Edward Broadbent const std::shared_ptr< 8337e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 8347e860f15SJohn Edward Broadbent const std::string& id) { 835d5afb2caSAndrew Geissler getHypervisorIfaceData( 8367e860f15SJohn Edward Broadbent id, 8377e860f15SJohn Edward Broadbent [asyncResp, ifaceId{std::string(id)}]( 838d5afb2caSAndrew Geissler const bool& success, const EthernetInterfaceData& ethData, 8397e860f15SJohn Edward Broadbent const boost::container::flat_set<IPv4AddressData>& 8407e860f15SJohn Edward Broadbent ipv4Data) { 841d5afb2caSAndrew Geissler if (!success) 842d5afb2caSAndrew Geissler { 8437e860f15SJohn Edward Broadbent messages::resourceNotFound( 8447e860f15SJohn Edward Broadbent asyncResp->res, "EthernetInterface", ifaceId); 845d5afb2caSAndrew Geissler return; 846d5afb2caSAndrew Geissler } 847d5afb2caSAndrew Geissler asyncResp->res.jsonValue["@odata.type"] = 848d5afb2caSAndrew Geissler "#EthernetInterface.v1_5_1.EthernetInterface"; 849d5afb2caSAndrew Geissler asyncResp->res.jsonValue["Name"] = 850d5afb2caSAndrew Geissler "Hypervisor Ethernet Interface"; 851d5afb2caSAndrew Geissler asyncResp->res.jsonValue["Description"] = 852d5afb2caSAndrew Geissler "Hypervisor's Virtual Management Ethernet Interface"; 8537e860f15SJohn Edward Broadbent parseInterfaceData(asyncResp->res.jsonValue, ifaceId, 8547e860f15SJohn Edward Broadbent ethData, ipv4Data); 855d5afb2caSAndrew Geissler }); 8567e860f15SJohn Edward Broadbent }); 857d5afb2caSAndrew Geissler 8587e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8597e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 860*ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 8617e860f15SJohn Edward Broadbent .methods( 8627e860f15SJohn Edward Broadbent boost::beast::http::verb:: 8637e860f15SJohn Edward Broadbent patch)([](const crow::Request& req, 8647e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8657e860f15SJohn Edward Broadbent const std::string& ifaceId) { 866d5afb2caSAndrew Geissler std::optional<std::string> hostName; 86764face74SRavi Teja std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses; 868d5afb2caSAndrew Geissler std::optional<nlohmann::json> ipv4Addresses; 869d5afb2caSAndrew Geissler std::optional<nlohmann::json> dhcpv4; 870d5afb2caSAndrew Geissler std::optional<bool> ipv4DHCPEnabled; 871d5afb2caSAndrew Geissler 8728d1b46d7Szhanghch05 if (!json_util::readJson(req, asyncResp->res, "HostName", hostName, 873d5afb2caSAndrew Geissler "IPv4StaticAddresses", ipv4StaticAddresses, 874d5afb2caSAndrew Geissler "IPv4Addresses", ipv4Addresses, "DHCPv4", 875d5afb2caSAndrew Geissler dhcpv4)) 876d5afb2caSAndrew Geissler { 877d5afb2caSAndrew Geissler return; 878d5afb2caSAndrew Geissler } 879d5afb2caSAndrew Geissler 880d5afb2caSAndrew Geissler if (ipv4Addresses) 881d5afb2caSAndrew Geissler { 882d5afb2caSAndrew Geissler messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 883d5afb2caSAndrew Geissler } 884d5afb2caSAndrew Geissler 885d5afb2caSAndrew Geissler if (dhcpv4) 886d5afb2caSAndrew Geissler { 8878d1b46d7Szhanghch05 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 888d5afb2caSAndrew Geissler ipv4DHCPEnabled)) 889d5afb2caSAndrew Geissler { 890d5afb2caSAndrew Geissler return; 891d5afb2caSAndrew Geissler } 892d5afb2caSAndrew Geissler } 893d5afb2caSAndrew Geissler 894d5afb2caSAndrew Geissler getHypervisorIfaceData( 895d5afb2caSAndrew Geissler ifaceId, 8967e860f15SJohn Edward Broadbent [asyncResp, ifaceId, hostName = std::move(hostName), 897d5afb2caSAndrew Geissler ipv4StaticAddresses = std::move(ipv4StaticAddresses), 898d5afb2caSAndrew Geissler ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)]( 899d5afb2caSAndrew Geissler const bool& success, const EthernetInterfaceData& ethData, 900d5afb2caSAndrew Geissler const boost::container::flat_set<IPv4AddressData>&) { 901d5afb2caSAndrew Geissler if (!success) 902d5afb2caSAndrew Geissler { 9037e860f15SJohn Edward Broadbent messages::resourceNotFound( 9047e860f15SJohn Edward Broadbent asyncResp->res, "EthernetInterface", ifaceId); 905d5afb2caSAndrew Geissler return; 906d5afb2caSAndrew Geissler } 907d5afb2caSAndrew Geissler 908d5afb2caSAndrew Geissler if (ipv4StaticAddresses) 909d5afb2caSAndrew Geissler { 910d5afb2caSAndrew Geissler const nlohmann::json& ipv4Static = *ipv4StaticAddresses; 91164face74SRavi Teja if (ipv4Static.begin() == ipv4Static.end()) 91264face74SRavi Teja { 91364face74SRavi Teja messages::propertyValueTypeError( 91464face74SRavi Teja asyncResp->res, 91564face74SRavi Teja ipv4Static.dump( 91664face74SRavi Teja 2, ' ', true, 91764face74SRavi Teja nlohmann::json::error_handler_t::replace), 91864face74SRavi Teja "IPv4StaticAddresses"); 91964face74SRavi Teja return; 92064face74SRavi Teja } 92164face74SRavi Teja 92264face74SRavi Teja // One and only one hypervisor instance supported 92364face74SRavi Teja if (ipv4Static.size() != 1) 92464face74SRavi Teja { 92564face74SRavi Teja messages::propertyValueFormatError( 92664face74SRavi Teja asyncResp->res, 92764face74SRavi Teja ipv4Static.dump( 92864face74SRavi Teja 2, ' ', true, 92964face74SRavi Teja nlohmann::json::error_handler_t::replace), 93064face74SRavi Teja "IPv4StaticAddresses"); 93164face74SRavi Teja return; 93264face74SRavi Teja } 93364face74SRavi Teja 934d5afb2caSAndrew Geissler const nlohmann::json& ipv4Json = ipv4Static[0]; 9357e860f15SJohn Edward Broadbent // Check if the param is 'null'. If its null, it means 9367e860f15SJohn Edward Broadbent // that user wants to delete the IP address. Deleting 9377e860f15SJohn Edward Broadbent // the IP address is allowed only if its statically 9387e860f15SJohn Edward Broadbent // configured. Deleting the address originated from DHCP 9397e860f15SJohn Edward Broadbent // is not allowed. 940d5afb2caSAndrew Geissler if ((ipv4Json.is_null()) && 9417e860f15SJohn Edward Broadbent (translateDHCPEnabledToBool(ethData.DHCPEnabled, 9427e860f15SJohn Edward Broadbent true))) 943d5afb2caSAndrew Geissler { 944d5afb2caSAndrew Geissler BMCWEB_LOG_INFO 945d5afb2caSAndrew Geissler << "Ignoring the delete on ipv4StaticAddresses " 946d5afb2caSAndrew Geissler "as the interface is DHCP enabled"; 947d5afb2caSAndrew Geissler } 948d5afb2caSAndrew Geissler else 949d5afb2caSAndrew Geissler { 950d5afb2caSAndrew Geissler handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, 951d5afb2caSAndrew Geissler asyncResp); 952d5afb2caSAndrew Geissler } 953d5afb2caSAndrew Geissler } 954d5afb2caSAndrew Geissler 955d5afb2caSAndrew Geissler if (hostName) 956d5afb2caSAndrew Geissler { 957d5afb2caSAndrew Geissler handleHostnamePatch(*hostName, asyncResp); 958d5afb2caSAndrew Geissler } 959d5afb2caSAndrew Geissler 960d5afb2caSAndrew Geissler if (dhcpv4) 961d5afb2caSAndrew Geissler { 962d5afb2caSAndrew Geissler setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 963d5afb2caSAndrew Geissler } 964d5afb2caSAndrew Geissler 9657e860f15SJohn Edward Broadbent // Set this interface to disabled/inactive. This will be set 9667e860f15SJohn Edward Broadbent // to enabled/active by the pldm once the hypervisor 9677e860f15SJohn Edward Broadbent // consumes the updated settings from the user. 968d5afb2caSAndrew Geissler setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 969d5afb2caSAndrew Geissler }); 9708d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::accepted); 9717e860f15SJohn Edward Broadbent }); 9724fbaf64aSAndrew Geissler 9737e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/ResetActionInfo/") 974*ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 9757e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 9767e860f15SJohn Edward Broadbent [](const crow::Request&, 9777e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9784fbaf64aSAndrew Geissler // Only return action info if hypervisor D-Bus object present 9794fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 9807e860f15SJohn Edward Broadbent [asyncResp]( 9817e860f15SJohn Edward Broadbent const boost::system::error_code ec, 9824fbaf64aSAndrew Geissler const std::vector<std::pair< 9834fbaf64aSAndrew Geissler std::string, std::vector<std::string>>>& objInfo) { 9844fbaf64aSAndrew Geissler if (ec) 9854fbaf64aSAndrew Geissler { 9864fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 9874fbaf64aSAndrew Geissler 9884fbaf64aSAndrew Geissler // No hypervisor objects found by mapper 9894fbaf64aSAndrew Geissler if (ec.value() == boost::system::errc::io_error) 9904fbaf64aSAndrew Geissler { 9917e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 9927e860f15SJohn Edward Broadbent "hypervisor", 9934fbaf64aSAndrew Geissler "ResetActionInfo"); 9944fbaf64aSAndrew Geissler return; 9954fbaf64aSAndrew Geissler } 9964fbaf64aSAndrew Geissler 9974fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 9984fbaf64aSAndrew Geissler return; 9994fbaf64aSAndrew Geissler } 10004fbaf64aSAndrew Geissler 10014fbaf64aSAndrew Geissler // One and only one hypervisor instance supported 10024fbaf64aSAndrew Geissler if (objInfo.size() != 1) 10034fbaf64aSAndrew Geissler { 10044fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 10054fbaf64aSAndrew Geissler return; 10064fbaf64aSAndrew Geissler } 10074fbaf64aSAndrew Geissler 10087e860f15SJohn Edward Broadbent // The hypervisor object only support the ability to 10097e860f15SJohn Edward Broadbent // turn On The system object Action should be utilized 10107e860f15SJohn Edward Broadbent // for other operations 10114fbaf64aSAndrew Geissler asyncResp->res.jsonValue = { 10124fbaf64aSAndrew Geissler {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"}, 10134fbaf64aSAndrew Geissler {"@odata.id", 10144fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/ResetActionInfo"}, 10154fbaf64aSAndrew Geissler {"Name", "Reset Action Info"}, 10164fbaf64aSAndrew Geissler {"Id", "ResetActionInfo"}, 10174fbaf64aSAndrew Geissler {"Parameters", 10184fbaf64aSAndrew Geissler {{{"Name", "ResetType"}, 10194fbaf64aSAndrew Geissler {"Required", true}, 10204fbaf64aSAndrew Geissler {"DataType", "String"}, 10214fbaf64aSAndrew Geissler {"AllowableValues", {"On"}}}}}}; 10224fbaf64aSAndrew Geissler }, 10234fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", 10244fbaf64aSAndrew Geissler "/xyz/openbmc_project/object_mapper", 10254fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", "GetObject", 10264fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 10277e860f15SJohn Edward Broadbent std::array<const char*, 1>{ 10287e860f15SJohn Edward Broadbent "xyz.openbmc_project.State.Host"}); 10297e860f15SJohn Edward Broadbent }); 10304fbaf64aSAndrew Geissler 10317e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 10324fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/") 1033*ed398213SEd Tanous .privileges(redfish::privileges::postComputerSystem) 10347e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 10357e860f15SJohn Edward Broadbent [](const crow::Request& req, 10367e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10374fbaf64aSAndrew Geissler std::optional<std::string> resetType; 10387e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "ResetType", 10397e860f15SJohn Edward Broadbent resetType)) 10404fbaf64aSAndrew Geissler { 10414fbaf64aSAndrew Geissler // readJson adds appropriate error to response 10424fbaf64aSAndrew Geissler return; 10434fbaf64aSAndrew Geissler } 10444fbaf64aSAndrew Geissler 10454fbaf64aSAndrew Geissler if (!resetType) 10464fbaf64aSAndrew Geissler { 10474fbaf64aSAndrew Geissler messages::actionParameterMissing( 10484fbaf64aSAndrew Geissler asyncResp->res, "ComputerSystem.Reset", "ResetType"); 10494fbaf64aSAndrew Geissler return; 10504fbaf64aSAndrew Geissler } 10514fbaf64aSAndrew Geissler 10524fbaf64aSAndrew Geissler // Hypervisor object only support On operation 10534fbaf64aSAndrew Geissler if (resetType != "On") 10544fbaf64aSAndrew Geissler { 10554fbaf64aSAndrew Geissler messages::propertyValueNotInList(asyncResp->res, *resetType, 10564fbaf64aSAndrew Geissler "ResetType"); 10574fbaf64aSAndrew Geissler return; 10584fbaf64aSAndrew Geissler } 10594fbaf64aSAndrew Geissler 10607e860f15SJohn Edward Broadbent std::string command = 10617e860f15SJohn Edward Broadbent "xyz.openbmc_project.State.Host.Transition.On"; 10624fbaf64aSAndrew Geissler 10634fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 10644fbaf64aSAndrew Geissler [asyncResp, resetType](const boost::system::error_code ec) { 10654fbaf64aSAndrew Geissler if (ec) 10664fbaf64aSAndrew Geissler { 10674fbaf64aSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 10687e860f15SJohn Edward Broadbent if (ec.value() == 10697e860f15SJohn Edward Broadbent boost::asio::error::invalid_argument) 10704fbaf64aSAndrew Geissler { 10714fbaf64aSAndrew Geissler messages::actionParameterNotSupported( 10724fbaf64aSAndrew Geissler asyncResp->res, *resetType, "Reset"); 10734fbaf64aSAndrew Geissler return; 10744fbaf64aSAndrew Geissler } 10754fbaf64aSAndrew Geissler 10767e860f15SJohn Edward Broadbent if (ec.value() == 10777e860f15SJohn Edward Broadbent boost::asio::error::host_unreachable) 10784fbaf64aSAndrew Geissler { 10797e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 10807e860f15SJohn Edward Broadbent "Actions", "Reset"); 10814fbaf64aSAndrew Geissler return; 10824fbaf64aSAndrew Geissler } 10834fbaf64aSAndrew Geissler 10844fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 10854fbaf64aSAndrew Geissler return; 10864fbaf64aSAndrew Geissler } 10874fbaf64aSAndrew Geissler messages::success(asyncResp->res); 10884fbaf64aSAndrew Geissler }, 10894fbaf64aSAndrew Geissler "xyz.openbmc_project.State.Hypervisor", 10904fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 10914fbaf64aSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 10924fbaf64aSAndrew Geissler "xyz.openbmc_project.State.Host", "RequestedHostTransition", 10934fbaf64aSAndrew Geissler std::variant<std::string>{std::move(command)}); 10947e860f15SJohn Edward Broadbent }); 10954fbaf64aSAndrew Geissler } 1096b8983957SEd Tanous } // namespace redfish::hypervisor 1097