/*
// 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.
*/

/**
 * The following requirments on Dbus should be satisfied for storage stack
 * working properly:
 * * system name and the storage name are globally unique
 * * On Single System system, the default system DBus object can be omitted.
 * * On Multi System system, the system DBus object and the association
 * (containing/contained_by) to Storage are manditory.
 */
#pragma once

#include "app.hpp"
#include "dbus_utility.hpp"
#include "generated/enums/drive.hpp"
#include "health.hpp"
#include "human_sort.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "openbmc_dbus_rest.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
#include "registries/privilege_registry.hpp"
#include "task.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/hex_utils.hpp"
#include "utils/nvme_metric_utils.hpp"
#include "utils/storage_utils.hpp"

#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <utils/location_utils.hpp>

#include <algorithm>
#include <array>
#include <cstdlib>
#include <filesystem>
#include <string_view>
#include <unordered_set>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{

/* Converts a NVMe dbus error to a redfish equivalent, adds to the response */
inline void storageAddDbusError(crow::Response& res, std::string_view func,
                                const std::string& storageId,
                                std::string_view errorName,
                                std::string_view errorDesc)
{
    (void)storageId;

    crow::Response err;

    BMCWEB_LOG_DEBUG << func << " " << errorName << ", " << errorDesc;
    if (errorName == "xyz.openbmc_project.Common.Error.TooManyResources")
    {
        messages::createLimitReachedForResource(err);
    }
    else if (errorName == "xyz.openbmc_project.Common.Error.InvalidArgument")
    {
        messages::propertyValueError(err, "");
    }
    else if (errorName ==
             "xyz.openbmc_project.Common.Error.DeviceOperationFailed" ||
             errorName == "xyz.openbmc_project.Common.Error.UnsupportedRequest")
    {
        messages::operationFailed(err);
    }
    else
    {
        messages::internalError(err);
    }

    // Some messages have "error" toplevel, others have "@Message.ExtendedInfo"
    // (addMessageToErrorJson() versus addMessageToJson()). Choose which.
    nlohmann::json extInfo;
    if (err.jsonValue.contains("error"))
    {
        extInfo = err.jsonValue["error"][messages::messageAnnotation][0];
    }
    else
    {
        extInfo = err.jsonValue[messages::messageAnnotation][0];
    }

    // Keep the specific error message provided from the NVMe software.
    extInfo["Message"] = errorDesc;

    messages::moveErrorsToErrorJson(res.jsonValue, extInfo);
    res.result(boost::beast::http::status::bad_request);
}

/**
 * @brief Makes sure the target Storage can be accessed through given System
 * @param asyncResp     Pointer to object holding response data
 * @param systemName    ID (D-Bus filename) of the System
 * @param storageId     ID (D-Bus filename) of the Storage
//  * @param cb            Callback function to call if the access is valid
 *
 * Sets an error response if the Storage can't be accessed through this System
 */
inline void
    checkSystemAndStorage(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& systemName,
                          const std::string& storageId)
{
    storage_utils::findStorage(
        asyncResp, storageId,
        [asyncResp, systemName,
         storageId](const sdbusplus::message::object_path& storagePath) {
        storage_utils::getSystemPathFromStorage(
            asyncResp, storagePath,
            [asyncResp, systemName,
             storageId](std::optional<std::string_view> systemPath) {
            if ((!systemPath &&
                 systemName != "system") // default single system system
                ||
                (systemPath &&
                 std::filesystem::path(*systemPath).filename() != systemName))
            {
                BMCWEB_LOG_ERROR
                    << "No association between System and Storage: "
                    << systemName << ", " << storageId;
                messages::internalError(asyncResp->res);
                return;
            }
            // cb();
        });
    });
}

inline void handleGetSystemStorageCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    asyncResp->res.jsonValue["@odata.type"] =
        "#StorageCollection.StorageCollection";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", systemName, "Storage");
    asyncResp->res.jsonValue["Name"] = "Storage Collection";

    storage_utils::getSystemPathFromName(
        asyncResp, systemName,
        [asyncResp, systemName](std::optional<std::string_view> systemPath) {
        if (!systemPath) // fall back to single-system system
        {

            if (systemName != "system")
            {
                messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                           systemName);
                return;
            }
            collection_util::getCollectionMembers(
                asyncResp,
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             systemName, "Storage"),
                std::array<std::string_view, 1>{
                    {"xyz.openbmc_project.Inventory.Item.Storage"}});
            return;
        }
        collection_util::getAssociatedCollectionMembers(
            asyncResp,
            crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                         "Storage"),
            std::array<std::string_view, 1>{
                {"xyz.openbmc_project.Inventory.Item.Storage"}},
            (std::string(*systemPath) + "/containing").c_str());
    });
}

inline void handleGetStorageCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    asyncResp->res.jsonValue["@odata.type"] =
        "#StorageCollection.StorageCollection";
    asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Storage";
    asyncResp->res.jsonValue["Name"] = "Storage Collection";
    constexpr std::array<std::string_view, 1> interface{
        "xyz.openbmc_project.Inventory.Item.Storage"};
    collection_util::getCollectionMembers(
        asyncResp, crow::utility::urlFromPieces("redfish", "v1", "Storage"),
        interface);
}

inline void requestRoutesStorageCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/")
        .privileges(redfish::privileges::getStorageCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGetSystemStorageCollection, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Storage/")
        .privileges(redfish::privileges::getStorageCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGetStorageCollection, std::ref(app)));
}

inline void getDrives(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::shared_ptr<HealthPopulate>& health,
                      const sdbusplus::message::object_path& storagePath,
                      const std::string& chassisId)
{
    const std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Drive"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        storagePath / "drive",
        sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
        interfaces, requestContext,
        [asyncResp, health, chassisId](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreePathsResponse& driveList) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Drive mapper call error";
            messages::internalError(asyncResp->res);
            return;
        }

        nlohmann::json& driveArray = asyncResp->res.jsonValue["Drives"];
        driveArray = nlohmann::json::array();
        auto& count = asyncResp->res.jsonValue["Drives@odata.count"];
        count = 0;

#ifdef HEALTH_POPULATE
        health->inventory.insert(health->inventory.end(), driveList.begin(),
                                 driveList.end());
#endif

        for (const std::string& drive : driveList)
        {
            sdbusplus::message::object_path object(drive);
            if (object.filename().empty())
            {
                BMCWEB_LOG_ERROR << "Failed to find filename in " << drive;
                return;
            }

            nlohmann::json::object_t driveJson;
            driveJson["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Chassis", chassisId, "Drives",
                object.filename());
            driveArray.emplace_back(std::move(driveJson));
        }

        count = driveArray.size();
    });
}

inline void
    populateCustomSSDInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const dbus::utility::MapperServiceMap& ifaces,
                          const std::string& path)
{
    std::string connection;
    std::string customSSDDbusInterface =
        "com.google.gbmc.ssd." +
        boost::algorithm::to_lower_copy(std::string(customSSD));

    for (const auto& x : ifaces)
    {
        for (const std::string& y : x.second)
        {
            if (y == customSSDDbusInterface)
            {
                connection = x.first;
                break;
            }
        }
        if (!connection.empty())
        {
            break;
        }
    }
    if (connection.empty())
    {
        return;
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);
    asyncResp->res.jsonValue["Links"]["Oem"]["Google"][std::string(customSSD)] =
        nlohmann::json::object_t();
    dbus_utils::getProperty<bool>(
        connection, path, customSSDDbusInterface, "PwrseqPgood", context,
        [asyncResp, path](const boost::system::error_code& ec,
                          bool pwrseqPgood) {
        // this interface isn't necessary, only check it if
        // we get a good return
        if (ec)
        {
            return;
        }

        asyncResp->res.jsonValue["Links"]["Oem"]["Google"]
                                [std::string(customSSD)]["PwrseqPgood"] =
            pwrseqPgood;
    });
    managedStore::GetManagedObjectStore()->getAllProperties(
        connection, path, customSSDDbusInterface, context,
        [asyncResp, connection, path, context](
            const boost::system::error_code ec2,
            const std::vector<std::pair<
                std::string, dbus::utility::DbusVariantType>>& propertiesList) {
        if (ec2)
        {
            // this interface isn't necessary
            return;
        }

        const bool* manufacturingMode = nullptr;
        const bool* watchdogTriggered = nullptr;
        const bool* fruEepromWriteProtect = nullptr;
        const bool* controllerOtpWriteProtect = nullptr;
        const bool* triggerPowerCycle = nullptr;
        const bool* triggerReset = nullptr;
        const bool* disableWatchdog = nullptr;
        const bool* debugMode = nullptr;
        const bool* controllerOtpWriteEnable = nullptr;
        const uint64_t* spiImgSelect = nullptr;
        const uint64_t* bootFailureCount = nullptr;
        const std::string* pwrseqState = nullptr;
        const uint64_t* uptimeInSeconds = nullptr;
        const uint64_t* uptimeInMinutes = nullptr;
        const bool* pgoodVdd12v0Ssd = nullptr;
        const bool* pgoodVddPcMor = nullptr;
        const bool* pgoodVdd3v3Pcie = nullptr;
        const bool* pgoodVdd0v83Mor = nullptr;
        const bool* pgoodVttVrefca = nullptr;
        const bool* pgoodVddFlashVcc = nullptr;
        const bool* pgood12vFlashVpp = nullptr;
        const std::string* cpldVersion = nullptr;

        std::string otpWriteProtectProperty =
            customSSDController + std::string("OtpWriteProtect");
        std::string otpWriteEnableProperty =
            customSSDController + std::string("OtpWriteEnable");

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), propertiesList,
            "ManufacturingMode", manufacturingMode, "WatchdogTriggered",
            watchdogTriggered, "FruEepromWriteProtect", fruEepromWriteProtect,
            otpWriteProtectProperty, controllerOtpWriteProtect,
            "TriggerPowerCycle", triggerPowerCycle, "TriggerReset",
            triggerReset, "DisableWatchdog", disableWatchdog, "DebugMode",
            debugMode, otpWriteEnableProperty, controllerOtpWriteEnable,
            "SpiImgSelect", spiImgSelect, "BootFailureCount", bootFailureCount,
            "PwrseqState", pwrseqState, "UptimeInSeconds", uptimeInSeconds,
            "UptimeInMinutes", uptimeInMinutes, "PgoodVdd12v0Ssd",
            pgoodVdd12v0Ssd, "PgoodVddPcMor", pgoodVddPcMor, "PgoodVdd3v3Pcie",
            pgoodVdd3v3Pcie, "PgoodVdd0v83Mor", pgoodVdd0v83Mor,
            "PgoodVttVrefca", pgoodVttVrefca, "PgoodVddFlashVcc",
            pgoodVddFlashVcc, "Pgood12vFlashVpp", pgood12vFlashVpp,
            "CpldVersion", cpldVersion);

        if (!success)
        {
            BMCWEB_LOG_CRITICAL << "Failed to parse Arguments for "
                                << std::string(customSSD);
            messages::internalError(asyncResp->res);
            return;
        }

        nlohmann::json& customSSDJsonObj =
            asyncResp->res
                .jsonValue["Links"]["Oem"]["Google"][std::string(customSSD)];
        customSSDJsonObj["@odata.type"] = customSSDOdataType;
        // Write Only and will always read as false.
        customSSDJsonObj["CpldReset"] = false;

        if (manufacturingMode != nullptr)
        {
            customSSDJsonObj["ManufacturingMode"] = *manufacturingMode;
        }
        if (watchdogTriggered != nullptr)
        {
            customSSDJsonObj["WatchdogTriggered"] = *watchdogTriggered;
        }
        if (fruEepromWriteProtect != nullptr)
        {
            customSSDJsonObj["FruEepromWriteProtect"] = *fruEepromWriteProtect;
        }
        if (controllerOtpWriteProtect != nullptr)
        {
            customSSDJsonObj[otpWriteProtectProperty] =
                *controllerOtpWriteProtect;
        }
        if (triggerPowerCycle != nullptr)
        {
            customSSDJsonObj["TriggerPowerCycle"] = *triggerPowerCycle;
        }
        if (triggerReset != nullptr)
        {
            customSSDJsonObj["TriggerReset"] = *triggerReset;
        }
        if (disableWatchdog != nullptr)
        {
            customSSDJsonObj["DisableWatchdog"] = *disableWatchdog;
        }
        if (debugMode != nullptr)
        {
            customSSDJsonObj["DebugMode"] = *debugMode;
        }
        if (controllerOtpWriteEnable != nullptr)
        {
            customSSDJsonObj[otpWriteEnableProperty] =
                *controllerOtpWriteEnable;
        }
        if (spiImgSelect != nullptr)
        {
            customSSDJsonObj["SpiImgSelect"] = *spiImgSelect;
        }
        if (bootFailureCount != nullptr)
        {
            customSSDJsonObj["BootFailureCount"] = *bootFailureCount;
        }
        if (pwrseqState != nullptr)
        {
            customSSDJsonObj["PwrseqState"] = *pwrseqState;
        }
        if (uptimeInSeconds != nullptr)
        {
            customSSDJsonObj["UptimeInSeconds"] = *uptimeInSeconds;
        }
        if (uptimeInMinutes != nullptr)
        {
            customSSDJsonObj["UptimeInMinutes"] = *uptimeInMinutes;
        }
        if (pgoodVdd12v0Ssd != nullptr)
        {
            customSSDJsonObj["PgoodVdd12v0Ssd"] = *pgoodVdd12v0Ssd;
        }
        if (pgoodVddPcMor != nullptr)
        {
            customSSDJsonObj["PgoodVddPcMor"] = *pgoodVddPcMor;
        }
        if (pgoodVdd3v3Pcie != nullptr)
        {
            customSSDJsonObj["PgoodVdd3v3Pcie"] = *pgoodVdd3v3Pcie;
        }
        if (pgoodVdd0v83Mor != nullptr)
        {
            customSSDJsonObj["PgoodVdd0v83Mor"] = *pgoodVdd0v83Mor;
        }
        if (pgoodVttVrefca != nullptr)
        {
            customSSDJsonObj["PgoodVttVrefca"] = *pgoodVttVrefca;
        }
        if (pgoodVddFlashVcc != nullptr)
        {
            customSSDJsonObj["PgoodVddFlashVcc"] = *pgoodVddFlashVcc;
        }
        if (pgood12vFlashVpp != nullptr)
        {
            customSSDJsonObj["Pgood12vFlashVpp"] = *pgood12vFlashVpp;
        }
        if (cpldVersion != nullptr)
        {
            customSSDJsonObj["CpldVersion"] = *cpldVersion;
        }

        customSSDJsonObj["Name"] = std::string(customSSD) + " GPIO Action Info";
    });

    managedStore::GetManagedObjectStore()->getAllProperties(
        connection, path, "xyz.openbmc_project.Inventory.Decorator.Asset",
        context,
        [asyncResp](const boost::system::error_code ec3,
                    const std::vector<std::pair<
                        std::string, dbus::utility::DbusVariantType>>& asset) {
        if (ec3)
        {
            // this interface isn't necessary
            return;
        }
        nlohmann::json::object_t customSSDFruEeprom;

        const std::string* partNumber = nullptr;
        const std::string* serialNumber = nullptr;
        const std::string* manufacturer = nullptr;
        const std::string* model = nullptr;
        const std::string* manufactureDate = nullptr;

        const bool assetSuccess = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), asset, "PartNumber", partNumber,
            "SerialNumber", serialNumber, "Manufacturer", manufacturer, "Model",
            model, "ManufactureDate", manufactureDate);
        if (!assetSuccess)
        {
            BMCWEB_LOG_CRITICAL << "Failed to parse Arguments for "
                                << std::string(customSSD);
            return;
        }
        customSSDFruEeprom["DeviceName"] = std::string(customSSD);
        // If we get to this point, then it is enabled.
        customSSDFruEeprom["Validity"] = "Enabled";
        if (partNumber != nullptr)
        {
            customSSDFruEeprom["BrdPartNumber"] = *partNumber;
        }
        if (serialNumber != nullptr)
        {
            customSSDFruEeprom["BrdSerialNumber"] = *serialNumber;
        }
        if (manufacturer != nullptr)
        {
            customSSDFruEeprom["BrdMfgName"] = *manufacturer;
        }
        if (model != nullptr)
        {
            customSSDFruEeprom["BrdProductName"] = *model;
        }
        if (manufactureDate != nullptr)
        {
            customSSDFruEeprom["BrdMfgTime"] = *manufactureDate;
        }
        asyncResp->res.jsonValue["Links"]["Oem"]["Google"]
                                [std::string(customSSD)]["FruEeprom"] =
            std::move(customSSDFruEeprom);
    });
}

inline void
    getDriveFromChassis(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::shared_ptr<HealthPopulate>& health,
                        const sdbusplus::message::object_path& storagePath)
{
    const std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        storagePath / "chassis",
        sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
        interfaces, requestContext,
        [asyncResp, health, storagePath](
            const boost::system::error_code ec,
            const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Chassis mapper call error";
            messages::internalError(asyncResp->res);
            return;
        }

        if (chassisList.empty())
        {
            BMCWEB_LOG_DEBUG << "Can not find the Chassis containing the drive";
            return;
        }

        if (chassisList.size() != 1)
        {
            BMCWEB_LOG_ERROR
                << "Storage is not associated with only one chassis";
            messages::internalError(asyncResp->res);
            return;
        }

        const std::string& chassisPath = chassisList.front();
        std::string chassisId =
            sdbusplus::message::object_path(chassisPath).filename();
        if (chassisId.empty())
        {
            BMCWEB_LOG_ERROR << "Failed to find filename in " << chassisPath;
            return;
        }
        getDrives(asyncResp, health, storagePath, chassisId);
    });
}

inline void
    handleGetSystemStorage(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;
    }

    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Storage"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, systemName, storageId](
            const boost::system::error_code ec,
            const dbus::utility::MapperGetSubTreePathsResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "requestRoutesStorage DBUS response error";
            messages::resourceNotFound(asyncResp->res,
                                       "#Storage.v1_13_0.Storage", storageId);
            return;
        }
        auto storage = std::find_if(subtree.begin(), subtree.end(),
                                    [&storageId](const std::string& path) {
            return sdbusplus::message::object_path(path).filename() ==
                   storageId;
        });
        if (storage == subtree.end())
        {
            messages::resourceNotFound(asyncResp->res,
                                       "#Storage.v1_13_0.Storage", storageId);
            return;
        }

        checkSystemAndStorage(asyncResp, systemName, storageId);
        asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_13_0.Storage";
        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", systemName.c_str(), "Storage",
            storageId);
        asyncResp->res.jsonValue["Name"] = "Storage";
        asyncResp->res.jsonValue["Id"] = storageId;
        asyncResp->res.jsonValue["Status"]["State"] = "Enabled";

        auto health = std::make_shared<HealthPopulate>(asyncResp);
#ifdef HEALTH_POPULATE
        health->populate();
#endif

        getDriveFromChassis(asyncResp, health, *storage);
        asyncResp->res.jsonValue["Controllers"]["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                         systemName.c_str(), "Storage",
                                         storageId, "Controllers");
        asyncResp->res.jsonValue["Volumes"]["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                         systemName.c_str(), "Storage",
                                         storageId, "Volumes");
    });
}

inline void
    handleGetStorage(App& app, const crow::Request& req,
                     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                     const std::string& storageId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        BMCWEB_LOG_DEBUG << "requestRoutesStorage setUpRedfishRoute failed";
        return;
    }

    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Storage"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, storageId](
            const boost::system::error_code ec,
            const dbus::utility::MapperGetSubTreePathsResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "requestRoutesStorage DBUS response error";
            messages::resourceNotFound(asyncResp->res,
                                       "#Storage.v1_13_0.Storage", storageId);
            return;
        }
        auto storage = std::find_if(subtree.begin(), subtree.end(),
                                    [&storageId](const std::string& storage) {
            return sdbusplus::message::object_path(storage).filename() ==
                   storageId;
        });
        if (storage == subtree.end())
        {
            messages::resourceNotFound(asyncResp->res,
                                       "#Storage.v1_13_0.Storage", storageId);
            return;
        }

        asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_13_0.Storage";
        asyncResp->res.jsonValue["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Storage", storageId);
        asyncResp->res.jsonValue["Name"] = "Storage";
        asyncResp->res.jsonValue["Id"] = storageId;
        asyncResp->res.jsonValue["Status"]["State"] = "Enabled";

        // Storage subsystem to Stroage link.
        storage_utils::getSystemPathFromStorage(
            asyncResp, *storage,
            [asyncResp, storageId](std::optional<std::string_view> systemPath) {
            nlohmann::json::array_t storageServices;
            nlohmann::json::object_t storageService;

            std::string systemName =
                systemPath ? std::filesystem::path(*systemPath).filename()
                           : "system";
            storageService["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", systemName, "Storage", storageId);
            storageServices.emplace_back(storageService);
            asyncResp->res.jsonValue["Links"]["StorageServices"] =
                std::move(storageServices);
            asyncResp->res.jsonValue["Links"]["StorageServices@odata.count"] =
                1;
        });
    });
}

inline void requestRoutesStorage(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/<str>/")
        .privileges(redfish::privileges::getStorage)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGetSystemStorage, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Storage/<str>/")
        .privileges(redfish::privileges::getStorage)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGetStorage, std::ref(app)));
}

inline void getDriveAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& connectionName,
                          const std::string& path)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        connectionName, path, "xyz.openbmc_project.Inventory.Decorator.Asset",
        context,
        [asyncResp](const boost::system::error_code& ec,
                    const std::vector<
                        std::pair<std::string, dbus::utility::DbusVariantType>>&
                        propertiesList) {
        if (ec)
        {
            // this interface isn't necessary
            return;
        }

        const std::string* partNumber = nullptr;
        const std::string* serialNumber = nullptr;
        const std::string* manufacturer = nullptr;
        const std::string* model = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
            partNumber, "SerialNumber", serialNumber, "Manufacturer",
            manufacturer, "Model", model);

        if (!success)
        {
            messages::internalError(asyncResp->res);
            return;
        }

        if (partNumber != nullptr)
        {
            asyncResp->res.jsonValue["PartNumber"] = *partNumber;
        }

        if (serialNumber != nullptr)
        {
            asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
        }

        if (manufacturer != nullptr)
        {
            asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
        }

        if (model != nullptr)
        {
            asyncResp->res.jsonValue["Model"] = *model;
        }
    });
}

inline void getDrivePresent(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const std::string& connectionName,
                            const std::string& path)
{
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<bool>(
        connectionName, path, "xyz.openbmc_project.Inventory.Item", "Present",
        requestContext,
        [asyncResp, path](const boost::system::error_code& ec,
                          const bool isPresent) {
        // this interface isn't necessary, only check it if
        // we get a good return
        if (ec)
        {
            return;
        }

        if (!isPresent)
        {
            asyncResp->res.jsonValue["Status"]["State"] = "Absent";
        }
    });
}

inline void getDriveState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& connectionName,
                          const std::string& path)
{
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<bool>(
        connectionName, path, "xyz.openbmc_project.State.Drive", "Rebuilding",
        requestContext,
        [asyncResp](const boost::system::error_code& ec, const bool updating) {
        // this interface isn't necessary, only check it
        // if we get a good return
        if (ec)
        {
            return;
        }

        // updating and disabled in the backend shouldn't be
        // able to be set at the same time, so we don't need
        // to check for the race condition of these two
        // calls
        if (updating)
        {
            asyncResp->res.jsonValue["Status"]["State"] = "Updating";
        }
    });
}

inline std::optional<std::string> convertDriveType(const std::string& type)
{
    if (type == "xyz.openbmc_project.Inventory.Item.Drive.DriveType.HDD")
    {
        return "HDD";
    }
    if (type == "xyz.openbmc_project.Inventory.Item.Drive.DriveType.SSD")
    {
        return "SSD";
    }

    return std::nullopt;
}

inline void addResetLinks(nlohmann::json& driveReset,
                          const std::string& driveId,
                          const std::string& chassisId)
{
    driveReset["target"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "Drives", driveId, "Actions",
        "Drive.Reset");
    driveReset["@Redfish.ActionInfo"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                     "Drives", driveId, "ResetActionInfo");
}

inline std::optional<std::string> convertDriveProtocol(const std::string& proto)
{
    if (proto == "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol.SAS")
    {
        return "SAS";
    }
    if (proto == "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol.SATA")
    {
        return "SATA";
    }
    if (proto == "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol.NVMe")
    {
        return "NVMe";
    }
    if (proto == "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol.FC")
    {
        return "FC";
    }
    if (proto == "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol.eMMC")
    {
        return "eMMC";
    }

    return std::nullopt;
}

inline void
    getDriveItemProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& driveId,
                           const std::optional<std::string>& chassisId,
                           const std::string& connectionName,
                           const std::string& path, bool hasDriveState)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        connectionName, path, "xyz.openbmc_project.Inventory.Item.Drive",
        context,
        [asyncResp, driveId, chassisId, hasDriveState](
            const boost::system::error_code& ec,
            const std::vector<std::pair<
                std::string, dbus::utility::DbusVariantType>>& propertiesList) {
        if (ec)
        {
            // this interface isn't required
            return;
        }
        const std::string* encryptionStatus = nullptr;
        const bool* isLocked = nullptr;
        for (const std::pair<std::string, dbus::utility::DbusVariantType>&
                 property : propertiesList)
        {
            const std::string& propertyName = property.first;
            if (propertyName == "Type")
            {
                const std::string* value =
                    std::get_if<std::string>(&property.second);
                if (value == nullptr)
                {
                    // illegal property
                    BMCWEB_LOG_ERROR << "Illegal property: Type";
                    messages::internalError(asyncResp->res);
                    return;
                }

                std::optional<std::string> mediaType = convertDriveType(*value);
                if (!mediaType)
                {
                    BMCWEB_LOG_ERROR << "Unsupported DriveType Interface: "
                                     << *value;
                    messages::internalError(asyncResp->res);
                    return;
                }

                asyncResp->res.jsonValue["MediaType"] = *mediaType;
            }
            else if (propertyName == "Capacity")
            {
                const uint64_t* capacity =
                    std::get_if<uint64_t>(&property.second);
                if (capacity == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Illegal property: Capacity";
                    messages::internalError(asyncResp->res);
                    return;
                }
                if (*capacity == 0)
                {
                    // drive capacity not known
                    continue;
                }

                asyncResp->res.jsonValue["CapacityBytes"] = *capacity;
            }
            else if (propertyName == "Protocol")
            {
                const std::string* value =
                    std::get_if<std::string>(&property.second);
                if (value == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Illegal property: Protocol";
                    messages::internalError(asyncResp->res);
                    return;
                }

                std::optional<std::string> proto = convertDriveProtocol(*value);
                if (!proto)
                {
                    BMCWEB_LOG_ERROR << "Unsupported DrivePrototype Interface: "
                                     << *value;
                    messages::internalError(asyncResp->res);
                    return;
                }
                asyncResp->res.jsonValue["Protocol"] = *proto;
            }
            else if (propertyName == "PredictedMediaLifeLeftPercent")
            {
                const uint8_t* lifeLeft =
                    std::get_if<uint8_t>(&property.second);
                if (lifeLeft == nullptr)
                {
                    BMCWEB_LOG_ERROR
                        << "Illegal property: PredictedMediaLifeLeftPercent";
                    messages::internalError(asyncResp->res);
                    return;
                }
                // 255 means reading the value is not supported
                if (*lifeLeft != 255)
                {
                    asyncResp->res.jsonValue["PredictedMediaLifeLeftPercent"] =
                        *lifeLeft;
                }
            }
            else if (propertyName == "Resettable" && hasDriveState)
            {
                const bool* value = std::get_if<bool>(&property.second);
                // If Resettable flag is not present, its not considered a
                // failure.
                if (value != nullptr && *value && chassisId.has_value())
                {
                    addResetLinks(
                        asyncResp->res.jsonValue["Actions"]["#Drive.Reset"],
                        driveId, *chassisId);
                }
            }
            else if (propertyName == "EncryptionStatus")
            {
                encryptionStatus = std::get_if<std::string>(&property.second);
                if (encryptionStatus == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Illegal property: EncryptionStatus";
                    messages::internalError(asyncResp->res);
                    return;
                }
            }
            else if (propertyName == "Locked")
            {
                isLocked = std::get_if<bool>(&property.second);
                if (isLocked == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Illegal property: Locked";
                    messages::internalError(asyncResp->res);
                    return;
                }
            }
        }

        if (encryptionStatus == nullptr || isLocked == nullptr ||
            *encryptionStatus ==
                "xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Unknown")
        {
            return;
        }
        if (*encryptionStatus !=
            "xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Encrypted")
        {
            //"The drive is not currently encrypted."
            asyncResp->res.jsonValue["EncryptionStatus"] =
                drive::EncryptionStatus::Unencrypted;
            return;
        }
        if (*isLocked)
        {
            //"The drive is currently encrypted and the data is not
            // accessible to the user."
            asyncResp->res.jsonValue["EncryptionStatus"] =
                drive::EncryptionStatus::Locked;
            return;
        }
        // if not locked
        // "The drive is currently encrypted but the data is accessible
        // to the user in unencrypted form."
        asyncResp->res.jsonValue["EncryptionStatus"] =
            drive::EncryptionStatus::Unlocked;
    });
}

inline void getDriveErase(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& chassisId,
                          const std::string& driveName)
{
    auto eraseUrl = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "Drives", driveName, "Actions",
        "Drive.SecureErase");
    asyncResp->res.jsonValue["Actions"]["#Drive.SecureErase"]["target"] =
        eraseUrl;
}

static void addAllDriveInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const std::string& driveId,
                            const std::string& connectionName,
                            const std::string& path,
                            const std::vector<std::string>& interfaces,
                            const std::string& chassisId)
{
    bool driveInterface = false;
    bool driveStateInterface = false;
    for (const std::string& interface : interfaces)
    {
        if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
        {
            getDriveAsset(asyncResp, connectionName, path);
        }
        else if (interface == "xyz.openbmc_project.Inventory.Item")
        {
            getDrivePresent(asyncResp, connectionName, path);
        }
        else if (interface == "xyz.openbmc_project.State.Drive")
        {
            driveStateInterface = true;
            getDriveState(asyncResp, connectionName, path);
        }
        else if (interface == "xyz.openbmc_project.Inventory.Item.Drive")
        {
            driveInterface = true;
        }
        else if (interface == "xyz.openbmc_project.Inventory.Item.DriveErase")
        {
            getDriveErase(asyncResp, chassisId, driveId);
        }
    }

    if (driveInterface)
    {
        getDriveItemProperties(asyncResp, driveId, chassisId, connectionName,
                               path, driveStateInterface);
        storage_utils::tryGetLocation(asyncResp, connectionName, path,
                                      storage_utils::driveInterface, interfaces,
                                      "/PhysicalLocation"_json_pointer);
    }
}

/**
 * Chassis drives, this URL will show all the DriveCollection
 * information
 */
inline void chassisDriveCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    // mapper call lambda
    constexpr std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, chassisId, requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            if (ec == boost::system::errc::host_unreachable)
            {
                messages::resourceNotFound(asyncResp->res, "Chassis",
                                           chassisId);
                return;
            }
            messages::internalError(asyncResp->res);
            return;
        }

        // Iterate over all retrieved ObjectPaths.
        for (const auto& [path, connectionNames] : subtree)
        {
            sdbusplus::message::object_path objPath(path);
            if (objPath.filename() != chassisId)
            {
                continue;
            }

            if (connectionNames.empty())
            {
                BMCWEB_LOG_ERROR << "Got 0 Connection names";
                continue;
            }

            asyncResp->res.jsonValue["@odata.type"] =
                "#DriveCollection.DriveCollection";
            asyncResp->res.jsonValue["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                             chassisId, "Drives");
            asyncResp->res.jsonValue["Name"] = "Drive Collection";

            // Association lambda
            dbus_utils::getAssociationEndPoints(
                path + "/drive", requestContext,
                [asyncResp,
                 chassisId](const boost::system::error_code& ec3,
                            const dbus::utility::MapperEndPoints& resp) {
                if (ec3)
                {
                    BMCWEB_LOG_ERROR << "Error in chassis Drive association ";
                }
                nlohmann::json& members = asyncResp->res.jsonValue["Members"];
                // important if array is empty
                members = nlohmann::json::array();

                std::vector<std::string> leafNames;
                for (const auto& drive : resp)
                {
                    sdbusplus::message::object_path drivePath(drive);
                    leafNames.emplace_back(drivePath.filename());
                }

                std::sort(leafNames.begin(), leafNames.end(),
                          AlphanumLess<std::string>());

                for (const auto& leafName : leafNames)
                {
                    nlohmann::json::object_t member;
                    member["@odata.id"] = crow::utility::urlFromPieces(
                        "redfish", "v1", "Chassis", chassisId, "Drives",
                        leafName);
                    members.emplace_back(std::move(member));
                    // navigation links will be registered in next patch set
                }
                asyncResp->res.jsonValue["Members@odata.count"] = resp.size();
            }); // end association lambda

        } // end Iterate over all retrieved ObjectPaths
    });
}

inline void requestRoutesChassisDrive(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Drives/")
        .privileges(redfish::privileges::getDriveCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(chassisDriveCollectionGet, std::ref(app)));
}

inline void storageVolumes(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const sdbusplus::message::object_path& storagePath,
    std::function<void(const boost::system::error_code& ec,
                       const std::vector<std::string>& volPaths)>&& cb)
{
    // Get list of attached volumes
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Volume"};
    managedStore::ManagedObjectStoreContext context(asyncResp);
    redfish::storage_utils::getAssociatedSubTreePaths(
        storagePath / "containing",
        sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
        interfaces, context,
        [cb](const boost::system::error_code& ec,
             const std::vector<std::string>& volPaths) { cb(ec, volPaths); });
}

inline void buildDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& chassisId,
                       const std::string& driveName,
                       const boost::system::error_code& ec,
                       const dbus::utility::MapperGetSubTreeResponse& subtree)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
        messages::internalError(asyncResp->res);
        return;
    }

    // Iterate over all retrieved ObjectPaths.
    for (const auto& [path, connectionNames] : subtree)
    {
        sdbusplus::message::object_path objPath(path);
        if (objPath.filename() != driveName)
        {
            continue;
        }

        if (connectionNames.empty())
        {
            BMCWEB_LOG_ERROR << "Got 0 Connection names";
            continue;
        }

        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Chassis", chassisId, "Drives", driveName);

        asyncResp->res.jsonValue["@odata.type"] = "#Drive.v1_7_0.Drive";
        asyncResp->res.jsonValue["Name"] = driveName;
        asyncResp->res.jsonValue["Id"] = driveName;
        // default it to Enabled
        asyncResp->res.jsonValue["Status"]["State"] = "Enabled";

        nlohmann::json::object_t linkChassisNav;
        linkChassisNav["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId);
        asyncResp->res.jsonValue["Links"]["Chassis"] = linkChassisNav;

        // mapper call chassis
        storage_utils::findStorage(
            asyncResp, driveName,
            [asyncResp,
             driveName](const sdbusplus::message::object_path& storagePath) {
            storage_utils::getSystemPathFromStorage(
                asyncResp, storagePath,
                [asyncResp, storagePath,
                 driveName](std::optional<std::string_view> systemPath) {
                std::string systemName =
                    systemPath ? std::filesystem::path(*systemPath).filename()
                               : "system";
                storageVolumes(
                    asyncResp, storagePath,
                    [asyncResp, systemName, driveName](
                        const boost::system::error_code& ec,
                        const dbus::utility::MapperGetSubTreePathsResponse&
                            volumeList) {
                    nlohmann::json::array_t volumes;
                    if (ec || volumeList.empty())
                    {
                        // No association found, just return.
                        return;
                    }

                    for (const std::string& path : volumeList)
                    {
                        std::string id =
                            sdbusplus::message::object_path(path).filename();
                        if (id.empty())
                        {
                            // Empty list, just return.
                            return;
                        }
                        nlohmann::json::object_t volume;
                        volume["@odata.id"] = crow::utility::urlFromPieces(
                            "redfish", "v1", "Systems", systemName, "Storage",
                            driveName, "Volumes", id);
                        volumes.emplace_back(volume);
                    }
                    asyncResp->res.jsonValue["Links"]["Volumes@odata.count"] =
                        volumes.size();
                    asyncResp->res.jsonValue["Links"]["Volumes"] =
                        std::move(volumes);
                });
            });
        });

        addAllDriveInfo(asyncResp, driveName, connectionNames[0].first, path,
                        connectionNames[0].second, chassisId);
    }
}

inline void
    matchAndFillDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& chassisId,
                      const std::string& driveName,
                      const std::vector<std::string>& resp)
{
    for (const std::string& drivePath : resp)
    {
        sdbusplus::message::object_path path(drivePath);
        std::string leaf = path.filename();
        if (leaf != driveName)
        {
            continue;
        }
        //  mapper call drive
        constexpr std::array<std::string_view, 1> driveInterface = {
            "xyz.openbmc_project.Inventory.Item.Drive"};
        managedStore::ManagedObjectStoreContext requestContext(asyncResp);
        managedStore::GetManagedObjectStore()->getSubTree(
            "/xyz/openbmc_project/inventory", 0, driveInterface, requestContext,
            [asyncResp, chassisId, driveName](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreeResponse& subtree) {
            buildDrive(asyncResp, chassisId, driveName, ec, subtree);
        });
        return;
    }
    messages::resourceNotFound(asyncResp->res, "#Drive.v1_7_0.Drive",
                               driveName);
}

struct EraseParams
{

    enum Action : std::uint8_t
    {
        CryptoErase,
        BlockErase,
        Overwrite,
    } action;

    static std::optional<EraseParams>
        parse(const crow::Request& req,
              const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
    {
        // Redfish allows sanitizationType to be defaulted, though we don't
        // know a good default at present, leave it mandatory.
        std::string sanitizationType;

        if (!json_util::readJsonAction(req, asyncResp->res, "SanitizationType",
                                       sanitizationType))
        {
            BMCWEB_LOG_DEBUG << "Missing request json parameters";
            return std::nullopt;
        }

        Action action = Action::CryptoErase;
        if (sanitizationType == "BlockErase")
        {
            action = Action::BlockErase;
        }
        else if (sanitizationType == "CryptographicErase")
        {
            action = Action::CryptoErase;
        }
        else if (sanitizationType == "Overwrite")
        {
            // Redfish defines an optional "OverwritePasses" parameter, we
            // don't handle that at the moment. If the client passes it, the
            // readJsonAction will fail it.
            action = Action::Overwrite;
        }
        else
        {
            messages::actionParameterValueNotInList(
                asyncResp->res, sanitizationType, "SanitizationType",
                "Drive.SecureErase");
            return std::nullopt;
        }

        return EraseParams{.action = action};
    }

    std::string actionName() const
    {
        switch (action)
        {
            case Action::CryptoErase:
                return "xyz.openbmc_project.Inventory.Item.DriveErase.EraseAction.CryptoErase";
            case Action::BlockErase:
                return "xyz.openbmc_project.Inventory.Item.DriveErase.EraseAction.BlockErase";
            case Action::Overwrite:
                return "xyz.openbmc_project.Inventory.Item.DriveErase.EraseAction.Overwrite";
        }
        return "unreachable";
    }
};

inline void eraseTaskUpdate(bool eraseInProgress,
                            const std::shared_ptr<task::TaskData>& taskData,
                            const std::string& connectionName,
                            const std::string& drivePath)
{
    if (eraseInProgress)
    {
        // nothing to do
        return;
    }

    // has finished, either success or failure
    taskData->stopMonitor();
    
    // Have to create a new Resp here as we cannot use the original resp or it never goes out of scope
    // This resp will not have a strand associated with it which is okay because this will never be
    // multithreaded
    auto resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
    managedStore::ManagedObjectStoreContext context(resp);
    redfish::storage_utils::getAllProperties(
        connectionName, drivePath,
        "xyz.openbmc_project.Inventory.Item.DriveErase", context,
        [taskData](const boost::system::error_code& ec,
                   const std::vector<std::pair<
                       std::string, dbus::utility::DbusVariantType>>& props) {
        if (ec)
        {
            taskData->messages.emplace_back(messages::internalError());
            taskData->state = "Exception";
            taskData->complete(
                nlohmann::json(),
                boost::beast::http::status::internal_server_error);
            return;
        }

        std::string errorName;
        std::string errorDescription;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), props, "ErrorName", errorName,
            "ErrorDescription", errorDescription);

        if (!success)
        {
            taskData->messages.emplace_back(messages::internalError());
            taskData->state = "Exception";
            taskData->complete(
                nlohmann::json(),
                boost::beast::http::status::internal_server_error);
            return;
        }

        if (errorName.empty())
        {
            // Erase Success
            taskData->state = "Completed";
            taskData->percentComplete = 100;
            taskData->messages.emplace_back(messages::success());
            taskData->complete();
        }
        else
        {
            // Erase Failed
            bmcweb::AsyncResp resp(nullptr);
            storageAddDbusError(resp.res, "eraseTaskUpdate", "", errorName,
                                errorDescription);
            for (auto& m :
                 resp.res.jsonValue["error"][messages::messageAnnotation])
            {
                taskData->messages.emplace_back(m);
            }
            taskData->state = "Exception";
            taskData->complete(std::move(resp.res.jsonValue),
                               resp.res.result());
        }
    });
}

inline bool eraseTaskHandler(sdbusplus::message_t& msg,
                             const std::shared_ptr<task::TaskData>& taskData,
                             const std::string& connectionName,
                             const std::string& drivePath)
{
    dbus::utility::DBusPropertiesMap props;
    std::string iface;
    msg.read(iface, props);

    if (iface != "xyz.openbmc_project.Inventory.Item.DriveErase")
    {
        BMCWEB_LOG_DEBUG << "eraseTaskHandler wrong interface";
        return !task::completed;
    }

    std::optional<bool> inProgress;
    std::optional<double> erasePercentage;
    sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), props,
                                       "EraseInProgress", inProgress,
                                       "ErasePercentage", erasePercentage);

    if (erasePercentage)
    {
        BMCWEB_LOG_DEBUG << "eraseTaskHandler update erasePercentage "
                         << *erasePercentage;
        taskData->percentComplete = static_cast<int>(*erasePercentage);
    }

    if (inProgress)
    {
        BMCWEB_LOG_DEBUG << "eraseTaskHandler update iniProgress "
                         << *inProgress;
        eraseTaskUpdate(*inProgress, taskData, connectionName, drivePath);
    }

    // completion is handled asynchronously so always return !completed
    return !task::completed;
}

// Clang believes that req is unused even though its captured in lambda
inline void eraseDrive(const crow::Request& req,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& connectionName,
                       const std::string& drivePath, const EraseParams& params)
{
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [req, asyncResp, connectionName, drivePath
         ](const boost::system::error_code ec,
                 const sdbusplus::message_t& msg) {
        // Failure returned from NVMe
        const ::sd_bus_error* sd_err = msg.get_error();
        if (sd_err != nullptr)
        {
            storageAddDbusError(asyncResp->res, "Drive Erase", "", sd_err->name,
                                sd_err->message);
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_DEBUG << "Erase dbus error " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        // success, create the async task
        BMCWEB_LOG_DEBUG << "erase started";
        std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
            [connectionName,
             drivePath](const boost::system::error_code& err,
                        sdbusplus::message_t& taskMsg,
                        const std::shared_ptr<task::TaskData>& taskData) {
            if (err)
            {
                // Internal error in property signal callback?
                BMCWEB_LOG_ERROR << drivePath << ": Error in task";
                taskData->messages.emplace_back(messages::internalError());
                taskData->state = "Cancelled";
                return task::completed;
            }

            return eraseTaskHandler(taskMsg, taskData, connectionName,
                                    drivePath);
        },
            "type='signal',interface='org.freedesktop.DBus.Properties',"
            "member='PropertiesChanged',arg0='xyz.openbmc_project.Inventory.Item.DriveErase',"
            "path='" +
                drivePath + "'");

        task->startTimer(std::chrono::minutes(180));
        task->populateResp(asyncResp->res);
        task->payload.emplace(req);

        // Erase may have completed prior to Task watching for signals, so poll
        // once.
        managedStore::ManagedObjectStoreContext context(asyncResp);
        redfish::storage_utils::getProperty<bool>(
            connectionName, drivePath,
            "xyz.openbmc_project.Inventory.Item.DriveErase", "EraseInProgress", context,
            [task, connectionName,
             drivePath](const boost::system::error_code& ec2, bool inProgress) {
            if (ec2)
            {
                BMCWEB_LOG_DEBUG << "erase poll error: " << ec2;
                return;
            }

            eraseTaskUpdate(inProgress, task, connectionName, drivePath);
        });
    },
        connectionName, drivePath,
        "xyz.openbmc_project.Inventory.Item.DriveErase", "Erase",
        params.actionName());
}

inline void
    matchAndEraseDrive(const crow::Request& req,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::vector<std::string>& drivePaths,
                       const std::string& driveName, const EraseParams& params)
{
    // Match the driveName
    int found = 0;
    std::string drivePath;
    for (const std::string& d : drivePaths)
    {
        sdbusplus::message::object_path path(d);
        std::string leaf = path.filename();
        if (leaf == driveName)
        {
            found++;
            drivePath = d;
        }
    }

    if (found > 1)
    {
        // Sanity check
        BMCWEB_LOG_DEBUG << "Multiple drives match name " << driveName;
        messages::internalError(asyncResp->res);
        return;
    }
    if (found == 0)
    {
        messages::resourceNotFound(asyncResp->res, "#Drive.v1_7_0.Drive",
                                   driveName);
        return;
    }

    // Find the connection
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.DriveErase"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getDbusObject(
        drivePath, interfaces, requestContext,
        [req, asyncResp, params,
         drivePath](const boost::system::error_code& ec,
                    const dbus::utility::MapperGetObject& services) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        if (services.size() != 1)
        {
            BMCWEB_LOG_DEBUG << "multiple serviceInterfaces entries";
            messages::internalError(asyncResp->res);
            return;
        }
        auto connectionName = services.front().first;

        // Perform the erase
        eraseDrive(req, asyncResp, connectionName, drivePath, params);
    });
}

// Find Chassis with chassisId and the Drives associated to it.
inline void findChassisDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& chassisId,
                      std::function<void(const boost::system::error_code ec3,
                                         const std::vector<std::string>& resp)>&&
                          cb)
{
    constexpr std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};
    // mapper call chassis
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, chassisId, cb, requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            messages::internalError(asyncResp->res);
            return;
        }

        // Iterate over all retrieved ObjectPaths.
        int found = 0;
        std::string chassisPath;
        for (const auto& [path, connectionNames] : subtree)
        {
            sdbusplus::message::object_path objPath(path);
            if (objPath.filename() != chassisId)
            {
                continue;
            }

            if (connectionNames.empty())
            {
                BMCWEB_LOG_ERROR << "Got 0 Connection names";
                continue;
            }
            found++;
            chassisPath = path;
        }
        if (found > 1)
        {
            BMCWEB_LOG_ERROR << "Multiple chassis match";
            messages::internalError(asyncResp->res);
            return;
        }
        if (found == 0)
        {
            messages::resourceNotFound(asyncResp->res,
                                       "#Chassis.v1_14_0.Chassis", chassisId);
            return;
        }
        dbus_utils::getAssociationEndPoints(chassisPath + "/drive",
                                            requestContext, cb);
    });
}

inline void
    handleChassisDriveGet(crow::App& app, const crow::Request& req,
                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& chassisId,
                          const std::string& driveName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    findChassisDrive(asyncResp, chassisId,
                     [asyncResp, chassisId,
                      driveName](const boost::system::error_code ec,
                                 const std::vector<std::string>& resp) {
        if (ec)
        {
            return; // no drives = no failures
        }
        matchAndFillDrive(asyncResp, chassisId, driveName, resp);
    });
}

inline void handleDriveSecureErase(crow::App& app, const crow::Request& req,
                                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                                   const std::string& chassisId,
                                   const std::string& driveName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    auto p = EraseParams::parse(req, asyncResp);
    if (!p)
    {
        return;
    }
    EraseParams params = *p;

    // Find paths of drives associated with the ChassisId
    findChassisDrive(asyncResp, chassisId,
                     [req, asyncResp, chassisId, driveName,
                      params](const boost::system::error_code ec,
                              const std::vector<std::string>& drivePaths) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
            messages::internalError(asyncResp->res);
            return;
        }
        matchAndEraseDrive(req, asyncResp, drivePaths, driveName, params);
    });
}

/**
 * This URL will show the drive interface for the specific drive in the chassis
 */
inline void requestRoutesChassisDriveName(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Drives/<str>/")
        .privileges(redfish::privileges::getChassis)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleChassisDriveGet, std::ref(app)));

    BMCWEB_ROUTE(
        app, "/redfish/v1/Chassis/<str>/Drives/<str>/Actions/Drive.SecureErase")
        .privileges(redfish::privileges::postDrive)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(handleDriveSecureErase, std::ref(app)));
}

inline void setResetType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& driveId, const std::string& action,
                         const dbus::utility::MapperGetSubTreeResponse& subtree)
{
    auto driveState =
        std::find_if(subtree.begin(), subtree.end(), [&driveId](auto& object) {
        const sdbusplus::message::object_path path(object.first);
        return path.filename() == driveId;
    });

    if (driveState == subtree.end())
    {
        messages::resourceNotFound(asyncResp->res, "Drive Action", driveId);
        return;
    }

    const std::string& path = driveState->first;
    const std::vector<std::pair<std::string, std::vector<std::string>>>&
        connectionNames = driveState->second;

    if (connectionNames.size() != 1)
    {
        BMCWEB_LOG_ERROR << "Connection size " << connectionNames.size()
                         << ", not equal to 1";
        messages::internalError(asyncResp->res);
        return;
    }

    managedStore::GetManagedObjectStore()->setProperty(
        connectionNames[0].first, path, "xyz.openbmc_project.State.Drive",
        "RequestedDriveTransition", action,
        [asyncResp, action](const boost::system::error_code ec) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "[Set] Bad D-Bus request error for " << action
                             << " : " << ec;
            messages::internalError(asyncResp->res);
            return;
        }
        messages::success(asyncResp->res);
    });
}

/**
 * Performs drive reset action.
 *
 * @param[in] asyncResp - Shared pointer for completing asynchronous calls
 * @param[in] driveId   - D-bus filename to identify the Drive
 * @param[in] resetType - Reset type for the Drive
 */
inline void
    performDriveReset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& driveId,
                      std::optional<std::string> resetType)
{
    std::string action;
    if (!resetType || *resetType == "PowerCycle")
    {
        action = "xyz.openbmc_project.State.Drive.Transition.Powercycle";
    }
    else if (*resetType == "ForceReset")
    {
        action = "xyz.openbmc_project.State.Drive.Transition.Reboot";
    }
    else
    {
        BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
                         << *resetType;
        messages::actionParameterNotSupported(asyncResp->res, *resetType,
                                              "ResetType");
        return;
    }

    BMCWEB_LOG_DEBUG << "Reset Drive with " << action;

    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.State.Drive"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, driveId,
         action](const boost::system::error_code& ec,
                 const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "DBUS response error";
            messages::internalError(asyncResp->res);
            return;
        }
        setResetType(asyncResp, driveId, action, subtree);
    });
}

inline void
    handleChassisDriveReset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const std::string& driveId,
                            const std::optional<std::string>& resetType,
                            const std::vector<std::string>& drives)
{
    std::unordered_set<std::string> drivesMap(drives.begin(), drives.end());
    constexpr std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Drive",
        "xyz.openbmc_project.State.Drive"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, driveId, resetType, drivesMap, requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Drive mapper call error ";
            messages::internalError(asyncResp->res);
            return;
        }

        auto drive = std::find_if(
            subtree.begin(), subtree.end(),
            [&driveId, &drivesMap](
                const std::pair<std::string, dbus::utility::MapperServiceMap>&
                    object) {
            return sdbusplus::message::object_path(object.first).filename() ==
                       driveId &&
                   drivesMap.contains(object.first);
        });

        if (drive == subtree.end())
        {
            messages::resourceNotFound(asyncResp->res, "Drive Action Reset",
                                       driveId);
            return;
        }

        const std::string& drivePath = drive->first;
        const dbus::utility::MapperServiceMap& driveConnections = drive->second;
        if (driveConnections.size() != 1)
        {
            BMCWEB_LOG_ERROR << "Connection size " << driveConnections.size()
                             << ", not equal to 1";
            messages::internalError(asyncResp->res);
            return;
        }

        bool driveInterface = false;
        bool driveStateInterface = false;
        for (const std::string& interface : driveConnections[0].second)
        {
            if (interface == "xyz.openbmc_project.Inventory.Item.Drive")
            {
                driveInterface = true;
            }
            if (interface == "xyz.openbmc_project.State.Drive")
            {
                driveStateInterface = true;
            }
        }
        if (!driveInterface || !driveStateInterface)
        {
            BMCWEB_LOG_ERROR << "Drive does not have the required interfaces ";
            messages::internalError(asyncResp->res);
            return;
        }

        dbus_utils::getProperty<bool>(
            driveConnections[0].first, drivePath,
            "xyz.openbmc_project.Inventory.Item.Drive", "Resettable",
            requestContext,
            [asyncResp, driveId, resetType](
                const boost::system::error_code propEc, bool resettable) {
            if (propEc)
            {
                BMCWEB_LOG_ERROR << "Failed to get resettable property ";
                messages::internalError(asyncResp->res);
                return;
            }
            if (!resettable)
            {
                messages::actionNotSupported(
                    asyncResp->res, "The drive does not support resets.");
                return;
            }
            performDriveReset(asyncResp, driveId, resetType);
        });
    });
}

inline void handlePostDriveResetAction(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& driveId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    BMCWEB_LOG_DEBUG << "Post Drive Reset.";

    nlohmann::json jsonRequest;
    std::optional<std::string> resetType;
    if (json_util::processJsonFromRequest(asyncResp->res, req, jsonRequest) &&
        !jsonRequest["ResetType"].empty())
    {
        resetType = jsonRequest["ResetType"];
    }

    findChassisDrive(asyncResp, chassisId,
                     [asyncResp, driveId,
                      resetType](const boost::system::error_code ec,
                                 const std::vector<std::string>& drives) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "failed to find drives";
            messages::internalError(asyncResp->res);
            return; // no drives = no failures
        }
        handleChassisDriveReset(asyncResp, driveId, resetType, drives);
    });
}

/**
 * DriveResetAction class supports the POST method for the Reset (reboot)
 * action.
 */
inline void requestDriveResetAction(App& app)
{
    BMCWEB_ROUTE(app,
                 "/redfish/v1/Chassis/<str>/Drives/<str>/Actions/Drive.Reset/")
        .privileges(redfish::privileges::postDrive)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(handlePostDriveResetAction, std::ref(app)));
}

inline void handleChassisDriveResetActionInfo(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& driveId,
    const std::vector<std::string>& drives)
{
    std::unordered_set<std::string> drivesMap(drives.begin(), drives.end());

    constexpr std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Drive",
        "xyz.openbmc_project.State.Drive"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, chassisId, driveId, drivesMap, requestContext](
            const boost::system::error_code ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Drive mapper call error";
            messages::internalError(asyncResp->res);
            return;
        }

        auto drive = std::find_if(
            subtree.begin(), subtree.end(),
            [&driveId, &drivesMap](
                const std::pair<std::string,
                                std::vector<std::pair<
                                    std::string, std::vector<std::string>>>>&
                    object) {
            return sdbusplus::message::object_path(object.first).filename() ==
                       driveId &&
                   drivesMap.contains(object.first);
        });

        if (drive == subtree.end())
        {
            messages::resourceNotFound(asyncResp->res, "Drive ResetActionInfo",
                                       driveId);
            return;
        }

        const std::string& drivePath = drive->first;
        const dbus::utility::MapperServiceMap& driveConnections = drive->second;

        if (driveConnections.size() != 1)
        {
            BMCWEB_LOG_ERROR << "Connection size " << driveConnections.size()
                             << ", not equal to 1";
            messages::internalError(asyncResp->res);
            return;
        }

        bool driveInterface = false;
        bool driveStateInterface = false;
        for (const std::string& interface : driveConnections[0].second)
        {
            if (interface == "xyz.openbmc_project.Inventory.Item.Drive")
            {
                driveInterface = true;
            }
            if (interface == "xyz.openbmc_project.State.Drive")
            {
                driveStateInterface = true;
            }
        }
        if (!driveInterface || !driveStateInterface)
        {
            BMCWEB_LOG_ERROR << "Drive does not have the required interfaces ";
            messages::internalError(asyncResp->res);
            return;
        }

        dbus_utils::getProperty<bool>(
            driveConnections[0].first, drivePath,
            "xyz.openbmc_project.Inventory.Item.Drive", "Resettable",
            requestContext,
            [asyncResp, chassisId,
             driveId](const boost::system::error_code propEc, bool resettable) {
            if (propEc)
            {
                BMCWEB_LOG_ERROR << "Failed to get resettable property ";
                messages::internalError(asyncResp->res);
                return;
            }
            if (!resettable)
            {
                messages::actionNotSupported(
                    asyncResp->res, "The drive does not support resets.");
                return;
            }
            asyncResp->res.jsonValue["@odata.type"] =
                "#ActionInfo.v1_1_2.ActionInfo";
            asyncResp->res.jsonValue["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                             chassisId, "Drives", driveId,
                                             "ResetActionInfo");
            asyncResp->res.jsonValue["Name"] = "Reset Action Info";
            asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
            nlohmann::json::array_t parameters;
            nlohmann::json::object_t parameter;
            parameter["Name"] = "ResetType";
            parameter["Required"] = true;
            parameter["DataType"] = "String";
            nlohmann::json::array_t allowableValues;
            allowableValues.emplace_back("PowerCycle");
            allowableValues.emplace_back("ForceRestart");
            parameter["AllowableValues"] = std::move(allowableValues);
            parameters.emplace_back(parameter);
            asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
        });
    });
}

inline void handleGetDriveResetActionInfo(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& driveId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    findChassisDrive(asyncResp, chassisId,
                     [asyncResp, chassisId,
                      driveId](const boost::system::error_code ec,
                               const std::vector<std::string>& drives) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "failed to find drives";
            messages::internalError(asyncResp->res);
            return; // no drives = no failures
        }
        handleChassisDriveResetActionInfo(asyncResp, chassisId, driveId,
                                          drives);
    });
}

/**
 * DriveResetActionInfo derived class for delivering Drive
 * ResetType AllowableValues using ResetInfo schema.
 */
inline void requestRoutesDriveResetActionInfo(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Drives/<str>/ResetActionInfo/")
        .privileges(redfish::privileges::getActionInfo)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGetDriveResetActionInfo, std::ref(app)));
}

inline void getStorageControllerAsset(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::system::error_code& ec,
    const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
        propertiesList)
{
    if (ec)
    {
        // this interface isn't necessary
        BMCWEB_LOG_DEBUG << "Failed to get StorageControllerAsset";
        return;
    }

    const std::string* partNumber = nullptr;
    const std::string* serialNumber = nullptr;
    const std::string* manufacturer = nullptr;
    const std::string* model = nullptr;
    if (!sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
            partNumber, "SerialNumber", serialNumber, "Manufacturer",
            manufacturer, "Model", model))
    {
        messages::internalError(asyncResp->res);
        return;
    }

    if (partNumber != nullptr)
    {
        asyncResp->res.jsonValue["PartNumber"] = *partNumber;
    }

    if (serialNumber != nullptr)
    {
        asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
    }

    if (manufacturer != nullptr)
    {
        asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
    }

    if (model != nullptr)
    {
        asyncResp->res.jsonValue["Model"] = *model;
    }
}

inline void tryPopulateControllerNvme(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& path, const dbus::utility::MapperServiceMap& ifaces)
{
    if (storage_utils::matchServiceName(ifaces,
                                        "xyz.openbmc_project.NVMe.NVMeAdmin"))
    {
        auto& nvprop = asyncResp->res.jsonValue["NVMeControllerProperties"];
        // TODO(matt) fetch other properties, don't use hardcoded values
        nvprop["ControllerType"] = "IO";
        nvprop["NVMeVersion"] = "1.4";
    }

    if (auto service = storage_utils::matchServiceName(
            ifaces, "xyz.openbmc_project.Software.ExtendedVersion"))
    {
        managedStore::ManagedObjectStoreContext context(asyncResp);
        redfish::storage_utils::getProperty<std::string>(
            *service, path, "xyz.openbmc_project.Software.ExtendedVersion",
            "ExtendedVersion", context,
            [asyncResp](const boost::system::error_code& ec,
                        const std::string& extVers) {
            if (ec)
            {
                return;
            }

            std::string v(
                "xyz.openbmc_project.NVMe.ControllerFirmwareVersion:");
            if (extVers.starts_with(v))
            {
                asyncResp->res.jsonValue["FirmwareVersion"] =
                    extVers.substr(v.size());
            }
        });
    }
}

inline void tryPopulateControllerSecurity(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::urls::url& controllerUrl,
    const dbus::utility::MapperServiceMap& ifaces)
{
    if (!storage_utils::matchServiceName(
            ifaces,
            "xyz.openbmc_project.Inventory.Item.StorageControllerSecurity"))
    {
        return;
    }

    boost::urls::url sendUrl(controllerUrl);
    crow::utility::appendUrlPieces(sendUrl, "Actions",
                                   "StorageController.SecuritySend");
    boost::urls::url receiveUrl(controllerUrl);
    crow::utility::appendUrlPieces(receiveUrl, "Actions",
                                   "StorageController.SecurityReceive");

    auto& actions = asyncResp->res.jsonValue["Actions"];
    actions["#StorageController.SecuritySend"]["target"] = sendUrl;
    actions["#StorageController.SecurityReceive"]["target"] = receiveUrl;
}

inline void storageCtrlAttachedVolumes(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const sdbusplus::message::object_path& controllerPath,
    std::function<void(const boost::system::error_code& ec,
                       const std::vector<std::string>& volPaths)>&&
        cb)
{
    // Get list of attached volumes
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Volume"};
    managedStore::ManagedObjectStoreContext context(asyncResp);
    redfish::storage_utils::getAssociatedSubTreePaths(
        controllerPath / "attaching",
        sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
        interfaces, context,
        [cb](const boost::system::error_code& ec,
             const std::vector<std::string>& volPaths) { cb(ec, volPaths); });
}

inline void populateStorageControllerAttached(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& storageId,
    const std::string& path)
{
    storageCtrlAttachedVolumes(
        asyncResp, path, [asyncResp, systemName,
               storageId](const boost::system::error_code& ec,
                          const std::vector<std::string>& attachedVolumeList) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "populating attached volumes failed";
            messages::internalError(asyncResp->res);
            return;
        }
        std::vector<boost::urls::url> redfishVolumes;
        for (const std::string& volumePath : attachedVolumeList)
        {
            std::string id =
                sdbusplus::message::object_path(volumePath).filename();
            if (id.empty())
            {
                BMCWEB_LOG_ERROR << "Failed to find filename in " << volumePath;
                return;
            }
            boost::urls::url volumeUrl = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", systemName, "Storage", storageId,
                "Volumes", id);
            redfishVolumes.emplace_back(volumeUrl);
        }
        asyncResp->res.jsonValue["Links"]["AttachedVolumes"] = redfishVolumes;
    });
}

inline void populateStorageController(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& storageId,
    const std::string& controllerId, const std::string& path,
    const dbus::utility::MapperServiceMap& ifaces)
{
    if (ifaces.size() != 1)
    {
        BMCWEB_LOG_ERROR << "Connection size " << ifaces.size()
                         << ", greater than 1";
        messages::internalError(asyncResp->res);
        return;
    }

    const std::string& connectionName = ifaces.front().first;
    const std::vector<std::string>& interfaces = ifaces.front().second;

    asyncResp->res.jsonValue["@odata.type"] =
        "#StorageController.v1_7_0.StorageController";
    auto url = crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                            systemName, "Storage", storageId,
                                            "Controllers", controllerId);
    asyncResp->res.jsonValue["@odata.id"] = url;
    asyncResp->res.jsonValue["Name"] = controllerId;
    asyncResp->res.jsonValue["Id"] = controllerId;
    asyncResp->res.jsonValue["Status"]["State"] = "Enabled";

    storage_utils::tryGetLocation(asyncResp, connectionName, path,
                                  storage_utils::controllerInterface,
                                  interfaces);
    populateStorageControllerAttached(asyncResp, systemName, storageId, path);
    tryPopulateControllerNvme(asyncResp, path, ifaces);
    tryPopulateMetricCollection(asyncResp, path, ifaces, systemName, storageId,
                                controllerId);
    tryPopulateControllerSecurity(asyncResp, url, ifaces);
    if (enableCustomSSD)
    {
        populateCustomSSDInfo(asyncResp, ifaces, path);
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<bool>(
        connectionName, path, "xyz.openbmc_project.Inventory.Item", "Present",
        context,
        [asyncResp](const boost::system::error_code& ec, bool isPresent) {
        // this interface isn't necessary, only check it
        // if we get a good return
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "Failed to get Present property";
            return;
        }
        if (!isPresent)
        {
            asyncResp->res.jsonValue["Status"]["State"] = "Absent";
        }
    });

    managedStore::GetManagedObjectStore()->getAllProperties(
        connectionName, path, "xyz.openbmc_project.Inventory.Decorator.Asset",
        context,
        [asyncResp](const boost::system::error_code& ec,
                    const std::vector<
                        std::pair<std::string, dbus::utility::DbusVariantType>>&
                        propertiesList) {
        getStorageControllerAsset(asyncResp, ec, propertiesList);
    });
}

inline void securitySendAction(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& path, const dbus::utility::MapperServiceMap& ifaces,
    uint8_t proto, uint16_t protoSpecific, const std::string& dataBase64)
{
    std::string dataString;
    if (!crow::utility::base64Decode(dataBase64, dataString))
    {
        BMCWEB_LOG_DEBUG << "base data base64decode";
        messages::actionParameterValueFormatError(
            asyncResp->res, "<data>", "Data", "StorageController.SecuritySend");
        return;
    }

    // base64Decode outputs a string not bytes
    uint8_t* buffer = reinterpret_cast<uint8_t*>(dataString.data()); // NOLINT
    std::vector<uint8_t> data(buffer, buffer + dataString.size()); // NOLINT

    auto service = storage_utils::matchServiceName(
        ifaces, "xyz.openbmc_project.Inventory.Item.StorageControllerSecurity");
    if (!service)
    {
        BMCWEB_LOG_DEBUG << "No servicename";
        messages::internalError(asyncResp->res);
        return;
    }

    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp](const boost::system::error_code ec,
                    const sdbusplus::message_t& msg) {
        // Failure returned from NVMe
        const ::sd_bus_error* sd_err = msg.get_error();
        if (sd_err != nullptr)
        {
            messages::generalError(asyncResp->res);
            BMCWEB_LOG_DEBUG << "SecuritySend NVMe error";
            if (sd_err->message != nullptr)
            {
                BMCWEB_LOG_DEBUG << "Error: " << sd_err->name << " message "
                                 << sd_err->message;
                asyncResp->res.jsonValue["error"]["message"] = sd_err->message;
            }
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_DEBUG << "SecuritySend dbus error " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        // success
        asyncResp->res.result(boost::beast::http::status::no_content);
    },
        *service, path,
        "xyz.openbmc_project.Inventory.Item.StorageControllerSecurity",
        "SecuritySend", proto, protoSpecific, data);
}

inline void securityReceiveAction(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& path, const dbus::utility::MapperServiceMap& ifaces,
    uint8_t proto, uint16_t protoSpecific, uint32_t transferLength)
{
    auto service = storage_utils::matchServiceName(
        ifaces, "xyz.openbmc_project.Inventory.Item.StorageControllerSecurity");
    if (!service)
    {
        BMCWEB_LOG_DEBUG << "No servicename";
        messages::internalError(asyncResp->res);
        return;
    }

    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp](const boost::system::error_code ec,
                    const sdbusplus::message_t& msg,
                    const std::vector<uint8_t>& data) {
        // Failure returned from NVMe
        const ::sd_bus_error* sd_err = msg.get_error();
        if (sd_err != nullptr)
        {
            messages::generalError(asyncResp->res);
            BMCWEB_LOG_DEBUG << "SecurityReceive NVMe error";
            if (sd_err->message != nullptr)
            {
                BMCWEB_LOG_DEBUG << "Error: " << sd_err->name << " message "
                                 << sd_err->message;
                asyncResp->res.jsonValue["error"]["message"] = sd_err->message;
            }
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_DEBUG << "SecurityReceive dbus error " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        // Success
        asyncResp->res.jsonValue["Data"] =
            crow::utility::base64encode(std::string_view(
                reinterpret_cast<const char*>(data.data()), data.size())); // NOLINT
    },
        *service, path,
        "xyz.openbmc_project.Inventory.Item.StorageControllerSecurity",
        "SecurityReceive", proto, protoSpecific, transferLength);
}

inline static void
    setCustomSSDOemGpio(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& path, const std::string& property,
                        bool value)
{

    std::string customSSDDbusInterface =
        "com.google.gbmc.ssd." +
        boost::algorithm::to_lower_copy(std::string(customSSD));

    managedStore::GetManagedObjectStore()->setProperty(
        "com.google.gbmc.ssd", path,
        customSSDDbusInterface, property, value,
        [asyncResp](const boost::system::error_code ec) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "setCustomSSDOemGpio D-Bus responses error: "
                             << ec;
            messages::internalError(asyncResp->res);
            return;
        }
        messages::success(asyncResp->res);
    });
}

inline static void
    setCustomSSDSpiImage(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& path, const std::string& property,
                         const std::string& value)
{
    std::string customSSDDbusInterface =
        "com.google.gbmc.ssd." +
        boost::algorithm::to_lower_copy(std::string(customSSD));

    managedStore::GetManagedObjectStore()->setProperty(
        "com.google.gbmc.ssd", path,
        customSSDDbusInterface, property, value,
        [asyncResp](const boost::system::error_code ec) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "setCustomSSDSpiImage D-Bus responses error: "
                             << ec;
            messages::internalError(asyncResp->res);
            return;
        }
        messages::success(asyncResp->res);
    });
}

inline void storagePatchCustomSSDOem(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& storageId, const std::string& controllerId,
    nlohmann::json& customSSDOem)
{
    storage_utils::findStorageAndController(
        asyncResp, storageId, controllerId,
        [asyncResp, storageId, controllerId, customSSDOem](
            const std::string& path, const dbus::utility::MapperServiceMap&) {
        if (customSSDOem.contains("MorristownOtpWriteEnable"))
        {
            setCustomSSDOemGpio(asyncResp, path, "MorristownOtpWriteEnable",
                                customSSDOem["MorristownOtpWriteEnable"]);
        }
        if (customSSDOem.contains("TriggerPowerCycle"))
        {
            setCustomSSDOemGpio(asyncResp, path, "TriggerPowerCycle",
                                customSSDOem["TriggerPowerCycle"]);
        }
        if (customSSDOem.contains("DisableWatchdog"))
        {
            setCustomSSDOemGpio(asyncResp, path, "DisableWatchdog",
                                customSSDOem["DisableWatchdog"]);
        }
        if (customSSDOem.contains("TriggerReset"))
        {
            setCustomSSDOemGpio(asyncResp, path, "TriggerReset",
                                customSSDOem["TriggerReset"]);
        }
        if (customSSDOem.contains("CpldReset"))
        {
            setCustomSSDOemGpio(asyncResp, path, "CpldReset",
                                customSSDOem["CpldReset"]);
        }
        if (customSSDOem.contains("SpiImgSelect"))
        {
            setCustomSSDSpiImage(asyncResp, path, "SpiImgSelect",
                                 customSSDOem["SpiImgSelect"]);
        }
    });
}

// Performs storage attach and detach operations.
// Will be called pseudo-recursively (asio dbus callbacks) to perform
// the operations.
inline void storageApplyAttachDetach(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& connectionName, const std::string& controllerPath,
    const std::shared_ptr<std::vector<std::string>>& attaches,
    const std::shared_ptr<std::vector<std::string>>& detaches)
{
    if (!detaches->empty())
    {
        sdbusplus::message::object_path v = detaches->back();
        detaches->pop_back();
        BMCWEB_LOG_DEBUG << "detaching " << v.str << " from " << controllerPath
                         << "\n";
        managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
            asyncResp->strand_,
            [asyncResp, connectionName, controllerPath, attaches,
             detaches](const boost::system::error_code ec,
                       const sdbusplus::message_t& msg) {
            // Failure returned from NVMe
            const ::sd_bus_error* sd_err = msg.get_error();
            if (sd_err != nullptr)
            {
                // TODO remove "" argument
                storageAddDbusError(asyncResp->res, "detach volume NVMe", "",
                                    sd_err->name, sd_err->message);
                return;
            }

            if (ec)
            {
                BMCWEB_LOG_DEBUG << "detach volume dbus error " << ec;
                messages::internalError(asyncResp->res);
                return;
            }

            // "recurse"
            storageApplyAttachDetach(asyncResp, connectionName, controllerPath,
                                     attaches, detaches);
        },
            connectionName, controllerPath,
            "xyz.openbmc_project.Inventory.Item.StorageController",
            "DetachVolume", v);
        return;
    }

    if (!attaches->empty())
    {
        sdbusplus::message::object_path v = attaches->back();
        attaches->pop_back();
        BMCWEB_LOG_DEBUG << "attaching " << v.str << " to " << controllerPath
                         << "\n";
        managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
            asyncResp->strand_,
            [asyncResp, connectionName, controllerPath, attaches,
             detaches](const boost::system::error_code ec,
                       const sdbusplus::message_t& msg) {
            // Failure returned from NVMe
            const ::sd_bus_error* sd_err = msg.get_error();
            if (sd_err != nullptr)
            {
                // TODO remove "" argument
                storageAddDbusError(asyncResp->res, "attach volume NVMe", "",
                                    sd_err->name, sd_err->message);
                return;
            }

            if (ec)
            {
                BMCWEB_LOG_DEBUG << "attach volume dbus error " << ec;
                messages::internalError(asyncResp->res);
                return;
            }

            // "recurse"
            storageApplyAttachDetach(asyncResp, connectionName, controllerPath,
                                     attaches, detaches);
        },
            connectionName, controllerPath,
            "xyz.openbmc_project.Inventory.Item.StorageController",
            "AttachVolume", v);
        return;
    }

    // both lists are complete, return success with the controller.
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.StorageController"};
    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getDbusObject(
        controllerPath, interfaces, context,
        [asyncResp, connectionName,
         controllerPath](const boost::system::error_code& ec,
                         const dbus::utility::MapperGetObject& interfaceDict) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "attach volume get controller dbus error "
                             << ec;
            messages::internalError(asyncResp->res);
            return;
        }
        if (interfaceDict.size() != 1)
        {
            BMCWEB_LOG_DEBUG << "attachdetach extra services";
            for (const auto& x : interfaceDict)
            {
                BMCWEB_LOG_DEBUG << "if " << x.first;
            }
            messages::internalError(asyncResp->res);
        }

        auto c = sdbusplus::message::object_path(controllerPath);
        auto storagePath = c.parent_path().parent_path();
        std::string storageId = storagePath.filename();
        std::string controllerId = c.filename();
        storage_utils::getSystemPathFromStorage(
            asyncResp, storagePath,
            [asyncResp, storageId, controllerId, controllerPath,
             interfaceDict](std::optional<std::string_view> systemPath) {
            std::string systemName =
                (systemPath) ? std::filesystem::path(*systemPath).filename()
                             : "system";
            populateStorageController(asyncResp, systemName, storageId,
                                      controllerId, controllerPath,
                                      interfaceDict);
        });
    });
}

inline void storagePatchAttachedVolumes(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& storageId,
    const std::string& controllerId, std::vector<std::string>& updateVolumeURIs)
{
    // vector of {parsed storageId, URI}
    std::vector<std::pair<std::string, std::string>> updateVolIDs;
    for (auto& u : updateVolumeURIs)
    {
        auto parsedUrl = boost::urls::parse_relative_ref(u);
        if (!parsedUrl)
        {
            BMCWEB_LOG_DEBUG << "bad attached volume URI " << u;
            messages::invalidURI(asyncResp->res, u);
            return;
        }
        std::string urlStorageId;
        std::string volumeId;
        if (!crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
                                            "Systems", systemName.c_str(),
                                            "Storage", std::ref(urlStorageId),
                                            "Volumes", std::ref(volumeId)))
        {
            BMCWEB_LOG_DEBUG << "bad attached volume URI " << u;
            messages::invalidURI(asyncResp->res, u);
            return;
        }

        if (urlStorageId != storageId)
        {
            BMCWEB_LOG_DEBUG << "bad attached volume URI " << u;
            messages::invalidURI(asyncResp->res, u);
            return;
        }

        updateVolIDs.emplace_back(volumeId, u);
    }

    storage_utils::findStorageAndController(
        asyncResp, storageId, controllerId,
        [asyncResp,
         updateVolIDs](const std::string& controllerPath,
                       const dbus::utility::MapperServiceMap& ifaces) {
        const auto& connectionName = ifaces.front().first;

        // Create dbus paths to update. Elements are {dbus_path, URI}
        std::vector<std::pair<std::string, std::string>> updateVolumes;
        auto storagePath = sdbusplus::message::object_path(controllerPath)
                               .parent_path()
                               .parent_path();
        updateVolumes.reserve(updateVolIDs.size());
        for (const auto& [u, uri] : updateVolIDs)
        {
            updateVolumes.emplace_back((storagePath / "volumes" / u).str, uri);
        }
        std::sort(updateVolumes.begin(), updateVolumes.end());

        // Get list of available volumes
        storageVolumes(
            asyncResp, storagePath,
            [asyncResp, updateVolumes, connectionName,
             controllerPath](const boost::system::error_code& ec,
                             const std::vector<std::string>& volPaths) {
            if (ec)
            {
                BMCWEB_LOG_DEBUG
                    << "patch attached volumes list volumes failed";
                messages::internalError(asyncResp->res);
                return;
            }

            for (const auto& a : volPaths)
            {
                BMCWEB_LOG_DEBUG << "vol is " << a;
            }

            std::vector<std::string> updatePaths;
            // Early check for bad volume paths
            for (const auto& [u, uri] : updateVolumes)
            {
                if (std::find(volPaths.begin(), volPaths.end(), u) ==
                    volPaths.end())
                {
                    BMCWEB_LOG_DEBUG << "patch volume not found " << uri;
                    messages::invalidURI(asyncResp->res, uri);
                    return;
                }
                updatePaths.emplace_back(u);
            }

            // Fetch currently attached volumes
            storageCtrlAttachedVolumes(
                asyncResp, controllerPath,
                [asyncResp, updatePaths, connectionName,
                 controllerPath](const boost::system::error_code& ec2,
                                 const std::vector<std::string>& ex) {
                if (ec2)
                {
                    BMCWEB_LOG_DEBUG
                        << "patch attached volumes list attached failed";
                    messages::internalError(asyncResp->res);
                    return;
                }

                // Find changes
                auto attaches = std::make_shared<std::vector<std::string>>();
                auto detaches = std::make_shared<std::vector<std::string>>();
                std::vector<std::string> existing(ex);
                std::sort(existing.begin(), existing.end());
                std::set_difference(updatePaths.begin(), updatePaths.end(),
                                    existing.begin(), existing.end(),
                                    std::back_inserter(*attaches));

                std::set_difference(existing.begin(), existing.end(),
                                    updatePaths.begin(), updatePaths.end(),
                                    std::back_inserter(*detaches));

                // Apply
                storageApplyAttachDetach(asyncResp, connectionName,
                                         controllerPath, attaches, detaches);
            });
        });
    });
}

inline void
    storagePatchController(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;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    if (!enableCustomSSD)
    {
        return;
    }

    std::optional<nlohmann::json> customSSDOem;
    std::optional<std::vector<std::string>> attachedVolumes;
    if (!json_util::readJsonPatch(
            req, asyncResp->res, "Links/AttachedVolumes", attachedVolumes,
            "Links/Oem/Google/" + std::string(customSSD), customSSDOem))
    {
        BMCWEB_LOG_DEBUG << "Bad controller patch input";
        return;
    }

    if (customSSDOem && attachedVolumes)
    {
        BMCWEB_LOG_DEBUG << "Multiple values to controller patch";
        messages::generalError(asyncResp->res);
        asyncResp->res.jsonValue["error"]["message"] =
            "PATCH may only alter one resource type";
        return;
    }

    if (!(customSSDOem || attachedVolumes))
    {
        BMCWEB_LOG_DEBUG << "No values to controller patch";
        messages::noOperation(asyncResp->res);
        return;
    }

    if (customSSDOem)
    {
        storagePatchCustomSSDOem(asyncResp, storageId, controllerId,
                                 *customSSDOem);
    }

    if (attachedVolumes)
    {
        storagePatchAttachedVolumes(asyncResp, systemName, storageId,
                                    controllerId, *attachedVolumes);
    }

    // TODO: we should setCompleteRequestHandler to return the modified
    // StorageController on completion, rather than handling in attachedVolumes.
}

inline void handlePostStorageControllerSecuritySend(
    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;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    uint8_t proto = 0;
    uint16_t protoSpecific = 0;
    std::string dataBase64;

    if (!json_util::readJsonAction(req, asyncResp->res, "SecurityProtocol",
                                   proto, "SecurityProtocolSpecific",
                                   protoSpecific, "Data", dataBase64))
    {
        BMCWEB_LOG_DEBUG << "Missing request json parameters";
        return;
    }

    storage_utils::findStorageAndController(
        asyncResp, storageId, controllerId,
        [asyncResp, proto, protoSpecific,
         dataBase64](const sdbusplus::message::object_path& path,
                     const dbus::utility::MapperServiceMap& ifaces) {
        securitySendAction(asyncResp, path, ifaces, proto, protoSpecific,
                           dataBase64);
    });
}

inline void handlePostStorageControllerSecurityReceive(
    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;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    uint8_t proto = 0;
    uint16_t protoSpecific = 0;
    uint32_t transferLength = 0;

    if (!json_util::readJsonAction(req, asyncResp->res, "SecurityProtocol",
                                   proto, "SecurityProtocolSpecific",
                                   protoSpecific, "AllocationLength",
                                   transferLength))
    {
        BMCWEB_LOG_DEBUG << "Missing request json parameters";
        return;
    }

    storage_utils::findStorageAndController(
        asyncResp, storageId, controllerId,
        [asyncResp, proto, protoSpecific,
         transferLength](const sdbusplus::message::object_path& path,
                         const dbus::utility::MapperServiceMap& ifaces) {
        securityReceiveAction(asyncResp, path, ifaces, proto, protoSpecific,
                              transferLength);
    });
}

inline void requestRoutesStorageControllerActions(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>/Actions/StorageController.SecuritySend")
        .privileges(redfish::privileges::postStorageController)
        .methods(boost::beast::http::verb::post)(std::bind_front(
            handlePostStorageControllerSecuritySend, std::ref(app)));

    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>/Actions/StorageController.SecurityReceive")
        .privileges(redfish::privileges::postStorageController)
        .methods(boost::beast::http::verb::post)(std::bind_front(
            handlePostStorageControllerSecurityReceive, std::ref(app)));

    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>")
        .privileges(redfish::privileges::patchStorageController)
        .methods(boost::beast::http::verb::patch)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& systemName, const std::string& storageId,
                   const std::string& controllerId) {
        storagePatchController(app, req, asyncResp, systemName, storageId,
                               controllerId);
    });
}

inline void populateStorageControllerCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& storageId,
    const dbus::utility::MapperGetSubTreeResponse& controllerList)
{
    if (!asyncResp->res.jsonValue["Members"].is_array())
    {
        asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
    }
    asyncResp->res.jsonValue["Members@odata.count"] =
        asyncResp->res.jsonValue["Members"].size();

    for (const auto& controller : controllerList)
    {
        const sdbusplus::message::object_path controllerPath = controller.first;
        storage_utils::findStorageForController(
            asyncResp, storageId, controllerPath,
            [asyncResp, systemName, controllerPath](
                const std::optional<sdbusplus::message::object_path>&
                    canonStoragePath) {
            if (!canonStoragePath)
            {
                BMCWEB_LOG_DEBUG << "No storage associated with controller "
                                 << std::string(controllerPath);
                return;
            }
            nlohmann::json::object_t member;
            std::string canonStorageId = (*canonStoragePath).filename();
            std::string controllerId = controllerPath.filename();
            member["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", systemName, "Storage",
                canonStorageId, "Controllers", controllerId);
            asyncResp->res.jsonValue["Members"].emplace_back(member);
            asyncResp->res.jsonValue["Members@odata.count"] =
                asyncResp->res.jsonValue["Members"].size();
        });
    }
}

inline void storageControllerCollectionHandler(
    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))
    {
        BMCWEB_LOG_DEBUG
            << "Failed to setup Redfish Route for StorageController Collection";
        return;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    storage_utils::findStorage(
        asyncResp, storageId,
        [asyncResp, systemName,
         storageId](const sdbusplus::message::object_path& storagePath) {
        asyncResp->res.jsonValue["@odata.type"] =
            "#StorageControllerCollection.StorageControllerCollection";
        asyncResp->res.jsonValue["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                         "Storage", storageId, "Controllers");
        asyncResp->res.jsonValue["Name"] = "Storage Controller Collection";

        auto& cap = asyncResp->res.jsonValue["@Redfish.CollectionCapabilities"];
        cap["@odata.type"] =
            "#CollectionCapabilities.v1_3_0.CollectionCapabilities";
        auto& cs = cap["Capabilities"];
        if (!cs.is_array())
        {
            cs = nlohmann::json::array_t();
        }
        auto& c = cs.emplace_back(nlohmann::json::object_t());
        c["CapabilitiesObject"]["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", systemName, "Storage", storageId,
            "Volumes", "Capabilities");
        c["Links"]["TargetCollection"]["@odata.id"] =
            asyncResp->res.jsonValue["@odata.id"];

        storage_utils::findControllersForStorage(
            asyncResp, storagePath,
            std::bind_front(populateStorageControllerCollection, asyncResp,
                            systemName, storageId));
    });
}

inline void
    tryPopulateVolumeNvme(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& connectionName,
                          const std::string& path,
                          const dbus::utility::MapperServiceMap& ifaces,
                          const std::string& volumeId, size_t blockSize)
{
    if (!storage_utils::matchServiceName(ifaces,
                                         "xyz.openbmc_project.Nvme.Volume"))
    {
        return;
    }

    asyncResp->res.jsonValue["Name"] = std::string("Namespace ") + volumeId;

    managedStore::ManagedObjectStoreContext context(asyncResp);
    redfish::storage_utils::getAllProperties(
        connectionName, path, "xyz.openbmc_project.Nvme.Volume", context,
        [asyncResp, blockSize](
            const boost::system::error_code& ec,
            const std::vector<std::pair<
                std::string, dbus::utility::DbusVariantType>>& propertiesList) {
        if (ec)
        {
            std::cerr << "error fetching nvme volume " << ec << '\n';
            // this interface isn't necessary
            return;
        }

        const uint32_t* namespaceId = nullptr;
        const size_t* lbaFormat = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), propertiesList, "NamespaceId",
            namespaceId, "LBAFormat", lbaFormat);

        if (!success)
        {
            messages::internalError(asyncResp->res);
            return;
        }

        auto& nvprop = asyncResp->res.jsonValue["NVMeNamespaceProperties"];
        if (namespaceId != nullptr)
        {
            nvprop["NamespaceId"] =
                std::string("0x") + intToHexString(*namespaceId, 8);
        }
        if (lbaFormat != nullptr)
        {
            auto& lbafprop = nvprop["LBAFormat"];
            lbafprop["LBAFormatType"] =
                std::string("LBAFormat") + std::to_string(*lbaFormat);
            lbafprop["LBADataSizeBytes"] = blockSize;
            // TODO: populate other lbaformat attributes, and metadata_at_end
        }
    });
}

inline void populateStorageVolume(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& storageId,
    const std::string& volumeId, const std::string& connectionName,
    const std::string& path, const dbus::utility::MapperServiceMap& ifaces)
{
    asyncResp->res.jsonValue["@odata.type"] = "#Volume.v1_9_0.Volume";
    auto url =
        crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                     "Storage", storageId, "Volumes", volumeId);
    asyncResp->res.jsonValue["@odata.id"] = url;
    // May be overridden by nvme
    asyncResp->res.jsonValue["Name"] = std::string("Volume ") + volumeId;
    asyncResp->res.jsonValue["Id"] = volumeId;

    managedStore::ManagedObjectStoreContext context(asyncResp);
    redfish::storage_utils::getAllProperties(
        connectionName, path, "xyz.openbmc_project.Inventory.Item.Volume",
        context,
        [asyncResp, connectionName, path, ifaces, volumeId](
            const boost::system::error_code& ec,
            const std::vector<std::pair<
                std::string, dbus::utility::DbusVariantType>>& propertiesList) {
        size_t volBlockSize = 0;
        // this interface isn't necessary
        if (!ec)
        {
            const uint64_t* size = nullptr;
            const size_t* blockSize = nullptr;

            const bool success = sdbusplus::unpackPropertiesNoThrow(
                dbus_utils::UnpackErrorPrinter(), propertiesList, "Size", size,
                "BlockSize", blockSize);

            if (!success)
            {
                messages::internalError(asyncResp->res);
                return;
            }

            auto& cap = asyncResp->res.jsonValue["Capacity"];
            auto& capdata = cap["Data"];
            if (size != nullptr)
            {
                capdata["ProvisionedBytes"] = *size;
            }
            // Capacity.Metadata or provisioned/allocated is not currently
            // handled by OpenBMC
            if (blockSize != nullptr)
            {
                asyncResp->res.jsonValue["BlockSizeBytes"] = *blockSize;
                volBlockSize = *blockSize;
            }
            tryPopulateVolumeNvme(asyncResp, connectionName, path, ifaces,
                                  volumeId, volBlockSize);
        }
    });

    auto findIfaces = std::find_if(
        ifaces.begin(), ifaces.end(),
        [connectionName](
            const std::pair<std::string, std::vector<std::string>>& pair) {
        return pair.first == connectionName;
    });
    if (findIfaces != ifaces.end())
    {
        storage_utils::tryGetLocation(asyncResp, connectionName, path,
                                      storage_utils::volumeInterface,
                                      findIfaces->second);
    }
}

inline void
    deleteStorageVolume(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& storageId,
                        const std::string& connectionName,
                        const std::string& path)
{
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp, storageId](const boost::system::error_code ec,
                               const sdbusplus::message_t& msg) {
        // Failure returned from NVMe
        const ::sd_bus_error* sd_err = msg.get_error();
        if (sd_err != nullptr)
        {
            storageAddDbusError(asyncResp->res, "delete Volume NVMe", storageId,
                                sd_err->name, sd_err->message);
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_DEBUG << "delete Volume dbus error " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        // success
        asyncResp->res.result(boost::beast::http::status::no_content);
    },
        connectionName, path, "xyz.openbmc_project.Object.Delete", "Delete");
}

inline void findStorageVolume(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& storageId, const std::string& volumeId,
    const std::function<
        void(const std::string& storagePath, const std::string& volumePath,
             const std::string& connectionName,
             const dbus::utility::MapperServiceMap& ifaces)>& cb)
{
    storage_utils::findStorage(
        asyncResp, storageId,
        [asyncResp, storageId, volumeId,
         cb](const sdbusplus::message::object_path& storagePath) {
        constexpr std::array<std::string_view, 1> interfaces = {
            "xyz.openbmc_project.Inventory.Item.Volume"};
        managedStore::ManagedObjectStoreContext context(asyncResp);
        redfish::storage_utils::getAssociatedSubTree(
            storagePath / "containing",
            sdbusplus::message::object_path("/xyz/openbmc_project/inventory"),
            0, interfaces, context,
            [asyncResp, storageId, volumeId, storagePath,
             cb](const boost::system::error_code& ec,
                 const dbus::utility::MapperGetSubTreeResponse& subtree) {
            if (ec || subtree.empty())
            {
                BMCWEB_LOG_DEBUG << "findStorageVolume error" << ec;
                messages::resourceNotFound(asyncResp->res,
                                           "#Volume.v1_9_0.Volume", volumeId);
                return;
            }

            for (const auto& [path, interfaceDict] : subtree)
            {
                sdbusplus::message::object_path object(path);
                std::string id = object.filename();
                if (id.empty())
                {
                    BMCWEB_LOG_ERROR << "Failed to find filename in " << path;
                    messages::resourceNotFound(
                        asyncResp->res, "#Volume.v1_9_0.Volume", volumeId);
                    return;
                }
                if (id != volumeId)
                {
                    continue;
                }

                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;
                cb(storagePath, path, connectionName, interfaceDict);
                return;
            }
            BMCWEB_LOG_DEBUG << "findStorageVolume not found";
            messages::resourceNotFound(asyncResp->res, "#Volume.v1_9_0.Volume",
                                       volumeId);
        });
    });
}

inline void createVolumeSuccess(const std::shared_ptr<task::TaskData>& taskData,
                                const std::string& service,
                                const std::string& storageId,
                                const std::string& progressPath)
{
    taskData->stopMonitor();

    // Have to create a new Resp here as we cannot use the original resp or it never goes out of scope
    // This resp will not have a strand associated with it which is okay because this will never be
    // multithreaded
    auto resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
    managedStore::ManagedObjectStoreContext context(resp);
    redfish::storage_utils::getProperty<sdbusplus::message::object_path>(
        service, progressPath,
        "xyz.openbmc_project.Nvme.CreateVolumeProgressSuccess", "VolumePath", context,
        [taskData, storageId,
         progressPath](const boost::system::error_code& ec,
                       const sdbusplus::message::object_path& volumePath) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "createVolumeSuccess volumepath error " << ec;
            taskData->messages.emplace_back(messages::internalError());
            taskData->state = "Exception";
            taskData->complete(
                nlohmann::json(),
                boost::beast::http::status::internal_server_error);
            return;
        }

        auto resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
        resp->res.setCompleteRequestHandler([taskData](crow::Response& res) {
            if (res.result() == boost::beast::http::status::ok)
            {
                taskData->messages.emplace_back(messages::created());
                taskData->state = "Completed";
                taskData->complete(std::move(res.jsonValue),
                                   boost::beast::http::status::created);
            }
            else
            {
                BMCWEB_LOG_DEBUG << "createVolumeSuccess error populating: "
                                 << res.result();
                BMCWEB_LOG_DEBUG << res.jsonValue;
                taskData->messages.emplace_back(messages::internalError());
                taskData->state = "Exception";
                taskData->complete(
                    nlohmann::json(),
                    boost::beast::http::status::internal_server_error);
            }
        });

        auto volumeId = volumePath.filename();

        findStorageVolume(
            resp, storageId, volumeId,
            [resp, storageId,
             volumeId](const std::string& sPath, const std::string& vPath,
                       const std::string& connectionName,
                       const dbus::utility::MapperServiceMap& ifaces) {
            BMCWEB_LOG_DEBUG << "createVolumeSuccess connectionName is "
                             << connectionName;
            storage_utils::getSystemPathFromStorage(
                resp, sPath,
                [resp, storageId, volumeId, connectionName, vPath,
                 ifaces](std::optional<std::string_view> systemPath) {
                std::string systemName =
                    systemPath ? std::filesystem::path(*systemPath).filename()
                               : "system";
                populateStorageVolume(resp, systemName, storageId, volumeId,
                                      connectionName, vPath, ifaces);
            });
            // on completion completeRequestHandler above will copy the response
            // to taskData
        });
    });
}

inline void createVolumeFailure(const std::shared_ptr<task::TaskData>& taskData,
                                const std::string& service,
                                const std::string& storageId,
                                const std::string& progressPath)
{
    taskData->stopMonitor();

    // Have to create a new Resp here as we cannot use the original resp or it never goes out of scope
    // This resp will not have a strand associated with it which is okay because this will never be
    // multithreaded
    auto resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
    managedStore::ManagedObjectStoreContext context(resp);
    redfish::storage_utils::getAllProperties(
        service, progressPath,
        "xyz.openbmc_project.Nvme.CreateVolumeProgressFailure", context,
        [taskData,
         storageId](const boost::system::error_code& ec,
                    const std::vector<std::pair<
                        std::string, dbus::utility::DbusVariantType>>& props) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "createVolumeSuccess volumepath error " << ec;
            taskData->messages.emplace_back(messages::internalError());
            taskData->state = "Exception";
            taskData->complete(
                nlohmann::json(),
                boost::beast::http::status::internal_server_error);
            return;
        }

        std::string errorName;
        std::string errorDesc;
        sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(),
                                           props, "ErrorName", errorName,
                                           "ErrorDescription", errorDesc);
        bmcweb::AsyncResp resp(nullptr);
        storageAddDbusError(resp.res, "createVolumeFailure", storageId,
                            errorName, errorDesc);
        for (auto& m : resp.res.jsonValue["error"][messages::messageAnnotation])
        {
            taskData->messages.emplace_back(m);
        }

        taskData->state = "Exception";
        taskData->complete(std::move(resp.res.jsonValue), resp.res.result());
    });
}

// Handles the Status property of Common.Progress interface
inline void createVolumeTaskUpdate(const std::string& status,
                                   const std::shared_ptr<task::TaskData>& taskData,
                                   const std::string& service,
                                   const std::string& storageId,
                                   const std::string& progressPath)
{
    if (status ==
        "xyz.openbmc_project.Common.Progress.OperationStatus.InProgress")
    {
        // nothing to do
    }
    else if (status ==
             "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
    {
        createVolumeSuccess(taskData, service, storageId, progressPath);
    }
    else if (status ==
                 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
             status ==
                 "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
    {
        createVolumeFailure(taskData, service, storageId, progressPath);
    }
    else
    {
        BMCWEB_LOG_DEBUG << "updateCreateVolumeTask unexpected state "
                         << status;
    }
}

// Handler called by TaskData on Commmon.Progress property change
inline bool createVolumeTaskHandler(sdbusplus::message_t& msg,
                                    const std::shared_ptr<task::TaskData>& taskData,
                                    const std::string& service,
                                    const std::string& storageId,
                                    const std::string& progressPath)
{
    dbus::utility::DBusPropertiesMap props;
    std::string iface;
    msg.read(iface, props);

    if (iface != "xyz.openbmc_project.Common.Progress")
    {
        BMCWEB_LOG_DEBUG << "updateCreateVolumeTask wrong interface";
        return !task::completed;
    }

    std::optional<std::string> status;
    sdbusplus::unpackPropertiesNoThrow(dbus_utils::UnpackErrorPrinter(), props,
                                       "Status", status);
    if (!status)
    {
        BMCWEB_LOG_DEBUG << "updateCreateVolumeTask not status update";
        return !task::completed;
    }

    createVolumeTaskUpdate(*status, taskData, service, storageId, progressPath);
    // completion is handled asynchronously so always return !completed
    return !task::completed;
}

inline void
    createStorageVolume(const crow::Request& req,
                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& storagePath,
                        const std::string& storageService, uint64_t size,
                        size_t lbaIndex, bool metadataAtEnd)
{
    auto storageId = sdbusplus::message::object_path(storagePath).filename();
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [req, asyncResp, storageId, storageService](
            const boost::system::error_code ec, const sdbusplus::message_t& msg,
            const sdbusplus::message::object_path& progressPath) {
        const ::sd_bus_error* sd_err = msg.get_error();
        if (sd_err != nullptr)
        {
            storageAddDbusError(asyncResp->res, "create Volume NVMe", storageId,
                                sd_err->name, sd_err->message);
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_DEBUG << "create Volume dbus error " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        // success
        BMCWEB_LOG_DEBUG << "create volume success, progress path "
                         << progressPath.str;
        std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
            [storageService, storageId,
             progressPath](const boost::system::error_code& err,
                           sdbusplus::message_t& taskMsg,
                           const std::shared_ptr<task::TaskData>& taskData) {
            if (err)
            {
                // Internal error in property signal callback?
                BMCWEB_LOG_ERROR << progressPath.str << ": Error in task";
                taskData->messages.emplace_back(messages::internalError());
                taskData->state = "Cancelled";
                return task::completed;
            }

            return createVolumeTaskHandler(taskMsg, taskData, storageService,
                                           storageId, progressPath);
        },
            "type='signal',interface='org.freedesktop.DBus.Properties',"
            "member='PropertiesChanged',arg0='xyz.openbmc_project.Common.Progress',"
            "path='" +
                progressPath.str + "'");

        task->startTimer(std::chrono::minutes(60));
        task->populateResp(asyncResp->res);
        task->payload.emplace(req);

        // Progress may have completed prior to Task watching for signals, so
        // poll Status once.
        managedStore::ManagedObjectStoreContext context(asyncResp);
        redfish::storage_utils::getProperty<std::string>(
            storageService, progressPath, "xyz.openbmc_project.Common.Progress",
            "Status", context,
            [task, storageService, storageId,
             progressPath](const boost::system::error_code& ec2,
                           const std::string& status) {
            if (ec2)
            {
                BMCWEB_LOG_ERROR << "createVolume poll error: "
                                 << ec2.message();
                return;
            }

            createVolumeTaskUpdate(status, task, storageService, storageId,
                                   progressPath);
        });
    },
        storageService, storagePath, "xyz.openbmc_project.Nvme.Storage",
        "CreateVolume", size, lbaIndex, metadataAtEnd);
}

inline void populateStorageVolumeCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::system::error_code& ec, const std::string& systemName,
    const std::string& storageId,
    const dbus::utility::MapperGetSubTreePathsResponse& volumeList)
{
    nlohmann::json::array_t members;
    if (ec || volumeList.empty())
    {
        asyncResp->res.jsonValue["Members"] = std::move(members);
        asyncResp->res.jsonValue["Members@odata.count"] = 0;
        BMCWEB_LOG_DEBUG << "Failed to find any storage Volumes";
        return;
    }

    for (const std::string& path : volumeList)
    {
        std::string id = sdbusplus::message::object_path(path).filename();
        if (id.empty())
        {
            BMCWEB_LOG_ERROR << "Failed to find filename in " << path;
            return;
        }
        nlohmann::json::object_t member;
        member["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                         "Storage", storageId, "Volumes", id);
        members.emplace_back(member);
    }
    asyncResp->res.jsonValue["Members@odata.count"] = members.size();
    asyncResp->res.jsonValue["Members"] = std::move(members);
}

inline void
    storageVolumeHandler(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))
    {
        BMCWEB_LOG_DEBUG << "Failed to setup Redfish Route for StorageVolume";
        return;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    findStorageVolume(
        asyncResp, storageId, volumeId,
        [asyncResp, systemName, storageId,
         volumeId](const std::string& /* sPath */, const std::string& vPath,
                   const std::string& connectionName,
                   const dbus::utility::MapperServiceMap& ifaces) {
        populateStorageVolume(asyncResp, systemName, storageId, volumeId,
                              connectionName, vPath, ifaces);
    });
}

inline std::optional<size_t> parseLbaFormatType(std::string_view ty)
{
    // expects LBAFormat0, LBAFormat1 etc
    if (!ty.starts_with("LBAFormat"))
    {
        BMCWEB_LOG_DEBUG << "wrong start";
        return std::nullopt;
    }

    ty.remove_prefix(std::min(ty.size(), strlen("LBAFormat")));

    size_t v = 0;
    auto e = std::from_chars(ty.data(), ty.data() + ty.size(), v);
    if (e.ptr != ty.data() + ty.size() || e.ec != std::errc())
    {
        return std::nullopt;
    }
    return v;
}

inline void storageVolumeCreateHandler(
    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))
    {
        BMCWEB_LOG_DEBUG << "Failed to setup Redfish Route for StorageVolume";
        return;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    uint64_t size = 0;
    std::string lbaFormat;
    // allow to default, non-metadata formats ignore the parameter
    std::optional<bool> metadataAtEnd = false;
    std::optional<std::string> name;

    if (!json_util::readJsonAction(
            req, asyncResp->res, "Name", name, "Capacity/Data/ProvisionedBytes",
            size, "NVMeNamespaceProperties/LBAFormat/LBAFormatType", lbaFormat,
            "NVMeNamespaceProperties/LBAFormat/MetadataTransferredAtEndOfDataLBA",
            metadataAtEnd))
    {
        BMCWEB_LOG_DEBUG << "create volume json input failed";
        return;
    }

    std::optional<size_t> lbaIndex = parseLbaFormatType(lbaFormat);
    if (!lbaIndex)
    {
        BMCWEB_LOG_DEBUG << "Bad parsing lbaFormatType";
        messages::propertyValueNotInList(
            asyncResp->res, lbaFormat,
            "NVMeNamespaceProperties.LBAFormat.LBAFormatType");
        return;
    }

    storage_utils::findStorageCallbackWithService(
        asyncResp, storageId,
        [req, asyncResp, size, lbaIndex,
         metadataAtEnd](const sdbusplus::message::object_path& storagePath,
                        const std::string& storageService) {
        createStorageVolume(req, asyncResp, storagePath, storageService, size,
                            *lbaIndex, *metadataAtEnd);
    });
}

inline void storageVolumeDeleteHandler(
    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)
{
    BMCWEB_LOG_DEBUG << "delete handler vol " << volumeId;
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        BMCWEB_LOG_DEBUG << "Failed to setup Redfish Route for StorageVolume";
        return;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    findStorageVolume(
        asyncResp, storageId, volumeId,
        [asyncResp, storageId,
         volumeId](const std::string& /* sPath */, const std::string& vPath,
                   const std::string& connectionName,
                   const dbus::utility::MapperServiceMap& ifaces) {
        (void)ifaces;
        deleteStorageVolume(asyncResp, storageId, connectionName, vPath);
    });
}

inline void storageVolumeCollectionHandler(
    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))
    {
        BMCWEB_LOG_DEBUG
            << "Failed to setup Redfish Route for StorageVolume Collection";
        return;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    storage_utils::findStorage(
        asyncResp, storageId,
        [asyncResp, systemName,
         storageId](const sdbusplus::message::object_path& storagePath) {
        asyncResp->res.jsonValue["@odata.type"] =
            "#VolumeCollection.VolumeCollection";
        asyncResp->res.jsonValue["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                         "Storage", storageId, "Volumes");
        asyncResp->res.jsonValue["Name"] = "Storage Volume Collection";

        storageVolumes(asyncResp, storagePath,
                       [asyncResp, systemName, storageId](
                           const boost::system::error_code& ec,
                           const dbus::utility::MapperGetSubTreePathsResponse&
                               volumeList) {
            populateStorageVolumeCollection(asyncResp, ec, systemName,
                                            storageId, volumeList);
        });
    });
}

inline std::string lookupRelativePerformance(const std::string& rp)
{
    if (rp == "xyz.openbmc_project.Nvme.Storage.RelativePerformance.Best")
    {
        return "Best";
    }
    if (rp ==
             "xyz.openbmc_project.Nvme.Storage.RelativePerformance.Better")
    {
        return "Better";
    }
    if (rp == "xyz.openbmc_project.Nvme.Storage.RelativePerformance.Good")
    {
        return "Good";
    }
    return "Degraded";
}

inline void storageVolumeCapabilitiesHandler(
    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))
    {
        BMCWEB_LOG_DEBUG
            << "Failed to setup Redfish Route for StorageVolume Capabilities";
        return;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    storage_utils::findStorageCallbackWithService(
        asyncResp, storageId,
        [asyncResp, systemName,
         storageId](const sdbusplus::message::object_path& storagePath,
                    const std::string& service) {
        managedStore::ManagedObjectStoreContext context(asyncResp);
        redfish::storage_utils::getProperty<
            std::vector<std::tuple<size_t, size_t, size_t, std::string>>>(
            service, storagePath, "xyz.openbmc_project.Nvme.Storage",
            "SupportedFormats", context,
            [asyncResp, systemName, storageId](
                const boost::system::error_code& ec,
                const std::vector<
                    std::tuple<size_t, size_t, size_t, std::string>>& formats) {
            asyncResp->res.jsonValue["@odata.type"] = "#Volume.v1_9_0.Volume";
            auto url = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", systemName, "Storage", storageId,
                "Volumes", "Capabilities");
            asyncResp->res.jsonValue["@odata.id"] = url;
            asyncResp->res.jsonValue["Id"] = "Capabilities";
            asyncResp->res.jsonValue["Name"] = "Capabilities for Volumes";
            auto& nv = asyncResp->res.jsonValue["NVMeNamespaceProperties"];
            auto& allowable =
                nv["LBAFormatsSupported@Redfish.AllowableValues"] =
                    nlohmann::json::array_t();
            auto& formatDesc = nv["LBAFormats"] = nlohmann::json::array_t();

            if (ec)
            {
                BMCWEB_LOG_WARNING
                    << "Failed to get SupportedFormats property for "
                    << storageId << " : " << ec.message();
                return;
            }

            for (const auto& [index, blockSize, metadataSize, relPerf] : formats)
            {
                auto name = std::string("LBAFormat") + std::to_string(index);
                allowable.emplace_back(name);
                auto& f = formatDesc.emplace_back(nlohmann::json::object_t());
                auto rp = lookupRelativePerformance(relPerf);
                f["LBAFormatType"] = name;
                f["RelativePerformance"] = rp;
                f["LBADataSizeBytes"] = blockSize;
                f["LBAMetadataSizeBytes"] = metadataSize;
            }
        });
    });
}
inline void storageControllerHandler(
    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))
    {
        BMCWEB_LOG_DEBUG
            << "Failed to setup Redfish Route for StorageController";
        return;
    }

    checkSystemAndStorage(asyncResp, systemName, storageId);

    storage_utils::findStorageAndController(
        asyncResp, storageId, controllerId,
        [asyncResp, storageId, systemName,
         controllerId](const sdbusplus::message::object_path& path,
                       const dbus::utility::MapperServiceMap& ifaces) {
        populateStorageController(asyncResp, systemName, storageId,
                                  controllerId, path, ifaces);
    });
}

inline void requestRoutesStorageControllerCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/")
        .privileges(redfish::privileges::getStorageControllerCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(storageControllerCollectionHandler, std::ref(app)));
}

inline void requestRoutesStorageController(App& app)
{
    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>")
        .privileges(redfish::privileges::getStorageController)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(storageControllerHandler, std::ref(app)));
}

inline void requestRoutesStorageVolumeCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/")
        .privileges(redfish::privileges::getVolumeCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(storageVolumeCollectionHandler, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/")
        .privileges(redfish::privileges::postVolumeCollection)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(storageVolumeCreateHandler, std::ref(app)));

    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/Capabilities")
        .privileges(redfish::privileges::getVolumeCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(storageVolumeCapabilitiesHandler, std::ref(app)));
}

inline void requestRoutesStorageVolume(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/<str>")
        .privileges(redfish::privileges::getVolume)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(storageVolumeHandler, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/<str>/Volumes/<str>")
        .privileges(redfish::privileges::deleteVolume)
        .methods(boost::beast::http::verb::delete_)(
            std::bind_front(storageVolumeDeleteHandler, std::ref(app)));
}

inline void requestRoutesStorageControllerMetric(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/<str>/Storage/<str>/Controllers/<str>/Oem/Google/Metrics/<str>")
        .privileges(redfish::privileges::privilegeSetLogin)
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& system, const std::string& storage,
                   const std::string& cntrl, const std::string& metric) {
        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
        {
            return;
        }
        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", system, "Storage", storage,
            "Controllers", cntrl, "Oem", "Google", "Metrics", metric);

        asyncResp->res.jsonValue["Name"] = metric;

        // TODO: verify system and storage relation

        nvmeMetricFetcher(asyncResp, storage, cntrl, metric);
    });
}

} // namespace redfish
