Add back odata support

/redfish/v1/odata/index.json was inadvertently moved to be not
installed in
a529a6aa44e04ae5845d1324f3e8c887ebd47f7b

This file is basically unused, and even this author doesn't understand
what it's used for, but it is technically required in the spec, so add
it back using a runtime derived handler.

Tested:
Get /redfish/v1/odata returns the appropriate struct.

Change-Id: I548abbdd9f0b1eb28299165202626feede41e363
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/redfish-core/lib/odata.hpp b/redfish-core/lib/odata.hpp
new file mode 100644
index 0000000..beb2647
--- /dev/null
+++ b/redfish-core/lib/odata.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "app.hpp"
+#include "error_messages.hpp"
+#include "http_request.hpp"
+#include "http_response.hpp"
+#include "query.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utility.hpp"
+
+#include <boost/url/format.hpp>
+#include <nlohmann/json.hpp>
+
+#include <memory>
+#include <ranges>
+#include <string>
+#include <string_view>
+
+namespace redfish
+{
+
+inline void redfishOdataGet(const crow::Request& /*req*/,
+                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    nlohmann::json::object_t obj;
+    obj["@odata.context"] = "/redfish/v1/$metadata";
+    nlohmann::json::array_t value;
+    for (std::string_view service :
+         {"$metadata", "odata", "JsonSchemas", "Service", "ServiceRoot",
+          "Systems", "Chassis", "Managers", "SessionService", "AccountService",
+          "UpdateService"})
+    {
+        nlohmann::json::object_t serviceObj;
+        serviceObj["kind"] = "Singleton";
+        serviceObj["name"] = "$metadata";
+        boost::urls::url url = boost::urls::format("/redfish/v1/{}", service);
+        if (service == "Service")
+        {
+            url = boost::urls::url("/redfish/v1");
+        }
+        serviceObj["url"] = url;
+        value.emplace_back(std::move(serviceObj));
+    }
+
+    obj["value"] = std::move(value);
+
+    asyncResp->res.jsonValue = std::move(obj);
+}
+
+inline void requestRoutesOdata(App& app)
+{
+    BMCWEB_ROUTE(app, "/redfish/v1/odata/")
+        .methods(boost::beast::http::verb::get)(redfishOdataGet);
+}
+
+} // namespace redfish