xref: /openbmc/bmcweb/features/redfish/lib/managers.hpp (revision 6bce33bc35e2e5bda0bbe910327c9be7d8d226e1)
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();
44f12894f8SJason 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";
89f12894f8SJason 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;
139f12894f8SJason 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";
158f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res,
159f12894f8SJason 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";
202f12894f8SJason M. Bills                                     messages::internalError(asyncResp->res,
203f12894f8SJason 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;
238f12894f8SJason 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;
262f12894f8SJason 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;
324f12894f8SJason 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;
331*6bce33bcSJames Feist                 boost::container::flat_set<std::string> calledConnections;
3325b4aa86bSJames Feist                 for (const auto& pathGroup : subtree)
3335b4aa86bSJames Feist                 {
3345b4aa86bSJames Feist                     for (const auto& connectionGroup : pathGroup.second)
3355b4aa86bSJames Feist                     {
336*6bce33bcSJames Feist                         auto findConnection =
337*6bce33bcSJames Feist                             calledConnections.find(connectionGroup.first);
338*6bce33bcSJames Feist                         if (findConnection != calledConnections.end())
339*6bce33bcSJames Feist                         {
340*6bce33bcSJames Feist                             break;
341*6bce33bcSJames Feist                         }
3425b4aa86bSJames Feist                         for (const std::string& interface :
3435b4aa86bSJames Feist                              connectionGroup.second)
3445b4aa86bSJames Feist                         {
3455b4aa86bSJames Feist                             if (interface == objectManagerIface)
3465b4aa86bSJames Feist                             {
3475b4aa86bSJames Feist                                 objectMgrPaths[connectionGroup.first] =
3485b4aa86bSJames Feist                                     pathGroup.first;
3495b4aa86bSJames Feist                             }
3505b4aa86bSJames Feist                             // this list is alphabetical, so we
3515b4aa86bSJames Feist                             // should have found the objMgr by now
3525b4aa86bSJames Feist                             if (interface == pidConfigurationIface ||
3535b4aa86bSJames Feist                                 interface == pidZoneConfigurationIface)
3545b4aa86bSJames Feist                             {
3555b4aa86bSJames Feist                                 auto findObjMgr =
3565b4aa86bSJames Feist                                     objectMgrPaths.find(connectionGroup.first);
3575b4aa86bSJames Feist                                 if (findObjMgr == objectMgrPaths.end())
3585b4aa86bSJames Feist                                 {
3595b4aa86bSJames Feist                                     BMCWEB_LOG_DEBUG << connectionGroup.first
3605b4aa86bSJames Feist                                                      << "Has no Object Manager";
3615b4aa86bSJames Feist                                     continue;
3625b4aa86bSJames Feist                                 }
363*6bce33bcSJames Feist 
364*6bce33bcSJames Feist                                 calledConnections.insert(connectionGroup.first);
365*6bce33bcSJames Feist 
3665b4aa86bSJames Feist                                 asyncPopulatePid(findObjMgr->first,
3675b4aa86bSJames Feist                                                  findObjMgr->second, asyncResp);
3685b4aa86bSJames Feist                                 break;
3695b4aa86bSJames Feist                             }
3705b4aa86bSJames Feist                         }
3715b4aa86bSJames Feist                     }
3725b4aa86bSJames Feist                 }
3735b4aa86bSJames Feist             },
3745b4aa86bSJames Feist             "xyz.openbmc_project.ObjectMapper",
3755b4aa86bSJames Feist             "/xyz/openbmc_project/object_mapper",
3765b4aa86bSJames Feist             "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", 0,
3775b4aa86bSJames Feist             std::array<const char*, 3>{pidConfigurationIface,
3785b4aa86bSJames Feist                                        pidZoneConfigurationIface,
3795b4aa86bSJames Feist                                        objectManagerIface});
3805b4aa86bSJames Feist     }
3815b4aa86bSJames Feist 
38255c7b7a2SEd Tanous     void doGet(crow::Response& res, const crow::Request& req,
3831abe55efSEd Tanous                const std::vector<std::string>& params) override
3841abe55efSEd Tanous     {
385ca537928SJennifer Lee         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
386ca537928SJennifer Lee         asyncResp->res.jsonValue = Node::json;
387ca537928SJennifer Lee 
3889c310685SBorawski.Lukasz         Node::json["DateTime"] = getDateTime();
38955c7b7a2SEd Tanous         res.jsonValue = Node::json;
3905b4aa86bSJames Feist 
391ca537928SJennifer Lee         crow::connections::systemBus->async_method_call(
392ca537928SJennifer Lee             [asyncResp](const boost::system::error_code ec,
3935b4aa86bSJames Feist                         const dbus::utility::ManagedObjectType& resp) {
394ca537928SJennifer Lee                 if (ec)
395ca537928SJennifer Lee                 {
396ca537928SJennifer Lee                     BMCWEB_LOG_ERROR << "Error while getting Software Version";
397f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
398ca537928SJennifer Lee                     return;
399ca537928SJennifer Lee                 }
400ca537928SJennifer Lee 
401ca537928SJennifer Lee                 for (auto& objpath : resp)
402ca537928SJennifer Lee                 {
403ca537928SJennifer Lee                     for (auto& interface : objpath.second)
404ca537928SJennifer Lee                     {
405ca537928SJennifer Lee                         // If interface is xyz.openbmc_project.Software.Version,
406ca537928SJennifer Lee                         // this is what we're looking for.
407ca537928SJennifer Lee                         if (interface.first ==
408ca537928SJennifer Lee                             "xyz.openbmc_project.Software.Version")
409ca537928SJennifer Lee                         {
410ca537928SJennifer Lee                             // Cut out everyting until last "/", ...
411ca537928SJennifer Lee                             const std::string& iface_id = objpath.first;
412ca537928SJennifer Lee                             for (auto& property : interface.second)
413ca537928SJennifer Lee                             {
414ca537928SJennifer Lee                                 if (property.first == "Version")
415ca537928SJennifer Lee                                 {
416ca537928SJennifer Lee                                     const std::string* value =
417ca537928SJennifer Lee                                         mapbox::getPtr<const std::string>(
418ca537928SJennifer Lee                                             property.second);
419ca537928SJennifer Lee                                     if (value == nullptr)
420ca537928SJennifer Lee                                     {
421ca537928SJennifer Lee                                         continue;
422ca537928SJennifer Lee                                     }
423ca537928SJennifer Lee                                     asyncResp->res
424ca537928SJennifer Lee                                         .jsonValue["FirmwareVersion"] = *value;
425ca537928SJennifer Lee                                 }
426ca537928SJennifer Lee                             }
427ca537928SJennifer Lee                         }
428ca537928SJennifer Lee                     }
429ca537928SJennifer Lee                 }
430ca537928SJennifer Lee             },
431ca537928SJennifer Lee             "xyz.openbmc_project.Software.BMC.Updater",
432ca537928SJennifer Lee             "/xyz/openbmc_project/software",
433ca537928SJennifer Lee             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
4345b4aa86bSJames Feist         getPidValues(asyncResp);
4355b4aa86bSJames Feist     }
4365b4aa86bSJames Feist 
4375b4aa86bSJames Feist     void doPatch(crow::Response& res, const crow::Request& req,
4385b4aa86bSJames Feist                  const std::vector<std::string>& params) override
4395b4aa86bSJames Feist     {
4409c310685SBorawski.Lukasz     }
4419c310685SBorawski.Lukasz 
4421abe55efSEd Tanous     std::string getDateTime() const
4431abe55efSEd Tanous     {
4449c310685SBorawski.Lukasz         std::array<char, 128> dateTime;
4459c310685SBorawski.Lukasz         std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
4469c310685SBorawski.Lukasz         std::time_t time = std::time(nullptr);
4479c310685SBorawski.Lukasz 
4489c310685SBorawski.Lukasz         if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
4491abe55efSEd Tanous                           std::localtime(&time)))
4501abe55efSEd Tanous         {
4519c310685SBorawski.Lukasz             // insert the colon required by the ISO 8601 standard
4529c310685SBorawski.Lukasz             redfishDateTime = std::string(dateTime.data());
4539c310685SBorawski.Lukasz             redfishDateTime.insert(redfishDateTime.end() - 2, ':');
4549c310685SBorawski.Lukasz         }
4559c310685SBorawski.Lukasz 
4569c310685SBorawski.Lukasz         return redfishDateTime;
4579c310685SBorawski.Lukasz     }
4589c310685SBorawski.Lukasz };
4599c310685SBorawski.Lukasz 
4601abe55efSEd Tanous class ManagerCollection : public Node
4611abe55efSEd Tanous {
4629c310685SBorawski.Lukasz   public:
4631abe55efSEd Tanous     ManagerCollection(CrowApp& app) : Node(app, "/redfish/v1/Managers/")
4641abe55efSEd Tanous     {
4659c310685SBorawski.Lukasz         Node::json["@odata.id"] = "/redfish/v1/Managers";
4669c310685SBorawski.Lukasz         Node::json["@odata.type"] = "#ManagerCollection.ManagerCollection";
4679c310685SBorawski.Lukasz         Node::json["@odata.context"] =
4689c310685SBorawski.Lukasz             "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
4699c310685SBorawski.Lukasz         Node::json["Name"] = "Manager Collection";
4709c310685SBorawski.Lukasz         Node::json["Members@odata.count"] = 1;
4715b4aa86bSJames Feist         Node::json["Members"] = {{{"@odata.id", "/redfish/v1/Managers/bmc"}}};
4723ebd75f7SEd Tanous 
473a434f2bdSEd Tanous         entityPrivileges = {
474a434f2bdSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
475e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
476e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
477e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
478e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
479e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
4809c310685SBorawski.Lukasz     }
4819c310685SBorawski.Lukasz 
4829c310685SBorawski.Lukasz   private:
48355c7b7a2SEd Tanous     void doGet(crow::Response& res, const crow::Request& req,
4841abe55efSEd Tanous                const std::vector<std::string>& params) override
4851abe55efSEd Tanous     {
4861abe55efSEd Tanous         // Collections don't include the static data added by SubRoute because
4871abe55efSEd Tanous         // it has a duplicate entry for members
48855c7b7a2SEd Tanous         res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
48955c7b7a2SEd Tanous         res.jsonValue["@odata.type"] = "#ManagerCollection.ManagerCollection";
49055c7b7a2SEd Tanous         res.jsonValue["@odata.context"] =
49155c7b7a2SEd Tanous             "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
49255c7b7a2SEd Tanous         res.jsonValue["Name"] = "Manager Collection";
49355c7b7a2SEd Tanous         res.jsonValue["Members@odata.count"] = 1;
49455c7b7a2SEd Tanous         res.jsonValue["Members"] = {
4955b4aa86bSJames Feist             {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
4969c310685SBorawski.Lukasz         res.end();
4979c310685SBorawski.Lukasz     }
4989c310685SBorawski.Lukasz };
4999c310685SBorawski.Lukasz } // namespace redfish
500