diff options
author | Nikhil Potade <nikhil.potade@linux.intel.com> | 2019-08-24 02:35:26 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2019-10-01 00:06:48 +0300 |
commit | e56c7b7092298c609831a65bcc8c21e62d422ba7 (patch) | |
tree | b7d67ab493242e8330ad3c334b955253bcb34f2d /redfish-core/lib/storage.hpp | |
parent | 3929aca1036033994610f6b3424aad124bf41d51 (diff) | |
download | bmcweb-e56c7b7092298c609831a65bcc8c21e62d422ba7.tar.xz |
Add Storage Schema for NVMe on Redfish
This provides an implementation for the Get methods for the Storage
schemas using following classes :
- StorageCollection
- Storage
Tested:
- Ran Redfish Service Validator to verify no issues are reported.
- Tested that the NVMe drives in the system show up and proper fields
are populated with appropriate data.
- Tested with no drives present. Made sure the Storage interface shows
no drives and Drive interface returns error message.
Signed-off-by: Nikhil Potade <nikhil.potade@linux.intel.com>
Change-Id: I9fa9f4cd69fe07cde15604c5405a6987774065fd
Diffstat (limited to 'redfish-core/lib/storage.hpp')
-rw-r--r-- | redfish-core/lib/storage.hpp | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp new file mode 100644 index 0000000000..8daead7632 --- /dev/null +++ b/redfish-core/lib/storage.hpp @@ -0,0 +1,250 @@ +/* +// Copyright (c) 2019 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ +#pragma once + +#include <node.hpp> + +namespace redfish +{ +class StorageCollection : public Node +{ + public: + StorageCollection(CrowApp &app) : + Node(app, "/redfish/v1/Systems/system/Storage/") + { + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; + } + + private: + void doGet(crow::Response &res, const crow::Request &req, + const std::vector<std::string> ¶ms) override + { + res.jsonValue["@odata.type"] = "#StorageCollection.StorageCollection"; + res.jsonValue["@odata.context"] = + "/redfish/v1/$metadata#StorageCollection.StorageCollection"; + res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage"; + res.jsonValue["Name"] = "Storage Collection"; + res.jsonValue["Members"] = { + {"@odata.id", "/redfish/v1/Systems/system/Storage/1"}}; + res.jsonValue["Members@odata.count"] = 1; + } +}; + +class Storage : public Node +{ + public: + Storage(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/Storage/1") + { + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; + } + + private: + void doGet(crow::Response &res, const crow::Request &req, + const std::vector<std::string> ¶ms) override + { + res.jsonValue["@odata.type"] = "#Storage.v1_2_0.Storage"; + 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["Id"] = "NVMe Controller"; + + auto asyncResp = std::make_shared<AsyncResp>(res); + crow::connections::systemBus->async_method_call( + [asyncResp](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; + if (ec) + { + return; + } + for (const std::string &objpath : storageList) + { + std::size_t lastPos = objpath.rfind("/"); + if (lastPos == std::string::npos || + objpath.size() <= lastPos + 1) + { + BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; + continue; + } + + storageArray.push_back( + {{"@odata.id", + "/redfish/v1/Systems/system/Storage/1/Drive/" + + objpath.substr(lastPos + 1)}}); + } + + asyncResp->res.jsonValue["Drives@odata.count"] = + storageArray.size(); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", + "/xyz/openbmc_project/inventory", int32_t(0), + std::array<const char *, 1>{ + "xyz.openbmc_project.Inventory.Item.Drive"}); + } +}; + +class Drive : public Node +{ + public: + Drive(CrowApp &app) : + Node(app, "/redfish/v1/Systems/system/Storage/1/Drive/<str>/", + std::string()) + { + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; + } + + private: + 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); + + 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) { + if (ec) + { + messages::resourceNotFound(asyncResp->res, "Drive", + driveId); + return; + } + + for (const std::pair< + std::string, + std::vector< + std::pair<std::string, std::vector<std::string>>>> + &object : subtree) + { + const std::string &path = object.first; + const std::vector< + std::pair<std::string, std::vector<std::string>>> + &connectionNames = object.second; + + if (!boost::ends_with(path, "/" + driveId)) + { + continue; + } + + asyncResp->res.jsonValue["@odata.type"] = + "#Drive.v1_2_0.Drive"; + asyncResp->res.jsonValue["@odata.context"] = + "/redfish/v1/$metadata#Drive.Drive"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Storage/1/Drive/" + driveId; + + if (connectionNames.size() != 1) + { + BMCWEB_LOG_ERROR << "Connection size " + << connectionNames.size() + << ", greater than 1"; + continue; + } + + const std::string &connectionName = + connectionNames[0].first; + crow::connections::systemBus->async_method_call( + [asyncResp, driveId]( + const boost::system::error_code ec, + const std::vector<std::pair< + std::string, + std::variant<bool, std::string, uint64_t>>> + &propertiesList) { + 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; + if ((propertyName == "PartNumber") || + (propertyName == "SerialNumber") || + (propertyName == "Manufacturer") || + (propertyName == "Model")) + { + const std::string *value = + std::get_if<std::string>( + &property.second); + if (value != nullptr) + { + asyncResp->res.jsonValue[propertyName] = + *value; + } + } + } + asyncResp->res.jsonValue["Name"] = driveId; + asyncResp->res.jsonValue["Id"] = driveId; + + getMainChassisId( + asyncResp, [](const std::string &chassisId, + std::shared_ptr<AsyncResp> aRsp) { + aRsp->res.jsonValue["Links"]["Chassis"] = { + {"@odata.id", + "/redfish/v1/Chassis/" + chassisId}}; + }); + }, + connectionName, path, "org.freedesktop.DBus.Properties", + "GetAll", + "xyz.openbmc_project.Inventory.Decorator.Asset"); + + return; + } + + // no object found with that name + messages::resourceNotFound(asyncResp->res, "Drive", driveId); + return; + }, + "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.Drive"}); + } +}; +} // namespace redfish
\ No newline at end of file |