Activation: support updating PSU from stored image
The previous code assume the image to update is from IMG_DIR.
Now it needs to update PSU from pre-built or stored images.
This commit adds the support, by constructing the systemd unit based on
Activation's Path property instead of IMG_DIR.
Tested: Verify on Witherspoon that it is able to activate a stored
image.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I0936bb921b22c7f67aee9689e3695e6b21703a29
diff --git a/src/activation.cpp b/src/activation.cpp
index 680cdd9..efff61b 100644
--- a/src/activation.cpp
+++ b/src/activation.cpp
@@ -27,32 +27,6 @@
using sdbusplus::exception::SdBusError;
using SoftwareActivation = softwareServer::Activation;
-namespace internal
-{
-/** Construct the systemd service name */
-std::string getUpdateService(const std::string& psuInventoryPath,
- const std::string& versionId)
-{
- // TODO: get image path from the related version
- // because it could be in either IMG_DIR, or IMG_DIR_PERSIST, or
- // IMG_DIR_BUILTIN
- fs::path imagePath(IMG_DIR);
- imagePath /= versionId;
-
- // The systemd unit shall be escaped
- std::string args = psuInventoryPath;
- args += "\\x20";
- args += imagePath;
- std::replace(args.begin(), args.end(), '/', '-');
-
- std::string service = PSU_UPDATE_SERVICE;
- auto p = service.find('@');
- assert(p != std::string::npos);
- service.insert(p + 1, args);
- return service;
-}
-
-} // namespace internal
auto Activation::activation(Activations value) -> Activations
{
if (value == Status::Activating)
@@ -109,7 +83,7 @@
bool Activation::doUpdate(const std::string& psuInventoryPath)
{
currentUpdatingPsu = psuInventoryPath;
- psuUpdateUnit = internal::getUpdateService(currentUpdatingPsu, versionId);
+ psuUpdateUnit = getUpdateService(currentUpdatingPsu);
try
{
auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
@@ -256,7 +230,8 @@
}
if (versionService.empty())
{
- log<level::ERR>("Error finding version service");
+ // When updating a stored image, there is no version object created by
+ // "xyz.openbmc_project.Software.Version" service, so skip it.
return;
}
@@ -301,8 +276,13 @@
{
// Store image in persistent dir separated by model
// and only store the latest one by removing old ones
- auto src = fs::path(IMG_DIR) / versionId;
+ auto src = path();
auto dst = fs::path(IMG_DIR_PERSIST) / model;
+ if (src == dst)
+ {
+ // This happens when updating an stored image, no need to store it again
+ return;
+ }
try
{
fs::remove_all(dst);
@@ -318,6 +298,23 @@
}
}
+std::string Activation::getUpdateService(const std::string& psuInventoryPath)
+{
+ fs::path imagePath(path());
+
+ // The systemd unit shall be escaped
+ std::string args = psuInventoryPath;
+ args += "\\x20";
+ args += imagePath;
+ std::replace(args.begin(), args.end(), '/', '-');
+
+ std::string service = PSU_UPDATE_SERVICE;
+ auto p = service.find('@');
+ assert(p != std::string::npos);
+ service.insert(p + 1, args);
+ return service;
+}
+
} // namespace updater
} // namespace software
} // namespace phosphor
diff --git a/src/activation.hpp b/src/activation.hpp
index beab767..be373c5 100644
--- a/src/activation.hpp
+++ b/src/activation.hpp
@@ -231,6 +231,14 @@
/** @brief Store the updated PSU image to persistent dir */
void storeImage();
+ /** @brief Construct the systemd service name
+ *
+ * @param[in] psuInventoryPath - The PSU inventory to be updated.
+ *
+ * @return The escaped string of systemd unit to do the PSU update.
+ */
+ std::string getUpdateService(const std::string& psuInventoryPath);
+
/** @brief Persistent sdbusplus DBus bus connection */
sdbusplus::bus::bus& bus;
diff --git a/test/test_activation.cpp b/test/test_activation.cpp
index 0c45a37..f89475a 100644
--- a/test/test_activation.cpp
+++ b/test/test_activation.cpp
@@ -51,6 +51,10 @@
{
return activation->psuQueue;
}
+ std::string getUpdateService(const std::string& psuInventoryPath)
+ {
+ return activation->getUpdateService(psuInventoryPath);
+ }
sdbusplus::SdBusMock sdbusMock;
sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
@@ -80,21 +84,19 @@
&mockedAssociationInterface, filePath);
}
-namespace phosphor::software::updater::internal
-{
-extern std::string getUpdateService(const std::string& psuInventoryPath,
- const std::string& versionId);
-}
-
TEST_F(TestActivation, getUpdateService)
{
std::string psuInventoryPath = "/com/example/inventory/powersupply1";
- std::string versionId = "12345678";
std::string toCompare = "psu-update@-com-example-inventory-"
"powersupply1\\x20-tmp-images-12345678.service";
+ versionId = "12345678";
+ filePath = "/tmp/images/12345678";
- auto service = phosphor::software::updater::internal::getUpdateService(
- psuInventoryPath, versionId);
+ activation = std::make_unique<Activation>(
+ mockedBus, dBusPath, versionId, extVersion, status, associations,
+ &mockedAssociationInterface, filePath);
+
+ auto service = getUpdateService(psuInventoryPath);
EXPECT_EQ(toCompare, service);
}