1d5afb2caSAndrew Geissler #pragma once 2d5afb2caSAndrew Geissler 3*7e860f15SJohn Edward Broadbent #include <app.hpp> 4d5afb2caSAndrew Geissler #include <boost/container/flat_map.hpp> 5d5afb2caSAndrew Geissler #include <boost/container/flat_set.hpp> 6d5afb2caSAndrew Geissler #include <dbus_singleton.hpp> 7d5afb2caSAndrew Geissler #include <error_messages.hpp> 8d5afb2caSAndrew Geissler #include <node.hpp> 9d5afb2caSAndrew Geissler #include <utils/json_utils.hpp> 10d5afb2caSAndrew Geissler 11d5afb2caSAndrew Geissler #include <optional> 12d5afb2caSAndrew Geissler #include <utility> 13d5afb2caSAndrew Geissler #include <variant> 14d5afb2caSAndrew Geissler 15d5afb2caSAndrew Geissler namespace redfish 16d5afb2caSAndrew Geissler { 17d5afb2caSAndrew Geissler 18d5afb2caSAndrew Geissler /** 19cc0bb6f2SAndrew Geissler * @brief Retrieves hypervisor state properties over dbus 20cc0bb6f2SAndrew Geissler * 21cc0bb6f2SAndrew Geissler * The hypervisor state object is optional so this function will only set the 22cc0bb6f2SAndrew Geissler * state variables if the object is found 23cc0bb6f2SAndrew Geissler * 24cc0bb6f2SAndrew Geissler * @param[in] aResp Shared pointer for completing asynchronous calls. 25cc0bb6f2SAndrew Geissler * 26cc0bb6f2SAndrew Geissler * @return None. 27cc0bb6f2SAndrew Geissler */ 288d1b46d7Szhanghch05 inline void getHypervisorState(const std::shared_ptr<bmcweb::AsyncResp>& aResp) 29cc0bb6f2SAndrew Geissler { 30cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "Get hypervisor state information."; 31cc0bb6f2SAndrew Geissler crow::connections::systemBus->async_method_call( 32cc0bb6f2SAndrew Geissler [aResp](const boost::system::error_code ec, 33cc0bb6f2SAndrew Geissler const std::variant<std::string>& hostState) { 34cc0bb6f2SAndrew Geissler if (ec) 35cc0bb6f2SAndrew Geissler { 36cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 37cc0bb6f2SAndrew Geissler // This is an optional D-Bus object so just return if 38cc0bb6f2SAndrew Geissler // error occurs 39cc0bb6f2SAndrew Geissler return; 40cc0bb6f2SAndrew Geissler } 41cc0bb6f2SAndrew Geissler 42cc0bb6f2SAndrew Geissler const std::string* s = std::get_if<std::string>(&hostState); 43cc0bb6f2SAndrew Geissler if (s == nullptr) 44cc0bb6f2SAndrew Geissler { 45cc0bb6f2SAndrew Geissler messages::internalError(aResp->res); 46cc0bb6f2SAndrew Geissler return; 47cc0bb6f2SAndrew Geissler } 48cc0bb6f2SAndrew Geissler 49cc0bb6f2SAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor state: " << *s; 50cc0bb6f2SAndrew Geissler // Verify Host State 51cc0bb6f2SAndrew Geissler if (*s == "xyz.openbmc_project.State.Host.HostState.Running") 52cc0bb6f2SAndrew Geissler { 53cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 54cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Enabled"; 55cc0bb6f2SAndrew Geissler } 56cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 57cc0bb6f2SAndrew Geissler "Quiesced") 58cc0bb6f2SAndrew Geissler { 59cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 60cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Quiesced"; 61cc0bb6f2SAndrew Geissler } 62cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 63cc0bb6f2SAndrew Geissler "Standby") 64cc0bb6f2SAndrew Geissler { 65cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "On"; 66cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 67cc0bb6f2SAndrew Geissler } 68cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 69cc0bb6f2SAndrew Geissler "TransitioningToRunning") 70cc0bb6f2SAndrew Geissler { 71cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "PoweringOn"; 72cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Starting"; 73cc0bb6f2SAndrew Geissler } 74cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState." 75cc0bb6f2SAndrew Geissler "TransitioningToOff") 76cc0bb6f2SAndrew Geissler { 77cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "PoweringOff"; 78cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Enabled"; 79cc0bb6f2SAndrew Geissler } 80cc0bb6f2SAndrew Geissler else if (*s == "xyz.openbmc_project.State.Host.HostState.Off") 81cc0bb6f2SAndrew Geissler { 82cc0bb6f2SAndrew Geissler aResp->res.jsonValue["PowerState"] = "Off"; 83cc0bb6f2SAndrew Geissler aResp->res.jsonValue["Status"]["State"] = "Disabled"; 84cc0bb6f2SAndrew Geissler } 85cc0bb6f2SAndrew Geissler else 86cc0bb6f2SAndrew Geissler { 87cc0bb6f2SAndrew Geissler messages::internalError(aResp->res); 88cc0bb6f2SAndrew Geissler return; 89cc0bb6f2SAndrew Geissler } 90cc0bb6f2SAndrew Geissler }, 91cc0bb6f2SAndrew Geissler "xyz.openbmc_project.State.Hypervisor", 92cc0bb6f2SAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 93cc0bb6f2SAndrew Geissler "org.freedesktop.DBus.Properties", "Get", 94cc0bb6f2SAndrew Geissler "xyz.openbmc_project.State.Host", "CurrentHostState"); 95cc0bb6f2SAndrew Geissler } 96cc0bb6f2SAndrew Geissler 97cc0bb6f2SAndrew Geissler /** 984fbaf64aSAndrew Geissler * @brief Populate Actions if any are valid for hypervisor object 994fbaf64aSAndrew Geissler * 1004fbaf64aSAndrew Geissler * The hypervisor state object is optional so this function will only set the 1014fbaf64aSAndrew Geissler * Action if the object is found 1024fbaf64aSAndrew Geissler * 1034fbaf64aSAndrew Geissler * @param[in] aResp Shared pointer for completing asynchronous calls. 1044fbaf64aSAndrew Geissler * 1054fbaf64aSAndrew Geissler * @return None. 1064fbaf64aSAndrew Geissler */ 1078d1b46d7Szhanghch05 inline void 1088d1b46d7Szhanghch05 getHypervisorActions(const std::shared_ptr<bmcweb::AsyncResp>& aResp) 1094fbaf64aSAndrew Geissler { 1104fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "Get hypervisor actions."; 1114fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 1124fbaf64aSAndrew Geissler [aResp]( 1134fbaf64aSAndrew Geissler const boost::system::error_code ec, 1144fbaf64aSAndrew Geissler const std::vector<std::pair<std::string, std::vector<std::string>>>& 1154fbaf64aSAndrew Geissler objInfo) { 1164fbaf64aSAndrew Geissler if (ec) 1174fbaf64aSAndrew Geissler { 1184fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 1194fbaf64aSAndrew Geissler // This is an optional D-Bus object so just return if 1204fbaf64aSAndrew Geissler // error occurs 1214fbaf64aSAndrew Geissler return; 1224fbaf64aSAndrew Geissler } 1234fbaf64aSAndrew Geissler 1244fbaf64aSAndrew Geissler if (objInfo.size() == 0) 1254fbaf64aSAndrew Geissler { 1264fbaf64aSAndrew Geissler // As noted above, this is an optional interface so just return 1274fbaf64aSAndrew Geissler // if there is no instance found 1284fbaf64aSAndrew Geissler return; 1294fbaf64aSAndrew Geissler } 1304fbaf64aSAndrew Geissler 1314fbaf64aSAndrew Geissler if (objInfo.size() > 1) 1324fbaf64aSAndrew Geissler { 1334fbaf64aSAndrew Geissler // More then one hypervisor object is not supported and is an 1344fbaf64aSAndrew Geissler // error 1354fbaf64aSAndrew Geissler messages::internalError(aResp->res); 1364fbaf64aSAndrew Geissler return; 1374fbaf64aSAndrew Geissler } 1384fbaf64aSAndrew Geissler 1394fbaf64aSAndrew Geissler // Object present so system support limited ComputerSystem Action 1404fbaf64aSAndrew Geissler aResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = { 1414fbaf64aSAndrew Geissler {"target", 1424fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"}, 1434fbaf64aSAndrew Geissler {"@Redfish.ActionInfo", 1444fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/ResetActionInfo"}}; 1454fbaf64aSAndrew Geissler }, 1464fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", 1474fbaf64aSAndrew Geissler "/xyz/openbmc_project/object_mapper", 1484fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", "GetObject", 1494fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 1504fbaf64aSAndrew Geissler std::array<const char*, 1>{"xyz.openbmc_project.State.Host"}); 1514fbaf64aSAndrew Geissler } 1524fbaf64aSAndrew Geissler 153d5afb2caSAndrew Geissler inline bool extractHypervisorInterfaceData( 154d5afb2caSAndrew Geissler const std::string& ethIfaceId, const GetManagedObjects& dbusData, 155d5afb2caSAndrew Geissler EthernetInterfaceData& ethData, 156d5afb2caSAndrew Geissler boost::container::flat_set<IPv4AddressData>& ipv4Config) 157d5afb2caSAndrew Geissler { 158d5afb2caSAndrew Geissler bool idFound = false; 159d5afb2caSAndrew Geissler for (const auto& objpath : dbusData) 160d5afb2caSAndrew Geissler { 161d5afb2caSAndrew Geissler for (const auto& ifacePair : objpath.second) 162d5afb2caSAndrew Geissler { 163d5afb2caSAndrew Geissler if (objpath.first == 164d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId) 165d5afb2caSAndrew Geissler { 166d5afb2caSAndrew Geissler idFound = true; 167d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 168d5afb2caSAndrew Geissler { 169d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 170d5afb2caSAndrew Geissler { 171d5afb2caSAndrew Geissler if (propertyPair.first == "MACAddress") 172d5afb2caSAndrew Geissler { 173d5afb2caSAndrew Geissler const std::string* mac = 174d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 175d5afb2caSAndrew Geissler if (mac != nullptr) 176d5afb2caSAndrew Geissler { 177d5afb2caSAndrew Geissler ethData.mac_address = *mac; 178d5afb2caSAndrew Geissler } 179d5afb2caSAndrew Geissler } 180d5afb2caSAndrew Geissler } 181d5afb2caSAndrew Geissler } 182d5afb2caSAndrew Geissler else if (ifacePair.first == 183d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface") 184d5afb2caSAndrew Geissler { 185d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 186d5afb2caSAndrew Geissler { 187d5afb2caSAndrew Geissler if (propertyPair.first == "DHCPEnabled") 188d5afb2caSAndrew Geissler { 189d5afb2caSAndrew Geissler const std::string* dhcp = 190d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 191d5afb2caSAndrew Geissler if (dhcp != nullptr) 192d5afb2caSAndrew Geissler { 193d5afb2caSAndrew Geissler ethData.DHCPEnabled = *dhcp; 194d5afb2caSAndrew Geissler break; // Interested on only "DHCPEnabled". 195d5afb2caSAndrew Geissler // Stop parsing since we got the 196d5afb2caSAndrew Geissler // "DHCPEnabled" value. 197d5afb2caSAndrew Geissler } 198d5afb2caSAndrew Geissler } 199d5afb2caSAndrew Geissler } 200d5afb2caSAndrew Geissler } 201d5afb2caSAndrew Geissler } 202d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor/" + 203d5afb2caSAndrew Geissler ethIfaceId + "/ipv4/addr0") 204d5afb2caSAndrew Geissler { 205d5afb2caSAndrew Geissler std::pair<boost::container::flat_set<IPv4AddressData>::iterator, 206d5afb2caSAndrew Geissler bool> 207d5afb2caSAndrew Geissler it = ipv4Config.insert(IPv4AddressData{}); 208d5afb2caSAndrew Geissler IPv4AddressData& ipv4Address = *it.first; 209d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Object.Enable") 210d5afb2caSAndrew Geissler { 211d5afb2caSAndrew Geissler for (auto& property : ifacePair.second) 212d5afb2caSAndrew Geissler { 213d5afb2caSAndrew Geissler if (property.first == "Enabled") 214d5afb2caSAndrew Geissler { 215d5afb2caSAndrew Geissler const bool* intfEnable = 216d5afb2caSAndrew Geissler std::get_if<bool>(&property.second); 217d5afb2caSAndrew Geissler if (intfEnable != nullptr) 218d5afb2caSAndrew Geissler { 219d5afb2caSAndrew Geissler ipv4Address.isActive = *intfEnable; 220d5afb2caSAndrew Geissler break; 221d5afb2caSAndrew Geissler } 222d5afb2caSAndrew Geissler } 223d5afb2caSAndrew Geissler } 224d5afb2caSAndrew Geissler } 225d5afb2caSAndrew Geissler if (ifacePair.first == "xyz.openbmc_project.Network.IP") 226d5afb2caSAndrew Geissler { 227d5afb2caSAndrew Geissler for (auto& property : ifacePair.second) 228d5afb2caSAndrew Geissler { 229d5afb2caSAndrew Geissler if (property.first == "Address") 230d5afb2caSAndrew Geissler { 231d5afb2caSAndrew Geissler const std::string* address = 232d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 233d5afb2caSAndrew Geissler if (address != nullptr) 234d5afb2caSAndrew Geissler { 235d5afb2caSAndrew Geissler ipv4Address.address = *address; 236d5afb2caSAndrew Geissler } 237d5afb2caSAndrew Geissler } 238d5afb2caSAndrew Geissler else if (property.first == "Origin") 239d5afb2caSAndrew Geissler { 240d5afb2caSAndrew Geissler const std::string* origin = 241d5afb2caSAndrew Geissler std::get_if<std::string>(&property.second); 242d5afb2caSAndrew Geissler if (origin != nullptr) 243d5afb2caSAndrew Geissler { 244d5afb2caSAndrew Geissler ipv4Address.origin = 245d5afb2caSAndrew Geissler translateAddressOriginDbusToRedfish(*origin, 246d5afb2caSAndrew Geissler true); 247d5afb2caSAndrew Geissler } 248d5afb2caSAndrew Geissler } 249d5afb2caSAndrew Geissler else if (property.first == "PrefixLength") 250d5afb2caSAndrew Geissler { 251d5afb2caSAndrew Geissler const uint8_t* mask = 252d5afb2caSAndrew Geissler std::get_if<uint8_t>(&property.second); 253d5afb2caSAndrew Geissler if (mask != nullptr) 254d5afb2caSAndrew Geissler { 255d5afb2caSAndrew Geissler // convert it to the string 256d5afb2caSAndrew Geissler ipv4Address.netmask = getNetmask(*mask); 257d5afb2caSAndrew Geissler } 258d5afb2caSAndrew Geissler } 259d5afb2caSAndrew Geissler else 260d5afb2caSAndrew Geissler { 261d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR 262d5afb2caSAndrew Geissler << "Got extra property: " << property.first 263d5afb2caSAndrew Geissler << " on the " << objpath.first.str << " object"; 264d5afb2caSAndrew Geissler } 265d5afb2caSAndrew Geissler } 266d5afb2caSAndrew Geissler } 267d5afb2caSAndrew Geissler } 268d5afb2caSAndrew Geissler if (objpath.first == "/xyz/openbmc_project/network/hypervisor") 269d5afb2caSAndrew Geissler { 270d5afb2caSAndrew Geissler // System configuration shows up in the global namespace, so no 271d5afb2caSAndrew Geissler // need to check eth number 272d5afb2caSAndrew Geissler if (ifacePair.first == 273d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration") 274d5afb2caSAndrew Geissler { 275d5afb2caSAndrew Geissler for (const auto& propertyPair : ifacePair.second) 276d5afb2caSAndrew Geissler { 277d5afb2caSAndrew Geissler if (propertyPair.first == "HostName") 278d5afb2caSAndrew Geissler { 279d5afb2caSAndrew Geissler const std::string* hostName = 280d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 281d5afb2caSAndrew Geissler if (hostName != nullptr) 282d5afb2caSAndrew Geissler { 283d5afb2caSAndrew Geissler ethData.hostname = *hostName; 284d5afb2caSAndrew Geissler } 285d5afb2caSAndrew Geissler } 286d5afb2caSAndrew Geissler else if (propertyPair.first == "DefaultGateway") 287d5afb2caSAndrew Geissler { 288d5afb2caSAndrew Geissler const std::string* defaultGateway = 289d5afb2caSAndrew Geissler std::get_if<std::string>(&propertyPair.second); 290d5afb2caSAndrew Geissler if (defaultGateway != nullptr) 291d5afb2caSAndrew Geissler { 292d5afb2caSAndrew Geissler ethData.default_gateway = *defaultGateway; 293d5afb2caSAndrew Geissler } 294d5afb2caSAndrew Geissler } 295d5afb2caSAndrew Geissler } 296d5afb2caSAndrew Geissler } 297d5afb2caSAndrew Geissler } 298d5afb2caSAndrew Geissler } 299d5afb2caSAndrew Geissler } 300d5afb2caSAndrew Geissler return idFound; 301d5afb2caSAndrew Geissler } 302d5afb2caSAndrew Geissler /** 303d5afb2caSAndrew Geissler * Function that retrieves all properties for given Hypervisor Ethernet 304d5afb2caSAndrew Geissler * Interface Object from Settings Manager 305d5afb2caSAndrew Geissler * @param ethIfaceId Hypervisor ethernet interface id to query on DBus 306d5afb2caSAndrew Geissler * @param callback a function that shall be called to convert Dbus output 307d5afb2caSAndrew Geissler * into JSON 308d5afb2caSAndrew Geissler */ 309d5afb2caSAndrew Geissler template <typename CallbackFunc> 310d5afb2caSAndrew Geissler void getHypervisorIfaceData(const std::string& ethIfaceId, 311d5afb2caSAndrew Geissler CallbackFunc&& callback) 312d5afb2caSAndrew Geissler { 313d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 314d5afb2caSAndrew Geissler [ethIfaceId{std::string{ethIfaceId}}, 315d5afb2caSAndrew Geissler callback{std::move(callback)}](const boost::system::error_code error, 316d5afb2caSAndrew Geissler const GetManagedObjects& resp) { 317d5afb2caSAndrew Geissler EthernetInterfaceData ethData{}; 318d5afb2caSAndrew Geissler boost::container::flat_set<IPv4AddressData> ipv4Data; 319d5afb2caSAndrew Geissler if (error) 320d5afb2caSAndrew Geissler { 321d5afb2caSAndrew Geissler callback(false, ethData, ipv4Data); 322d5afb2caSAndrew Geissler return; 323d5afb2caSAndrew Geissler } 324d5afb2caSAndrew Geissler 325d5afb2caSAndrew Geissler bool found = extractHypervisorInterfaceData(ethIfaceId, resp, 326d5afb2caSAndrew Geissler ethData, ipv4Data); 327d5afb2caSAndrew Geissler if (!found) 328d5afb2caSAndrew Geissler { 329d5afb2caSAndrew Geissler BMCWEB_LOG_INFO << "Hypervisor Interface not found"; 330d5afb2caSAndrew Geissler } 331d5afb2caSAndrew Geissler callback(found, ethData, ipv4Data); 332d5afb2caSAndrew Geissler }, 333d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", "/", 334d5afb2caSAndrew Geissler "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 335d5afb2caSAndrew Geissler } 336d5afb2caSAndrew Geissler 337d5afb2caSAndrew Geissler /** 338d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface IPAddress DBUS 339d5afb2caSAndrew Geissler * 340d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 341d5afb2caSAndrew Geissler * @param[in] ipv4Address Address from the incoming request 342d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 343d5afb2caSAndrew Geissler * 344d5afb2caSAndrew Geissler * @return None. 345d5afb2caSAndrew Geissler */ 3468d1b46d7Szhanghch05 inline void 3478d1b46d7Szhanghch05 setHypervisorIPv4Address(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 348d5afb2caSAndrew Geissler const std::string& ethIfaceId, 349d5afb2caSAndrew Geissler const std::string& ipv4Address) 350d5afb2caSAndrew Geissler { 351d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor IPaddress : " << ipv4Address 352d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 353d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 354d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 355d5afb2caSAndrew Geissler if (ec) 356d5afb2caSAndrew Geissler { 357d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 358d5afb2caSAndrew Geissler return; 359d5afb2caSAndrew Geissler } 360d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress is Set"; 361d5afb2caSAndrew Geissler }, 362d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 363d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 364d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 365d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Address", 366d5afb2caSAndrew Geissler std::variant<std::string>(ipv4Address)); 367d5afb2caSAndrew Geissler } 368d5afb2caSAndrew Geissler 369d5afb2caSAndrew Geissler /** 370d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface SubnetMask DBUS 371d5afb2caSAndrew Geissler * 372d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 373d5afb2caSAndrew Geissler * @param[in] subnet SubnetMask from the incoming request 374d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 375d5afb2caSAndrew Geissler * 376d5afb2caSAndrew Geissler * @return None. 377d5afb2caSAndrew Geissler */ 3788d1b46d7Szhanghch05 inline void 3798d1b46d7Szhanghch05 setHypervisorIPv4Subnet(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 3808d1b46d7Szhanghch05 const std::string& ethIfaceId, const uint8_t subnet) 381d5afb2caSAndrew Geissler { 382d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Setting the Hypervisor subnet : " << subnet 383d5afb2caSAndrew Geissler << " on Iface: " << ethIfaceId; 384d5afb2caSAndrew Geissler 385d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 386d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 387d5afb2caSAndrew Geissler if (ec) 388d5afb2caSAndrew Geissler { 389d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 390d5afb2caSAndrew Geissler return; 391d5afb2caSAndrew Geissler } 392d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "SubnetMask is Set"; 393d5afb2caSAndrew Geissler }, 394d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 395d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", 396d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 397d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "PrefixLength", 398d5afb2caSAndrew Geissler std::variant<uint8_t>(subnet)); 399d5afb2caSAndrew Geissler } 400d5afb2caSAndrew Geissler 401d5afb2caSAndrew Geissler /** 402d5afb2caSAndrew Geissler * @brief Sets the Hypervisor Interface Gateway DBUS 403d5afb2caSAndrew Geissler * 404d5afb2caSAndrew Geissler * @param[in] aResp Shared pointer for generating response message. 405d5afb2caSAndrew Geissler * @param[in] gateway Gateway from the incoming request 406d5afb2caSAndrew Geissler * @param[in] ethIfaceId Hypervisor Interface Id 407d5afb2caSAndrew Geissler * 408d5afb2caSAndrew Geissler * @return None. 409d5afb2caSAndrew Geissler */ 4108d1b46d7Szhanghch05 inline void 4118d1b46d7Szhanghch05 setHypervisorIPv4Gateway(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 412d5afb2caSAndrew Geissler const std::string& gateway) 413d5afb2caSAndrew Geissler { 414d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG 415d5afb2caSAndrew Geissler << "Setting the DefaultGateway to the last configured gateway"; 416d5afb2caSAndrew Geissler 417d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 418d5afb2caSAndrew Geissler [aResp](const boost::system::error_code ec) { 419d5afb2caSAndrew Geissler if (ec) 420d5afb2caSAndrew Geissler { 421d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 422d5afb2caSAndrew Geissler return; 423d5afb2caSAndrew Geissler } 424d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Default Gateway is Set"; 425d5afb2caSAndrew Geissler }, 426d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 427d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor", 428d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 429d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.SystemConfiguration", "DefaultGateway", 430d5afb2caSAndrew Geissler std::variant<std::string>(gateway)); 431d5afb2caSAndrew Geissler } 432d5afb2caSAndrew Geissler 433d5afb2caSAndrew Geissler /** 434d5afb2caSAndrew Geissler * @brief Creates a static IPv4 entry 435d5afb2caSAndrew Geissler * 436d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 437d5afb2caSAndrew Geissler * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 438d5afb2caSAndrew Geissler * @param[in] gateway IPv4 address of this interfaces gateway 439d5afb2caSAndrew Geissler * @param[in] address IPv4 address to assign to this interface 440d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 441d5afb2caSAndrew Geissler * 442d5afb2caSAndrew Geissler * @return None 443d5afb2caSAndrew Geissler */ 4448d1b46d7Szhanghch05 inline void 4458d1b46d7Szhanghch05 createHypervisorIPv4(const std::string& ifaceId, uint8_t prefixLength, 4468d1b46d7Szhanghch05 const std::string& gateway, const std::string& address, 4478d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 448d5afb2caSAndrew Geissler { 449d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 450d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 451d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 452d5afb2caSAndrew Geissler } 453d5afb2caSAndrew Geissler 454d5afb2caSAndrew Geissler /** 455d5afb2caSAndrew Geissler * @brief Deletes given IPv4 interface 456d5afb2caSAndrew Geissler * 457d5afb2caSAndrew Geissler * @param[in] ifaceId Id of interface whose IP should be deleted 458d5afb2caSAndrew Geissler * @param[io] asyncResp Response object that will be returned to client 459d5afb2caSAndrew Geissler * 460d5afb2caSAndrew Geissler * @return None 461d5afb2caSAndrew Geissler */ 4628d1b46d7Szhanghch05 inline void 4638d1b46d7Szhanghch05 deleteHypervisorIPv4(const std::string& ifaceId, 4648d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 465d5afb2caSAndrew Geissler { 466d5afb2caSAndrew Geissler std::string address = "0.0.0.0"; 467d5afb2caSAndrew Geissler std::string gateway = "0.0.0.0"; 468d5afb2caSAndrew Geissler const uint8_t prefixLength = 0; 469d5afb2caSAndrew Geissler setHypervisorIPv4Address(asyncResp, ifaceId, address); 470d5afb2caSAndrew Geissler setHypervisorIPv4Gateway(asyncResp, gateway); 471d5afb2caSAndrew Geissler setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength); 472d5afb2caSAndrew Geissler } 473d5afb2caSAndrew Geissler 474*7e860f15SJohn Edward Broadbent inline void parseInterfaceData( 475d5afb2caSAndrew Geissler nlohmann::json& jsonResponse, const std::string& ifaceId, 476d5afb2caSAndrew Geissler const EthernetInterfaceData& ethData, 477d5afb2caSAndrew Geissler const boost::container::flat_set<IPv4AddressData>& ipv4Data) 478d5afb2caSAndrew Geissler { 479d5afb2caSAndrew Geissler jsonResponse["Id"] = ifaceId; 480d5afb2caSAndrew Geissler jsonResponse["@odata.id"] = 481d5afb2caSAndrew Geissler "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + ifaceId; 482d5afb2caSAndrew Geissler jsonResponse["InterfaceEnabled"] = true; 483d5afb2caSAndrew Geissler jsonResponse["MACAddress"] = ethData.mac_address; 484d5afb2caSAndrew Geissler 485d5afb2caSAndrew Geissler jsonResponse["HostName"] = ethData.hostname; 486d5afb2caSAndrew Geissler jsonResponse["DHCPv4"]["DHCPEnabled"] = 487d5afb2caSAndrew Geissler translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 488d5afb2caSAndrew Geissler 489d5afb2caSAndrew Geissler nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 490d5afb2caSAndrew Geissler nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 491d5afb2caSAndrew Geissler ipv4Array = nlohmann::json::array(); 492d5afb2caSAndrew Geissler ipv4StaticArray = nlohmann::json::array(); 493d5afb2caSAndrew Geissler for (auto& ipv4Config : ipv4Data) 494d5afb2caSAndrew Geissler { 495d5afb2caSAndrew Geissler if (ipv4Config.isActive) 496d5afb2caSAndrew Geissler { 497d5afb2caSAndrew Geissler 498d5afb2caSAndrew Geissler ipv4Array.push_back({{"AddressOrigin", ipv4Config.origin}, 499d5afb2caSAndrew Geissler {"SubnetMask", ipv4Config.netmask}, 500d5afb2caSAndrew Geissler {"Address", ipv4Config.address}, 501d5afb2caSAndrew Geissler {"Gateway", ethData.default_gateway}}); 502d5afb2caSAndrew Geissler if (ipv4Config.origin == "Static") 503d5afb2caSAndrew Geissler { 504d5afb2caSAndrew Geissler ipv4StaticArray.push_back( 505d5afb2caSAndrew Geissler {{"AddressOrigin", ipv4Config.origin}, 506d5afb2caSAndrew Geissler {"SubnetMask", ipv4Config.netmask}, 507d5afb2caSAndrew Geissler {"Address", ipv4Config.address}, 508d5afb2caSAndrew Geissler {"Gateway", ethData.default_gateway}}); 509d5afb2caSAndrew Geissler } 510d5afb2caSAndrew Geissler } 511d5afb2caSAndrew Geissler } 512d5afb2caSAndrew Geissler } 513d5afb2caSAndrew Geissler 514*7e860f15SJohn Edward Broadbent inline void setDHCPEnabled(const std::string& ifaceId, 515*7e860f15SJohn Edward Broadbent const bool& ipv4DHCPEnabled, 5168d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 517d5afb2caSAndrew Geissler { 518*7e860f15SJohn Edward Broadbent const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); 519d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 520d5afb2caSAndrew Geissler [asyncResp](const boost::system::error_code ec) { 521d5afb2caSAndrew Geissler if (ec) 522d5afb2caSAndrew Geissler { 523d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 524d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 525d5afb2caSAndrew Geissler return; 526d5afb2caSAndrew Geissler } 527d5afb2caSAndrew Geissler }, 528d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 529d5afb2caSAndrew Geissler "/xyz/openbmc_project/network/hypervisor/" + ifaceId, 530d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 531d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled", 532d5afb2caSAndrew Geissler std::variant<std::string>{dhcp}); 533d5afb2caSAndrew Geissler 534d5afb2caSAndrew Geissler // Set the IPv4 address origin to the DHCP / Static as per the new value 535d5afb2caSAndrew Geissler // of the DHCPEnabled property 536d5afb2caSAndrew Geissler std::string origin; 537d5afb2caSAndrew Geissler if (ipv4DHCPEnabled == false) 538d5afb2caSAndrew Geissler { 539d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 540d5afb2caSAndrew Geissler } 541d5afb2caSAndrew Geissler else 542d5afb2caSAndrew Geissler { 543d5afb2caSAndrew Geissler // DHCPEnabled is set to true. Delete the current IPv4 settings 544d5afb2caSAndrew Geissler // to receive the new values from DHCP server. 545d5afb2caSAndrew Geissler deleteHypervisorIPv4(ifaceId, asyncResp); 546d5afb2caSAndrew Geissler origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 547d5afb2caSAndrew Geissler } 548d5afb2caSAndrew Geissler crow::connections::systemBus->async_method_call( 549d5afb2caSAndrew Geissler [asyncResp](const boost::system::error_code ec) { 550d5afb2caSAndrew Geissler if (ec) 551d5afb2caSAndrew Geissler { 552d5afb2caSAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 553d5afb2caSAndrew Geissler messages::internalError(asyncResp->res); 554d5afb2caSAndrew Geissler return; 555d5afb2caSAndrew Geissler } 556d5afb2caSAndrew Geissler BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set"; 557d5afb2caSAndrew Geissler }, 558d5afb2caSAndrew Geissler "xyz.openbmc_project.Settings", 559*7e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 560d5afb2caSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 561d5afb2caSAndrew Geissler "xyz.openbmc_project.Network.IP", "Origin", 562d5afb2caSAndrew Geissler std::variant<std::string>(origin)); 563d5afb2caSAndrew Geissler } 564d5afb2caSAndrew Geissler 565*7e860f15SJohn Edward Broadbent inline void handleHypervisorIPv4StaticPatch( 566*7e860f15SJohn Edward Broadbent const std::string& ifaceId, const nlohmann::json& input, 567*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 568d5afb2caSAndrew Geissler { 569*7e860f15SJohn Edward Broadbent if ((!input.is_array()) || input.empty()) 570d5afb2caSAndrew Geissler { 571*7e860f15SJohn Edward Broadbent messages::propertyValueTypeError(asyncResp->res, input.dump(), 572*7e860f15SJohn Edward Broadbent "IPv4StaticAddresses"); 573d5afb2caSAndrew Geissler return; 574d5afb2caSAndrew Geissler } 575d5afb2caSAndrew Geissler 576*7e860f15SJohn Edward Broadbent // Hypervisor considers the first IP address in the array list 577*7e860f15SJohn Edward Broadbent // as the Hypervisor's virtual management interface supports single IPv4 578*7e860f15SJohn Edward Broadbent // address 579*7e860f15SJohn Edward Broadbent const nlohmann::json& thisJson = input[0]; 580*7e860f15SJohn Edward Broadbent 581*7e860f15SJohn Edward Broadbent // For the error string 582*7e860f15SJohn Edward Broadbent std::string pathString = "IPv4StaticAddresses/1"; 583*7e860f15SJohn Edward Broadbent 584*7e860f15SJohn Edward Broadbent if (!thisJson.is_null() && !thisJson.empty()) 585*7e860f15SJohn Edward Broadbent { 586*7e860f15SJohn Edward Broadbent std::optional<std::string> address; 587*7e860f15SJohn Edward Broadbent std::optional<std::string> subnetMask; 588*7e860f15SJohn Edward Broadbent std::optional<std::string> gateway; 589*7e860f15SJohn Edward Broadbent nlohmann::json thisJsonCopy = thisJson; 590*7e860f15SJohn Edward Broadbent if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 591*7e860f15SJohn Edward Broadbent address, "SubnetMask", subnetMask, "Gateway", 592*7e860f15SJohn Edward Broadbent gateway)) 593*7e860f15SJohn Edward Broadbent { 594*7e860f15SJohn Edward Broadbent messages::propertyValueFormatError( 595*7e860f15SJohn Edward Broadbent asyncResp->res, 596*7e860f15SJohn Edward Broadbent thisJson.dump(2, ' ', true, 597*7e860f15SJohn Edward Broadbent nlohmann::json::error_handler_t::replace), 598*7e860f15SJohn Edward Broadbent pathString); 599*7e860f15SJohn Edward Broadbent return; 600*7e860f15SJohn Edward Broadbent } 601*7e860f15SJohn Edward Broadbent 602*7e860f15SJohn Edward Broadbent uint8_t prefixLength = 0; 603*7e860f15SJohn Edward Broadbent bool errorInEntry = false; 604*7e860f15SJohn Edward Broadbent if (address) 605*7e860f15SJohn Edward Broadbent { 606*7e860f15SJohn Edward Broadbent if (!ipv4VerifyIpAndGetBitcount(*address)) 607*7e860f15SJohn Edward Broadbent { 608*7e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *address, 609*7e860f15SJohn Edward Broadbent pathString + "/Address"); 610*7e860f15SJohn Edward Broadbent errorInEntry = true; 611*7e860f15SJohn Edward Broadbent } 612*7e860f15SJohn Edward Broadbent } 613*7e860f15SJohn Edward Broadbent else 614*7e860f15SJohn Edward Broadbent { 615*7e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Address"); 616*7e860f15SJohn Edward Broadbent errorInEntry = true; 617*7e860f15SJohn Edward Broadbent } 618*7e860f15SJohn Edward Broadbent 619*7e860f15SJohn Edward Broadbent if (subnetMask) 620*7e860f15SJohn Edward Broadbent { 621*7e860f15SJohn Edward Broadbent if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 622*7e860f15SJohn Edward Broadbent { 623*7e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *subnetMask, 624*7e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 625*7e860f15SJohn Edward Broadbent errorInEntry = true; 626*7e860f15SJohn Edward Broadbent } 627*7e860f15SJohn Edward Broadbent } 628*7e860f15SJohn Edward Broadbent else 629*7e860f15SJohn Edward Broadbent { 630*7e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, 631*7e860f15SJohn Edward Broadbent pathString + "/SubnetMask"); 632*7e860f15SJohn Edward Broadbent errorInEntry = true; 633*7e860f15SJohn Edward Broadbent } 634*7e860f15SJohn Edward Broadbent 635*7e860f15SJohn Edward Broadbent if (gateway) 636*7e860f15SJohn Edward Broadbent { 637*7e860f15SJohn Edward Broadbent if (!ipv4VerifyIpAndGetBitcount(*gateway)) 638*7e860f15SJohn Edward Broadbent { 639*7e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, *gateway, 640*7e860f15SJohn Edward Broadbent pathString + "/Gateway"); 641*7e860f15SJohn Edward Broadbent errorInEntry = true; 642*7e860f15SJohn Edward Broadbent } 643*7e860f15SJohn Edward Broadbent } 644*7e860f15SJohn Edward Broadbent else 645*7e860f15SJohn Edward Broadbent { 646*7e860f15SJohn Edward Broadbent messages::propertyMissing(asyncResp->res, pathString + "/Gateway"); 647*7e860f15SJohn Edward Broadbent errorInEntry = true; 648*7e860f15SJohn Edward Broadbent } 649*7e860f15SJohn Edward Broadbent 650*7e860f15SJohn Edward Broadbent if (errorInEntry) 651*7e860f15SJohn Edward Broadbent { 652*7e860f15SJohn Edward Broadbent return; 653*7e860f15SJohn Edward Broadbent } 654*7e860f15SJohn Edward Broadbent 655*7e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Calling createHypervisorIPv4 on : " << ifaceId 656*7e860f15SJohn Edward Broadbent << "," << *address; 657*7e860f15SJohn Edward Broadbent createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address, 658*7e860f15SJohn Edward Broadbent asyncResp); 659*7e860f15SJohn Edward Broadbent // Set the DHCPEnabled to false since the Static IPv4 is set 660*7e860f15SJohn Edward Broadbent setDHCPEnabled(ifaceId, false, asyncResp); 661*7e860f15SJohn Edward Broadbent } 662*7e860f15SJohn Edward Broadbent else 663*7e860f15SJohn Edward Broadbent { 664*7e860f15SJohn Edward Broadbent if (thisJson.is_null()) 665*7e860f15SJohn Edward Broadbent { 666*7e860f15SJohn Edward Broadbent deleteHypervisorIPv4(ifaceId, asyncResp); 667*7e860f15SJohn Edward Broadbent } 668*7e860f15SJohn Edward Broadbent } 669*7e860f15SJohn Edward Broadbent } 670*7e860f15SJohn Edward Broadbent 671*7e860f15SJohn Edward Broadbent inline bool isHostnameValid(const std::string& hostName) 672*7e860f15SJohn Edward Broadbent { 673*7e860f15SJohn Edward Broadbent // As per RFC 1123 674*7e860f15SJohn Edward Broadbent // Allow up to 255 characters 675*7e860f15SJohn Edward Broadbent if (hostName.length() > 255) 676*7e860f15SJohn Edward Broadbent { 677*7e860f15SJohn Edward Broadbent return false; 678*7e860f15SJohn Edward Broadbent } 679*7e860f15SJohn Edward Broadbent // Validate the regex 680*7e860f15SJohn Edward Broadbent const std::regex pattern( 681*7e860f15SJohn Edward Broadbent "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 682*7e860f15SJohn Edward Broadbent 683*7e860f15SJohn Edward Broadbent return std::regex_match(hostName, pattern); 684*7e860f15SJohn Edward Broadbent } 685*7e860f15SJohn Edward Broadbent 686*7e860f15SJohn Edward Broadbent inline void 687*7e860f15SJohn Edward Broadbent handleHostnamePatch(const std::string& hostName, 688*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 689*7e860f15SJohn Edward Broadbent { 690*7e860f15SJohn Edward Broadbent if (!isHostnameValid(hostName)) 691*7e860f15SJohn Edward Broadbent { 692*7e860f15SJohn Edward Broadbent messages::propertyValueFormatError(asyncResp->res, hostName, 693*7e860f15SJohn Edward Broadbent "HostName"); 694*7e860f15SJohn Edward Broadbent return; 695*7e860f15SJohn Edward Broadbent } 696*7e860f15SJohn Edward Broadbent 697*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["HostName"] = hostName; 698*7e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 699*7e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec) { 700*7e860f15SJohn Edward Broadbent if (ec) 701*7e860f15SJohn Edward Broadbent { 702*7e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 703*7e860f15SJohn Edward Broadbent } 704*7e860f15SJohn Edward Broadbent }, 705*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 706*7e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 707*7e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 708*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 709*7e860f15SJohn Edward Broadbent std::variant<std::string>(hostName)); 710*7e860f15SJohn Edward Broadbent } 711*7e860f15SJohn Edward Broadbent 712*7e860f15SJohn Edward Broadbent inline void 713*7e860f15SJohn Edward Broadbent setIPv4InterfaceEnabled(const std::string& ifaceId, const bool& isActive, 714*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 715*7e860f15SJohn Edward Broadbent { 716*7e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 717*7e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec) { 718*7e860f15SJohn Edward Broadbent if (ec) 719*7e860f15SJohn Edward Broadbent { 720*7e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 721*7e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 722*7e860f15SJohn Edward Broadbent return; 723*7e860f15SJohn Edward Broadbent } 724*7e860f15SJohn Edward Broadbent }, 725*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 726*7e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", 727*7e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Set", 728*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Object.Enable", "Enabled", 729*7e860f15SJohn Edward Broadbent std::variant<bool>(isActive)); 730*7e860f15SJohn Edward Broadbent } 731*7e860f15SJohn Edward Broadbent 732*7e860f15SJohn Edward Broadbent inline void requestRoutesHypervisorSystems(App& app) 733*7e860f15SJohn Edward Broadbent { 734*7e860f15SJohn Edward Broadbent /** 735*7e860f15SJohn Edward Broadbent * Hypervisor Systems derived class for delivering Computer Systems Schema. 736*7e860f15SJohn Edward Broadbent */ 737*7e860f15SJohn Edward Broadbent 738*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/") 739*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 740*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 741*7e860f15SJohn Edward Broadbent [](const crow::Request&, 742*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 743*7e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 744*7e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code ec, 745*7e860f15SJohn Edward Broadbent const std::variant<std::string>& /*hostName*/) { 746*7e860f15SJohn Edward Broadbent if (ec) 747*7e860f15SJohn Edward Broadbent { 748*7e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, "System", 749*7e860f15SJohn Edward Broadbent "hypervisor"); 750*7e860f15SJohn Edward Broadbent return; 751*7e860f15SJohn Edward Broadbent } 752*7e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "Hypervisor is available"; 753*7e860f15SJohn Edward Broadbent 754*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.type"] = 755*7e860f15SJohn Edward Broadbent "#ComputerSystem.v1_6_0.ComputerSystem"; 756*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.id"] = 757*7e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor"; 758*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = "Hypervisor"; 759*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "Hypervisor"; 760*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Id"] = "hypervisor"; 761*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = { 762*7e860f15SJohn Edward Broadbent {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 763*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["EthernetInterfaces"] = { 764*7e860f15SJohn Edward Broadbent {"@odata.id", "/redfish/v1/Systems/hypervisor/" 765*7e860f15SJohn Edward Broadbent "EthernetInterfaces"}}; 766*7e860f15SJohn Edward Broadbent getHypervisorState(asyncResp); 767*7e860f15SJohn Edward Broadbent getHypervisorActions(asyncResp); 768*7e860f15SJohn Edward Broadbent // TODO: Add "SystemType" : "hypervisor" 769*7e860f15SJohn Edward Broadbent }, 770*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Settings", 771*7e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 772*7e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "Get", 773*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.SystemConfiguration", 774*7e860f15SJohn Edward Broadbent "HostName"); 775*7e860f15SJohn Edward Broadbent }); 776*7e860f15SJohn Edward Broadbent 777*7e860f15SJohn Edward Broadbent /** 778*7e860f15SJohn Edward Broadbent * HypervisorInterfaceCollection class to handle the GET and PATCH on 779*7e860f15SJohn Edward Broadbent * Hypervisor Interface 780*7e860f15SJohn Edward Broadbent */ 781*7e860f15SJohn Edward Broadbent 782*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") 783*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 784*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 785*7e860f15SJohn Edward Broadbent [](const crow::Request&, 786*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 787*7e860f15SJohn Edward Broadbent const std::array<const char*, 1> interfaces = { 788*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Network.EthernetInterface"}; 789*7e860f15SJohn Edward Broadbent 790*7e860f15SJohn Edward Broadbent crow::connections::systemBus->async_method_call( 791*7e860f15SJohn Edward Broadbent [asyncResp](const boost::system::error_code error, 792*7e860f15SJohn Edward Broadbent const std::vector<std::string>& ifaceList) { 793*7e860f15SJohn Edward Broadbent if (error) 794*7e860f15SJohn Edward Broadbent { 795*7e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, "System", 796*7e860f15SJohn Edward Broadbent "hypervisor"); 797*7e860f15SJohn Edward Broadbent return; 798*7e860f15SJohn Edward Broadbent } 799*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.type"] = 800*7e860f15SJohn Edward Broadbent "#EthernetInterfaceCollection." 801*7e860f15SJohn Edward Broadbent "EthernetInterfaceCollection"; 802*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["@odata.id"] = 803*7e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces"; 804*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = 805*7e860f15SJohn Edward Broadbent "Hypervisor Ethernet " 806*7e860f15SJohn Edward Broadbent "Interface Collection"; 807*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = 808*7e860f15SJohn Edward Broadbent "Collection of Virtual Management " 809*7e860f15SJohn Edward Broadbent "Interfaces for the hypervisor"; 810*7e860f15SJohn Edward Broadbent 811*7e860f15SJohn Edward Broadbent nlohmann::json& ifaceArray = 812*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 813*7e860f15SJohn Edward Broadbent ifaceArray = nlohmann::json::array(); 814*7e860f15SJohn Edward Broadbent for (const std::string& iface : ifaceList) 815*7e860f15SJohn Edward Broadbent { 816*7e860f15SJohn Edward Broadbent sdbusplus::message::object_path path(iface); 817*7e860f15SJohn Edward Broadbent std::string name = path.filename(); 818*7e860f15SJohn Edward Broadbent if (name.empty()) 819*7e860f15SJohn Edward Broadbent { 820*7e860f15SJohn Edward Broadbent continue; 821*7e860f15SJohn Edward Broadbent } 822*7e860f15SJohn Edward Broadbent 823*7e860f15SJohn Edward Broadbent ifaceArray.push_back( 824*7e860f15SJohn Edward Broadbent {{"@odata.id", "/redfish/v1/Systems/hypervisor/" 825*7e860f15SJohn Edward Broadbent "EthernetInterfaces/" + 826*7e860f15SJohn Edward Broadbent name}}); 827*7e860f15SJohn Edward Broadbent } 828*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members@odata.count"] = 829*7e860f15SJohn Edward Broadbent ifaceArray.size(); 830*7e860f15SJohn Edward Broadbent }, 831*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.ObjectMapper", 832*7e860f15SJohn Edward Broadbent "/xyz/openbmc_project/object_mapper", 833*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 834*7e860f15SJohn Edward Broadbent "/xyz/openbmc_project/network/hypervisor", 0, interfaces); 835*7e860f15SJohn Edward Broadbent }); 836*7e860f15SJohn Edward Broadbent 837*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 838*7e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 839*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 840*7e860f15SJohn Edward Broadbent .methods( 841*7e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request&, 842*7e860f15SJohn Edward Broadbent const std::shared_ptr< 843*7e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 844*7e860f15SJohn Edward Broadbent const std::string& id) { 845d5afb2caSAndrew Geissler getHypervisorIfaceData( 846*7e860f15SJohn Edward Broadbent id, 847*7e860f15SJohn Edward Broadbent [asyncResp, ifaceId{std::string(id)}]( 848d5afb2caSAndrew Geissler const bool& success, const EthernetInterfaceData& ethData, 849*7e860f15SJohn Edward Broadbent const boost::container::flat_set<IPv4AddressData>& 850*7e860f15SJohn Edward Broadbent ipv4Data) { 851d5afb2caSAndrew Geissler if (!success) 852d5afb2caSAndrew Geissler { 853*7e860f15SJohn Edward Broadbent messages::resourceNotFound( 854*7e860f15SJohn Edward Broadbent asyncResp->res, "EthernetInterface", ifaceId); 855d5afb2caSAndrew Geissler return; 856d5afb2caSAndrew Geissler } 857d5afb2caSAndrew Geissler asyncResp->res.jsonValue["@odata.type"] = 858d5afb2caSAndrew Geissler "#EthernetInterface.v1_5_1.EthernetInterface"; 859d5afb2caSAndrew Geissler asyncResp->res.jsonValue["Name"] = 860d5afb2caSAndrew Geissler "Hypervisor Ethernet Interface"; 861d5afb2caSAndrew Geissler asyncResp->res.jsonValue["Description"] = 862d5afb2caSAndrew Geissler "Hypervisor's Virtual Management Ethernet Interface"; 863*7e860f15SJohn Edward Broadbent parseInterfaceData(asyncResp->res.jsonValue, ifaceId, 864*7e860f15SJohn Edward Broadbent ethData, ipv4Data); 865d5afb2caSAndrew Geissler }); 866*7e860f15SJohn Edward Broadbent }); 867d5afb2caSAndrew Geissler 868*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 869*7e860f15SJohn Edward Broadbent "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") 870*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 871*7e860f15SJohn Edward Broadbent .methods( 872*7e860f15SJohn Edward Broadbent boost::beast::http::verb:: 873*7e860f15SJohn Edward Broadbent patch)([](const crow::Request& req, 874*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 875*7e860f15SJohn Edward Broadbent const std::string& ifaceId) { 876d5afb2caSAndrew Geissler std::optional<std::string> hostName; 87764face74SRavi Teja std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses; 878d5afb2caSAndrew Geissler std::optional<nlohmann::json> ipv4Addresses; 879d5afb2caSAndrew Geissler std::optional<nlohmann::json> dhcpv4; 880d5afb2caSAndrew Geissler std::optional<bool> ipv4DHCPEnabled; 881d5afb2caSAndrew Geissler 8828d1b46d7Szhanghch05 if (!json_util::readJson(req, asyncResp->res, "HostName", hostName, 883d5afb2caSAndrew Geissler "IPv4StaticAddresses", ipv4StaticAddresses, 884d5afb2caSAndrew Geissler "IPv4Addresses", ipv4Addresses, "DHCPv4", 885d5afb2caSAndrew Geissler dhcpv4)) 886d5afb2caSAndrew Geissler { 887d5afb2caSAndrew Geissler return; 888d5afb2caSAndrew Geissler } 889d5afb2caSAndrew Geissler 890d5afb2caSAndrew Geissler if (ipv4Addresses) 891d5afb2caSAndrew Geissler { 892d5afb2caSAndrew Geissler messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); 893d5afb2caSAndrew Geissler } 894d5afb2caSAndrew Geissler 895d5afb2caSAndrew Geissler if (dhcpv4) 896d5afb2caSAndrew Geissler { 8978d1b46d7Szhanghch05 if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 898d5afb2caSAndrew Geissler ipv4DHCPEnabled)) 899d5afb2caSAndrew Geissler { 900d5afb2caSAndrew Geissler return; 901d5afb2caSAndrew Geissler } 902d5afb2caSAndrew Geissler } 903d5afb2caSAndrew Geissler 904d5afb2caSAndrew Geissler getHypervisorIfaceData( 905d5afb2caSAndrew Geissler ifaceId, 906*7e860f15SJohn Edward Broadbent [asyncResp, ifaceId, hostName = std::move(hostName), 907d5afb2caSAndrew Geissler ipv4StaticAddresses = std::move(ipv4StaticAddresses), 908d5afb2caSAndrew Geissler ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)]( 909d5afb2caSAndrew Geissler const bool& success, const EthernetInterfaceData& ethData, 910d5afb2caSAndrew Geissler const boost::container::flat_set<IPv4AddressData>&) { 911d5afb2caSAndrew Geissler if (!success) 912d5afb2caSAndrew Geissler { 913*7e860f15SJohn Edward Broadbent messages::resourceNotFound( 914*7e860f15SJohn Edward Broadbent asyncResp->res, "EthernetInterface", ifaceId); 915d5afb2caSAndrew Geissler return; 916d5afb2caSAndrew Geissler } 917d5afb2caSAndrew Geissler 918d5afb2caSAndrew Geissler if (ipv4StaticAddresses) 919d5afb2caSAndrew Geissler { 920d5afb2caSAndrew Geissler const nlohmann::json& ipv4Static = *ipv4StaticAddresses; 92164face74SRavi Teja if (ipv4Static.begin() == ipv4Static.end()) 92264face74SRavi Teja { 92364face74SRavi Teja messages::propertyValueTypeError( 92464face74SRavi Teja asyncResp->res, 92564face74SRavi Teja ipv4Static.dump( 92664face74SRavi Teja 2, ' ', true, 92764face74SRavi Teja nlohmann::json::error_handler_t::replace), 92864face74SRavi Teja "IPv4StaticAddresses"); 92964face74SRavi Teja return; 93064face74SRavi Teja } 93164face74SRavi Teja 93264face74SRavi Teja // One and only one hypervisor instance supported 93364face74SRavi Teja if (ipv4Static.size() != 1) 93464face74SRavi Teja { 93564face74SRavi Teja messages::propertyValueFormatError( 93664face74SRavi Teja asyncResp->res, 93764face74SRavi Teja ipv4Static.dump( 93864face74SRavi Teja 2, ' ', true, 93964face74SRavi Teja nlohmann::json::error_handler_t::replace), 94064face74SRavi Teja "IPv4StaticAddresses"); 94164face74SRavi Teja return; 94264face74SRavi Teja } 94364face74SRavi Teja 944d5afb2caSAndrew Geissler const nlohmann::json& ipv4Json = ipv4Static[0]; 945*7e860f15SJohn Edward Broadbent // Check if the param is 'null'. If its null, it means 946*7e860f15SJohn Edward Broadbent // that user wants to delete the IP address. Deleting 947*7e860f15SJohn Edward Broadbent // the IP address is allowed only if its statically 948*7e860f15SJohn Edward Broadbent // configured. Deleting the address originated from DHCP 949*7e860f15SJohn Edward Broadbent // is not allowed. 950d5afb2caSAndrew Geissler if ((ipv4Json.is_null()) && 951*7e860f15SJohn Edward Broadbent (translateDHCPEnabledToBool(ethData.DHCPEnabled, 952*7e860f15SJohn Edward Broadbent true))) 953d5afb2caSAndrew Geissler { 954d5afb2caSAndrew Geissler BMCWEB_LOG_INFO 955d5afb2caSAndrew Geissler << "Ignoring the delete on ipv4StaticAddresses " 956d5afb2caSAndrew Geissler "as the interface is DHCP enabled"; 957d5afb2caSAndrew Geissler } 958d5afb2caSAndrew Geissler else 959d5afb2caSAndrew Geissler { 960d5afb2caSAndrew Geissler handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, 961d5afb2caSAndrew Geissler asyncResp); 962d5afb2caSAndrew Geissler } 963d5afb2caSAndrew Geissler } 964d5afb2caSAndrew Geissler 965d5afb2caSAndrew Geissler if (hostName) 966d5afb2caSAndrew Geissler { 967d5afb2caSAndrew Geissler handleHostnamePatch(*hostName, asyncResp); 968d5afb2caSAndrew Geissler } 969d5afb2caSAndrew Geissler 970d5afb2caSAndrew Geissler if (dhcpv4) 971d5afb2caSAndrew Geissler { 972d5afb2caSAndrew Geissler setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); 973d5afb2caSAndrew Geissler } 974d5afb2caSAndrew Geissler 975*7e860f15SJohn Edward Broadbent // Set this interface to disabled/inactive. This will be set 976*7e860f15SJohn Edward Broadbent // to enabled/active by the pldm once the hypervisor 977*7e860f15SJohn Edward Broadbent // consumes the updated settings from the user. 978d5afb2caSAndrew Geissler setIPv4InterfaceEnabled(ifaceId, false, asyncResp); 979d5afb2caSAndrew Geissler }); 9808d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::accepted); 981*7e860f15SJohn Edward Broadbent }); 9824fbaf64aSAndrew Geissler 983*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/ResetActionInfo/") 984*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 985*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 986*7e860f15SJohn Edward Broadbent [](const crow::Request&, 987*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9884fbaf64aSAndrew Geissler // Only return action info if hypervisor D-Bus object present 9894fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 990*7e860f15SJohn Edward Broadbent [asyncResp]( 991*7e860f15SJohn Edward Broadbent const boost::system::error_code ec, 9924fbaf64aSAndrew Geissler const std::vector<std::pair< 9934fbaf64aSAndrew Geissler std::string, std::vector<std::string>>>& objInfo) { 9944fbaf64aSAndrew Geissler if (ec) 9954fbaf64aSAndrew Geissler { 9964fbaf64aSAndrew Geissler BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 9974fbaf64aSAndrew Geissler 9984fbaf64aSAndrew Geissler // No hypervisor objects found by mapper 9994fbaf64aSAndrew Geissler if (ec.value() == boost::system::errc::io_error) 10004fbaf64aSAndrew Geissler { 1001*7e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 1002*7e860f15SJohn Edward Broadbent "hypervisor", 10034fbaf64aSAndrew Geissler "ResetActionInfo"); 10044fbaf64aSAndrew Geissler return; 10054fbaf64aSAndrew Geissler } 10064fbaf64aSAndrew Geissler 10074fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 10084fbaf64aSAndrew Geissler return; 10094fbaf64aSAndrew Geissler } 10104fbaf64aSAndrew Geissler 10114fbaf64aSAndrew Geissler // One and only one hypervisor instance supported 10124fbaf64aSAndrew Geissler if (objInfo.size() != 1) 10134fbaf64aSAndrew Geissler { 10144fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 10154fbaf64aSAndrew Geissler return; 10164fbaf64aSAndrew Geissler } 10174fbaf64aSAndrew Geissler 1018*7e860f15SJohn Edward Broadbent // The hypervisor object only support the ability to 1019*7e860f15SJohn Edward Broadbent // turn On The system object Action should be utilized 1020*7e860f15SJohn Edward Broadbent // for other operations 10214fbaf64aSAndrew Geissler asyncResp->res.jsonValue = { 10224fbaf64aSAndrew Geissler {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"}, 10234fbaf64aSAndrew Geissler {"@odata.id", 10244fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/ResetActionInfo"}, 10254fbaf64aSAndrew Geissler {"Name", "Reset Action Info"}, 10264fbaf64aSAndrew Geissler {"Id", "ResetActionInfo"}, 10274fbaf64aSAndrew Geissler {"Parameters", 10284fbaf64aSAndrew Geissler {{{"Name", "ResetType"}, 10294fbaf64aSAndrew Geissler {"Required", true}, 10304fbaf64aSAndrew Geissler {"DataType", "String"}, 10314fbaf64aSAndrew Geissler {"AllowableValues", {"On"}}}}}}; 10324fbaf64aSAndrew Geissler }, 10334fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", 10344fbaf64aSAndrew Geissler "/xyz/openbmc_project/object_mapper", 10354fbaf64aSAndrew Geissler "xyz.openbmc_project.ObjectMapper", "GetObject", 10364fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 1037*7e860f15SJohn Edward Broadbent std::array<const char*, 1>{ 1038*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.State.Host"}); 1039*7e860f15SJohn Edward Broadbent }); 10404fbaf64aSAndrew Geissler 1041*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 10424fbaf64aSAndrew Geissler "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/") 1043*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 1044*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1045*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 1046*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10474fbaf64aSAndrew Geissler std::optional<std::string> resetType; 1048*7e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "ResetType", 1049*7e860f15SJohn Edward Broadbent resetType)) 10504fbaf64aSAndrew Geissler { 10514fbaf64aSAndrew Geissler // readJson adds appropriate error to response 10524fbaf64aSAndrew Geissler return; 10534fbaf64aSAndrew Geissler } 10544fbaf64aSAndrew Geissler 10554fbaf64aSAndrew Geissler if (!resetType) 10564fbaf64aSAndrew Geissler { 10574fbaf64aSAndrew Geissler messages::actionParameterMissing( 10584fbaf64aSAndrew Geissler asyncResp->res, "ComputerSystem.Reset", "ResetType"); 10594fbaf64aSAndrew Geissler return; 10604fbaf64aSAndrew Geissler } 10614fbaf64aSAndrew Geissler 10624fbaf64aSAndrew Geissler // Hypervisor object only support On operation 10634fbaf64aSAndrew Geissler if (resetType != "On") 10644fbaf64aSAndrew Geissler { 10654fbaf64aSAndrew Geissler messages::propertyValueNotInList(asyncResp->res, *resetType, 10664fbaf64aSAndrew Geissler "ResetType"); 10674fbaf64aSAndrew Geissler return; 10684fbaf64aSAndrew Geissler } 10694fbaf64aSAndrew Geissler 1070*7e860f15SJohn Edward Broadbent std::string command = 1071*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.State.Host.Transition.On"; 10724fbaf64aSAndrew Geissler 10734fbaf64aSAndrew Geissler crow::connections::systemBus->async_method_call( 10744fbaf64aSAndrew Geissler [asyncResp, resetType](const boost::system::error_code ec) { 10754fbaf64aSAndrew Geissler if (ec) 10764fbaf64aSAndrew Geissler { 10774fbaf64aSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1078*7e860f15SJohn Edward Broadbent if (ec.value() == 1079*7e860f15SJohn Edward Broadbent boost::asio::error::invalid_argument) 10804fbaf64aSAndrew Geissler { 10814fbaf64aSAndrew Geissler messages::actionParameterNotSupported( 10824fbaf64aSAndrew Geissler asyncResp->res, *resetType, "Reset"); 10834fbaf64aSAndrew Geissler return; 10844fbaf64aSAndrew Geissler } 10854fbaf64aSAndrew Geissler 1086*7e860f15SJohn Edward Broadbent if (ec.value() == 1087*7e860f15SJohn Edward Broadbent boost::asio::error::host_unreachable) 10884fbaf64aSAndrew Geissler { 1089*7e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 1090*7e860f15SJohn Edward Broadbent "Actions", "Reset"); 10914fbaf64aSAndrew Geissler return; 10924fbaf64aSAndrew Geissler } 10934fbaf64aSAndrew Geissler 10944fbaf64aSAndrew Geissler messages::internalError(asyncResp->res); 10954fbaf64aSAndrew Geissler return; 10964fbaf64aSAndrew Geissler } 10974fbaf64aSAndrew Geissler messages::success(asyncResp->res); 10984fbaf64aSAndrew Geissler }, 10994fbaf64aSAndrew Geissler "xyz.openbmc_project.State.Hypervisor", 11004fbaf64aSAndrew Geissler "/xyz/openbmc_project/state/hypervisor0", 11014fbaf64aSAndrew Geissler "org.freedesktop.DBus.Properties", "Set", 11024fbaf64aSAndrew Geissler "xyz.openbmc_project.State.Host", "RequestedHostTransition", 11034fbaf64aSAndrew Geissler std::variant<std::string>{std::move(command)}); 1104*7e860f15SJohn Edward Broadbent }); 11054fbaf64aSAndrew Geissler } 1106d5afb2caSAndrew Geissler } // namespace redfish 1107