blob: 8daead763215cc9ce5322ccea18084827eb40095 [file] [log] [blame]
Nikhil Potadee56c7b72019-08-23 16:35:26 -07001/*
2// Copyright (c) 2019 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
20namespace redfish
21{
22class StorageCollection : public Node
23{
24 public:
25 StorageCollection(CrowApp &app) :
26 Node(app, "/redfish/v1/Systems/system/Storage/")
27 {
28 entityPrivileges = {
29 {boost::beast::http::verb::get, {{"Login"}}},
30 {boost::beast::http::verb::head, {{"Login"}}},
31 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
32 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
33 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
34 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
35 }
36
37 private:
38 void doGet(crow::Response &res, const crow::Request &req,
39 const std::vector<std::string> &params) override
40 {
41 res.jsonValue["@odata.type"] = "#StorageCollection.StorageCollection";
42 res.jsonValue["@odata.context"] =
43 "/redfish/v1/$metadata#StorageCollection.StorageCollection";
44 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage";
45 res.jsonValue["Name"] = "Storage Collection";
46 res.jsonValue["Members"] = {
47 {"@odata.id", "/redfish/v1/Systems/system/Storage/1"}};
48 res.jsonValue["Members@odata.count"] = 1;
49 }
50};
51
52class Storage : public Node
53{
54 public:
55 Storage(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/Storage/1")
56 {
57 entityPrivileges = {
58 {boost::beast::http::verb::get, {{"Login"}}},
59 {boost::beast::http::verb::head, {{"Login"}}},
60 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
61 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
62 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
63 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
64 }
65
66 private:
67 void doGet(crow::Response &res, const crow::Request &req,
68 const std::vector<std::string> &params) override
69 {
70 res.jsonValue["@odata.type"] = "#Storage.v1_2_0.Storage";
71 res.jsonValue["@odata.context"] =
72 "/redfish/v1/$metadata#Storage.Storage";
73 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage/1";
74 res.jsonValue["Name"] = "Storage Controller";
75 res.jsonValue["Id"] = "NVMe Controller";
76
77 auto asyncResp = std::make_shared<AsyncResp>(res);
78 crow::connections::systemBus->async_method_call(
79 [asyncResp](const boost::system::error_code ec,
80 const std::vector<std::string> &storageList) {
81 nlohmann::json &storageArray =
82 asyncResp->res.jsonValue["Drives"];
83 storageArray = nlohmann::json::array();
84 asyncResp->res.jsonValue["Drives@odata.count"] = 0;
85 if (ec)
86 {
87 return;
88 }
89 for (const std::string &objpath : storageList)
90 {
91 std::size_t lastPos = objpath.rfind("/");
92 if (lastPos == std::string::npos ||
93 objpath.size() <= lastPos + 1)
94 {
95 BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
96 continue;
97 }
98
99 storageArray.push_back(
100 {{"@odata.id",
101 "/redfish/v1/Systems/system/Storage/1/Drive/" +
102 objpath.substr(lastPos + 1)}});
103 }
104
105 asyncResp->res.jsonValue["Drives@odata.count"] =
106 storageArray.size();
107 },
108 "xyz.openbmc_project.ObjectMapper",
109 "/xyz/openbmc_project/object_mapper",
110 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
111 "/xyz/openbmc_project/inventory", int32_t(0),
112 std::array<const char *, 1>{
113 "xyz.openbmc_project.Inventory.Item.Drive"});
114 }
115};
116
117class Drive : public Node
118{
119 public:
120 Drive(CrowApp &app) :
121 Node(app, "/redfish/v1/Systems/system/Storage/1/Drive/<str>/",
122 std::string())
123 {
124 entityPrivileges = {
125 {boost::beast::http::verb::get, {{"Login"}}},
126 {boost::beast::http::verb::head, {{"Login"}}},
127 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
128 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
129 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
130 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
131 }
132
133 private:
134 void doGet(crow::Response &res, const crow::Request &req,
135 const std::vector<std::string> &params) override
136 {
137 const std::string &driveId = params[0];
138
139 auto asyncResp = std::make_shared<AsyncResp>(res);
140
141 crow::connections::systemBus->async_method_call(
142 [asyncResp, driveId](
143 const boost::system::error_code ec,
144 const std::vector<std::pair<
145 std::string, std::vector<std::pair<
146 std::string, std::vector<std::string>>>>>
147 &subtree) {
148 if (ec)
149 {
150 messages::resourceNotFound(asyncResp->res, "Drive",
151 driveId);
152 return;
153 }
154
155 for (const std::pair<
156 std::string,
157 std::vector<
158 std::pair<std::string, std::vector<std::string>>>>
159 &object : subtree)
160 {
161 const std::string &path = object.first;
162 const std::vector<
163 std::pair<std::string, std::vector<std::string>>>
164 &connectionNames = object.second;
165
166 if (!boost::ends_with(path, "/" + driveId))
167 {
168 continue;
169 }
170
171 asyncResp->res.jsonValue["@odata.type"] =
172 "#Drive.v1_2_0.Drive";
173 asyncResp->res.jsonValue["@odata.context"] =
174 "/redfish/v1/$metadata#Drive.Drive";
175 asyncResp->res.jsonValue["@odata.id"] =
176 "/redfish/v1/Systems/system/Storage/1/Drive/" + driveId;
177
178 if (connectionNames.size() != 1)
179 {
180 BMCWEB_LOG_ERROR << "Connection size "
181 << connectionNames.size()
182 << ", greater than 1";
183 continue;
184 }
185
186 const std::string &connectionName =
187 connectionNames[0].first;
188 crow::connections::systemBus->async_method_call(
189 [asyncResp, driveId](
190 const boost::system::error_code ec,
191 const std::vector<std::pair<
192 std::string,
193 std::variant<bool, std::string, uint64_t>>>
194 &propertiesList) {
195 for (const std::pair<
196 std::string,
197 std::variant<bool, std::string, uint64_t>>
198 &property : propertiesList)
199 {
200 // Store DBus properties that are also
201 // Redfish properties with same name and a
202 // string value
203 const std::string &propertyName =
204 property.first;
205 if ((propertyName == "PartNumber") ||
206 (propertyName == "SerialNumber") ||
207 (propertyName == "Manufacturer") ||
208 (propertyName == "Model"))
209 {
210 const std::string *value =
211 std::get_if<std::string>(
212 &property.second);
213 if (value != nullptr)
214 {
215 asyncResp->res.jsonValue[propertyName] =
216 *value;
217 }
218 }
219 }
220 asyncResp->res.jsonValue["Name"] = driveId;
221 asyncResp->res.jsonValue["Id"] = driveId;
222
223 getMainChassisId(
224 asyncResp, [](const std::string &chassisId,
225 std::shared_ptr<AsyncResp> aRsp) {
226 aRsp->res.jsonValue["Links"]["Chassis"] = {
227 {"@odata.id",
228 "/redfish/v1/Chassis/" + chassisId}};
229 });
230 },
231 connectionName, path, "org.freedesktop.DBus.Properties",
232 "GetAll",
233 "xyz.openbmc_project.Inventory.Decorator.Asset");
234
235 return;
236 }
237
238 // no object found with that name
239 messages::resourceNotFound(asyncResp->res, "Drive", driveId);
240 return;
241 },
242 "xyz.openbmc_project.ObjectMapper",
243 "/xyz/openbmc_project/object_mapper",
244 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
245 "/xyz/openbmc_project/inventory", int32_t(0),
246 std::array<const char *, 1>{
247 "xyz.openbmc_project.Inventory.Item.Drive"});
248 }
249};
250} // namespace redfish