Initial phosphor-state-manager commit
Still a lot of work to come with this one but this is the
initial makefile and building of a basic application
that provides dbus introspection and properties of
the xyz/openbmc_project/State/Host.interface.yaml
Change-Id: I406fafa6a50721b2f28ab6df03ef98a940e2db6e
Signed-off-by: Andrew Geissler <andrewg@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..9a2ba2f
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,11 @@
+AM_DEFAULT_SOURCE_EXT = .cpp
+
+sbin_PROGRAMS = \
+ op-host-state-manager
+
+op_host_state_manager_SOURCES = \
+ host_state_manager.cpp \
+ xyz.openbmc_project.State.Host.cpp \
+ host_state_manager_main.cpp
+
+op_host_state_manager_LDFLAGS = $(SYSTEMD_LIBS)
\ No newline at end of file
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..9941c73
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,18 @@
+#!/bin/sh -xe
+
+AUTOCONF_FILES="Makefile.in aclocal.m4 ar-lib autom4te.cache compile \
+ config.guess config.h.in config.sub configure depcomp install-sh \
+ ltmain.sh missing *libtool test-driver"
+
+case $1 in
+ clean)
+ test -f Makefile && make maintainer-clean
+ for file in ${AUTOCONF_FILES}; do
+ find -name "$file" | xargs -r rm -rf
+ done
+ exit 0
+ ;;
+esac
+
+autoreconf -i
+echo 'Run "./configure ${CONFIGURE_FLAGS} && make"'
\ No newline at end of file
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..847d7e5
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,33 @@
+AC_PREREQ([2.69])
+AC_INIT([phosphor-state-manager], [1.0], [https://github.com/openbmc/phosphor-state-manager/issues])
+AC_LANG([C++])
+AC_CONFIG_HEADERS([config.h])
+AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz])
+AM_SILENT_RULES([yes])
+
+# Checks for programs
+AC_PROG_CXX
+AC_PROG_INSTALL #Checks/sets the install variable to be used
+AC_PROG_MAKE_SET
+
+# Check for libraries
+PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AX_CXX_COMPILE_STDCXX_14([noext])
+AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
+
+AC_ARG_VAR(BUSNAME, [The Dbus busname to own])
+AS_IF([test "x$BUSNAME" == "x"], [BUSNAME="xyz.openbmc_project.State.Host"])
+AC_DEFINE_UNQUOTED([BUSNAME], ["$BUSNAME"], [The DBus busname to own])
+
+AC_ARG_VAR(OBJPATH, [The host state manager Dbus root])
+AS_IF([test "x$OBJPATH" == "x"], [OBJPATH="/xyz/openbmc_project/state/host"])
+AC_DEFINE_UNQUOTED([OBJPATH], ["$OBJPATH"], [The host state manager Dbus root])
+
+# Check for header files.
+AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd developement package required])])
+AC_CHECK_HEADER(sdbusplus/server.hpp, ,[AC_MSG_ERROR([Could not find sdbusplus/server.hpp...openbmc/sdbusplus package required])])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
\ No newline at end of file
diff --git a/host_state_manager.cpp b/host_state_manager.cpp
new file mode 100644
index 0000000..378396c
--- /dev/null
+++ b/host_state_manager.cpp
@@ -0,0 +1,13 @@
+#include <iostream>
+#include "host_state_manager.hpp"
+
+namespace phosphor
+{
+namespace state
+{
+namespace manager
+{
+
+} // namespace manager
+} // namespace state
+} // namepsace phosphor
diff --git a/host_state_manager.hpp b/host_state_manager.hpp
new file mode 100644
index 0000000..4a755db
--- /dev/null
+++ b/host_state_manager.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include "xyz/openbmc_project/State/Host/server.hpp"
+
+namespace phosphor
+{
+namespace state
+{
+namespace manager
+{
+
+/** @class Host
+ * @brief OpenBMC host state management implementation.
+ * @details A concrete implementation for xyz.openbmc_project.State.Host
+ * DBus API.
+ */
+class Host : public sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::State::server::Host>
+{
+ public:
+ /** @brief Constructs Host State Manager
+ *
+ * @param[in] bus - The Dbus bus object
+ * @param[in] busName - The Dbus name to own
+ * @param[in] objPath - The Dbus object path
+ */
+ Host(sdbusplus::bus::bus& bus,
+ const char* busName,
+ const char* objPath) :
+ sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::State::server::Host>(
+ bus, objPath) {};
+
+ private:
+};
+
+} // namespace manager
+} // namespace state
+} // namespace phosphor
diff --git a/host_state_manager_main.cpp b/host_state_manager_main.cpp
new file mode 100644
index 0000000..07314e1
--- /dev/null
+++ b/host_state_manager_main.cpp
@@ -0,0 +1,26 @@
+#include <cstdlib>
+#include <iostream>
+#include <exception>
+#include <sdbusplus/bus.hpp>
+#include "config.h"
+#include "host_state_manager.hpp"
+
+int main(int argc, char *argv[])
+{
+ auto bus = sdbusplus::bus::new_default();
+
+ phosphor::state::manager::Host manager(bus,
+ BUSNAME,
+ OBJPATH);
+ // Add sdbusplus ObjectManager.
+ sdbusplus::server::manager::manager objManager(bus, OBJPATH);
+
+ bus.request_name(BUSNAME);
+
+ while(true)
+ {
+ bus.process_discard();
+ bus.wait();
+ }
+ return 0;
+}
diff --git a/xyz.openbmc_project.State.Host.cpp b/xyz.openbmc_project.State.Host.cpp
new file mode 100644
index 0000000..490d171
--- /dev/null
+++ b/xyz.openbmc_project.State.Host.cpp
@@ -0,0 +1,272 @@
+#include <algorithm>
+#include <sdbusplus/server.hpp>
+#include <sdbusplus/exception.hpp>
+#include <xyz/openbmc_project/State/Host/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace server
+{
+
+Host::Host(bus::bus& bus, const char* path)
+ : _xyz_openbmc_project_State_Host_interface(
+ bus, path, _interface, _vtable, this)
+{
+}
+
+
+
+auto Host::requestedHostTransition() const ->
+ Transition
+{
+ return _requestedHostTransition;
+}
+
+int Host::_callback_get_RequestedHostTransition(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* reply, void* context,
+ sd_bus_error* error)
+{
+ using sdbusplus::server::binding::details::convertForMessage;
+
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(reply));
+
+ auto o = static_cast<Host*>(context);
+ m.append(convertForMessage(o->requestedHostTransition()));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+auto Host::requestedHostTransition(Transition value) ->
+ Transition
+{
+ if (_requestedHostTransition != value)
+ {
+ _requestedHostTransition = value;
+ _xyz_openbmc_project_State_Host_interface.property_changed("RequestedHostTransition");
+ }
+
+ return _requestedHostTransition;
+}
+
+int Host::_callback_set_RequestedHostTransition(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* value, void* context,
+ sd_bus_error* error)
+{
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(value));
+
+ auto o = static_cast<Host*>(context);
+
+ std::string v{};
+ m.read(v);
+ o->requestedHostTransition(convertTransitionFromString(v));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+namespace details
+{
+namespace Host
+{
+static const auto _property_RequestedHostTransition =
+ utility::tuple_to_array(message::types::type_id<
+ std::string>());
+}
+}
+auto Host::currentHostState() const ->
+ HostState
+{
+ return _currentHostState;
+}
+
+int Host::_callback_get_CurrentHostState(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* reply, void* context,
+ sd_bus_error* error)
+{
+ using sdbusplus::server::binding::details::convertForMessage;
+
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(reply));
+
+ auto o = static_cast<Host*>(context);
+ m.append(convertForMessage(o->currentHostState()));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+auto Host::currentHostState(HostState value) ->
+ HostState
+{
+ if (_currentHostState != value)
+ {
+ _currentHostState = value;
+ _xyz_openbmc_project_State_Host_interface.property_changed("CurrentHostState");
+ }
+
+ return _currentHostState;
+}
+
+int Host::_callback_set_CurrentHostState(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* value, void* context,
+ sd_bus_error* error)
+{
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(value));
+
+ auto o = static_cast<Host*>(context);
+
+ std::string v{};
+ m.read(v);
+ o->currentHostState(convertHostStateFromString(v));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+namespace details
+{
+namespace Host
+{
+static const auto _property_CurrentHostState =
+ utility::tuple_to_array(message::types::type_id<
+ std::string>());
+}
+}
+
+
+namespace
+{
+/** String to enum mapping for Host::Transition */
+static const std::tuple<const char*, Host::Transition> mappingHostTransition[] =
+ {
+ std::make_tuple( "xyz.openbmc_project.State.Host.Transition.Off", Host::Transition::Off ),
+ std::make_tuple( "xyz.openbmc_project.State.Host.Transition.On", Host::Transition::On ),
+ std::make_tuple( "xyz.openbmc_project.State.Host.Transition.Reboot", Host::Transition::Reboot ),
+ };
+
+} // anonymous namespace
+
+auto Host::convertTransitionFromString(std::string& s) ->
+ Transition
+{
+ auto i = std::find_if(
+ std::begin(mappingHostTransition),
+ std::end(mappingHostTransition),
+ [&s](auto& e){ return 0 == strcmp(s.c_str(), std::get<0>(e)); } );
+ if (std::end(mappingHostTransition) == i)
+ {
+ throw sdbusplus::exception::InvalidEnumString();
+ }
+ else
+ {
+ return std::get<1>(*i);
+ }
+}
+
+std::string convertForMessage(Host::Transition v)
+{
+ auto i = std::find_if(
+ std::begin(mappingHostTransition),
+ std::end(mappingHostTransition),
+ [v](auto& e){ return v == std::get<1>(e); });
+ return std::get<0>(*i);
+}
+
+namespace
+{
+/** String to enum mapping for Host::HostState */
+static const std::tuple<const char*, Host::HostState> mappingHostHostState[] =
+ {
+ std::make_tuple( "xyz.openbmc_project.State.Host.HostState.Off", Host::HostState::Off ),
+ std::make_tuple( "xyz.openbmc_project.State.Host.HostState.Running", Host::HostState::Running ),
+ };
+
+} // anonymous namespace
+
+auto Host::convertHostStateFromString(std::string& s) ->
+ HostState
+{
+ auto i = std::find_if(
+ std::begin(mappingHostHostState),
+ std::end(mappingHostHostState),
+ [&s](auto& e){ return 0 == strcmp(s.c_str(), std::get<0>(e)); } );
+ if (std::end(mappingHostHostState) == i)
+ {
+ throw sdbusplus::exception::InvalidEnumString();
+ }
+ else
+ {
+ return std::get<1>(*i);
+ }
+}
+
+std::string convertForMessage(Host::HostState v)
+{
+ auto i = std::find_if(
+ std::begin(mappingHostHostState),
+ std::end(mappingHostHostState),
+ [v](auto& e){ return v == std::get<1>(e); });
+ return std::get<0>(*i);
+}
+
+const vtable::vtable_t Host::_vtable[] = {
+ vtable::start(),
+ vtable::property("RequestedHostTransition",
+ details::Host::_property_RequestedHostTransition
+ .data(),
+ _callback_get_RequestedHostTransition,
+ _callback_set_RequestedHostTransition,
+ vtable::property_::emits_change),
+ vtable::property("CurrentHostState",
+ details::Host::_property_CurrentHostState
+ .data(),
+ _callback_get_CurrentHostState,
+ _callback_set_CurrentHostState,
+ vtable::property_::emits_change),
+ vtable::end()
+};
+
+} // namespace server
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
diff --git a/xyz/openbmc_project/State/Host/server.hpp b/xyz/openbmc_project/State/Host/server.hpp
new file mode 100644
index 0000000..149baa0
--- /dev/null
+++ b/xyz/openbmc_project/State/Host/server.hpp
@@ -0,0 +1,133 @@
+#pragma once
+#include <tuple>
+#include <systemd/sd-bus.h>
+#include <sdbusplus/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace server
+{
+
+class Host
+{
+ public:
+ /* Define all of the basic class operations:
+ * Not allowed:
+ * - Default constructor to avoid nullptrs.
+ * - Copy operations due to internal unique_ptr.
+ * - Move operations due to 'this' being registered as the
+ * 'context' with sdbus.
+ * Allowed:
+ * - Destructor.
+ */
+ Host() = delete;
+ Host(const Host&) = delete;
+ Host& operator=(const Host&) = delete;
+ Host(Host&&) = delete;
+ Host& operator=(Host&&) = delete;
+ virtual ~Host() = default;
+
+ /** @brief Constructor to put object onto bus at a dbus path.
+ * @param[in] bus - Bus to attach to.
+ * @param[in] path - Path to attach at.
+ */
+ Host(bus::bus& bus, const char* path);
+
+ enum class Transition
+ {
+ Off,
+ On,
+ Reboot,
+ };
+ enum class HostState
+ {
+ Off,
+ Running,
+ };
+
+
+
+ /** Get value of RequestedHostTransition */
+ virtual Transition requestedHostTransition() const;
+ /** Set value of RequestedHostTransition */
+ virtual Transition requestedHostTransition(Transition value);
+ /** Get value of CurrentHostState */
+ virtual HostState currentHostState() const;
+ /** Set value of CurrentHostState */
+ virtual HostState currentHostState(HostState value);
+
+ /** @brief Convert a string to an appropriate enum value.
+ * @param[in] s - The string to convert in the form of
+ * "xyz.openbmc_project.State.Host.<value name>"
+ * @return - The enum value.
+ */
+ static Transition convertTransitionFromString(std::string& s);
+ /** @brief Convert a string to an appropriate enum value.
+ * @param[in] s - The string to convert in the form of
+ * "xyz.openbmc_project.State.Host.<value name>"
+ * @return - The enum value.
+ */
+ static HostState convertHostStateFromString(std::string& s);
+
+ private:
+
+ /** @brief sd-bus callback for get-property 'RequestedHostTransition' */
+ static int _callback_get_RequestedHostTransition(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+ /** @brief sd-bus callback for set-property 'RequestedHostTransition' */
+ static int _callback_set_RequestedHostTransition(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+
+ /** @brief sd-bus callback for get-property 'CurrentHostState' */
+ static int _callback_get_CurrentHostState(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+ /** @brief sd-bus callback for set-property 'CurrentHostState' */
+ static int _callback_set_CurrentHostState(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+
+
+ static constexpr auto _interface = "xyz.openbmc_project.State.Host";
+ static const vtable::vtable_t _vtable[];
+ sdbusplus::server::interface::interface
+ _xyz_openbmc_project_State_Host_interface;
+
+ Transition _requestedHostTransition = Transition::Off;
+ HostState _currentHostState{};
+
+};
+
+/* Specialization of sdbusplus::server::bindings::details::convertForMessage
+ * for enum-type Host::Transition.
+ *
+ * This converts from the enum to a constant c-string representing the enum.
+ *
+ * @param[in] e - Enum value to convert.
+ * @return C-string representing the name for the enum value.
+ */
+std::string convertForMessage(Host::Transition e);
+/* Specialization of sdbusplus::server::bindings::details::convertForMessage
+ * for enum-type Host::HostState.
+ *
+ * This converts from the enum to a constant c-string representing the enum.
+ *
+ * @param[in] e - Enum value to convert.
+ * @return C-string representing the name for the enum value.
+ */
+std::string convertForMessage(Host::HostState e);
+
+} // namespace server
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+