From 391c5dedbb1caa1069e07fcf58344c73de391a0d Mon Sep 17 00:00:00 2001 From: "Czarnowski, Przemyslaw" Date: Fri, 20 Dec 2019 14:06:30 +0100 Subject: Add configuration class Configuration class is used to read configration from file and validate entries. Also exposes API to serve stored data. Change-Id: Id4989ff45ff4a5cf7af7acf76a89b1c5838862f4 Signed-off-by: Rapkiewicz, Pawel Signed-off-by: Czarnowski, Przemyslaw --- virtual-media/src/configuration.hpp | 233 ++++++++++++++++++++++++++++++++++++ virtual-media/src/main.cpp | 14 ++- 2 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 virtual-media/src/configuration.hpp diff --git a/virtual-media/src/configuration.hpp b/virtual-media/src/configuration.hpp new file mode 100644 index 0000000..dd71837 --- /dev/null +++ b/virtual-media/src/configuration.hpp @@ -0,0 +1,233 @@ +#pragma once + +#include "logger.hpp" +#include "system.hpp" + +#include +#include +#include +#include +#include +#include +#include + +class Configuration +{ + public: + enum class Mode + { + // Proxy mode - works directly from browser and uses JavaScript/HTML5 + // to communicate over Secure WebSockets directly to HTTPS endpoint + // hosted by bmcweb on BMC + proxy = 0, + + // Legacy mode - is initiated from browser using Redfish defined + // VirtualMedia schemas, then BMC process connects to external + // CIFS/HTTPS image pointed during initialization. + legacy = 1, + }; + + struct MountPoint + { + NBDDevice nbdDevice; + std::string unixSocket; + std::string endPointId; + std::optional timeout; + std::optional blocksize; + Mode mode; + + static std::vector toArgs(const MountPoint& mp) + { + std::vector args = { + "-t", "30", "-u", mp.unixSocket, mp.nbdDevice.to_path(), "-n"}; + return args; + } + }; + + const MountPoint* getMountPoint(const std::string& name) const + { + const auto mp = mountPoints.find(name); + if (mp != mountPoints.end()) + { + return &(mp->second); + } + else + { + return nullptr; + } + } + + bool valid = false; + boost::container::flat_map mountPoints; + + Configuration(const std::string& file) + { + valid = loadConfiguration(file); + } + + private: + bool loadConfiguration(const std::string& file) noexcept + { + std::ifstream configFile(file); + if (!configFile.is_open()) + { + LogMsg(Logger::Critical, "Could not open configuration file"); + return false; + } + try + { + auto data = nlohmann::json::parse(configFile, nullptr); + setupVariables(data); + } + catch (nlohmann::json::exception& e) + { + LogMsg(Logger::Critical, "Error parsing JSON file"); + return false; + } + catch (std::out_of_range& e) + { + LogMsg(Logger::Critical, "Error parsing JSON file"); + return false; + } + return true; + } + + bool setupVariables(const nlohmann::json& config) + { + for (const auto& item : config.items()) + { + if (item.key() == "MountPoints") + { + for (const auto& mountpoint : item.value().items()) + { + MountPoint mp; + const auto nbdDeviceIter = + mountpoint.value().find("NBDDevice"); + if (nbdDeviceIter != mountpoint.value().cend()) + { + const std::string* value = + nbdDeviceIter->get_ptr(); + if (value) + { + mp.nbdDevice = NBDDevice(value->c_str()); + if (!mp.nbdDevice) + { + LogMsg(Logger::Error, + "NBDDevice unrecognized."); + continue; + } + } + else + { + LogMsg(Logger::Error, + "NBDDevice required, not set"); + continue; + } + }; + const auto unixSocketIter = + mountpoint.value().find("UnixSocket"); + if (unixSocketIter != mountpoint.value().cend()) + { + const std::string* value = + unixSocketIter->get_ptr(); + if (value) + { + mp.unixSocket = *value; + } + else + { + LogMsg(Logger::Error, + "UnixSocket required, not set"); + continue; + } + } + const auto endPointIdIter = + mountpoint.value().find("EndpointId"); + if (endPointIdIter != mountpoint.value().cend()) + { + const std::string* value = + endPointIdIter->get_ptr(); + if (value) + { + mp.endPointId = *value; + } + else + { + LogMsg(Logger::Info, + "EndpointId required, not set"); + continue; + } + } + const auto timeoutIter = mountpoint.value().find("Timeout"); + if (timeoutIter != mountpoint.value().cend()) + { + const uint64_t* value = + timeoutIter->get_ptr(); + if (value) + { + mp.timeout = *value; + } + else + { + LogMsg(Logger::Info, + "Timeout not set, use default"); + } + } + const auto blocksizeIter = + mountpoint.value().find("BlockSize"); + if (blocksizeIter != mountpoint.value().cend()) + { + const uint64_t* value = + blocksizeIter->get_ptr(); + if (value) + { + mp.blocksize = *value; + } + else + { + LogMsg(Logger::Info, + "BlockSize not set, use default"); + } + } + const auto modeIter = mountpoint.value().find("Mode"); + if (modeIter != mountpoint.value().cend()) + { + const uint64_t* value = + modeIter->get_ptr(); + if (value) + { + if (*value == 0) + { + mp.mode = Configuration::Mode::proxy; + } + else if (*value == 1) + { + mp.mode = Configuration::Mode::legacy; + } + else + { + LogMsg(Logger::Error, + "Incorrect Mode, skip this mount point"); + continue; + } + } + else + { + LogMsg(Logger::Error, + "Mode not set, skip this mount point"); + continue; + } + } + else + { + LogMsg(Logger::Error, + "Mode does not exist, skip this mount point"); + continue; + } + mountPoints[mountpoint.key()] = std::move(mp); + } + } + } + return true; + } +}; diff --git a/virtual-media/src/main.cpp b/virtual-media/src/main.cpp index 666c3a6..792cdf2 100644 --- a/virtual-media/src/main.cpp +++ b/virtual-media/src/main.cpp @@ -1,3 +1,4 @@ +#include "configuration.hpp" #include "logger.hpp" #include "system.hpp" @@ -20,8 +21,10 @@ class App { public: - App(boost::asio::io_context& ioc, sd_bus* custom_bus = nullptr) : - ioc(ioc), devMonitor(ioc) + App(boost::asio::io_context& ioc, const Configuration& config, + sd_bus* custom_bus = nullptr) : + ioc(ioc), + devMonitor(ioc), config(config) { if (!custom_bus) { @@ -48,10 +51,15 @@ class App std::shared_ptr objServer; std::shared_ptr objManager; DeviceMonitor devMonitor; + const Configuration& config; }; int main() { + Configuration config("/etc/virtual-media.json"); + if (!config.valid) + return -1; + boost::asio::io_context ioc; boost::asio::signal_set signals(ioc, SIGINT, SIGTERM); signals.async_wait( @@ -66,7 +74,7 @@ int main() sd_bus_start(b); #endif sd_bus_default_system(&b); - App app(ioc, b); + App app(ioc, config, b); ioc.run(); -- cgit v1.2.3