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 20*5b4aa86bSJames Feist #include <boost/algorithm/string/replace.hpp> 21*5b4aa86bSJames Feist #include <dbus_utility.hpp> 22*5b4aa86bSJames Feist 231abe55efSEd Tanous namespace redfish 241abe55efSEd Tanous { 25*5b4aa86bSJames Feist static constexpr const char* objectManagerIface = 26*5b4aa86bSJames Feist "org.freedesktop.DBus.ObjectManager"; 27*5b4aa86bSJames Feist static constexpr const char* pidConfigurationIface = 28*5b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid"; 29*5b4aa86bSJames Feist static constexpr const char* pidZoneConfigurationIface = 30*5b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid.Zone"; 319c310685SBorawski.Lukasz 32*5b4aa86bSJames Feist static void asyncPopulatePid(const std::string& connection, 33*5b4aa86bSJames Feist const std::string& path, 34*5b4aa86bSJames Feist std::shared_ptr<AsyncResp> asyncResp) 35*5b4aa86bSJames Feist { 36*5b4aa86bSJames Feist 37*5b4aa86bSJames Feist crow::connections::systemBus->async_method_call( 38*5b4aa86bSJames Feist [asyncResp](const boost::system::error_code ec, 39*5b4aa86bSJames Feist const dbus::utility::ManagedObjectType& managedObj) { 40*5b4aa86bSJames Feist if (ec) 41*5b4aa86bSJames Feist { 42*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << ec; 43*5b4aa86bSJames Feist asyncResp->res.result( 44*5b4aa86bSJames Feist boost::beast::http::status::internal_server_error); 45*5b4aa86bSJames Feist asyncResp->res.jsonValue.clear(); 46*5b4aa86bSJames Feist return; 47*5b4aa86bSJames Feist } 48*5b4aa86bSJames Feist nlohmann::json& configRoot = 49*5b4aa86bSJames Feist asyncResp->res.jsonValue["Oem"]["OpenBmc"]["Fan"]; 50*5b4aa86bSJames Feist nlohmann::json& fans = configRoot["FanControllers"]; 51*5b4aa86bSJames Feist fans["@odata.type"] = "#OemManager.FanControllers"; 52*5b4aa86bSJames Feist fans["@odata.context"] = 53*5b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.FanControllers"; 54*5b4aa86bSJames Feist fans["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc/" 55*5b4aa86bSJames Feist "Fan/FanControllers"; 56*5b4aa86bSJames Feist 57*5b4aa86bSJames Feist nlohmann::json& pids = configRoot["PidControllers"]; 58*5b4aa86bSJames Feist pids["@odata.type"] = "#OemManager.PidControllers"; 59*5b4aa86bSJames Feist pids["@odata.context"] = 60*5b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.PidControllers"; 61*5b4aa86bSJames Feist pids["@odata.id"] = 62*5b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/PidControllers"; 63*5b4aa86bSJames Feist 64*5b4aa86bSJames Feist nlohmann::json& zones = configRoot["FanZones"]; 65*5b4aa86bSJames Feist zones["@odata.id"] = 66*5b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones"; 67*5b4aa86bSJames Feist zones["@odata.type"] = "#OemManager.FanZones"; 68*5b4aa86bSJames Feist zones["@odata.context"] = 69*5b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.FanZones"; 70*5b4aa86bSJames Feist configRoot["@odata.id"] = 71*5b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan"; 72*5b4aa86bSJames Feist configRoot["@odata.type"] = "#OemManager.Fan"; 73*5b4aa86bSJames Feist configRoot["@odata.context"] = 74*5b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.Fan"; 75*5b4aa86bSJames Feist 76*5b4aa86bSJames Feist bool propertyError = false; 77*5b4aa86bSJames Feist for (const auto& pathPair : managedObj) 78*5b4aa86bSJames Feist { 79*5b4aa86bSJames Feist for (const auto& intfPair : pathPair.second) 80*5b4aa86bSJames Feist { 81*5b4aa86bSJames Feist if (intfPair.first != pidConfigurationIface && 82*5b4aa86bSJames Feist intfPair.first != pidZoneConfigurationIface) 83*5b4aa86bSJames Feist { 84*5b4aa86bSJames Feist continue; 85*5b4aa86bSJames Feist } 86*5b4aa86bSJames Feist auto findName = intfPair.second.find("Name"); 87*5b4aa86bSJames Feist if (findName == intfPair.second.end()) 88*5b4aa86bSJames Feist { 89*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Pid Field missing Name"; 90*5b4aa86bSJames Feist asyncResp->res.result( 91*5b4aa86bSJames Feist boost::beast::http::status::internal_server_error); 92*5b4aa86bSJames Feist return; 93*5b4aa86bSJames Feist } 94*5b4aa86bSJames Feist const std::string* namePtr = 95*5b4aa86bSJames Feist mapbox::getPtr<const std::string>(findName->second); 96*5b4aa86bSJames Feist if (namePtr == nullptr) 97*5b4aa86bSJames Feist { 98*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Pid Name Field illegal"; 99*5b4aa86bSJames Feist return; 100*5b4aa86bSJames Feist } 101*5b4aa86bSJames Feist 102*5b4aa86bSJames Feist std::string name = *namePtr; 103*5b4aa86bSJames Feist dbus::utility::escapePathForDbus(name); 104*5b4aa86bSJames Feist if (intfPair.first == pidZoneConfigurationIface) 105*5b4aa86bSJames Feist { 106*5b4aa86bSJames Feist std::string chassis; 107*5b4aa86bSJames Feist if (!dbus::utility::getNthStringFromPath( 108*5b4aa86bSJames Feist pathPair.first.str, 5, chassis)) 109*5b4aa86bSJames Feist { 110*5b4aa86bSJames Feist chassis = "#IllegalValue"; 111*5b4aa86bSJames Feist } 112*5b4aa86bSJames Feist nlohmann::json& zone = zones[name]; 113*5b4aa86bSJames Feist zone["Chassis"] = { 114*5b4aa86bSJames Feist {"@odata.id", "/redfish/v1/Chassis/" + chassis}}; 115*5b4aa86bSJames Feist zone["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/" 116*5b4aa86bSJames Feist "OpenBmc/Fan/FanZones/" + 117*5b4aa86bSJames Feist name; 118*5b4aa86bSJames Feist zone["@odata.type"] = "#OemManager.FanZone"; 119*5b4aa86bSJames Feist zone["@odata.context"] = 120*5b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.FanZone"; 121*5b4aa86bSJames Feist } 122*5b4aa86bSJames Feist 123*5b4aa86bSJames Feist for (const auto& propertyPair : intfPair.second) 124*5b4aa86bSJames Feist { 125*5b4aa86bSJames Feist if (propertyPair.first == "Type" || 126*5b4aa86bSJames Feist propertyPair.first == "Class" || 127*5b4aa86bSJames Feist propertyPair.first == "Name") 128*5b4aa86bSJames Feist { 129*5b4aa86bSJames Feist continue; 130*5b4aa86bSJames Feist } 131*5b4aa86bSJames Feist 132*5b4aa86bSJames Feist // zones 133*5b4aa86bSJames Feist if (intfPair.first == pidZoneConfigurationIface) 134*5b4aa86bSJames Feist { 135*5b4aa86bSJames Feist const double* ptr = mapbox::getPtr<const double>( 136*5b4aa86bSJames Feist propertyPair.second); 137*5b4aa86bSJames Feist if (ptr == nullptr) 138*5b4aa86bSJames Feist { 139*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Field Illegal " 140*5b4aa86bSJames Feist << propertyPair.first; 141*5b4aa86bSJames Feist asyncResp->res.result( 142*5b4aa86bSJames Feist boost::beast::http::status:: 143*5b4aa86bSJames Feist internal_server_error); 144*5b4aa86bSJames Feist return; 145*5b4aa86bSJames Feist } 146*5b4aa86bSJames Feist zones[name][propertyPair.first] = *ptr; 147*5b4aa86bSJames Feist } 148*5b4aa86bSJames Feist 149*5b4aa86bSJames Feist // pid and fans are off the same configuration 150*5b4aa86bSJames Feist if (intfPair.first == pidConfigurationIface) 151*5b4aa86bSJames Feist { 152*5b4aa86bSJames Feist const std::string* classPtr = nullptr; 153*5b4aa86bSJames Feist auto findClass = intfPair.second.find("Class"); 154*5b4aa86bSJames Feist if (findClass != intfPair.second.end()) 155*5b4aa86bSJames Feist { 156*5b4aa86bSJames Feist classPtr = mapbox::getPtr<const std::string>( 157*5b4aa86bSJames Feist findClass->second); 158*5b4aa86bSJames Feist } 159*5b4aa86bSJames Feist if (classPtr == nullptr) 160*5b4aa86bSJames Feist { 161*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Pid Class Field illegal"; 162*5b4aa86bSJames Feist asyncResp->res.result( 163*5b4aa86bSJames Feist boost::beast::http::status:: 164*5b4aa86bSJames Feist internal_server_error); 165*5b4aa86bSJames Feist return; 166*5b4aa86bSJames Feist } 167*5b4aa86bSJames Feist bool isFan = *classPtr == "fan"; 168*5b4aa86bSJames Feist nlohmann::json& element = 169*5b4aa86bSJames Feist isFan ? fans[name] : pids[name]; 170*5b4aa86bSJames Feist if (isFan) 171*5b4aa86bSJames Feist { 172*5b4aa86bSJames Feist element["@odata.id"] = 173*5b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/" 174*5b4aa86bSJames Feist "OpenBmc/Fan/FanControllers/" + 175*5b4aa86bSJames Feist std::string(name); 176*5b4aa86bSJames Feist element["@odata.type"] = 177*5b4aa86bSJames Feist "#OemManager.FanController"; 178*5b4aa86bSJames Feist 179*5b4aa86bSJames Feist element["@odata.context"] = 180*5b4aa86bSJames Feist "/redfish/v1/" 181*5b4aa86bSJames Feist "$metadata#OemManager.FanController"; 182*5b4aa86bSJames Feist } 183*5b4aa86bSJames Feist else 184*5b4aa86bSJames Feist { 185*5b4aa86bSJames Feist element["@odata.id"] = 186*5b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/" 187*5b4aa86bSJames Feist "OpenBmc/Fan/PidControllers/" + 188*5b4aa86bSJames Feist std::string(name); 189*5b4aa86bSJames Feist element["@odata.type"] = 190*5b4aa86bSJames Feist "#OemManager.PidController"; 191*5b4aa86bSJames Feist element["@odata.context"] = 192*5b4aa86bSJames Feist "/redfish/v1/$metadata" 193*5b4aa86bSJames Feist "#OemManager.PidController"; 194*5b4aa86bSJames Feist } 195*5b4aa86bSJames Feist 196*5b4aa86bSJames Feist if (propertyPair.first == "Zones") 197*5b4aa86bSJames Feist { 198*5b4aa86bSJames Feist const std::vector<std::string>* inputs = 199*5b4aa86bSJames Feist mapbox::getPtr< 200*5b4aa86bSJames Feist const std::vector<std::string>>( 201*5b4aa86bSJames Feist propertyPair.second); 202*5b4aa86bSJames Feist 203*5b4aa86bSJames Feist if (inputs == nullptr) 204*5b4aa86bSJames Feist { 205*5b4aa86bSJames Feist BMCWEB_LOG_ERROR 206*5b4aa86bSJames Feist << "Zones Pid Field Illegal"; 207*5b4aa86bSJames Feist asyncResp->res.result( 208*5b4aa86bSJames Feist boost::beast::http::status:: 209*5b4aa86bSJames Feist internal_server_error); 210*5b4aa86bSJames Feist return; 211*5b4aa86bSJames Feist } 212*5b4aa86bSJames Feist auto& data = element[propertyPair.first]; 213*5b4aa86bSJames Feist data = nlohmann::json::array(); 214*5b4aa86bSJames Feist for (std::string itemCopy : *inputs) 215*5b4aa86bSJames Feist { 216*5b4aa86bSJames Feist dbus::utility::escapePathForDbus(itemCopy); 217*5b4aa86bSJames Feist data.push_back( 218*5b4aa86bSJames Feist {{"@odata.id", 219*5b4aa86bSJames Feist "/redfish/v1/Managers/bmc#/Oem/" 220*5b4aa86bSJames Feist "OpenBmc/Fan/FanZones/" + 221*5b4aa86bSJames Feist itemCopy}}); 222*5b4aa86bSJames Feist } 223*5b4aa86bSJames Feist } 224*5b4aa86bSJames Feist // todo(james): may never happen, but this 225*5b4aa86bSJames Feist // assumes configuration data referenced in the 226*5b4aa86bSJames Feist // PID config is provided by the same daemon, we 227*5b4aa86bSJames Feist // could add another loop to cover all cases, 228*5b4aa86bSJames Feist // but I'm okay kicking this can down the road a 229*5b4aa86bSJames Feist // bit 230*5b4aa86bSJames Feist 231*5b4aa86bSJames Feist else if (propertyPair.first == "Inputs" || 232*5b4aa86bSJames Feist propertyPair.first == "Outputs") 233*5b4aa86bSJames Feist { 234*5b4aa86bSJames Feist auto& data = element[propertyPair.first]; 235*5b4aa86bSJames Feist const std::vector<std::string>* inputs = 236*5b4aa86bSJames Feist mapbox::getPtr< 237*5b4aa86bSJames Feist const std::vector<std::string>>( 238*5b4aa86bSJames Feist propertyPair.second); 239*5b4aa86bSJames Feist 240*5b4aa86bSJames Feist if (inputs == nullptr) 241*5b4aa86bSJames Feist { 242*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Field Illegal " 243*5b4aa86bSJames Feist << propertyPair.first; 244*5b4aa86bSJames Feist asyncResp->res.result( 245*5b4aa86bSJames Feist boost::beast::http::status:: 246*5b4aa86bSJames Feist internal_server_error); 247*5b4aa86bSJames Feist return; 248*5b4aa86bSJames Feist } 249*5b4aa86bSJames Feist data = *inputs; 250*5b4aa86bSJames Feist } // doubles 251*5b4aa86bSJames Feist else if (propertyPair.first == 252*5b4aa86bSJames Feist "FFGainCoefficient" || 253*5b4aa86bSJames Feist propertyPair.first == "FFOffCoefficient" || 254*5b4aa86bSJames Feist propertyPair.first == "ICoefficient" || 255*5b4aa86bSJames Feist propertyPair.first == "ILimitMax" || 256*5b4aa86bSJames Feist propertyPair.first == "ILimitMin" || 257*5b4aa86bSJames Feist propertyPair.first == "OutLimitMax" || 258*5b4aa86bSJames Feist propertyPair.first == "OutLimitMin" || 259*5b4aa86bSJames Feist propertyPair.first == "PCoefficient" || 260*5b4aa86bSJames Feist propertyPair.first == "SlewNeg" || 261*5b4aa86bSJames Feist propertyPair.first == "SlewPos") 262*5b4aa86bSJames Feist { 263*5b4aa86bSJames Feist const double* ptr = 264*5b4aa86bSJames Feist mapbox::getPtr<const double>( 265*5b4aa86bSJames Feist propertyPair.second); 266*5b4aa86bSJames Feist if (ptr == nullptr) 267*5b4aa86bSJames Feist { 268*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << "Field Illegal " 269*5b4aa86bSJames Feist << propertyPair.first; 270*5b4aa86bSJames Feist asyncResp->res.result( 271*5b4aa86bSJames Feist boost::beast::http::status:: 272*5b4aa86bSJames Feist internal_server_error); 273*5b4aa86bSJames Feist return; 274*5b4aa86bSJames Feist } 275*5b4aa86bSJames Feist element[propertyPair.first] = *ptr; 276*5b4aa86bSJames Feist } 277*5b4aa86bSJames Feist } 278*5b4aa86bSJames Feist } 279*5b4aa86bSJames Feist } 280*5b4aa86bSJames Feist } 281*5b4aa86bSJames Feist }, 282*5b4aa86bSJames Feist connection, path, objectManagerIface, "GetManagedObjects"); 283*5b4aa86bSJames Feist } 284ca537928SJennifer Lee 2851abe55efSEd Tanous class Manager : public Node 2861abe55efSEd Tanous { 2879c310685SBorawski.Lukasz public: 288*5b4aa86bSJames Feist Manager(CrowApp& app) : Node(app, "/redfish/v1/Managers/bmc/") 2891abe55efSEd Tanous { 290*5b4aa86bSJames Feist Node::json["@odata.id"] = "/redfish/v1/Managers/bmc"; 2919c310685SBorawski.Lukasz Node::json["@odata.type"] = "#Manager.v1_3_0.Manager"; 2929c310685SBorawski.Lukasz Node::json["@odata.context"] = "/redfish/v1/$metadata#Manager.Manager"; 293*5b4aa86bSJames Feist Node::json["Id"] = "bmc"; 2949c310685SBorawski.Lukasz Node::json["Name"] = "OpenBmc Manager"; 2959c310685SBorawski.Lukasz Node::json["Description"] = "Baseboard Management Controller"; 2969c310685SBorawski.Lukasz Node::json["PowerState"] = "On"; 297ca537928SJennifer Lee Node::json["ManagerType"] = "BMC"; 2989c310685SBorawski.Lukasz Node::json["UUID"] = 29955c7b7a2SEd Tanous app.template getMiddleware<crow::persistent_data::Middleware>() 30055c7b7a2SEd Tanous .systemUuid; 3019c310685SBorawski.Lukasz Node::json["Model"] = "OpenBmc"; // TODO(ed), get model 302ca537928SJennifer Lee Node::json["EthernetInterfaces"] = { 303*5b4aa86bSJames Feist {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces"}}; 3043ebd75f7SEd Tanous 305a434f2bdSEd Tanous entityPrivileges = { 306a434f2bdSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 307e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 308e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 309e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 310e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 311e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 312*5b4aa86bSJames Feist 313*5b4aa86bSJames Feist // default oem data 314*5b4aa86bSJames Feist nlohmann::json& oem = Node::json["Oem"]; 315*5b4aa86bSJames Feist nlohmann::json& oemOpenbmc = oem["OpenBmc"]; 316*5b4aa86bSJames Feist oem["@odata.type"] = "#OemManager.Oem"; 317*5b4aa86bSJames Feist oem["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem"; 318*5b4aa86bSJames Feist oem["@odata.context"] = "/redfish/v1/$metadata#OemManager.Oem"; 319*5b4aa86bSJames Feist oemOpenbmc["@odata.type"] = "#OemManager.OpenBmc"; 320*5b4aa86bSJames Feist oemOpenbmc["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc"; 321*5b4aa86bSJames Feist oemOpenbmc["@odata.context"] = 322*5b4aa86bSJames Feist "/redfish/v1/$metadata#OemManager.OpenBmc"; 3239c310685SBorawski.Lukasz } 3249c310685SBorawski.Lukasz 3259c310685SBorawski.Lukasz private: 326*5b4aa86bSJames Feist void getPidValues(std::shared_ptr<AsyncResp> asyncResp) 327*5b4aa86bSJames Feist { 328*5b4aa86bSJames Feist crow::connections::systemBus->async_method_call( 329*5b4aa86bSJames Feist [asyncResp](const boost::system::error_code ec, 330*5b4aa86bSJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 331*5b4aa86bSJames Feist if (ec) 332*5b4aa86bSJames Feist { 333*5b4aa86bSJames Feist BMCWEB_LOG_ERROR << ec; 334*5b4aa86bSJames Feist asyncResp->res.result( 335*5b4aa86bSJames Feist boost::beast::http::status::internal_server_error); 336*5b4aa86bSJames Feist return; 337*5b4aa86bSJames Feist } 338*5b4aa86bSJames Feist 339*5b4aa86bSJames Feist // create map of <connection, path to objMgr>> 340*5b4aa86bSJames Feist boost::container::flat_map<std::string, std::string> 341*5b4aa86bSJames Feist objectMgrPaths; 342*5b4aa86bSJames Feist for (const auto& pathGroup : subtree) 343*5b4aa86bSJames Feist { 344*5b4aa86bSJames Feist for (const auto& connectionGroup : pathGroup.second) 345*5b4aa86bSJames Feist { 346*5b4aa86bSJames Feist for (const std::string& interface : 347*5b4aa86bSJames Feist connectionGroup.second) 348*5b4aa86bSJames Feist { 349*5b4aa86bSJames Feist if (interface == objectManagerIface) 350*5b4aa86bSJames Feist { 351*5b4aa86bSJames Feist objectMgrPaths[connectionGroup.first] = 352*5b4aa86bSJames Feist pathGroup.first; 353*5b4aa86bSJames Feist } 354*5b4aa86bSJames Feist // this list is alphabetical, so we 355*5b4aa86bSJames Feist // should have found the objMgr by now 356*5b4aa86bSJames Feist if (interface == pidConfigurationIface || 357*5b4aa86bSJames Feist interface == pidZoneConfigurationIface) 358*5b4aa86bSJames Feist { 359*5b4aa86bSJames Feist auto findObjMgr = 360*5b4aa86bSJames Feist objectMgrPaths.find(connectionGroup.first); 361*5b4aa86bSJames Feist if (findObjMgr == objectMgrPaths.end()) 362*5b4aa86bSJames Feist { 363*5b4aa86bSJames Feist BMCWEB_LOG_DEBUG << connectionGroup.first 364*5b4aa86bSJames Feist << "Has no Object Manager"; 365*5b4aa86bSJames Feist continue; 366*5b4aa86bSJames Feist } 367*5b4aa86bSJames Feist asyncPopulatePid(findObjMgr->first, 368*5b4aa86bSJames Feist findObjMgr->second, asyncResp); 369*5b4aa86bSJames Feist break; 370*5b4aa86bSJames Feist } 371*5b4aa86bSJames Feist } 372*5b4aa86bSJames Feist } 373*5b4aa86bSJames Feist } 374*5b4aa86bSJames Feist }, 375*5b4aa86bSJames Feist "xyz.openbmc_project.ObjectMapper", 376*5b4aa86bSJames Feist "/xyz/openbmc_project/object_mapper", 377*5b4aa86bSJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", 0, 378*5b4aa86bSJames Feist std::array<const char*, 3>{pidConfigurationIface, 379*5b4aa86bSJames Feist pidZoneConfigurationIface, 380*5b4aa86bSJames Feist objectManagerIface}); 381*5b4aa86bSJames Feist } 382*5b4aa86bSJames Feist 38355c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 3841abe55efSEd Tanous const std::vector<std::string>& params) override 3851abe55efSEd Tanous { 386ca537928SJennifer Lee std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 387ca537928SJennifer Lee asyncResp->res.jsonValue = Node::json; 388ca537928SJennifer Lee 3899c310685SBorawski.Lukasz Node::json["DateTime"] = getDateTime(); 39055c7b7a2SEd Tanous res.jsonValue = Node::json; 391*5b4aa86bSJames Feist 392ca537928SJennifer Lee crow::connections::systemBus->async_method_call( 393ca537928SJennifer Lee [asyncResp](const boost::system::error_code ec, 394*5b4aa86bSJames Feist const dbus::utility::ManagedObjectType& resp) { 395ca537928SJennifer Lee if (ec) 396ca537928SJennifer Lee { 397ca537928SJennifer Lee BMCWEB_LOG_ERROR << "Error while getting Software Version"; 398ca537928SJennifer Lee asyncResp->res.result( 399ca537928SJennifer Lee boost::beast::http::status::internal_server_error); 400ca537928SJennifer Lee return; 401ca537928SJennifer Lee } 402ca537928SJennifer Lee 403ca537928SJennifer Lee for (auto& objpath : resp) 404ca537928SJennifer Lee { 405ca537928SJennifer Lee for (auto& interface : objpath.second) 406ca537928SJennifer Lee { 407ca537928SJennifer Lee // If interface is xyz.openbmc_project.Software.Version, 408ca537928SJennifer Lee // this is what we're looking for. 409ca537928SJennifer Lee if (interface.first == 410ca537928SJennifer Lee "xyz.openbmc_project.Software.Version") 411ca537928SJennifer Lee { 412ca537928SJennifer Lee // Cut out everyting until last "/", ... 413ca537928SJennifer Lee const std::string& iface_id = objpath.first; 414ca537928SJennifer Lee for (auto& property : interface.second) 415ca537928SJennifer Lee { 416ca537928SJennifer Lee if (property.first == "Version") 417ca537928SJennifer Lee { 418ca537928SJennifer Lee const std::string* value = 419ca537928SJennifer Lee mapbox::getPtr<const std::string>( 420ca537928SJennifer Lee property.second); 421ca537928SJennifer Lee if (value == nullptr) 422ca537928SJennifer Lee { 423ca537928SJennifer Lee continue; 424ca537928SJennifer Lee } 425ca537928SJennifer Lee asyncResp->res 426ca537928SJennifer Lee .jsonValue["FirmwareVersion"] = *value; 427ca537928SJennifer Lee } 428ca537928SJennifer Lee } 429ca537928SJennifer Lee } 430ca537928SJennifer Lee } 431ca537928SJennifer Lee } 432ca537928SJennifer Lee }, 433ca537928SJennifer Lee "xyz.openbmc_project.Software.BMC.Updater", 434ca537928SJennifer Lee "/xyz/openbmc_project/software", 435ca537928SJennifer Lee "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 436*5b4aa86bSJames Feist getPidValues(asyncResp); 437*5b4aa86bSJames Feist } 438*5b4aa86bSJames Feist 439*5b4aa86bSJames Feist void doPatch(crow::Response& res, const crow::Request& req, 440*5b4aa86bSJames Feist const std::vector<std::string>& params) override 441*5b4aa86bSJames Feist { 4429c310685SBorawski.Lukasz } 4439c310685SBorawski.Lukasz 4441abe55efSEd Tanous std::string getDateTime() const 4451abe55efSEd Tanous { 4469c310685SBorawski.Lukasz std::array<char, 128> dateTime; 4479c310685SBorawski.Lukasz std::string redfishDateTime("0000-00-00T00:00:00Z00:00"); 4489c310685SBorawski.Lukasz std::time_t time = std::time(nullptr); 4499c310685SBorawski.Lukasz 4509c310685SBorawski.Lukasz if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z", 4511abe55efSEd Tanous std::localtime(&time))) 4521abe55efSEd Tanous { 4539c310685SBorawski.Lukasz // insert the colon required by the ISO 8601 standard 4549c310685SBorawski.Lukasz redfishDateTime = std::string(dateTime.data()); 4559c310685SBorawski.Lukasz redfishDateTime.insert(redfishDateTime.end() - 2, ':'); 4569c310685SBorawski.Lukasz } 4579c310685SBorawski.Lukasz 4589c310685SBorawski.Lukasz return redfishDateTime; 4599c310685SBorawski.Lukasz } 4609c310685SBorawski.Lukasz }; 4619c310685SBorawski.Lukasz 4621abe55efSEd Tanous class ManagerCollection : public Node 4631abe55efSEd Tanous { 4649c310685SBorawski.Lukasz public: 4651abe55efSEd Tanous ManagerCollection(CrowApp& app) : Node(app, "/redfish/v1/Managers/") 4661abe55efSEd Tanous { 4679c310685SBorawski.Lukasz Node::json["@odata.id"] = "/redfish/v1/Managers"; 4689c310685SBorawski.Lukasz Node::json["@odata.type"] = "#ManagerCollection.ManagerCollection"; 4699c310685SBorawski.Lukasz Node::json["@odata.context"] = 4709c310685SBorawski.Lukasz "/redfish/v1/$metadata#ManagerCollection.ManagerCollection"; 4719c310685SBorawski.Lukasz Node::json["Name"] = "Manager Collection"; 4729c310685SBorawski.Lukasz Node::json["Members@odata.count"] = 1; 473*5b4aa86bSJames Feist Node::json["Members"] = {{{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 4743ebd75f7SEd Tanous 475a434f2bdSEd Tanous entityPrivileges = { 476a434f2bdSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 477e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 478e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 479e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 480e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 481e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 4829c310685SBorawski.Lukasz } 4839c310685SBorawski.Lukasz 4849c310685SBorawski.Lukasz private: 48555c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 4861abe55efSEd Tanous const std::vector<std::string>& params) override 4871abe55efSEd Tanous { 4881abe55efSEd Tanous // Collections don't include the static data added by SubRoute because 4891abe55efSEd Tanous // it has a duplicate entry for members 49055c7b7a2SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Managers"; 49155c7b7a2SEd Tanous res.jsonValue["@odata.type"] = "#ManagerCollection.ManagerCollection"; 49255c7b7a2SEd Tanous res.jsonValue["@odata.context"] = 49355c7b7a2SEd Tanous "/redfish/v1/$metadata#ManagerCollection.ManagerCollection"; 49455c7b7a2SEd Tanous res.jsonValue["Name"] = "Manager Collection"; 49555c7b7a2SEd Tanous res.jsonValue["Members@odata.count"] = 1; 49655c7b7a2SEd Tanous res.jsonValue["Members"] = { 497*5b4aa86bSJames Feist {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 4989c310685SBorawski.Lukasz res.end(); 4999c310685SBorawski.Lukasz } 5009c310685SBorawski.Lukasz }; 5019c310685SBorawski.Lukasz } // namespace redfish 502