blob: fd238d0c8659b237ba5f73090db248670038723b [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
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050030auto Activation::activation(Activations value) ->
31 Activations
32{
Saqib Khan942df8a2017-06-01 14:09:27 -050033
34 if (value != softwareServer::Activation::Activations::Active)
35 {
36 redundancyPriority.reset(nullptr);
37 }
38
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050039 if (value == softwareServer::Activation::Activations::Activating)
40 {
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050041 softwareServer::Activation::activation(value);
42
Michael Tritz9d25b602017-06-14 14:41:43 -050043 if (squashfsLoaded == false && rwVolumesCreated == false)
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050044 {
Michael Tritz9d25b602017-06-14 14:41:43 -050045 // If the squashfs image has not yet been loaded to pnor and the
46 // RW volumes have not yet been created, we need to start the
47 // service files for each of those actions.
Saqib Khan1e9b7162017-04-18 10:21:59 -050048
Michael Tritz1793b642017-06-28 18:35:58 -050049 if (!activationProgress)
50 {
51 activationProgress = std::make_unique<ActivationProgress>(bus,
52 path);
53 }
54
Michael Tritz9d25b602017-06-14 14:41:43 -050055 if (!activationBlocksTransition)
Adriana Kobylak55f9e832017-05-14 16:13:00 -050056 {
Michael Tritz9d25b602017-06-14 14:41:43 -050057 activationBlocksTransition =
58 std::make_unique<ActivationBlocksTransition>(
Saqib Khan942df8a2017-06-01 14:09:27 -050059 bus,
60 path);
61 }
62
Michael Tritz9d25b602017-06-14 14:41:43 -050063 constexpr auto squashfsMountService =
64 "obmc-flash-bios-squashfsmount@";
65 auto squashfsMountServiceFile = std::string(squashfsMountService) +
66 versionId + ".service";
67 auto method = bus.new_method_call(
68 SYSTEMD_BUSNAME,
69 SYSTEMD_PATH,
70 SYSTEMD_INTERFACE,
71 "StartUnit");
72 method.append(squashfsMountServiceFile, "replace");
73 bus.call_noreply(method);
74
75 constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
76 auto ubimountServiceFile = std::string(ubimountService) +
77 versionId +
78 ".service";
79 method = bus.new_method_call(
80 SYSTEMD_BUSNAME,
81 SYSTEMD_PATH,
82 SYSTEMD_INTERFACE,
83 "StartUnit");
84 method.append(ubimountServiceFile, "replace");
85 bus.call_noreply(method);
86
Michael Tritz1793b642017-06-28 18:35:58 -050087 activationProgress->progress(10);
88
Michael Tritz9d25b602017-06-14 14:41:43 -050089 return softwareServer::Activation::activation(value);
90 }
91 else if (squashfsLoaded == true && rwVolumesCreated == true)
92 {
93 // Only when the squashfs image is finished loading AND the RW
94 // volumes have been created do we proceed with activation.
95
96 // The ubimount service files attemps to create the RW and Preserved
97 // UBI volumes. If the service fails, the mount dirs PNOR_PRSV
98 // and PNOR_RW_PREFIX_<versionid> won't be present. Check for the
99 // existence of those directories to validate the service file was
100 // successful, also for the existence of the RO directory where the
101 // image is supposed to reside.
102 if ((fs::is_directory(PNOR_PRSV)) &&
103 (fs::is_directory(PNOR_RW_PREFIX + versionId)) &&
104 (fs::is_directory(PNOR_RO_PREFIX + versionId)))
105 {
Michael Tritz1793b642017-06-28 18:35:58 -0500106 activationProgress->progress(90);
107
Michael Tritz9d25b602017-06-14 14:41:43 -0500108 if (!fs::is_directory(PNOR_ACTIVE_PATH))
109 {
110 fs::create_directories(PNOR_ACTIVE_PATH);
111 }
112
113 // If the RW or RO active links exist, remove them and create new
114 // ones pointing to the active version.
115 if (fs::is_symlink(PNOR_RO_ACTIVE_PATH))
116 {
117 fs::remove(PNOR_RO_ACTIVE_PATH);
118 }
119 fs::create_directory_symlink(PNOR_RO_PREFIX + versionId,
120 PNOR_RO_ACTIVE_PATH);
121 if (fs::is_symlink(PNOR_RW_ACTIVE_PATH))
122 {
123 fs::remove(PNOR_RW_ACTIVE_PATH);
124 }
125 fs::create_directory_symlink(PNOR_RW_PREFIX + versionId,
126 PNOR_RW_ACTIVE_PATH);
127
128 // There is only one preserved directory as it is not tied to a
129 // version, so just create the link if it doesn't exist already.
130 if (!fs::is_symlink(PNOR_PRSV_ACTIVE_PATH))
131 {
132 fs::create_directory_symlink(PNOR_PRSV,
133 PNOR_PRSV_ACTIVE_PATH);
134 }
135
136 // Set Redundancy Priority before setting to Active
137 if (!redundancyPriority)
138 {
139 redundancyPriority =
140 std::make_unique<RedundancyPriority>(
141 bus,
Saqib Khan81bac882017-06-08 12:17:01 -0500142 path,
143 *this,
144 0);
Michael Tritz9d25b602017-06-14 14:41:43 -0500145 }
Michael Tritz1793b642017-06-28 18:35:58 -0500146
147 activationProgress->progress(100);
148
Saqib Khancb9df4e2017-06-26 11:06:07 -0500149 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500150 activationProgress.reset(nullptr);
151
Michael Tritz137dddd2017-07-25 09:55:40 -0500152 squashfsLoaded = false;
153 rwVolumesCreated = false;
154
155 //TODO: openbmc/openbmc#1843: Unsubscribe from systemd signals.
156
Michael Tritz9d25b602017-06-14 14:41:43 -0500157 return softwareServer::Activation::activation(
158 softwareServer::Activation::Activations::Active);
159 }
160 else
161 {
Saqib Khancb9df4e2017-06-26 11:06:07 -0500162 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500163 activationProgress.reset(nullptr);
Michael Tritz9d25b602017-06-14 14:41:43 -0500164 return softwareServer::Activation::activation(
165 softwareServer::Activation::Activations::Failed);
166 }
Adriana Kobylak55f9e832017-05-14 16:13:00 -0500167 }
168 else
169 {
Michael Tritz9d25b602017-06-14 14:41:43 -0500170 // If either the squashfs image has not yet been loaded or the RW
171 // volumes have not yet been created, the activation process is
172 // ongoing, so we return "Activating" status.
173 return softwareServer::Activation::activation(value);
Adriana Kobylak55f9e832017-05-14 16:13:00 -0500174 }
Adriana Kobylak692b5552017-04-17 14:02:58 -0500175 }
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500176 else
177 {
178 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500179 activationProgress.reset(nullptr);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500180 return softwareServer::Activation::activation(value);
181 }
182}
183
184auto Activation::requestedActivation(RequestedActivations value) ->
185 RequestedActivations
186{
Michael Tritz9d25b602017-06-14 14:41:43 -0500187 squashfsLoaded = false;
188 rwVolumesCreated = false;
189
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500190 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
191 (softwareServer::Activation::requestedActivation() !=
192 softwareServer::Activation::RequestedActivations::Active))
193 {
194 if ((softwareServer::Activation::activation() ==
195 softwareServer::Activation::Activations::Ready) ||
196 (softwareServer::Activation::activation() ==
197 softwareServer::Activation::Activations::Failed))
198 {
199 Activation::activation(
200 softwareServer::Activation::Activations::Activating);
201
202 }
203 }
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500204 return softwareServer::Activation::requestedActivation(value);
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500205}
206
Saqib Khan2021b4c2017-06-07 14:37:36 -0500207uint8_t RedundancyPriority::priority(uint8_t value)
208{
Saqib Khan81bac882017-06-08 12:17:01 -0500209 parent.parent.freePriority(value);
Saqib Khan2021b4c2017-06-07 14:37:36 -0500210 return softwareServer::RedundancyPriority::priority(value);
211}
212
Michael Tritz9d25b602017-06-14 14:41:43 -0500213void Activation::unitStateChange(sdbusplus::message::message& msg)
214{
215 uint32_t newStateID {};
216 sdbusplus::message::object_path newStateObjPath;
217 std::string newStateUnit{};
218 std::string newStateResult{};
219
220 //Read the msg and populate each variable
221 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
222
223 auto squashfsMountServiceFile =
224 "obmc-flash-bios-squashfsmount@" + versionId + ".service";
225
226 auto ubimountServiceFile =
227 "obmc-flash-bios-ubimount@" + versionId + ".service";
228
229 if(newStateUnit == squashfsMountServiceFile && newStateResult == "done")
230 {
Michael Tritz1793b642017-06-28 18:35:58 -0500231 squashfsLoaded = true;
232 activationProgress->progress(activationProgress->progress() + 20);
Michael Tritz9d25b602017-06-14 14:41:43 -0500233 }
234
235 if(newStateUnit == ubimountServiceFile && newStateResult == "done")
236 {
237 rwVolumesCreated = true;
Michael Tritz1793b642017-06-28 18:35:58 -0500238 activationProgress->progress(activationProgress->progress() + 50);
Michael Tritz9d25b602017-06-14 14:41:43 -0500239 }
240
241 if(squashfsLoaded && rwVolumesCreated)
242 {
243 Activation::activation(
244 softwareServer::Activation::Activations::Activating);
245 }
246
247 if((newStateUnit == squashfsMountServiceFile ||
248 newStateUnit == ubimountServiceFile) &&
249 (newStateResult == "failed" || newStateResult == "dependency"))
250 {
251 Activation::activation(softwareServer::Activation::Activations::Failed);
252 }
253
254 return;
255}
256
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500257} // namespace updater
258} // namespace software
259} // namespace openpower