blob: b63853d4363a841e82f81fc0b9fcecab9ebef0d8 [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"
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -05005
6namespace openpower
7{
8namespace software
9{
10namespace updater
11{
12
Adriana Kobylak55f9e832017-05-14 16:13:00 -050013namespace fs = std::experimental::filesystem;
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050014namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
15
Michael Tritz9d25b602017-06-14 14:41:43 -050016constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
17constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
18
19void Activation::subscribeToSystemdSignals()
20{
21 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
22 SYSTEMD_OBJ_PATH,
23 SYSTEMD_INTERFACE,
24 "Subscribe");
25 this->bus.call_noreply(method);
26
27 return;
28}
29
Saqib Khan2af5c492017-07-17 16:15:13 -050030void Activation::createSymlinks()
31{
32 if (!fs::is_directory(PNOR_ACTIVE_PATH))
33 {
34 fs::create_directories(PNOR_ACTIVE_PATH);
35 }
36
37 // If the RW or RO active links exist, remove them and create new
38 // ones pointing to the active version.
39 if (fs::is_symlink(PNOR_RO_ACTIVE_PATH))
40 {
41 fs::remove(PNOR_RO_ACTIVE_PATH);
42 }
43 fs::create_directory_symlink(PNOR_RO_PREFIX + versionId,
44 PNOR_RO_ACTIVE_PATH);
45 if (fs::is_symlink(PNOR_RW_ACTIVE_PATH))
46 {
47 fs::remove(PNOR_RW_ACTIVE_PATH);
48 }
49 fs::create_directory_symlink(PNOR_RW_PREFIX + versionId,
50 PNOR_RW_ACTIVE_PATH);
51
52 // There is only one preserved directory as it is not tied to a
53 // version, so just create the link if it doesn't exist already
54 if (!fs::is_symlink(PNOR_PRSV_ACTIVE_PATH))
55 {
56 fs::create_directory_symlink(PNOR_PRSV,
57 PNOR_PRSV_ACTIVE_PATH);
58 }
59}
60
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050061auto Activation::activation(Activations value) ->
62 Activations
63{
Saqib Khan942df8a2017-06-01 14:09:27 -050064
65 if (value != softwareServer::Activation::Activations::Active)
66 {
67 redundancyPriority.reset(nullptr);
68 }
69
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050070 if (value == softwareServer::Activation::Activations::Activating)
71 {
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050072 softwareServer::Activation::activation(value);
73
Michael Tritz9d25b602017-06-14 14:41:43 -050074 if (squashfsLoaded == false && rwVolumesCreated == false)
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050075 {
Michael Tritz9d25b602017-06-14 14:41:43 -050076 // If the squashfs image has not yet been loaded to pnor and the
77 // RW volumes have not yet been created, we need to start the
78 // service files for each of those actions.
Saqib Khan1e9b7162017-04-18 10:21:59 -050079
Michael Tritz1793b642017-06-28 18:35:58 -050080 if (!activationProgress)
81 {
82 activationProgress = std::make_unique<ActivationProgress>(bus,
83 path);
84 }
85
Michael Tritz9d25b602017-06-14 14:41:43 -050086 if (!activationBlocksTransition)
Adriana Kobylak55f9e832017-05-14 16:13:00 -050087 {
Michael Tritz9d25b602017-06-14 14:41:43 -050088 activationBlocksTransition =
89 std::make_unique<ActivationBlocksTransition>(
Saqib Khan942df8a2017-06-01 14:09:27 -050090 bus,
91 path);
92 }
93
Michael Tritz9d25b602017-06-14 14:41:43 -050094 constexpr auto squashfsMountService =
95 "obmc-flash-bios-squashfsmount@";
96 auto squashfsMountServiceFile = std::string(squashfsMountService) +
97 versionId + ".service";
98 auto method = bus.new_method_call(
99 SYSTEMD_BUSNAME,
100 SYSTEMD_PATH,
101 SYSTEMD_INTERFACE,
102 "StartUnit");
103 method.append(squashfsMountServiceFile, "replace");
104 bus.call_noreply(method);
105
106 constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
107 auto ubimountServiceFile = std::string(ubimountService) +
108 versionId +
109 ".service";
110 method = bus.new_method_call(
111 SYSTEMD_BUSNAME,
112 SYSTEMD_PATH,
113 SYSTEMD_INTERFACE,
114 "StartUnit");
115 method.append(ubimountServiceFile, "replace");
116 bus.call_noreply(method);
117
Michael Tritz1793b642017-06-28 18:35:58 -0500118 activationProgress->progress(10);
119
Michael Tritz9d25b602017-06-14 14:41:43 -0500120 return softwareServer::Activation::activation(value);
121 }
122 else if (squashfsLoaded == true && rwVolumesCreated == true)
123 {
124 // Only when the squashfs image is finished loading AND the RW
125 // volumes have been created do we proceed with activation.
126
127 // The ubimount service files attemps to create the RW and Preserved
128 // UBI volumes. If the service fails, the mount dirs PNOR_PRSV
129 // and PNOR_RW_PREFIX_<versionid> won't be present. Check for the
130 // existence of those directories to validate the service file was
131 // successful, also for the existence of the RO directory where the
132 // image is supposed to reside.
133 if ((fs::is_directory(PNOR_PRSV)) &&
134 (fs::is_directory(PNOR_RW_PREFIX + versionId)) &&
135 (fs::is_directory(PNOR_RO_PREFIX + versionId)))
136 {
Michael Tritz1793b642017-06-28 18:35:58 -0500137 activationProgress->progress(90);
Saqib Khan2af5c492017-07-17 16:15:13 -0500138 createSymlinks();
Michael Tritz9d25b602017-06-14 14:41:43 -0500139
140 // Set Redundancy Priority before setting to Active
141 if (!redundancyPriority)
142 {
143 redundancyPriority =
144 std::make_unique<RedundancyPriority>(
145 bus,
Saqib Khan81bac882017-06-08 12:17:01 -0500146 path,
147 *this,
148 0);
Michael Tritz9d25b602017-06-14 14:41:43 -0500149 }
Michael Tritz1793b642017-06-28 18:35:58 -0500150
151 activationProgress->progress(100);
152
Saqib Khancb9df4e2017-06-26 11:06:07 -0500153 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500154 activationProgress.reset(nullptr);
155
Michael Tritz137dddd2017-07-25 09:55:40 -0500156 squashfsLoaded = false;
157 rwVolumesCreated = false;
158
159 //TODO: openbmc/openbmc#1843: Unsubscribe from systemd signals.
160
Michael Tritz9d25b602017-06-14 14:41:43 -0500161 return softwareServer::Activation::activation(
162 softwareServer::Activation::Activations::Active);
163 }
164 else
165 {
Saqib Khancb9df4e2017-06-26 11:06:07 -0500166 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500167 activationProgress.reset(nullptr);
Michael Tritz9d25b602017-06-14 14:41:43 -0500168 return softwareServer::Activation::activation(
169 softwareServer::Activation::Activations::Failed);
170 }
Adriana Kobylak55f9e832017-05-14 16:13:00 -0500171 }
172 else
173 {
Michael Tritz9d25b602017-06-14 14:41:43 -0500174 // If either the squashfs image has not yet been loaded or the RW
175 // volumes have not yet been created, the activation process is
176 // ongoing, so we return "Activating" status.
177 return softwareServer::Activation::activation(value);
Adriana Kobylak55f9e832017-05-14 16:13:00 -0500178 }
Adriana Kobylak692b5552017-04-17 14:02:58 -0500179 }
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500180 else
181 {
182 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500183 activationProgress.reset(nullptr);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500184 return softwareServer::Activation::activation(value);
185 }
186}
187
188auto Activation::requestedActivation(RequestedActivations value) ->
189 RequestedActivations
190{
Michael Tritz9d25b602017-06-14 14:41:43 -0500191 squashfsLoaded = false;
192 rwVolumesCreated = false;
193
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500194 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
195 (softwareServer::Activation::requestedActivation() !=
196 softwareServer::Activation::RequestedActivations::Active))
197 {
198 if ((softwareServer::Activation::activation() ==
199 softwareServer::Activation::Activations::Ready) ||
200 (softwareServer::Activation::activation() ==
201 softwareServer::Activation::Activations::Failed))
202 {
203 Activation::activation(
204 softwareServer::Activation::Activations::Activating);
205
206 }
207 }
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500208 return softwareServer::Activation::requestedActivation(value);
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500209}
210
Saqib Khan2021b4c2017-06-07 14:37:36 -0500211uint8_t RedundancyPriority::priority(uint8_t value)
212{
Saqib Khan81bac882017-06-08 12:17:01 -0500213 parent.parent.freePriority(value);
Saqib Khan2af5c492017-07-17 16:15:13 -0500214
215 if(parent.parent.isLowestPriority(value))
216 {
217 // Need to update the symlinks to point to Software Version
218 // with lowest priority.
219 parent.createSymlinks();
220 }
221
Saqib Khan2021b4c2017-06-07 14:37:36 -0500222 return softwareServer::RedundancyPriority::priority(value);
223}
224
Michael Tritz9d25b602017-06-14 14:41:43 -0500225void Activation::unitStateChange(sdbusplus::message::message& msg)
226{
227 uint32_t newStateID {};
228 sdbusplus::message::object_path newStateObjPath;
229 std::string newStateUnit{};
230 std::string newStateResult{};
231
232 //Read the msg and populate each variable
233 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
234
235 auto squashfsMountServiceFile =
236 "obmc-flash-bios-squashfsmount@" + versionId + ".service";
237
238 auto ubimountServiceFile =
239 "obmc-flash-bios-ubimount@" + versionId + ".service";
240
241 if(newStateUnit == squashfsMountServiceFile && newStateResult == "done")
242 {
Michael Tritz1793b642017-06-28 18:35:58 -0500243 squashfsLoaded = true;
244 activationProgress->progress(activationProgress->progress() + 20);
Michael Tritz9d25b602017-06-14 14:41:43 -0500245 }
246
247 if(newStateUnit == ubimountServiceFile && newStateResult == "done")
248 {
249 rwVolumesCreated = true;
Michael Tritz1793b642017-06-28 18:35:58 -0500250 activationProgress->progress(activationProgress->progress() + 50);
Michael Tritz9d25b602017-06-14 14:41:43 -0500251 }
252
253 if(squashfsLoaded && rwVolumesCreated)
254 {
255 Activation::activation(
256 softwareServer::Activation::Activations::Activating);
257 }
258
259 if((newStateUnit == squashfsMountServiceFile ||
260 newStateUnit == ubimountServiceFile) &&
261 (newStateResult == "failed" || newStateResult == "dependency"))
262 {
263 Activation::activation(softwareServer::Activation::Activations::Failed);
264 }
265
266 return;
267}
268
Leonel Gonzalez9c8adfa2017-07-12 11:08:40 -0500269void Activation::delete_()
270{
271 parent.erase(versionId);
272}
273
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500274} // namespace updater
275} // namespace software
276} // namespace openpower