140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3d5afb2caSAndrew Geissler #pragma once 4d5afb2caSAndrew Geissler 5d7857201SEd Tanous #include "bmcweb_config.h" 6d7857201SEd Tanous 73ccb3adbSEd Tanous #include "app.hpp" 8d7857201SEd Tanous #include "async_resp.hpp" 97a1dbc48SGeorge Liu #include "dbus_utility.hpp" 103ccb3adbSEd Tanous #include "error_messages.hpp" 113ccb3adbSEd Tanous #include "ethernet.hpp" 12539d8c6bSEd Tanous #include "generated/enums/action_info.hpp" 13539d8c6bSEd Tanous #include "generated/enums/computer_system.hpp" 14539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 15d7857201SEd Tanous #include "http_request.hpp" 16d7857201SEd Tanous #include "logging.hpp" 173ccb3adbSEd Tanous #include "query.hpp" 183ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 19d7857201SEd Tanous #include "utils/dbus_utils.hpp" 20033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 213ccb3adbSEd Tanous #include "utils/json_utils.hpp" 22033f1e4dSEd Tanous 23d7857201SEd Tanous #include <boost/beast/http/status.hpp> 24d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 25ef4c65b7SEd Tanous #include <boost/url/format.hpp> 26d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 27d5afb2caSAndrew Geissler 287a1dbc48SGeorge Liu #include <array> 29d7857201SEd Tanous #include <cstddef> 30d7857201SEd Tanous #include <cstdint> 31d7857201SEd Tanous #include <functional> 32d7857201SEd Tanous #include <memory> 33d5afb2caSAndrew Geissler #include <optional> 34d7857201SEd Tanous #include <string> 357a1dbc48SGeorge Liu #include <string_view> 36d5afb2caSAndrew Geissler #include <utility> 37d7857201SEd Tanous #include <variant> 38d7857201SEd Tanous #include <vector> 39d5afb2caSAndrew Geissler 4088a8a174SEd Tanous namespace redfish 41d5afb2caSAndrew Geissler { 42d5afb2caSAndrew Geissler 43d5afb2caSAndrew Geissler /** 44cc0bb6f2SAndrew Geissler * @brief Retrieves hypervisor state properties over dbus 45cc0bb6f2SAndrew Geissler * 46cc0bb6f2SAndrew Geissler * The hypervisor state object is optional so this function will only set the 47cc0bb6f2SAndrew Geissler * state variables if the object is found 48cc0bb6f2SAndrew Geissler * 49ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 50cc0bb6f2SAndrew Geissler * 51cc0bb6f2SAndrew Geissler * @return None. 52cc0bb6f2SAndrew Geissler */ 53*504af5a0SPatrick Williams inline void getHypervisorState( 54*504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 55cc0bb6f2SAndrew Geissler { 5662598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor state information."); 57deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 58deae6a78SEd Tanous "xyz.openbmc_project.State.Hypervisor", 591e1e598dSJonathan Doman "/xyz/openbmc_project/state/hypervisor0", 601e1e598dSJonathan Doman "xyz.openbmc_project.State.Host", "CurrentHostState", 61ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 621e1e598dSJonathan Doman const std::string& hostState) { 63cc0bb6f2SAndrew Geissler if (ec) 64cc0bb6f2SAndrew Geissler { 6562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 66cc0bb6f2SAndrew Geissler // This is an optional D-Bus object so just return if 67cc0bb6f2SAndrew Geissler // error occurs 68cc0bb6f2SAndrew Geissler return; 69cc0bb6f2SAndrew Geissler } 70cc0bb6f2SAndrew Geissler 7162598e31SEd Tanous BMCWEB_LOG_DEBUG("Hypervisor state: {}", hostState); 72cc0bb6f2SAndrew Geissler // Verify Host State 731e1e598dSJonathan Doman if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") 74cc0bb6f2SAndrew Geissler { 75bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 76bd79bce8SPatrick Williams resource::PowerState::On; 77539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 78539d8c6bSEd Tanous resource::State::Enabled; 79cc0bb6f2SAndrew Geissler } 801e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 811e1e598dSJonathan Doman "Quiesced") 82cc0bb6f2SAndrew Geissler { 83bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 84bd79bce8SPatrick Williams resource::PowerState::On; 85539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 86539d8c6bSEd Tanous resource::State::Quiesced; 87cc0bb6f2SAndrew Geissler } 881e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 891e1e598dSJonathan Doman "Standby") 90cc0bb6f2SAndrew Geissler { 91bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 92bd79bce8SPatrick Williams resource::PowerState::On; 93539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 94539d8c6bSEd Tanous resource::State::StandbyOffline; 95cc0bb6f2SAndrew Geissler } 961e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 971e1e598dSJonathan Doman "TransitioningToRunning") 98cc0bb6f2SAndrew Geissler { 99539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = 100539d8c6bSEd Tanous resource::PowerState::PoweringOn; 101539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 102539d8c6bSEd Tanous resource::State::Starting; 103cc0bb6f2SAndrew Geissler } 1041e1e598dSJonathan Doman else if (hostState == "xyz.openbmc_project.State.Host.HostState." 1051e1e598dSJonathan Doman "TransitioningToOff") 106cc0bb6f2SAndrew Geissler { 107539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = 108539d8c6bSEd Tanous resource::PowerState::PoweringOff; 109539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 110539d8c6bSEd Tanous resource::State::Enabled; 111cc0bb6f2SAndrew Geissler } 112bd79bce8SPatrick Williams else if (hostState == 113bd79bce8SPatrick Williams "xyz.openbmc_project.State.Host.HostState.Off") 114cc0bb6f2SAndrew Geissler { 115bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 116bd79bce8SPatrick Williams resource::PowerState::Off; 117539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 118539d8c6bSEd Tanous resource::State::Disabled; 119cc0bb6f2SAndrew Geissler } 120cc0bb6f2SAndrew Geissler else 121cc0bb6f2SAndrew Geissler { 122ac106bf6SEd Tanous messages::internalError(asyncResp->res); 123cc0bb6f2SAndrew Geissler return; 124cc0bb6f2SAndrew Geissler } 1251e1e598dSJonathan Doman }); 126cc0bb6f2SAndrew Geissler } 127cc0bb6f2SAndrew Geissler 128cc0bb6f2SAndrew Geissler /** 1294fbaf64aSAndrew Geissler * @brief Populate Actions if any are valid for hypervisor object 1304fbaf64aSAndrew Geissler * 1314fbaf64aSAndrew Geissler * The hypervisor state object is optional so this function will only set the 1324fbaf64aSAndrew Geissler * Action if the object is found 1334fbaf64aSAndrew Geissler * 134ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls. 1354fbaf64aSAndrew Geissler * 1364fbaf64aSAndrew Geissler * @return None. 1374fbaf64aSAndrew Geissler */ 138*504af5a0SPatrick Williams inline void getHypervisorActions( 139*504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1404fbaf64aSAndrew Geissler { 14162598e31SEd Tanous BMCWEB_LOG_DEBUG("Get hypervisor actions."); 1422b73119cSGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1432b73119cSGeorge Liu "xyz.openbmc_project.State.Host"}; 1442b73119cSGeorge Liu dbus::utility::getDbusObject( 1452b73119cSGeorge Liu "/xyz/openbmc_project/state/hypervisor0", interfaces, 146ac106bf6SEd Tanous [asyncResp]( 1472b73119cSGeorge Liu const boost::system::error_code& ec, 1484fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1494fbaf64aSAndrew Geissler objInfo) { 1504fbaf64aSAndrew Geissler if (ec) 1514fbaf64aSAndrew Geissler { 15262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 1534fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1544fbaf64aSAndrew Geissler // error occurs 1554fbaf64aSAndrew Geissler return; 1564fbaf64aSAndrew Geissler } 1574fbaf64aSAndrew Geissler 15826f6976fSEd Tanous if (objInfo.empty()) 1594fbaf64aSAndrew Geissler { 1604fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1614fbaf64aSAndrew Geissler // if there is no instance found 1624fbaf64aSAndrew Geissler return; 1634fbaf64aSAndrew Geissler } 1644fbaf64aSAndrew Geissler 1654fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1664fbaf64aSAndrew Geissler { 1674fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1684fbaf64aSAndrew Geissler // error 169ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1704fbaf64aSAndrew Geissler return; 1714fbaf64aSAndrew Geissler } 1724fbaf64aSAndrew Geissler 1734fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 174613dabeaSEd Tanous nlohmann::json& reset = 175ac106bf6SEd Tanous asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]; 176613dabeaSEd Tanous reset["target"] = 177613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"; 178613dabeaSEd Tanous reset["@Redfish.ActionInfo"] = 179613dabeaSEd Tanous "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 1802b73119cSGeorge Liu }); 1814fbaf64aSAndrew Geissler } 1824fbaf64aSAndrew Geissler 183d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 184711ac7a9SEd Tanous const std::string& ethIfaceId, 185711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 18677179532SEd Tanous EthernetInterfaceData& ethData, std::vector<IPv4AddressData>& ipv4Config) 187d5afb2caSAndrew Geissler { 188d5afb2caSAndrew Geissler bool idFound = false; 189d5afb2caSAndrew Geissler for (const auto& objpath : dbusData) 190d5afb2caSAndrew Geissler { 191d5afb2caSAndrew Geissler for (const auto& ifacePair : objpath.second) 192d5afb2caSAndrew Geissler { 193d5afb2caSAndrew Geissler if (objpath.first == 194d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId) 195d5afb2caSAndrew Geissler { 196d5afb2caSAndrew Geissler idFound = true; 1974652c640SAsmitha Karunanithi if (ifacePair.first == 198d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface") 199d5afb2caSAndrew Geissler { 200d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 201d5afb2caSAndrew Geissler { 202d5afb2caSAndrew Geissler if (propertyPair.first == "DHCPEnabled") 203d5afb2caSAndrew Geissler { 204d5afb2caSAndrew Geissler const std::string* dhcp = 205d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 206d5afb2caSAndrew Geissler if (dhcp != nullptr) 207d5afb2caSAndrew Geissler { 20882695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcp; 209d5afb2caSAndrew Geissler break; // Interested on only "DHCPEnabled". 210d5afb2caSAndrew Geissler // Stop parsing since we got the 211d5afb2caSAndrew Geissler // "DHCPEnabled" value. 212d5afb2caSAndrew Geissler } 213d5afb2caSAndrew Geissler } 214d5afb2caSAndrew Geissler } 215d5afb2caSAndrew Geissler } 216d5afb2caSAndrew Geissler } 217d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor/" + 218d5afb2caSAndrew Geissler ethIfaceId + "/ipv4/addr0") 219d5afb2caSAndrew Geissler { 22077179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 221d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Object.Enable") 222d5afb2caSAndrew Geissler { 2239eb808c1SEd Tanous for (const auto& property : ifacePair.second) 224d5afb2caSAndrew Geissler { 225d5afb2caSAndrew Geissler if (property.first == "Enabled") 226d5afb2caSAndrew Geissler { 227d5afb2caSAndrew Geissler const bool* intfEnable = 228d5afb2caSAndrew Geissler std::get_if<bool>(&property.second); 229d5afb2caSAndrew Geissler if (intfEnable != nullptr) 230d5afb2caSAndrew Geissler { 231d5afb2caSAndrew Geissler ipv4Address.isActive = *intfEnable; 232d5afb2caSAndrew Geissler break; 233d5afb2caSAndrew Geissler } 234d5afb2caSAndrew Geissler } 235d5afb2caSAndrew Geissler } 236d5afb2caSAndrew Geissler } 237d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.IP") 238d5afb2caSAndrew Geissler { 2399eb808c1SEd Tanous for (const auto& property : ifacePair.second) 240d5afb2caSAndrew Geissler { 241d5afb2caSAndrew Geissler if (property.first == "Address") 242d5afb2caSAndrew Geissler { 243d5afb2caSAndrew Geissler const std::string* address = 244d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 245d5afb2caSAndrew Geissler if (address != nullptr) 246d5afb2caSAndrew Geissler { 247d5afb2caSAndrew Geissler ipv4Address.address = *address; 248d5afb2caSAndrew Geissler } 249d5afb2caSAndrew Geissler } 250d5afb2caSAndrew Geissler else if (property.first == "Origin") 251d5afb2caSAndrew Geissler { 252d5afb2caSAndrew Geissler const std::string* origin = 253d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 254d5afb2caSAndrew Geissler if (origin != nullptr) 255d5afb2caSAndrew Geissler { 256d5afb2caSAndrew Geissler ipv4Address.origin = 257d5afb2caSAndrew Geissler translateAddressOriginDbusToRedfish(*origin, 258d5afb2caSAndrew Geissler true); 259d5afb2caSAndrew Geissler } 260d5afb2caSAndrew Geissler } 261d5afb2caSAndrew Geissler else if (property.first == "PrefixLength") 262d5afb2caSAndrew Geissler { 263d5afb2caSAndrew Geissler const uint8_t* mask = 264d5afb2caSAndrew Geissler std::get_if<uint8_t>(&property.second); 265d5afb2caSAndrew Geissler if (mask != nullptr) 266d5afb2caSAndrew Geissler { 267d5afb2caSAndrew Geissler // convert it to the string 268d5afb2caSAndrew Geissler ipv4Address.netmask = getNetmask(*mask); 269d5afb2caSAndrew Geissler } 270d5afb2caSAndrew Geissler } 271889ff694SAsmitha Karunanithi else if (property.first == "Type" || 272889ff694SAsmitha Karunanithi property.first == "Gateway") 273889ff694SAsmitha Karunanithi { 274889ff694SAsmitha Karunanithi // Type & Gateway is not used 275889ff694SAsmitha Karunanithi continue; 276889ff694SAsmitha Karunanithi } 277d5afb2caSAndrew Geissler else 278d5afb2caSAndrew Geissler { 27962598e31SEd Tanous BMCWEB_LOG_ERROR( 28062598e31SEd Tanous "Got extra property: {} on the {} object", 28162598e31SEd Tanous property.first, objpath.first.str); 282d5afb2caSAndrew Geissler } 283d5afb2caSAndrew Geissler } 284d5afb2caSAndrew Geissler } 285d5afb2caSAndrew Geissler } 286d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 287d5afb2caSAndrew Geissler { 288d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 289d5afb2caSAndrew Geissler // need to check eth number 290d5afb2caSAndrew Geissler if (ifacePair.first == 291d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 292d5afb2caSAndrew Geissler { 293d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 294d5afb2caSAndrew Geissler { 295d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 296d5afb2caSAndrew Geissler { 297d5afb2caSAndrew Geissler const std::string* hostName = 298d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 299d5afb2caSAndrew Geissler if (hostName != nullptr) 300d5afb2caSAndrew Geissler { 30182695a5bSJiaqing Zhao ethData.hostName = *hostName; 302d5afb2caSAndrew Geissler } 303d5afb2caSAndrew Geissler } 304d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 305d5afb2caSAndrew Geissler { 306d5afb2caSAndrew Geissler const std::string* defaultGateway = 307d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 308d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 309d5afb2caSAndrew Geissler { 31082695a5bSJiaqing Zhao ethData.defaultGateway = *defaultGateway; 311d5afb2caSAndrew Geissler } 312d5afb2caSAndrew Geissler } 313d5afb2caSAndrew Geissler } 314d5afb2caSAndrew Geissler } 315d5afb2caSAndrew Geissler } 316d5afb2caSAndrew Geissler } 317d5afb2caSAndrew Geissler } 318d5afb2caSAndrew Geissler return idFound; 319d5afb2caSAndrew Geissler } 320d5afb2caSAndrew Geissler /** 321d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 322d5afb2caSAndrew Geissler * Interface Object from Settings Manager 323d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 324d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 325d5afb2caSAndrew Geissler * into JSON 326d5afb2caSAndrew Geissler */ 327d5afb2caSAndrew Geissler template <typename CallbackFunc> 328d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 329d5afb2caSAndrew Geissler CallbackFunc&& callback) 330d5afb2caSAndrew Geissler { 3315eb468daSGeorge Liu sdbusplus::message::object_path path("/"); 3325eb468daSGeorge Liu dbus::utility::getManagedObjects( 3335eb468daSGeorge Liu "xyz.openbmc_project.Settings", path, 334f94c4ecfSEd Tanous [ethIfaceId{std::string{ethIfaceId}}, 3358cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 3368b24275dSEd Tanous const boost::system::error_code& ec, 33721fe928bSEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 338d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 33977179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 3408b24275dSEd Tanous if (ec) 341d5afb2caSAndrew Geissler { 342d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 343d5afb2caSAndrew Geissler return; 344d5afb2caSAndrew Geissler } 345d5afb2caSAndrew Geissler 346bd79bce8SPatrick Williams bool found = extractHypervisorInterfaceData(ethIfaceId, resp, 347bd79bce8SPatrick Williams ethData, ipv4Data); 348d5afb2caSAndrew Geissler if (!found) 349d5afb2caSAndrew Geissler { 35062598e31SEd Tanous BMCWEB_LOG_INFO("Hypervisor Interface not found"); 351d5afb2caSAndrew Geissler } 352d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 3535eb468daSGeorge Liu }); 354d5afb2caSAndrew Geissler } 355d5afb2caSAndrew Geissler 356d5afb2caSAndrew Geissler /** 357d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 358d5afb2caSAndrew Geissler * 359ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 360d5afb2caSAndrew Geissler * @param[in] ipv4Address Address from the incoming request 361d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 362d5afb2caSAndrew Geissler * 363d5afb2caSAndrew Geissler * @return None. 364d5afb2caSAndrew Geissler */ 365ac106bf6SEd Tanous inline void setHypervisorIPv4Address( 366ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 367ac106bf6SEd Tanous const std::string& ethIfaceId, const std::string& ipv4Address) 368d5afb2caSAndrew Geissler { 36962598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor IPaddress : {} on Iface: {}", 37062598e31SEd Tanous ipv4Address, ethIfaceId); 371d82b5e1fSAsmitha Karunanithi 372bd79bce8SPatrick Williams setDbusProperty( 373bd79bce8SPatrick Williams asyncResp, "IPv4StaticAddresses/1/Address", 374e93abac6SGinu George "xyz.openbmc_project.Settings", 375bd79bce8SPatrick Williams "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 376e93abac6SGinu George "xyz.openbmc_project.Network.IP", "Address", ipv4Address); 377d5afb2caSAndrew Geissler } 378d5afb2caSAndrew Geissler 379d5afb2caSAndrew Geissler /** 380d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 381d5afb2caSAndrew Geissler * 382ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 383d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 384d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 385d5afb2caSAndrew Geissler * 386d5afb2caSAndrew Geissler * @return None. 387d5afb2caSAndrew Geissler */ 388*504af5a0SPatrick Williams inline void setHypervisorIPv4Subnet( 389*504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3908d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 391d5afb2caSAndrew Geissler { 39262598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting the Hypervisor subnet : {} on Iface: {}", subnet, 39362598e31SEd Tanous ethIfaceId); 394d5afb2caSAndrew Geissler 395bd79bce8SPatrick Williams setDbusProperty( 396bd79bce8SPatrick Williams asyncResp, "IPv4StaticAddresses/1/SubnetMask", 397e93abac6SGinu George "xyz.openbmc_project.Settings", 398bd79bce8SPatrick Williams "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 399e93abac6SGinu George "xyz.openbmc_project.Network.IP", "PrefixLength", subnet); 400d5afb2caSAndrew Geissler } 401d5afb2caSAndrew Geissler 402d5afb2caSAndrew Geissler /** 403d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 404d5afb2caSAndrew Geissler * 405ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for generating response message. 406d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 407d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 408d5afb2caSAndrew Geissler * 409d5afb2caSAndrew Geissler * @return None. 410d5afb2caSAndrew Geissler */ 411ac106bf6SEd Tanous inline void setHypervisorIPv4Gateway( 412ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 413d5afb2caSAndrew Geissler const std::string& gateway) 414d5afb2caSAndrew Geissler { 41562598e31SEd Tanous BMCWEB_LOG_DEBUG( 41662598e31SEd Tanous "Setting the DefaultGateway to the last configured gateway"); 417d5afb2caSAndrew Geissler 418e93abac6SGinu George setDbusProperty(asyncResp, "IPv4StaticAddresses/1/Gateway", 419e93abac6SGinu George "xyz.openbmc_project.Settings", 420d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 421d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 422d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 423e93abac6SGinu George "DefaultGateway", gateway); 424d5afb2caSAndrew Geissler } 425d5afb2caSAndrew Geissler 426d5afb2caSAndrew Geissler /** 427d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 428d5afb2caSAndrew Geissler * 429d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 430d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 431d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 432d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 433d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 434d5afb2caSAndrew Geissler * 435d5afb2caSAndrew Geissler * @return None 436d5afb2caSAndrew Geissler */ 437*504af5a0SPatrick Williams inline void createHypervisorIPv4( 438*504af5a0SPatrick Williams const std::string& ifaceId, uint8_t prefixLength, 4398d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4408d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 441d5afb2caSAndrew Geissler { 442d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 443d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 444d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 445d5afb2caSAndrew Geissler } 446d5afb2caSAndrew Geissler 447d5afb2caSAndrew Geissler /** 448d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 449d5afb2caSAndrew Geissler * 450d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 451d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 452d5afb2caSAndrew Geissler * 453d5afb2caSAndrew Geissler * @return None 454d5afb2caSAndrew Geissler */ 455*504af5a0SPatrick Williams inline void deleteHypervisorIPv4( 456*504af5a0SPatrick Williams const std::string& ifaceId, 4578d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 458d5afb2caSAndrew Geissler { 459d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 460d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 461d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 462d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 463d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 464d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 465d5afb2caSAndrew Geissler } 466d5afb2caSAndrew Geissler 46777179532SEd Tanous inline void parseInterfaceData(nlohmann::json& jsonResponse, 46877179532SEd Tanous const std::string& ifaceId, 469d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 47077179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) 471d5afb2caSAndrew Geissler { 472d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 473ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 474ef4c65b7SEd Tanous "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", ifaceId); 475d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 47682695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 477d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 47882695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 479d5afb2caSAndrew Geissler 480d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 481d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 482d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 483d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 4849eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 485d5afb2caSAndrew Geissler { 486d5afb2caSAndrew Geissler if (ipv4Config.isActive) 487d5afb2caSAndrew Geissler { 4881476687dSEd Tanous nlohmann::json::object_t ipv4; 4891476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 4901476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 4911476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 4921476687dSEd Tanous ipv4["Gateway"] = ethData.defaultGateway; 493d5afb2caSAndrew Geissler 494d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 495d5afb2caSAndrew Geissler { 4961476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 497d5afb2caSAndrew Geissler } 498b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 499d5afb2caSAndrew Geissler } 500d5afb2caSAndrew Geissler } 501d5afb2caSAndrew Geissler } 502d5afb2caSAndrew Geissler 50377179532SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, bool ipv4DHCPEnabled, 5048d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 505d5afb2caSAndrew Geissler { 5067e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 507d82b5e1fSAsmitha Karunanithi 508e93abac6SGinu George setDbusProperty( 509e93abac6SGinu George asyncResp, "DHCPv4/DHCPEnabled", "xyz.openbmc_project.Settings", 510d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 511d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor") / 512d82b5e1fSAsmitha Karunanithi ifaceId, 513e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled", dhcp); 514d5afb2caSAndrew Geissler 515d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 516d5afb2caSAndrew Geissler // of the DHCPEnabled property 517d5afb2caSAndrew Geissler std::string origin; 518e05aec50SEd Tanous if (!ipv4DHCPEnabled) 519d5afb2caSAndrew Geissler { 520d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 521d5afb2caSAndrew Geissler } 522d5afb2caSAndrew Geissler else 523d5afb2caSAndrew Geissler { 524d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 525d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 526d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 527d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 528d5afb2caSAndrew Geissler } 529d82b5e1fSAsmitha Karunanithi 530bd79bce8SPatrick Williams setDbusProperty( 531bd79bce8SPatrick Williams asyncResp, "IPv4StaticAddresses/1/AddressOrigin", 532e93abac6SGinu George "xyz.openbmc_project.Settings", 533bd79bce8SPatrick Williams "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 534e93abac6SGinu George "xyz.openbmc_project.Network.IP", "Origin", origin); 535d5afb2caSAndrew Geissler } 536d5afb2caSAndrew Geissler 5377e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 53821fe928bSEd Tanous const std::string& ifaceId, 53921fe928bSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 5407e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 541d5afb2caSAndrew Geissler { 5427e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 5437e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 5447e860f15SJohn Edward Broadbent // address 54521fe928bSEd Tanous std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson = input[0]; 54621fe928bSEd Tanous nlohmann::json::object_t* obj = 54721fe928bSEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 54821fe928bSEd Tanous if (obj == nullptr) 5497e860f15SJohn Edward Broadbent { 55021fe928bSEd Tanous deleteHypervisorIPv4(ifaceId, asyncResp); 55121fe928bSEd Tanous return; 55221fe928bSEd Tanous } 55321fe928bSEd Tanous if (obj->empty()) 55421fe928bSEd Tanous { 55521fe928bSEd Tanous return; 55621fe928bSEd Tanous } 557f8fe53e7SEd Tanous // For the error string 558f8fe53e7SEd Tanous std::string pathString = "IPv4StaticAddresses/1"; 55921fe928bSEd Tanous std::string address; 56021fe928bSEd Tanous std::string subnetMask; 56121fe928bSEd Tanous std::string gateway; 562afc474aeSMyung Bae if (!json_util::readJsonObject( // 563afc474aeSMyung Bae *obj, asyncResp->res, // 564afc474aeSMyung Bae "Address", address, // 565afc474aeSMyung Bae "Gateway", gateway, // 566afc474aeSMyung Bae "SubnetMask", subnetMask // 567afc474aeSMyung Bae )) 5687e860f15SJohn Edward Broadbent { 5697e860f15SJohn Edward Broadbent return; 5707e860f15SJohn Edward Broadbent } 5717e860f15SJohn Edward Broadbent 5727e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 57321fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(address)) 5747e860f15SJohn Edward Broadbent { 57521fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, address, 5767e860f15SJohn Edward Broadbent pathString + "/Address"); 57721fe928bSEd Tanous return; 5787e860f15SJohn Edward Broadbent } 5797e860f15SJohn Edward Broadbent 58021fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(subnetMask, &prefixLength)) 5817e860f15SJohn Edward Broadbent { 58221fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, subnetMask, 5837e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 58421fe928bSEd Tanous return; 5857e860f15SJohn Edward Broadbent } 5867e860f15SJohn Edward Broadbent 58721fe928bSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(gateway)) 5887e860f15SJohn Edward Broadbent { 58921fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, gateway, 5907e860f15SJohn Edward Broadbent pathString + "/Gateway"); 5917e860f15SJohn Edward Broadbent return; 5927e860f15SJohn Edward Broadbent } 5937e860f15SJohn Edward Broadbent 59462598e31SEd Tanous BMCWEB_LOG_DEBUG("Calling createHypervisorIPv4 on : {},{}", ifaceId, 59521fe928bSEd Tanous address); 59621fe928bSEd Tanous createHypervisorIPv4(ifaceId, prefixLength, gateway, address, asyncResp); 5977e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 5987e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 5997e860f15SJohn Edward Broadbent } 6007e860f15SJohn Edward Broadbent 60188a8a174SEd Tanous inline void handleHypervisorHostnamePatch( 60288a8a174SEd Tanous const std::string& hostName, 6037e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6047e860f15SJohn Edward Broadbent { 6057e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 6067e860f15SJohn Edward Broadbent { 6077e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 6087e860f15SJohn Edward Broadbent "HostName"); 6097e860f15SJohn Edward Broadbent return; 6107e860f15SJohn Edward Broadbent } 6117e860f15SJohn Edward Broadbent 6127e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 613e93abac6SGinu George setDbusProperty(asyncResp, "HostName", "xyz.openbmc_project.Settings", 614d82b5e1fSAsmitha Karunanithi sdbusplus::message::object_path( 615d82b5e1fSAsmitha Karunanithi "/xyz/openbmc_project/network/hypervisor"), 616d82b5e1fSAsmitha Karunanithi "xyz.openbmc_project.Network.SystemConfiguration", 617e93abac6SGinu George "HostName", hostName); 6187e860f15SJohn Edward Broadbent } 6197e860f15SJohn Edward Broadbent 620*504af5a0SPatrick Williams inline void setIPv4InterfaceEnabled( 621*504af5a0SPatrick Williams const std::string& ifaceId, bool isActive, 6227e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6237e860f15SJohn Edward Broadbent { 624e93abac6SGinu George setDbusProperty( 625e93abac6SGinu George asyncResp, "InterfaceEnabled", "xyz.openbmc_project.Settings", 626e93abac6SGinu George "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 627e93abac6SGinu George "xyz.openbmc_project.Object.Enable", "Enabled", isActive); 6287e860f15SJohn Edward Broadbent } 6297e860f15SJohn Edward Broadbent 630f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceCollectionGet( 631f40448e5SGunnar Mills App& app, const crow::Request& req, 632f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 633f40448e5SGunnar Mills { 634f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 635f40448e5SGunnar Mills { 636f40448e5SGunnar Mills return; 637f40448e5SGunnar Mills } 638f40448e5SGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 639f40448e5SGunnar Mills "xyz.openbmc_project.Network.EthernetInterface"}; 640f40448e5SGunnar Mills 641f40448e5SGunnar Mills dbus::utility::getSubTreePaths( 642f40448e5SGunnar Mills "/xyz/openbmc_project/network/hypervisor", 0, interfaces, 643f40448e5SGunnar Mills [asyncResp]( 6448b24275dSEd Tanous const boost::system::error_code& ec, 645f40448e5SGunnar Mills const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) { 6468b24275dSEd Tanous if (ec) 647f40448e5SGunnar Mills { 648bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "System", 649bd79bce8SPatrick Williams "hypervisor"); 650f40448e5SGunnar Mills return; 651f40448e5SGunnar Mills } 652f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 653f40448e5SGunnar Mills "#EthernetInterfaceCollection." 654f40448e5SGunnar Mills "EthernetInterfaceCollection"; 655f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 656f40448e5SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 657f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet " 658f40448e5SGunnar Mills "Interface Collection"; 659f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 660f40448e5SGunnar Mills "Collection of Virtual Management " 661f40448e5SGunnar Mills "Interfaces for the hypervisor"; 662f40448e5SGunnar Mills 663f40448e5SGunnar Mills nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 664f40448e5SGunnar Mills ifaceArray = nlohmann::json::array(); 665f40448e5SGunnar Mills for (const std::string& iface : ifaceList) 666f40448e5SGunnar Mills { 667f40448e5SGunnar Mills sdbusplus::message::object_path path(iface); 668f40448e5SGunnar Mills std::string name = path.filename(); 669f40448e5SGunnar Mills if (name.empty()) 670f40448e5SGunnar Mills { 671f40448e5SGunnar Mills continue; 672f40448e5SGunnar Mills } 673f40448e5SGunnar Mills nlohmann::json::object_t ethIface; 674ef4c65b7SEd Tanous ethIface["@odata.id"] = boost::urls::format( 675bd79bce8SPatrick Williams "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", 676bd79bce8SPatrick Williams name); 677b2ba3072SPatrick Williams ifaceArray.emplace_back(std::move(ethIface)); 678f40448e5SGunnar Mills } 679f40448e5SGunnar Mills asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 680f40448e5SGunnar Mills }); 681f40448e5SGunnar Mills } 682f40448e5SGunnar Mills 683f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfaceGet( 684f40448e5SGunnar Mills App& app, const crow::Request& req, 685f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 686f40448e5SGunnar Mills { 687f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 688f40448e5SGunnar Mills { 689f40448e5SGunnar Mills return; 690f40448e5SGunnar Mills } 691f40448e5SGunnar Mills getHypervisorIfaceData( 692f40448e5SGunnar Mills id, [asyncResp, ifaceId{std::string(id)}]( 69377179532SEd Tanous bool success, const EthernetInterfaceData& ethData, 69477179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data) { 695f40448e5SGunnar Mills if (!success) 696f40448e5SGunnar Mills { 697f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 698f40448e5SGunnar Mills ifaceId); 699f40448e5SGunnar Mills return; 700f40448e5SGunnar Mills } 701f40448e5SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 70293bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 703f40448e5SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface"; 704f40448e5SGunnar Mills asyncResp->res.jsonValue["Description"] = 705f40448e5SGunnar Mills "Hypervisor's Virtual Management Ethernet Interface"; 706f40448e5SGunnar Mills parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData, 707f40448e5SGunnar Mills ipv4Data); 708f40448e5SGunnar Mills }); 709f40448e5SGunnar Mills } 710f40448e5SGunnar Mills 7118d8c30c3SGunnar Mills inline void handleHypervisorSystemGet( 7128d8c30c3SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7138d8c30c3SGunnar Mills { 7148d8c30c3SGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 7158d8c30c3SGunnar Mills "#ComputerSystem.v1_6_0.ComputerSystem"; 71668896206SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/hypervisor"; 7178d8c30c3SGunnar Mills asyncResp->res.jsonValue["Description"] = "Hypervisor"; 7188d8c30c3SGunnar Mills asyncResp->res.jsonValue["Name"] = "Hypervisor"; 7198d8c30c3SGunnar Mills asyncResp->res.jsonValue["Id"] = "hypervisor"; 72068896206SGunnar Mills asyncResp->res.jsonValue["SystemType"] = computer_system::SystemType::OS; 7218d8c30c3SGunnar Mills nlohmann::json::array_t managedBy; 7228d8c30c3SGunnar Mills nlohmann::json::object_t manager; 72368896206SGunnar Mills manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}", 72468896206SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 725ad539545SPatrick Williams managedBy.emplace_back(std::move(manager)); 72668896206SGunnar Mills asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); 7278d8c30c3SGunnar Mills asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 7288d8c30c3SGunnar Mills "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 7298d8c30c3SGunnar Mills getHypervisorState(asyncResp); 7308d8c30c3SGunnar Mills getHypervisorActions(asyncResp); 7318d8c30c3SGunnar Mills // TODO: Add "SystemType" : "hypervisor" 7328d8c30c3SGunnar Mills } 7338d8c30c3SGunnar Mills 734f40448e5SGunnar Mills inline void handleHypervisorEthernetInterfacePatch( 735f40448e5SGunnar Mills App& app, const crow::Request& req, 736f40448e5SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 737f40448e5SGunnar Mills const std::string& ifaceId) 738f40448e5SGunnar Mills { 739f40448e5SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 740f40448e5SGunnar Mills { 741f40448e5SGunnar Mills return; 742f40448e5SGunnar Mills } 743f40448e5SGunnar Mills std::optional<std::string> hostName; 74421fe928bSEd Tanous std::optional< 74521fe928bSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 74621fe928bSEd Tanous ipv4StaticAddresses; 74721fe928bSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> ipv4Addresses; 748f40448e5SGunnar Mills std::optional<bool> ipv4DHCPEnabled; 749f40448e5SGunnar Mills 750afc474aeSMyung Bae if (!json_util::readJsonPatch( // 751afc474aeSMyung Bae req, asyncResp->res, // 752afc474aeSMyung Bae "DHCPv4/DHCPEnabled", ipv4DHCPEnabled, // 753afc474aeSMyung Bae "IPv4Addresses", ipv4Addresses, // 754afc474aeSMyung Bae "IPv4StaticAddresses", ipv4StaticAddresses, // 755afc474aeSMyung Bae "HostName", hostName // 756afc474aeSMyung Bae )) 757f40448e5SGunnar Mills { 758f40448e5SGunnar Mills return; 759f40448e5SGunnar Mills } 760f40448e5SGunnar Mills 761f40448e5SGunnar Mills if (ipv4Addresses) 762f40448e5SGunnar Mills { 763f40448e5SGunnar Mills messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 764f40448e5SGunnar Mills return; 765f40448e5SGunnar Mills } 766f40448e5SGunnar Mills 767f40448e5SGunnar Mills getHypervisorIfaceData( 76821fe928bSEd Tanous ifaceId, 76921fe928bSEd Tanous [asyncResp, ifaceId, hostName = std::move(hostName), 7705a39f77aSPatrick Williams ipv4StaticAddresses = std::move(ipv4StaticAddresses), 77121fe928bSEd Tanous ipv4DHCPEnabled](bool success, const EthernetInterfaceData& ethData, 77221fe928bSEd Tanous const std::vector<IPv4AddressData>&) mutable { 773f40448e5SGunnar Mills if (!success) 774f40448e5SGunnar Mills { 775f40448e5SGunnar Mills messages::resourceNotFound(asyncResp->res, "EthernetInterface", 776f40448e5SGunnar Mills ifaceId); 777f40448e5SGunnar Mills return; 778f40448e5SGunnar Mills } 779f40448e5SGunnar Mills 780f40448e5SGunnar Mills if (ipv4StaticAddresses) 781f40448e5SGunnar Mills { 782bd79bce8SPatrick Williams std::vector<std::variant<nlohmann::json::object_t, 783bd79bce8SPatrick Williams std::nullptr_t>>& ipv4Static = 784bd79bce8SPatrick Williams *ipv4StaticAddresses; 785f40448e5SGunnar Mills if (ipv4Static.begin() == ipv4Static.end()) 786f40448e5SGunnar Mills { 78721fe928bSEd Tanous messages::propertyValueTypeError(asyncResp->res, 78821fe928bSEd Tanous std::vector<std::string>(), 789f40448e5SGunnar Mills "IPv4StaticAddresses"); 790f40448e5SGunnar Mills return; 791f40448e5SGunnar Mills } 792f40448e5SGunnar Mills 793f40448e5SGunnar Mills // One and only one hypervisor instance supported 794f40448e5SGunnar Mills if (ipv4Static.size() != 1) 795f40448e5SGunnar Mills { 79621fe928bSEd Tanous messages::propertyValueFormatError(asyncResp->res, "[]", 797f40448e5SGunnar Mills "IPv4StaticAddresses"); 798f40448e5SGunnar Mills return; 799f40448e5SGunnar Mills } 800f40448e5SGunnar Mills 801bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>& 802bd79bce8SPatrick Williams ipv4Json = ipv4Static[0]; 803f40448e5SGunnar Mills // Check if the param is 'null'. If its null, it means 804f40448e5SGunnar Mills // that user wants to delete the IP address. Deleting 805f40448e5SGunnar Mills // the IP address is allowed only if its statically 806f40448e5SGunnar Mills // configured. Deleting the address originated from DHCP 807f40448e5SGunnar Mills // is not allowed. 80821fe928bSEd Tanous if (std::holds_alternative<std::nullptr_t>(ipv4Json) && 80921fe928bSEd Tanous translateDhcpEnabledToBool(ethData.dhcpEnabled, true)) 810f40448e5SGunnar Mills { 811bd79bce8SPatrick Williams BMCWEB_LOG_INFO( 812bd79bce8SPatrick Williams "Ignoring the delete on ipv4StaticAddresses " 81362598e31SEd Tanous "as the interface is DHCP enabled"); 814f40448e5SGunnar Mills } 815f40448e5SGunnar Mills else 816f40448e5SGunnar Mills { 817bd79bce8SPatrick Williams handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, 818bd79bce8SPatrick Williams asyncResp); 819f40448e5SGunnar Mills } 820f40448e5SGunnar Mills } 821f40448e5SGunnar Mills 822f40448e5SGunnar Mills if (hostName) 823f40448e5SGunnar Mills { 824f40448e5SGunnar Mills handleHypervisorHostnamePatch(*hostName, asyncResp); 825f40448e5SGunnar Mills } 826f40448e5SGunnar Mills 82721fe928bSEd Tanous if (ipv4DHCPEnabled) 828f40448e5SGunnar Mills { 829f40448e5SGunnar Mills setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 830f40448e5SGunnar Mills } 831f40448e5SGunnar Mills 832f40448e5SGunnar Mills // Set this interface to disabled/inactive. This will be set 833f40448e5SGunnar Mills // to enabled/active by the pldm once the hypervisor 834f40448e5SGunnar Mills // consumes the updated settings from the user. 835f40448e5SGunnar Mills setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 836f40448e5SGunnar Mills }); 837f40448e5SGunnar Mills asyncResp->res.result(boost::beast::http::status::accepted); 838f40448e5SGunnar Mills } 839f40448e5SGunnar Mills 840a5d0cedbSGunnar Mills inline void handleHypervisorResetActionGet( 841a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 842a5d0cedbSGunnar Mills { 843a5d0cedbSGunnar Mills // Only return action info if hypervisor D-Bus object present 844a5d0cedbSGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 845a5d0cedbSGunnar Mills "xyz.openbmc_project.State.Host"}; 846a5d0cedbSGunnar Mills dbus::utility::getDbusObject( 847a5d0cedbSGunnar Mills "/xyz/openbmc_project/state/hypervisor0", interfaces, 848a5d0cedbSGunnar Mills [asyncResp]( 849a5d0cedbSGunnar Mills const boost::system::error_code& ec, 850a5d0cedbSGunnar Mills const std::vector<std::pair<std::string, std::vector<std::string>>>& 851a5d0cedbSGunnar Mills objInfo) { 852a5d0cedbSGunnar Mills if (ec) 853a5d0cedbSGunnar Mills { 85462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 855a5d0cedbSGunnar Mills 856a5d0cedbSGunnar Mills // No hypervisor objects found by mapper 857a5d0cedbSGunnar Mills if (ec.value() == boost::system::errc::io_error) 858a5d0cedbSGunnar Mills { 859a5d0cedbSGunnar Mills messages::resourceNotFound(asyncResp->res, "hypervisor", 860a5d0cedbSGunnar Mills "ResetActionInfo"); 861a5d0cedbSGunnar Mills return; 862a5d0cedbSGunnar Mills } 863a5d0cedbSGunnar Mills 864a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 865a5d0cedbSGunnar Mills return; 866a5d0cedbSGunnar Mills } 867a5d0cedbSGunnar Mills 868a5d0cedbSGunnar Mills // One and only one hypervisor instance supported 869a5d0cedbSGunnar Mills if (objInfo.size() != 1) 870a5d0cedbSGunnar Mills { 871a5d0cedbSGunnar Mills messages::internalError(asyncResp->res); 872a5d0cedbSGunnar Mills return; 873a5d0cedbSGunnar Mills } 874a5d0cedbSGunnar Mills 875a5d0cedbSGunnar Mills // The hypervisor object only support the ability to 876a5d0cedbSGunnar Mills // turn On The system object Action should be utilized 877a5d0cedbSGunnar Mills // for other operations 878a5d0cedbSGunnar Mills 879a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.type"] = 880a5d0cedbSGunnar Mills "#ActionInfo.v1_1_2.ActionInfo"; 881a5d0cedbSGunnar Mills asyncResp->res.jsonValue["@odata.id"] = 882a5d0cedbSGunnar Mills "/redfish/v1/Systems/hypervisor/ResetActionInfo"; 883a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 884a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 885a5d0cedbSGunnar Mills nlohmann::json::array_t parameters; 886a5d0cedbSGunnar Mills nlohmann::json::object_t parameter; 887a5d0cedbSGunnar Mills parameter["Name"] = "ResetType"; 888a5d0cedbSGunnar Mills parameter["Required"] = true; 889539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 890a5d0cedbSGunnar Mills nlohmann::json::array_t allowed; 891ad539545SPatrick Williams allowed.emplace_back("On"); 892a5d0cedbSGunnar Mills parameter["AllowableValues"] = std::move(allowed); 893ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 894a5d0cedbSGunnar Mills asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 895a5d0cedbSGunnar Mills }); 896a5d0cedbSGunnar Mills } 897a5d0cedbSGunnar Mills 898a5d0cedbSGunnar Mills inline void handleHypervisorSystemResetPost( 899dd7090e6SGunnar Mills const crow::Request& req, 900a5d0cedbSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 901a5d0cedbSGunnar Mills { 902a5d0cedbSGunnar Mills std::optional<std::string> resetType; 903a5d0cedbSGunnar Mills if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 904a5d0cedbSGunnar Mills { 905a5d0cedbSGunnar Mills // readJson adds appropriate error to response 906a5d0cedbSGunnar Mills return; 907a5d0cedbSGunnar Mills } 908a5d0cedbSGunnar Mills 909a5d0cedbSGunnar Mills if (!resetType) 910a5d0cedbSGunnar Mills { 911a5d0cedbSGunnar Mills messages::actionParameterMissing(asyncResp->res, "ComputerSystem.Reset", 912a5d0cedbSGunnar Mills "ResetType"); 913a5d0cedbSGunnar Mills return; 914a5d0cedbSGunnar Mills } 915a5d0cedbSGunnar Mills 916a5d0cedbSGunnar Mills // Hypervisor object only support On operation 917a5d0cedbSGunnar Mills if (resetType != "On") 918a5d0cedbSGunnar Mills { 919a5d0cedbSGunnar Mills messages::propertyValueNotInList(asyncResp->res, *resetType, 920a5d0cedbSGunnar Mills "ResetType"); 921a5d0cedbSGunnar Mills return; 922a5d0cedbSGunnar Mills } 923a5d0cedbSGunnar Mills 924a5d0cedbSGunnar Mills std::string command = "xyz.openbmc_project.State.Host.Transition.On"; 925a5d0cedbSGunnar Mills 926bd79bce8SPatrick Williams setDbusPropertyAction( 927bd79bce8SPatrick Williams asyncResp, "xyz.openbmc_project.State.Hypervisor", 9281827b4f1SAsmitha Karunanithi sdbusplus::message::object_path( 9291827b4f1SAsmitha Karunanithi "/xyz/openbmc_project/state/hypervisor0"), 930bd79bce8SPatrick Williams "xyz.openbmc_project.State.Host", "RequestedHostTransition", 931bd79bce8SPatrick Williams "ResetType", "ComputerSystem.Reset", command); 932a5d0cedbSGunnar Mills } 933a5d0cedbSGunnar Mills 9347e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 9357e860f15SJohn Edward Broadbent { 9367e860f15SJohn Edward Broadbent /** 9377e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 9387e860f15SJohn Edward Broadbent * Hypervisor Interface 9397e860f15SJohn Edward Broadbent */ 9407e860f15SJohn Edward Broadbent 9417e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 942ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 943f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 944f40448e5SGunnar Mills handleHypervisorEthernetInterfaceCollectionGet, std::ref(app))); 9457e860f15SJohn Edward Broadbent 9467e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9477e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 948ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 949f40448e5SGunnar Mills .methods(boost::beast::http::verb::get)(std::bind_front( 950f40448e5SGunnar Mills handleHypervisorEthernetInterfaceGet, std::ref(app))); 951d5afb2caSAndrew Geissler 9527e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9537e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 954ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 955f40448e5SGunnar Mills .methods(boost::beast::http::verb::patch)(std::bind_front( 956f40448e5SGunnar Mills handleHypervisorEthernetInterfacePatch, std::ref(app))); 9574fbaf64aSAndrew Geissler } 95888a8a174SEd Tanous } // namespace redfish 959