1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3d5afb2caSAndrew Geissler #pragma once 4d5afb2caSAndrew Geissler 53ccb3adbSEd Tanous #include "app.hpp" 63ccb3adbSEd Tanous #include "dbus_singleton.hpp" 77a1dbc48SGeorge Liu #include "dbus_utility.hpp" 83ccb3adbSEd Tanous #include "error_messages.hpp" 93ccb3adbSEd Tanous #include "ethernet.hpp" 10539d8c6bSEd Tanous #include "generated/enums/action_info.hpp" 11539d8c6bSEd Tanous #include "generated/enums/computer_system.hpp" 12539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 133ccb3adbSEd Tanous #include "query.hpp" 143ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 15033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 163ccb3adbSEd Tanous #include "utils/json_utils.hpp" 17033f1e4dSEd Tanous 18ef4c65b7SEd Tanous #include <boost/url/format.hpp> 191e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 20d5afb2caSAndrew Geissler 217a1dbc48SGeorge Liu #include <array> 22d5afb2caSAndrew Geissler #include <optional> 237a1dbc48SGeorge Liu #include <string_view> 24d5afb2caSAndrew Geissler #include <utility> 25d5afb2caSAndrew Geissler 2688a8a174SEd Tanous namespace redfish 27d5afb2caSAndrew Geissler { 28d5afb2caSAndrew Geissler 29d5afb2caSAndrew Geissler /** 30cc0bb6f2SAndrew Geissler * @brief Retrieves hypervisor state properties over dbus 31cc0bb6f2SAndrew Geissler * 32cc0bb6f2SAndrew Geissler * The hypervisor state object is optional so this function will only set the 33cc0bb6f2SAndrew Geissler * state variables if the object is found 34cc0bb6f2SAndrew Geissler * 35ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 36cc0bb6f2SAndrew Geissler * 37cc0bb6f2SAndrew Geissler * @return None. 38cc0bb6f2SAndrew Geissler */ 39ac106bf6SEd Tanous inline void 40ac106bf6SEd Tanous getHypervisorState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 41cc0bb6f2SAndrew Geissler { 4262598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor state information."); 43deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 44deae6a78SEd Tanous "xyz.openbmc_project.State.Hypervisor", 451e1e598dSJonathan Doman "/xyz/openbmc_project/state/hypervisor0", 461e1e598dSJonathan Doman "xyz.openbmc_project.State.Host", "CurrentHostState", 47ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 481e1e598dSJonathan Doman const std::string& hostState) { 49cc0bb6f2SAndrew Geissler if (ec) 50cc0bb6f2SAndrew Geissler { 5162598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 52cc0bb6f2SAndrew Geissler // This is an optional D-Bus object so just return if 53cc0bb6f2SAndrew Geissler // error occurs 54cc0bb6f2SAndrew Geissler return; 55cc0bb6f2SAndrew Geissler } 56cc0bb6f2SAndrew Geissler 5762598e31SEd Tanous BMCWEB_LOG_DEBUG("Hypervisor state: {}", hostState); 58cc0bb6f2SAndrew Geissler // Verify Host State 591e1e598dSJonathan Doman if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") 60cc0bb6f2SAndrew Geissler { 61bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 62bd79bce8SPatrick Williams resource::PowerState::On; 63539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 64539d8c6bSEd Tanous resource::State::Enabled; 65cc0bb6f2SAndrew Geissler } 661e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 671e1e598dSJonathan Doman "Quiesced") 68cc0bb6f2SAndrew Geissler { 69bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 70bd79bce8SPatrick Williams resource::PowerState::On; 71539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 72539d8c6bSEd Tanous resource::State::Quiesced; 73cc0bb6f2SAndrew Geissler } 741e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 751e1e598dSJonathan Doman "Standby") 76cc0bb6f2SAndrew Geissler { 77bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 78bd79bce8SPatrick Williams resource::PowerState::On; 79539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 80539d8c6bSEd Tanous resource::State::StandbyOffline; 81cc0bb6f2SAndrew Geissler } 821e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 831e1e598dSJonathan Doman "TransitioningToRunning") 84cc0bb6f2SAndrew Geissler { 85539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = 86539d8c6bSEd Tanous resource::PowerState::PoweringOn; 87539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 88539d8c6bSEd Tanous resource::State::Starting; 89cc0bb6f2SAndrew Geissler } 901e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 911e1e598dSJonathan Doman "TransitioningToOff") 92cc0bb6f2SAndrew Geissler { 93539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = 94539d8c6bSEd Tanous resource::PowerState::PoweringOff; 95539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 96539d8c6bSEd Tanous resource::State::Enabled; 97cc0bb6f2SAndrew Geissler } 98bd79bce8SPatrick Williams else if (hostState == 99bd79bce8SPatrick Williams "xyz.openbmc_project.State.Host.HostState.Off") 100cc0bb6f2SAndrew Geissler { 101bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 102bd79bce8SPatrick Williams resource::PowerState::Off; 103539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 104539d8c6bSEd Tanous resource::State::Disabled; 105cc0bb6f2SAndrew Geissler } 106cc0bb6f2SAndrew Geissler else 107cc0bb6f2SAndrew Geissler { 108ac106bf6SEd Tanous messages::internalError(asyncResp->res); 109cc0bb6f2SAndrew Geissler return; 110cc0bb6f2SAndrew Geissler } 1111e1e598dSJonathan Doman }); 112cc0bb6f2SAndrew Geissler } 113cc0bb6f2SAndrew Geissler 114cc0bb6f2SAndrew Geissler /** 1154fbaf64aSAndrew Geissler * @brief Populate Actions if any are valid for hypervisor object 1164fbaf64aSAndrew Geissler * 1174fbaf64aSAndrew Geissler * The hypervisor state object is optional so this function will only set the 1184fbaf64aSAndrew Geissler * Action if the object is found 1194fbaf64aSAndrew Geissler * 120ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 1214fbaf64aSAndrew Geissler * 1224fbaf64aSAndrew Geissler * @return None. 1234fbaf64aSAndrew Geissler */ 1248d1b46d7Szhanghch05 inline void 125ac106bf6SEd Tanous getHypervisorActions(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1264fbaf64aSAndrew Geissler { 12762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor actions."); 1282b73119cSGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1292b73119cSGeorge Liu "xyz.openbmc_project.State.Host"}; 1302b73119cSGeorge Liu dbus::utility::getDbusObject( 1312b73119cSGeorge Liu "/xyz/openbmc_project/state/hypervisor0", interfaces, 132ac106bf6SEd Tanous [asyncResp]( 1332b73119cSGeorge Liu const boost::system::error_code& ec, 1344fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1354fbaf64aSAndrew Geissler objInfo) { 1364fbaf64aSAndrew Geissler if (ec) 1374fbaf64aSAndrew Geissler { 13862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 1394fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1404fbaf64aSAndrew Geissler // error occurs 1414fbaf64aSAndrew Geissler return; 1424fbaf64aSAndrew Geissler } 1434fbaf64aSAndrew Geissler 14426f6976fSEd Tanous if (objInfo.empty()) 1454fbaf64aSAndrew Geissler { 1464fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1474fbaf64aSAndrew Geissler // if there is no instance found 1484fbaf64aSAndrew Geissler return; 1494fbaf64aSAndrew Geissler } 1504fbaf64aSAndrew Geissler 1514fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1524fbaf64aSAndrew Geissler { 1534fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1544fbaf64aSAndrew Geissler // error 155ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1564fbaf64aSAndrew Geissler return; 1574fbaf64aSAndrew Geissler } 1584fbaf64aSAndrew Geissler 1594fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 160613dabeaSEd Tanous nlohmann::json& reset = 161ac106bf6SEd Tanous asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]; 162613dabeaSEd Tanous reset["target"] = 163613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"; 164613dabeaSEd Tanous reset["@Redfish.ActionInfo"] = 165613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 1662b73119cSGeorge Liu }); 1674fbaf64aSAndrew Geissler } 1684fbaf64aSAndrew Geissler 169d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 170711ac7a9SEd Tanous const std::string& ethIfaceId, 171711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 17277179532SEd Tanous EthernetInterfaceData& ethData, std::vector<IPv4AddressData>& ipv4Config) 173d5afb2caSAndrew Geissler { 174d5afb2caSAndrew Geissler bool idFound = false; 175d5afb2caSAndrew Geissler for (const auto& objpath : dbusData) 176d5afb2caSAndrew Geissler { 177d5afb2caSAndrew Geissler for (const auto& ifacePair : objpath.second) 178d5afb2caSAndrew Geissler { 179d5afb2caSAndrew Geissler if (objpath.first == 180d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId) 181d5afb2caSAndrew Geissler { 182d5afb2caSAndrew Geissler idFound = true; 1834652c640SAsmitha Karunanithi if (ifacePair.first == 184d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface") 185d5afb2caSAndrew Geissler { 186d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 187d5afb2caSAndrew Geissler { 188d5afb2caSAndrew Geissler if (propertyPair.first == "DHCPEnabled") 189d5afb2caSAndrew Geissler { 190d5afb2caSAndrew Geissler const std::string* dhcp = 191d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 192d5afb2caSAndrew Geissler if (dhcp != nullptr) 193d5afb2caSAndrew Geissler { 19482695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcp; 195d5afb2caSAndrew Geissler break; // Interested on only "DHCPEnabled". 196d5afb2caSAndrew Geissler // Stop parsing since we got the 197d5afb2caSAndrew Geissler // "DHCPEnabled" value. 198d5afb2caSAndrew Geissler } 199d5afb2caSAndrew Geissler } 200d5afb2caSAndrew Geissler } 201d5afb2caSAndrew Geissler } 202d5afb2caSAndrew Geissler } 203d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor/" + 204d5afb2caSAndrew Geissler ethIfaceId + "/ipv4/addr0") 205d5afb2caSAndrew Geissler { 20677179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 207d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Object.Enable") 208d5afb2caSAndrew Geissler { 2099eb808c1SEd Tanous for (const auto& property : ifacePair.second) 210d5afb2caSAndrew Geissler { 211d5afb2caSAndrew Geissler if (property.first == "Enabled") 212d5afb2caSAndrew Geissler { 213d5afb2caSAndrew Geissler const bool* intfEnable = 214d5afb2caSAndrew Geissler std::get_if<bool>(&property.second); 215d5afb2caSAndrew Geissler if (intfEnable != nullptr) 216d5afb2caSAndrew Geissler { 217d5afb2caSAndrew Geissler ipv4Address.isActive = *intfEnable; 218d5afb2caSAndrew Geissler break; 219d5afb2caSAndrew Geissler } 220d5afb2caSAndrew Geissler } 221d5afb2caSAndrew Geissler } 222d5afb2caSAndrew Geissler } 223d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.IP") 224d5afb2caSAndrew Geissler { 2259eb808c1SEd Tanous for (const auto& property : ifacePair.second) 226d5afb2caSAndrew Geissler { 227d5afb2caSAndrew Geissler if (property.first == "Address") 228d5afb2caSAndrew Geissler { 229d5afb2caSAndrew Geissler const std::string* address = 230d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 231d5afb2caSAndrew Geissler if (address != nullptr) 232d5afb2caSAndrew Geissler { 233d5afb2caSAndrew Geissler ipv4Address.address = *address; 234d5afb2caSAndrew Geissler } 235d5afb2caSAndrew Geissler } 236d5afb2caSAndrew Geissler else if (property.first == "Origin") 237d5afb2caSAndrew Geissler { 238d5afb2caSAndrew Geissler const std::string* origin = 239d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 240d5afb2caSAndrew Geissler if (origin != nullptr) 241d5afb2caSAndrew Geissler { 242d5afb2caSAndrew Geissler ipv4Address.origin = 243d5afb2caSAndrew Geissler translateAddressOriginDbusToRedfish(*origin, 244d5afb2caSAndrew Geissler true); 245d5afb2caSAndrew Geissler } 246d5afb2caSAndrew Geissler } 247d5afb2caSAndrew Geissler else if (property.first == "PrefixLength") 248d5afb2caSAndrew Geissler { 249d5afb2caSAndrew Geissler const uint8_t* mask = 250d5afb2caSAndrew Geissler std::get_if<uint8_t>(&property.second); 251d5afb2caSAndrew Geissler if (mask != nullptr) 252d5afb2caSAndrew Geissler { 253d5afb2caSAndrew Geissler // convert it to the string 254d5afb2caSAndrew Geissler ipv4Address.netmask = getNetmask(*mask); 255d5afb2caSAndrew Geissler } 256d5afb2caSAndrew Geissler } 257889ff694SAsmitha Karunanithi else if (property.first == "Type" || 258889ff694SAsmitha Karunanithi property.first == "Gateway") 259889ff694SAsmitha Karunanithi { 260889ff694SAsmitha Karunanithi // Type & Gateway is not used 261889ff694SAsmitha Karunanithi continue; 262889ff694SAsmitha Karunanithi } 263d5afb2caSAndrew Geissler else 264d5afb2caSAndrew Geissler { 26562598e31SEd Tanous BMCWEB_LOG_ERROR( 26662598e31SEd Tanous "Got extra property: {} on the {} object", 26762598e31SEd Tanous property.first, objpath.first.str); 268d5afb2caSAndrew Geissler } 269d5afb2caSAndrew Geissler } 270d5afb2caSAndrew Geissler } 271d5afb2caSAndrew Geissler } 272d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 273d5afb2caSAndrew Geissler { 274d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 275d5afb2caSAndrew Geissler // need to check eth number 276d5afb2caSAndrew Geissler if (ifacePair.first == 277d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 278d5afb2caSAndrew Geissler { 279d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 280d5afb2caSAndrew Geissler { 281d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 282d5afb2caSAndrew Geissler { 283d5afb2caSAndrew Geissler const std::string* hostName = 284d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 285d5afb2caSAndrew Geissler if (hostName != nullptr) 286d5afb2caSAndrew Geissler { 28782695a5bSJiaqing Zhao ethData.hostName = *hostName; 288d5afb2caSAndrew Geissler } 289d5afb2caSAndrew Geissler } 290d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 291d5afb2caSAndrew Geissler { 292d5afb2caSAndrew Geissler const std::string* defaultGateway = 293d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 294d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 295d5afb2caSAndrew Geissler { 29682695a5bSJiaqing Zhao ethData.defaultGateway = *defaultGateway; 297d5afb2caSAndrew Geissler } 298d5afb2caSAndrew Geissler } 299d5afb2caSAndrew Geissler } 300d5afb2caSAndrew Geissler } 301d5afb2caSAndrew Geissler } 302d5afb2caSAndrew Geissler } 303d5afb2caSAndrew Geissler } 304d5afb2caSAndrew Geissler return idFound; 305d5afb2caSAndrew Geissler } 306d5afb2caSAndrew Geissler /** 307d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 308d5afb2caSAndrew Geissler * Interface Object from Settings Manager 309d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 310d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 311d5afb2caSAndrew Geissler * into JSON 312d5afb2caSAndrew Geissler */ 313d5afb2caSAndrew Geissler template <typename CallbackFunc> 314d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 315d5afb2caSAndrew Geissler CallbackFunc&& callback) 316d5afb2caSAndrew Geissler { 3175eb468daSGeorge Liu sdbusplus::message::object_path path("/"); 3185eb468daSGeorge Liu dbus::utility::getManagedObjects( 3195eb468daSGeorge Liu "xyz.openbmc_project.Settings", path, 320f94c4ecfSEd Tanous [ethIfaceId{std::string{ethIfaceId}}, 3218cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 3228b24275dSEd Tanous const boost::system::error_code& ec, 32321fe928bSEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 324d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 32577179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 3268b24275dSEd Tanous if (ec) 327d5afb2caSAndrew Geissler { 328d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 329d5afb2caSAndrew Geissler return; 330d5afb2caSAndrew Geissler } 331d5afb2caSAndrew Geissler 332bd79bce8SPatrick Williams bool found = extractHypervisorInterfaceData(ethIfaceId, resp, 333bd79bce8SPatrick Williams ethData, ipv4Data); 334d5afb2caSAndrew Geissler if (!found) 335d5afb2caSAndrew Geissler { 33662598e31SEd Tanous BMCWEB_LOG_INFO("Hypervisor Interface not found"); 337d5afb2caSAndrew Geissler } 338d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 3395eb468daSGeorge Liu }); 340d5afb2caSAndrew Geissler } 341d5afb2caSAndrew Geissler 342d5afb2caSAndrew Geissler /** 343d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 344d5afb2caSAndrew Geissler * 345ac106bf6SEd Tanous * @param[in] asyncResp 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 */ 351ac106bf6SEd Tanous inline void setHypervisorIPv4Address( 352ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 353ac106bf6SEd Tanous const std::string& ethIfaceId, const std::string& ipv4Address) 354d5afb2caSAndrew Geissler { 35562598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor IPaddress : {} on Iface: {}", 35662598e31SEd Tanous ipv4Address, ethIfaceId); 357d82b5e1fSAsmitha Karunanithi 358bd79bce8SPatrick Williams setDbusProperty( 359bd79bce8SPatrick Williams asyncResp, "IPv4StaticAddresses/1/Address", 360e93abac6SGinu George "xyz.openbmc_project.Settings", 361bd79bce8SPatrick Williams "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 362e93abac6SGinu George "xyz.openbmc_project.Network.IP", "Address", ipv4Address); 363d5afb2caSAndrew Geissler } 364d5afb2caSAndrew Geissler 365d5afb2caSAndrew Geissler /** 366d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 367d5afb2caSAndrew Geissler * 368ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 369d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 370d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 371d5afb2caSAndrew Geissler * 372d5afb2caSAndrew Geissler * @return None. 373d5afb2caSAndrew Geissler */ 3748d1b46d7Szhanghch05 inline void 375ac106bf6SEd Tanous setHypervisorIPv4Subnet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3768d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 377d5afb2caSAndrew Geissler { 37862598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor subnet : {} on Iface: {}", subnet, 37962598e31SEd Tanous ethIfaceId); 380d5afb2caSAndrew Geissler 381bd79bce8SPatrick Williams setDbusProperty( 382bd79bce8SPatrick Williams asyncResp, "IPv4StaticAddresses/1/SubnetMask", 383e93abac6SGinu George "xyz.openbmc_project.Settings", 384bd79bce8SPatrick Williams "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 385e93abac6SGinu George "xyz.openbmc_project.Network.IP", "PrefixLength", subnet); 386d5afb2caSAndrew Geissler } 387d5afb2caSAndrew Geissler 388d5afb2caSAndrew Geissler /** 389d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 390d5afb2caSAndrew Geissler * 391ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 392d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 393d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 394d5afb2caSAndrew Geissler * 395d5afb2caSAndrew Geissler * @return None. 396d5afb2caSAndrew Geissler */ 397ac106bf6SEd Tanous inline void setHypervisorIPv4Gateway( 398ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 399d5afb2caSAndrew Geissler const std::string& gateway) 400d5afb2caSAndrew Geissler { 40162598e31SEd Tanous BMCWEB_LOG_DEBUG( 40262598e31SEd Tanous "Setting the DefaultGateway to the last configured gateway"); 403d5afb2caSAndrew Geissler 404e93abac6SGinu George setDbusProperty(asyncResp, "IPv4StaticAddresses/1/Gateway", 405e93abac6SGinu George "xyz.openbmc_project.Settings", 406d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 407d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 408d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 409e93abac6SGinu George "DefaultGateway", gateway); 410d5afb2caSAndrew Geissler } 411d5afb2caSAndrew Geissler 412d5afb2caSAndrew Geissler /** 413d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 414d5afb2caSAndrew Geissler * 415d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 416d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 417d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 418d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 419d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 420d5afb2caSAndrew Geissler * 421d5afb2caSAndrew Geissler * @return None 422d5afb2caSAndrew Geissler */ 4238d1b46d7Szhanghch05 inline void 4248d1b46d7Szhanghch05 createHypervisorIPv4(const std::string& ifaceId, uint8_t prefixLength, 4258d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4268d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 427d5afb2caSAndrew Geissler { 428d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 429d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 430d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 431d5afb2caSAndrew Geissler } 432d5afb2caSAndrew Geissler 433d5afb2caSAndrew Geissler /** 434d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 435d5afb2caSAndrew Geissler * 436d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 437d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 438d5afb2caSAndrew Geissler * 439d5afb2caSAndrew Geissler * @return None 440d5afb2caSAndrew Geissler */ 4418d1b46d7Szhanghch05 inline void 4428d1b46d7Szhanghch05 deleteHypervisorIPv4(const std::string& ifaceId, 4438d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 444d5afb2caSAndrew Geissler { 445d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 446d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 447d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 448d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 449d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 450d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 451d5afb2caSAndrew Geissler } 452d5afb2caSAndrew Geissler 45377179532SEd Tanous inline void parseInterfaceData(nlohmann::json& jsonResponse, 45477179532SEd Tanous const std::string& ifaceId, 455d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 45677179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) 457d5afb2caSAndrew Geissler { 458d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 459ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 460ef4c65b7SEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", ifaceId); 461d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 46282695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 463d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 46482695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 465d5afb2caSAndrew Geissler 466d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 467d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 468d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 469d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 4709eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 471d5afb2caSAndrew Geissler { 472d5afb2caSAndrew Geissler if (ipv4Config.isActive) 473d5afb2caSAndrew Geissler { 4741476687dSEd Tanous nlohmann::json::object_t ipv4; 4751476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 4761476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 4771476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 4781476687dSEd Tanous ipv4["Gateway"] = ethData.defaultGateway; 479d5afb2caSAndrew Geissler 480d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 481d5afb2caSAndrew Geissler { 4821476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 483d5afb2caSAndrew Geissler } 484b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 485d5afb2caSAndrew Geissler } 486d5afb2caSAndrew Geissler } 487d5afb2caSAndrew Geissler } 488d5afb2caSAndrew Geissler 48977179532SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, bool ipv4DHCPEnabled, 4908d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 491d5afb2caSAndrew Geissler { 4927e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 493d82b5e1fSAsmitha Karunanithi 494e93abac6SGinu George setDbusProperty( 495e93abac6SGinu George asyncResp, "DHCPv4/DHCPEnabled", "xyz.openbmc_project.Settings", 496d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 497d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor") / 498d82b5e1fSAsmitha Karunanithi ifaceId, 499e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled", dhcp); 500d5afb2caSAndrew Geissler 501d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 502d5afb2caSAndrew Geissler // of the DHCPEnabled property 503d5afb2caSAndrew Geissler std::string origin; 504e05aec50SEd Tanous if (!ipv4DHCPEnabled) 505d5afb2caSAndrew Geissler { 506d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 507d5afb2caSAndrew Geissler } 508d5afb2caSAndrew Geissler else 509d5afb2caSAndrew Geissler { 510d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 511d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 512d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 513d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 514d5afb2caSAndrew Geissler } 515d82b5e1fSAsmitha Karunanithi 516bd79bce8SPatrick Williams setDbusProperty( 517bd79bce8SPatrick Williams asyncResp, "IPv4StaticAddresses/1/AddressOrigin", 518e93abac6SGinu George "xyz.openbmc_project.Settings", 519bd79bce8SPatrick Williams "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 520e93abac6SGinu George "xyz.openbmc_project.Network.IP", "Origin", origin); 521d5afb2caSAndrew Geissler } 522d5afb2caSAndrew Geissler 5237e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 52421fe928bSEd Tanous const std::string& ifaceId, 52521fe928bSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 5267e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 527d5afb2caSAndrew Geissler { 5287e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 5297e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 5307e860f15SJohn Edward Broadbent // address 53121fe928bSEd Tanous std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson = input[0]; 53221fe928bSEd Tanous nlohmann::json::object_t* obj = 53321fe928bSEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 53421fe928bSEd Tanous if (obj == nullptr) 5357e860f15SJohn Edward Broadbent { 53621fe928bSEd Tanous deleteHypervisorIPv4(ifaceId, asyncResp); 53721fe928bSEd Tanous return; 53821fe928bSEd Tanous } 53921fe928bSEd Tanous if (obj->empty()) 54021fe928bSEd Tanous { 54121fe928bSEd Tanous return; 54221fe928bSEd Tanous } 543f8fe53e7SEd Tanous // For the error string 544f8fe53e7SEd Tanous std::string pathString = "IPv4StaticAddresses/1"; 54521fe928bSEd Tanous std::string address; 54621fe928bSEd Tanous std::string subnetMask; 54721fe928bSEd Tanous std::string gateway; 548afc474aeSMyung Bae if (!json_util::readJsonObject( // 549afc474aeSMyung Bae *obj, asyncResp->res, // 550afc474aeSMyung Bae "Address", address, // 551afc474aeSMyung Bae "Gateway", gateway, // 552afc474aeSMyung Bae "SubnetMask", subnetMask // 553afc474aeSMyung Bae )) 5547e860f15SJohn Edward Broadbent { 5557e860f15SJohn Edward Broadbent return; 5567e860f15SJohn Edward Broadbent } 5577e860f15SJohn Edward Broadbent 5587e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 55921fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(address)) 5607e860f15SJohn Edward Broadbent { 56121fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, address, 5627e860f15SJohn Edward Broadbent pathString + "/Address"); 56321fe928bSEd Tanous return; 5647e860f15SJohn Edward Broadbent } 5657e860f15SJohn Edward Broadbent 56621fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(subnetMask, &prefixLength)) 5677e860f15SJohn Edward Broadbent { 56821fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, subnetMask, 5697e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 57021fe928bSEd Tanous return; 5717e860f15SJohn Edward Broadbent } 5727e860f15SJohn Edward Broadbent 57321fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(gateway)) 5747e860f15SJohn Edward Broadbent { 57521fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, gateway, 5767e860f15SJohn Edward Broadbent pathString + "/Gateway"); 5777e860f15SJohn Edward Broadbent return; 5787e860f15SJohn Edward Broadbent } 5797e860f15SJohn Edward Broadbent 58062598e31SEd Tanous BMCWEB_LOG_DEBUG("Calling createHypervisorIPv4 on : {},{}", ifaceId, 58121fe928bSEd Tanous address); 58221fe928bSEd Tanous createHypervisorIPv4(ifaceId, prefixLength, gateway, address, asyncResp); 5837e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 5847e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 5857e860f15SJohn Edward Broadbent } 5867e860f15SJohn Edward Broadbent 58788a8a174SEd Tanous inline void handleHypervisorHostnamePatch( 58888a8a174SEd Tanous const std::string& hostName, 5897e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 5907e860f15SJohn Edward Broadbent { 5917e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 5927e860f15SJohn Edward Broadbent { 5937e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 5947e860f15SJohn Edward Broadbent "HostName"); 5957e860f15SJohn Edward Broadbent return; 5967e860f15SJohn Edward Broadbent } 5977e860f15SJohn Edward Broadbent 5987e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 599e93abac6SGinu George setDbusProperty(asyncResp, "HostName", "xyz.openbmc_project.Settings", 600d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 601d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 602d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 603e93abac6SGinu George "HostName", hostName); 6047e860f15SJohn Edward Broadbent } 6057e860f15SJohn Edward Broadbent 6067e860f15SJohn Edward Broadbent inline void 60777179532SEd Tanous setIPv4InterfaceEnabled(const std::string& ifaceId, bool isActive, 6087e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6097e860f15SJohn Edward Broadbent { 610e93abac6SGinu George setDbusProperty( 611e93abac6SGinu George asyncResp, "InterfaceEnabled", "xyz.openbmc_project.Settings", 612e93abac6SGinu George "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 613e93abac6SGinu George "xyz.openbmc_project.Object.Enable", "Enabled", isActive); 6147e860f15SJohn Edward Broadbent } 6157e860f15SJohn Edward Broadbent 616f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceCollectionGet( 617f40448e5SGunnar Mills App& app, const crow::Request& req, 618f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 619f40448e5SGunnar Mills { 620f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 621f40448e5SGunnar Mills { 622f40448e5SGunnar Mills return; 623f40448e5SGunnar Mills } 624f40448e5SGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 625f40448e5SGunnar Mills "xyz.openbmc_project.Network.EthernetInterface"}; 626f40448e5SGunnar Mills 627f40448e5SGunnar Mills dbus::utility::getSubTreePaths( 628f40448e5SGunnar Mills "/xyz/openbmc_project/network/hypervisor", 0, interfaces, 629f40448e5SGunnar Mills [asyncResp]( 6308b24275dSEd Tanous const boost::system::error_code& ec, 631f40448e5SGunnar Mills const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) { 6328b24275dSEd Tanous if (ec) 633f40448e5SGunnar Mills { 634bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "System", 635bd79bce8SPatrick Williams "hypervisor"); 636f40448e5SGunnar Mills return; 637f40448e5SGunnar Mills } 638f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 639f40448e5SGunnar Mills "#EthernetInterfaceCollection." 640f40448e5SGunnar Mills "EthernetInterfaceCollection"; 641f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 642f40448e5SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 643f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet " 644f40448e5SGunnar Mills "Interface Collection"; 645f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 646f40448e5SGunnar Mills "Collection of Virtual Management " 647f40448e5SGunnar Mills "Interfaces for the hypervisor"; 648f40448e5SGunnar Mills 649f40448e5SGunnar Mills nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 650f40448e5SGunnar Mills ifaceArray = nlohmann::json::array(); 651f40448e5SGunnar Mills for (const std::string& iface : ifaceList) 652f40448e5SGunnar Mills { 653f40448e5SGunnar Mills sdbusplus::message::object_path path(iface); 654f40448e5SGunnar Mills std::string name = path.filename(); 655f40448e5SGunnar Mills if (name.empty()) 656f40448e5SGunnar Mills { 657f40448e5SGunnar Mills continue; 658f40448e5SGunnar Mills } 659f40448e5SGunnar Mills nlohmann::json::object_t ethIface; 660ef4c65b7SEd Tanous ethIface["@odata.id"] = boost::urls::format( 661bd79bce8SPatrick Williams "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", 662bd79bce8SPatrick Williams name); 663b2ba3072SPatrick Williams ifaceArray.emplace_back(std::move(ethIface)); 664f40448e5SGunnar Mills } 665f40448e5SGunnar Mills asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 666f40448e5SGunnar Mills }); 667f40448e5SGunnar Mills } 668f40448e5SGunnar Mills 669f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceGet( 670f40448e5SGunnar Mills App& app, const crow::Request& req, 671f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 672f40448e5SGunnar Mills { 673f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 674f40448e5SGunnar Mills { 675f40448e5SGunnar Mills return; 676f40448e5SGunnar Mills } 677f40448e5SGunnar Mills getHypervisorIfaceData( 678f40448e5SGunnar Mills id, [asyncResp, ifaceId{std::string(id)}]( 67977179532SEd Tanous bool success, const EthernetInterfaceData& ethData, 68077179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) { 681f40448e5SGunnar Mills if (!success) 682f40448e5SGunnar Mills { 683f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 684f40448e5SGunnar Mills ifaceId); 685f40448e5SGunnar Mills return; 686f40448e5SGunnar Mills } 687f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 68893bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 689f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface"; 690f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 691f40448e5SGunnar Mills "Hypervisor's Virtual Management Ethernet Interface"; 692f40448e5SGunnar Mills parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData, 693f40448e5SGunnar Mills ipv4Data); 694f40448e5SGunnar Mills }); 695f40448e5SGunnar Mills } 696f40448e5SGunnar Mills 6978d8c30c3SGunnar Mills inline void handleHypervisorSystemGet( 6988d8c30c3SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6998d8c30c3SGunnar Mills { 7008d8c30c3SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 7018d8c30c3SGunnar Mills "#ComputerSystem.v1_6_0.ComputerSystem"; 70268896206SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/hypervisor"; 7038d8c30c3SGunnar Mills asyncResp->res.jsonValue["Description"] = "Hypervisor"; 7048d8c30c3SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor"; 7058d8c30c3SGunnar Mills asyncResp->res.jsonValue["Id"] = "hypervisor"; 70668896206SGunnar Mills asyncResp->res.jsonValue["SystemType"] = computer_system::SystemType::OS; 7078d8c30c3SGunnar Mills nlohmann::json::array_t managedBy; 7088d8c30c3SGunnar Mills nlohmann::json::object_t manager; 70968896206SGunnar Mills manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}", 71068896206SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 711ad539545SPatrick Williams managedBy.emplace_back(std::move(manager)); 71268896206SGunnar Mills asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); 7138d8c30c3SGunnar Mills asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 7148d8c30c3SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 7158d8c30c3SGunnar Mills getHypervisorState(asyncResp); 7168d8c30c3SGunnar Mills getHypervisorActions(asyncResp); 7178d8c30c3SGunnar Mills // TODO: Add "SystemType" : "hypervisor" 7188d8c30c3SGunnar Mills } 7198d8c30c3SGunnar Mills 720f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfacePatch( 721f40448e5SGunnar Mills App& app, const crow::Request& req, 722f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 723f40448e5SGunnar Mills const std::string& ifaceId) 724f40448e5SGunnar Mills { 725f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 726f40448e5SGunnar Mills { 727f40448e5SGunnar Mills return; 728f40448e5SGunnar Mills } 729f40448e5SGunnar Mills std::optional<std::string> hostName; 73021fe928bSEd Tanous std::optional< 73121fe928bSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 73221fe928bSEd Tanous ipv4StaticAddresses; 73321fe928bSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> ipv4Addresses; 734f40448e5SGunnar Mills std::optional<bool> ipv4DHCPEnabled; 735f40448e5SGunnar Mills 736afc474aeSMyung Bae if (!json_util::readJsonPatch( // 737afc474aeSMyung Bae req, asyncResp->res, // 738afc474aeSMyung Bae "DHCPv4/DHCPEnabled", ipv4DHCPEnabled, // 739afc474aeSMyung Bae "IPv4Addresses", ipv4Addresses, // 740afc474aeSMyung Bae "IPv4StaticAddresses", ipv4StaticAddresses, // 741afc474aeSMyung Bae "HostName", hostName // 742afc474aeSMyung Bae )) 743f40448e5SGunnar Mills { 744f40448e5SGunnar Mills return; 745f40448e5SGunnar Mills } 746f40448e5SGunnar Mills 747f40448e5SGunnar Mills if (ipv4Addresses) 748f40448e5SGunnar Mills { 749f40448e5SGunnar Mills messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 750f40448e5SGunnar Mills return; 751f40448e5SGunnar Mills } 752f40448e5SGunnar Mills 753f40448e5SGunnar Mills getHypervisorIfaceData( 75421fe928bSEd Tanous ifaceId, 75521fe928bSEd Tanous [asyncResp, ifaceId, hostName = std::move(hostName), 7565a39f77aSPatrick Williams ipv4StaticAddresses = std::move(ipv4StaticAddresses), 75721fe928bSEd Tanous ipv4DHCPEnabled](bool success, const EthernetInterfaceData& ethData, 75821fe928bSEd Tanous const std::vector<IPv4AddressData>&) mutable { 759f40448e5SGunnar Mills if (!success) 760f40448e5SGunnar Mills { 761f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 762f40448e5SGunnar Mills ifaceId); 763f40448e5SGunnar Mills return; 764f40448e5SGunnar Mills } 765f40448e5SGunnar Mills 766f40448e5SGunnar Mills if (ipv4StaticAddresses) 767f40448e5SGunnar Mills { 768bd79bce8SPatrick Williams std::vector<std::variant<nlohmann::json::object_t, 769bd79bce8SPatrick Williams std::nullptr_t>>& ipv4Static = 770bd79bce8SPatrick Williams *ipv4StaticAddresses; 771f40448e5SGunnar Mills if (ipv4Static.begin() == ipv4Static.end()) 772f40448e5SGunnar Mills { 77321fe928bSEd Tanous messages::propertyValueTypeError(asyncResp->res, 77421fe928bSEd Tanous std::vector<std::string>(), 775f40448e5SGunnar Mills "IPv4StaticAddresses"); 776f40448e5SGunnar Mills return; 777f40448e5SGunnar Mills } 778f40448e5SGunnar Mills 779f40448e5SGunnar Mills // One and only one hypervisor instance supported 780f40448e5SGunnar Mills if (ipv4Static.size() != 1) 781f40448e5SGunnar Mills { 78221fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, "[]", 783f40448e5SGunnar Mills "IPv4StaticAddresses"); 784f40448e5SGunnar Mills return; 785f40448e5SGunnar Mills } 786f40448e5SGunnar Mills 787bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>& 788bd79bce8SPatrick Williams ipv4Json = ipv4Static[0]; 789f40448e5SGunnar Mills // Check if the param is 'null'. If its null, it means 790f40448e5SGunnar Mills // that user wants to delete the IP address. Deleting 791f40448e5SGunnar Mills // the IP address is allowed only if its statically 792f40448e5SGunnar Mills // configured. Deleting the address originated from DHCP 793f40448e5SGunnar Mills // is not allowed. 79421fe928bSEd Tanous if (std::holds_alternative<std::nullptr_t>(ipv4Json) && 79521fe928bSEd Tanous translateDhcpEnabledToBool(ethData.dhcpEnabled, true)) 796f40448e5SGunnar Mills { 797bd79bce8SPatrick Williams BMCWEB_LOG_INFO( 798bd79bce8SPatrick Williams "Ignoring the delete on ipv4StaticAddresses " 79962598e31SEd Tanous "as the interface is DHCP enabled"); 800f40448e5SGunnar Mills } 801f40448e5SGunnar Mills else 802f40448e5SGunnar Mills { 803bd79bce8SPatrick Williams handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, 804bd79bce8SPatrick Williams asyncResp); 805f40448e5SGunnar Mills } 806f40448e5SGunnar Mills } 807f40448e5SGunnar Mills 808f40448e5SGunnar Mills if (hostName) 809f40448e5SGunnar Mills { 810f40448e5SGunnar Mills handleHypervisorHostnamePatch(*hostName, asyncResp); 811f40448e5SGunnar Mills } 812f40448e5SGunnar Mills 81321fe928bSEd Tanous if (ipv4DHCPEnabled) 814f40448e5SGunnar Mills { 815f40448e5SGunnar Mills setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 816f40448e5SGunnar Mills } 817f40448e5SGunnar Mills 818f40448e5SGunnar Mills // Set this interface to disabled/inactive. This will be set 819f40448e5SGunnar Mills // to enabled/active by the pldm once the hypervisor 820f40448e5SGunnar Mills // consumes the updated settings from the user. 821f40448e5SGunnar Mills setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 822f40448e5SGunnar Mills }); 823f40448e5SGunnar Mills asyncResp->res.result(boost::beast::http::status::accepted); 824f40448e5SGunnar Mills } 825f40448e5SGunnar Mills 826a5d0cedbSGunnar Mills inline void handleHypervisorResetActionGet( 827a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 828a5d0cedbSGunnar Mills { 829a5d0cedbSGunnar Mills // Only return action info if hypervisor D-Bus object present 830a5d0cedbSGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 831a5d0cedbSGunnar Mills "xyz.openbmc_project.State.Host"}; 832a5d0cedbSGunnar Mills dbus::utility::getDbusObject( 833a5d0cedbSGunnar Mills "/xyz/openbmc_project/state/hypervisor0", interfaces, 834a5d0cedbSGunnar Mills [asyncResp]( 835a5d0cedbSGunnar Mills const boost::system::error_code& ec, 836a5d0cedbSGunnar Mills const std::vector<std::pair<std::string, std::vector<std::string>>>& 837a5d0cedbSGunnar Mills objInfo) { 838a5d0cedbSGunnar Mills if (ec) 839a5d0cedbSGunnar Mills { 84062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 841a5d0cedbSGunnar Mills 842a5d0cedbSGunnar Mills // No hypervisor objects found by mapper 843a5d0cedbSGunnar Mills if (ec.value() == boost::system::errc::io_error) 844a5d0cedbSGunnar Mills { 845a5d0cedbSGunnar Mills messages::resourceNotFound(asyncResp->res, "hypervisor", 846a5d0cedbSGunnar Mills "ResetActionInfo"); 847a5d0cedbSGunnar Mills return; 848a5d0cedbSGunnar Mills } 849a5d0cedbSGunnar Mills 850a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 851a5d0cedbSGunnar Mills return; 852a5d0cedbSGunnar Mills } 853a5d0cedbSGunnar Mills 854a5d0cedbSGunnar Mills // One and only one hypervisor instance supported 855a5d0cedbSGunnar Mills if (objInfo.size() != 1) 856a5d0cedbSGunnar Mills { 857a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 858a5d0cedbSGunnar Mills return; 859a5d0cedbSGunnar Mills } 860a5d0cedbSGunnar Mills 861a5d0cedbSGunnar Mills // The hypervisor object only support the ability to 862a5d0cedbSGunnar Mills // turn On The system object Action should be utilized 863a5d0cedbSGunnar Mills // for other operations 864a5d0cedbSGunnar Mills 865a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 866a5d0cedbSGunnar Mills "#ActionInfo.v1_1_2.ActionInfo"; 867a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 868a5d0cedbSGunnar Mills "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 869a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 870a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 871a5d0cedbSGunnar Mills nlohmann::json::array_t parameters; 872a5d0cedbSGunnar Mills nlohmann::json::object_t parameter; 873a5d0cedbSGunnar Mills parameter["Name"] = "ResetType"; 874a5d0cedbSGunnar Mills parameter["Required"] = true; 875539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 876a5d0cedbSGunnar Mills nlohmann::json::array_t allowed; 877ad539545SPatrick Williams allowed.emplace_back("On"); 878a5d0cedbSGunnar Mills parameter["AllowableValues"] = std::move(allowed); 879ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 880a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 881a5d0cedbSGunnar Mills }); 882a5d0cedbSGunnar Mills } 883a5d0cedbSGunnar Mills 884a5d0cedbSGunnar Mills inline void handleHypervisorSystemResetPost( 885dd7090e6SGunnar Mills const crow::Request& req, 886a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 887a5d0cedbSGunnar Mills { 888a5d0cedbSGunnar Mills std::optional<std::string> resetType; 889a5d0cedbSGunnar Mills if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 890a5d0cedbSGunnar Mills { 891a5d0cedbSGunnar Mills // readJson adds appropriate error to response 892a5d0cedbSGunnar Mills return; 893a5d0cedbSGunnar Mills } 894a5d0cedbSGunnar Mills 895a5d0cedbSGunnar Mills if (!resetType) 896a5d0cedbSGunnar Mills { 897a5d0cedbSGunnar Mills messages::actionParameterMissing(asyncResp->res, "ComputerSystem.Reset", 898a5d0cedbSGunnar Mills "ResetType"); 899a5d0cedbSGunnar Mills return; 900a5d0cedbSGunnar Mills } 901a5d0cedbSGunnar Mills 902a5d0cedbSGunnar Mills // Hypervisor object only support On operation 903a5d0cedbSGunnar Mills if (resetType != "On") 904a5d0cedbSGunnar Mills { 905a5d0cedbSGunnar Mills messages::propertyValueNotInList(asyncResp->res, *resetType, 906a5d0cedbSGunnar Mills "ResetType"); 907a5d0cedbSGunnar Mills return; 908a5d0cedbSGunnar Mills } 909a5d0cedbSGunnar Mills 910a5d0cedbSGunnar Mills std::string command = "xyz.openbmc_project.State.Host.Transition.On"; 911a5d0cedbSGunnar Mills 912bd79bce8SPatrick Williams setDbusPropertyAction( 913bd79bce8SPatrick Williams asyncResp, "xyz.openbmc_project.State.Hypervisor", 9141827b4f1SAsmitha Karunanithi sdbusplus::message::object_path( 9151827b4f1SAsmitha Karunanithi "/xyz/openbmc_project/state/hypervisor0"), 916bd79bce8SPatrick Williams "xyz.openbmc_project.State.Host", "RequestedHostTransition", 917bd79bce8SPatrick Williams "ResetType", "ComputerSystem.Reset", command); 918a5d0cedbSGunnar Mills } 919a5d0cedbSGunnar Mills 9207e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 9217e860f15SJohn Edward Broadbent { 9227e860f15SJohn Edward Broadbent /** 9237e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 9247e860f15SJohn Edward Broadbent * Hypervisor Interface 9257e860f15SJohn Edward Broadbent */ 9267e860f15SJohn Edward Broadbent 9277e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 928ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 929f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 930f40448e5SGunnar Mills handleHypervisorEthernetInterfaceCollectionGet, std::ref(app))); 9317e860f15SJohn Edward Broadbent 9327e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9337e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 934ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 935f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 936f40448e5SGunnar Mills handleHypervisorEthernetInterfaceGet, std::ref(app))); 937d5afb2caSAndrew Geissler 9387e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9397e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 940ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 941f40448e5SGunnar Mills .methods(boost::beast::http::verb::patch)(std::bind_front( 942f40448e5SGunnar Mills handleHypervisorEthernetInterfacePatch, std::ref(app))); 9434fbaf64aSAndrew Geissler } 94488a8a174SEd Tanous } // namespace redfish 945