blob: 3dfa2bc64a52005e637d8c07682554133d3f6cae [file] [log] [blame]
Saqib Khan35e83f32017-05-22 11:37:32 -05001#include <fstream>
Gunnar Millsec1b41c2017-05-02 12:20:36 -05002#include <string>
Gunnar Mills2ce7da22017-05-04 15:37:56 -05003#include <phosphor-logging/log.hpp>
Gunnar Millsec1b41c2017-05-02 12:20:36 -05004#include "config.h"
Gunnar Mills2ce7da22017-05-04 15:37:56 -05005#include "item_updater.hpp"
6#include "xyz/openbmc_project/Software/Version/server.hpp"
Saqib Khan35e83f32017-05-22 11:37:32 -05007#include <experimental/filesystem>
Saqib Khan705f1bf2017-06-09 23:58:38 -05008#include "version.hpp"
Saqib Khan5d532672017-08-09 10:44:50 -05009#include "serialize.hpp"
Gunnar Millsec1b41c2017-05-02 12:20:36 -050010
11namespace phosphor
12{
13namespace software
14{
15namespace updater
16{
17
Gunnar Mills2ce7da22017-05-04 15:37:56 -050018// When you see server:: you know we're referencing our base class
19namespace server = sdbusplus::xyz::openbmc_project::Software::server;
Michael Tritz0129d922017-08-10 19:33:46 -050020namespace control = sdbusplus::xyz::openbmc_project::Control::server;
Gunnar Mills2ce7da22017-05-04 15:37:56 -050021
22using namespace phosphor::logging;
Saqib Khan35e83f32017-05-22 11:37:32 -050023namespace fs = std::experimental::filesystem;
24
Gunnar Mills9a782242017-08-22 16:23:15 -050025const std::vector<std::string> bmcImages = { "image-kernel",
26 "image-rofs",
27 "image-rwfs",
28 "image-u-boot" };
Gunnar Mills2ce7da22017-05-04 15:37:56 -050029
Patrick Williamse75d10f2017-05-30 16:56:32 -050030void ItemUpdater::createActivation(sdbusplus::message::message& msg)
Gunnar Millsec1b41c2017-05-02 12:20:36 -050031{
Saqib Khan84a0e692017-06-28 17:27:01 -050032
33 using SVersion = server::Version;
34 using VersionPurpose = SVersion::VersionPurpose;
Gunnar Mills9a782242017-08-22 16:23:15 -050035 using VersionClass = phosphor::software::manager::Version;
Saqib Khan84a0e692017-06-28 17:27:01 -050036 namespace mesg = sdbusplus::message;
37 namespace variant_ns = mesg::variant_ns;
38
39 mesg::object_path objPath;
40 auto purpose = VersionPurpose::Unknown;
Saqib Khan705f1bf2017-06-09 23:58:38 -050041 std::string version;
Gunnar Mills2ce7da22017-05-04 15:37:56 -050042 std::map<std::string,
Patrick Williamse75d10f2017-05-30 16:56:32 -050043 std::map<std::string,
Saqib Khan84a0e692017-06-28 17:27:01 -050044 mesg::variant<std::string>>> interfaces;
Patrick Williamse75d10f2017-05-30 16:56:32 -050045 msg.read(objPath, interfaces);
Gunnar Mills2ce7da22017-05-04 15:37:56 -050046 std::string path(std::move(objPath));
Saqib Khan19177d32017-06-20 08:11:49 -050047 std::string filePath;
Gunnar Mills2ce7da22017-05-04 15:37:56 -050048
49 for (const auto& intf : interfaces)
50 {
Saqib Khan705f1bf2017-06-09 23:58:38 -050051 if (intf.first == VERSION_IFACE)
Gunnar Mills2ce7da22017-05-04 15:37:56 -050052 {
Saqib Khan705f1bf2017-06-09 23:58:38 -050053 for (const auto& property : intf.second)
Gunnar Mills2ce7da22017-05-04 15:37:56 -050054 {
Saqib Khan705f1bf2017-06-09 23:58:38 -050055 if (property.first == "Purpose")
Gunnar Mills2ce7da22017-05-04 15:37:56 -050056 {
Saqib Khan84a0e692017-06-28 17:27:01 -050057 auto value = SVersion::convertVersionPurposeFromString(
Gunnar Mills9a782242017-08-22 16:23:15 -050058 variant_ns::get<std::string>(property.second));
Saqib Khan84a0e692017-06-28 17:27:01 -050059 if (value == VersionPurpose::BMC ||
60 value == VersionPurpose::System)
61 {
62 purpose = value;
63 }
Saqib Khan705f1bf2017-06-09 23:58:38 -050064 }
65 else if (property.first == "Version")
66 {
Saqib Khan84a0e692017-06-28 17:27:01 -050067 version = variant_ns::get<std::string>(property.second);
Gunnar Mills2ce7da22017-05-04 15:37:56 -050068 }
69 }
70 }
Saqib Khan19177d32017-06-20 08:11:49 -050071 else if (intf.first == FILEPATH_IFACE)
72 {
73 for (const auto& property : intf.second)
74 {
75 if (property.first == "Path")
76 {
Saqib Khan84a0e692017-06-28 17:27:01 -050077 filePath = variant_ns::get<std::string>(property.second);
Saqib Khan19177d32017-06-20 08:11:49 -050078 }
79 }
80 }
Gunnar Mills2ce7da22017-05-04 15:37:56 -050081 }
Saqib Khan705f1bf2017-06-09 23:58:38 -050082 if (version.empty() ||
Saqib Khan19177d32017-06-20 08:11:49 -050083 filePath.empty() ||
Saqib Khan84a0e692017-06-28 17:27:01 -050084 purpose == VersionPurpose::Unknown)
Saqib Khan705f1bf2017-06-09 23:58:38 -050085 {
86 return;
87 }
Gunnar Mills2ce7da22017-05-04 15:37:56 -050088
89 // Version id is the last item in the path
90 auto pos = path.rfind("/");
91 if (pos == std::string::npos)
92 {
93 log<level::ERR>("No version id found in object path",
94 entry("OBJPATH=%s", path));
Patrick Williamse75d10f2017-05-30 16:56:32 -050095 return;
Gunnar Mills2ce7da22017-05-04 15:37:56 -050096 }
97
98 auto versionId = path.substr(pos + 1);
99
Patrick Williamse75d10f2017-05-30 16:56:32 -0500100 if (activations.find(versionId) == activations.end())
Gunnar Mills2ce7da22017-05-04 15:37:56 -0500101 {
Saqib Khan35e83f32017-05-22 11:37:32 -0500102 // Determine the Activation state by processing the given image dir.
103 auto activationState = server::Activation::Activations::Invalid;
Gunnar Mills9a782242017-08-22 16:23:15 -0500104 ItemUpdater::ActivationStatus result =
105 ItemUpdater::validateSquashFSImage(filePath);
Gunnar Mills43b25cd2017-09-07 13:19:34 -0500106 AssociationList associations = {};
107
Saqib Khan35e83f32017-05-22 11:37:32 -0500108 if (result == ItemUpdater::ActivationStatus::ready)
109 {
110 activationState = server::Activation::Activations::Ready;
Gunnar Mills43b25cd2017-09-07 13:19:34 -0500111 // Create an association to the BMC inventory item
112 associations.emplace_back(std::make_tuple(
113 ACTIVATION_FWD_ASSOCIATION,
114 ACTIVATION_REV_ASSOCIATION,
115 bmcInventoryPath));
Saqib Khan35e83f32017-05-22 11:37:32 -0500116 }
Gunnar Millsb60add12017-08-24 16:41:42 -0500117
Saqib Khan35e83f32017-05-22 11:37:32 -0500118 activations.insert(std::make_pair(
Saqib Khan705f1bf2017-06-09 23:58:38 -0500119 versionId,
120 std::make_unique<Activation>(
121 bus,
122 path,
Saqib Khan4c1aec02017-07-06 11:46:13 -0500123 *this,
Saqib Khan35e83f32017-05-22 11:37:32 -0500124 versionId,
Gunnar Millsb60add12017-08-24 16:41:42 -0500125 activationState,
126 associations)));
Saqib Khan705f1bf2017-06-09 23:58:38 -0500127 versions.insert(std::make_pair(
128 versionId,
Gunnar Mills9a782242017-08-22 16:23:15 -0500129 std::make_unique<VersionClass>(
Saqib Khan705f1bf2017-06-09 23:58:38 -0500130 bus,
131 path,
132 version,
133 purpose,
Eddie James9440f492017-08-30 11:34:16 -0500134 filePath)));
Gunnar Mills2ce7da22017-05-04 15:37:56 -0500135 }
Saqib Khan7b5010f2017-08-09 10:03:11 -0500136 else
137 {
138 log<level::INFO>("Software Object with the same version already exists",
Gunnar Mills9a782242017-08-22 16:23:15 -0500139 entry("VERSION_ID=%s", versionId));
Saqib Khan7b5010f2017-08-09 10:03:11 -0500140 }
Patrick Williamse75d10f2017-05-30 16:56:32 -0500141 return;
Gunnar Millsec1b41c2017-05-02 12:20:36 -0500142}
143
Saqib Khanba239882017-05-26 08:41:54 -0500144void ItemUpdater::processBMCImage()
145{
Gunnar Mills88e8a322017-09-13 11:09:28 -0500146 using VersionClass = phosphor::software::manager::Version;
147 // Read os-release from /etc/ to get the functional BMC version
148 auto functionalVersion = VersionClass::getBMCVersion(OS_RELEASE_FILE);
149
Saqib Khan1eef62d2017-08-10 15:29:34 -0500150 // Read os-release from folders under /media/ to get
151 // BMC Software Versions.
152 for(const auto& iter : fs::directory_iterator(MEDIA_DIR))
153 {
154 auto activationState = server::Activation::Activations::Active;
Saqib Khan6fab70d2017-09-07 00:13:50 -0500155 static const auto BMC_RO_PREFIX_LEN = strlen(BMC_ROFS_PREFIX);
Saqib Khan1eef62d2017-08-10 15:29:34 -0500156
157 // Check if the BMC_RO_PREFIXis the prefix of the iter.path
158 if (0 == iter.path().native().compare(0, BMC_RO_PREFIX_LEN,
Saqib Khan6fab70d2017-09-07 00:13:50 -0500159 BMC_ROFS_PREFIX))
Saqib Khan1eef62d2017-08-10 15:29:34 -0500160 {
Saqib Khan021c3652017-09-26 12:11:02 -0500161 // The versionId is extracted from the path
162 // for example /media/ro-2a1022fe.
163 auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
Saqib Khan1eef62d2017-08-10 15:29:34 -0500164 auto osRelease = iter.path() / OS_RELEASE_FILE;
165 if (!fs::is_regular_file(osRelease))
166 {
167 log<level::ERR>("Failed to read osRelease\n",
168 entry("FileName=%s", osRelease.string()));
Saqib Khan021c3652017-09-26 12:11:02 -0500169 ItemUpdater::erase(id);
170 continue;
Saqib Khan1eef62d2017-08-10 15:29:34 -0500171 }
Gunnar Mills88e8a322017-09-13 11:09:28 -0500172 auto version = VersionClass::getBMCVersion(osRelease);
Saqib Khan1eef62d2017-08-10 15:29:34 -0500173 if (version.empty())
174 {
175 log<level::ERR>("Failed to read version from osRelease",
176 entry("FILENAME=%s", osRelease.string()));
177 activationState = server::Activation::Activations::Invalid;
178 }
Saqib Khan021c3652017-09-26 12:11:02 -0500179
Saqib Khan1eef62d2017-08-10 15:29:34 -0500180 auto purpose = server::Version::VersionPurpose::BMC;
181 auto path = fs::path(SOFTWARE_OBJPATH) / id;
182
Gunnar Mills88e8a322017-09-13 11:09:28 -0500183 // Create functional association if this is the functional version
184 if (version.compare(functionalVersion) == 0)
185 {
186 createFunctionalAssociation(path);
187 }
188
Gunnar Mills43b25cd2017-09-07 13:19:34 -0500189 AssociationList associations = {};
190
191 if (activationState == server::Activation::Activations::Active)
192 {
193 // Create an association to the BMC inventory item
194 associations.emplace_back(std::make_tuple(
195 ACTIVATION_FWD_ASSOCIATION,
196 ACTIVATION_REV_ASSOCIATION,
197 bmcInventoryPath));
198
199 // Create an active association since this image is active
200 createActiveAssociation(path);
201 }
202
Adriana Kobylakee590c72017-09-26 15:16:06 -0500203 // Create Version instance for this version.
204 auto versionPtr = std::make_unique<VersionClass>(
205 bus,
206 path,
207 version,
208 purpose,
209 "");
210 auto isVersionFunctional = versionPtr->isFunctional();
211 versions.insert(std::make_pair(
212 id,
213 std::move(versionPtr)));
214
Saqib Khan1eef62d2017-08-10 15:29:34 -0500215 // Create Activation instance for this version.
216 activations.insert(std::make_pair(
217 id,
218 std::make_unique<Activation>(
219 bus,
220 path,
221 *this,
222 id,
223 server::Activation::Activations::Active,
224 associations)));
225
226 // If Active, create RedundancyPriority instance for this version.
227 if (activationState == server::Activation::Activations::Active)
228 {
229 uint8_t priority = std::numeric_limits<uint8_t>::max();
230 if (!restoreFromFile(id, priority))
231 {
Adriana Kobylakee590c72017-09-26 15:16:06 -0500232 if (isVersionFunctional)
233 {
234 priority = 0;
235 }
236 else
237 {
238 log<level::ERR>("Unable to restore priority from file.",
239 entry("VERSIONID=%s", id));
240 }
Saqib Khan1eef62d2017-08-10 15:29:34 -0500241 }
242 activations.find(id)->second->redundancyPriority =
243 std::make_unique<RedundancyPriority>(
Saqib Khanba239882017-05-26 08:41:54 -0500244 bus,
245 path,
Saqib Khan1eef62d2017-08-10 15:29:34 -0500246 *(activations.find(id)->second),
247 priority);
248 }
Saqib Khan1eef62d2017-08-10 15:29:34 -0500249 }
250 }
Saqib Khanba239882017-05-26 08:41:54 -0500251 return;
252}
253
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500254void ItemUpdater::erase(std::string entryId)
255{
Eddie James6d873712017-09-01 11:29:07 -0500256 // Find entry in versions map
257 auto it = versions.find(entryId);
258 if (it != versions.end())
259 {
260 if (it->second->isFunctional())
261 {
262 log<level::ERR>(("Error: Version " + entryId + \
263 " is currently running on the BMC." \
264 " Unable to remove.").c_str());
265 return;
266 }
267
268 // Delete ReadOnly partitions if it's not active
269 removeReadOnlyPartition(entryId);
270 removeFile(entryId);
271 }
272 else
273 {
274 // Delete ReadOnly partitions even if we can't find the version
275 removeReadOnlyPartition(entryId);
276 removeFile(entryId);
277
278 log<level::ERR>(("Error: Failed to find version " + entryId + \
279 " in item updater versions map." \
280 " Unable to remove.").c_str());
281 return;
282 }
Saqib Khan1eef62d2017-08-10 15:29:34 -0500283
284 // Remove the priority environment variable.
285 auto serviceFile = "obmc-flash-bmc-setenv@" + entryId + ".service";
286 auto method = bus.new_method_call(
287 SYSTEMD_BUSNAME,
288 SYSTEMD_PATH,
289 SYSTEMD_INTERFACE,
290 "StartUnit");
291 method.append(serviceFile, "replace");
292 bus.call_noreply(method);
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500293
294 // Removing entry in versions map
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500295 this->versions.erase(entryId);
296
297 // Removing entry in activations map
298 auto ita = activations.find(entryId);
299 if (ita == activations.end())
300 {
301 log<level::ERR>(("Error: Failed to find version " + entryId + \
Gunnar Mills9a782242017-08-22 16:23:15 -0500302 " in item updater activations map." \
303 " Unable to remove.").c_str());
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500304 return;
305 }
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500306
307 this->activations.erase(entryId);
308}
309
Michael Tritzbc1bf3a2017-09-18 16:38:23 -0500310void ItemUpdater::deleteAll()
311{
312 std::vector<std::string> deletableVersions;
313
314 for (const auto& versionIt : versions)
315 {
316 if (!versionIt.second->isFunctional())
317 {
318 deletableVersions.push_back(versionIt.first);
319 }
320 }
321
322 for (const auto& deletableIt : deletableVersions)
323 {
324 ItemUpdater::erase(deletableIt);
325 }
326
327 // Remove any volumes that do not match current versions.
328 auto method = bus.new_method_call(
329 SYSTEMD_BUSNAME,
330 SYSTEMD_PATH,
331 SYSTEMD_INTERFACE,
332 "StartUnit");
333 method.append("obmc-flash-bmc-cleanup.service", "replace");
334 bus.call_noreply(method);
335}
336
Saqib Khan35e83f32017-05-22 11:37:32 -0500337ItemUpdater::ActivationStatus ItemUpdater::validateSquashFSImage(
Gunnar Mills9a782242017-08-22 16:23:15 -0500338 const std::string& filePath)
Saqib Khan35e83f32017-05-22 11:37:32 -0500339{
Michael Tritzb1cfdf92017-08-14 14:33:30 -0500340 bool invalid = false;
Saqib Khan35e83f32017-05-22 11:37:32 -0500341
Michael Tritzb1cfdf92017-08-14 14:33:30 -0500342 for (auto& bmcImage : bmcImages)
Saqib Khan35e83f32017-05-22 11:37:32 -0500343 {
Michael Tritzb1cfdf92017-08-14 14:33:30 -0500344 fs::path file(filePath);
345 file /= bmcImage;
346 std::ifstream efile(file.c_str());
347 if (efile.good() != 1)
348 {
349 log<level::ERR>("Failed to find the BMC image.",
Gunnar Mills9a782242017-08-22 16:23:15 -0500350 entry("IMAGE=%s", bmcImage.c_str()));
Michael Tritzb1cfdf92017-08-14 14:33:30 -0500351 invalid = true;
352 }
Saqib Khan35e83f32017-05-22 11:37:32 -0500353 }
Michael Tritzb1cfdf92017-08-14 14:33:30 -0500354
355 if (invalid)
Saqib Khan35e83f32017-05-22 11:37:32 -0500356 {
Saqib Khan35e83f32017-05-22 11:37:32 -0500357 return ItemUpdater::ActivationStatus::invalid;
358 }
Michael Tritzb1cfdf92017-08-14 14:33:30 -0500359
360 return ItemUpdater::ActivationStatus::ready;
Saqib Khan35e83f32017-05-22 11:37:32 -0500361}
362
Saqib Khanb9da6632017-09-13 09:48:37 -0500363void ItemUpdater::freePriority(uint8_t value, const std::string& versionId)
Saqib Khan4c1aec02017-07-06 11:46:13 -0500364{
365 //TODO openbmc/openbmc#1896 Improve the performance of this function
366 for (const auto& intf : activations)
367 {
Gunnar Mills9a782242017-08-22 16:23:15 -0500368 if (intf.second->redundancyPriority)
Saqib Khan4c1aec02017-07-06 11:46:13 -0500369 {
Saqib Khanb9da6632017-09-13 09:48:37 -0500370 if (intf.second->redundancyPriority.get()->priority() == value &&
371 intf.second->versionId != versionId)
Saqib Khan4c1aec02017-07-06 11:46:13 -0500372 {
Gunnar Mills9a782242017-08-22 16:23:15 -0500373 intf.second->redundancyPriority.get()->priority(value + 1);
Saqib Khan4c1aec02017-07-06 11:46:13 -0500374 }
375 }
376 }
377}
378
Michael Tritz37a59042017-07-12 13:44:53 -0500379void ItemUpdater::reset()
380{
381 // Mark the read-write partition for recreation upon reboot.
382 auto method = bus.new_method_call(
383 SYSTEMD_BUSNAME,
384 SYSTEMD_PATH,
385 SYSTEMD_INTERFACE,
386 "StartUnit");
Michael Tritz0129d922017-08-10 19:33:46 -0500387 method.append("obmc-flash-bmc-setenv@rwreset\\x3dtrue.service", "replace");
Michael Tritz37a59042017-07-12 13:44:53 -0500388 bus.call_noreply(method);
389
390 log<level::INFO>("BMC factory reset will take effect upon reboot.");
391
392 return;
393}
394
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500395void ItemUpdater::removeReadOnlyPartition(std::string versionId)
396{
397 auto serviceFile = "obmc-flash-bmc-ubiro-remove@" + versionId +
398 ".service";
399
400 // Remove the read-only partitions.
401 auto method = bus.new_method_call(
402 SYSTEMD_BUSNAME,
403 SYSTEMD_PATH,
404 SYSTEMD_INTERFACE,
405 "StartUnit");
406 method.append(serviceFile, "replace");
407 bus.call_noreply(method);
408}
409
Michael Tritz0129d922017-08-10 19:33:46 -0500410bool ItemUpdater::fieldModeEnabled(bool value)
411{
412 // enabling field mode is intended to be one way: false -> true
413 if (value && !control::FieldMode::fieldModeEnabled())
414 {
415 control::FieldMode::fieldModeEnabled(value);
416
417 auto method = bus.new_method_call(
418 SYSTEMD_BUSNAME,
419 SYSTEMD_PATH,
420 SYSTEMD_INTERFACE,
421 "StartUnit");
422 method.append("obmc-flash-bmc-setenv@fieldmode\\x3dtrue.service",
Gunnar Mills9a782242017-08-22 16:23:15 -0500423 "replace");
Michael Tritz0129d922017-08-10 19:33:46 -0500424 bus.call_noreply(method);
425
426 method = bus.new_method_call(
427 SYSTEMD_BUSNAME,
428 SYSTEMD_PATH,
429 SYSTEMD_INTERFACE,
430 "StopUnit");
431 method.append("usr-local.mount", "replace");
432 bus.call_noreply(method);
433
434 std::vector<std::string> usrLocal = {"usr-local.mount"};
435
436 method = bus.new_method_call(
437 SYSTEMD_BUSNAME,
438 SYSTEMD_PATH,
439 SYSTEMD_INTERFACE,
440 "MaskUnitFiles");
441 method.append(usrLocal, false, true);
442 bus.call_noreply(method);
443 }
444
445 return control::FieldMode::fieldModeEnabled();
446}
447
448void ItemUpdater::restoreFieldModeStatus()
449{
450 std::ifstream input("/run/fw_env");
451 std::string envVar;
452 std::getline(input, envVar);
453
Gunnar Mills9a782242017-08-22 16:23:15 -0500454 if (envVar.find("fieldmode=true") != std::string::npos)
Michael Tritz0129d922017-08-10 19:33:46 -0500455 {
456 ItemUpdater::fieldModeEnabled(true);
457 }
458}
459
Gunnar Millsb60add12017-08-24 16:41:42 -0500460void ItemUpdater::setBMCInventoryPath()
461{
462 //TODO: openbmc/openbmc#1786 - Get the BMC path by looking for objects
463 // that implement the BMC inventory interface
464 auto depth = 0;
465 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME,
466 MAPPER_PATH,
467 MAPPER_INTERFACE,
468 "GetSubTreePaths");
469
470 mapperCall.append(CHASSIS_INVENTORY_PATH);
471 mapperCall.append(depth);
472
473 // TODO: openbmc/openbmc#2226 - Add Inventory Item filter when
474 // mapper is fixed.
475 std::vector<std::string> filter = {};
476 mapperCall.append(filter);
477
478 auto response = bus.call(mapperCall);
479 if (response.is_method_error())
480 {
481 log<level::ERR>("Error in mapper GetSubTreePath");
482 return;
483 }
484
485 using ObjectPaths = std::vector<std::string>;
486 ObjectPaths result;
487 response.read(result);
488
489 if (result.empty())
490 {
491 log<level::ERR>("Invalid response from mapper");
492 return;
493 }
494
495 for (auto& iter : result)
496 {
497 const auto& path = iter;
498 if (path.substr(path.find_last_of('/') + 1).compare("bmc") == 0)
499 {
500 bmcInventoryPath = path;
501 return;
502 }
503 }
504}
505
Gunnar Millsf10b2322017-09-21 15:31:55 -0500506void ItemUpdater::createActiveAssociation(const std::string& path)
Gunnar Millsded875d2017-08-28 16:44:52 -0500507{
508 assocs.emplace_back(std::make_tuple(ACTIVE_FWD_ASSOCIATION,
509 ACTIVE_REV_ASSOCIATION,
510 path));
511 associations(assocs);
512}
513
Gunnar Mills88e8a322017-09-13 11:09:28 -0500514void ItemUpdater::createFunctionalAssociation(const std::string& path)
515{
516 assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION,
517 FUNCTIONAL_REV_ASSOCIATION,
518 path));
519 associations(assocs);
520}
521
Gunnar Millsf10b2322017-09-21 15:31:55 -0500522void ItemUpdater::removeActiveAssociation(const std::string& path)
Gunnar Millsded875d2017-08-28 16:44:52 -0500523{
524 for (auto iter = assocs.begin(); iter != assocs.end();)
525 {
Gunnar Mills88e8a322017-09-13 11:09:28 -0500526 // Since there could be multiple associations to the same path,
527 // only remove ones that have an active forward association.
528 if ((std::get<0>(*iter)).compare(ACTIVE_FWD_ASSOCIATION) == 0 &&
529 (std::get<2>(*iter)).compare(path) == 0)
Gunnar Millsded875d2017-08-28 16:44:52 -0500530 {
531 iter = assocs.erase(iter);
532 associations(assocs);
533 }
534 else
535 {
536 ++iter;
537 }
538 }
539}
540
Saqib Khanb9da6632017-09-13 09:48:37 -0500541bool ItemUpdater::isLowestPriority(uint8_t value)
542{
543 for (const auto& intf : activations)
544 {
545 if(intf.second->redundancyPriority)
546 {
547 if (intf.second->redundancyPriority.get()->priority() < value)
548 {
549 return false;
550 }
551 }
552 }
553 return true;
554}
555
Gunnar Millsec1b41c2017-05-02 12:20:36 -0500556} // namespace updater
557} // namespace software
558} // namespace phosphor