summaryrefslogtreecommitdiff
path: root/redfish-core/lib/metadata.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'redfish-core/lib/metadata.hpp')
-rw-r--r--redfish-core/lib/metadata.hpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/redfish-core/lib/metadata.hpp b/redfish-core/lib/metadata.hpp
new file mode 100644
index 0000000000..4d8b1312c7
--- /dev/null
+++ b/redfish-core/lib/metadata.hpp
@@ -0,0 +1,123 @@
+#pragma once
+
+#include "bmcweb_config.h"
+
+#include "app.hpp"
+#include "async_resp.hpp"
+#include "http_request.hpp"
+#include "persistent_data.hpp"
+#include "query.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/systemd_utils.hpp"
+
+#include <tinyxml2.h>
+
+#include <nlohmann/json.hpp>
+
+namespace redfish
+{
+
+inline std::string
+ getMetadataPieceForFile(const std::filesystem::path& filename)
+{
+ std::string xml;
+ tinyxml2::XMLDocument doc;
+ std::string pathStr = filename.string();
+ if (doc.LoadFile(pathStr.c_str()) != tinyxml2::XML_SUCCESS)
+ {
+ BMCWEB_LOG_ERROR("Failed to open XML file {}", pathStr);
+ return "";
+ }
+ xml += std::format(" <edmx:Reference Uri=\"/redfish/v1/schema/{}\">\n",
+ filename.filename().string());
+ // std::string edmx = "{http://docs.oasis-open.org/odata/ns/edmx}";
+ // std::string edm = "{http://docs.oasis-open.org/odata/ns/edm}";
+ const char* edmx = "edmx:Edmx";
+ for (tinyxml2::XMLElement* edmxNode = doc.FirstChildElement(edmx);
+ edmxNode != nullptr; edmxNode = edmxNode->NextSiblingElement(edmx))
+ {
+ const char* dataServices = "edmx:DataServices";
+ for (tinyxml2::XMLElement* node =
+ edmxNode->FirstChildElement(dataServices);
+ node != nullptr; node = node->NextSiblingElement(dataServices))
+ {
+ BMCWEB_LOG_DEBUG("Got data service for {}", pathStr);
+ const char* schemaTag = "Schema";
+ for (tinyxml2::XMLElement* schemaNode =
+ node->FirstChildElement(schemaTag);
+ schemaNode != nullptr;
+ schemaNode = schemaNode->NextSiblingElement(schemaTag))
+ {
+ std::string ns = schemaNode->Attribute("Namespace");
+ // BMCWEB_LOG_DEBUG("Found namespace {}", ns);
+ std::string alias;
+ if (std::string_view(ns).starts_with("RedfishExtensions"))
+ {
+ alias = " Alias=\"Redfish\"";
+ }
+ xml += std::format(
+ " <edmx:Include Namespace=\"{}\"{}/>\n", ns, alias);
+ }
+ }
+ }
+ xml += " </edmx:Reference>\n";
+ return xml;
+}
+
+inline void
+ handleMetadataGet(App& /*app*/, const crow::Request& /*req*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ std::filesystem::path schema("/usr/share/www/redfish/v1/schema");
+ std::error_code ec;
+ auto iter = std::filesystem::directory_iterator(schema, ec);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Failed to open XML folder {}", schema.string());
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
+ std::string xml;
+
+ xml += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ xml +=
+ "<edmx:Edmx xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" Version=\"4.0\">\n";
+ for (const auto& dirEntry : iter)
+ {
+ std::string path = dirEntry.path().filename();
+ if (!std::string_view(path).ends_with("_v1.xml"))
+ {
+ continue;
+ }
+ std::string metadataPiece = getMetadataPieceForFile(dirEntry.path());
+ if (metadataPiece.empty())
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
+ xml += metadataPiece;
+ }
+ xml += " <edmx:DataServices>\n";
+ xml +=
+ " <Schema xmlns=\"http://docs.oasis-open.org/odata/ns/edm\" Namespace=\"Service\">\n";
+ xml +=
+ " <EntityContainer Name=\"Service\" Extends=\"ServiceRoot.v1_0_0.ServiceContainer\"/>\n";
+ xml += " </Schema>\n";
+ xml += " </edmx:DataServices>\n";
+ xml += "</edmx:Edmx>\n";
+
+ asyncResp->res.addHeader(boost::beast::http::field::content_type,
+ "application/xml");
+ asyncResp->res.write(std::move(xml));
+}
+
+inline void requestRoutesMetadata(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/$metadata")
+ .methods(boost::beast::http::verb::get)(
+ std::bind_front(handleMetadataGet, std::ref(app)));
+}
+
+} // namespace redfish