diff options
| author | Lei YU <mine260309@gmail.com> | 2017-02-09 11:37:26 +0800 |
|---|---|---|
| committer | Lei YU <mine260309@gmail.com> | 2017-10-15 20:15:34 +0800 |
| commit | 415b964f063f81cd8ec3d1ffc3955be51de06690 (patch) | |
| tree | 581108a6e5501488572f32a3645cc6ac6092b9e3 | |
| parent | af5abc5785535f4e059a35be60dbbd012c61facf (diff) | |
| download | phosphor-time-manager-415b964f063f81cd8ec3d1ffc3955be51de06690.tar.gz phosphor-time-manager-415b964f063f81cd8ec3d1ffc3955be51de06690.zip | |
Add time Manager to handle property changes callback
1. Implement time::Manager who registers property change signal for time
mode and owner;
2. Add PropertyChangeListner interface to handle the callback;
3. Make EpochBase to implement the interface.
Change-Id: I185580ae37353e1ed82a47e4905fb22e269ac09d
Signed-off-by: Lei YU <mine260309@gmail.com>
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rw-r--r-- | epoch_base.cpp | 88 | ||||
| -rw-r--r-- | epoch_base.hpp | 107 | ||||
| -rw-r--r-- | main.cpp | 10 | ||||
| -rw-r--r-- | manager.cpp | 179 | ||||
| -rw-r--r-- | manager.hpp | 135 | ||||
| -rw-r--r-- | property_change_listener.hpp | 23 | ||||
| -rw-r--r-- | test/Makefile.am | 3 | ||||
| -rw-r--r-- | test/TestBmcEpoch.cpp | 4 | ||||
| -rw-r--r-- | test/TestEpochBase.cpp | 46 | ||||
| -rw-r--r-- | test/TestHostEpoch.cpp | 4 | ||||
| -rw-r--r-- | test/TestManager.cpp | 76 | ||||
| -rw-r--r-- | types.hpp | 49 |
13 files changed, 516 insertions, 211 deletions
diff --git a/Makefile.am b/Makefile.am index 0af260f..066dd33 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,8 @@ noinst_LTLIBRARIES = libtimemanager.la libtimemanager_la_SOURCES = \ epoch_base.cpp \ bmc_epoch.cpp \ - host_epoch.cpp + host_epoch.cpp \ + manager.cpp phosphor_timemanager_SOURCES = \ main.cpp diff --git a/epoch_base.cpp b/epoch_base.cpp index 06232bb..07b3113 100644 --- a/epoch_base.cpp +++ b/epoch_base.cpp @@ -5,15 +5,6 @@ #include <iomanip> #include <sstream> -namespace // anonymous -{ -constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host"; -constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0"; -constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host"; -constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"; -constexpr auto METHOD_GET = "Get"; -} - namespace phosphor { namespace time @@ -21,90 +12,21 @@ namespace time using namespace phosphor::logging; -const std::map<std::string, EpochBase::Owner> -EpochBase::ownerMap = { - { "BMC", EpochBase::Owner::BMC }, - { "HOST", EpochBase::Owner::HOST }, - { "SPLIT", EpochBase::Owner::SPLIT }, - { "BOTH", EpochBase::Owner::BOTH }, -}; - EpochBase::EpochBase(sdbusplus::bus::bus& bus, const char* objPath) - : sdbusplus::server::object::object<EpochTime>(bus, objPath, true), + : sdbusplus::server::object::object<EpochTime>(bus, objPath), bus(bus) { - initialize(); - // Deferred this until we could get our property correct - emit_object_added(); -} - -void EpochBase::setCurrentTimeMode(const std::string& mode) -{ - log<level::INFO>("Time mode is changed", - entry("MODE=%s", mode.c_str())); - timeMode = convertToMode(mode); -} - -void EpochBase::setCurrentTimeOwner(const std::string& owner) -{ - log<level::INFO>("Time owner is changed", - entry("OWNER=%s", owner.c_str())); - timeOwner = convertToOwner(owner); -} - -void EpochBase::initialize() -{ - setCurrentTimeMode(getSettings("time_mode")); - setCurrentTimeOwner(getSettings("time_owner")); - // TODO: subscribe settingsd's property changes callback -} - -std::string EpochBase::getSettings(const char* value) const -{ - sdbusplus::message::variant<std::string> mode; - auto method = bus.new_method_call(SETTINGS_SERVICE, - SETTINGS_PATH, - PROPERTY_INTERFACE, - METHOD_GET); - method.append(SETTINGS_INTERFACE, value); - auto reply = bus.call(method); - if (reply) - { - reply.read(mode); - } - - return mode.get<std::string>(); } -EpochBase::Mode EpochBase::convertToMode(const std::string& mode) +void EpochBase::onModeChanged(Mode mode) { - if (mode == "NTP") - { - return Mode::NTP; - } - else if (mode == "MANUAL") - { - return Mode::MANUAL; - } - else - { - log<level::ERR>("Unrecognized mode", - entry("%s", mode.c_str())); - return Mode::NTP; - } + timeMode = mode; } -EpochBase::Owner EpochBase::convertToOwner(const std::string& owner) +void EpochBase::onOwnerChanged(Owner owner) { - auto it = ownerMap.find(owner); - if (it == ownerMap.end()) - { - log<level::ERR>("Unrecognized owner", - entry("%s", owner.c_str())); - return Owner::BMC; - } - return it->second; + timeOwner = owner; } using namespace std::chrono; diff --git a/epoch_base.hpp b/epoch_base.hpp index fc505d0..f31a32b 100644 --- a/epoch_base.hpp +++ b/epoch_base.hpp @@ -1,5 +1,7 @@ #pragma once +#include "property_change_listener.hpp" + #include <sdbusplus/bus.hpp> #include <xyz/openbmc_project/Time/EpochTime/server.hpp> @@ -16,64 +18,30 @@ namespace time * DBus API for epoch time. */ class EpochBase : public sdbusplus::server::object::object < - sdbusplus::xyz::openbmc_project::Time::server::EpochTime > + sdbusplus::xyz::openbmc_project::Time::server::EpochTime >, + public PropertyChangeListner { public: friend class TestEpochBase; - /** @brief Supported time modes - * NTP Time sourced by Network Time Server - * MANUAL User of the system need to set the time - */ - enum class Mode - { - NTP, - MANUAL, - }; - - /** @brief Supported time owners - * BMC Time source may be NTP or MANUAL but it has to be set natively - * on the BMC. Meaning, host can not set the time. What it also - * means is that when BMC gets IPMI_SET_SEL_TIME, then its ignored. - * similarly, when BMC gets IPMI_GET_SEL_TIME, then the BMC's time - * is returned. - * - * HOST Its only IPMI_SEL_SEL_TIME that will set the time on BMC. - * Meaning, IPMI_GET_SEL_TIME and request to get BMC time will - * result in same value. - * - * SPLIT Both BMC and HOST will maintain their individual clocks but then - * the time information is stored in BMC. BMC can have either NTP - * or MANUAL as it's source of time and will set the time directly - * on the BMC. When IPMI_SET_SEL_TIME is received, then the delta - * between that and BMC's time is calculated and is stored. - * When BMC reads the time, the current time is returned. - * When IPMI_GET_SEL_TIME is received, BMC's time is retrieved and - * then the delta offset is factored in prior to returning. - * - * BOTH: BMC's time is set with whoever that sets the time. Similarly, - * BMC's time is returned to whoever that asks the time. - */ - enum class Owner - { - BMC, - HOST, - SPLIT, - BOTH, - }; - EpochBase(sdbusplus::bus::bus& bus, const char* objPath); + /** @brief Notified on time mode changed */ + void onModeChanged(Mode mode) override; + + /** @brief Notified on time owner changed */ + void onOwnerChanged(Owner owner) override; + protected: /** @brief Persistent sdbusplus DBus connection */ sdbusplus::bus::bus& bus; /** @brief The current time mode */ - Mode timeMode; + Mode timeMode = Mode::NTP; /** @brief The current time owner */ - Owner timeOwner; + Owner timeOwner = Owner::BMC; /** @brief Set current time to system * @@ -89,57 +57,6 @@ class EpochBase : public sdbusplus::server::object::object < * @return Microseconds since UTC */ std::chrono::microseconds getTime() const; - - /** @brief Convert a string to enum Mode - * - * Convert the time mode string to enum. - * Valid strings are "NTP", "MANUAL" - * If it's not a valid time mode string, return NTP. - * - * @param[in] mode - The string of time mode - * - * @return The Mode enum - */ - static Mode convertToMode(const std::string& mode); - - /** @brief Convert a string to enum Owner - * - * Convert the time owner string to enum. - * Valid strings are "BMC", "HOST", "SPLIT", "BOTH" - * If it's not a valid time owner string, return BMC. - * - * @param[in] owner - The string of time owner - * - * @return The Owner enum - */ - static Owner convertToOwner(const std::string& owner); - - private: - /** @brief Initialize the time mode and owner */ - void initialize(); - - /** @brief Set current time mode - * - * @param[in] mode - The string of time mode - */ - void setCurrentTimeMode(const std::string& mode); - - /** @brief Set current time owner - * - * @param[in] owner - The string of time owner - */ - void setCurrentTimeOwner(const std::string& owner); - - /** @brief Get setting value from settings manager - * - * @param[in] setting - The string of the setting to get - * - * @return The value of the setting - */ - std::string getSettings(const char* setting) const; - - /** @brief The map maps the string key to enum Owner */ - static const std::map<std::string, Owner> ownerMap; }; } // namespace time @@ -3,13 +3,23 @@ #include "config.h" #include "bmc_epoch.hpp" #include "host_epoch.hpp" +#include "manager.hpp" int main() { auto bus = sdbusplus::bus::new_default(); + + // Add sdbusplus ObjectManager + sdbusplus::server::manager::manager bmcEpochObjManager(bus, OBJPATH_BMC); + sdbusplus::server::manager::manager hostEpochObjManager(bus, OBJPATH_HOST); + + phosphor::time::Manager manager(bus); phosphor::time::BmcEpoch bmc(bus, OBJPATH_BMC); phosphor::time::HostEpoch host(bus,OBJPATH_HOST); + manager.addListener(&bmc); + manager.addListener(&host); + bus.request_name(BUSNAME); while (true) diff --git a/manager.cpp b/manager.cpp new file mode 100644 index 0000000..c4732f4 --- /dev/null +++ b/manager.cpp @@ -0,0 +1,179 @@ +#include "manager.hpp" + +#include <phosphor-logging/log.hpp> + +namespace rules = sdbusplus::bus::match::rules; + +namespace // anonymous +{ +constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host"; +constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0"; +constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host"; +constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"; +constexpr auto METHOD_GET = "Get"; + +constexpr auto PROPERTY_TIME_MODE = "time_mode"; +constexpr auto PROPERTY_TIME_OWNER = "time_owner"; + +// TODO: Use new settings in xyz.openbmc_project +const auto MATCH_PROPERTY_CHANGE = + rules::type::signal() + + rules::member("PropertiesChanged") + + rules::path("/org/openbmc/settings/host0") + + rules::interface("org.freedesktop.DBus.Properties"); + +} + +namespace phosphor +{ +namespace time +{ + +using namespace phosphor::logging; + +const std::set<std::string> +Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER}; + +const std::map<std::string, Owner> Manager::ownerMap = +{ + { "BMC", Owner::BMC }, + { "HOST", Owner::HOST }, + { "SPLIT", Owner::SPLIT }, + { "BOTH", Owner::BOTH }, +}; + +Manager::Manager(sdbusplus::bus::bus& bus) + : bus(bus), + propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this) +{ + setCurrentTimeMode(getSettings(PROPERTY_TIME_MODE)); + setCurrentTimeOwner(getSettings(PROPERTY_TIME_OWNER)); +} + +void Manager::addListener(PropertyChangeListner* listener) +{ + // Notify listener about the initial value + listener->onModeChanged(timeMode); + listener->onOwnerChanged(timeOwner); + + listeners.insert(listener); +} + +void Manager::onPropertyChanged(const std::string& key, + const std::string& value) +{ + // TODO: Check pgood + // If it's off, notify listners; + // If it's on, hold the values and store in persistent storage. + // And when pgood turns back to off, notify the listners. + + // TODO: Check dhcp_ntp + + if (key == PROPERTY_TIME_MODE) + { + setCurrentTimeMode(value); + for (const auto& listener : listeners) + { + listener->onModeChanged(timeMode); + } + } + else if (key == PROPERTY_TIME_OWNER) + { + setCurrentTimeOwner(value); + for (const auto& listener : listeners) + { + listener->onOwnerChanged(timeOwner); + } + } +} + +int Manager::onPropertyChanged(sd_bus_message* msg, + void* userData, + sd_bus_error* retError) +{ + using properties = std::map < std::string, + sdbusplus::message::variant<int, std::string >>; + auto m = sdbusplus::message::message(msg); + // message type: sa{sv}as + std::string ignore; + properties props; + m.read(ignore, props); + for (const auto& item : props) + { + if (managedProperties.find(item.first) != managedProperties.end()) + { + static_cast<Manager*>(userData) + ->onPropertyChanged(item.first, item.second.get<std::string>()); + } + } + return 0; +} + + +void Manager::setCurrentTimeMode(const std::string& mode) +{ + log<level::INFO>("Time mode is changed", + entry("MODE=%s", mode.c_str())); + timeMode = convertToMode(mode); +} + +void Manager::setCurrentTimeOwner(const std::string& owner) +{ + log<level::INFO>("Time owner is changed", + entry("OWNER=%s", owner.c_str())); + timeOwner = convertToOwner(owner); +} + +std::string Manager::getSettings(const char* value) const +{ + sdbusplus::message::variant<std::string> mode; + auto method = bus.new_method_call(SETTINGS_SERVICE, + SETTINGS_PATH, + PROPERTY_INTERFACE, + METHOD_GET); + method.append(SETTINGS_INTERFACE, value); + auto reply = bus.call(method); + if (reply) + { + reply.read(mode); + } + else + { + log<level::ERR>("Failed to get settings"); + } + + return mode.get<std::string>(); +} + +Mode Manager::convertToMode(const std::string& mode) +{ + if (mode == "NTP") + { + return Mode::NTP; + } + else if (mode == "MANUAL") + { + return Mode::MANUAL; + } + else + { + log<level::ERR>("Unrecognized mode", + entry("%s", mode.c_str())); + return Mode::NTP; + } +} + +Owner Manager::convertToOwner(const std::string& owner) +{ + auto it = ownerMap.find(owner); + if (it == ownerMap.end()) + { + log<level::ERR>("Unrecognized owner", + entry("%s", owner.c_str())); + return Owner::BMC; + } + return it->second; +} + +} +} diff --git a/manager.hpp b/manager.hpp new file mode 100644 index 0000000..65240ac --- /dev/null +++ b/manager.hpp @@ -0,0 +1,135 @@ +#pragma once + +#include "types.hpp" +#include "property_change_listener.hpp" + +#include <sdbusplus/bus.hpp> +#include <sdbusplus/bus/match.hpp> + +#include <set> +#include <string> + +namespace phosphor +{ +namespace time +{ + +/** @class Manager + * @brief The manager to handle OpenBMC time. + * @details It registers various time related settings and properties signals + * on DBus and handle the changes. + * For certain properties it also notifies the changed events to listeners. + */ +class Manager +{ + public: + friend class TestManager; + explicit Manager(sdbusplus::bus::bus& bus); + + /** @brief Add a listener that will be called + * when property is changed + **/ + void addListener(PropertyChangeListner* listener); + + private: + /** @brief Persistent sdbusplus DBus connection */ + sdbusplus::bus::bus& bus; + + /** @brief The match of settings property change */ + sdbusplus::bus::match::match propertyChangeMatch; + + /** @brief The container to hold all the listeners */ + std::set<PropertyChangeListner*> listeners; + + /** @brief The current time mode */ + Mode timeMode; + + /** @brief The current time owner */ + Owner timeOwner; + + /** @brief Get setting from settingsd service + * + * @param[in] setting - The string of the setting + * + * @return The setting value in string + */ + std::string getSettings(const char* setting) const; + + /** @brief Set current time mode + * + * @param[in] mode - The string of time mode + */ + void setCurrentTimeMode(const std::string& mode); + + /** @brief Set current time owner + * + * @param[in] owner - The string of time owner + */ + void setCurrentTimeOwner(const std::string& owner); + + /** @brief Notified on settings property changed + * + * @param[in] key - The name of property that is changed + * @param[in] value - The value of the property + */ + void onPropertyChanged(const std::string& key, + const std::string& value); + + /** @brief The static function called on settings property changed + * + * @param[in] msg - Data associated with subscribed signal + * @param[in] userData - Pointer to this object instance + * @param[out] retError - Not used but required with signal API + */ + static int onPropertyChanged(sd_bus_message* msg, + void* userData, + sd_bus_error* retError); + + /** @brief Convert a string to enum Mode + * + * Convert the time mode string to enum. + * Valid strings are "NTP", "MANUAL" + * If it's not a valid time mode string, return NTP. + * + * @param[in] mode - The string of time mode + * + * @return The Mode enum + */ + static Mode convertToMode(const std::string& mode); + + /** @brief Convert a string to enum Owner + * + * Convert the time owner string to enum. + * Valid strings are "BMC", "HOST", "SPLIT", "BOTH" + * If it's not a valid time owner string, return BMC. + * + * @param[in] owner - The string of time owner + * + * @return The Owner enum + */ + static Owner convertToOwner(const std::string& owner); + + using Updater = std::function<void(const std::string&)>; + + /** @brief Map the property string to functions that shall + * be called when the property is changed + */ + const std::map<std::string, Updater> propertyUpdaters = + { + {"time_mode", std::bind(&Manager::setCurrentTimeMode, + this, std::placeholders::_1)}, + {"time_owner", std::bind(&Manager::setCurrentTimeOwner, + this, std::placeholders::_1)} + }; + + /** @brief The properties that manager shall notify the + * listeners when changed + */ + static const std::set<std::string> managedProperties; + + /** @brief The map that maps the string to Owners */ + static const std::map<std::string, Owner> ownerMap; +}; + +} +} diff --git a/property_change_listener.hpp b/property_change_listener.hpp new file mode 100644 index 0000000..de23f47 --- /dev/null +++ b/property_change_listener.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "types.hpp" + +namespace phosphor +{ +namespace time +{ + +class PropertyChangeListner +{ + public: + virtual ~PropertyChangeListner() {} + + /** @brief Notified on time mode is changed */ + virtual void onModeChanged(Mode mode) = 0; + + /** @brief Notified on time owner is changed */ + virtual void onOwnerChanged(Owner owner) = 0; +}; + +} +} diff --git a/test/Makefile.am b/test/Makefile.am index bdd258e..b8ea41c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -8,7 +8,8 @@ check_PROGRAMS += test test_SOURCES = \ TestEpochBase.cpp \ TestBmcEpoch.cpp \ - TestHostEpoch.cpp + TestHostEpoch.cpp \ + TestManager.cpp test_LDADD = $(top_builddir)/libtimemanager.la diff --git a/test/TestBmcEpoch.cpp b/test/TestBmcEpoch.cpp index da65b3e..2fd55a5 100644 --- a/test/TestBmcEpoch.cpp +++ b/test/TestBmcEpoch.cpp @@ -3,6 +3,7 @@ #include "bmc_epoch.hpp" #include "config.h" +#include "types.hpp" namespace phosphor { @@ -13,9 +14,6 @@ using namespace std::chrono; class TestBmcEpoch : public testing::Test { public: - using Mode = EpochBase::Mode; - using Owner = EpochBase::Owner; - sdbusplus::bus::bus bus; BmcEpoch bmcEpoch; diff --git a/test/TestEpochBase.cpp b/test/TestEpochBase.cpp index c3ca7e1..e4a2b68 100644 --- a/test/TestEpochBase.cpp +++ b/test/TestEpochBase.cpp @@ -1,6 +1,7 @@ #include <sdbusplus/bus.hpp> #include <gtest/gtest.h> +#include "types.hpp" #include "epoch_base.hpp" namespace phosphor @@ -11,9 +12,6 @@ namespace time class TestEpochBase : public testing::Test { public: - using Mode = EpochBase::Mode; - using Owner = EpochBase::Owner; - sdbusplus::bus::bus bus; EpochBase epochBase; @@ -24,40 +22,38 @@ class TestEpochBase : public testing::Test // Empty } - // Proxies for EpochBase's private members and functions - Mode convertToMode(const std::string& mode) + Mode getMode() { - return EpochBase::convertToMode(mode); + return epochBase.timeMode; } - Owner convertToOwner(const std::string& owner) + Owner getOwner() { - return EpochBase::convertToOwner(owner); + return epochBase.timeOwner; } }; -TEST_F(TestEpochBase, convertToMode) +TEST_F(TestEpochBase, onModeChange) { - EXPECT_EQ(Mode::NTP, convertToMode("NTP")); - EXPECT_EQ(Mode::MANUAL, convertToMode("MANUAL")); + epochBase.onModeChanged(Mode::NTP); + EXPECT_EQ(Mode::NTP, getMode()); - // All unrecognized strings are mapped to Ntp - EXPECT_EQ(Mode::NTP, convertToMode("")); - EXPECT_EQ(Mode::NTP, convertToMode("Manual")); - EXPECT_EQ(Mode::NTP, convertToMode("whatever")); + epochBase.onModeChanged(Mode::MANUAL); + EXPECT_EQ(Mode::MANUAL, getMode()); } - -TEST_F(TestEpochBase, convertToOwner) +TEST_F(TestEpochBase, onOwnerChange) { - EXPECT_EQ(Owner::BMC, convertToOwner("BMC")); - EXPECT_EQ(Owner::HOST, convertToOwner("HOST")); - EXPECT_EQ(Owner::SPLIT, convertToOwner("SPLIT")); - EXPECT_EQ(Owner::BOTH, convertToOwner("BOTH")); + epochBase.onOwnerChanged(Owner::BMC); + EXPECT_EQ(Owner::BMC, getOwner()); + + epochBase.onOwnerChanged(Owner::HOST); + EXPECT_EQ(Owner::HOST, getOwner()); + + epochBase.onOwnerChanged(Owner::SPLIT); + EXPECT_EQ(Owner::SPLIT, getOwner()); - // All unrecognized strings are mapped to Bmc - EXPECT_EQ(Owner::BMC, convertToOwner("")); - EXPECT_EQ(Owner::BMC, convertToOwner("Split")); - EXPECT_EQ(Owner::BMC, convertToOwner("xyz")); + epochBase.onOwnerChanged(Owner::BOTH); + EXPECT_EQ(Owner::BOTH, getOwner()); } } diff --git a/test/TestHostEpoch.cpp b/test/TestHostEpoch.cpp index dca8d72..ec8ecf1 100644 --- a/test/TestHostEpoch.cpp +++ b/test/TestHostEpoch.cpp @@ -3,6 +3,7 @@ #include "host_epoch.hpp" #include "config.h" +#include "types.hpp" namespace phosphor { @@ -15,9 +16,6 @@ using namespace std::chrono_literals; class TestHostEpoch : public testing::Test { public: - using Mode = EpochBase::Mode; - using Owner = EpochBase::Owner; - sdbusplus::bus::bus bus; HostEpoch hostEpoch; diff --git a/test/TestManager.cpp b/test/TestManager.cpp new file mode 100644 index 0000000..4d9ae73 --- /dev/null +++ b/test/TestManager.cpp @@ -0,0 +1,76 @@ +#include <sdbusplus/bus.hpp> +#include <gtest/gtest.h> + +#include "types.hpp" +#include "manager.hpp" + +namespace phosphor +{ +namespace time +{ + +class TestManager : public testing::Test +{ + public: + sdbusplus::bus::bus bus; + Manager manager; + + TestManager() + : bus(sdbusplus::bus::new_default()), + manager(bus) + { + // Empty + } + + // Proxies for Manager's private members and functions + Mode getTimeMode() + { + return manager.timeMode; + } + Owner getTimeOwner() + { + return manager.timeOwner; + } + Mode convertToMode(const std::string& mode) + { + return Manager::convertToMode(mode); + } + Owner convertToOwner(const std::string& owner) + { + return Manager::convertToOwner(owner); + } +}; + +TEST_F(TestManager, empty) +{ + EXPECT_EQ(Mode::NTP, getTimeMode()); + EXPECT_EQ(Owner::BMC, getTimeOwner()); +} + +TEST_F(TestManager, convertToMode) +{ + EXPECT_EQ(Mode::NTP, convertToMode("NTP")); + EXPECT_EQ(Mode::MANUAL, convertToMode("MANUAL")); + + // All unrecognized strings are mapped to Ntp + EXPECT_EQ(Mode::NTP, convertToMode("")); + EXPECT_EQ(Mode::NTP, convertToMode("Manual")); + EXPECT_EQ(Mode::NTP, convertToMode("whatever")); +} + + +TEST_F(TestManager, convertToOwner) +{ + EXPECT_EQ(Owner::BMC, convertToOwner("BMC")); + EXPECT_EQ(Owner::HOST, convertToOwner("HOST")); + EXPECT_EQ(Owner::SPLIT, convertToOwner("SPLIT")); + EXPECT_EQ(Owner::BOTH, convertToOwner("BOTH")); + + // All unrecognized strings are mapped to Bmc + EXPECT_EQ(Owner::BMC, convertToOwner("")); + EXPECT_EQ(Owner::BMC, convertToOwner("Split")); + EXPECT_EQ(Owner::BMC, convertToOwner("xyz")); +} + +} +} diff --git a/types.hpp b/types.hpp new file mode 100644 index 0000000..9b88965 --- /dev/null +++ b/types.hpp @@ -0,0 +1,49 @@ +#pragma once + +namespace phosphor +{ +namespace time +{ + /** @brief Supported time modes + * NTP Time sourced by Network Time Server + * MANUAL User of the system need to set the time + */ + enum class Mode + { + NTP, + MANUAL, + }; + + /** @brief Supported time owners + * BMC Time source may be NTP or MANUAL but it has to be set natively + * on the BMC. Meaning, host can not set the time. What it also + * means is that when BMC gets IPMI_SET_SEL_TIME, then its ignored. + * similarly, when BMC gets IPMI_GET_SEL_TIME, then the BMC's time + * is returned. + * + * HOST Its only IPMI_SEL_SEL_TIME that will set the time on BMC. + * Meaning, IPMI_GET_SEL_TIME and request to get BMC time will + * result in same value. + * + * SPLIT Both BMC and HOST will maintain their individual clocks but then + * the time information is stored in BMC. BMC can have either NTP + * or MANUAL as it's source of time and will set the time directly + * on the BMC. When IPMI_SET_SEL_TIME is received, then the delta + * between that and BMC's time is calculated and is stored. + * When BMC reads the time, the current time is returned. + * When IPMI_GET_SEL_TIME is received, BMC's time is retrieved and + * then the delta offset is factored in prior to returning. + * + * BOTH: BMC's time is set with whoever that sets the time. Similarly, + * BMC's time is returned to whoever that asks the time. + */ + enum class Owner + { + BMC, + HOST, + SPLIT, + BOTH, + }; +} +} + |

