Add Software Activation Interface

Change-Id: I922d6cfe31b6a20bd228167c5e12def69d5ef113
Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index daf5508..e992c8b 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,7 @@
 phosphor_version_software_manager_SOURCES = \
 	version_software_manager.cpp \
 	xyz.openbmc_project.Software.Version.cpp \
-	version_software_manager_main.cpp
+	version_software_manager_main.cpp \
+	xyz.openbmc_project.Software.Activation.cpp
 
 phosphor_version_software_manager_LDFLAGS = $(SYSTEMD_LIBS)
diff --git a/version_software_manager.hpp b/version_software_manager.hpp
index 7212cc2..a011022 100644
--- a/version_software_manager.hpp
+++ b/version_software_manager.hpp
@@ -2,6 +2,7 @@
 
 #include <sdbusplus/bus.hpp>
 #include "xyz/openbmc_project/Software/Version/server.hpp"
+#include "xyz/openbmc_project/Software/Activation/server.hpp"
 
 namespace phosphor
 {
@@ -16,7 +17,8 @@
  *  DBus API.
  */
 class Version : public sdbusplus::server::object::object<
-                sdbusplus::xyz::openbmc_project::Software::server::Version>
+                sdbusplus::xyz::openbmc_project::Software::server::Version,
+                sdbusplus::xyz::openbmc_project::Software::server::Activation>
 {
     public:
         /** @brief Constructs Version Software Manager
@@ -31,9 +33,11 @@
         Version(sdbusplus::bus::bus& bus,
                 const char* objPath) :
                 sdbusplus::server::object::object<
-                    sdbusplus::xyz::openbmc_project::Software::server::Version>
-                        (bus, (std::string{objPath} + '/' +
-                            getId()).c_str(), true)
+                    sdbusplus::xyz::openbmc_project::Software::server::Version,
+                    sdbusplus::xyz::openbmc_project::Software::
+                        server::Activation>
+                            (bus, (std::string{objPath} + '/' +
+                                getId()).c_str(), true)
         {
             // Set properties.
             purpose(VersionPurpose::BMC);
diff --git a/xyz.openbmc_project.Software.Activation.cpp b/xyz.openbmc_project.Software.Activation.cpp
new file mode 100644
index 0000000..9001113
--- /dev/null
+++ b/xyz.openbmc_project.Software.Activation.cpp
@@ -0,0 +1,275 @@
+#include <algorithm>
+#include <sdbusplus/server.hpp>
+#include <sdbusplus/exception.hpp>
+#include <xyz/openbmc_project/Software/Activation/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Software
+{
+namespace server
+{
+
+Activation::Activation(bus::bus& bus, const char* path)
+        : _xyz_openbmc_project_Software_Activation_interface(
+                bus, path, _interface, _vtable, this)
+{
+}
+
+
+
+auto Activation::activation() const ->
+        Activations
+{
+    return _activation;
+}
+
+int Activation::_callback_get_Activation(
+        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<Activation*>(context);
+        m.append(convertForMessage(o->activation()));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+auto Activation::activation(Activations value) ->
+        Activations
+{
+    if (_activation != value)
+    {
+        _activation = value;
+        _xyz_openbmc_project_Software_Activation_interface.property_changed("Activation");
+    }
+
+    return _activation;
+}
+
+int Activation::_callback_set_Activation(
+        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<Activation*>(context);
+
+        std::string v{};
+        m.read(v);
+        o->activation(convertActivationsFromString(v));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+namespace details
+{
+namespace Activation
+{
+static const auto _property_Activation =
+    utility::tuple_to_array(message::types::type_id<
+            std::string>());
+}
+}
+auto Activation::requestedActivation() const ->
+        RequestedActivations
+{
+    return _requestedActivation;
+}
+
+int Activation::_callback_get_RequestedActivation(
+        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<Activation*>(context);
+        m.append(convertForMessage(o->requestedActivation()));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+auto Activation::requestedActivation(RequestedActivations value) ->
+        RequestedActivations
+{
+    if (_requestedActivation != value)
+    {
+        _requestedActivation = value;
+        _xyz_openbmc_project_Software_Activation_interface.property_changed("RequestedActivation");
+    }
+
+    return _requestedActivation;
+}
+
+int Activation::_callback_set_RequestedActivation(
+        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<Activation*>(context);
+
+        std::string v{};
+        m.read(v);
+        o->requestedActivation(convertRequestedActivationsFromString(v));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+namespace details
+{
+namespace Activation
+{
+static const auto _property_RequestedActivation =
+    utility::tuple_to_array(message::types::type_id<
+            std::string>());
+}
+}
+
+
+namespace
+{
+/** String to enum mapping for Activation::Activations */
+static const std::tuple<const char*, Activation::Activations> mappingActivationActivations[] =
+        {
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.Activations.NotReady",                 Activation::Activations::NotReady ),
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.Activations.Invalid",                 Activation::Activations::Invalid ),
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.Activations.Ready",                 Activation::Activations::Ready ),
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.Activations.Activating",                 Activation::Activations::Activating ),
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.Activations.Active",                 Activation::Activations::Active ),
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.Activations.Failed",                 Activation::Activations::Failed ),
+        };
+
+} // anonymous namespace
+
+auto Activation::convertActivationsFromString(std::string& s) ->
+        Activations
+{
+    auto i = std::find_if(
+            std::begin(mappingActivationActivations),
+            std::end(mappingActivationActivations),
+            [&s](auto& e){ return 0 == strcmp(s.c_str(), std::get<0>(e)); } );
+    if (std::end(mappingActivationActivations) == i)
+    {
+        throw sdbusplus::exception::InvalidEnumString();
+    }
+    else
+    {
+        return std::get<1>(*i);
+    }
+}
+
+std::string convertForMessage(Activation::Activations v)
+{
+    auto i = std::find_if(
+            std::begin(mappingActivationActivations),
+            std::end(mappingActivationActivations),
+            [v](auto& e){ return v == std::get<1>(e); });
+    return std::get<0>(*i);
+}
+
+namespace
+{
+/** String to enum mapping for Activation::RequestedActivations */
+static const std::tuple<const char*, Activation::RequestedActivations> mappingActivationRequestedActivations[] =
+        {
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.RequestedActivations.None",                 Activation::RequestedActivations::None ),
+            std::make_tuple( "xyz.openbmc_project.Software.Activation.RequestedActivations.Active",                 Activation::RequestedActivations::Active ),
+        };
+
+} // anonymous namespace
+
+auto Activation::convertRequestedActivationsFromString(std::string& s) ->
+        RequestedActivations
+{
+    auto i = std::find_if(
+            std::begin(mappingActivationRequestedActivations),
+            std::end(mappingActivationRequestedActivations),
+            [&s](auto& e){ return 0 == strcmp(s.c_str(), std::get<0>(e)); } );
+    if (std::end(mappingActivationRequestedActivations) == i)
+    {
+        throw sdbusplus::exception::InvalidEnumString();
+    }
+    else
+    {
+        return std::get<1>(*i);
+    }
+}
+
+std::string convertForMessage(Activation::RequestedActivations v)
+{
+    auto i = std::find_if(
+            std::begin(mappingActivationRequestedActivations),
+            std::end(mappingActivationRequestedActivations),
+            [v](auto& e){ return v == std::get<1>(e); });
+    return std::get<0>(*i);
+}
+
+const vtable::vtable_t Activation::_vtable[] = {
+    vtable::start(),
+    vtable::property("Activation",
+                     details::Activation::_property_Activation
+                        .data(),
+                     _callback_get_Activation,
+                     _callback_set_Activation,
+                     vtable::property_::emits_change),
+    vtable::property("RequestedActivation",
+                     details::Activation::_property_RequestedActivation
+                        .data(),
+                     _callback_get_RequestedActivation,
+                     _callback_set_RequestedActivation,
+                     vtable::property_::emits_change),
+    vtable::end()
+};
+
+} // namespace server
+} // namespace Software
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
diff --git a/xyz/openbmc_project/Software/Activation/server.hpp b/xyz/openbmc_project/Software/Activation/server.hpp
new file mode 100644
index 0000000..011d202
--- /dev/null
+++ b/xyz/openbmc_project/Software/Activation/server.hpp
@@ -0,0 +1,136 @@
+#pragma once
+#include <tuple>
+#include <systemd/sd-bus.h>
+#include <sdbusplus/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Software
+{
+namespace server
+{
+
+class Activation
+{
+    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.
+         */
+        Activation() = delete;
+        Activation(const Activation&) = delete;
+        Activation& operator=(const Activation&) = delete;
+        Activation(Activation&&) = delete;
+        Activation& operator=(Activation&&) = delete;
+        virtual ~Activation() = 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.
+         */
+        Activation(bus::bus& bus, const char* path);
+
+        enum class Activations
+        {
+            NotReady,
+            Invalid,
+            Ready,
+            Activating,
+            Active,
+            Failed,
+        };
+        enum class RequestedActivations
+        {
+            None,
+            Active,
+        };
+
+
+
+        /** Get value of Activation */
+        virtual Activations activation() const;
+        /** Set value of Activation */
+        virtual Activations activation(Activations value);
+        /** Get value of RequestedActivation */
+        virtual RequestedActivations requestedActivation() const;
+        /** Set value of RequestedActivation */
+        virtual RequestedActivations requestedActivation(RequestedActivations value);
+
+    /** @brief Convert a string to an appropriate enum value.
+     *  @param[in] s - The string to convert in the form of
+     *                 "xyz.openbmc_project.Software.Activation.<value name>"
+     *  @return - The enum value.
+     */
+    static Activations convertActivationsFromString(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.Software.Activation.<value name>"
+     *  @return - The enum value.
+     */
+    static RequestedActivations convertRequestedActivationsFromString(std::string& s);
+
+    private:
+
+        /** @brief sd-bus callback for get-property 'Activation' */
+        static int _callback_get_Activation(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+        /** @brief sd-bus callback for set-property 'Activation' */
+        static int _callback_set_Activation(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+
+        /** @brief sd-bus callback for get-property 'RequestedActivation' */
+        static int _callback_get_RequestedActivation(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+        /** @brief sd-bus callback for set-property 'RequestedActivation' */
+        static int _callback_set_RequestedActivation(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+
+
+        static constexpr auto _interface = "xyz.openbmc_project.Software.Activation";
+        static const vtable::vtable_t _vtable[];
+        sdbusplus::server::interface::interface
+                _xyz_openbmc_project_Software_Activation_interface;
+
+        Activations _activation{};
+        RequestedActivations _requestedActivation{};
+
+};
+
+/* Specialization of sdbusplus::server::bindings::details::convertForMessage
+ * for enum-type Activation::Activations.
+ *
+ * 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(Activation::Activations e);
+/* Specialization of sdbusplus::server::bindings::details::convertForMessage
+ * for enum-type Activation::RequestedActivations.
+ *
+ * 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(Activation::RequestedActivations e);
+
+} // namespace server
+} // namespace Software
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+