summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCzarnowski, Przemyslaw <przemyslaw.hawrylewicz.czarnowski@intel.com>2019-12-20 16:06:30 +0300
committerCzarnowski, Przemyslaw <przemyslaw.hawrylewicz.czarnowski@intel.com>2020-01-17 11:51:09 +0300
commit391c5dedbb1caa1069e07fcf58344c73de391a0d (patch)
treec2d7194a5a9074fe9e4ea3c410b29cb5d4892876
parenta1a6e0c1c0b4be4c5bea0e3233be8bb11e60a079 (diff)
downloadprovingground-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.hpp233
-rw-r--r--virtual-media/src/main.cpp14
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();