From 6d93fe942fe3df101a644ffa39e1e4feab4382e7 Mon Sep 17 00:00:00 2001 From: "Czarnowski, Przemyslaw" Date: Fri, 20 Dec 2019 13:05:42 +0100 Subject: Entry commit for new VM code Introducing Virtual Media based on State Machine. - Logging class added - Stub for Main application Change-Id: I05ef576c170e2f9acf90800708f4447452f4050f Signed-off-by: Rapkiewicz, Pawel Signed-off-by: Czarnowski, Przemyslaw --- virtual-media/src/logger.hpp | 95 ++++ virtual-media/src/main.cpp | 1032 +----------------------------------------- 2 files changed, 101 insertions(+), 1026 deletions(-) create mode 100644 virtual-media/src/logger.hpp diff --git a/virtual-media/src/logger.hpp b/virtual-media/src/logger.hpp new file mode 100644 index 0000000..1950019 --- /dev/null +++ b/virtual-media/src/logger.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include +#include + +#define LOG_LEVEL Debug + +namespace Logger +{ + +struct Struct +{ + constexpr static const int32_t value = 6; + constexpr static const char* name = "Struct "; +}; + +struct Debug +{ + constexpr static const int32_t value = 5; + constexpr static const char* name = "Debug "; +}; + +struct Info +{ + constexpr static const int32_t value = 4; + constexpr static const char* name = "Info "; +}; + +struct Warning +{ + constexpr static const int32_t value = 3; + constexpr static const char* name = "Warning "; +}; + +struct Error +{ + constexpr static const int32_t value = 2; + constexpr static const char* name = "Error "; +}; + +struct Critical +{ + constexpr static const int32_t value = 1; + constexpr static const char* name = "Critical"; +}; + +template +constexpr const char* baseNameImpl(const char (&str)[Len], std::size_t pos) +{ + return pos == 0 ? str + : (str[pos] == '/' || str[pos] == '\\') + ? str + pos + 1 + : baseNameImpl(str, --pos); +} + +template +constexpr const char* baseName(const char (&str)[Len]) +{ + return baseNameImpl(str, Len - 1); +} + +template +std::ostream& operator<<(std::ostream& os, const std::vector& v) +{ + for (const auto& i : v) + { + os << i << " "; + } + return os; +} + +template +constexpr void logImpl(const char* file, int32_t line, const char* fname, + Args&&... args) +{ + if constexpr (LogLevel::value <= DefinedLogLevel::value) + { + std::cout << "[" << LogLevel::name << "] [" << file << ":" << line + << "] " << fname << "(): "; + (std::cout << ... << args) << std::endl; + } +} + +template +constexpr void log(const char* file, int32_t line, const char* fname, + Args&&... args) +{ + logImpl(file, line, fname, args...); +} + +#define LogMsg(level, ...) \ + Logger::log(Logger::baseName(__FILE__), __LINE__, __FUNCTION__, \ + __VA_ARGS__) + +} // namespace Logger diff --git a/virtual-media/src/main.cpp b/virtual-media/src/main.cpp index 6d5ffb6..7caae14 100644 --- a/virtual-media/src/main.cpp +++ b/virtual-media/src/main.cpp @@ -1,3 +1,5 @@ +#include "logger.hpp" + #include #include @@ -14,572 +16,10 @@ #include #include -namespace fs = std::filesystem; - -namespace udev -{ -#include -struct udev; -struct udev_monitor; -struct udev_device; - -struct udevDeleter -{ - void operator()(udev* desc) const - { - udev_unref(desc); - } -}; - -struct monitorDeleter -{ - void operator()(udev_monitor* desc) const - { - udev_monitor_unref(desc); - }; -}; - -struct deviceDeleter -{ - void operator()(udev_device* desc) const - { - udev_device_unref(desc); - }; -}; -} // namespace udev - -enum class StateChange -{ - notmonitored, - unknown, - removed, - inserted -}; - -class DeviceMonitor -{ - public: - DeviceMonitor(boost::asio::io_context& ioc) : ioc(ioc), monitorSd(ioc) - { - udev = std::unique_ptr(udev::udev_new()); - if (!udev) - { - throw std::system_error(EFAULT, std::generic_category(), - "Unable to create uDev handler."); - } - - monitor = std::unique_ptr( - udev::udev_monitor_new_from_netlink(udev.get(), "kernel")); - - if (!monitor) - { - throw std::system_error(EFAULT, std::generic_category(), - "Unable to create uDev Monitor handler."); - } - int rc = udev_monitor_filter_add_match_subsystem_devtype( - monitor.get(), "block", "disk"); - - if (rc) - { - throw std::system_error(EFAULT, std::generic_category(), - "Could not apply filters."); - } - rc = udev_monitor_enable_receiving(monitor.get()); - if (rc) - { - throw std::system_error(EFAULT, std::generic_category(), - "Enable receiving failed."); - } - monitorSd.assign(udev_monitor_get_fd(monitor.get())); - } - - DeviceMonitor(const DeviceMonitor&) = delete; - DeviceMonitor(DeviceMonitor&&) = delete; - - DeviceMonitor& operator=(const DeviceMonitor&) = delete; - DeviceMonitor& operator=(DeviceMonitor&&) = delete; - - template - void run(DeviceChangeStateCb callback) - { - boost::asio::spawn(ioc, [this, - callback](boost::asio::yield_context yield) { - boost::system::error_code ec; - while (1) - { - monitorSd.async_wait( - boost::asio::posix::stream_descriptor::wait_read, - yield[ec]); - - std::unique_ptr device = - std::unique_ptr( - udev::udev_monitor_receive_device(monitor.get())); - if (device) - { - const char* devAction = - udev_device_get_action(device.get()); - if (devAction == nullptr) - { - std::cerr << "Received NULL action.\n"; - continue; - } - if (strcmp(devAction, "change") == 0) - { - const char* sysname = - udev_device_get_sysname(device.get()); - if (sysname == nullptr) - { - std::cerr << "Received NULL sysname.\n"; - continue; - } - auto monitoredDevice = devices.find(sysname); - if (monitoredDevice != devices.cend()) - { - const char* size_str = - udev_device_get_sysattr_value(device.get(), - "size"); - if (size_str == nullptr) - { - std::cerr << "Received NULL size.\n"; - continue; - } - uint64_t size = 0; - try - { - size = std::stoul(size_str, 0, 0); - } - catch (const std::exception& e) - { - std::cerr - << "Could not convert size to integer.\n"; - continue; - } - if (size > 0 && monitoredDevice->second != - StateChange::inserted) - { - std::cout << sysname << " inserted.\n"; - monitoredDevice->second = StateChange::inserted; - callback(sysname, StateChange::inserted); - } - else if (size == 0 && monitoredDevice->second != - StateChange::removed) - { - std::cout << sysname << " removed.\n"; - monitoredDevice->second = StateChange::removed; - callback(sysname, StateChange::removed); - } - }; - } - } - } - }); - } - - void addDevice(const std::string& device) - { - std::cout << "Watch on /dev/" << device << '\n'; - devices.insert( - std::pair(device, StateChange::unknown)); - } - - StateChange getState(const std::string& device) - { - auto monitoredDevice = devices.find(device); - if (monitoredDevice != devices.cend()) - { - return monitoredDevice->second; - } - return StateChange::notmonitored; - } - - private: - boost::asio::io_context& ioc; - boost::asio::posix::stream_descriptor monitorSd; - - std::unique_ptr udev; - std::unique_ptr monitor; - - boost::container::flat_map devices; -}; - -class Process : public std::enable_shared_from_this -{ - public: - Process(boost::asio::io_context& ioc, const std::string& name) : - ioc(ioc), pipe(ioc), name(name) - { - } - - template - bool spawn(const std::vector& args, ExitCb&& onExit) - { - std::error_code ec; - child = boost::process::child( - "/usr/sbin/nbd-client", - //"/sbin/nbd-client", "-N", "otherexport", "127.0.0.1", "/dev/nbd0", - //"-n", - boost::process::args(args), - boost::process::on_exit( - [name(this->name), onExit{std::move(onExit)}]( - int exit, const std::error_code& ecIn) { - std::cout << "- child " << name << "(" << exit << " " - << ecIn << ")\n"; - auto process = processList.find(name); - if (process != processList.end() && process->second) - { - std::cout << "Removing process from processList\n"; - process->second.reset(); - } - onExit(name); - }), - (boost::process::std_out & boost::process::std_err) > pipe, ec, - ioc); - - if (ec) - { - std::cerr << "Error while creating child process: " << ec << '\n'; - return false; - } - - boost::asio::spawn(ioc, [this, self = shared_from_this()]( - boost::asio::yield_context yield) { - boost::system::error_code bec; - std::string line; - boost::asio::dynamic_string_buffer buffer{line}; - std::cout << "Entering COUT Loop\n"; - while (1) - { - auto x = boost::asio::async_read_until(pipe, std::move(buffer), - '\n', yield[bec]); - std::cout << "-[" << name << "]-> " << line; - buffer.consume(x); - if (bec) - { - std::cerr << "Loop Error: " << bec << '\n'; - break; - } - } - std::cout << "Exiting from COUT Loop\n"; - }); - return true; - } - - void terminate(int signal = SIGTERM) - { - int rc = kill(child.id(), SIGTERM); - if (rc) - { - return; - } - child.wait(); - } - - static void addProcess(const std::string& name) - { - processList[name] = nullptr; - } - - template - static bool spawn(boost::asio::io_context& ioc, const std::string& name, - const std::vector& args, ExitCb&& onExit) - { - auto process = processList.find(name); - if (process != processList.end() && !process->second) - { - std::cout << "Spawning process for " << name << '\n'; - - auto newProcess = std::make_shared(ioc, name); - if (newProcess->spawn(args, onExit)) - { - process->second = newProcess; - return true; - } - std::cout << "Process (" << name << ") exited immediately.\n"; - return false; - } - std::cout << "No process (" << name << ") to be spawned.\n"; - return false; - } - - static bool terminate(const std::string& name, int signal = SIGTERM) - { - auto process = processList.find(name); - if (process != processList.end() && process->second) - { - std::cout << "Terminating " << name << '\n'; - process->second->terminate(signal); - return true; - } - std::cout << "No process (" << name << ") for termination.\n"; - return false; - } - - static bool isActive(const std::string& name) - { - auto process = processList.find(name); - if (process != processList.end()) - { - if (process->second) - { - return true; - } - } - return false; - } - - private: - boost::asio::io_context& ioc; - boost::process::child child; - boost::process::async_pipe pipe; - std::string name; - inline static boost::container::flat_map> - processList; -}; - -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 - { - std::string 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 = { - "-N", "otherexport", "-u", - mp.unixSocket, "/dev/" + mp.nbdDevice, "-n"}; - return args; - } - }; - - 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()) - { - std::cout << "Could not open configuration file\n"; - return false; - } - try - { - auto data = nlohmann::json::parse(configFile, nullptr); - setupVariables(data); - } - catch (nlohmann::json::exception& e) - { - std::cerr << "Error parsing JSON file\n"; - return false; - } - catch (std::out_of_range& e) - { - std::cerr << "Error parsing JSON file\n"; - 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 = *value; - } - else - { - std::cerr << "NBDDevice required, not set\n"; - 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 - { - std::cerr << "UnixSocket required, not set\n"; - 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 - { - std::cerr << "EndpointId required, not set\n"; - 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 - { - std::cout << "Timeout not set, use default\n"; - } - } - 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 - { - std::cout << "BlockSize not set, use default\n"; - } - } - 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 - { - std::cerr << "Incorrect Mode, skip this mount " - "point\n"; - continue; - } - } - else - { - std::cerr - << "Mode not set, skip this mount point\n"; - continue; - } - } - else - { - std::cerr - << "Mode does not exist, skip this mount point\n"; - continue; - } - mountPoints[mountpoint.key()] = std::move(mp); - } - } - } - return true; - } -}; - -class ParametersManager -{ - public: - struct Parameters - { - // Legacy mode specific parameters - std::string imageUrl; - std::string mountDirectoryPath; - }; - - ParametersManager() - { - } - - void addMountPoint(const std::string& name) - { - Parameters parameters; - parameters.imageUrl.clear(); - parameters.mountDirectoryPath.clear(); - mountPoints[name] = std::move(parameters); - } - - Parameters* getMountPoint(const std::string& name) - { - if (mountPoints.find(name) != mountPoints.end()) - { - return &mountPoints[name]; - } - else - { - return nullptr; - } - } - - private: - boost::container::flat_map mountPoints; -}; - class App { public: - App(boost::asio::io_context& ioc, const Configuration& config, - sd_bus* custom_bus = nullptr) : - ioc(ioc), - devMonitor(ioc), config(config), paramMgr() + App(boost::asio::io_context& ioc, sd_bus* custom_bus = nullptr) : ioc(ioc) { if (!custom_bus) { @@ -594,478 +34,17 @@ class App bus->request_name("xyz.openbmc_project.VirtualMedia"); objManager = std::make_shared( *bus, "/xyz/openbmc_project/VirtualMedia"); - for (const auto& entry : config.mountPoints) - { - if (entry.second.mode == Configuration::Mode::Proxy) - { - devMonitor.addDevice(entry.second.nbdDevice); - Process::addProcess(entry.first); - } - - addMountPointInterface(entry.first, entry.second); - - if (entry.second.mode == Configuration::Mode::Proxy) - { - addProxyInterface(entry.first, entry.second); - addProcessInterface(entry.first); - } - else - { - addLegacyInterface(entry.first); - } - - paramMgr.addMountPoint(entry.first); - } - devMonitor.run([this](const std::string& device, StateChange change) { - configureUsbGadget(device, change); - }); - }; - - private: - bool echoToFile(const fs::path& fname, const std::string& content) - { - std::ofstream fileWriter; - fileWriter.exceptions(std::ofstream::failbit | std::ofstream::badbit); - fileWriter.open(fname, std::ios::out | std::ios::app); - fileWriter << content << std::endl; // Make sure for new line and flush - fileWriter.close(); - return true; - } - - int configureUsbGadget(const std::string& device, StateChange change, - const std::string& lunFile = "") - { - int result = 0; - std::error_code ec; - if (change == StateChange::unknown) - { - std::cerr << "Change to unknown state is not possible\n"; - return -1; - } - - // If lun file provided just use it to inject to the lun.0/file - // instead of /dev/ - std::string lunFileInternal; - if (lunFile.empty()) - { - lunFileInternal = "/dev/" + device; - } - else - { - lunFileInternal = lunFile; - } - - const fs::path gadgetDir = - "/sys/kernel/config/usb_gadget/mass-storage-" + device; - const fs::path funcMassStorageDir = - gadgetDir / "functions/mass_storage.usb0"; - const fs::path stringsDir = gadgetDir / "strings/0x409"; - const fs::path configDir = gadgetDir / "configs/c.1"; - const fs::path massStorageDir = configDir / "mass_storage.usb0"; - const fs::path configStringsDir = configDir / "strings/0x409"; - - if (change == StateChange::inserted) - { - try - { - fs::create_directories(gadgetDir); - echoToFile(gadgetDir / "idVendor", "0x1d6b"); - echoToFile(gadgetDir / "idProduct", "0x0104"); - fs::create_directories(stringsDir); - echoToFile(stringsDir / "manufacturer", "OpenBMC"); - echoToFile(stringsDir / "product", "Virtual Media Device"); - fs::create_directories(configStringsDir); - echoToFile(configStringsDir / "configuration", "config 1"); - fs::create_directories(funcMassStorageDir); - fs::create_directories(funcMassStorageDir / "lun.0"); - fs::create_directory_symlink(funcMassStorageDir, - massStorageDir); - echoToFile(funcMassStorageDir / "lun.0/removable", "1"); - echoToFile(funcMassStorageDir / "lun.0/ro", "1"); - echoToFile(funcMassStorageDir / "lun.0/cdrom", "0"); - echoToFile(funcMassStorageDir / "lun.0/file", lunFileInternal); - - for (const auto& port : fs::directory_iterator( - "/sys/bus/platform/devices/1e6a0000.usb-vhub")) - { - if (fs::is_directory(port) && !fs::is_symlink(port) && - !fs::exists(port.path() / "gadget/suspended")) - { - const std::string portId = port.path().filename(); - std::cout << "Use port : " << port.path().filename() - << '\n'; - echoToFile(gadgetDir / "UDC", portId); - return 0; - } - } - } - catch (fs::filesystem_error& e) - { - // Got error perform cleanup - std::cerr << e.what() << '\n'; - result = -1; - } - catch (std::ofstream::failure& e) - { - // Got error perform cleanup - std::cerr << e.what() << '\n'; - result = -1; - } - } - // StateChange: unknown, notmonitored, inserted were handler - // earlier. We'll get here only for removed, or cleanup - - fs::remove_all(massStorageDir, ec); - if (ec) - { - std::cerr << ec.message() << '\n'; - } - fs::remove_all(funcMassStorageDir, ec); - if (ec) - { - std::cerr << ec.message() << '\n'; - } - fs::remove_all(configStringsDir, ec); - if (ec) - { - std::cerr << ec.message() << '\n'; - } - fs::remove_all(configDir, ec); - if (ec) - { - std::cerr << ec.message() << '\n'; - } - fs::remove_all(stringsDir, ec); - if (ec) - { - std::cerr << ec.message() << '\n'; - } - fs::remove_all(gadgetDir, ec); - if (ec) - { - std::cerr << ec.message() << '\n'; - result = -1; - } - - return result; - } - - void addMountPointInterface(const std::string& name, - const Configuration::MountPoint& mp) - { - std::string objPath; - if (mp.mode == Configuration::Mode::Proxy) - { - objPath = "/xyz/openbmc_project/VirtualMedia/Proxy/"; - } - else - { - objPath = "/xyz/openbmc_project/VirtualMedia/Legacy/"; - } - - auto iface = objServer->add_interface( - objPath + name, "xyz.openbmc_project.VirtualMedia.MountPoint"); - iface->register_property("Device", mp.nbdDevice); - iface->register_property("EndpointId", mp.endPointId); - iface->register_property("Socket", mp.unixSocket); - iface->register_property("Timeout", *mp.timeout); - iface->register_property("BlockSize", *mp.blocksize); - iface->register_property( - "ImageUrl", std::string(""), - [](const std::string& req, std::string& property) { - throw sdbusplus::exception::SdBusError( - EPERM, "Setting ImageUrl property is not allowed"); - return -1; - }, - [this, name](const std::string& property) { - auto parameters = paramMgr.getMountPoint(name); - if (parameters == nullptr) - { - return std::string(""); - } - else - { - return parameters->imageUrl; - } - }); - iface->initialize(); - }; - - void addProxyInterface(const std::string& name, - const Configuration::MountPoint& mp) - { - auto iface = objServer->add_interface( - "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, - "xyz.openbmc_project.VirtualMedia.Proxy"); - iface->register_method( - "Mount", [&, name, args(Configuration::MountPoint::toArgs(mp))]() { - return Process::spawn( - ioc, name, args, [this](const std::string& name) { - configureUsbGadget(name, StateChange::removed); - }); - }); - iface->register_method("Unmount", [this, name]() { - const auto mp = config.mountPoints.find(name); - std::string nbdDevice = mp->second.nbdDevice; - configureUsbGadget(nbdDevice, StateChange::removed); - return Process::terminate(name); - }); - iface->initialize(); - } - - int prepareTempDirForLegacyMode(std::string& path) - { - int result = -1; - char mountPathTemplate[] = "/tmp/vm_legacy.XXXXXX"; - const char* tmpPath = mkdtemp(mountPathTemplate); - if (tmpPath != nullptr) - { - path = tmpPath; - result = 0; - } - - return result; - } - - bool checkUrl(const std::string& urlScheme, const std::string& imageUrl) - { - if (urlScheme.compare(imageUrl.substr(0, urlScheme.size())) == 0) - { - return true; - } - else - { - return false; - } - } - - bool getImagePathFromUrl(const std::string& urlScheme, - const std::string& imageUrl, - std::string* imagePath) - { - if (checkUrl(urlScheme, imageUrl)) - { - if (imagePath != nullptr) - { - *imagePath = imageUrl.substr(urlScheme.size() - 1); - return true; - } - else - { - std::cerr << "Invalid parameter provied\n"; - return false; - } - } - else - { - std::cerr << "Provied url does not match scheme\n"; - return false; - } - } - - bool checkHttpsUrl(const std::string& imageUrl) - { - return checkUrl("https://", imageUrl); - } - - bool getImagePathFromHttpsUrl(const std::string& imageUrl, - std::string* imagePath) - { - return getImagePathFromUrl("https://", imageUrl, imagePath); - } - - bool checkCifsUrl(const std::string& imageUrl) - { - return checkUrl("smb://", imageUrl); - } - - bool getImagePathFromCifsUrl(const std::string& imageUrl, - std::string* imagePath) - { - return getImagePathFromUrl("smb://", imageUrl, imagePath); - } - - fs::path getImagePath(const std::string& imageUrl) - { - std::string imagePath; - - if (getImagePathFromHttpsUrl(imageUrl, &imagePath)) - { - return fs::path(imagePath); - } - else if (getImagePathFromCifsUrl(imageUrl, &imagePath)) - { - return fs::path(imagePath); - } - else - { - std::cerr << "Unrecognized url's scheme encountered\n"; - return fs::path(""); - } - } - - int mountCifsUrlForLegcyMode(const std::string& name, - const std::string& imageUrl, - ParametersManager::Parameters* parameters) - { - int result = -1; - fs::path imageUrlPath = getImagePath(imageUrl); - const std::string imageUrlParentPath = - "/" + imageUrlPath.parent_path().string(); - std::string mountDirectoryPath; - result = prepareTempDirForLegacyMode(mountDirectoryPath); - if (result != 0) - { - std::cerr << "Failed to create tmp directory\n"; - return result; - } - - result = mount(imageUrlParentPath.c_str(), mountDirectoryPath.c_str(), - "cifs", 0, - "username=,password=,nolock,sec=" - "ntlmsspi,seal,vers=3.0"); - if (result != 0) - { - std::cerr << "Failed to mount the url\n"; - fs::remove_all(fs::path(mountDirectoryPath)); - return result; - } - - const std::string imageMountPath = - mountDirectoryPath + "/" + imageUrlPath.filename().string(); - result = - configureUsbGadget(name, StateChange::inserted, imageMountPath); - if (result != 0) - { - std::cerr << "Failed to run usb gadget\n"; - umount(mountDirectoryPath.c_str()); - fs::remove_all(fs::path(mountDirectoryPath)); - return result; - } - - parameters->mountDirectoryPath = mountDirectoryPath; - - return result; - } - - int umountCifsUrlForLegcyMode(const std::string& name, - ParametersManager::Parameters* parameters) - { - int result = -1; - - result = configureUsbGadget(name, StateChange::removed); - if (result != 0) - { - std::cerr << "Failed to unmount resource\n"; - return result; - } - - umount(parameters->mountDirectoryPath.c_str()); - fs::remove_all(fs::path(parameters->mountDirectoryPath)); - parameters->mountDirectoryPath.clear(); - - return result; - } - - void addLegacyInterface(const std::string& name) - { - auto iface = objServer->add_interface( - "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, - "xyz.openbmc_project.VirtualMedia.Legacy"); - iface->register_method( - "Mount", [this, name](const std::string& imageUrl) { - auto parameters = paramMgr.getMountPoint(name); - if (parameters == nullptr) - { - throw sdbusplus::exception::SdBusError( - ENOENT, "Failed to find the node."); - } - - if (!parameters->imageUrl.empty()) - { - throw sdbusplus::exception::SdBusError( - ETXTBSY, "Node already used and resource mounted."); - } - - if (checkCifsUrl(imageUrl)) - { - int result = - mountCifsUrlForLegcyMode(name, imageUrl, parameters); - if (result != 0) - { - throw sdbusplus::exception::SdBusError( - -result, "Failed to mount cifs url."); - } - } - else - { - throw sdbusplus::exception::SdBusError( - EINVAL, "Not supported url's scheme."); - } - - parameters->imageUrl = imageUrl; - }); - iface->register_method("Unmount", [this, name]() { - auto parameters = paramMgr.getMountPoint(name); - if (parameters == nullptr) - { - throw sdbusplus::exception::SdBusError( - ENOENT, "Failed to find the node."); - } - - if (parameters->imageUrl.empty()) - { - throw sdbusplus::exception::SdBusError( - ENOENT, "Node is not used and no resource mounted."); - } - - if (checkCifsUrl(parameters->imageUrl)) - { - int result = umountCifsUrlForLegcyMode(name, parameters); - if (result != 0) - { - throw sdbusplus::exception::SdBusError( - -result, "Failed to unmount cifs resource."); - } - } - else - { - throw sdbusplus::exception::SdBusError( - EINVAL, "Not supported url's scheme."); - } - - parameters->imageUrl.clear(); - }); - iface->initialize(); - } - - void addProcessInterface(const std::string& name) - { - auto iface = objServer->add_interface( - "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, - "xyz.openbmc_project.VirtualMedia.Process"); - iface->register_property( - "Active", bool(false), - [](const bool& req, bool& property) { return 0; }, - [name](const bool& property) { return Process::isActive(name); }); - iface->initialize(); } + private: boost::asio::io_context& ioc; - DeviceMonitor devMonitor; std::shared_ptr bus; std::shared_ptr objServer; std::shared_ptr objManager; - const Configuration& config; - ParametersManager paramMgr; }; 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( @@ -1079,7 +58,8 @@ int main() sd_bus_set_address(b, CUSTOM_DBUS_PATH); sd_bus_start(b); #endif - App app(ioc, config, b); + sd_bus_default_system(&b); + App app(ioc, b); ioc.run(); -- cgit v1.2.3