diff options
author | Czarnowski, Przemyslaw <przemyslaw.hawrylewicz.czarnowski@intel.com> | 2019-12-20 16:06:30 +0300 |
---|---|---|
committer | Czarnowski, Przemyslaw <przemyslaw.hawrylewicz.czarnowski@intel.com> | 2020-01-17 11:51:09 +0300 |
commit | 391c5dedbb1caa1069e07fcf58344c73de391a0d (patch) | |
tree | c2d7194a5a9074fe9e4ea3c410b29cb5d4892876 | |
parent | a1a6e0c1c0b4be4c5bea0e3233be8bb11e60a079 (diff) | |
download | provingground-391c5dedbb1caa1069e07fcf58344c73de391a0d.tar.xz |
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 <pawel.rapkiewicz@intel.com>
Signed-off-by: Czarnowski, Przemyslaw <przemyslaw.hawrylewicz.czarnowski@intel.com>
-rw-r--r-- | virtual-media/src/configuration.hpp | 233 | ||||
-rw-r--r-- | virtual-media/src/main.cpp | 14 |
2 files changed, 244 insertions, 3 deletions
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 <algorithm> +#include <boost/container/flat_map.hpp> +#include <iostream> +#include <nlohmann/json.hpp> +#include <optional> +#include <string> +#include <vector> + +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<int> timeout; + std::optional<int> blocksize; + Mode mode; + + static std::vector<std::string> toArgs(const MountPoint& mp) + { + std::vector<std::string> 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<std::string, MountPoint> 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<const std::string*>(); + 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<const std::string*>(); + 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<const std::string*>(); + 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<const uint64_t*>(); + 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<const uint64_t*>(); + 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<const uint64_t*>(); + 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<sdbusplus::asio::object_server> objServer; std::shared_ptr<sdbusplus::server::manager::manager> 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(); |