blob: df84879a75fd9af354b4ff414ed2d3ddad9a655a [file] [log] [blame]
Lei YU12c9f4c2019-09-11 15:08:15 +08001#include "config.h"
2
Lei YU01539e72019-07-31 10:57:38 +08003#include "activation.hpp"
4
Lei YU12c9f4c2019-09-11 15:08:15 +08005#include "utils.hpp"
6
7#include <cassert>
8#include <filesystem>
9
Lei YU01539e72019-07-31 10:57:38 +080010namespace phosphor
11{
12namespace software
13{
14namespace updater
15{
16
Lei YU12c9f4c2019-09-11 15:08:15 +080017constexpr auto SYSTEMD_BUSNAME = "org.freedesktop.systemd1";
18constexpr auto SYSTEMD_PATH = "/org/freedesktop/systemd1";
19constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
20
21namespace fs = std::filesystem;
Lei YU01539e72019-07-31 10:57:38 +080022namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
23
Lei YU12c9f4c2019-09-11 15:08:15 +080024using SoftwareActivation = softwareServer::Activation;
25
26namespace internal
27{
28/** Construct the systemd service name */
29std::string getUpdateService(const std::string& psuInventoryPath,
30 const std::string& versionId)
31{
32 fs::path imagePath(IMG_DIR);
33 imagePath /= versionId;
34
35 // The systemd unit shall be escaped
36 std::string args = psuInventoryPath;
37 args += "\\x20";
38 args += imagePath;
39 std::replace(args.begin(), args.end(), '/', '-');
40
41 std::string service = PSU_UPDATE_SERVICE;
42 auto p = service.find('@');
43 assert(p != std::string::npos);
44 service.insert(p + 1, args);
45 return service;
46}
47
48} // namespace internal
Lei YU01539e72019-07-31 10:57:38 +080049auto Activation::activation(Activations value) -> Activations
50{
Lei YU12c9f4c2019-09-11 15:08:15 +080051 if (value == Status::Activating)
52 {
53 startActivation();
54 }
55 else
56 {
57 // TODO
58 }
59
60 return SoftwareActivation::activation(value);
Lei YU01539e72019-07-31 10:57:38 +080061}
62
63auto Activation::requestedActivation(RequestedActivations value)
64 -> RequestedActivations
65{
Lei YU12c9f4c2019-09-11 15:08:15 +080066 if ((value == SoftwareActivation::RequestedActivations::Active) &&
67 (SoftwareActivation::requestedActivation() !=
68 SoftwareActivation::RequestedActivations::Active))
69 {
70 if ((activation() == Status::Ready) || (activation() == Status::Failed))
71 {
72 activation(Status::Activating);
73 }
74 }
75 return SoftwareActivation::requestedActivation(value);
76}
77
78void Activation::unitStateChange(sdbusplus::message::message& msg)
79{
80 uint32_t newStateID{};
81 sdbusplus::message::object_path newStateObjPath;
82 std::string newStateUnit{};
83 std::string newStateResult{};
84
85 // Read the msg and populate each variable
86 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
87
88 if (newStateUnit == psuUpdateUnit)
89 {
90 if (newStateResult == "done")
91 {
92 finishActivation();
93 }
94 if (newStateResult == "failed" || newStateResult == "dependency")
95 {
96 activation(Status::Failed);
97 }
98 }
99}
100
101void Activation::startActivation()
102{
103 // TODO: for now only update one psu, future commits shall handle update
104 // multiple psus
105 auto psuPaths = utils::getPSUInventoryPath(bus);
106 if (psuPaths.empty())
107 {
108 return;
109 }
110
111 psuUpdateUnit = internal::getUpdateService(psuPaths[0], versionId);
112
113 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
114 SYSTEMD_INTERFACE, "StartUnit");
115 method.append(psuUpdateUnit, "replace");
116 bus.call_noreply(method);
117}
118
119void Activation::finishActivation()
120{
121 // TODO: delete the interfaces created by phosphor-software-manager
122 // TODO: delete the old software object
123 // TODO: create related associations
124 activation(Status::Active);
Lei YU01539e72019-07-31 10:57:38 +0800125}
126
127} // namespace updater
128} // namespace software
129} // namespace phosphor