diff --git a/src/libaktualizr/package_manager/ostreemanager.cc b/src/libaktualizr/package_manager/ostreemanager.cc index 118bc70d4..f823b101b 100644 --- a/src/libaktualizr/package_manager/ostreemanager.cc +++ b/src/libaktualizr/package_manager/ostreemanager.cc @@ -395,7 +395,13 @@ Uptane::Target OstreeManager::getCurrent() const { // themselves, this actually works just fine for them, too. storage_->loadPrimaryInstalledVersions(¤t_version, nullptr); - if (!!current_version && current_version->sha256Hash() == current_hash) { + bool staged_reboot_pending = false; + if (config.booted == BootedType::kStaged) { + bool reboot_needed; + storage_->loadNeedReboot(&reboot_needed); + staged_reboot_pending = reboot_needed && !bootloader_->rebootDetected(); + } + if (!!current_version && (current_version->sha256Hash() == current_hash || staged_reboot_pending)) { return *current_version; } diff --git a/src/libaktualizr/storage/invstorage.h b/src/libaktualizr/storage/invstorage.h index 24b249c1f..6e63786f1 100644 --- a/src/libaktualizr/storage/invstorage.h +++ b/src/libaktualizr/storage/invstorage.h @@ -36,7 +36,7 @@ struct MisconfiguredEcu { EcuState state; }; -enum class InstalledVersionUpdateMode { kNone, kCurrent, kPending }; +enum class InstalledVersionUpdateMode { kNone, kCurrent, kPending, kBadTarget }; // Functions loading/storing multiple pieces of data are supposed to do so // atomically as far as implementation makes it possible. @@ -116,8 +116,8 @@ class INvStorage { InstalledVersionUpdateMode update_mode) = 0; virtual bool loadInstalledVersions(const std::string& ecu_serial, boost::optional* current_version, boost::optional* pending_version) const = 0; - virtual bool loadInstallationLog(const std::string& ecu_serial, std::vector* log, - bool only_installed) const = 0; + virtual bool loadInstallationLog(const std::string& ecu_serial, std::vector* log, bool only_installed, + bool include_current = true) const = 0; virtual bool hasPendingInstall() = 0; virtual void getPendingEcus(std::vector>* pendingEcus) = 0; virtual void clearInstalledVersions() = 0; @@ -166,8 +166,9 @@ class INvStorage { void savePrimaryInstalledVersion(const Uptane::Target& target, InstalledVersionUpdateMode update_mode) { return saveInstalledVersion("", target, update_mode); } - bool loadPrimaryInstallationLog(std::vector* log, bool only_installed) const { - return loadInstallationLog("", log, only_installed); + bool loadPrimaryInstallationLog(std::vector* log, bool only_installed, + bool include_current = true) const { + return loadInstallationLog("", log, only_installed, include_current); } void importInstalledVersions(const boost::filesystem::path& base_path); diff --git a/src/libaktualizr/storage/sqlstorage.cc b/src/libaktualizr/storage/sqlstorage.cc index f445f5930..0fdde9595 100644 --- a/src/libaktualizr/storage/sqlstorage.cc +++ b/src/libaktualizr/storage/sqlstorage.cc @@ -1118,6 +1118,17 @@ void SQLStorage::saveInstalledVersion(const std::string& ecu_serial, const Uptan LOG_ERROR << "Failed to save installed versions: " << db.errmsg(); return; } + } else if (update_mode == InstalledVersionUpdateMode::kBadTarget) { + // unset 'pending' and 'was_installed' for all installations of the target in the current ecu + auto statement = db.prepareStatement( + "UPDATE installed_versions SET is_pending = 0, was_installed = 0 WHERE ecu_serial = ? AND name = ?", + ecu_serial_real, target.filename()); + if (statement.step() != SQLITE_DONE) { + LOG_ERROR << "Failed to save installed versions: " << db.errmsg(); + return; + } + db.commitTransaction(); + return; } if (!!old_id) { @@ -1180,7 +1191,7 @@ static void loadEcuMap(SQLite3Guard& db, std::string& ecu_serial, Uptane::EcuMap } bool SQLStorage::loadInstallationLog(const std::string& ecu_serial, std::vector* log, - bool only_installed) const { + bool only_installed, bool include_current) const { SQLite3Guard db = dbConnection(); std::string ecu_serial_real = ecu_serial; @@ -1188,12 +1199,13 @@ bool SQLStorage::loadInstallationLog(const std::string& ecu_serial, std::vector< loadEcuMap(db, ecu_serial_real, ecu_map); std::string query = - "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE " - "ecu_serial = ? ORDER BY id;"; + std::string( + "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE ") + + (include_current ? "" : " is_current = 0 AND ") + "ecu_serial = ? ORDER BY id;"; if (only_installed) { - query = - "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE " - "ecu_serial = ? AND was_installed = 1 ORDER BY id;"; + query = std::string( + "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE ") + + (include_current ? "" : " is_current = 0 AND ") + "ecu_serial = ? AND was_installed = 1 ORDER BY id;"; } auto statement = db.prepareStatement(query, ecu_serial_real); diff --git a/src/libaktualizr/storage/sqlstorage.h b/src/libaktualizr/storage/sqlstorage.h index 21fe33208..21e8bf1e2 100644 --- a/src/libaktualizr/storage/sqlstorage.h +++ b/src/libaktualizr/storage/sqlstorage.h @@ -80,8 +80,8 @@ class SQLStorage : public SQLStorageBase, public INvStorage { InstalledVersionUpdateMode update_mode) override; bool loadInstalledVersions(const std::string& ecu_serial, boost::optional* current_version, boost::optional* pending_version) const override; - bool loadInstallationLog(const std::string& ecu_serial, std::vector* log, - bool only_installed) const override; + bool loadInstallationLog(const std::string& ecu_serial, std::vector* log, bool only_installed, + bool include_current = true) const override; bool hasPendingInstall() override; void getPendingEcus(std::vector>* pendingEcus) override; void clearInstalledVersions() override;