diff options
author | James Feist <james.feist@linux.intel.com> | 2019-11-21 03:20:23 +0300 |
---|---|---|
committer | James Feist <james.feist@linux.intel.com> | 2019-11-27 20:16:49 +0300 |
commit | e284a7c19bb93e28b4ff20fcd437b2f2b26f0a44 (patch) | |
tree | 51033ffda75af0244ee33b5db1e5e1ddde67cb45 /redfish-core | |
parent | 3e6217d7d4a1523a889b536967cdcec169b3dd1f (diff) | |
download | bmcweb-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')
-rw-r--r-- | redfish-core/lib/storage.hpp | 190 | ||||
-rw-r--r-- | redfish-core/lib/systems.hpp | 5 |
2 files changed, 174 insertions, 21 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> ¶ms) 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( diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp index 42992272ca..0e6cb09412 100644 --- a/redfish-core/lib/systems.hpp +++ b/redfish-core/lib/systems.hpp @@ -1700,10 +1700,11 @@ class Systems : public Node }; auto asyncResp = std::make_shared<AsyncResp>(res); - constexpr const std::array<const char *, 3> inventoryForSystems = { + constexpr const std::array<const char *, 4> inventoryForSystems = { "xyz.openbmc_project.Inventory.Item.Dimm", "xyz.openbmc_project.Inventory.Item.Cpu", - "xyz.openbmc_project.Inventory.Item.Drive"}; + "xyz.openbmc_project.Inventory.Item.Drive", + "xyz.openbmc_project.Inventory.Item.StorageController"}; auto health = std::make_shared<HealthPopulate>(asyncResp); crow::connections::systemBus->async_method_call( |