1d5afb2caSAndrew Geissler #pragma once 2d5afb2caSAndrew Geissler 33ccb3adbSEd Tanous #include "app.hpp" 43ccb3adbSEd Tanous #include "dbus_singleton.hpp" 57a1dbc48SGeorge Liu #include "dbus_utility.hpp" 63ccb3adbSEd Tanous #include "error_messages.hpp" 73ccb3adbSEd Tanous #include "ethernet.hpp" 8*539d8c6bSEd Tanous #include "generated/enums/action_info.hpp" 9*539d8c6bSEd Tanous #include "generated/enums/computer_system.hpp" 10*539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 113ccb3adbSEd Tanous #include "query.hpp" 123ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 13033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 143ccb3adbSEd Tanous #include "utils/json_utils.hpp" 15033f1e4dSEd Tanous 16ef4c65b7SEd Tanous #include <boost/url/format.hpp> 171e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 18d5afb2caSAndrew Geissler 197a1dbc48SGeorge Liu #include <array> 20d5afb2caSAndrew Geissler #include <optional> 217a1dbc48SGeorge Liu #include <string_view> 22d5afb2caSAndrew Geissler #include <utility> 23d5afb2caSAndrew Geissler 2488a8a174SEd Tanous namespace redfish 25d5afb2caSAndrew Geissler { 26d5afb2caSAndrew Geissler 27d5afb2caSAndrew Geissler /** 28cc0bb6f2SAndrew Geissler * @brief Retrieves hypervisor state properties over dbus 29cc0bb6f2SAndrew Geissler * 30cc0bb6f2SAndrew Geissler * The hypervisor state object is optional so this function will only set the 31cc0bb6f2SAndrew Geissler * state variables if the object is found 32cc0bb6f2SAndrew Geissler * 33ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 34cc0bb6f2SAndrew Geissler * 35cc0bb6f2SAndrew Geissler * @return None. 36cc0bb6f2SAndrew Geissler */ 37ac106bf6SEd Tanous inline void 38ac106bf6SEd Tanous getHypervisorState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 39cc0bb6f2SAndrew Geissler { 4062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor state information."); 411e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 421e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Hypervisor", 431e1e598dSJonathan Doman "/xyz/openbmc_project/state/hypervisor0", 441e1e598dSJonathan Doman "xyz.openbmc_project.State.Host", "CurrentHostState", 45ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 461e1e598dSJonathan Doman const std::string& hostState) { 47cc0bb6f2SAndrew Geissler if (ec) 48cc0bb6f2SAndrew Geissler { 4962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 50cc0bb6f2SAndrew Geissler // This is an optional D-Bus object so just return if 51cc0bb6f2SAndrew Geissler // error occurs 52cc0bb6f2SAndrew Geissler return; 53cc0bb6f2SAndrew Geissler } 54cc0bb6f2SAndrew Geissler 5562598e31SEd Tanous BMCWEB_LOG_DEBUG("Hypervisor state: {}", hostState); 56cc0bb6f2SAndrew Geissler // Verify Host State 571e1e598dSJonathan Doman if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") 58cc0bb6f2SAndrew Geissler { 59*539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 60*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 61*539d8c6bSEd Tanous resource::State::Enabled; 62cc0bb6f2SAndrew Geissler } 631e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 641e1e598dSJonathan Doman "Quiesced") 65cc0bb6f2SAndrew Geissler { 66*539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 67*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 68*539d8c6bSEd Tanous resource::State::Quiesced; 69cc0bb6f2SAndrew Geissler } 701e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 711e1e598dSJonathan Doman "Standby") 72cc0bb6f2SAndrew Geissler { 73*539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 74*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 75*539d8c6bSEd Tanous resource::State::StandbyOffline; 76cc0bb6f2SAndrew Geissler } 771e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 781e1e598dSJonathan Doman "TransitioningToRunning") 79cc0bb6f2SAndrew Geissler { 80*539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = 81*539d8c6bSEd Tanous resource::PowerState::PoweringOn; 82*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 83*539d8c6bSEd Tanous resource::State::Starting; 84cc0bb6f2SAndrew Geissler } 851e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 861e1e598dSJonathan Doman "TransitioningToOff") 87cc0bb6f2SAndrew Geissler { 88*539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = 89*539d8c6bSEd Tanous resource::PowerState::PoweringOff; 90*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 91*539d8c6bSEd Tanous resource::State::Enabled; 92cc0bb6f2SAndrew Geissler } 93002d39b4SEd Tanous else if (hostState == "xyz.openbmc_project.State.Host.HostState.Off") 94cc0bb6f2SAndrew Geissler { 95*539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::Off; 96*539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 97*539d8c6bSEd Tanous resource::State::Disabled; 98cc0bb6f2SAndrew Geissler } 99cc0bb6f2SAndrew Geissler else 100cc0bb6f2SAndrew Geissler { 101ac106bf6SEd Tanous messages::internalError(asyncResp->res); 102cc0bb6f2SAndrew Geissler return; 103cc0bb6f2SAndrew Geissler } 1041e1e598dSJonathan Doman }); 105cc0bb6f2SAndrew Geissler } 106cc0bb6f2SAndrew Geissler 107cc0bb6f2SAndrew Geissler /** 1084fbaf64aSAndrew Geissler * @brief Populate Actions if any are valid for hypervisor object 1094fbaf64aSAndrew Geissler * 1104fbaf64aSAndrew Geissler * The hypervisor state object is optional so this function will only set the 1114fbaf64aSAndrew Geissler * Action if the object is found 1124fbaf64aSAndrew Geissler * 113ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 1144fbaf64aSAndrew Geissler * 1154fbaf64aSAndrew Geissler * @return None. 1164fbaf64aSAndrew Geissler */ 1178d1b46d7Szhanghch05 inline void 118ac106bf6SEd Tanous getHypervisorActions(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1194fbaf64aSAndrew Geissler { 12062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor actions."); 1212b73119cSGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1222b73119cSGeorge Liu "xyz.openbmc_project.State.Host"}; 1232b73119cSGeorge Liu dbus::utility::getDbusObject( 1242b73119cSGeorge Liu "/xyz/openbmc_project/state/hypervisor0", interfaces, 125ac106bf6SEd Tanous [asyncResp]( 1262b73119cSGeorge Liu const boost::system::error_code& ec, 1274fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1284fbaf64aSAndrew Geissler objInfo) { 1294fbaf64aSAndrew Geissler if (ec) 1304fbaf64aSAndrew Geissler { 13162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 1324fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1334fbaf64aSAndrew Geissler // error occurs 1344fbaf64aSAndrew Geissler return; 1354fbaf64aSAndrew Geissler } 1364fbaf64aSAndrew Geissler 13726f6976fSEd Tanous if (objInfo.empty()) 1384fbaf64aSAndrew Geissler { 1394fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1404fbaf64aSAndrew Geissler // if there is no instance found 1414fbaf64aSAndrew Geissler return; 1424fbaf64aSAndrew Geissler } 1434fbaf64aSAndrew Geissler 1444fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1454fbaf64aSAndrew Geissler { 1464fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1474fbaf64aSAndrew Geissler // error 148ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1494fbaf64aSAndrew Geissler return; 1504fbaf64aSAndrew Geissler } 1514fbaf64aSAndrew Geissler 1524fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 153613dabeaSEd Tanous nlohmann::json& reset = 154ac106bf6SEd Tanous asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]; 155613dabeaSEd Tanous reset["target"] = 156613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"; 157613dabeaSEd Tanous reset["@Redfish.ActionInfo"] = 158613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 1592b73119cSGeorge Liu }); 1604fbaf64aSAndrew Geissler } 1614fbaf64aSAndrew Geissler 162d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 163711ac7a9SEd Tanous const std::string& ethIfaceId, 164711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 16577179532SEd Tanous EthernetInterfaceData& ethData, std::vector<IPv4AddressData>& ipv4Config) 166d5afb2caSAndrew Geissler { 167d5afb2caSAndrew Geissler bool idFound = false; 168d5afb2caSAndrew Geissler for (const auto& objpath : dbusData) 169d5afb2caSAndrew Geissler { 170d5afb2caSAndrew Geissler for (const auto& ifacePair : objpath.second) 171d5afb2caSAndrew Geissler { 172d5afb2caSAndrew Geissler if (objpath.first == 173d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId) 174d5afb2caSAndrew Geissler { 175d5afb2caSAndrew Geissler idFound = true; 176d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 177d5afb2caSAndrew Geissler { 178d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 179d5afb2caSAndrew Geissler { 180d5afb2caSAndrew Geissler if (propertyPair.first == "MACAddress") 181d5afb2caSAndrew Geissler { 182d5afb2caSAndrew Geissler const std::string* mac = 183d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 184d5afb2caSAndrew Geissler if (mac != nullptr) 185d5afb2caSAndrew Geissler { 18682695a5bSJiaqing Zhao ethData.macAddress = *mac; 187d5afb2caSAndrew Geissler } 188d5afb2caSAndrew Geissler } 189d5afb2caSAndrew Geissler } 190d5afb2caSAndrew Geissler } 191d5afb2caSAndrew Geissler else if (ifacePair.first == 192d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface") 193d5afb2caSAndrew Geissler { 194d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 195d5afb2caSAndrew Geissler { 196d5afb2caSAndrew Geissler if (propertyPair.first == "DHCPEnabled") 197d5afb2caSAndrew Geissler { 198d5afb2caSAndrew Geissler const std::string* dhcp = 199d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 200d5afb2caSAndrew Geissler if (dhcp != nullptr) 201d5afb2caSAndrew Geissler { 20282695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcp; 203d5afb2caSAndrew Geissler break; // Interested on only "DHCPEnabled". 204d5afb2caSAndrew Geissler // Stop parsing since we got the 205d5afb2caSAndrew Geissler // "DHCPEnabled" value. 206d5afb2caSAndrew Geissler } 207d5afb2caSAndrew Geissler } 208d5afb2caSAndrew Geissler } 209d5afb2caSAndrew Geissler } 210d5afb2caSAndrew Geissler } 211d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor/" + 212d5afb2caSAndrew Geissler ethIfaceId + "/ipv4/addr0") 213d5afb2caSAndrew Geissler { 21477179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 215d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Object.Enable") 216d5afb2caSAndrew Geissler { 2179eb808c1SEd Tanous for (const auto& property : ifacePair.second) 218d5afb2caSAndrew Geissler { 219d5afb2caSAndrew Geissler if (property.first == "Enabled") 220d5afb2caSAndrew Geissler { 221d5afb2caSAndrew Geissler const bool* intfEnable = 222d5afb2caSAndrew Geissler std::get_if<bool>(&property.second); 223d5afb2caSAndrew Geissler if (intfEnable != nullptr) 224d5afb2caSAndrew Geissler { 225d5afb2caSAndrew Geissler ipv4Address.isActive = *intfEnable; 226d5afb2caSAndrew Geissler break; 227d5afb2caSAndrew Geissler } 228d5afb2caSAndrew Geissler } 229d5afb2caSAndrew Geissler } 230d5afb2caSAndrew Geissler } 231d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.IP") 232d5afb2caSAndrew Geissler { 2339eb808c1SEd Tanous for (const auto& property : ifacePair.second) 234d5afb2caSAndrew Geissler { 235d5afb2caSAndrew Geissler if (property.first == "Address") 236d5afb2caSAndrew Geissler { 237d5afb2caSAndrew Geissler const std::string* address = 238d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 239d5afb2caSAndrew Geissler if (address != nullptr) 240d5afb2caSAndrew Geissler { 241d5afb2caSAndrew Geissler ipv4Address.address = *address; 242d5afb2caSAndrew Geissler } 243d5afb2caSAndrew Geissler } 244d5afb2caSAndrew Geissler else if (property.first == "Origin") 245d5afb2caSAndrew Geissler { 246d5afb2caSAndrew Geissler const std::string* origin = 247d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 248d5afb2caSAndrew Geissler if (origin != nullptr) 249d5afb2caSAndrew Geissler { 250d5afb2caSAndrew Geissler ipv4Address.origin = 251d5afb2caSAndrew Geissler translateAddressOriginDbusToRedfish(*origin, 252d5afb2caSAndrew Geissler true); 253d5afb2caSAndrew Geissler } 254d5afb2caSAndrew Geissler } 255d5afb2caSAndrew Geissler else if (property.first == "PrefixLength") 256d5afb2caSAndrew Geissler { 257d5afb2caSAndrew Geissler const uint8_t* mask = 258d5afb2caSAndrew Geissler std::get_if<uint8_t>(&property.second); 259d5afb2caSAndrew Geissler if (mask != nullptr) 260d5afb2caSAndrew Geissler { 261d5afb2caSAndrew Geissler // convert it to the string 262d5afb2caSAndrew Geissler ipv4Address.netmask = getNetmask(*mask); 263d5afb2caSAndrew Geissler } 264d5afb2caSAndrew Geissler } 265889ff694SAsmitha Karunanithi else if (property.first == "Type" || 266889ff694SAsmitha Karunanithi property.first == "Gateway") 267889ff694SAsmitha Karunanithi { 268889ff694SAsmitha Karunanithi // Type & Gateway is not used 269889ff694SAsmitha Karunanithi continue; 270889ff694SAsmitha Karunanithi } 271d5afb2caSAndrew Geissler else 272d5afb2caSAndrew Geissler { 27362598e31SEd Tanous BMCWEB_LOG_ERROR( 27462598e31SEd Tanous "Got extra property: {} on the {} object", 27562598e31SEd Tanous property.first, objpath.first.str); 276d5afb2caSAndrew Geissler } 277d5afb2caSAndrew Geissler } 278d5afb2caSAndrew Geissler } 279d5afb2caSAndrew Geissler } 280d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 281d5afb2caSAndrew Geissler { 282d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 283d5afb2caSAndrew Geissler // need to check eth number 284d5afb2caSAndrew Geissler if (ifacePair.first == 285d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 286d5afb2caSAndrew Geissler { 287d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 288d5afb2caSAndrew Geissler { 289d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 290d5afb2caSAndrew Geissler { 291d5afb2caSAndrew Geissler const std::string* hostName = 292d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 293d5afb2caSAndrew Geissler if (hostName != nullptr) 294d5afb2caSAndrew Geissler { 29582695a5bSJiaqing Zhao ethData.hostName = *hostName; 296d5afb2caSAndrew Geissler } 297d5afb2caSAndrew Geissler } 298d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 299d5afb2caSAndrew Geissler { 300d5afb2caSAndrew Geissler const std::string* defaultGateway = 301d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 302d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 303d5afb2caSAndrew Geissler { 30482695a5bSJiaqing Zhao ethData.defaultGateway = *defaultGateway; 305d5afb2caSAndrew Geissler } 306d5afb2caSAndrew Geissler } 307d5afb2caSAndrew Geissler } 308d5afb2caSAndrew Geissler } 309d5afb2caSAndrew Geissler } 310d5afb2caSAndrew Geissler } 311d5afb2caSAndrew Geissler } 312d5afb2caSAndrew Geissler return idFound; 313d5afb2caSAndrew Geissler } 314d5afb2caSAndrew Geissler /** 315d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 316d5afb2caSAndrew Geissler * Interface Object from Settings Manager 317d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 318d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 319d5afb2caSAndrew Geissler * into JSON 320d5afb2caSAndrew Geissler */ 321d5afb2caSAndrew Geissler template <typename CallbackFunc> 322d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 323d5afb2caSAndrew Geissler CallbackFunc&& callback) 324d5afb2caSAndrew Geissler { 3255eb468daSGeorge Liu sdbusplus::message::object_path path("/"); 3265eb468daSGeorge Liu dbus::utility::getManagedObjects( 3275eb468daSGeorge Liu "xyz.openbmc_project.Settings", path, 328f94c4ecfSEd Tanous [ethIfaceId{std::string{ethIfaceId}}, 3298cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 3308b24275dSEd Tanous const boost::system::error_code& ec, 33121fe928bSEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 332d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 33377179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 3348b24275dSEd Tanous if (ec) 335d5afb2caSAndrew Geissler { 336d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 337d5afb2caSAndrew Geissler return; 338d5afb2caSAndrew Geissler } 339d5afb2caSAndrew Geissler 34089492a15SPatrick Williams bool found = extractHypervisorInterfaceData(ethIfaceId, resp, ethData, 34189492a15SPatrick Williams ipv4Data); 342d5afb2caSAndrew Geissler if (!found) 343d5afb2caSAndrew Geissler { 34462598e31SEd Tanous BMCWEB_LOG_INFO("Hypervisor Interface not found"); 345d5afb2caSAndrew Geissler } 346d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 3475eb468daSGeorge Liu }); 348d5afb2caSAndrew Geissler } 349d5afb2caSAndrew Geissler 350d5afb2caSAndrew Geissler /** 351d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 352d5afb2caSAndrew Geissler * 353ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 354d5afb2caSAndrew Geissler * @param[in] ipv4Address Address from the incoming request 355d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 356d5afb2caSAndrew Geissler * 357d5afb2caSAndrew Geissler * @return None. 358d5afb2caSAndrew Geissler */ 359ac106bf6SEd Tanous inline void setHypervisorIPv4Address( 360ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 361ac106bf6SEd Tanous const std::string& ethIfaceId, const std::string& ipv4Address) 362d5afb2caSAndrew Geissler { 36362598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor IPaddress : {} on Iface: {}", 36462598e31SEd Tanous ipv4Address, ethIfaceId); 365d82b5e1fSAsmitha Karunanithi 366e93abac6SGinu George setDbusProperty(asyncResp, "IPv4StaticAddresses/1/Address", 367e93abac6SGinu George "xyz.openbmc_project.Settings", 368d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + 369d82b5e1fSAsmitha Karunanithi "/ipv4/addr0", 370e93abac6SGinu George "xyz.openbmc_project.Network.IP", "Address", ipv4Address); 371d5afb2caSAndrew Geissler } 372d5afb2caSAndrew Geissler 373d5afb2caSAndrew Geissler /** 374d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 375d5afb2caSAndrew Geissler * 376ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 377d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 378d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 379d5afb2caSAndrew Geissler * 380d5afb2caSAndrew Geissler * @return None. 381d5afb2caSAndrew Geissler */ 3828d1b46d7Szhanghch05 inline void 383ac106bf6SEd Tanous setHypervisorIPv4Subnet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3848d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 385d5afb2caSAndrew Geissler { 38662598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor subnet : {} on Iface: {}", subnet, 38762598e31SEd Tanous ethIfaceId); 388d5afb2caSAndrew Geissler 389e93abac6SGinu George setDbusProperty(asyncResp, "IPv4StaticAddresses/1/SubnetMask", 390e93abac6SGinu George "xyz.openbmc_project.Settings", 391d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + 392d82b5e1fSAsmitha Karunanithi "/ipv4/addr0", 393e93abac6SGinu George "xyz.openbmc_project.Network.IP", "PrefixLength", subnet); 394d5afb2caSAndrew Geissler } 395d5afb2caSAndrew Geissler 396d5afb2caSAndrew Geissler /** 397d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 398d5afb2caSAndrew Geissler * 399ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 400d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 401d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 402d5afb2caSAndrew Geissler * 403d5afb2caSAndrew Geissler * @return None. 404d5afb2caSAndrew Geissler */ 405ac106bf6SEd Tanous inline void setHypervisorIPv4Gateway( 406ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 407d5afb2caSAndrew Geissler const std::string& gateway) 408d5afb2caSAndrew Geissler { 40962598e31SEd Tanous BMCWEB_LOG_DEBUG( 41062598e31SEd Tanous "Setting the DefaultGateway to the last configured gateway"); 411d5afb2caSAndrew Geissler 412e93abac6SGinu George setDbusProperty(asyncResp, "IPv4StaticAddresses/1/Gateway", 413e93abac6SGinu George "xyz.openbmc_project.Settings", 414d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 415d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 416d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 417e93abac6SGinu George "DefaultGateway", gateway); 418d5afb2caSAndrew Geissler } 419d5afb2caSAndrew Geissler 420d5afb2caSAndrew Geissler /** 421d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 422d5afb2caSAndrew Geissler * 423d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 424d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 425d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 426d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 427d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 428d5afb2caSAndrew Geissler * 429d5afb2caSAndrew Geissler * @return None 430d5afb2caSAndrew Geissler */ 4318d1b46d7Szhanghch05 inline void 4328d1b46d7Szhanghch05 createHypervisorIPv4(const std::string& ifaceId, uint8_t prefixLength, 4338d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4348d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 435d5afb2caSAndrew Geissler { 436d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 437d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 438d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 439d5afb2caSAndrew Geissler } 440d5afb2caSAndrew Geissler 441d5afb2caSAndrew Geissler /** 442d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 443d5afb2caSAndrew Geissler * 444d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 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 deleteHypervisorIPv4(const std::string& ifaceId, 4518d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 452d5afb2caSAndrew Geissler { 453d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 454d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 455d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 456d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 457d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 458d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 459d5afb2caSAndrew Geissler } 460d5afb2caSAndrew Geissler 46177179532SEd Tanous inline void parseInterfaceData(nlohmann::json& jsonResponse, 46277179532SEd Tanous const std::string& ifaceId, 463d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 46477179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) 465d5afb2caSAndrew Geissler { 466d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 467ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 468ef4c65b7SEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", ifaceId); 469d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 47082695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 471d5afb2caSAndrew Geissler 47282695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 473d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 47482695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 475d5afb2caSAndrew Geissler 476d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 477d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 478d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 479d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 4809eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 481d5afb2caSAndrew Geissler { 482d5afb2caSAndrew Geissler if (ipv4Config.isActive) 483d5afb2caSAndrew Geissler { 4841476687dSEd Tanous nlohmann::json::object_t ipv4; 4851476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 4861476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 4871476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 4881476687dSEd Tanous ipv4["Gateway"] = ethData.defaultGateway; 489d5afb2caSAndrew Geissler 490d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 491d5afb2caSAndrew Geissler { 4921476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 493d5afb2caSAndrew Geissler } 494b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 495d5afb2caSAndrew Geissler } 496d5afb2caSAndrew Geissler } 497d5afb2caSAndrew Geissler } 498d5afb2caSAndrew Geissler 49977179532SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, bool ipv4DHCPEnabled, 5008d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 501d5afb2caSAndrew Geissler { 5027e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 503d82b5e1fSAsmitha Karunanithi 504e93abac6SGinu George setDbusProperty( 505e93abac6SGinu George asyncResp, "DHCPv4/DHCPEnabled", "xyz.openbmc_project.Settings", 506d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 507d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor") / 508d82b5e1fSAsmitha Karunanithi ifaceId, 509e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled", dhcp); 510d5afb2caSAndrew Geissler 511d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 512d5afb2caSAndrew Geissler // of the DHCPEnabled property 513d5afb2caSAndrew Geissler std::string origin; 514e05aec50SEd Tanous if (!ipv4DHCPEnabled) 515d5afb2caSAndrew Geissler { 516d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 517d5afb2caSAndrew Geissler } 518d5afb2caSAndrew Geissler else 519d5afb2caSAndrew Geissler { 520d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 521d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 522d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 523d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 524d5afb2caSAndrew Geissler } 525d82b5e1fSAsmitha Karunanithi 526e93abac6SGinu George setDbusProperty(asyncResp, "IPv4StaticAddresses/1/AddressOrigin", 527e93abac6SGinu George "xyz.openbmc_project.Settings", 528d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor/" + ifaceId + 529d82b5e1fSAsmitha Karunanithi "/ipv4/addr0", 530e93abac6SGinu George "xyz.openbmc_project.Network.IP", "Origin", origin); 531d5afb2caSAndrew Geissler } 532d5afb2caSAndrew Geissler 5337e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 53421fe928bSEd Tanous const std::string& ifaceId, 53521fe928bSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 5367e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 537d5afb2caSAndrew Geissler { 5387e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 5397e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 5407e860f15SJohn Edward Broadbent // address 54121fe928bSEd Tanous std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson = input[0]; 54221fe928bSEd Tanous nlohmann::json::object_t* obj = 54321fe928bSEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 54421fe928bSEd Tanous if (obj == nullptr) 5457e860f15SJohn Edward Broadbent { 54621fe928bSEd Tanous deleteHypervisorIPv4(ifaceId, asyncResp); 54721fe928bSEd Tanous return; 54821fe928bSEd Tanous } 54921fe928bSEd Tanous if (obj->empty()) 55021fe928bSEd Tanous { 55121fe928bSEd Tanous return; 55221fe928bSEd Tanous } 553f8fe53e7SEd Tanous // For the error string 554f8fe53e7SEd Tanous std::string pathString = "IPv4StaticAddresses/1"; 55521fe928bSEd Tanous std::string address; 55621fe928bSEd Tanous std::string subnetMask; 55721fe928bSEd Tanous std::string gateway; 55821fe928bSEd Tanous if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address, 55921fe928bSEd Tanous "SubnetMask", subnetMask, "Gateway", 5607e860f15SJohn Edward Broadbent gateway)) 5617e860f15SJohn Edward Broadbent { 5627e860f15SJohn Edward Broadbent return; 5637e860f15SJohn Edward Broadbent } 5647e860f15SJohn Edward Broadbent 5657e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 56621fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(address)) 5677e860f15SJohn Edward Broadbent { 56821fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, address, 5697e860f15SJohn Edward Broadbent pathString + "/Address"); 57021fe928bSEd Tanous return; 5717e860f15SJohn Edward Broadbent } 5727e860f15SJohn Edward Broadbent 57321fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(subnetMask, &prefixLength)) 5747e860f15SJohn Edward Broadbent { 57521fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, subnetMask, 5767e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 57721fe928bSEd Tanous return; 5787e860f15SJohn Edward Broadbent } 5797e860f15SJohn Edward Broadbent 58021fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(gateway)) 5817e860f15SJohn Edward Broadbent { 58221fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, gateway, 5837e860f15SJohn Edward Broadbent pathString + "/Gateway"); 5847e860f15SJohn Edward Broadbent return; 5857e860f15SJohn Edward Broadbent } 5867e860f15SJohn Edward Broadbent 58762598e31SEd Tanous BMCWEB_LOG_DEBUG("Calling createHypervisorIPv4 on : {},{}", ifaceId, 58821fe928bSEd Tanous address); 58921fe928bSEd Tanous createHypervisorIPv4(ifaceId, prefixLength, gateway, address, asyncResp); 5907e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 5917e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 5927e860f15SJohn Edward Broadbent } 5937e860f15SJohn Edward Broadbent 59488a8a174SEd Tanous inline void handleHypervisorHostnamePatch( 59588a8a174SEd Tanous const std::string& hostName, 5967e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 5977e860f15SJohn Edward Broadbent { 5987e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 5997e860f15SJohn Edward Broadbent { 6007e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 6017e860f15SJohn Edward Broadbent "HostName"); 6027e860f15SJohn Edward Broadbent return; 6037e860f15SJohn Edward Broadbent } 6047e860f15SJohn Edward Broadbent 6057e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 606e93abac6SGinu George setDbusProperty(asyncResp, "HostName", "xyz.openbmc_project.Settings", 607d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 608d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 609d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 610e93abac6SGinu George "HostName", hostName); 6117e860f15SJohn Edward Broadbent } 6127e860f15SJohn Edward Broadbent 6137e860f15SJohn Edward Broadbent inline void 61477179532SEd Tanous setIPv4InterfaceEnabled(const std::string& ifaceId, bool isActive, 6157e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6167e860f15SJohn Edward Broadbent { 617e93abac6SGinu George setDbusProperty( 618e93abac6SGinu George asyncResp, "InterfaceEnabled", "xyz.openbmc_project.Settings", 619e93abac6SGinu George "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 620e93abac6SGinu George "xyz.openbmc_project.Object.Enable", "Enabled", isActive); 6217e860f15SJohn Edward Broadbent } 6227e860f15SJohn Edward Broadbent 623f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceCollectionGet( 624f40448e5SGunnar Mills App& app, const crow::Request& req, 625f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 626f40448e5SGunnar Mills { 627f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 628f40448e5SGunnar Mills { 629f40448e5SGunnar Mills return; 630f40448e5SGunnar Mills } 631f40448e5SGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 632f40448e5SGunnar Mills "xyz.openbmc_project.Network.EthernetInterface"}; 633f40448e5SGunnar Mills 634f40448e5SGunnar Mills dbus::utility::getSubTreePaths( 635f40448e5SGunnar Mills "/xyz/openbmc_project/network/hypervisor", 0, interfaces, 636f40448e5SGunnar Mills [asyncResp]( 6378b24275dSEd Tanous const boost::system::error_code& ec, 638f40448e5SGunnar Mills const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) { 6398b24275dSEd Tanous if (ec) 640f40448e5SGunnar Mills { 641f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "System", "hypervisor"); 642f40448e5SGunnar Mills return; 643f40448e5SGunnar Mills } 644f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 645f40448e5SGunnar Mills "#EthernetInterfaceCollection." 646f40448e5SGunnar Mills "EthernetInterfaceCollection"; 647f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 648f40448e5SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 649f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet " 650f40448e5SGunnar Mills "Interface Collection"; 651f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 652f40448e5SGunnar Mills "Collection of Virtual Management " 653f40448e5SGunnar Mills "Interfaces for the hypervisor"; 654f40448e5SGunnar Mills 655f40448e5SGunnar Mills nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 656f40448e5SGunnar Mills ifaceArray = nlohmann::json::array(); 657f40448e5SGunnar Mills for (const std::string& iface : ifaceList) 658f40448e5SGunnar Mills { 659f40448e5SGunnar Mills sdbusplus::message::object_path path(iface); 660f40448e5SGunnar Mills std::string name = path.filename(); 661f40448e5SGunnar Mills if (name.empty()) 662f40448e5SGunnar Mills { 663f40448e5SGunnar Mills continue; 664f40448e5SGunnar Mills } 665f40448e5SGunnar Mills nlohmann::json::object_t ethIface; 666ef4c65b7SEd Tanous ethIface["@odata.id"] = boost::urls::format( 667ef4c65b7SEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", name); 668b2ba3072SPatrick Williams ifaceArray.emplace_back(std::move(ethIface)); 669f40448e5SGunnar Mills } 670f40448e5SGunnar Mills asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 671f40448e5SGunnar Mills }); 672f40448e5SGunnar Mills } 673f40448e5SGunnar Mills 674f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceGet( 675f40448e5SGunnar Mills App& app, const crow::Request& req, 676f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 677f40448e5SGunnar Mills { 678f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 679f40448e5SGunnar Mills { 680f40448e5SGunnar Mills return; 681f40448e5SGunnar Mills } 682f40448e5SGunnar Mills getHypervisorIfaceData( 683f40448e5SGunnar Mills id, [asyncResp, ifaceId{std::string(id)}]( 68477179532SEd Tanous bool success, const EthernetInterfaceData& ethData, 68577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) { 686f40448e5SGunnar Mills if (!success) 687f40448e5SGunnar Mills { 688f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 689f40448e5SGunnar Mills ifaceId); 690f40448e5SGunnar Mills return; 691f40448e5SGunnar Mills } 692f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 69393bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 694f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface"; 695f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 696f40448e5SGunnar Mills "Hypervisor's Virtual Management Ethernet Interface"; 697f40448e5SGunnar Mills parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData, 698f40448e5SGunnar Mills ipv4Data); 699f40448e5SGunnar Mills }); 700f40448e5SGunnar Mills } 701f40448e5SGunnar Mills 7028d8c30c3SGunnar Mills inline void handleHypervisorSystemGet( 7038d8c30c3SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7048d8c30c3SGunnar Mills { 7058d8c30c3SGunnar Mills sdbusplus::asio::getProperty<std::string>( 7068d8c30c3SGunnar Mills *crow::connections::systemBus, "xyz.openbmc_project.Settings", 7078d8c30c3SGunnar Mills "/xyz/openbmc_project/network/hypervisor", 7088d8c30c3SGunnar Mills "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 7098d8c30c3SGunnar Mills [asyncResp](const boost::system::error_code& ec, 7108d8c30c3SGunnar Mills const std::string& /*hostName*/) { 7118d8c30c3SGunnar Mills if (ec) 7128d8c30c3SGunnar Mills { 7138d8c30c3SGunnar Mills messages::resourceNotFound(asyncResp->res, "System", "hypervisor"); 7148d8c30c3SGunnar Mills return; 7158d8c30c3SGunnar Mills } 71662598e31SEd Tanous BMCWEB_LOG_DEBUG("Hypervisor is available"); 7178d8c30c3SGunnar Mills 7188d8c30c3SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 7198d8c30c3SGunnar Mills "#ComputerSystem.v1_6_0.ComputerSystem"; 7208d8c30c3SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 7218d8c30c3SGunnar Mills "/redfish/v1/Systems/hypervisor"; 7228d8c30c3SGunnar Mills asyncResp->res.jsonValue["Description"] = "Hypervisor"; 7238d8c30c3SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor"; 7248d8c30c3SGunnar Mills asyncResp->res.jsonValue["Id"] = "hypervisor"; 725*539d8c6bSEd Tanous asyncResp->res.jsonValue["SystemType"] = 726*539d8c6bSEd Tanous computer_system::SystemType::OS; 7278d8c30c3SGunnar Mills nlohmann::json::array_t managedBy; 7288d8c30c3SGunnar Mills nlohmann::json::object_t manager; 729253f11b8SEd Tanous manager["@odata.id"] = boost::urls::format( 730253f11b8SEd Tanous "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 731ad539545SPatrick Williams managedBy.emplace_back(std::move(manager)); 7328d8c30c3SGunnar Mills asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); 7338d8c30c3SGunnar Mills asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 7348d8c30c3SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 7358d8c30c3SGunnar Mills getHypervisorState(asyncResp); 7368d8c30c3SGunnar Mills getHypervisorActions(asyncResp); 7378d8c30c3SGunnar Mills // TODO: Add "SystemType" : "hypervisor" 7388d8c30c3SGunnar Mills }); 7398d8c30c3SGunnar Mills } 7408d8c30c3SGunnar Mills 741f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfacePatch( 742f40448e5SGunnar Mills App& app, const crow::Request& req, 743f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 744f40448e5SGunnar Mills const std::string& ifaceId) 745f40448e5SGunnar Mills { 746f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 747f40448e5SGunnar Mills { 748f40448e5SGunnar Mills return; 749f40448e5SGunnar Mills } 750f40448e5SGunnar Mills std::optional<std::string> hostName; 75121fe928bSEd Tanous std::optional< 75221fe928bSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 75321fe928bSEd Tanous ipv4StaticAddresses; 75421fe928bSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> ipv4Addresses; 755f40448e5SGunnar Mills std::optional<bool> ipv4DHCPEnabled; 756f40448e5SGunnar Mills 757f40448e5SGunnar Mills if (!json_util::readJsonPatch(req, asyncResp->res, "HostName", hostName, 758f40448e5SGunnar Mills "IPv4StaticAddresses", ipv4StaticAddresses, 75921fe928bSEd Tanous "IPv4Addresses", ipv4Addresses, 76021fe928bSEd Tanous "DHCPv4/DHCPEnabled", ipv4DHCPEnabled)) 761f40448e5SGunnar Mills { 762f40448e5SGunnar Mills return; 763f40448e5SGunnar Mills } 764f40448e5SGunnar Mills 765f40448e5SGunnar Mills if (ipv4Addresses) 766f40448e5SGunnar Mills { 767f40448e5SGunnar Mills messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 768f40448e5SGunnar Mills return; 769f40448e5SGunnar Mills } 770f40448e5SGunnar Mills 771f40448e5SGunnar Mills getHypervisorIfaceData( 77221fe928bSEd Tanous ifaceId, 77321fe928bSEd Tanous [asyncResp, ifaceId, hostName = std::move(hostName), 7745a39f77aSPatrick Williams ipv4StaticAddresses = std::move(ipv4StaticAddresses), 77521fe928bSEd Tanous ipv4DHCPEnabled](bool success, const EthernetInterfaceData& ethData, 77621fe928bSEd Tanous const std::vector<IPv4AddressData>&) mutable { 777f40448e5SGunnar Mills if (!success) 778f40448e5SGunnar Mills { 779f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 780f40448e5SGunnar Mills ifaceId); 781f40448e5SGunnar Mills return; 782f40448e5SGunnar Mills } 783f40448e5SGunnar Mills 784f40448e5SGunnar Mills if (ipv4StaticAddresses) 785f40448e5SGunnar Mills { 78621fe928bSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& 78721fe928bSEd Tanous ipv4Static = *ipv4StaticAddresses; 788f40448e5SGunnar Mills if (ipv4Static.begin() == ipv4Static.end()) 789f40448e5SGunnar Mills { 79021fe928bSEd Tanous messages::propertyValueTypeError(asyncResp->res, 79121fe928bSEd Tanous std::vector<std::string>(), 792f40448e5SGunnar Mills "IPv4StaticAddresses"); 793f40448e5SGunnar Mills return; 794f40448e5SGunnar Mills } 795f40448e5SGunnar Mills 796f40448e5SGunnar Mills // One and only one hypervisor instance supported 797f40448e5SGunnar Mills if (ipv4Static.size() != 1) 798f40448e5SGunnar Mills { 79921fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, "[]", 800f40448e5SGunnar Mills "IPv4StaticAddresses"); 801f40448e5SGunnar Mills return; 802f40448e5SGunnar Mills } 803f40448e5SGunnar Mills 80421fe928bSEd Tanous std::variant<nlohmann::json::object_t, std::nullptr_t>& ipv4Json = 80521fe928bSEd Tanous ipv4Static[0]; 806f40448e5SGunnar Mills // Check if the param is 'null'. If its null, it means 807f40448e5SGunnar Mills // that user wants to delete the IP address. Deleting 808f40448e5SGunnar Mills // the IP address is allowed only if its statically 809f40448e5SGunnar Mills // configured. Deleting the address originated from DHCP 810f40448e5SGunnar Mills // is not allowed. 81121fe928bSEd Tanous if (std::holds_alternative<std::nullptr_t>(ipv4Json) && 81221fe928bSEd Tanous translateDhcpEnabledToBool(ethData.dhcpEnabled, true)) 813f40448e5SGunnar Mills { 81462598e31SEd Tanous BMCWEB_LOG_INFO("Ignoring the delete on ipv4StaticAddresses " 81562598e31SEd Tanous "as the interface is DHCP enabled"); 816f40448e5SGunnar Mills } 817f40448e5SGunnar Mills else 818f40448e5SGunnar Mills { 819f40448e5SGunnar Mills handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, asyncResp); 820f40448e5SGunnar Mills } 821f40448e5SGunnar Mills } 822f40448e5SGunnar Mills 823f40448e5SGunnar Mills if (hostName) 824f40448e5SGunnar Mills { 825f40448e5SGunnar Mills handleHypervisorHostnamePatch(*hostName, asyncResp); 826f40448e5SGunnar Mills } 827f40448e5SGunnar Mills 82821fe928bSEd Tanous if (ipv4DHCPEnabled) 829f40448e5SGunnar Mills { 830f40448e5SGunnar Mills setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 831f40448e5SGunnar Mills } 832f40448e5SGunnar Mills 833f40448e5SGunnar Mills // Set this interface to disabled/inactive. This will be set 834f40448e5SGunnar Mills // to enabled/active by the pldm once the hypervisor 835f40448e5SGunnar Mills // consumes the updated settings from the user. 836f40448e5SGunnar Mills setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 837f40448e5SGunnar Mills }); 838f40448e5SGunnar Mills asyncResp->res.result(boost::beast::http::status::accepted); 839f40448e5SGunnar Mills } 840f40448e5SGunnar Mills 841a5d0cedbSGunnar Mills inline void handleHypervisorResetActionGet( 842a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 843a5d0cedbSGunnar Mills { 844a5d0cedbSGunnar Mills // Only return action info if hypervisor D-Bus object present 845a5d0cedbSGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 846a5d0cedbSGunnar Mills "xyz.openbmc_project.State.Host"}; 847a5d0cedbSGunnar Mills dbus::utility::getDbusObject( 848a5d0cedbSGunnar Mills "/xyz/openbmc_project/state/hypervisor0", interfaces, 849a5d0cedbSGunnar Mills [asyncResp]( 850a5d0cedbSGunnar Mills const boost::system::error_code& ec, 851a5d0cedbSGunnar Mills const std::vector<std::pair<std::string, std::vector<std::string>>>& 852a5d0cedbSGunnar Mills objInfo) { 853a5d0cedbSGunnar Mills if (ec) 854a5d0cedbSGunnar Mills { 85562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 856a5d0cedbSGunnar Mills 857a5d0cedbSGunnar Mills // No hypervisor objects found by mapper 858a5d0cedbSGunnar Mills if (ec.value() == boost::system::errc::io_error) 859a5d0cedbSGunnar Mills { 860a5d0cedbSGunnar Mills messages::resourceNotFound(asyncResp->res, "hypervisor", 861a5d0cedbSGunnar Mills "ResetActionInfo"); 862a5d0cedbSGunnar Mills return; 863a5d0cedbSGunnar Mills } 864a5d0cedbSGunnar Mills 865a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 866a5d0cedbSGunnar Mills return; 867a5d0cedbSGunnar Mills } 868a5d0cedbSGunnar Mills 869a5d0cedbSGunnar Mills // One and only one hypervisor instance supported 870a5d0cedbSGunnar Mills if (objInfo.size() != 1) 871a5d0cedbSGunnar Mills { 872a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 873a5d0cedbSGunnar Mills return; 874a5d0cedbSGunnar Mills } 875a5d0cedbSGunnar Mills 876a5d0cedbSGunnar Mills // The hypervisor object only support the ability to 877a5d0cedbSGunnar Mills // turn On The system object Action should be utilized 878a5d0cedbSGunnar Mills // for other operations 879a5d0cedbSGunnar Mills 880a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 881a5d0cedbSGunnar Mills "#ActionInfo.v1_1_2.ActionInfo"; 882a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 883a5d0cedbSGunnar Mills "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 884a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 885a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 886a5d0cedbSGunnar Mills nlohmann::json::array_t parameters; 887a5d0cedbSGunnar Mills nlohmann::json::object_t parameter; 888a5d0cedbSGunnar Mills parameter["Name"] = "ResetType"; 889a5d0cedbSGunnar Mills parameter["Required"] = true; 890*539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 891a5d0cedbSGunnar Mills nlohmann::json::array_t allowed; 892ad539545SPatrick Williams allowed.emplace_back("On"); 893a5d0cedbSGunnar Mills parameter["AllowableValues"] = std::move(allowed); 894ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 895a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 896a5d0cedbSGunnar Mills }); 897a5d0cedbSGunnar Mills } 898a5d0cedbSGunnar Mills 899a5d0cedbSGunnar Mills inline void handleHypervisorSystemResetPost( 900a5d0cedbSGunnar Mills App& app, const crow::Request& req, 901a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 902a5d0cedbSGunnar Mills { 903a5d0cedbSGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 904a5d0cedbSGunnar Mills { 905a5d0cedbSGunnar Mills return; 906a5d0cedbSGunnar Mills } 907a5d0cedbSGunnar Mills std::optional<std::string> resetType; 908a5d0cedbSGunnar Mills if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 909a5d0cedbSGunnar Mills { 910a5d0cedbSGunnar Mills // readJson adds appropriate error to response 911a5d0cedbSGunnar Mills return; 912a5d0cedbSGunnar Mills } 913a5d0cedbSGunnar Mills 914a5d0cedbSGunnar Mills if (!resetType) 915a5d0cedbSGunnar Mills { 916a5d0cedbSGunnar Mills messages::actionParameterMissing(asyncResp->res, "ComputerSystem.Reset", 917a5d0cedbSGunnar Mills "ResetType"); 918a5d0cedbSGunnar Mills return; 919a5d0cedbSGunnar Mills } 920a5d0cedbSGunnar Mills 921a5d0cedbSGunnar Mills // Hypervisor object only support On operation 922a5d0cedbSGunnar Mills if (resetType != "On") 923a5d0cedbSGunnar Mills { 924a5d0cedbSGunnar Mills messages::propertyValueNotInList(asyncResp->res, *resetType, 925a5d0cedbSGunnar Mills "ResetType"); 926a5d0cedbSGunnar Mills return; 927a5d0cedbSGunnar Mills } 928a5d0cedbSGunnar Mills 929a5d0cedbSGunnar Mills std::string command = "xyz.openbmc_project.State.Host.Transition.On"; 930a5d0cedbSGunnar Mills 9311827b4f1SAsmitha Karunanithi setDbusPropertyAction(asyncResp, "xyz.openbmc_project.State.Hypervisor", 9321827b4f1SAsmitha Karunanithi sdbusplus::message::object_path( 9331827b4f1SAsmitha Karunanithi "/xyz/openbmc_project/state/hypervisor0"), 9341827b4f1SAsmitha Karunanithi "xyz.openbmc_project.State.Host", 9351827b4f1SAsmitha Karunanithi "RequestedHostTransition", "ResetType", 9361827b4f1SAsmitha Karunanithi "ComputerSystem.Reset", command); 937a5d0cedbSGunnar Mills } 938a5d0cedbSGunnar Mills 9397e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 9407e860f15SJohn Edward Broadbent { 9417e860f15SJohn Edward Broadbent /** 9427e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 9437e860f15SJohn Edward Broadbent * Hypervisor Interface 9447e860f15SJohn Edward Broadbent */ 9457e860f15SJohn Edward Broadbent 9467e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 947ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 948f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 949f40448e5SGunnar Mills handleHypervisorEthernetInterfaceCollectionGet, std::ref(app))); 9507e860f15SJohn Edward Broadbent 9517e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9527e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 953ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 954f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 955f40448e5SGunnar Mills handleHypervisorEthernetInterfaceGet, std::ref(app))); 956d5afb2caSAndrew Geissler 9577e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9587e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 959ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 960f40448e5SGunnar Mills .methods(boost::beast::http::verb::patch)(std::bind_front( 961f40448e5SGunnar Mills handleHypervisorEthernetInterfacePatch, std::ref(app))); 9624fbaf64aSAndrew Geissler 9637e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9644fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/") 965ed398213SEd Tanous .privileges(redfish::privileges::postComputerSystem) 9667e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 967a5d0cedbSGunnar Mills std::bind_front(handleHypervisorSystemResetPost, std::ref(app))); 9684fbaf64aSAndrew Geissler } 96988a8a174SEd Tanous } // namespace redfish 970