system: Work around RAUC not providing some properties
We encountered an issue where RAUC did not provide bundle.version and
installed.timestamp properties. It turns out that it was because of
missing /slot.raucs file.
However we expected that RAUC always provide all the required
properties and this issue then led to map::at throwing an exception.
This patch implements 'more defensive behaviour' when working with the
contents returned by RAUC by checking whether the properties are present
in the map.
Change-Id: Iefed40c6cef410103fe583bd4dbd08dc39f069da
diff --git a/src/system/Firmware.cpp b/src/system/Firmware.cpp
index 10d34a1..d1f8d29 100644
--- a/src/system/Firmware.cpp
+++ b/src/system/Firmware.cpp
@@ -133,12 +133,23 @@
for (const auto& slotName : FIRMWARE_SLOTS) {
if (auto it = slotStatus.find(slotName); it != slotStatus.end()) { // if there is an update for the slot "slotName"
const auto& props = it->second;
- auto xpathPrefix = CZECHLIGHT_SYSTEM_FIRMWARE_MODULE_PREFIX + "firmware-slot[name='" + std::get<std::string>(props.at("bootname")) + "']/";
+ std::string xpathPrefix;
- m_slotStatusCache[xpathPrefix + "state"] = std::get<std::string>(props.at("state"));
- m_slotStatusCache[xpathPrefix + "version"] = std::get<std::string>(props.at("bundle.version"));
- m_slotStatusCache[xpathPrefix + "installed"] = std::get<std::string>(props.at("installed.timestamp"));
- m_slotStatusCache[xpathPrefix + "boot-status"] = std::get<std::string>(props.at("boot-status"));
+ // Better be defensive about provided properties. If somebody removes /slot.raucs, RAUC doesn't provide all the data (at least bundle.version and installed.timestamp).
+ if (auto pit = props.find("bootname"); pit != props.end()) {
+ xpathPrefix = CZECHLIGHT_SYSTEM_FIRMWARE_MODULE_PREFIX + "firmware-slot[name='" + std::get<std::string>(pit->second) + "']/";
+ } else {
+ m_log->error("RAUC didn't provide 'bootname' property for slot '{}'. Skipping update for that slot.");
+ continue;
+ }
+
+ for (const auto& [yangKey, raucKey] : {std::pair{"state", "state"}, {"boot-status", "boot-status"}, {"version", "bundle.version"}, {"installed", "installed.timestamp"}}) {
+ if (auto pit = props.find(raucKey); pit != props.end()) {
+ m_slotStatusCache[xpathPrefix + yangKey] = std::get<std::string>(pit->second);
+ } else {
+ m_log->warn("RAUC didn't provide '{}' property for slot '{}'.", raucKey, slotName);
+ }
+ }
}
}