blob: 2230d0fd839cb677786c37fa9952f65a80900781 [file] [log] [blame]
#include "config.h"
#include "activation.hpp"
#include "utils.hpp"
#include <cassert>
#include <filesystem>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
namespace phosphor
{
namespace software
{
namespace updater
{
constexpr auto SYSTEMD_BUSNAME = "org.freedesktop.systemd1";
constexpr auto SYSTEMD_PATH = "/org/freedesktop/systemd1";
constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
namespace fs = std::filesystem;
namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
using namespace phosphor::logging;
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)
{
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)
{
startActivation();
}
else
{
// TODO
}
return SoftwareActivation::activation(value);
}
auto Activation::requestedActivation(RequestedActivations value)
-> RequestedActivations
{
if ((value == SoftwareActivation::RequestedActivations::Active) &&
(SoftwareActivation::requestedActivation() !=
SoftwareActivation::RequestedActivations::Active))
{
if ((activation() == Status::Ready) || (activation() == Status::Failed))
{
activation(Status::Activating);
}
}
return SoftwareActivation::requestedActivation(value);
}
void Activation::unitStateChange(sdbusplus::message::message& 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 == psuUpdateUnit)
{
if (newStateResult == "done")
{
finishActivation();
}
if (newStateResult == "failed" || newStateResult == "dependency")
{
activation(Status::Failed);
}
}
}
void Activation::startActivation()
{
// TODO: for now only update one psu, future commits shall handle update
// multiple psus
auto psuPaths = utils::getPSUInventoryPath(bus);
if (psuPaths.empty())
{
return;
}
psuUpdateUnit = internal::getUpdateService(psuPaths[0], versionId);
auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
SYSTEMD_INTERFACE, "StartUnit");
method.append(psuUpdateUnit, "replace");
bus.call_noreply(method);
}
void Activation::finishActivation()
{
// TODO: delete the old software object
// TODO: create related associations
deleteImageManagerObject();
activation(Status::Active);
}
void Activation::deleteImageManagerObject()
{
// Get the Delete object for <versionID> inside image_manager
constexpr auto versionServiceStr = "xyz.openbmc_project.Software.Version";
constexpr auto deleteInterface = "xyz.openbmc_project.Object.Delete";
std::string versionService;
auto services = utils::getServices(bus, path.c_str(), deleteInterface);
// We need to find the phosphor-version-software-manager's version service
// to invoke the delete interface
for (const auto& service : services)
{
if (service.find(versionServiceStr) != std::string::npos)
{
versionService = service;
break;
}
}
if (versionService.empty())
{
log<level::ERR>("Error finding version service");
return;
}
// Call the Delete object for <versionID> inside image_manager
auto method = bus.new_method_call(versionService.c_str(), path.c_str(),
deleteInterface, "Delete");
try
{
bus.call(method);
}
catch (const SdBusError& e)
{
log<level::ERR>("Error performing call to Delete object path",
entry("ERROR=%s", e.what()),
entry("PATH=%s", path.c_str()));
}
}
} // namespace updater
} // namespace software
} // namespace phosphor