1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #pragma once
17 
18 #include "node.hpp"
19 
20 namespace redfish
21 {
22 
23 /**
24  * DBus types primitives for several generic DBus interfaces
25  * TODO consider move this to separate file into boost::dbus
26  */
27 using GetManagedObjectsType = boost::container::flat_map<
28     sdbusplus::message::object_path,
29     boost::container::flat_map<
30         std::string,
31         boost::container::flat_map<
32             std::string, sdbusplus::message::variant<
33                              std::string, bool, uint8_t, int16_t, uint16_t,
34                              int32_t, uint32_t, int64_t, uint64_t, double>>>>;
35 
36 class Manager : public Node
37 {
38   public:
39     Manager(CrowApp &app) : Node(app, "/redfish/v1/Managers/openbmc/")
40     {
41         Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc";
42         Node::json["@odata.type"] = "#Manager.v1_3_0.Manager";
43         Node::json["@odata.context"] = "/redfish/v1/$metadata#Manager.Manager";
44         Node::json["Id"] = "openbmc";
45         Node::json["Name"] = "OpenBmc Manager";
46         Node::json["Description"] = "Baseboard Management Controller";
47         Node::json["PowerState"] = "On";
48         Node::json["ManagerType"] = "BMC";
49         Node::json["UUID"] =
50             app.template getMiddleware<crow::persistent_data::Middleware>()
51                 .systemUuid;
52         Node::json["Model"] = "OpenBmc"; // TODO(ed), get model
53         Node::json["EthernetInterfaces"] = {
54             {"@odata.id", "/redfish/v1/Managers/openbmc/EthernetInterfaces"}};
55 
56         entityPrivileges = {
57             {boost::beast::http::verb::get, {{"Login"}}},
58             {boost::beast::http::verb::head, {{"Login"}}},
59             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
60             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
61             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
62             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
63     }
64 
65   private:
66     void doGet(crow::Response &res, const crow::Request &req,
67                const std::vector<std::string> &params) override
68     {
69         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
70         asyncResp->res.jsonValue = Node::json;
71 
72         Node::json["DateTime"] = getDateTime();
73         res.jsonValue = Node::json;
74         crow::connections::systemBus->async_method_call(
75             [asyncResp](const boost::system::error_code ec,
76                         const GetManagedObjectsType &resp) {
77                 if (ec)
78                 {
79                     BMCWEB_LOG_ERROR << "Error while getting Software Version";
80                     asyncResp->res.result(
81                         boost::beast::http::status::internal_server_error);
82                     return;
83                 }
84 
85                 for (auto &objpath : resp)
86                 {
87                     for (auto &interface : objpath.second)
88                     {
89                         // If interface is xyz.openbmc_project.Software.Version,
90                         // this is what we're looking for.
91                         if (interface.first ==
92                             "xyz.openbmc_project.Software.Version")
93                         {
94                             // Cut out everyting until last "/", ...
95                             const std::string &iface_id = objpath.first;
96                             for (auto &property : interface.second)
97                             {
98                                 if (property.first == "Version")
99                                 {
100                                     const std::string *value =
101                                         mapbox::getPtr<const std::string>(
102                                             property.second);
103                                     if (value == nullptr)
104                                     {
105                                         continue;
106                                     }
107                                     asyncResp->res
108                                         .jsonValue["FirmwareVersion"] = *value;
109                                 }
110                             }
111                         }
112                     }
113                 }
114             },
115             "xyz.openbmc_project.Software.BMC.Updater",
116             "/xyz/openbmc_project/software",
117             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
118     }
119 
120     std::string getDateTime() const
121     {
122         std::array<char, 128> dateTime;
123         std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
124         std::time_t time = std::time(nullptr);
125 
126         if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
127                           std::localtime(&time)))
128         {
129             // insert the colon required by the ISO 8601 standard
130             redfishDateTime = std::string(dateTime.data());
131             redfishDateTime.insert(redfishDateTime.end() - 2, ':');
132         }
133 
134         return redfishDateTime;
135     }
136 };
137 
138 class ManagerCollection : public Node
139 {
140   public:
141     ManagerCollection(CrowApp &app) : Node(app, "/redfish/v1/Managers/")
142     {
143         Node::json["@odata.id"] = "/redfish/v1/Managers";
144         Node::json["@odata.type"] = "#ManagerCollection.ManagerCollection";
145         Node::json["@odata.context"] =
146             "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
147         Node::json["Name"] = "Manager Collection";
148         Node::json["Members@odata.count"] = 1;
149         Node::json["Members"] = {
150             {{"@odata.id", "/redfish/v1/Managers/openbmc"}}};
151 
152         entityPrivileges = {
153             {boost::beast::http::verb::get, {{"Login"}}},
154             {boost::beast::http::verb::head, {{"Login"}}},
155             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
156             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
157             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
158             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
159     }
160 
161   private:
162     void doGet(crow::Response &res, const crow::Request &req,
163                const std::vector<std::string> &params) override
164     {
165         // Collections don't include the static data added by SubRoute because
166         // it has a duplicate entry for members
167         res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
168         res.jsonValue["@odata.type"] = "#ManagerCollection.ManagerCollection";
169         res.jsonValue["@odata.context"] =
170             "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
171         res.jsonValue["Name"] = "Manager Collection";
172         res.jsonValue["Members@odata.count"] = 1;
173         res.jsonValue["Members"] = {
174             {{"@odata.id", "/redfish/v1/Managers/openbmc"}}};
175         res.end();
176     }
177 };
178 
179 } // namespace redfish
180