blob: a4cc6d155d71852ff469eff2436d90e67f9501c8 [file] [log] [blame]
#include "activation_static.hpp"
#include "item_updater.hpp"
#include <phosphor-logging/log.hpp>
namespace openpower
{
namespace software
{
namespace updater
{
namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
using namespace phosphor::logging;
auto ActivationStatic::activation(Activations value) -> Activations
{
auto ret = value;
if (value != softwareServer::Activation::Activations::Active)
{
redundancyPriority.reset(nullptr);
}
if (value == softwareServer::Activation::Activations::Activating)
{
fs::path imagePath(IMG_DIR);
imagePath /= versionId;
for (const auto& entry : fs::directory_iterator(imagePath))
{
if (entry.path().extension() == ".pnor")
{
pnorFilePath = entry;
break;
}
}
if (pnorFilePath.empty())
{
log<level::ERR>("Unable to find pnor file",
entry("DIR=%s", imagePath.c_str()));
ret = softwareServer::Activation::Activations::Failed;
goto out;
}
#ifdef WANT_SIGNATURE_VERIFY
// Validate the signed image.
if (!validateSignature(pnorFilePath.filename()))
{
// Cleanup
activationBlocksTransition.reset(nullptr);
activationProgress.reset(nullptr);
ret = softwareServer::Activation::Activations::Failed;
goto out;
}
#endif
if (parent.freeSpace())
{
startActivation();
}
else
{
ret = softwareServer::Activation::Activations::Failed;
}
}
else
{
activationBlocksTransition.reset(nullptr);
activationProgress.reset(nullptr);
}
out:
return softwareServer::Activation::activation(ret);
}
void ActivationStatic::startActivation()
{
if (!activationProgress)
{
activationProgress = std::make_unique<ActivationProgress>(bus, path);
}
if (!activationBlocksTransition)
{
activationBlocksTransition =
std::make_unique<ActivationBlocksTransition>(bus, path);
}
// TODO: check why the signal is still received without calling this
// function?
subscribeToSystemdSignals();
log<level::INFO>("Start programming...",
entry("PNOR=%s", pnorFilePath.c_str()));
std::string pnorFileEscaped = pnorFilePath.string();
// Escape all '/' to '-'
std::replace(pnorFileEscaped.begin(), pnorFileEscaped.end(), '/', '-');
constexpr auto updatePNORService = "openpower-pnor-update@";
pnorUpdateUnit = std::string(updatePNORService) + pnorFileEscaped +
".service";
auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
SYSTEMD_INTERFACE, "StartUnit");
method.append(pnorUpdateUnit, "replace");
bus.call_noreply(method);
activationProgress->progress(10);
}
void ActivationStatic::unitStateChange(sdbusplus::message_t& msg)
{
uint32_t newStateID{};
sdbusplus::message::object_path newStateObjPath;
std::string newStateUnit{};
std::string newStateResult{};
// Read the msg and populate each variable
msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
if (newStateUnit == pnorUpdateUnit)
{
if (newStateResult == "done")
{
finishActivation();
}
if (newStateResult == "failed" || newStateResult == "dependency")
{
Activation::activation(
softwareServer::Activation::Activations::Failed);
}
}
}
void ActivationStatic::finishActivation()
{
activationProgress->progress(90);
// Set Redundancy Priority before setting to Active
if (!redundancyPriority)
{
redundancyPriority = std::make_unique<RedundancyPriority>(bus, path,
*this, 0);
}
activationProgress->progress(100);
activationBlocksTransition.reset();
activationProgress.reset();
unsubscribeFromSystemdSignals();
// Remove version object from image manager
deleteImageManagerObject();
// Create active association
parent.createActiveAssociation(path);
// Create updateable association as this
// can be re-programmed.
parent.createUpdateableAssociation(path);
// Create functional association
parent.updateFunctionalAssociation(versionId);
Activation::activation(Activation::Activations::Active);
}
} // namespace updater
} // namespace software
} // namespace openpower