| #ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_NVME_FEATURES_H_ |
| #define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_NVME_FEATURES_H_ |
| |
| #include <systemd/sd-bus.h> |
| |
| #include <array> |
| #include <cstddef> |
| #include <cstdint> |
| #include <functional> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| #include <tuple> |
| #include <utility> |
| #include <variant> |
| #include <vector> |
| |
| #include "absl/functional/any_invocable.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/str_cat.h" |
| #include "boost/beast/http/verb.hpp" // NOLINT |
| #include "boost/system/error_code.hpp" // NOLINT |
| #include "app.hpp" |
| #include "http_request.hpp" |
| #include "http_response.hpp" |
| #include "logging.hpp" |
| #include "utility.hpp" |
| #include "async_resp.hpp" |
| #include "dbus_utility.hpp" |
| #include "error_messages.hpp" |
| #include "query.hpp" |
| #include "registries/privilege_registry.hpp" |
| #include "dbus_utils.hpp" |
| #include "json_utils.hpp" |
| #include "storage_utils.hpp" |
| #include "storage.hpp" |
| #include <nlohmann/json_fwd.hpp> |
| #include "managed_store.hpp" |
| #include "managed_store_types.hpp" |
| #include "sdbusplus/message.hpp" |
| #include "sdbusplus/message/native_types.hpp" |
| |
| namespace redfish { |
| |
| inline void processNvmeFeaturesCollectionGet( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& parentUri, const std::string& service, |
| const std::string& path) { |
| managedStore::ManagedObjectStoreContext context(asyncResp); |
| dbus_utils::getProperty< |
| std::vector<std::tuple<std::string, std::string, std::string>>>( |
| service, path, "xyz.openbmc_project.NVMe.FeatureStore", |
| "FeatureCollection", context, |
| [asyncResp, parentUri]( |
| const boost::system::error_code& ec, |
| const std::vector<std::tuple<std::string, std::string, std::string>>& |
| features) { |
| if (ec) { |
| BMCWEB_LOG_ERROR << "Failed to get FeatureCollection: " << ec; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| nlohmann::json& members = asyncResp->res.jsonValue["Members"]; |
| members = nlohmann::json::array(); |
| for (const auto& feature : features) { |
| nlohmann::json::object_t member; |
| member["@odata.id"] = |
| absl::StrCat(parentUri, "/", std::get<0>(feature)); |
| members.push_back(member); |
| } |
| |
| asyncResp->res.jsonValue["@odata.id"] = parentUri; |
| asyncResp->res.jsonValue["@odata.type"] = |
| "#GoogleNvmeFeatureCollection.GoogleNvmeFeatureCollection"; |
| asyncResp->res.jsonValue["Name"] = "NVMe Features Collection"; |
| asyncResp->res.jsonValue["Members@odata.count"] = members.size(); |
| }); |
| } |
| |
| inline void processNvmeFeatureGet( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& parentUri, const std::string& featureName, |
| const std::string& service, const std::string& path) { |
| managedStore::ManagedObjectStoreContext context(asyncResp); |
| managedStore::GetManagedObjectStore()->getAllProperties( |
| service, path, "xyz.openbmc_project.NVMe.FeatureStore", context, |
| [asyncResp, parentUri, featureName, service, path]( |
| const boost::system::error_code& ec, |
| const std::vector<std::pair< |
| std::string, dbus::utility::DbusVariantType>>& properties) { |
| if (ec) { |
| BMCWEB_LOG_ERROR << "Failed to get properties: " << ec; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| std::string revision; |
| std::vector<std::tuple<std::string, std::string, std::string>> |
| featureCollection; |
| |
| bool revisionFound = false; |
| bool featureCollectionFound = false; |
| for (const auto& [propName, propVar] : properties) { |
| if (propName == "ProtoLibraryVersion") { |
| const std::string* revisionPtr = std::get_if<std::string>(&propVar); |
| if (revisionPtr != nullptr) { |
| revision = *revisionPtr; |
| revisionFound = true; |
| } |
| } else if (propName == "FeatureCollection") { |
| const auto* fcPtr = std::get_if< |
| std::vector<std::tuple<std::string, std::string, std::string>>>( |
| &propVar); |
| if (fcPtr != nullptr) { |
| featureCollection = *fcPtr; |
| featureCollectionFound = true; |
| } |
| } |
| } |
| |
| if (!revisionFound || !featureCollectionFound) { |
| BMCWEB_LOG_ERROR << "Failed to read ProtoLibraryVersion or " |
| "FeatureCollection"; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| std::string featureIdStr; |
| std::string className; |
| bool featureFoundInCollection = false; |
| for (const auto& feature : featureCollection) { |
| if (std::get<0>(feature) == featureName) { |
| featureIdStr = std::get<1>(feature); |
| className = std::get<2>(feature); |
| featureFoundInCollection = true; |
| break; |
| } |
| } |
| |
| if (!featureFoundInCollection) { |
| messages::resourceNotFound(asyncResp->res, "GoogleNvmeFeature", |
| featureName); |
| return; |
| } |
| |
| asyncResp->res.jsonValue["@odata.id"] = |
| absl::StrCat(parentUri, "/", featureName); |
| asyncResp->res.jsonValue["@odata.type"] = |
| "#GoogleNvmeFeature.v1_0_0.GoogleNvmeFeature"; |
| asyncResp->res.jsonValue["Id"] = featureName; |
| asyncResp->res.jsonValue["Name"] = featureName; |
| asyncResp->res.jsonValue["FeatureId"] = featureIdStr; |
| |
| size_t pos = featureName.rfind('_'); |
| if (pos != std::string::npos) { |
| asyncResp->res.jsonValue["Select"] = featureName.substr(pos + 1); |
| } |
| |
| asyncResp->res.jsonValue["DataProto"]["ClassName"] = className; |
| asyncResp->res.jsonValue["DataProto"]["Revision"] = revision; |
| |
| managedStore::GetManagedObjectStore() |
| ->PostDbusCallToIoContextThreadSafe( |
| asyncResp->strand_, |
| absl::AnyInvocable<void(const boost::system::error_code&, |
| const sdbusplus::message_t&, |
| const std::vector<uint8_t>&)>( |
| [asyncResp](const boost::system::error_code& ec2, |
| const sdbusplus::message_t& msg, |
| const std::vector<uint8_t>& payload) { |
| if (ec2) { |
| BMCWEB_LOG_ERROR << "Failed to call GetFeature: " |
| << ec2; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| const ::sd_bus_error* sd_err = nullptr; |
| if (msg) { |
| sd_err = msg.get_error(); |
| } |
| if (sd_err != nullptr) { |
| storageAddDbusError(asyncResp->res, "GetFeature", "", |
| sd_err->name, sd_err->message); |
| return; |
| } |
| asyncResp->res.jsonValue["DataProto"]["PayloadBase64"] = |
| crow::utility::base64encode(std::string_view( |
| reinterpret_cast<const char*>(payload.data()), |
| payload.size())); |
| }), |
| service, path, "xyz.openbmc_project.NVMe.FeatureStore", |
| "GetFeature", featureName); |
| }); |
| } |
| |
| inline absl::StatusOr<std::string> getPayloadBase64( |
| const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { |
| nlohmann::json dataProto; |
| if (!json_util::readJsonPatch(req, asyncResp->res, "DataProto", dataProto)) { |
| return absl::InvalidArgumentError("Invalid or Missing DataProto"); |
| } |
| |
| std::string payloadBase64; |
| if (!json_util::readJson(dataProto, asyncResp->res, "PayloadBase64", |
| payloadBase64)) { |
| return absl::InvalidArgumentError("Invalid or Missing PayloadBase64"); |
| } |
| |
| return payloadBase64; |
| } |
| |
| inline void processNvmeFeaturePatch( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& featureName, const std::string& payloadBase64, |
| const std::string& service, const std::string& path) { |
| std::string decodedPayload; |
| if (!crow::utility::base64Decode(payloadBase64, decodedPayload)) { |
| messages::propertyValueFormatError(asyncResp->res, payloadBase64, |
| "DataProto/PayloadBase64"); |
| return; |
| } |
| std::vector<uint8_t> payload(decodedPayload.begin(), decodedPayload.end()); |
| |
| BMCWEB_LOG_DEBUG << "Patching NVMeFeature " << featureName << " on " << path; |
| |
| managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( |
| asyncResp->strand_, |
| [asyncResp, featureName](const boost::system::error_code& ec, |
| const sdbusplus::message_t& msg) { |
| const ::sd_bus_error* sd_err = msg.get_error(); |
| if (sd_err != nullptr) { |
| storageAddDbusError(asyncResp->res, "SetFeature", featureName, |
| sd_err->name, sd_err->message); |
| return; |
| } |
| if (ec) { |
| BMCWEB_LOG_ERROR << "Failed to call SetFeature: " << ec; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| messages::success(asyncResp->res); |
| }, |
| service, path, "xyz.openbmc_project.NVMe.FeatureStore", "SetFeature", |
| featureName, payload); |
| } |
| |
| inline void getFeatureStoreServiceForPath( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& path, |
| std::function<void(const std::string& service)> cb) { |
| constexpr std::array<std::string_view, 1> interfaces = { |
| "xyz.openbmc_project.NVMe.FeatureStore"}; |
| managedStore::ManagedObjectStoreContext context(asyncResp); |
| storage_utils::getDbusObject( |
| path, interfaces, context, |
| [asyncResp, path, cb = std::move(cb)]( |
| const boost::system::error_code& ec, |
| const dbus::utility::MapperGetObject& objects) mutable { |
| if (ec || objects.empty()) { |
| BMCWEB_LOG_ERROR << "Failed to find FeatureStore interface for " |
| << path; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| std::move(cb)(objects.front().first); |
| }); |
| } |
| |
| inline void handleControllerNvmeFeaturesCollectionGet( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& systemName, const std::string& storageId, |
| const std::string& controllerId) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| BMCWEB_LOG_DEBUG << "Get NVMeFeatures Collection for controller " |
| << controllerId; |
| |
| storage_utils::findStorageAndController( |
| asyncResp, storageId, controllerId, |
| [asyncResp, systemName, storageId, controllerId]( |
| const sdbusplus::message::object_path& path, |
| const dbus::utility::MapperServiceMap& ifaces) { |
| std::optional<std::string> service = storage_utils::matchServiceName( |
| ifaces, "xyz.openbmc_project.NVMe.FeatureStore"); |
| if (!service) { |
| BMCWEB_LOG_ERROR << "Failed to find FeatureStore interface for " |
| << path.str; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| std::string parentUri(crow::utility::urlFromPieces( |
| "redfish", "v1", "Systems", systemName, |
| "Storage", storageId, "Controllers", |
| controllerId, "Oem", "Google", "Features") |
| .buffer()); |
| processNvmeFeaturesCollectionGet(asyncResp, parentUri, *service, |
| path.str); |
| }); |
| } |
| |
| inline bool parseNvmeFeatureProperties( |
| const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>& |
| properties, |
| const std::string& featureName, std::string& revision, |
| std::string& featureIdStr, std::string& className, crow::Response& res) { |
| std::vector<std::tuple<std::string, std::string, std::string>> |
| featureCollection; |
| |
| bool revisionFound = false; |
| bool featureCollectionFound = false; |
| for (const auto& [propName, propVar] : properties) { |
| if (propName == "ProtoLibraryVersion") { |
| const std::string* revisionPtr = std::get_if<std::string>(&propVar); |
| if (revisionPtr != nullptr) { |
| revision = *revisionPtr; |
| revisionFound = true; |
| } |
| } else if (propName == "FeatureCollection") { |
| const auto* fcPtr = std::get_if< |
| std::vector<std::tuple<std::string, std::string, std::string>>>( |
| &propVar); |
| if (fcPtr != nullptr) { |
| featureCollection = *fcPtr; |
| featureCollectionFound = true; |
| } |
| } |
| } |
| |
| if (!revisionFound || !featureCollectionFound) { |
| BMCWEB_LOG_ERROR << "Failed to read ProtoLibraryVersion or " |
| "FeatureCollection"; |
| messages::internalError(res); |
| return false; |
| } |
| |
| bool featureFoundInCollection = false; |
| for (const auto& feature : featureCollection) { |
| if (std::get<0>(feature) == featureName) { |
| featureIdStr = std::get<1>(feature); |
| className = std::get<2>(feature); |
| featureFoundInCollection = true; |
| break; |
| } |
| } |
| |
| if (!featureFoundInCollection) { |
| messages::resourceNotFound(res, "GoogleNvmeFeature", featureName); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| inline void handleControllerNvmeFeatureGet( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& systemName, const std::string& storageId, |
| const std::string& controllerId, const std::string& featureName) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| BMCWEB_LOG_DEBUG << "Get NVMeFeature " << featureName; |
| |
| storage_utils::findStorageAndController( |
| asyncResp, storageId, controllerId, |
| [asyncResp, systemName, storageId, controllerId, featureName]( |
| const sdbusplus::message::object_path& path, |
| const dbus::utility::MapperServiceMap& ifaces) { |
| std::optional<std::string> service = storage_utils::matchServiceName( |
| ifaces, "xyz.openbmc_project.NVMe.FeatureStore"); |
| if (!service) { |
| BMCWEB_LOG_ERROR << "Failed to find FeatureStore interface for " |
| << path.str; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| std::string parentUri(crow::utility::urlFromPieces( |
| "redfish", "v1", "Systems", systemName, |
| "Storage", storageId, "Controllers", |
| controllerId, "Oem", "Google", "Features") |
| .buffer()); |
| processNvmeFeatureGet(asyncResp, parentUri, featureName, *service, |
| path.str); |
| }); |
| } |
| |
| inline void handleControllerNvmeFeaturePatch( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& /*systemName*/, const std::string& storageId, |
| const std::string& controllerId, const std::string& featureName) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| |
| absl::StatusOr<std::string> payloadBase64 = getPayloadBase64(req, asyncResp); |
| if (!payloadBase64.ok()) { |
| BMCWEB_LOG_ERROR << "Failed to parse Request Payload for " << featureName |
| << " Base64: " << payloadBase64.status(); |
| return; |
| } |
| |
| storage_utils::findStorageAndController( |
| asyncResp, storageId, controllerId, |
| [asyncResp, featureName, payloadBase64 = std::move(*payloadBase64)]( |
| const sdbusplus::message::object_path& path, |
| const dbus::utility::MapperServiceMap& ifaces) { |
| auto service = storage_utils::matchServiceName( |
| ifaces, "xyz.openbmc_project.NVMe.FeatureStore"); |
| if (!service) { |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| processNvmeFeaturePatch(asyncResp, featureName, payloadBase64, *service, |
| path.str); |
| }); |
| } |
| |
| inline void handleStorageNvmeFeaturesCollectionGet( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& systemName, const std::string& storageId) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| BMCWEB_LOG_DEBUG << "Get NVMeFeatures Collection for storage " << storageId; |
| |
| storage_utils::findStorage( |
| asyncResp, storageId, |
| [asyncResp, systemName, |
| storageId](const sdbusplus::message::object_path& storagePath) { |
| getFeatureStoreServiceForPath( |
| asyncResp, storagePath.str, |
| [asyncResp, systemName, storageId, |
| storagePath](const std::string& service) { |
| std::string parentUri( |
| crow::utility::urlFromPieces("redfish", "v1", "Systems", |
| systemName, "Storage", storageId, |
| "Oem", "Google", "Features") |
| .buffer()); |
| processNvmeFeaturesCollectionGet(asyncResp, parentUri, service, |
| storagePath.str); |
| }); |
| }); |
| } |
| |
| inline void handleStorageNvmeFeatureGet( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& systemName, const std::string& storageId, |
| const std::string& featureName) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| BMCWEB_LOG_DEBUG << "Get NVMeFeature " << featureName; |
| |
| storage_utils::findStorage( |
| asyncResp, storageId, |
| [asyncResp, systemName, storageId, |
| featureName](const sdbusplus::message::object_path& storagePath) { |
| getFeatureStoreServiceForPath( |
| asyncResp, storagePath.str, |
| [asyncResp, systemName, storageId, featureName, |
| storagePath](const std::string& service) { |
| std::string parentUri( |
| crow::utility::urlFromPieces("redfish", "v1", "Systems", |
| systemName, "Storage", storageId, |
| "Oem", "Google", "Features") |
| .buffer()); |
| processNvmeFeatureGet(asyncResp, parentUri, featureName, service, |
| storagePath.str); |
| }); |
| }); |
| } |
| |
| inline void handleStorageNvmeFeaturePatch( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& /*systemName*/, const std::string& storageId, |
| const std::string& featureName) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| |
| absl::StatusOr<std::string> payloadBase64 = getPayloadBase64(req, asyncResp); |
| if (!payloadBase64.ok()) { |
| BMCWEB_LOG_ERROR << "Failed to parse Request Payload for " << featureName |
| << " Base64: " << payloadBase64.status(); |
| return; |
| } |
| |
| storage_utils::findStorage( |
| asyncResp, storageId, |
| [asyncResp, featureName, payloadBase64 = std::move(*payloadBase64)]( |
| const sdbusplus::message::object_path& storagePath) { |
| getFeatureStoreServiceForPath( |
| asyncResp, storagePath.str, |
| [asyncResp, featureName, payloadBase64, |
| storagePath](const std::string& service) { |
| processNvmeFeaturePatch(asyncResp, featureName, payloadBase64, |
| service, storagePath.str); |
| }); |
| }); |
| } |
| |
| inline void findVolumePath( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& storageId, const std::string& volumeId, |
| std::function<void(const sdbusplus::message::object_path& path)> cb) { |
| storage_utils::findStorage( |
| asyncResp, storageId, |
| [asyncResp, volumeId, cb = std::move(cb)]( |
| const sdbusplus::message::object_path& storagePath) mutable { |
| constexpr std::array<std::string_view, 1> interfaces = { |
| "xyz.openbmc_project.Inventory.Item.Volume"}; |
| managedStore::ManagedObjectStoreContext requestContext(asyncResp); |
| managedStore::GetManagedObjectStore()->getAssociatedSubTree( |
| storagePath / "containing", |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), |
| 0, interfaces, requestContext, |
| [asyncResp, volumeId, cb = std::move(cb)]( |
| const boost::system::error_code& ec, |
| const dbus::utility::MapperGetSubTreeResponse& |
| subtree) mutable { |
| if (ec) { |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| for (const auto& [path, ifaces] : subtree) { |
| if (sdbusplus::message::object_path(path).filename() == |
| volumeId) { |
| std::move(cb)(path); |
| return; |
| } |
| } |
| messages::resourceNotFound(asyncResp->res, "Volume", volumeId); |
| }); |
| }); |
| } |
| |
| inline void handleVolumeNvmeFeaturesCollectionGet( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& systemName, const std::string& storageId, |
| const std::string& volumeId) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| BMCWEB_LOG_DEBUG << "Get NVMeFeatures Collection for volume " << volumeId; |
| |
| findVolumePath( |
| asyncResp, storageId, volumeId, |
| [asyncResp, systemName, storageId, |
| volumeId](const sdbusplus::message::object_path& volumePath) { |
| getFeatureStoreServiceForPath( |
| asyncResp, volumePath.str, |
| [asyncResp, systemName, storageId, volumeId, |
| volumePath](const std::string& service) { |
| std::string parentUri(crow::utility::urlFromPieces( |
| "redfish", "v1", "Systems", systemName, |
| "Storage", storageId, "Volumes", |
| volumeId, "Oem", "Google", "Features") |
| .buffer()); |
| processNvmeFeaturesCollectionGet(asyncResp, parentUri, service, |
| volumePath.str); |
| }); |
| }); |
| } |
| |
| inline void handleVolumeNvmeFeatureGet( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& systemName, const std::string& storageId, |
| const std::string& volumeId, const std::string& featureName) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| BMCWEB_LOG_DEBUG << "Get NVMeFeature " << featureName; |
| |
| findVolumePath( |
| asyncResp, storageId, volumeId, |
| [asyncResp, systemName, storageId, volumeId, |
| featureName](const sdbusplus::message::object_path& volumePath) { |
| getFeatureStoreServiceForPath( |
| asyncResp, volumePath.str, |
| [asyncResp, systemName, storageId, volumeId, featureName, |
| volumePath](const std::string& service) { |
| std::string parentUri(crow::utility::urlFromPieces( |
| "redfish", "v1", "Systems", systemName, |
| "Storage", storageId, "Volumes", |
| volumeId, "Oem", "Google", "Features") |
| .buffer()); |
| processNvmeFeatureGet(asyncResp, parentUri, featureName, service, |
| volumePath.str); |
| }); |
| }); |
| } |
| |
| inline void handleVolumeNvmeFeaturePatch( |
| App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& /*systemName*/, const std::string& storageId, |
| const std::string& volumeId, const std::string& featureName) { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { |
| return; |
| } |
| |
| absl::StatusOr<std::string> payloadBase64 = getPayloadBase64(req, asyncResp); |
| if (!payloadBase64.ok()) { |
| BMCWEB_LOG_ERROR << "Failed to parse Request Payload for " << featureName |
| << " Base64: " << payloadBase64.status(); |
| return; |
| } |
| |
| findVolumePath( |
| asyncResp, storageId, volumeId, |
| [asyncResp, featureName, payloadBase64 = std::move(*payloadBase64)]( |
| const sdbusplus::message::object_path& volumePath) { |
| getFeatureStoreServiceForPath( |
| asyncResp, volumePath.str, |
| [asyncResp, featureName, payloadBase64, |
| volumePath](const std::string& service) { |
| processNvmeFeaturePatch(asyncResp, featureName, payloadBase64, |
| service, volumePath.str); |
| }); |
| }); |
| } |
| |
| inline void requestRoutesNvmeFeatures(App& app) { |
| BMCWEB_ROUTE(app, |
| "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>/Oem/" |
| "Google/Features/") |
| .privileges(redfish::privileges::getStorageController) |
| .methods(boost::beast::http::verb::get)(std::bind_front( |
| handleControllerNvmeFeaturesCollectionGet, std::ref(app))); |
| |
| BMCWEB_ROUTE(app, |
| "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>/Oem/" |
| "Google/Features/<str>/") |
| .privileges(redfish::privileges::getStorageController) |
| .methods(boost::beast::http::verb::get)( |
| std::bind_front(handleControllerNvmeFeatureGet, std::ref(app))); |
| |
| BMCWEB_ROUTE(app, |
| "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>/Oem/" |
| "Google/Features/<str>/") |
| .privileges(redfish::privileges::patchStorageController) |
| .methods(boost::beast::http::verb::patch)( |
| std::bind_front(handleControllerNvmeFeaturePatch, std::ref(app))); |
| |
| BMCWEB_ROUTE(app, |
| "/redfish/v1/Systems/<str>/Storage/<str>/Oem/Google/Features/") |
| .privileges(redfish::privileges::getStorage) |
| .methods(boost::beast::http::verb::get)(std::bind_front( |
| handleStorageNvmeFeaturesCollectionGet, std::ref(app))); |
| |
| BMCWEB_ROUTE( |
| app, "/redfish/v1/Systems/<str>/Storage/<str>/Oem/Google/Features/<str>/") |
| .privileges(redfish::privileges::getStorage) |
| .methods(boost::beast::http::verb::get)( |
| std::bind_front(handleStorageNvmeFeatureGet, std::ref(app))); |
| |
| BMCWEB_ROUTE( |
| app, "/redfish/v1/Systems/<str>/Storage/<str>/Oem/Google/Features/<str>/") |
| .privileges(redfish::privileges::patchStorage) |
| .methods(boost::beast::http::verb::patch)( |
| std::bind_front(handleStorageNvmeFeaturePatch, std::ref(app))); |
| |
| BMCWEB_ROUTE(app, |
| "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/<str>/Oem/" |
| "Google/Features/") |
| .privileges(redfish::privileges::getVolume) |
| .methods(boost::beast::http::verb::get)(std::bind_front( |
| handleVolumeNvmeFeaturesCollectionGet, std::ref(app))); |
| |
| BMCWEB_ROUTE(app, |
| "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/<str>/Oem/" |
| "Google/Features/<str>/") |
| .privileges(redfish::privileges::getVolume) |
| .methods(boost::beast::http::verb::get)( |
| std::bind_front(handleVolumeNvmeFeatureGet, std::ref(app))); |
| |
| BMCWEB_ROUTE(app, |
| "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/<str>/Oem/" |
| "Google/Features/<str>/") |
| .privileges(redfish::privileges::patchVolume) |
| .methods(boost::beast::http::verb::patch)( |
| std::bind_front(handleVolumeNvmeFeaturePatch, std::ref(app))); |
| } |
| } // namespace redfish |
| |
| #endif // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_NVME_FEATURES_H_ |