diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 47d4848..e4d732c 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -21,6 +21,7 @@
 #include "../lib/chassis.hpp"
 #include "../lib/ethernet.hpp"
 #include "../lib/event_service.hpp"
+#include "../lib/hypervisor_system.hpp"
 #include "../lib/log_services.hpp"
 #include "../lib/managers.hpp"
 #include "../lib/memory.hpp"
@@ -41,10 +42,7 @@
 #include "../lib/telemetry_service.hpp"
 #include "../lib/thermal.hpp"
 #include "../lib/update_service.hpp"
-#ifdef BMCWEB_ENABLE_VM_NBDPROXY
 #include "../lib/virtual_media.hpp"
-#endif // BMCWEB_ENABLE_VM_NBDPROXY
-#include "../lib/hypervisor_system.hpp"
 
 namespace redfish
 {
@@ -148,13 +146,11 @@
         requestRoutesSystemResetActionInfo(app);
         requestRoutesBiosService(app);
         requestRoutesBiosReset(app);
+
 #ifdef BMCWEB_ENABLE_VM_NBDPROXY
-        nodes.emplace_back(std::make_unique<VirtualMedia>(app));
-        nodes.emplace_back(std::make_unique<VirtualMediaCollection>(app));
-        nodes.emplace_back(
-            std::make_unique<VirtualMediaActionInsertMedia>(app));
-        nodes.emplace_back(std::make_unique<VirtualMediaActionEjectMedia>(app));
+        requestNBDVirtualMediaRoutes(app);
 #endif // BMCWEB_ENABLE_VM_NBDPROXY
+
 #ifdef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
         requestRoutesDBusLogServiceActionsClear(app);
         requestRoutesDBusEventLogEntryCollection(app);
diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
index cdb6a51..e0b6726 100644
--- a/redfish-core/lib/virtual_media.hpp
+++ b/redfish-core/lib/virtual_media.hpp
@@ -25,12 +25,11 @@
 #include <boost/url/url_view.hpp>
 
 namespace redfish
-
 {
 /**
  * @brief Function extracts transfer protocol name from URI.
  */
-static std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
+inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
 {
     try
     {
@@ -39,7 +38,7 @@
         {
             return "CIFS";
         }
-        else if (scheme == "https")
+        if (scheme == "https")
         {
             return "HTTPS";
         }
@@ -54,7 +53,7 @@
 /**
  * @brief Read all known properties from VM object interfaces
  */
-static void
+inline void
     vmParseInterfaceObject(const DbusInterfaceType& interface,
                            const std::shared_ptr<bmcweb::AsyncResp>& aResp)
 {
@@ -164,12 +163,17 @@
 /**
  * @brief Fill template for Virtual Media Item.
  */
-static nlohmann::json vmItemTemplate(const std::string& name,
+inline nlohmann::json vmItemTemplate(const std::string& name,
                                      const std::string& resName)
 {
     nlohmann::json item;
-    item["@odata.id"] =
-        "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName;
+
+    std::string id = "/redfish/v1/Managers/";
+    id += name;
+    id += "/VirtualMedia/";
+    id += resName;
+    item["@odata.id"] = std::move(id);
+
     item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
     item["Name"] = "Virtual Removable Media";
     item["Id"] = resName;
@@ -185,7 +189,7 @@
 /**
  *  @brief Fills collection data
  */
-static void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
+inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
                               const std::string& service,
                               const std::string& name)
 {
@@ -210,9 +214,12 @@
                     continue;
                 }
 
-                item["@odata.id"] =
-                    "/redfish/v1/Managers/" + name + "/VirtualMedia/" + path;
+                std::string id = "/redfish/v1/Managers/";
+                id += name;
+                id += "/VirtualMedia/";
+                id += path;
 
+                item["@odata.id"] = std::move(id);
                 members.emplace_back(std::move(item));
             }
             aResp->res.jsonValue["Members@odata.count"] = members.size();
@@ -224,7 +231,7 @@
 /**
  *  @brief Fills data for specific resource
  */
-static void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& service, const std::string& name,
                       const std::string& resName)
 {
@@ -268,22 +275,25 @@
                 }
 
                 aResp->res.jsonValue = vmItemTemplate(name, resName);
+                std::string actionsId = "/redfish/v1/Managers/";
+                actionsId += name;
+                actionsId += "/VirtualMedia/";
+                actionsId += resName;
+                actionsId += "/Actions";
 
                 // Check if dbus path is Legacy type
                 if (mode.filename() == "Legacy")
                 {
                     aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
                                         ["target"] =
-                        "/redfish/v1/Managers/" + name + "/VirtualMedia/" +
-                        resName + "/Actions/VirtualMedia.InsertMedia";
+                        actionsId + "/VirtualMedia.InsertMedia";
                 }
 
                 vmParseInterfaceObject(item.second, aResp);
 
                 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
                                     ["target"] =
-                    "/redfish/v1/Managers/" + name + "/VirtualMedia/" +
-                    resName + "/Actions/VirtualMedia.EjectMedia";
+                    actionsId + "/VirtualMedia.EjectMedia";
 
                 return;
             }
@@ -296,899 +306,791 @@
 }
 
 /**
-   @brief InsertMedia action class
+ * @brief Transfer protocols supported for InsertMedia action.
+ *
  */
-class VirtualMediaActionInsertMedia : public Node
+enum class TransferProtocol
 {
-  public:
-    VirtualMediaActionInsertMedia(App& app) :
-        Node(app,
-             "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
-             "VirtualMedia.InsertMedia",
-             std::string(), std::string())
+    https,
+    smb,
+    invalid
+};
+
+/**
+ * @brief Function extracts transfer protocol type from URI.
+ *
+ */
+inline std::optional<TransferProtocol>
+    getTransferProtocolFromUri(const std::string& imageUri)
+{
+    try
     {
-        entityPrivileges = {
-            {boost::beast::http::verb::get, {{"Login"}}},
-            {boost::beast::http::verb::head, {{"Login"}}},
-            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
-    }
-
-  private:
-    /**
-     * @brief Transfer protocols supported for InsertMedia action.
-     *
-     */
-    enum class TransferProtocol
-    {
-        https,
-        smb,
-        invalid
-    };
-
-    /**
-     * @brief Function extracts transfer protocol type from URI.
-     *
-     */
-    std::optional<TransferProtocol>
-        getTransferProtocolFromUri(const std::string& imageUri)
-    {
-        try
-        {
-            std::string_view scheme = boost::urls::url_view(imageUri).scheme();
-            if (scheme == "smb")
-            {
-                return TransferProtocol::smb;
-            }
-            if (scheme == "https")
-            {
-                return TransferProtocol::https;
-            }
-            else if (!scheme.empty())
-            {
-                return TransferProtocol::invalid;
-            }
-        }
-        catch (std::exception& p)
-        {
-            BMCWEB_LOG_ERROR << p.what();
-        }
-
-        return {};
-    }
-
-    /**
-     * @brief Function convert transfer protocol from string param.
-     *
-     */
-    std::optional<TransferProtocol> getTransferProtocolFromParam(
-        const std::optional<std::string>& transferProtocolType)
-    {
-        if (transferProtocolType == std::nullopt)
-        {
-            return {};
-        }
-
-        if (*transferProtocolType == "CIFS")
+        std::string_view scheme = boost::urls::url_view(imageUri).scheme();
+        if (scheme == "smb")
         {
             return TransferProtocol::smb;
         }
-
-        if (*transferProtocolType == "HTTPS")
+        if (scheme == "https")
         {
             return TransferProtocol::https;
         }
-
-        return TransferProtocol::invalid;
+        if (!scheme.empty())
+        {
+            return TransferProtocol::invalid;
+        }
     }
-
-    /**
-     * @brief Function extends URI with transfer protocol type.
-     *
-     */
-    std::string
-        getUriWithTransferProtocol(const std::string& imageUri,
-                                   const TransferProtocol& transferProtocol)
+    catch (std::exception& p)
     {
-        if (transferProtocol == TransferProtocol::smb)
-        {
-            return "smb://" + imageUri;
-        }
-
-        if (transferProtocol == TransferProtocol::https)
-        {
-            return "https://" + imageUri;
-        }
-
-        return imageUri;
+        BMCWEB_LOG_ERROR << p.what();
     }
 
-    /**
-     * @brief Function validate parameters of insert media request.
-     *
-     */
-    bool validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                        std::string& imageUrl,
-                        const std::optional<bool>& inserted,
-                        const std::optional<std::string>& transferMethod,
-                        const std::optional<std::string>& transferProtocolType)
+    return {};
+}
+
+/**
+ * @brief Function convert transfer protocol from string param.
+ *
+ */
+inline std::optional<TransferProtocol> getTransferProtocolFromParam(
+    const std::optional<std::string>& transferProtocolType)
+{
+    if (transferProtocolType == std::nullopt)
     {
-        BMCWEB_LOG_DEBUG << "Validation started";
-        // required param imageUrl must not be empty
-        if (imageUrl.empty())
-        {
-            BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
-
-            messages::propertyValueFormatError(asyncResp->res, "<empty>",
-                                               "Image");
-
-            return false;
-        }
-
-        // optional param inserted must be true
-        if ((inserted != std::nullopt) && (*inserted != true))
-        {
-            BMCWEB_LOG_ERROR
-                << "Request action optional parameter Inserted must be true.";
-
-            messages::actionParameterNotSupported(asyncResp->res, "Inserted",
-                                                  "InsertMedia");
-
-            return false;
-        }
-
-        // optional param transferMethod must be stream
-        if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
-        {
-            BMCWEB_LOG_ERROR << "Request action optional parameter "
-                                "TransferMethod must be Stream.";
-
-            messages::actionParameterNotSupported(
-                asyncResp->res, "TransferMethod", "InsertMedia");
-
-            return false;
-        }
-
-        std::optional<TransferProtocol> uriTransferProtocolType =
-            getTransferProtocolFromUri(imageUrl);
-
-        std::optional<TransferProtocol> paramTransferProtocolType =
-            getTransferProtocolFromParam(transferProtocolType);
-
-        // ImageUrl does not contain valid protocol type
-        if (*uriTransferProtocolType == TransferProtocol::invalid)
-        {
-            BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
-                                "contain specified protocol type from list: "
-                                "(smb, https).";
-
-            messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl);
-
-            return false;
-        }
-
-        // transferProtocolType should contain value from list
-        if (*paramTransferProtocolType == TransferProtocol::invalid)
-        {
-            BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
-                                "must be provided with value from list: "
-                                "(CIFS, HTTPS).";
-
-            messages::propertyValueNotInList(
-                asyncResp->res, *transferProtocolType, "TransferProtocolType");
-            return false;
-        }
-
-        // valid transfer protocol not provided either with URI nor param
-        if ((uriTransferProtocolType == std::nullopt) &&
-            (paramTransferProtocolType == std::nullopt))
-        {
-            BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
-                                "contain specified protocol type or param "
-                                "TransferProtocolType must be provided.";
-
-            messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl);
-
-            return false;
-        }
-
-        // valid transfer protocol provided both with URI and param
-        if ((paramTransferProtocolType != std::nullopt) &&
-            (uriTransferProtocolType != std::nullopt))
-        {
-            // check if protocol is the same for URI and param
-            if (*paramTransferProtocolType != *uriTransferProtocolType)
-            {
-                BMCWEB_LOG_ERROR << "Request action parameter "
-                                    "TransferProtocolType must  contain the "
-                                    "same protocol type as protocol type "
-                                    "provided with param imageUrl.";
-
-                messages::actionParameterValueTypeError(
-                    asyncResp->res, *transferProtocolType,
-                    "TransferProtocolType", "InsertMedia");
-
-                return false;
-            }
-        }
-
-        // validation passed
-        // add protocol to URI if needed
-        if (uriTransferProtocolType == std::nullopt)
-        {
-            imageUrl = getUriWithTransferProtocol(imageUrl,
-                                                  *paramTransferProtocolType);
-        }
-
-        return true;
+        return {};
     }
 
-    /**
-     * @brief Function handles POST method request.
-     *
-     * Analyzes POST body message before sends Reset request data to dbus.
-     */
-    void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                const crow::Request& req,
-                const std::vector<std::string>& params) override
+    if (*transferProtocolType == "CIFS")
     {
-        if (params.size() != 2)
-        {
-            messages::internalError(asyncResp->res);
-            return;
-        }
-
-        // take resource name from URL
-        const std::string& resName = params[1];
-
-        if (params[0] != "bmc")
-        {
-            messages::resourceNotFound(asyncResp->res, "VirtualMedia.Insert",
-                                       resName);
-
-            return;
-        }
-
-        crow::connections::systemBus->async_method_call(
-            [this, asyncResp, req,
-             resName](const boost::system::error_code ec,
-                      const GetObjectType& getObjectType) {
-                if (ec)
-                {
-                    BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
-                                     << ec;
-                    messages::internalError(asyncResp->res);
-
-                    return;
-                }
-                std::string service = getObjectType.begin()->first;
-                BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
-
-                crow::connections::systemBus->async_method_call(
-                    [this, service, resName, req,
-                     asyncResp](const boost::system::error_code ec,
-                                ManagedObjectType& subtree) {
-                        if (ec)
-                        {
-                            BMCWEB_LOG_DEBUG << "DBUS response error";
-
-                            return;
-                        }
-
-                        for (const auto& object : subtree)
-                        {
-                            const std::string& path =
-                                static_cast<const std::string&>(object.first);
-
-                            std::size_t lastIndex = path.rfind('/');
-                            if (lastIndex == std::string::npos)
-                            {
-                                continue;
-                            }
-
-                            lastIndex += 1;
-
-                            if (path.substr(lastIndex) == resName)
-                            {
-                                lastIndex = path.rfind("Proxy");
-                                if (lastIndex != std::string::npos)
-                                {
-                                    // Not possible in proxy mode
-                                    BMCWEB_LOG_DEBUG << "InsertMedia not "
-                                                        "allowed in proxy mode";
-                                    messages::resourceNotFound(
-                                        asyncResp->res,
-                                        "VirtualMedia.InsertMedia", resName);
-
-                                    return;
-                                }
-
-                                lastIndex = path.rfind("Legacy");
-                                if (lastIndex == std::string::npos)
-                                {
-                                    continue;
-                                }
-
-                                // Legacy mode
-                                std::string imageUrl;
-                                std::optional<std::string> userName;
-                                std::optional<std::string> password;
-                                std::optional<std::string> transferMethod;
-                                std::optional<std::string> transferProtocolType;
-                                std::optional<bool> writeProtected = true;
-                                std::optional<bool> inserted;
-
-                                // Read obligatory parameters (url of image)
-                                if (!json_util::readJson(
-                                        req, asyncResp->res, "Image", imageUrl,
-                                        "WriteProtected", writeProtected,
-                                        "UserName", userName, "Password",
-                                        password, "Inserted", inserted,
-                                        "TransferMethod", transferMethod,
-                                        "TransferProtocolType",
-                                        transferProtocolType))
-                                {
-                                    BMCWEB_LOG_DEBUG << "Image is not provided";
-                                    return;
-                                }
-
-                                bool paramsValid = validateParams(
-                                    asyncResp->res, imageUrl, inserted,
-                                    transferMethod, transferProtocolType);
-
-                                if (paramsValid == false)
-                                {
-                                    return;
-                                }
-
-                                // manager is irrelevant for VirtualMedia dbus
-                                // calls
-                                doMountVmLegacy(asyncResp, service, resName,
-                                                imageUrl, !(*writeProtected),
-                                                std::move(*userName),
-                                                std::move(*password));
-
-                                return;
-                            }
-                        }
-                        BMCWEB_LOG_DEBUG << "Parent item not found";
-                        messages::resourceNotFound(asyncResp->res,
-                                                   "VirtualMedia", resName);
-                    },
-                    service, "/xyz/openbmc_project/VirtualMedia",
-                    "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
-            },
-            "xyz.openbmc_project.ObjectMapper",
-            "/xyz/openbmc_project/object_mapper",
-            "xyz.openbmc_project.ObjectMapper", "GetObject",
-            "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
+        return TransferProtocol::smb;
     }
 
+    if (*transferProtocolType == "HTTPS")
+    {
+        return TransferProtocol::https;
+    }
+
+    return TransferProtocol::invalid;
+}
+
+/**
+ * @brief Function extends URI with transfer protocol type.
+ *
+ */
+inline std::string
+    getUriWithTransferProtocol(const std::string& imageUri,
+                               const TransferProtocol& transferProtocol)
+{
+    if (transferProtocol == TransferProtocol::smb)
+    {
+        return "smb://" + imageUri;
+    }
+
+    if (transferProtocol == TransferProtocol::https)
+    {
+        return "https://" + imageUri;
+    }
+
+    return imageUri;
+}
+
+/**
+ * @brief Function validate parameters of insert media request.
+ *
+ */
+inline bool
+    validateParams(crow::Response& res, std::string& imageUrl,
+                   const std::optional<bool>& inserted,
+                   const std::optional<std::string>& transferMethod,
+                   const std::optional<std::string>& transferProtocolType)
+{
+    BMCWEB_LOG_DEBUG << "Validation started";
+    // required param imageUrl must not be empty
+    if (imageUrl.empty())
+    {
+        BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
+
+        messages::propertyValueFormatError(res, "<empty>", "Image");
+
+        return false;
+    }
+
+    // optional param inserted must be true
+    if ((inserted != std::nullopt) && (*inserted != true))
+    {
+        BMCWEB_LOG_ERROR
+            << "Request action optional parameter Inserted must be true.";
+
+        messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
+
+        return false;
+    }
+
+    // optional param transferMethod must be stream
+    if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
+    {
+        BMCWEB_LOG_ERROR << "Request action optional parameter "
+                            "TransferMethod must be Stream.";
+
+        messages::actionParameterNotSupported(res, "TransferMethod",
+                                              "InsertMedia");
+
+        return false;
+    }
+
+    std::optional<TransferProtocol> uriTransferProtocolType =
+        getTransferProtocolFromUri(imageUrl);
+
+    std::optional<TransferProtocol> paramTransferProtocolType =
+        getTransferProtocolFromParam(transferProtocolType);
+
+    // ImageUrl does not contain valid protocol type
+    if (*uriTransferProtocolType == TransferProtocol::invalid)
+    {
+        BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
+                            "contain specified protocol type from list: "
+                            "(smb, https).";
+
+        messages::resourceAtUriInUnknownFormat(res, imageUrl);
+
+        return false;
+    }
+
+    // transferProtocolType should contain value from list
+    if (*paramTransferProtocolType == TransferProtocol::invalid)
+    {
+        BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
+                            "must be provided with value from list: "
+                            "(CIFS, HTTPS).";
+
+        messages::propertyValueNotInList(res, *transferProtocolType,
+                                         "TransferProtocolType");
+        return false;
+    }
+
+    // valid transfer protocol not provided either with URI nor param
+    if ((uriTransferProtocolType == std::nullopt) &&
+        (paramTransferProtocolType == std::nullopt))
+    {
+        BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
+                            "contain specified protocol type or param "
+                            "TransferProtocolType must be provided.";
+
+        messages::resourceAtUriInUnknownFormat(res, imageUrl);
+
+        return false;
+    }
+
+    // valid transfer protocol provided both with URI and param
+    if ((paramTransferProtocolType != std::nullopt) &&
+        (uriTransferProtocolType != std::nullopt))
+    {
+        // check if protocol is the same for URI and param
+        if (*paramTransferProtocolType != *uriTransferProtocolType)
+        {
+            BMCWEB_LOG_ERROR << "Request action parameter "
+                                "TransferProtocolType must  contain the "
+                                "same protocol type as protocol type "
+                                "provided with param imageUrl.";
+
+            messages::actionParameterValueTypeError(res, *transferProtocolType,
+                                                    "TransferProtocolType",
+                                                    "InsertMedia");
+
+            return false;
+        }
+    }
+
+    // validation passed
+    // add protocol to URI if needed
+    if (uriTransferProtocolType == std::nullopt)
+    {
+        imageUrl =
+            getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
+    }
+
+    return true;
+}
+
+template <typename T>
+static void secureCleanup(T& value)
+{
+    auto raw = const_cast<typename T::value_type*>(value.data());
+    explicit_bzero(raw, value.size() * sizeof(*raw));
+}
+
+class Credentials
+{
+  public:
+    Credentials(std::string&& user, std::string&& password) :
+        userBuf(std::move(user)), passBuf(std::move(password))
+    {}
+
+    ~Credentials()
+    {
+        secureCleanup(userBuf);
+        secureCleanup(passBuf);
+    }
+
+    const std::string& user()
+    {
+        return userBuf;
+    }
+
+    const std::string& password()
+    {
+        return passBuf;
+    }
+
+    Credentials() = delete;
+    Credentials(const Credentials&) = delete;
+    Credentials& operator=(const Credentials&) = delete;
+
+  private:
+    std::string userBuf;
+    std::string passBuf;
+};
+
+class CredentialsProvider
+{
+  public:
     template <typename T>
-    static void secureCleanup(T& value)
+    struct Deleter
     {
-        auto raw = const_cast<typename T::value_type*>(value.data());
-        explicit_bzero(raw, value.size() * sizeof(*raw));
+        void operator()(T* buff) const
+        {
+            if (buff)
+            {
+                secureCleanup(*buff);
+                delete buff;
+            }
+        }
+    };
+
+    using Buffer = std::vector<char>;
+    using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
+    // Using explicit definition instead of std::function to avoid implicit
+    // conversions eg. stack copy instead of reference
+    using FormatterFunc = void(const std::string& username,
+                               const std::string& password, Buffer& dest);
+
+    CredentialsProvider(std::string&& user, std::string&& password) :
+        credentials(std::move(user), std::move(password))
+    {}
+
+    const std::string& user()
+    {
+        return credentials.user();
     }
 
-    class Credentials
+    const std::string& password()
     {
-      public:
-        Credentials(std::string&& user, std::string&& password) :
-            userBuf(std::move(user)), passBuf(std::move(password))
-        {}
+        return credentials.password();
+    }
 
-        ~Credentials()
-        {
-            secureCleanup(userBuf);
-            secureCleanup(passBuf);
-        }
-
-        const std::string& user()
-        {
-            return userBuf;
-        }
-
-        const std::string& password()
-        {
-            return passBuf;
-        }
-
-      private:
-        Credentials() = delete;
-        Credentials(const Credentials&) = delete;
-        Credentials& operator=(const Credentials&) = delete;
-
-        std::string userBuf;
-        std::string passBuf;
-    };
-
-    class CredentialsProvider
+    SecureBuffer pack(FormatterFunc formatter)
     {
-      public:
-        template <typename T>
-        struct Deleter
+        SecureBuffer packed{new Buffer{}};
+        if (formatter)
         {
-            void operator()(T* buff) const
-            {
-                if (buff)
-                {
-                    secureCleanup(*buff);
-                    delete buff;
-                }
-            }
-        };
-
-        using Buffer = std::vector<char>;
-        using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
-        // Using explicit definition instead of std::function to avoid implicit
-        // conversions eg. stack copy instead of reference
-        using FormatterFunc = void(const std::string& username,
-                                   const std::string& password, Buffer& dest);
-
-        CredentialsProvider(std::string&& user, std::string&& password) :
-            credentials(std::move(user), std::move(password))
-        {}
-
-        const std::string& user()
-        {
-            return credentials.user();
+            formatter(credentials.user(), credentials.password(), *packed);
         }
 
-        const std::string& password()
-        {
-            return credentials.password();
-        }
+        return packed;
+    }
 
-        SecureBuffer pack(FormatterFunc formatter)
-        {
-            SecureBuffer packed{new Buffer{}};
-            if (formatter)
-            {
-                formatter(credentials.user(), credentials.password(), *packed);
-            }
+  private:
+    Credentials credentials;
+};
 
-            return packed;
-        }
+// Wrapper for boost::async_pipe ensuring proper pipe cleanup
+template <typename Buffer>
+class Pipe
+{
+  public:
+    using unix_fd = sdbusplus::message::unix_fd;
 
-      private:
-        Credentials credentials;
-    };
+    Pipe(boost::asio::io_context& io, Buffer&& buffer) :
+        impl(io), buffer{std::move(buffer)}
+    {}
 
-    // Wrapper for boost::async_pipe ensuring proper pipe cleanup
-    template <typename Buffer>
-    class Pipe
+    ~Pipe()
     {
-      public:
-        using unix_fd = sdbusplus::message::unix_fd;
+        // Named pipe needs to be explicitly removed
+        impl.close();
+    }
 
-        Pipe(boost::asio::io_context& io, Buffer&& buffer) :
-            impl(io), buffer{std::move(buffer)}
-        {}
-
-        ~Pipe()
-        {
-            // Named pipe needs to be explicitly removed
-            impl.close();
-        }
-
-        unix_fd fd()
-        {
-            return unix_fd{impl.native_source()};
-        }
-
-        template <typename WriteHandler>
-        void asyncWrite(WriteHandler&& handler)
-        {
-            impl.async_write_some(data(), std::forward<WriteHandler>(handler));
-        }
-
-      private:
-        // Specialization for pointer types
-        template <typename B = Buffer>
-        typename std::enable_if<boost::has_dereference<B>::value,
-                                boost::asio::const_buffer>::type
-            data()
-        {
-            return boost::asio::buffer(*buffer);
-        }
-
-        template <typename B = Buffer>
-        typename std::enable_if<!boost::has_dereference<B>::value,
-                                boost::asio::const_buffer>::type
-            data()
-        {
-            return boost::asio::buffer(buffer);
-        }
-
-        const std::string name;
-        boost::process::async_pipe impl;
-        Buffer buffer;
-    };
-
-    /**
-     * @brief Function transceives data with dbus directly.
-     *
-     * All BMC state properties will be retrieved before sending reset request.
-     */
-    void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                         const std::string& service, const std::string& name,
-                         const std::string& imageUrl, const bool rw,
-                         std::string&& userName, std::string&& password)
+    unix_fd fd()
     {
-        using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
-        constexpr const size_t secretLimit = 1024;
+        return unix_fd{impl.native_source()};
+    }
 
-        std::shared_ptr<SecurePipe> secretPipe;
-        std::variant<int, SecurePipe::unix_fd> unixFd = -1;
+    template <typename WriteHandler>
+    void asyncWrite(WriteHandler&& handler)
+    {
+        impl.async_write_some(data(), std::forward<WriteHandler>(handler));
+    }
 
-        if (!userName.empty() || !password.empty())
+  private:
+    // Specialization for pointer types
+    template <typename B = Buffer>
+    typename std::enable_if<boost::has_dereference<B>::value,
+                            boost::asio::const_buffer>::type
+        data()
+    {
+        return boost::asio::buffer(*buffer);
+    }
+
+    template <typename B = Buffer>
+    typename std::enable_if<!boost::has_dereference<B>::value,
+                            boost::asio::const_buffer>::type
+        data()
+    {
+        return boost::asio::buffer(buffer);
+    }
+
+    const std::string name;
+    boost::process::async_pipe impl;
+    Buffer buffer;
+};
+
+/**
+ * @brief Function transceives data with dbus directly.
+ *
+ * All BMC state properties will be retrieved before sending reset request.
+ */
+inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                            const std::string& service, const std::string& name,
+                            const std::string& imageUrl, const bool rw,
+                            std::string&& userName, std::string&& password)
+{
+    using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
+    constexpr const size_t secretLimit = 1024;
+
+    std::shared_ptr<SecurePipe> secretPipe;
+    std::variant<int, SecurePipe::unix_fd> unixFd = -1;
+
+    if (!userName.empty() || !password.empty())
+    {
+        // Encapsulate in safe buffer
+        CredentialsProvider credentials(std::move(userName),
+                                        std::move(password));
+
+        // Payload must contain data + NULL delimiters
+        if (credentials.user().size() + credentials.password().size() + 2 >
+            secretLimit)
         {
-            // Encapsulate in safe buffer
-            CredentialsProvider credentials(std::move(userName),
-                                            std::move(password));
+            BMCWEB_LOG_ERROR << "Credentials too long to handle";
+            messages::unrecognizedRequestBody(asyncResp->res);
+            return;
+        }
 
-            // Payload must contain data + NULL delimiters
-            if (credentials.user().size() + credentials.password().size() + 2 >
-                secretLimit)
-            {
-                BMCWEB_LOG_ERROR << "Credentials too long to handle";
-                messages::unrecognizedRequestBody(asyncResp->res);
-                return;
-            }
-
-            // Pack secret
-            auto secret = credentials.pack([](const auto& user,
-                                              const auto& pass, auto& buff) {
+        // Pack secret
+        auto secret = credentials.pack(
+            [](const auto& user, const auto& pass, auto& buff) {
                 std::copy(user.begin(), user.end(), std::back_inserter(buff));
                 buff.push_back('\0');
                 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
                 buff.push_back('\0');
             });
 
-            // Open pipe
-            secretPipe = std::make_shared<SecurePipe>(
-                crow::connections::systemBus->get_io_context(),
-                std::move(secret));
-            unixFd = secretPipe->fd();
+        // Open pipe
+        secretPipe = std::make_shared<SecurePipe>(
+            crow::connections::systemBus->get_io_context(), std::move(secret));
+        unixFd = secretPipe->fd();
 
-            // Pass secret over pipe
-            secretPipe->asyncWrite(
-                [asyncResp](const boost::system::error_code& ec, std::size_t) {
-                    if (ec)
-                    {
-                        BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
-                        messages::internalError(asyncResp->res);
-                    }
-                });
-        }
+        // Pass secret over pipe
+        secretPipe->asyncWrite(
+            [asyncResp](const boost::system::error_code& ec, std::size_t) {
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
+                    messages::internalError(asyncResp->res);
+                }
+            });
+    }
 
+    crow::connections::systemBus->async_method_call(
+        [asyncResp, secretPipe](const boost::system::error_code ec,
+                                bool success) {
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
+                messages::internalError(asyncResp->res);
+            }
+            else if (!success)
+            {
+                BMCWEB_LOG_ERROR << "Service responded with error";
+                messages::generalError(asyncResp->res);
+            }
+        },
+        service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
+        "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
+        unixFd);
+}
+
+/**
+ * @brief Function transceives data with dbus directly.
+ *
+ * All BMC state properties will be retrieved before sending reset request.
+ */
+inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                       const std::string& service, const std::string& name,
+                       bool legacy)
+{
+
+    // Legacy mount requires parameter with image
+    if (legacy)
+    {
         crow::connections::systemBus->async_method_call(
-            [asyncResp, secretPipe](const boost::system::error_code ec,
-                                    bool success) {
+            [asyncResp](const boost::system::error_code ec) {
                 if (ec)
                 {
                     BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
+
                     messages::internalError(asyncResp->res);
-                }
-                else if (!success)
-                {
-                    BMCWEB_LOG_ERROR << "Service responded with error";
-                    messages::generalError(asyncResp->res);
+                    return;
                 }
             },
             service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
-            "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
-            unixFd);
+            "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
     }
-};
-
-/**
-   @brief EjectMedia action class
- */
-class VirtualMediaActionEjectMedia : public Node
-{
-  public:
-    VirtualMediaActionEjectMedia(App& app) :
-        Node(app,
-             "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
-             "VirtualMedia.EjectMedia",
-             std::string(), std::string())
+    else // proxy
     {
-        entityPrivileges = {
-            {boost::beast::http::verb::get, {{"Login"}}},
-            {boost::beast::http::verb::head, {{"Login"}}},
-            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
-    }
-
-  private:
-    /**
-     * @brief Function handles POST method request.
-     *
-     * Analyzes POST body message before sends Reset request data to dbus.
-     */
-    void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                const crow::Request& req,
-                const std::vector<std::string>& params) override
-    {
-        if (params.size() != 2)
-        {
-            messages::internalError(asyncResp->res);
-            return;
-        }
-
-        // take resource name from URL
-        const std::string& resName = params[1];
-
-        if (params[0] != "bmc")
-        {
-            messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject",
-                                       resName);
-
-            return;
-        }
-
         crow::connections::systemBus->async_method_call(
-            [this, asyncResp{std::move(asyncResp)}, req,
-             resName](const boost::system::error_code ec,
-                      const GetObjectType& getObjectType) {
+            [asyncResp](const boost::system::error_code ec) {
                 if (ec)
                 {
-                    BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
-                                     << ec;
+                    BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
+
                     messages::internalError(asyncResp->res);
+                    return;
+                }
+            },
+            service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
+            "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
+    }
+}
+
+inline void requestNBDVirtualMediaRoutes(App& app)
+{
+    BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
+                      "VirtualMedia.InsertMedia")
+        .privileges({"ConfigureManager"})
+        .methods(boost::beast::http::verb::post)(
+            [](const crow::Request& req,
+               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+               const std::string& name, const std::string& resName) {
+                if (name != "bmc")
+                {
+                    messages::resourceNotFound(asyncResp->res,
+                                               "VirtualMedia.Insert", resName);
 
                     return;
                 }
-                std::string service = getObjectType.begin()->first;
-                BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
 
                 crow::connections::systemBus->async_method_call(
-                    [this, resName, service, req,
-                     asyncResp{asyncResp}](const boost::system::error_code ec,
-                                           ManagedObjectType& subtree) {
+                    [asyncResp, req,
+                     resName](const boost::system::error_code ec,
+                              const GetObjectType& getObjectType) {
                         if (ec)
                         {
-                            BMCWEB_LOG_DEBUG << "DBUS response error";
+                            BMCWEB_LOG_ERROR
+                                << "ObjectMapper::GetObject call failed: "
+                                << ec;
+                            messages::internalError(asyncResp->res);
 
                             return;
                         }
+                        std::string service = getObjectType.begin()->first;
+                        BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
 
-                        for (const auto& object : subtree)
-                        {
-                            const std::string& path =
-                                static_cast<const std::string&>(object.first);
-
-                            std::size_t lastIndex = path.rfind('/');
-                            if (lastIndex == std::string::npos)
-                            {
-                                continue;
-                            }
-
-                            lastIndex += 1;
-
-                            if (path.substr(lastIndex) == resName)
-                            {
-                                lastIndex = path.rfind("Proxy");
-                                if (lastIndex != std::string::npos)
+                        crow::connections::systemBus->async_method_call(
+                            [service, resName, req,
+                             asyncResp](const boost::system::error_code ec,
+                                        ManagedObjectType& subtree) {
+                                if (ec)
                                 {
-                                    // Proxy mode
-                                    doVmAction(asyncResp, service, resName,
-                                               false);
+                                    BMCWEB_LOG_DEBUG << "DBUS response error";
+
+                                    return;
                                 }
 
-                                lastIndex = path.rfind("Legacy");
-                                if (lastIndex != std::string::npos)
+                                for (const auto& object : subtree)
                                 {
-                                    // Legacy mode
-                                    doVmAction(asyncResp, service, resName,
-                                               true);
-                                }
+                                    const std::string& path =
+                                        static_cast<const std::string&>(
+                                            object.first);
 
-                                return;
-                            }
-                        }
-                        BMCWEB_LOG_DEBUG << "Parent item not found";
-                        messages::resourceNotFound(asyncResp->res,
-                                                   "VirtualMedia", resName);
+                                    std::size_t lastIndex = path.rfind('/');
+                                    if (lastIndex == std::string::npos)
+                                    {
+                                        continue;
+                                    }
+
+                                    lastIndex += 1;
+
+                                    if (path.substr(lastIndex) == resName)
+                                    {
+                                        lastIndex = path.rfind("Proxy");
+                                        if (lastIndex != std::string::npos)
+                                        {
+                                            // Not possible in proxy mode
+                                            BMCWEB_LOG_DEBUG
+                                                << "InsertMedia not "
+                                                   "allowed in proxy mode";
+                                            messages::resourceNotFound(
+                                                asyncResp->res,
+                                                "VirtualMedia.InsertMedia",
+                                                resName);
+
+                                            return;
+                                        }
+
+                                        lastIndex = path.rfind("Legacy");
+                                        if (lastIndex == std::string::npos)
+                                        {
+                                            continue;
+                                        }
+
+                                        // Legacy mode
+                                        std::string imageUrl;
+                                        std::optional<std::string> userName;
+                                        std::optional<std::string> password;
+                                        std::optional<std::string>
+                                            transferMethod;
+                                        std::optional<std::string>
+                                            transferProtocolType;
+                                        std::optional<bool> writeProtected =
+                                            true;
+                                        std::optional<bool> inserted;
+
+                                        // Read obligatory parameters (url of
+                                        // image)
+                                        if (!json_util::readJson(
+                                                req, asyncResp->res, "Image",
+                                                imageUrl, "WriteProtected",
+                                                writeProtected, "UserName",
+                                                userName, "Password", password,
+                                                "Inserted", inserted,
+                                                "TransferMethod",
+                                                transferMethod,
+                                                "TransferProtocolType",
+                                                transferProtocolType))
+                                        {
+                                            BMCWEB_LOG_DEBUG
+                                                << "Image is not provided";
+                                            return;
+                                        }
+
+                                        bool paramsValid = validateParams(
+                                            asyncResp->res, imageUrl, inserted,
+                                            transferMethod,
+                                            transferProtocolType);
+
+                                        if (paramsValid == false)
+                                        {
+                                            return;
+                                        }
+
+                                        // manager is irrelevant for
+                                        // VirtualMedia dbus calls
+                                        doMountVmLegacy(asyncResp, service,
+                                                        resName, imageUrl,
+                                                        !(*writeProtected),
+                                                        std::move(*userName),
+                                                        std::move(*password));
+
+                                        return;
+                                    }
+                                }
+                                BMCWEB_LOG_DEBUG << "Parent item not found";
+                                messages::resourceNotFound(
+                                    asyncResp->res, "VirtualMedia", resName);
+                            },
+                            service, "/xyz/openbmc_project/VirtualMedia",
+                            "org.freedesktop.DBus.ObjectManager",
+                            "GetManagedObjects");
                     },
-                    service, "/xyz/openbmc_project/VirtualMedia",
-                    "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
-            },
-            "xyz.openbmc_project.ObjectMapper",
-            "/xyz/openbmc_project/object_mapper",
-            "xyz.openbmc_project.ObjectMapper", "GetObject",
-            "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
-    }
+                    "xyz.openbmc_project.ObjectMapper",
+                    "/xyz/openbmc_project/object_mapper",
+                    "xyz.openbmc_project.ObjectMapper", "GetObject",
+                    "/xyz/openbmc_project/VirtualMedia",
+                    std::array<const char*, 0>());
+            });
 
-    /**
-     * @brief Function transceives data with dbus directly.
-     *
-     * All BMC state properties will be retrieved before sending reset request.
-     */
-    void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                    const std::string& service, const std::string& name,
-                    bool legacy)
-    {
+    BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
+                      "VirtualMedia.EjectMedia")
+        .privileges({"ConfigureManager"})
+        .methods(boost::beast::http::verb::post)(
+            [](const crow::Request& req,
+               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+               const std::string& name, const std::string& resName) {
+                if (name != "bmc")
+                {
+                    messages::resourceNotFound(asyncResp->res,
+                                               "VirtualMedia.Eject", resName);
 
-        // Legacy mount requires parameter with image
-        if (legacy)
-        {
-            crow::connections::systemBus->async_method_call(
-                [asyncResp](const boost::system::error_code ec) {
-                    if (ec)
-                    {
-                        BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
+                    return;
+                }
 
-                        messages::internalError(asyncResp->res);
-                        return;
-                    }
-                },
-                service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
-                "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
-        }
-        else // proxy
-        {
-            crow::connections::systemBus->async_method_call(
-                [asyncResp](const boost::system::error_code ec) {
-                    if (ec)
-                    {
-                        BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
-
-                        messages::internalError(asyncResp->res);
-                        return;
-                    }
-                },
-                service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
-                "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
-        }
-    }
-};
-
-class VirtualMediaCollection : public Node
-{
-  public:
-    /*
-     * Default Constructor
-     */
-    VirtualMediaCollection(App& app) :
-        Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string())
-    {
-        entityPrivileges = {
-            {boost::beast::http::verb::get, {{"Login"}}},
-            {boost::beast::http::verb::head, {{"Login"}}},
-            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
-    }
-
-  private:
-    /**
-     * Functions triggers appropriate requests on DBus
-     */
-    void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-               const crow::Request&,
-               const std::vector<std::string>& params) override
-    {
-
-        // Check if there is required param, truly entering this shall be
-        // impossible
-        if (params.size() != 1)
-        {
-            messages::internalError(asyncResp->res);
-
-            return;
-        }
-
-        const std::string& name = params[0];
-
-        if (name != "bmc")
-        {
-            messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
-
-            return;
-        }
-
-        asyncResp->res.jsonValue["@odata.type"] =
-            "#VirtualMediaCollection.VirtualMediaCollection";
-        asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
-        asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/Managers/" + name + "/VirtualMedia";
-
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, name](const boost::system::error_code ec,
+                crow::connections::systemBus->async_method_call(
+                    [asyncResp, req,
+                     resName](const boost::system::error_code ec,
                               const GetObjectType& getObjectType) {
-                if (ec)
+                        if (ec)
+                        {
+                            BMCWEB_LOG_ERROR
+                                << "ObjectMapper::GetObject call failed: "
+                                << ec;
+                            messages::internalError(asyncResp->res);
+
+                            return;
+                        }
+                        std::string service = getObjectType.begin()->first;
+                        BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
+
+                        crow::connections::systemBus->async_method_call(
+                            [resName, service, req, asyncResp{asyncResp}](
+                                const boost::system::error_code ec,
+                                ManagedObjectType& subtree) {
+                                if (ec)
+                                {
+                                    BMCWEB_LOG_DEBUG << "DBUS response error";
+
+                                    return;
+                                }
+
+                                for (const auto& object : subtree)
+                                {
+                                    const std::string& path =
+                                        static_cast<const std::string&>(
+                                            object.first);
+
+                                    std::size_t lastIndex = path.rfind('/');
+                                    if (lastIndex == std::string::npos)
+                                    {
+                                        continue;
+                                    }
+
+                                    lastIndex += 1;
+
+                                    if (path.substr(lastIndex) == resName)
+                                    {
+                                        lastIndex = path.rfind("Proxy");
+                                        if (lastIndex != std::string::npos)
+                                        {
+                                            // Proxy mode
+                                            doVmAction(asyncResp, service,
+                                                       resName, false);
+                                        }
+
+                                        lastIndex = path.rfind("Legacy");
+                                        if (lastIndex != std::string::npos)
+                                        {
+                                            // Legacy mode
+                                            doVmAction(asyncResp, service,
+                                                       resName, true);
+                                        }
+
+                                        return;
+                                    }
+                                }
+                                BMCWEB_LOG_DEBUG << "Parent item not found";
+                                messages::resourceNotFound(
+                                    asyncResp->res, "VirtualMedia", resName);
+                            },
+                            service, "/xyz/openbmc_project/VirtualMedia",
+                            "org.freedesktop.DBus.ObjectManager",
+                            "GetManagedObjects");
+                    },
+                    "xyz.openbmc_project.ObjectMapper",
+                    "/xyz/openbmc_project/object_mapper",
+                    "xyz.openbmc_project.ObjectMapper", "GetObject",
+                    "/xyz/openbmc_project/VirtualMedia",
+                    std::array<const char*, 0>());
+            });
+    BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
+        .privileges({"Login"})
+        .methods(boost::beast::http::verb::get)(
+            [](const crow::Request& /* req */,
+               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+               const std::string& name) {
+                if (name != "bmc")
                 {
-                    BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
-                                     << ec;
-                    messages::internalError(asyncResp->res);
+                    messages::resourceNotFound(asyncResp->res, "VirtualMedia",
+                                               name);
 
                     return;
                 }
-                std::string service = getObjectType.begin()->first;
-                BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
 
-                getVmResourceList(asyncResp, service, name);
-            },
-            "xyz.openbmc_project.ObjectMapper",
-            "/xyz/openbmc_project/object_mapper",
-            "xyz.openbmc_project.ObjectMapper", "GetObject",
-            "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
-    }
-};
+                asyncResp->res.jsonValue["@odata.type"] =
+                    "#VirtualMediaCollection.VirtualMediaCollection";
+                asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
+                asyncResp->res.jsonValue["@odata.id"] =
+                    "/redfish/v1/Managers/" + name + "/VirtualMedia";
 
-class VirtualMedia : public Node
-{
-  public:
-    /*
-     * Default Constructor
-     */
-    VirtualMedia(App& app) :
-        Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/",
-             std::string(), std::string())
-    {
-        entityPrivileges = {
-            {boost::beast::http::verb::get, {{"Login"}}},
-            {boost::beast::http::verb::head, {{"Login"}}},
-            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
-            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
-    }
+                crow::connections::systemBus->async_method_call(
+                    [asyncResp, name](const boost::system::error_code ec,
+                                      const GetObjectType& getObjectType) {
+                        if (ec)
+                        {
+                            BMCWEB_LOG_ERROR
+                                << "ObjectMapper::GetObject call failed: "
+                                << ec;
+                            messages::internalError(asyncResp->res);
 
-  private:
-    /**
-     * Functions triggers appropriate requests on DBus
-     */
-    void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-               const crow::Request&,
-               const std::vector<std::string>& params) override
-    {
-        // Check if there is required param, truly entering this shall be
-        // impossible
-        if (params.size() != 2)
-        {
-            messages::internalError(asyncResp->res);
-            return;
-        }
-        const std::string& name = params[0];
-        const std::string& resName = params[1];
+                            return;
+                        }
+                        std::string service = getObjectType.begin()->first;
+                        BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
 
-        if (name != "bmc")
-        {
-            messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
+                        getVmResourceList(asyncResp, service, name);
+                    },
+                    "xyz.openbmc_project.ObjectMapper",
+                    "/xyz/openbmc_project/object_mapper",
+                    "xyz.openbmc_project.ObjectMapper", "GetObject",
+                    "/xyz/openbmc_project/VirtualMedia",
+                    std::array<const char*, 0>());
+            });
 
-            return;
-        }
-
-        crow::connections::systemBus->async_method_call(
-            [asyncResp, name, resName](const boost::system::error_code ec,
-                                       const GetObjectType& getObjectType) {
-                if (ec)
+    BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
+        .privileges({"Login"})
+        .methods(boost::beast::http::verb::get)(
+            [](const crow::Request& /* req */,
+               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+               const std::string& name, const std::string& resName) {
+                if (name != "bmc")
                 {
-                    BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
-                                     << ec;
-                    messages::internalError(asyncResp->res);
+                    messages::resourceNotFound(asyncResp->res, "VirtualMedia",
+                                               resName);
 
                     return;
                 }
-                std::string service = getObjectType.begin()->first;
-                BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
 
-                getVmData(asyncResp, service, name, resName);
-            },
-            "xyz.openbmc_project.ObjectMapper",
-            "/xyz/openbmc_project/object_mapper",
-            "xyz.openbmc_project.ObjectMapper", "GetObject",
-            "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
-    }
-};
+                crow::connections::systemBus->async_method_call(
+                    [asyncResp, name,
+                     resName](const boost::system::error_code ec,
+                              const GetObjectType& getObjectType) {
+                        if (ec)
+                        {
+                            BMCWEB_LOG_ERROR
+                                << "ObjectMapper::GetObject call failed: "
+                                << ec;
+                            messages::internalError(asyncResp->res);
+
+                            return;
+                        }
+                        std::string service = getObjectType.begin()->first;
+                        BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
+
+                        getVmData(asyncResp, service, name, resName);
+                    },
+                    "xyz.openbmc_project.ObjectMapper",
+                    "/xyz/openbmc_project/object_mapper",
+                    "xyz.openbmc_project.ObjectMapper", "GetObject",
+                    "/xyz/openbmc_project/VirtualMedia",
+                    std::array<const char*, 0>());
+            });
+}
 
 } // namespace redfish
