19c310685SBorawski.Lukasz /* 29c310685SBorawski.Lukasz // Copyright (c) 2018 Intel Corporation 39c310685SBorawski.Lukasz // 49c310685SBorawski.Lukasz // Licensed under the Apache License, Version 2.0 (the "License"); 59c310685SBorawski.Lukasz // you may not use this file except in compliance with the License. 69c310685SBorawski.Lukasz // You may obtain a copy of the License at 79c310685SBorawski.Lukasz // 89c310685SBorawski.Lukasz // http://www.apache.org/licenses/LICENSE-2.0 99c310685SBorawski.Lukasz // 109c310685SBorawski.Lukasz // Unless required by applicable law or agreed to in writing, software 119c310685SBorawski.Lukasz // distributed under the License is distributed on an "AS IS" BASIS, 129c310685SBorawski.Lukasz // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139c310685SBorawski.Lukasz // See the License for the specific language governing permissions and 149c310685SBorawski.Lukasz // limitations under the License. 159c310685SBorawski.Lukasz */ 169c310685SBorawski.Lukasz #pragma once 179c310685SBorawski.Lukasz 189c310685SBorawski.Lukasz #include "node.hpp" 199c310685SBorawski.Lukasz 205b4aa86bSJames Feist #include <boost/algorithm/string/replace.hpp> 215b4aa86bSJames Feist #include <dbus_utility.hpp> 225b4aa86bSJames Feist 231abe55efSEd Tanous namespace redfish 241abe55efSEd Tanous { 255b4aa86bSJames Feist static constexpr const char* objectManagerIface = 265b4aa86bSJames Feist "org.freedesktop.DBus.ObjectManager"; 275b4aa86bSJames Feist static constexpr const char* pidConfigurationIface = 285b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid"; 295b4aa86bSJames Feist static constexpr const char* pidZoneConfigurationIface = 305b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid.Zone"; 319c310685SBorawski.Lukasz 325b4aa86bSJames Feist static void asyncPopulatePid(const std::string& connection, 335b4aa86bSJames Feist const std::string& path, 345b4aa86bSJames Feist std::shared_ptr<AsyncResp> asyncResp) 355b4aa86bSJames Feist { 365b4aa86bSJames Feist 375b4aa86bSJames Feist crow::connections::systemBus->async_method_call( 385b4aa86bSJames Feist [asyncResp](const boost::system::error_code ec, 395b4aa86bSJames Feist const dbus::utility::ManagedObjectType& managedObj) { 405b4aa86bSJames Feist if (ec) 415b4aa86bSJames Feist { 425b4aa86bSJames Feist BMCWEB_LOG_ERROR << ec; 435b4aa86bSJames Feist asyncResp->res.jsonValue.clear(); 44*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 455b4aa86bSJames Feist return; 465b4aa86bSJames Feist } 475b4aa86bSJames Feist nlohmann::json& configRoot = 485b4aa86bSJames Feist asyncResp->res.jsonValue["Oem"]["OpenBmc"]["Fan"]; 495b4aa86bSJames Feist nlohmann::json& fans = configRoot["FanControllers"]; 505b4aa86bSJames Feist fans["@odata.type"] = "#OemManager.FanControllers"; 515b4aa86bSJames Feist fans["@odata.context"] = 525b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.FanControllers"; 535b4aa86bSJames Feist fans["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc/" 545b4aa86bSJames Feist "Fan/FanControllers"; 555b4aa86bSJames Feist 565b4aa86bSJames Feist nlohmann::json& pids = configRoot["PidControllers"]; 575b4aa86bSJames Feist pids["@odata.type"] = "#OemManager.PidControllers"; 585b4aa86bSJames Feist pids["@odata.context"] = 595b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.PidControllers"; 605b4aa86bSJames Feist pids["@odata.id"] = 615b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/PidControllers"; 625b4aa86bSJames Feist 635b4aa86bSJames Feist nlohmann::json& zones = configRoot["FanZones"]; 645b4aa86bSJames Feist zones["@odata.id"] = 655b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones"; 665b4aa86bSJames Feist zones["@odata.type"] = "#OemManager.FanZones"; 675b4aa86bSJames Feist zones["@odata.context"] = 685b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.FanZones"; 695b4aa86bSJames Feist configRoot["@odata.id"] = 705b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan"; 715b4aa86bSJames Feist configRoot["@odata.type"] = "#OemManager.Fan"; 725b4aa86bSJames Feist configRoot["@odata.context"] = 735b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.Fan"; 745b4aa86bSJames Feist 755b4aa86bSJames Feist bool propertyError = false; 765b4aa86bSJames Feist for (const auto& pathPair : managedObj) 775b4aa86bSJames Feist { 785b4aa86bSJames Feist for (const auto& intfPair : pathPair.second) 795b4aa86bSJames Feist { 805b4aa86bSJames Feist if (intfPair.first != pidConfigurationIface && 815b4aa86bSJames Feist intfPair.first != pidZoneConfigurationIface) 825b4aa86bSJames Feist { 835b4aa86bSJames Feist continue; 845b4aa86bSJames Feist } 855b4aa86bSJames Feist auto findName = intfPair.second.find("Name"); 865b4aa86bSJames Feist if (findName == intfPair.second.end()) 875b4aa86bSJames Feist { 885b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Pid Field missing Name"; 89*f12894f8SJason M. Bills messages::internalError(asyncResp->res, "Name"); 905b4aa86bSJames Feist return; 915b4aa86bSJames Feist } 925b4aa86bSJames Feist const std::string* namePtr = 935b4aa86bSJames Feist mapbox::getPtr<const std::string>(findName->second); 945b4aa86bSJames Feist if (namePtr == nullptr) 955b4aa86bSJames Feist { 965b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Pid Name Field illegal"; 975b4aa86bSJames Feist return; 985b4aa86bSJames Feist } 995b4aa86bSJames Feist 1005b4aa86bSJames Feist std::string name = *namePtr; 1015b4aa86bSJames Feist dbus::utility::escapePathForDbus(name); 1025b4aa86bSJames Feist if (intfPair.first == pidZoneConfigurationIface) 1035b4aa86bSJames Feist { 1045b4aa86bSJames Feist std::string chassis; 1055b4aa86bSJames Feist if (!dbus::utility::getNthStringFromPath( 1065b4aa86bSJames Feist pathPair.first.str, 5, chassis)) 1075b4aa86bSJames Feist { 1085b4aa86bSJames Feist chassis = "#IllegalValue"; 1095b4aa86bSJames Feist } 1105b4aa86bSJames Feist nlohmann::json& zone = zones[name]; 1115b4aa86bSJames Feist zone["Chassis"] = { 1125b4aa86bSJames Feist {"@odata.id", "/redfish/v1/Chassis/" + chassis}}; 1135b4aa86bSJames Feist zone["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/" 1145b4aa86bSJames Feist "OpenBmc/Fan/FanZones/" + 1155b4aa86bSJames Feist name; 1165b4aa86bSJames Feist zone["@odata.type"] = "#OemManager.FanZone"; 1175b4aa86bSJames Feist zone["@odata.context"] = 1185b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.FanZone"; 1195b4aa86bSJames Feist } 1205b4aa86bSJames Feist 1215b4aa86bSJames Feist for (const auto& propertyPair : intfPair.second) 1225b4aa86bSJames Feist { 1235b4aa86bSJames Feist if (propertyPair.first == "Type" || 1245b4aa86bSJames Feist propertyPair.first == "Class" || 1255b4aa86bSJames Feist propertyPair.first == "Name") 1265b4aa86bSJames Feist { 1275b4aa86bSJames Feist continue; 1285b4aa86bSJames Feist } 1295b4aa86bSJames Feist 1305b4aa86bSJames Feist // zones 1315b4aa86bSJames Feist if (intfPair.first == pidZoneConfigurationIface) 1325b4aa86bSJames Feist { 1335b4aa86bSJames Feist const double* ptr = mapbox::getPtr<const double>( 1345b4aa86bSJames Feist propertyPair.second); 1355b4aa86bSJames Feist if (ptr == nullptr) 1365b4aa86bSJames Feist { 1375b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Field Illegal " 1385b4aa86bSJames Feist << propertyPair.first; 139*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1405b4aa86bSJames Feist return; 1415b4aa86bSJames Feist } 1425b4aa86bSJames Feist zones[name][propertyPair.first] = *ptr; 1435b4aa86bSJames Feist } 1445b4aa86bSJames Feist 1455b4aa86bSJames Feist // pid and fans are off the same configuration 1465b4aa86bSJames Feist if (intfPair.first == pidConfigurationIface) 1475b4aa86bSJames Feist { 1485b4aa86bSJames Feist const std::string* classPtr = nullptr; 1495b4aa86bSJames Feist auto findClass = intfPair.second.find("Class"); 1505b4aa86bSJames Feist if (findClass != intfPair.second.end()) 1515b4aa86bSJames Feist { 1525b4aa86bSJames Feist classPtr = mapbox::getPtr<const std::string>( 1535b4aa86bSJames Feist findClass->second); 1545b4aa86bSJames Feist } 1555b4aa86bSJames Feist if (classPtr == nullptr) 1565b4aa86bSJames Feist { 1575b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Pid Class Field illegal"; 158*f12894f8SJason M. Bills messages::internalError(asyncResp->res, 159*f12894f8SJason M. Bills "Class"); 1605b4aa86bSJames Feist return; 1615b4aa86bSJames Feist } 1625b4aa86bSJames Feist bool isFan = *classPtr == "fan"; 1635b4aa86bSJames Feist nlohmann::json& element = 1645b4aa86bSJames Feist isFan ? fans[name] : pids[name]; 1655b4aa86bSJames Feist if (isFan) 1665b4aa86bSJames Feist { 1675b4aa86bSJames Feist element["@odata.id"] = 1685b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/" 1695b4aa86bSJames Feist "OpenBmc/Fan/FanControllers/" + 1705b4aa86bSJames Feist std::string(name); 1715b4aa86bSJames Feist element["@odata.type"] = 1725b4aa86bSJames Feist "#OemManager.FanController"; 1735b4aa86bSJames Feist 1745b4aa86bSJames Feist element["@odata.context"] = 1755b4aa86bSJames Feist "/redfish/v1/" 1765b4aa86bSJames Feist "$metadata#OemManager.FanController"; 1775b4aa86bSJames Feist } 1785b4aa86bSJames Feist else 1795b4aa86bSJames Feist { 1805b4aa86bSJames Feist element["@odata.id"] = 1815b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/" 1825b4aa86bSJames Feist "OpenBmc/Fan/PidControllers/" + 1835b4aa86bSJames Feist std::string(name); 1845b4aa86bSJames Feist element["@odata.type"] = 1855b4aa86bSJames Feist "#OemManager.PidController"; 1865b4aa86bSJames Feist element["@odata.context"] = 1875b4aa86bSJames Feist "/redfish/v1/$metadata" 1885b4aa86bSJames Feist "#OemManager.PidController"; 1895b4aa86bSJames Feist } 1905b4aa86bSJames Feist 1915b4aa86bSJames Feist if (propertyPair.first == "Zones") 1925b4aa86bSJames Feist { 1935b4aa86bSJames Feist const std::vector<std::string>* inputs = 1945b4aa86bSJames Feist mapbox::getPtr< 1955b4aa86bSJames Feist const std::vector<std::string>>( 1965b4aa86bSJames Feist propertyPair.second); 1975b4aa86bSJames Feist 1985b4aa86bSJames Feist if (inputs == nullptr) 1995b4aa86bSJames Feist { 2005b4aa86bSJames Feist BMCWEB_LOG_ERROR 2015b4aa86bSJames Feist << "Zones Pid Field Illegal"; 202*f12894f8SJason M. Bills messages::internalError(asyncResp->res, 203*f12894f8SJason M. Bills "Zones"); 2045b4aa86bSJames Feist return; 2055b4aa86bSJames Feist } 2065b4aa86bSJames Feist auto& data = element[propertyPair.first]; 2075b4aa86bSJames Feist data = nlohmann::json::array(); 2085b4aa86bSJames Feist for (std::string itemCopy : *inputs) 2095b4aa86bSJames Feist { 2105b4aa86bSJames Feist dbus::utility::escapePathForDbus(itemCopy); 2115b4aa86bSJames Feist data.push_back( 2125b4aa86bSJames Feist {{"@odata.id", 2135b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/" 2145b4aa86bSJames Feist "OpenBmc/Fan/FanZones/" + 2155b4aa86bSJames Feist itemCopy}}); 2165b4aa86bSJames Feist } 2175b4aa86bSJames Feist } 2185b4aa86bSJames Feist // todo(james): may never happen, but this 2195b4aa86bSJames Feist // assumes configuration data referenced in the 2205b4aa86bSJames Feist // PID config is provided by the same daemon, we 2215b4aa86bSJames Feist // could add another loop to cover all cases, 2225b4aa86bSJames Feist // but I'm okay kicking this can down the road a 2235b4aa86bSJames Feist // bit 2245b4aa86bSJames Feist 2255b4aa86bSJames Feist else if (propertyPair.first == "Inputs" || 2265b4aa86bSJames Feist propertyPair.first == "Outputs") 2275b4aa86bSJames Feist { 2285b4aa86bSJames Feist auto& data = element[propertyPair.first]; 2295b4aa86bSJames Feist const std::vector<std::string>* inputs = 2305b4aa86bSJames Feist mapbox::getPtr< 2315b4aa86bSJames Feist const std::vector<std::string>>( 2325b4aa86bSJames Feist propertyPair.second); 2335b4aa86bSJames Feist 2345b4aa86bSJames Feist if (inputs == nullptr) 2355b4aa86bSJames Feist { 2365b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Field Illegal " 2375b4aa86bSJames Feist << propertyPair.first; 238*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2395b4aa86bSJames Feist return; 2405b4aa86bSJames Feist } 2415b4aa86bSJames Feist data = *inputs; 2425b4aa86bSJames Feist } // doubles 2435b4aa86bSJames Feist else if (propertyPair.first == 2445b4aa86bSJames Feist "FFGainCoefficient" || 2455b4aa86bSJames Feist propertyPair.first == "FFOffCoefficient" || 2465b4aa86bSJames Feist propertyPair.first == "ICoefficient" || 2475b4aa86bSJames Feist propertyPair.first == "ILimitMax" || 2485b4aa86bSJames Feist propertyPair.first == "ILimitMin" || 2495b4aa86bSJames Feist propertyPair.first == "OutLimitMax" || 2505b4aa86bSJames Feist propertyPair.first == "OutLimitMin" || 2515b4aa86bSJames Feist propertyPair.first == "PCoefficient" || 2525b4aa86bSJames Feist propertyPair.first == "SlewNeg" || 2535b4aa86bSJames Feist propertyPair.first == "SlewPos") 2545b4aa86bSJames Feist { 2555b4aa86bSJames Feist const double* ptr = 2565b4aa86bSJames Feist mapbox::getPtr<const double>( 2575b4aa86bSJames Feist propertyPair.second); 2585b4aa86bSJames Feist if (ptr == nullptr) 2595b4aa86bSJames Feist { 2605b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Field Illegal " 2615b4aa86bSJames Feist << propertyPair.first; 262*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2635b4aa86bSJames Feist return; 2645b4aa86bSJames Feist } 2655b4aa86bSJames Feist element[propertyPair.first] = *ptr; 2665b4aa86bSJames Feist } 2675b4aa86bSJames Feist } 2685b4aa86bSJames Feist } 2695b4aa86bSJames Feist } 2705b4aa86bSJames Feist } 2715b4aa86bSJames Feist }, 2725b4aa86bSJames Feist connection, path, objectManagerIface, "GetManagedObjects"); 2735b4aa86bSJames Feist } 274ca537928SJennifer Lee 2751abe55efSEd Tanous class Manager : public Node 2761abe55efSEd Tanous { 2779c310685SBorawski.Lukasz public: 2785b4aa86bSJames Feist Manager(CrowApp& app) : Node(app, "/redfish/v1/Managers/bmc/") 2791abe55efSEd Tanous { 2805b4aa86bSJames Feist Node::json["@odata.id"] = "/redfish/v1/Managers/bmc"; 2819c310685SBorawski.Lukasz Node::json["@odata.type"] = "#Manager.v1_3_0.Manager"; 2829c310685SBorawski.Lukasz Node::json["@odata.context"] = "/redfish/v1/$metadata#Manager.Manager"; 2835b4aa86bSJames Feist Node::json["Id"] = "bmc"; 2849c310685SBorawski.Lukasz Node::json["Name"] = "OpenBmc Manager"; 2859c310685SBorawski.Lukasz Node::json["Description"] = "Baseboard Management Controller"; 2869c310685SBorawski.Lukasz Node::json["PowerState"] = "On"; 287ca537928SJennifer Lee Node::json["ManagerType"] = "BMC"; 2889c310685SBorawski.Lukasz Node::json["UUID"] = 28955c7b7a2SEd Tanous app.template getMiddleware<crow::persistent_data::Middleware>() 29055c7b7a2SEd Tanous .systemUuid; 2919c310685SBorawski.Lukasz Node::json["Model"] = "OpenBmc"; // TODO(ed), get model 292ca537928SJennifer Lee Node::json["EthernetInterfaces"] = { 2935b4aa86bSJames Feist {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces"}}; 2943ebd75f7SEd Tanous 295a434f2bdSEd Tanous entityPrivileges = { 296a434f2bdSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 297e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 298e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 299e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 300e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 301e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 3025b4aa86bSJames Feist 3035b4aa86bSJames Feist // default oem data 3045b4aa86bSJames Feist nlohmann::json& oem = Node::json["Oem"]; 3055b4aa86bSJames Feist nlohmann::json& oemOpenbmc = oem["OpenBmc"]; 3065b4aa86bSJames Feist oem["@odata.type"] = "#OemManager.Oem"; 3075b4aa86bSJames Feist oem["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem"; 3085b4aa86bSJames Feist oem["@odata.context"] = "/redfish/v1/$metadata#OemManager.Oem"; 3095b4aa86bSJames Feist oemOpenbmc["@odata.type"] = "#OemManager.OpenBmc"; 3105b4aa86bSJames Feist oemOpenbmc["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc"; 3115b4aa86bSJames Feist oemOpenbmc["@odata.context"] = 3125b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.OpenBmc"; 3139c310685SBorawski.Lukasz } 3149c310685SBorawski.Lukasz 3159c310685SBorawski.Lukasz private: 3165b4aa86bSJames Feist void getPidValues(std::shared_ptr<AsyncResp> asyncResp) 3175b4aa86bSJames Feist { 3185b4aa86bSJames Feist crow::connections::systemBus->async_method_call( 3195b4aa86bSJames Feist [asyncResp](const boost::system::error_code ec, 3205b4aa86bSJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 3215b4aa86bSJames Feist if (ec) 3225b4aa86bSJames Feist { 3235b4aa86bSJames Feist BMCWEB_LOG_ERROR << ec; 324*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 3255b4aa86bSJames Feist return; 3265b4aa86bSJames Feist } 3275b4aa86bSJames Feist 3285b4aa86bSJames Feist // create map of <connection, path to objMgr>> 3295b4aa86bSJames Feist boost::container::flat_map<std::string, std::string> 3305b4aa86bSJames Feist objectMgrPaths; 3315b4aa86bSJames Feist for (const auto& pathGroup : subtree) 3325b4aa86bSJames Feist { 3335b4aa86bSJames Feist for (const auto& connectionGroup : pathGroup.second) 3345b4aa86bSJames Feist { 3355b4aa86bSJames Feist for (const std::string& interface : 3365b4aa86bSJames Feist connectionGroup.second) 3375b4aa86bSJames Feist { 3385b4aa86bSJames Feist if (interface == objectManagerIface) 3395b4aa86bSJames Feist { 3405b4aa86bSJames Feist objectMgrPaths[connectionGroup.first] = 3415b4aa86bSJames Feist pathGroup.first; 3425b4aa86bSJames Feist } 3435b4aa86bSJames Feist // this list is alphabetical, so we 3445b4aa86bSJames Feist // should have found the objMgr by now 3455b4aa86bSJames Feist if (interface == pidConfigurationIface || 3465b4aa86bSJames Feist interface == pidZoneConfigurationIface) 3475b4aa86bSJames Feist { 3485b4aa86bSJames Feist auto findObjMgr = 3495b4aa86bSJames Feist objectMgrPaths.find(connectionGroup.first); 3505b4aa86bSJames Feist if (findObjMgr == objectMgrPaths.end()) 3515b4aa86bSJames Feist { 3525b4aa86bSJames Feist BMCWEB_LOG_DEBUG << connectionGroup.first 3535b4aa86bSJames Feist << "Has no Object Manager"; 3545b4aa86bSJames Feist continue; 3555b4aa86bSJames Feist } 3565b4aa86bSJames Feist asyncPopulatePid(findObjMgr->first, 3575b4aa86bSJames Feist findObjMgr->second, asyncResp); 3585b4aa86bSJames Feist break; 3595b4aa86bSJames Feist } 3605b4aa86bSJames Feist } 3615b4aa86bSJames Feist } 3625b4aa86bSJames Feist } 3635b4aa86bSJames Feist }, 3645b4aa86bSJames Feist "xyz.openbmc_project.ObjectMapper", 3655b4aa86bSJames Feist "/xyz/openbmc_project/object_mapper", 3665b4aa86bSJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", 0, 3675b4aa86bSJames Feist std::array<const char*, 3>{pidConfigurationIface, 3685b4aa86bSJames Feist pidZoneConfigurationIface, 3695b4aa86bSJames Feist objectManagerIface}); 3705b4aa86bSJames Feist } 3715b4aa86bSJames Feist 37255c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 3731abe55efSEd Tanous const std::vector<std::string>& params) override 3741abe55efSEd Tanous { 375ca537928SJennifer Lee std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 376ca537928SJennifer Lee asyncResp->res.jsonValue = Node::json; 377ca537928SJennifer Lee 3789c310685SBorawski.Lukasz Node::json["DateTime"] = getDateTime(); 37955c7b7a2SEd Tanous res.jsonValue = Node::json; 3805b4aa86bSJames Feist 381ca537928SJennifer Lee crow::connections::systemBus->async_method_call( 382ca537928SJennifer Lee [asyncResp](const boost::system::error_code ec, 3835b4aa86bSJames Feist const dbus::utility::ManagedObjectType& resp) { 384ca537928SJennifer Lee if (ec) 385ca537928SJennifer Lee { 386ca537928SJennifer Lee BMCWEB_LOG_ERROR << "Error while getting Software Version"; 387*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 388ca537928SJennifer Lee return; 389ca537928SJennifer Lee } 390ca537928SJennifer Lee 391ca537928SJennifer Lee for (auto& objpath : resp) 392ca537928SJennifer Lee { 393ca537928SJennifer Lee for (auto& interface : objpath.second) 394ca537928SJennifer Lee { 395ca537928SJennifer Lee // If interface is xyz.openbmc_project.Software.Version, 396ca537928SJennifer Lee // this is what we're looking for. 397ca537928SJennifer Lee if (interface.first == 398ca537928SJennifer Lee "xyz.openbmc_project.Software.Version") 399ca537928SJennifer Lee { 400ca537928SJennifer Lee // Cut out everyting until last "/", ... 401ca537928SJennifer Lee const std::string& iface_id = objpath.first; 402ca537928SJennifer Lee for (auto& property : interface.second) 403ca537928SJennifer Lee { 404ca537928SJennifer Lee if (property.first == "Version") 405ca537928SJennifer Lee { 406ca537928SJennifer Lee const std::string* value = 407ca537928SJennifer Lee mapbox::getPtr<const std::string>( 408ca537928SJennifer Lee property.second); 409ca537928SJennifer Lee if (value == nullptr) 410ca537928SJennifer Lee { 411ca537928SJennifer Lee continue; 412ca537928SJennifer Lee } 413ca537928SJennifer Lee asyncResp->res 414ca537928SJennifer Lee .jsonValue["FirmwareVersion"] = *value; 415ca537928SJennifer Lee } 416ca537928SJennifer Lee } 417ca537928SJennifer Lee } 418ca537928SJennifer Lee } 419ca537928SJennifer Lee } 420ca537928SJennifer Lee }, 421ca537928SJennifer Lee "xyz.openbmc_project.Software.BMC.Updater", 422ca537928SJennifer Lee "/xyz/openbmc_project/software", 423ca537928SJennifer Lee "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 4245b4aa86bSJames Feist getPidValues(asyncResp); 4255b4aa86bSJames Feist } 4265b4aa86bSJames Feist 4275b4aa86bSJames Feist void doPatch(crow::Response& res, const crow::Request& req, 4285b4aa86bSJames Feist const std::vector<std::string>& params) override 4295b4aa86bSJames Feist { 4309c310685SBorawski.Lukasz } 4319c310685SBorawski.Lukasz 4321abe55efSEd Tanous std::string getDateTime() const 4331abe55efSEd Tanous { 4349c310685SBorawski.Lukasz std::array<char, 128> dateTime; 4359c310685SBorawski.Lukasz std::string redfishDateTime("0000-00-00T00:00:00Z00:00"); 4369c310685SBorawski.Lukasz std::time_t time = std::time(nullptr); 4379c310685SBorawski.Lukasz 4389c310685SBorawski.Lukasz if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z", 4391abe55efSEd Tanous std::localtime(&time))) 4401abe55efSEd Tanous { 4419c310685SBorawski.Lukasz // insert the colon required by the ISO 8601 standard 4429c310685SBorawski.Lukasz redfishDateTime = std::string(dateTime.data()); 4439c310685SBorawski.Lukasz redfishDateTime.insert(redfishDateTime.end() - 2, ':'); 4449c310685SBorawski.Lukasz } 4459c310685SBorawski.Lukasz 4469c310685SBorawski.Lukasz return redfishDateTime; 4479c310685SBorawski.Lukasz } 4489c310685SBorawski.Lukasz }; 4499c310685SBorawski.Lukasz 4501abe55efSEd Tanous class ManagerCollection : public Node 4511abe55efSEd Tanous { 4529c310685SBorawski.Lukasz public: 4531abe55efSEd Tanous ManagerCollection(CrowApp& app) : Node(app, "/redfish/v1/Managers/") 4541abe55efSEd Tanous { 4559c310685SBorawski.Lukasz Node::json["@odata.id"] = "/redfish/v1/Managers"; 4569c310685SBorawski.Lukasz Node::json["@odata.type"] = "#ManagerCollection.ManagerCollection"; 4579c310685SBorawski.Lukasz Node::json["@odata.context"] = 4589c310685SBorawski.Lukasz "/redfish/v1/$metadata#ManagerCollection.ManagerCollection"; 4599c310685SBorawski.Lukasz Node::json["Name"] = "Manager Collection"; 4609c310685SBorawski.Lukasz Node::json["Members@odata.count"] = 1; 4615b4aa86bSJames Feist Node::json["Members"] = {{{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 4623ebd75f7SEd Tanous 463a434f2bdSEd Tanous entityPrivileges = { 464a434f2bdSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 465e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 466e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 467e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 468e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 469e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 4709c310685SBorawski.Lukasz } 4719c310685SBorawski.Lukasz 4729c310685SBorawski.Lukasz private: 47355c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 4741abe55efSEd Tanous const std::vector<std::string>& params) override 4751abe55efSEd Tanous { 4761abe55efSEd Tanous // Collections don't include the static data added by SubRoute because 4771abe55efSEd Tanous // it has a duplicate entry for members 47855c7b7a2SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Managers"; 47955c7b7a2SEd Tanous res.jsonValue["@odata.type"] = "#ManagerCollection.ManagerCollection"; 48055c7b7a2SEd Tanous res.jsonValue["@odata.context"] = 48155c7b7a2SEd Tanous "/redfish/v1/$metadata#ManagerCollection.ManagerCollection"; 48255c7b7a2SEd Tanous res.jsonValue["Name"] = "Manager Collection"; 48355c7b7a2SEd Tanous res.jsonValue["Members@odata.count"] = 1; 48455c7b7a2SEd Tanous res.jsonValue["Members"] = { 4855b4aa86bSJames Feist {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 4869c310685SBorawski.Lukasz res.end(); 4879c310685SBorawski.Lukasz } 4889c310685SBorawski.Lukasz }; 4899c310685SBorawski.Lukasz } // namespace redfish 490