summaryrefslogtreecommitdiff
path: root/redfish-core/lib/storage.hpp
diff options
context:
space:
mode:
authorJames Feist <james.feist@linux.intel.com>2019-11-21 03:20:23 +0300
committerJames Feist <james.feist@linux.intel.com>2019-11-27 20:16:49 +0300
commite284a7c19bb93e28b4ff20fcd437b2f2b26f0a44 (patch)
tree51033ffda75af0244ee33b5db1e5e1ddde67cb45 /redfish-core/lib/storage.hpp
parent3e6217d7d4a1523a889b536967cdcec169b3dd1f (diff)
downloadbmcweb-e284a7c19bb93e28b4ff20fcd437b2f2b26f0a44.tar.xz
Storage: Add Storage Controller
This adds support for Storage Controllers. Tested: Validator passed { "@odata.context": "/redfish/v1/$metadata#Storage.Storage", "@odata.id": "/redfish/v1/Systems/system/Storage/1", "@odata.type": "#Storage.v1_7_1.Storage", "Drives": [ { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_1" }, { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_2" }, { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_3" }, { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_4" }, { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_5" }, { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_6" }, { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_7" }, { "@odata.id": "/redfish/v1/Systems/system/Storage/1/Drives/Drive_8" } ], "Drives@odata.count": 8, "Id": "1", "Name": "Storage Controller", "Status": { "Health": "OK", "HealthRollup": "OK", "State": "Enabled" }, "StorageControllers": [ { "@odata.context": "/redfish/v1/$metadata#Storage.StorageController", "@odata.id": "/redfish/v1/Systems/system/Storage/1#/StorageControllers/0", "@odata.type": "#Storage.v1_7_0.StorageController", "Manufacturer": "$BOARD_MANUFACTURER", "MemberId": "HSBP_1", "Model": "$BOARD_PRODUCT_NAME", "Name": "HSBP_1", "PartNumber": "$BOARD_PART_NUMBER", "SerialNumber": "$BOARD_SERIAL_NUMBER", "Status": { "Health": "OK", "HealthRollup": "OK", "State": "Enabled" } } ] } Change-Id: I9d956343daa74ddfa912e3cbe0d38b0e42a4859f Signed-off-by: James Feist <james.feist@linux.intel.com>
Diffstat (limited to 'redfish-core/lib/storage.hpp')
-rw-r--r--redfish-core/lib/storage.hpp190
1 files changed, 171 insertions, 19 deletions
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
index 9c51975eb1..856ef5e450 100644
--- a/redfish-core/lib/storage.hpp
+++ b/redfish-core/lib/storage.hpp
@@ -16,6 +16,7 @@
#pragma once
#include "health.hpp"
+#include "openbmc_dbus_rest.hpp"
#include <node.hpp>
@@ -74,19 +75,22 @@ class Storage : public Node
res.jsonValue["@odata.context"] =
"/redfish/v1/$metadata#Storage.Storage";
res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage/1";
- res.jsonValue["Name"] = "Storage Controller";
+ res.jsonValue["Name"] = "Storage";
res.jsonValue["Id"] = "1";
res.jsonValue["Status"]["State"] = "Enabled";
auto asyncResp = std::make_shared<AsyncResp>(res);
+ auto health = std::make_shared<HealthPopulate>(asyncResp);
+ health->populate();
+
crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::vector<std::string> &storageList) {
+ [asyncResp, health](const boost::system::error_code ec,
+ const std::vector<std::string> &storageList) {
nlohmann::json &storageArray =
asyncResp->res.jsonValue["Drives"];
storageArray = nlohmann::json::array();
- asyncResp->res.jsonValue["Drives@odata.count"] = 0;
- auto health = std::make_shared<HealthPopulate>(asyncResp);
+ auto &count = asyncResp->res.jsonValue["Drives@odata.count"];
+ count = 0;
if (ec)
{
@@ -95,8 +99,9 @@ class Storage : public Node
return;
}
- health->inventory = storageList;
- health->populate();
+ health->inventory.insert(health->inventory.end(),
+ storageList.begin(),
+ storageList.end());
for (const std::string &objpath : storageList)
{
@@ -114,8 +119,7 @@ class Storage : public Node
objpath.substr(lastPos + 1)}});
}
- asyncResp->res.jsonValue["Drives@odata.count"] =
- storageArray.size();
+ count = storageArray.size();
},
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
@@ -123,6 +127,154 @@ class Storage : public Node
"/xyz/openbmc_project/inventory", int32_t(0),
std::array<const char *, 1>{
"xyz.openbmc_project.Inventory.Item.Drive"});
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ health](const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType &subtree) {
+ if (ec || !subtree.size())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ nlohmann::json &root =
+ asyncResp->res.jsonValue["StorageControllers"];
+ root = nlohmann::json::array();
+ for (const auto &[path, interfaceDict] : subtree)
+ {
+ std::size_t lastPos = path.rfind("/");
+ if (lastPos == std::string::npos ||
+ (path.size() <= lastPos + 1))
+ {
+ BMCWEB_LOG_ERROR << "Failed to find '/' in " << path;
+ return;
+ }
+
+ if (interfaceDict.size() != 1)
+ {
+ BMCWEB_LOG_ERROR << "Connection size "
+ << interfaceDict.size()
+ << ", greater than 1";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const std::string &connectionName =
+ interfaceDict.front().first;
+
+ size_t index = root.size();
+ nlohmann::json &storageController =
+ root.emplace_back(nlohmann::json::object());
+
+ std::string id = path.substr(lastPos + 1);
+
+ storageController["@odata.type"] =
+ "#Storage.v1_7_0.StorageController";
+ storageController["@odata.context"] =
+ "/redfish/v1/$metadata#Storage.StorageController";
+ storageController["@odata.id"] =
+ "/redfish/v1/Systems/system/Storage/1"
+ "#/StorageControllers/" +
+ std::to_string(index);
+ storageController["Name"] = id;
+ storageController["MemberId"] = id;
+ storageController["Status"]["State"] = "Enabled";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, index](const boost::system::error_code ec,
+ const std::variant<bool> present) {
+ // this interface isn't necessary, only check it if
+ // we get a good return
+ if (ec)
+ {
+ return;
+ }
+ const bool *enabled = std::get_if<bool>(&present);
+ if (enabled == nullptr)
+ {
+ BMCWEB_LOG_DEBUG << "Illegal property present";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (!(*enabled))
+ {
+ asyncResp->res
+ .jsonValue["StorageControllers"][index]
+ ["Status"]["State"] = "Disabled";
+ }
+ },
+ connectionName, path, "org.freedesktop.DBus.Properties",
+ "Get", "xyz.openbmc_project.Inventory.Item", "Present");
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ index](const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string,
+ std::variant<bool, std::string, uint64_t>>>
+ &propertiesList) {
+ if (ec)
+ {
+ // this interface isn't necessary
+ return;
+ }
+ for (const std::pair<
+ std::string,
+ std::variant<bool, std::string, uint64_t>>
+ &property : propertiesList)
+ {
+ // Store DBus properties that are also
+ // Redfish properties with same name and a
+ // string value
+ const std::string &propertyName =
+ property.first;
+ nlohmann::json &object =
+ asyncResp->res
+ .jsonValue["StorageControllers"][index];
+ if ((propertyName == "PartNumber") ||
+ (propertyName == "SerialNumber") ||
+ (propertyName == "Manufacturer") ||
+ (propertyName == "Model"))
+ {
+ const std::string *value =
+ std::get_if<std::string>(
+ &property.second);
+ if (value == nullptr)
+ {
+ // illegal property
+ messages::internalError(asyncResp->res);
+ continue;
+ }
+ object[propertyName] = *value;
+ }
+ }
+ },
+ connectionName, path, "org.freedesktop.DBus.Properties",
+ "GetAll",
+ "xyz.openbmc_project.Inventory.Decorator.Asset");
+ }
+
+ // this is done after we know the json array will no longer be
+ // resized, as json::array uses vector underneath and we need
+ // references to its members that won't change
+ size_t count = 0;
+ for (const auto &[path, interfaceDict] : subtree)
+ {
+ auto subHealth = std::make_shared<HealthPopulate>(
+ asyncResp, root[count]["Status"]);
+ subHealth->inventory.emplace_back(path);
+ health->inventory.emplace_back(path);
+ health->children.emplace_back(subHealth);
+ count++;
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", int32_t(0),
+ std::array<const char *, 1>{
+ "xyz.openbmc_project.Inventory.Item.StorageController"});
}
};
@@ -146,17 +298,18 @@ class Drive : public Node
void doGet(crow::Response &res, const crow::Request &req,
const std::vector<std::string> &params) override
{
- const std::string &driveId = params[0];
-
auto asyncResp = std::make_shared<AsyncResp>(res);
+ if (params.size() != 1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string &driveId = params[0];
crow::connections::systemBus->async_method_call(
- [asyncResp, driveId](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, std::vector<std::pair<
- std::string, std::vector<std::string>>>>>
- &subtree) {
+ [asyncResp,
+ driveId](const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType &subtree) {
if (ec)
{
BMCWEB_LOG_ERROR << "Drive mapper call error";
@@ -251,8 +404,7 @@ class Drive : public Node
asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
auto health = std::make_shared<HealthPopulate>(asyncResp);
- health->inventory = std::vector<std::string>{path};
-
+ health->inventory.emplace_back(path);
health->populate();
crow::connections::systemBus->async_method_call(