blob: 4be19583d3a1e7873b7c8ebe05446000bf93319c [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
Saqib Khan2af5c492017-07-17 16:15:13 -050031void Activation::createSymlinks()
32{
33 if (!fs::is_directory(PNOR_ACTIVE_PATH))
34 {
35 fs::create_directories(PNOR_ACTIVE_PATH);
36 }
37
38 // If the RW or RO active links exist, remove them and create new
39 // ones pointing to the active version.
40 if (fs::is_symlink(PNOR_RO_ACTIVE_PATH))
41 {
42 fs::remove(PNOR_RO_ACTIVE_PATH);
43 }
44 fs::create_directory_symlink(PNOR_RO_PREFIX + versionId,
45 PNOR_RO_ACTIVE_PATH);
46 if (fs::is_symlink(PNOR_RW_ACTIVE_PATH))
47 {
48 fs::remove(PNOR_RW_ACTIVE_PATH);
49 }
50 fs::create_directory_symlink(PNOR_RW_PREFIX + versionId,
51 PNOR_RW_ACTIVE_PATH);
52
53 // There is only one preserved directory as it is not tied to a
54 // version, so just create the link if it doesn't exist already
55 if (!fs::is_symlink(PNOR_PRSV_ACTIVE_PATH))
56 {
57 fs::create_directory_symlink(PNOR_PRSV,
58 PNOR_PRSV_ACTIVE_PATH);
59 }
60}
61
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050062auto Activation::activation(Activations value) ->
63 Activations
64{
Saqib Khan942df8a2017-06-01 14:09:27 -050065
66 if (value != softwareServer::Activation::Activations::Active)
67 {
68 redundancyPriority.reset(nullptr);
69 }
70
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050071 if (value == softwareServer::Activation::Activations::Activating)
72 {
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050073 softwareServer::Activation::activation(value);
74
Michael Tritz9d25b602017-06-14 14:41:43 -050075 if (squashfsLoaded == false && rwVolumesCreated == false)
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050076 {
Michael Tritz9d25b602017-06-14 14:41:43 -050077 // If the squashfs image has not yet been loaded to pnor and the
78 // RW volumes have not yet been created, we need to start the
79 // service files for each of those actions.
Saqib Khan1e9b7162017-04-18 10:21:59 -050080
Michael Tritz1793b642017-06-28 18:35:58 -050081 if (!activationProgress)
82 {
83 activationProgress = std::make_unique<ActivationProgress>(bus,
84 path);
85 }
86
Michael Tritz9d25b602017-06-14 14:41:43 -050087 if (!activationBlocksTransition)
Adriana Kobylak55f9e832017-05-14 16:13:00 -050088 {
Michael Tritz9d25b602017-06-14 14:41:43 -050089 activationBlocksTransition =
90 std::make_unique<ActivationBlocksTransition>(
Saqib Khan942df8a2017-06-01 14:09:27 -050091 bus,
92 path);
93 }
94
Michael Tritz9d25b602017-06-14 14:41:43 -050095 constexpr auto squashfsMountService =
96 "obmc-flash-bios-squashfsmount@";
97 auto squashfsMountServiceFile = std::string(squashfsMountService) +
98 versionId + ".service";
99 auto method = bus.new_method_call(
100 SYSTEMD_BUSNAME,
101 SYSTEMD_PATH,
102 SYSTEMD_INTERFACE,
103 "StartUnit");
104 method.append(squashfsMountServiceFile, "replace");
105 bus.call_noreply(method);
106
107 constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
108 auto ubimountServiceFile = std::string(ubimountService) +
109 versionId +
110 ".service";
111 method = bus.new_method_call(
112 SYSTEMD_BUSNAME,
113 SYSTEMD_PATH,
114 SYSTEMD_INTERFACE,
115 "StartUnit");
116 method.append(ubimountServiceFile, "replace");
117 bus.call_noreply(method);
118
Michael Tritz1793b642017-06-28 18:35:58 -0500119 activationProgress->progress(10);
120
Michael Tritz9d25b602017-06-14 14:41:43 -0500121 return softwareServer::Activation::activation(value);
122 }
123 else if (squashfsLoaded == true && rwVolumesCreated == true)
124 {
125 // Only when the squashfs image is finished loading AND the RW
126 // volumes have been created do we proceed with activation.
127
128 // The ubimount service files attemps to create the RW and Preserved
129 // UBI volumes. If the service fails, the mount dirs PNOR_PRSV
130 // and PNOR_RW_PREFIX_<versionid> won't be present. Check for the
131 // existence of those directories to validate the service file was
132 // successful, also for the existence of the RO directory where the
133 // image is supposed to reside.
134 if ((fs::is_directory(PNOR_PRSV)) &&
135 (fs::is_directory(PNOR_RW_PREFIX + versionId)) &&
136 (fs::is_directory(PNOR_RO_PREFIX + versionId)))
137 {
Michael Tritz1793b642017-06-28 18:35:58 -0500138 activationProgress->progress(90);
Saqib Khan2af5c492017-07-17 16:15:13 -0500139 createSymlinks();
Michael Tritz9d25b602017-06-14 14:41:43 -0500140
141 // Set Redundancy Priority before setting to Active
142 if (!redundancyPriority)
143 {
144 redundancyPriority =
145 std::make_unique<RedundancyPriority>(
146 bus,
Saqib Khan81bac882017-06-08 12:17:01 -0500147 path,
148 *this,
149 0);
Michael Tritz9d25b602017-06-14 14:41:43 -0500150 }
Michael Tritz1793b642017-06-28 18:35:58 -0500151
152 activationProgress->progress(100);
153
Saqib Khancb9df4e2017-06-26 11:06:07 -0500154 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500155 activationProgress.reset(nullptr);
156
Michael Tritz137dddd2017-07-25 09:55:40 -0500157 squashfsLoaded = false;
158 rwVolumesCreated = false;
159
160 //TODO: openbmc/openbmc#1843: Unsubscribe from systemd signals.
161
Michael Tritz9d25b602017-06-14 14:41:43 -0500162 return softwareServer::Activation::activation(
163 softwareServer::Activation::Activations::Active);
164 }
165 else
166 {
Saqib Khancb9df4e2017-06-26 11:06:07 -0500167 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500168 activationProgress.reset(nullptr);
Michael Tritz9d25b602017-06-14 14:41:43 -0500169 return softwareServer::Activation::activation(
170 softwareServer::Activation::Activations::Failed);
171 }
Adriana Kobylak55f9e832017-05-14 16:13:00 -0500172 }
173 else
174 {
Michael Tritz9d25b602017-06-14 14:41:43 -0500175 // If either the squashfs image has not yet been loaded or the RW
176 // volumes have not yet been created, the activation process is
177 // ongoing, so we return "Activating" status.
178 return softwareServer::Activation::activation(value);
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 return softwareServer::Activation::activation(value);
186 }
187}
188
189auto Activation::requestedActivation(RequestedActivations value) ->
190 RequestedActivations
191{
Michael Tritz9d25b602017-06-14 14:41:43 -0500192 squashfsLoaded = false;
193 rwVolumesCreated = false;
194
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500195 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
196 (softwareServer::Activation::requestedActivation() !=
197 softwareServer::Activation::RequestedActivations::Active))
198 {
199 if ((softwareServer::Activation::activation() ==
200 softwareServer::Activation::Activations::Ready) ||
201 (softwareServer::Activation::activation() ==
202 softwareServer::Activation::Activations::Failed))
203 {
204 Activation::activation(
205 softwareServer::Activation::Activations::Activating);
206
207 }
208 }
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500209 return softwareServer::Activation::requestedActivation(value);
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500210}
211
Saqib Khan2021b4c2017-06-07 14:37:36 -0500212uint8_t RedundancyPriority::priority(uint8_t value)
213{
Saqib Khan81bac882017-06-08 12:17:01 -0500214 parent.parent.freePriority(value);
Saqib Khan2af5c492017-07-17 16:15:13 -0500215
216 if(parent.parent.isLowestPriority(value))
217 {
218 // Need to update the symlinks to point to Software Version
219 // with lowest priority.
220 parent.createSymlinks();
221 }
222
Michael Tritz60bc20f2017-07-29 23:32:21 -0500223 storeToFile(parent.versionId, value);
Saqib Khan2021b4c2017-06-07 14:37:36 -0500224 return softwareServer::RedundancyPriority::priority(value);
225}
226
Michael Tritz9d25b602017-06-14 14:41:43 -0500227void Activation::unitStateChange(sdbusplus::message::message& msg)
228{
229 uint32_t newStateID {};
230 sdbusplus::message::object_path newStateObjPath;
231 std::string newStateUnit{};
232 std::string newStateResult{};
233
234 //Read the msg and populate each variable
235 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
236
237 auto squashfsMountServiceFile =
238 "obmc-flash-bios-squashfsmount@" + versionId + ".service";
239
240 auto ubimountServiceFile =
241 "obmc-flash-bios-ubimount@" + versionId + ".service";
242
243 if(newStateUnit == squashfsMountServiceFile && newStateResult == "done")
244 {
Michael Tritz1793b642017-06-28 18:35:58 -0500245 squashfsLoaded = true;
246 activationProgress->progress(activationProgress->progress() + 20);
Michael Tritz9d25b602017-06-14 14:41:43 -0500247 }
248
249 if(newStateUnit == ubimountServiceFile && newStateResult == "done")
250 {
251 rwVolumesCreated = true;
Michael Tritz1793b642017-06-28 18:35:58 -0500252 activationProgress->progress(activationProgress->progress() + 50);
Michael Tritz9d25b602017-06-14 14:41:43 -0500253 }
254
255 if(squashfsLoaded && rwVolumesCreated)
256 {
257 Activation::activation(
258 softwareServer::Activation::Activations::Activating);
259 }
260
261 if((newStateUnit == squashfsMountServiceFile ||
262 newStateUnit == ubimountServiceFile) &&
263 (newStateResult == "failed" || newStateResult == "dependency"))
264 {
265 Activation::activation(softwareServer::Activation::Activations::Failed);
266 }
267
268 return;
269}
270
Leonel Gonzalez9c8adfa2017-07-12 11:08:40 -0500271void Activation::delete_()
272{
273 parent.erase(versionId);
274}
275
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500276} // namespace updater
277} // namespace software
278} // namespace openpower