xref: /openbmc/bmcweb/features/redfish/lib/managers.hpp (revision f12894f8bd7fc26ffa16e5a89072e6c19095f866)
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