blob: de659bcc1e975d87ff5073c2a75e554d64f5d4b8 [file] [log] [blame]
Jennifer Lee729dae72018-04-24 15:59:34 -07001/*
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#include <boost/container/flat_map.hpp>
20
21namespace redfish {
22
23class OnDemandSoftwareInventoryProvider {
24 public:
25 template <typename CallbackFunc>
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070026 void get_all_software_inventory_object(CallbackFunc &&callback) {
Jennifer Lee729dae72018-04-24 15:59:34 -070027 crow::connections::system_bus->async_method_call(
28 [callback{std::move(callback)}](
29 const boost::system::error_code error_code,
30 const std::vector<std::pair<
31 std::string,
32 std::vector<std::pair<std::string, std::vector<std::string>>>>>
33 &subtree) {
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070034 CROW_LOG_DEBUG << "get all software inventory object callback...";
Jennifer Lee729dae72018-04-24 15:59:34 -070035 if (error_code) {
36 // Something wrong on DBus, the error_code is not important at this
37 // moment, just return success=false, and empty output. Since size
38 // of vector may vary depending on information from Entity Manager,
39 // and empty output could not be treated same way as error.
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070040 callback(false, subtree);
Jennifer Lee729dae72018-04-24 15:59:34 -070041 return;
42 }
43
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070044 if (subtree.empty()) {
45 CROW_LOG_DEBUG << "subtree empty";
46 callback(false, subtree);
47 } else {
48 CROW_LOG_DEBUG << "subtree has something";
49 callback(true, subtree);
Jennifer Lee729dae72018-04-24 15:59:34 -070050 }
51 },
52 "xyz.openbmc_project.ObjectMapper",
53 "/xyz/openbmc_project/object_mapper",
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070054 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
55 "/xyz/openbmc_project/software", int32_t(1),
Jennifer Lee729dae72018-04-24 15:59:34 -070056 std::array<const char *, 1>{"xyz.openbmc_project.Software.Version"});
57 }
Jennifer Lee729dae72018-04-24 15:59:34 -070058};
59
60class UpdateService : public Node {
61 public:
62 UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/") {
63 Node::json["@odata.type"] = "#UpdateService.v1_2_0.UpdateService";
64 Node::json["@odata.id"] = "/redfish/v1/UpdateService";
65 Node::json["@odata.context"] =
66 "/redfish/v1/$metadata#UpdateService.UpdateService";
67 Node::json["Id"] = "UpdateService";
68 Node::json["Description"] = "Service for Software Update";
69 Node::json["Name"] = "Update Service";
70 Node::json["ServiceEnabled"] = true; // UpdateService cannot be disabled
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070071 Node::json["FirmwareInventory"] = {
72 {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
Jennifer Lee729dae72018-04-24 15:59:34 -070073
74 entityPrivileges = {
75 {boost::beast::http::verb::get, {{"Login"}}},
76 {boost::beast::http::verb::head, {{"Login"}}},
77 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
78 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
79 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
80 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
81 }
82
83 private:
84 void doGet(crow::response &res, const crow::request &req,
85 const std::vector<std::string> &params) override {
86 res.json_value = Node::json;
87 res.end();
88 }
89};
90
91class SoftwareInventoryCollection : public Node {
92 public:
93 /*
94 * Default Constructor
95 */
96 template <typename CrowApp>
97 SoftwareInventoryCollection(CrowApp &app)
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070098 : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/") {
Jennifer Lee729dae72018-04-24 15:59:34 -070099 Node::json["@odata.type"] =
100 "#SoftwareInventoryCollection.SoftwareInventoryCollection";
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700101 Node::json["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory";
Jennifer Lee729dae72018-04-24 15:59:34 -0700102 Node::json["@odata.context"] =
103 "/redfish/v1/"
104 "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
105 Node::json["Name"] = "Software Inventory Collection";
106
107 entityPrivileges = {
108 {boost::beast::http::verb::get, {{"Login"}}},
109 {boost::beast::http::verb::head, {{"Login"}}},
110 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
111 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
112 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
113 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
114 }
115
116 private:
117 /**
118 * Functions triggers appropriate requests on DBus
119 */
120 void doGet(crow::response &res, const crow::request &req,
121 const std::vector<std::string> &params) override {
122 res.json_value = Node::json;
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700123 software_inventory_provider.get_all_software_inventory_object(
124 [&](const bool &success,
125 const std::vector<std::pair<
126 std::string,
127 std::vector<std::pair<std::string, std::vector<std::string>>>>>
128 &subtree) {
129 if (!success) {
Jennifer Lee729dae72018-04-24 15:59:34 -0700130 res.result(boost::beast::http::status::internal_server_error);
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700131 res.end();
132 return;
Jennifer Lee729dae72018-04-24 15:59:34 -0700133 }
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700134
135 if (subtree.empty()) {
136 CROW_LOG_DEBUG << "subtree empty!!";
137 res.end();
138 return;
139 }
140
141 res.json_value["Members"] = nlohmann::json::array();
142
143 for (auto &obj : subtree) {
144 const std::vector<std::pair<std::string, std::vector<std::string>>>
145 &connections = obj.second;
146
147 for (auto &conn : connections) {
148 const std::string connectionName = conn.first;
149 CROW_LOG_DEBUG << "connectionName = " << connectionName;
150 CROW_LOG_DEBUG << "obj.first = " << obj.first;
151
152 crow::connections::system_bus->async_method_call(
153 [&](const boost::system::error_code error_code,
154 const boost::container::flat_map<std::string, VariantType>
155 &propertiesList) {
156 CROW_LOG_DEBUG << "safe returned in lambda function";
157 if (error_code) {
158 res.result(
159 boost::beast::http::status::internal_server_error);
160 res.end();
161 return;
162 }
163 boost::container::flat_map<std::string,
164 VariantType>::const_iterator it =
165 propertiesList.find("Purpose");
166 const std::string &sw_inv_purpose =
167 *(mapbox::get_ptr<const std::string>(it->second));
168 std::size_t last_pos = sw_inv_purpose.rfind(".");
169 if (last_pos != std::string::npos) {
170 res.json_value["Members"].push_back(
171 {{"@odata.id",
172 "/redfish/v1/UpdateService/FirmwareInventory/" +
173 sw_inv_purpose.substr(last_pos + 1)}});
174 res.json_value["Members@odata.count"] =
175 res.json_value["Members"].size();
176 res.end();
177 }
178
179 },
180 connectionName, obj.first, "org.freedesktop.DBus.Properties",
181 "GetAll", "xyz.openbmc_project.Software.Version");
182 }
183 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700184 });
Jennifer Lee729dae72018-04-24 15:59:34 -0700185 }
186 OnDemandSoftwareInventoryProvider software_inventory_provider;
187};
188/**
189 * Chassis override class for delivering Chassis Schema
190 */
191class SoftwareInventory : public Node {
192 public:
193 /*
194 * Default Constructor
195 */
196 template <typename CrowApp>
197 SoftwareInventory(CrowApp &app)
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700198 : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
Jennifer Lee729dae72018-04-24 15:59:34 -0700199 std::string()) {
200 Node::json["@odata.type"] = "#SoftwareInventory.v1_1_0.SoftwareInventory";
Jennifer Lee729dae72018-04-24 15:59:34 -0700201 Node::json["@odata.context"] =
202 "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
203 Node::json["Name"] = "Software Inventory";
204 Node::json["Status"] = "OK"; // TODO
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700205 Node::json["Updateable"] = false;
Jennifer Lee729dae72018-04-24 15:59:34 -0700206
207 entityPrivileges = {
208 {boost::beast::http::verb::get, {{"Login"}}},
209 {boost::beast::http::verb::head, {{"Login"}}},
210 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
211 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
212 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
213 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
214 }
215
216 private:
217 /**
218 * Functions triggers appropriate requests on DBus
219 */
220 void doGet(crow::response &res, const crow::request &req,
221 const std::vector<std::string> &params) override {
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700222 res.json_value = Node::json;
223
Jennifer Lee729dae72018-04-24 15:59:34 -0700224 if (params.size() != 1) {
225 res.result(boost::beast::http::status::internal_server_error);
226 res.end();
227 return;
228 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700229
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700230 const std::string &sw_id = params[0];
231 res.json_value["@odata.id"] =
232 "/redfish/v1/UpdateService/FirmwareInventory/" + sw_id;
233 software_inventory_provider.get_all_software_inventory_object(
234 [&, id{std::string(sw_id)} ](
235 const bool &success,
236 const std::vector<std::pair<
237 std::string,
238 std::vector<std::pair<std::string, std::vector<std::string>>>>>
239 &subtree) {
240 CROW_LOG_DEBUG << "doGet callback...";
241 if (!success) {
242 res.result(boost::beast::http::status::internal_server_error);
243 res.end();
244 return;
Jennifer Lee729dae72018-04-24 15:59:34 -0700245 }
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700246
247 if (subtree.empty()) {
248 CROW_LOG_DEBUG << "subtree empty!!";
249 res.end();
250 return;
251 }
252
253 for (auto &obj : subtree) {
254 const std::vector<std::pair<std::string, std::vector<std::string>>>
255 &connections = obj.second;
256
257 for (auto &conn : connections) {
258 const std::string connectionName = conn.first;
259 CROW_LOG_DEBUG << "connectionName = " << connectionName;
260 CROW_LOG_DEBUG << "obj.first = " << obj.first;
261
262 crow::connections::system_bus->async_method_call(
263 [&, id{std::string(id)} ](
264 const boost::system::error_code error_code,
265 const boost::container::flat_map<std::string, VariantType>
266 &propertiesList) {
267 if (error_code) {
268 res.result(
269 boost::beast::http::status::internal_server_error);
270 res.end();
271 return;
272 }
273 boost::container::flat_map<std::string,
274 VariantType>::const_iterator it =
275 propertiesList.find("Purpose");
276 if (it == propertiesList.end()) {
277 CROW_LOG_DEBUG << "Can't find property \"Purpose\"!";
278 return;
279 }
280 const std::string &sw_inv_purpose =
281 *(mapbox::get_ptr<const std::string>(it->second));
282 CROW_LOG_DEBUG << "sw_inv_purpose = " << sw_inv_purpose;
283 if (boost::ends_with(sw_inv_purpose, "." + id)) {
284 it = propertiesList.find("Version");
285 if (it == propertiesList.end()) {
286 CROW_LOG_DEBUG << "Can't find property \"Version\"!";
287 return;
288 }
289 res.json_value["Version"] =
290 *(mapbox::get_ptr<const std::string>(it->second));
291 res.json_value["Id"] = id;
292 res.end();
293 }
294
295 },
296 connectionName, obj.first, "org.freedesktop.DBus.Properties",
297 "GetAll", "xyz.openbmc_project.Software.Version");
298 }
299 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700300 });
301 }
302
303 OnDemandSoftwareInventoryProvider software_inventory_provider;
304};
305
306} // namespace redfish