Activation: create associations
Create activation, functional, activate associations during PSU update.
Tested: With dummy psu update service, verify the assocations are
created when the PSU update is completed, and not created
when PSU update fails.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I3d457e65b55066b93f7fc9a3311093dcec05d020
diff --git a/src/activation.cpp b/src/activation.cpp
index f63352a..f1181fb 100644
--- a/src/activation.cpp
+++ b/src/activation.cpp
@@ -105,7 +105,8 @@
bool Activation::doUpdate(const std::string& psuInventoryPath)
{
- psuUpdateUnit = internal::getUpdateService(psuInventoryPath, versionId);
+ currentUpdatingPsu = psuInventoryPath;
+ psuUpdateUnit = internal::getUpdateService(currentUpdatingPsu, versionId);
try
{
auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
@@ -141,6 +142,13 @@
auto progress = activationProgress->progress() + progressStep;
activationProgress->progress(progress);
+ // Update the activation association
+ auto assocs = associations();
+ assocs.emplace_back(ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
+ currentUpdatingPsu);
+ currentUpdatingPsu.clear();
+ associations(assocs);
+
psuQueue.pop();
doUpdate(); // Update the next psu
}
@@ -202,8 +210,11 @@
activationProgress->progress(100);
// TODO: delete the old software object
- // TODO: create related associations
deleteImageManagerObject();
+
+ associationInterface->createActiveAssociation(path);
+ associationInterface->addFunctionalAssociation(path);
+
activation(Status::Active);
}
diff --git a/src/activation.hpp b/src/activation.hpp
index 59364e4..d0fdaba 100644
--- a/src/activation.hpp
+++ b/src/activation.hpp
@@ -2,6 +2,7 @@
#include "config.h"
+#include "association_interface.hpp"
#include "types.hpp"
#include <queue>
@@ -123,7 +124,8 @@
*/
Activation(sdbusplus::bus::bus& bus, const std::string& path,
const std::string& versionId, const std::string& extVersion,
- Status activationStatus, const AssociationList& assocs) :
+ Status activationStatus, const AssociationList& assocs,
+ AssociationInterface* associationInterface) :
ActivationInherit(bus, path.c_str(), true),
versionId(versionId), bus(bus), path(path),
systemdSignals(
@@ -132,7 +134,8 @@
sdbusRule::path("/org/freedesktop/systemd1") +
sdbusRule::interface("org.freedesktop.systemd1.Manager"),
std::bind(&Activation::unitStateChange, this,
- std::placeholders::_1))
+ std::placeholders::_1)),
+ associationInterface(associationInterface)
{
// Set Properties.
extendedVersion(extVersion);
@@ -227,11 +230,17 @@
/** @brief The PSU update systemd unit */
std::string psuUpdateUnit;
+ /** @brief The PSU Inventory path of the current updating PSU */
+ std::string currentUpdatingPsu;
+
/** @brief Persistent ActivationBlocksTransition dbus object */
std::unique_ptr<ActivationBlocksTransition> activationBlocksTransition;
/** @brief Persistent ActivationProgress dbus object */
std::unique_ptr<ActivationProgress> activationProgress;
+
+ /** @brief The AssociationInterface pointer */
+ AssociationInterface* associationInterface;
};
} // namespace updater
diff --git a/src/association_interface.hpp b/src/association_interface.hpp
new file mode 100644
index 0000000..e3d653c
--- /dev/null
+++ b/src/association_interface.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <string>
+
+class AssociationInterface
+{
+ public:
+ virtual ~AssociationInterface() = default;
+
+ /** @brief Create an active association to the
+ * newly active software image
+ *
+ * @param[in] path - The path to create the association to.
+ */
+ virtual void createActiveAssociation(const std::string& path) = 0;
+
+ /** @brief Add the functional association to the
+ * new "running" PSU images
+ *
+ * @param[in] path - The path to add the association to.
+ */
+ virtual void addFunctionalAssociation(const std::string& path) = 0;
+
+ /** @brief Remove the associations from the provided software image path
+ *
+ * @param[in] path - The path to remove the association from.
+ */
+ virtual void removeAssociation(const std::string& path) = 0;
+};
diff --git a/src/item_updater.cpp b/src/item_updater.cpp
index 50c1a26..e100381 100644
--- a/src/item_updater.cpp
+++ b/src/item_updater.cpp
@@ -190,7 +190,7 @@
const AssociationList& assocs)
{
return std::make_unique<Activation>(bus, path, versionId, extVersion,
- activationStatus, assocs);
+ activationStatus, assocs, this);
}
void ItemUpdater::createPsuObject(const std::string& psuInventoryPath,
diff --git a/src/item_updater.hpp b/src/item_updater.hpp
index eabe66f..c0a64fa 100644
--- a/src/item_updater.hpp
+++ b/src/item_updater.hpp
@@ -3,6 +3,7 @@
#include "config.h"
#include "activation.hpp"
+#include "association_interface.hpp"
#include "types.hpp"
#include "utils.hpp"
#include "version.hpp"
@@ -31,7 +32,7 @@
/** @class ItemUpdater
* @brief Manages the activation of the PSU version items.
*/
-class ItemUpdater : public ItemUpdaterInherit
+class ItemUpdater : public ItemUpdaterInherit, public AssociationInterface
{
friend class ::TestItemUpdater;
@@ -63,27 +64,27 @@
*/
void deleteAll();
- private:
/** @brief Creates an active association to the
* newly active software image
*
* @param[in] path - The path to create the association to.
*/
- void createActiveAssociation(const std::string& path);
+ void createActiveAssociation(const std::string& path) override;
/** @brief Add the functional association to the
* new "running" PSU images
*
* @param[in] path - The path to add the association to.
*/
- void addFunctionalAssociation(const std::string& path);
+ void addFunctionalAssociation(const std::string& path) override;
/** @brief Removes the associations from the provided software image path
*
* @param[in] path - The path to remove the association from.
*/
- void removeAssociation(const std::string& path);
+ void removeAssociation(const std::string& path) override;
+ private:
/** @brief Callback function for Software.Version match.
* @details Creates an Activation D-Bus object.
*
diff --git a/test/mocked_association_interface.hpp b/test/mocked_association_interface.hpp
new file mode 100644
index 0000000..731ea58
--- /dev/null
+++ b/test/mocked_association_interface.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "association_interface.hpp"
+
+#include <gmock/gmock.h>
+
+class MockedAssociationInterface : public AssociationInterface
+{
+ public:
+ virtual ~MockedAssociationInterface() = default;
+
+ MOCK_METHOD1(createActiveAssociation, void(const std::string& path));
+ MOCK_METHOD1(addFunctionalAssociation, void(const std::string& path));
+ MOCK_METHOD1(removeAssociation, void(const std::string& path));
+};
diff --git a/test/test_activation.cpp b/test/test_activation.cpp
index 338dc60..891cdb6 100644
--- a/test/test_activation.cpp
+++ b/test/test_activation.cpp
@@ -1,4 +1,5 @@
#include "activation.hpp"
+#include "mocked_association_interface.hpp"
#include "mocked_utils.hpp"
#include <sdbusplus/test/sdbus_mock.hpp>
@@ -37,13 +38,14 @@
{
return activation->activationProgress->progress();
}
- static constexpr auto dBusPath = SOFTWARE_OBJPATH;
sdbusplus::SdBusMock sdbusMock;
sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
const utils::MockedUtils& mockedUtils;
+ MockedAssociationInterface mockedAssociationInterface;
std::unique_ptr<Activation> activation;
std::string versionId = "abcdefgh";
std::string extVersion = "Some Ext Version";
+ std::string dBusPath = std::string(SOFTWARE_OBJPATH) + "/" + versionId;
Status status = Status::Ready;
AssociationList associations;
};
@@ -51,7 +53,8 @@
TEST_F(TestActivation, ctordtor)
{
activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
- extVersion, status, associations);
+ extVersion, status, associations,
+ &mockedAssociationInterface);
}
namespace phosphor::software::updater::internal
@@ -75,12 +78,17 @@
TEST_F(TestActivation, doUpdateWhenNoPSU)
{
activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
- extVersion, status, associations);
+ extVersion, status, associations,
+ &mockedAssociationInterface);
ON_CALL(mockedUtils, getPSUInventoryPath(_))
.WillByDefault(
Return(std::vector<std::string>({}))); // No PSU inventory
activation->requestedActivation(RequestedStatus::Active);
+ EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
+ .Times(0);
+ EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
+ .Times(0);
EXPECT_EQ(Status::Failed, activation->activation());
}
@@ -88,7 +96,8 @@
{
constexpr auto psu0 = "/com/example/inventory/psu0";
activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
- extVersion, status, associations);
+ extVersion, status, associations,
+ &mockedAssociationInterface);
ON_CALL(mockedUtils, getPSUInventoryPath(_))
.WillByDefault(
Return(std::vector<std::string>({psu0}))); // One PSU inventory
@@ -96,6 +105,10 @@
EXPECT_EQ(Status::Activating, activation->activation());
+ EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
+ .Times(1);
+ EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
+ .Times(1);
onUpdateDone();
EXPECT_EQ(Status::Active, activation->activation());
}
@@ -107,7 +120,8 @@
constexpr auto psu2 = "/com/example/inventory/psu2";
constexpr auto psu3 = "/com/example/inventory/psu3";
activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
- extVersion, status, associations);
+ extVersion, status, associations,
+ &mockedAssociationInterface);
ON_CALL(mockedUtils, getPSUInventoryPath(_))
.WillByDefault(Return(
std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
@@ -128,6 +142,11 @@
EXPECT_EQ(Status::Activating, activation->activation());
EXPECT_EQ(70, getProgress());
+ EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
+ .Times(1);
+ EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
+ .Times(1);
+
onUpdateDone();
EXPECT_EQ(Status::Active, activation->activation());
}
@@ -139,7 +158,8 @@
constexpr auto psu2 = "/com/example/inventory/psu2";
constexpr auto psu3 = "/com/example/inventory/psu3";
activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
- extVersion, status, associations);
+ extVersion, status, associations,
+ &mockedAssociationInterface);
ON_CALL(mockedUtils, getPSUInventoryPath(_))
.WillByDefault(Return(
std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
@@ -152,6 +172,10 @@
EXPECT_EQ(Status::Activating, activation->activation());
EXPECT_EQ(30, getProgress());
+ EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
+ .Times(0);
+ EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
+ .Times(0);
onUpdateFailed();
EXPECT_EQ(Status::Failed, activation->activation());
}
@@ -160,7 +184,8 @@
{
constexpr auto psu0 = "/com/example/inventory/psu0";
activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
- extVersion, status, associations);
+ extVersion, status, associations,
+ &mockedAssociationInterface);
ON_CALL(mockedUtils, getPSUInventoryPath(_))
.WillByDefault(
Return(std::vector<std::string>({psu0}))); // One PSU inventory