blob: 21efbd5b032fbb379a6e20f75ca7c1bef7e6d269 [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>
26 void get_all_software_inventory_data(CallbackFunc &&callback) {
27 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) {
34
35 std::vector<boost::container::flat_map<std::string, std::string>>
36 output;
37
38 if (error_code) {
39 // Something wrong on DBus, the error_code is not important at this
40 // moment, just return success=false, and empty output. Since size
41 // of vector may vary depending on information from Entity Manager,
42 // and empty output could not be treated same way as error.
43 callback(false, output);
44 return;
45 }
46
47 for (auto &obj : subtree) {
48 const std::vector<std::pair<std::string, std::vector<std::string>>>
49 &connectionNames = obj.second;
50
51 const std::string connectionName = connectionNames[0].first;
52
53 crow::connections::system_bus->async_method_call(
54 [&](const boost::system::error_code error_code,
55 const std::vector<std::pair<std::string, VariantType>>
56 &propertiesList) {
57 for (auto &property : propertiesList) {
58 boost::container::flat_map<std::string, std::string>
59 single_sw_item_properties;
60 single_sw_item_properties[property.first] =
61 *(mapbox::get_ptr<const std::string>(property.second));
62 output.emplace_back(single_sw_item_properties);
63 }
64 },
65 connectionName, obj.first, "org.freedesktop.DBus.Properties",
66 "GetAll", "xyz.openbmc_project.Software.Version");
67 // Finally make a callback with usefull data
68 callback(true, output);
69 }
70 },
71 "xyz.openbmc_project.ObjectMapper",
72 "/xyz/openbmc_project/object_mapper",
73 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
74 "/xyz/openbmc_project/software", int32_t(0),
75 std::array<const char *, 1>{"xyz.openbmc_project.Software.Version"});
76 }
77 /*
78 * Function that retrieves all SoftwareInventory available through
79 * Software.BMC.Updater.
80 * @param callback a function that shall be called to convert Dbus output into
81 * JSON.
82 */
83 template <typename CallbackFunc>
84 void get_software_inventory_list(CallbackFunc &&callback) {
85 get_all_software_inventory_data(
86 [callback](
87 const bool &success,
88 const std::vector<
89 boost::container::flat_map<std::string, std::string>> &output) {
90 std::vector<std::string> sw_inv_list;
91 for (auto &i : output) {
92 boost::container::flat_map<std::string, std::string>::const_iterator
93 p = i.find("Purpose");
94 if ((p != i.end())) {
95 const std::string &sw_inv_purpose =
96 boost::get<std::string>(p->second);
97 std::size_t last_pos = sw_inv_purpose.rfind(".");
98 if (last_pos != std::string::npos) {
99 // and put it into output vector.
100 sw_inv_list.emplace_back(sw_inv_purpose.substr(last_pos + 1));
101 }
102 }
103 }
104 callback(true, sw_inv_list);
105 });
106 };
107
108 template <typename CallbackFunc>
109 void get_software_inventory_data(const std::string &res_name,
110 CallbackFunc &&callback) {
111 get_all_software_inventory_data(
112 [res_name, callback](
113 const bool &success,
114 const std::vector<
115 boost::container::flat_map<std::string, std::string>> &output) {
116 for (auto &i : output) {
117 boost::container::flat_map<std::string, std::string>::const_iterator
118 p = i.find("Purpose");
119 // Find the one with Purpose matching res_name
120 if ((p != i.end()) &&
121 boost::ends_with(boost::get<std::string>(p->second),
122 "." + res_name)) {
123 callback(true, i);
124 }
125 }
126 });
127 }
128};
129
130class UpdateService : public Node {
131 public:
132 UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/") {
133 Node::json["@odata.type"] = "#UpdateService.v1_2_0.UpdateService";
134 Node::json["@odata.id"] = "/redfish/v1/UpdateService";
135 Node::json["@odata.context"] =
136 "/redfish/v1/$metadata#UpdateService.UpdateService";
137 Node::json["Id"] = "UpdateService";
138 Node::json["Description"] = "Service for Software Update";
139 Node::json["Name"] = "Update Service";
140 Node::json["ServiceEnabled"] = true; // UpdateService cannot be disabled
141 Node::json["SoftwareInventory"] = {
142 {"@odata.id", "/redfish/v1/UpdateService/SoftwareInventory"}};
143
144 entityPrivileges = {
145 {boost::beast::http::verb::get, {{"Login"}}},
146 {boost::beast::http::verb::head, {{"Login"}}},
147 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
148 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
149 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
150 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
151 }
152
153 private:
154 void doGet(crow::response &res, const crow::request &req,
155 const std::vector<std::string> &params) override {
156 res.json_value = Node::json;
157 res.end();
158 }
159};
160
161class SoftwareInventoryCollection : public Node {
162 public:
163 /*
164 * Default Constructor
165 */
166 template <typename CrowApp>
167 SoftwareInventoryCollection(CrowApp &app)
168 : Node(app, "/redfish/v1/UpdateService/SoftwareInventory/") {
169 Node::json["@odata.type"] =
170 "#SoftwareInventoryCollection.SoftwareInventoryCollection";
171 Node::json["@odata.id"] = "/redfish/v1/UpdateService/SoftwareInventory";
172 Node::json["@odata.context"] =
173 "/redfish/v1/"
174 "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
175 Node::json["Name"] = "Software Inventory Collection";
176
177 entityPrivileges = {
178 {boost::beast::http::verb::get, {{"Login"}}},
179 {boost::beast::http::verb::head, {{"Login"}}},
180 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
181 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
182 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
183 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
184 }
185
186 private:
187 /**
188 * Functions triggers appropriate requests on DBus
189 */
190 void doGet(crow::response &res, const crow::request &req,
191 const std::vector<std::string> &params) override {
192 res.json_value = Node::json;
193 // Get sw inventory list, and call the below callback for JSON preparation
194 software_inventory_provider.get_software_inventory_list(
195 [&](const bool &success, const std::vector<std::string> &output) {
196
197 if (success) {
198 // ... prepare json array with appropriate @odata.id links
199 nlohmann::json sw_inventory_array = nlohmann::json::array();
200 for (const std::string &sw_item : output) {
201 sw_inventory_array.push_back(
202 {{"@odata.id",
203 "/redfish/v1/UpdateService/SoftwareInventory/" + sw_item}});
204 }
205 // Then attach members, count size and return
206
207 Node::json["Members"] = sw_inventory_array;
208 Node::json["Members@odata.count"] = sw_inventory_array.size();
209 res.json_value = Node::json;
210 } else {
211 // ... otherwise, return INTERNALL ERROR
212 res.result(boost::beast::http::status::internal_server_error);
213 }
214 res.end();
215 });
216 res.end();
217 }
218 OnDemandSoftwareInventoryProvider software_inventory_provider;
219};
220/**
221 * Chassis override class for delivering Chassis Schema
222 */
223class SoftwareInventory : public Node {
224 public:
225 /*
226 * Default Constructor
227 */
228 template <typename CrowApp>
229 SoftwareInventory(CrowApp &app)
230 : Node(app, "/redfish/v1/UpdateService/SoftwareInventory/<str>/",
231 std::string()) {
232 Node::json["@odata.type"] = "#SoftwareInventory.v1_1_0.SoftwareInventory";
233 Node::json["@odata.id"] = "/redfish/v1/UpdateService/SoftwareInventory";
234 Node::json["@odata.context"] =
235 "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
236 Node::json["Name"] = "Software Inventory";
237 Node::json["Status"] = "OK"; // TODO
238 Node::json["Updateable"] = "No";
239
240 entityPrivileges = {
241 {boost::beast::http::verb::get, {{"Login"}}},
242 {boost::beast::http::verb::head, {{"Login"}}},
243 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
244 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
245 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
246 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
247 }
248
249 private:
250 /**
251 * Functions triggers appropriate requests on DBus
252 */
253 void doGet(crow::response &res, const crow::request &req,
254 const std::vector<std::string> &params) override {
255 if (params.size() != 1) {
256 res.result(boost::beast::http::status::internal_server_error);
257 res.end();
258 return;
259 }
260 const std::string &sw_id = params[0];
261 software_inventory_provider.get_software_inventory_data(
262 sw_id, [&, id{std::string(sw_id)} ](
263 const bool &success,
264 const boost::container::flat_map<std::string, std::string>
265 &output) {
266 res.json_value = Node::json;
267 // If success...
268 if (success) {
269 // prepare all the schema required fields.
270 res.json_value["@odata.id"] =
271 "/redfish/v1/UpdateService/SoftwareInventory/" + id;
272 // also the one from dbus
273 boost::container::flat_map<std::string, std::string>::const_iterator
274 it = output.find("Version");
275 res.json_value["Version"] = boost::get<std::string>(it->second);
276
277 res.json_value["Id"] = id;
278 // prepare respond, and send
279 } else {
280 res.result(boost::beast::http::status::not_found);
281 }
282 res.end();
283 });
284 }
285
286 OnDemandSoftwareInventoryProvider software_inventory_provider;
287};
288
289} // namespace redfish