blob: fd54ccd07002de4b3df80cc1ce49711c051c3a6c [file] [log] [blame]
Adriana Kobylak55f9e832017-05-14 16:13:00 -05001#include <experimental/filesystem>
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -05002#include "activation.hpp"
Adriana Kobylak692b5552017-04-17 14:02:58 -05003#include "config.h"
Saqib Khan81bac882017-06-08 12:17:01 -05004#include "item_updater.hpp"
Michael Tritz60bc20f2017-07-29 23:32:21 -05005#include "serialize.hpp"
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -05006
7namespace openpower
8{
9namespace software
10{
11namespace updater
12{
13
Adriana Kobylak55f9e832017-05-14 16:13:00 -050014namespace fs = std::experimental::filesystem;
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050015namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
16
Michael Tritz9d25b602017-06-14 14:41:43 -050017constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
18constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
19
20void Activation::subscribeToSystemdSignals()
21{
22 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
23 SYSTEMD_OBJ_PATH,
24 SYSTEMD_INTERFACE,
25 "Subscribe");
26 this->bus.call_noreply(method);
27
28 return;
29}
30
Michael Tritz1cb127f2017-07-26 15:40:38 -050031void Activation::unsubscribeFromSystemdSignals()
32{
33 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
34 SYSTEMD_OBJ_PATH,
35 SYSTEMD_INTERFACE,
36 "Unsubscribe");
37 this->bus.call_noreply(method);
38
39 return;
40}
41
Saqib Khan2af5c492017-07-17 16:15:13 -050042void Activation::createSymlinks()
43{
44 if (!fs::is_directory(PNOR_ACTIVE_PATH))
45 {
46 fs::create_directories(PNOR_ACTIVE_PATH);
47 }
48
49 // If the RW or RO active links exist, remove them and create new
50 // ones pointing to the active version.
51 if (fs::is_symlink(PNOR_RO_ACTIVE_PATH))
52 {
53 fs::remove(PNOR_RO_ACTIVE_PATH);
54 }
55 fs::create_directory_symlink(PNOR_RO_PREFIX + versionId,
56 PNOR_RO_ACTIVE_PATH);
57 if (fs::is_symlink(PNOR_RW_ACTIVE_PATH))
58 {
59 fs::remove(PNOR_RW_ACTIVE_PATH);
60 }
61 fs::create_directory_symlink(PNOR_RW_PREFIX + versionId,
62 PNOR_RW_ACTIVE_PATH);
63
64 // There is only one preserved directory as it is not tied to a
65 // version, so just create the link if it doesn't exist already
66 if (!fs::is_symlink(PNOR_PRSV_ACTIVE_PATH))
67 {
68 fs::create_directory_symlink(PNOR_PRSV,
69 PNOR_PRSV_ACTIVE_PATH);
70 }
71}
72
Michael Tritz1cb127f2017-07-26 15:40:38 -050073void Activation::startActivation()
74{
75 // Since the squashfs image has not yet been loaded to pnor and the
76 // RW volumes have not yet been created, we need to start the
77 // service files for each of those actions.
78
79 if (!activationProgress)
80 {
81 activationProgress = std::make_unique<ActivationProgress>(
82 bus, path);
83 }
84
85 if (!activationBlocksTransition)
86 {
87 activationBlocksTransition =
88 std::make_unique<ActivationBlocksTransition>(bus, path);
89 }
90
91 constexpr auto squashfsMountService =
92 "obmc-flash-bios-squashfsmount@";
93 auto squashfsMountServiceFile = std::string(squashfsMountService) +
94 versionId + ".service";
95 auto method = bus.new_method_call(
96 SYSTEMD_BUSNAME,
97 SYSTEMD_PATH,
98 SYSTEMD_INTERFACE,
99 "StartUnit");
100 method.append(squashfsMountServiceFile, "replace");
101 bus.call_noreply(method);
102
103 constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
104 auto ubimountServiceFile = std::string(ubimountService) +
105 versionId + ".service";
106 method = bus.new_method_call(
107 SYSTEMD_BUSNAME,
108 SYSTEMD_PATH,
109 SYSTEMD_INTERFACE,
110 "StartUnit");
111 method.append(ubimountServiceFile, "replace");
112 bus.call_noreply(method);
113
114 activationProgress->progress(10);
115}
116
117void Activation::finishActivation()
118{
119 activationProgress->progress(90);
120 createSymlinks();
121
122 // Set Redundancy Priority before setting to Active
123 if (!redundancyPriority)
124 {
125 redundancyPriority = std::make_unique<RedundancyPriority>(
126 bus, path, *this, 0);
127 }
128
129 activationProgress->progress(100);
130
131 activationBlocksTransition.reset(nullptr);
132 activationProgress.reset(nullptr);
133
134 squashfsLoaded = false;
135 rwVolumesCreated = false;
136 Activation::unsubscribeFromSystemdSignals();
137}
138
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500139auto Activation::activation(Activations value) ->
140 Activations
141{
Saqib Khan942df8a2017-06-01 14:09:27 -0500142
143 if (value != softwareServer::Activation::Activations::Active)
144 {
145 redundancyPriority.reset(nullptr);
146 }
147
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500148 if (value == softwareServer::Activation::Activations::Activating)
149 {
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500150 softwareServer::Activation::activation(value);
151
Michael Tritz9d25b602017-06-14 14:41:43 -0500152 if (squashfsLoaded == false && rwVolumesCreated == false)
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500153 {
Michael Tritz1cb127f2017-07-26 15:40:38 -0500154 Activation::startActivation();
Michael Tritz9d25b602017-06-14 14:41:43 -0500155 return softwareServer::Activation::activation(value);
156 }
157 else if (squashfsLoaded == true && rwVolumesCreated == true)
158 {
159 // Only when the squashfs image is finished loading AND the RW
Michael Tritz1cb127f2017-07-26 15:40:38 -0500160 // volumes have been created do we proceed with activation. To
161 // verify that this happened, we check for the mount dirs PNOR_PRSV
162 // and PNOR_RW_PREFIX_<versionid>, as well as the image dir R0.
Michael Tritz9d25b602017-06-14 14:41:43 -0500163
Michael Tritz9d25b602017-06-14 14:41:43 -0500164 if ((fs::is_directory(PNOR_PRSV)) &&
165 (fs::is_directory(PNOR_RW_PREFIX + versionId)) &&
166 (fs::is_directory(PNOR_RO_PREFIX + versionId)))
167 {
Michael Tritz1cb127f2017-07-26 15:40:38 -0500168 Activation::finishActivation();
Michael Tritz9d25b602017-06-14 14:41:43 -0500169 return softwareServer::Activation::activation(
170 softwareServer::Activation::Activations::Active);
171 }
172 else
173 {
Saqib Khancb9df4e2017-06-26 11:06:07 -0500174 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500175 activationProgress.reset(nullptr);
Michael Tritz9d25b602017-06-14 14:41:43 -0500176 return softwareServer::Activation::activation(
177 softwareServer::Activation::Activations::Failed);
178 }
Adriana Kobylak55f9e832017-05-14 16:13:00 -0500179 }
Adriana Kobylak692b5552017-04-17 14:02:58 -0500180 }
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500181 else
182 {
183 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500184 activationProgress.reset(nullptr);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500185 }
Michael Tritz1cb127f2017-07-26 15:40:38 -0500186
187 return softwareServer::Activation::activation(value);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500188}
189
190auto Activation::requestedActivation(RequestedActivations value) ->
191 RequestedActivations
192{
Michael Tritz9d25b602017-06-14 14:41:43 -0500193 squashfsLoaded = false;
194 rwVolumesCreated = false;
195
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500196 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
197 (softwareServer::Activation::requestedActivation() !=
198 softwareServer::Activation::RequestedActivations::Active))
199 {
200 if ((softwareServer::Activation::activation() ==
201 softwareServer::Activation::Activations::Ready) ||
202 (softwareServer::Activation::activation() ==
203 softwareServer::Activation::Activations::Failed))
204 {
205 Activation::activation(
206 softwareServer::Activation::Activations::Activating);
207
208 }
209 }
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500210 return softwareServer::Activation::requestedActivation(value);
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500211}
212
Saqib Khan2021b4c2017-06-07 14:37:36 -0500213uint8_t RedundancyPriority::priority(uint8_t value)
214{
Saqib Khanb8e7f312017-08-12 10:24:10 -0500215 parent.parent.freePriority(value, parent.versionId);
Saqib Khan2af5c492017-07-17 16:15:13 -0500216
217 if(parent.parent.isLowestPriority(value))
218 {
219 // Need to update the symlinks to point to Software Version
220 // with lowest priority.
221 parent.createSymlinks();
222 }
223
Michael Tritz60bc20f2017-07-29 23:32:21 -0500224 storeToFile(parent.versionId, value);
Saqib Khan2021b4c2017-06-07 14:37:36 -0500225 return softwareServer::RedundancyPriority::priority(value);
226}
227
Michael Tritz9d25b602017-06-14 14:41:43 -0500228void Activation::unitStateChange(sdbusplus::message::message& msg)
229{
230 uint32_t newStateID {};
231 sdbusplus::message::object_path newStateObjPath;
232 std::string newStateUnit{};
233 std::string newStateResult{};
234
235 //Read the msg and populate each variable
236 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
237
238 auto squashfsMountServiceFile =
239 "obmc-flash-bios-squashfsmount@" + versionId + ".service";
240
241 auto ubimountServiceFile =
242 "obmc-flash-bios-ubimount@" + versionId + ".service";
243
244 if(newStateUnit == squashfsMountServiceFile && newStateResult == "done")
245 {
Michael Tritz1793b642017-06-28 18:35:58 -0500246 squashfsLoaded = true;
247 activationProgress->progress(activationProgress->progress() + 20);
Michael Tritz9d25b602017-06-14 14:41:43 -0500248 }
249
250 if(newStateUnit == ubimountServiceFile && newStateResult == "done")
251 {
252 rwVolumesCreated = true;
Michael Tritz1793b642017-06-28 18:35:58 -0500253 activationProgress->progress(activationProgress->progress() + 50);
Michael Tritz9d25b602017-06-14 14:41:43 -0500254 }
255
256 if(squashfsLoaded && rwVolumesCreated)
257 {
258 Activation::activation(
259 softwareServer::Activation::Activations::Activating);
260 }
261
262 if((newStateUnit == squashfsMountServiceFile ||
263 newStateUnit == ubimountServiceFile) &&
264 (newStateResult == "failed" || newStateResult == "dependency"))
265 {
266 Activation::activation(softwareServer::Activation::Activations::Failed);
267 }
268
269 return;
270}
271
Leonel Gonzalez9c8adfa2017-07-12 11:08:40 -0500272void Activation::delete_()
273{
274 parent.erase(versionId);
275}
276
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500277} // namespace updater
278} // namespace software
279} // namespace openpower