Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report which apps require update in DownloadStarted event #357

Merged
merged 2 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/aklite_client_ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,19 @@ GetTargetToInstallResult AkliteClientExt::GetTargetToInstall(const CheckInResult
<< " Skipping its installation.";
}

if (force_apps_sync || !client_->appsInSync(Target::fromTufTarget(current))) {
auto apps_to_update = client_->appsToUpdate(Target::fromTufTarget(current));
if (force_apps_sync || !apps_to_update.empty()) {
// Force installation of apps
res.selected_target = current;
LOG_INFO
<< "The specified Target is already installed, enforcing installation to make sure it's synced and running:"
<< res.selected_target.Name();

res.status = GetTargetToInstallResult::Status::UpdateSyncApps;
res.reason = "Syncing Active Target Apps";
res.reason = "Syncing Active Target Apps\n";
mike-sul marked this conversation as resolved.
Show resolved Hide resolved
for (const auto& app_to_update : apps_to_update) {
res.reason += "- " + app_to_update.first + ": " + app_to_update.second + "\n";
}
} else {
// No targets to install
res.selected_target = TufTarget();
Expand Down
2 changes: 1 addition & 1 deletion src/cli/cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ static StatusCode pullAndInstall(AkliteClientExt &client, int version, const std
LOG_WARNING << "Downgrading from " << current.Version() << " to " << gti_res.selected_target.Version() << "...";
}

auto pi_res = client.PullAndInstall(gti_res.selected_target, "", "", install_mode, local_update_source,
auto pi_res = client.PullAndInstall(gti_res.selected_target, gti_res.reason, "", install_mode, local_update_source,
pull_mode == PullMode::All, do_install);
return res2StatusCode<InstallResult::Status>(i2s, pi_res.status);
}
Expand Down
32 changes: 25 additions & 7 deletions src/composeappmanager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ ComposeAppManager::AppsContainer ComposeAppManager::getApps(const Uptane::Target
return apps;
}

ComposeAppManager::AppsContainer ComposeAppManager::getAppsToUpdate(const Uptane::Target& t) const {
ComposeAppManager::AppsContainer ComposeAppManager::getAppsToUpdate(const Uptane::Target& t,
AppsSyncReason& apps_and_reasons) const {
AppsContainer apps_to_update;

auto currently_installed_target_apps = Target::appsJson(OstreeManager::getCurrent());
Expand All @@ -206,13 +207,15 @@ ComposeAppManager::AppsContainer ComposeAppManager::getAppsToUpdate(const Uptane
if (app_data.empty()) {
// new app in Target
apps_to_update.insert(app_pair);
apps_and_reasons[app_pair.first] = "new app in target";
LOG_INFO << app_name << " will be installed";
continue;
}

if (app_pair.second != app_data["uri"].asString()) {
// an existing App update
apps_to_update.insert(app_pair);
apps_and_reasons[app_pair.first] = "new version in target";
LOG_INFO << app_name << " will be updated";
continue;
}
Expand All @@ -221,29 +224,44 @@ ComposeAppManager::AppsContainer ComposeAppManager::getAppsToUpdate(const Uptane
!boost::filesystem::exists(cfg_.apps_root / app_name / Docker::ComposeAppEngine::ComposeFile)) {
// an App that is supposed to be installed has been removed somehow, let's install it again
apps_to_update.insert(app_pair);
apps_and_reasons[app_pair.first] = "missing installation, to be re-installed";
LOG_INFO << app_name << " will be re-installed";
continue;
}

LOG_DEBUG << app_name << " performing full status check";
if (!app_engine_->isFetched({app_name, app_pair.second}) || !app_engine_->isRunning({app_name, app_pair.second})) {
// an App that is supposed to be installed and running is not fully installed or running
if (!app_engine_->isFetched({app_name, app_pair.second})) {
// an App that is supposed to be installed is not fully installed
apps_to_update.insert(app_pair);
LOG_INFO << app_name << " update will be re-installed or completed";
apps_and_reasons[app_pair.first] = "not fetched";
LOG_INFO << app_name << " is not fully fetched; missing blobs will be fetched";
continue;
}
if (!app_engine_->isRunning({app_name, app_pair.second})) {
// an App that is supposed to running is not running
apps_to_update.insert(app_pair);
apps_and_reasons[app_pair.first] = "not running";
LOG_INFO << app_name << " is not installed or not running; will be installed and started";
continue;
}
}

return apps_to_update;
}

bool ComposeAppManager::checkForAppsToUpdate(const Uptane::Target& target) {
cur_apps_to_fetch_and_update_ = getAppsToUpdate(target);
ComposeAppManager::AppsSyncReason ComposeAppManager::checkForAppsToUpdate(const Uptane::Target& target) {
AppsSyncReason apps_and_reasons;
cur_apps_to_fetch_and_update_ = getAppsToUpdate(target, apps_and_reasons);
if (!!cfg_.reset_apps) {
cur_apps_to_fetch_ = getAppsToFetch(target);
}
are_apps_checked_ = true;
return cur_apps_to_fetch_and_update_.empty() && cur_apps_to_fetch_.empty();
for (const auto& app : cur_apps_to_fetch_) {
if (apps_and_reasons.count(app.first) == 0) {
apps_and_reasons[app.first] = "not fetched (reset apps)";
}
}
return apps_and_reasons;
}

DownloadResult ComposeAppManager::Download(const TufTarget& target) {
Expand Down
5 changes: 3 additions & 2 deletions src/composeappmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ComposeAppManager : public RootfsTreeManager {
};

using AppsContainer = std::unordered_map<std::string, std::string>;
using AppsSyncReason = std::unordered_map<std::string, std::string>;

ComposeAppManager(const PackageConfig& pconfig, const BootloaderConfig& bconfig,
const std::shared_ptr<INvStorage>& storage, const std::shared_ptr<HttpInterface>& http,
Expand All @@ -58,8 +59,8 @@ class ComposeAppManager : public RootfsTreeManager {
// Returns an intersection of Target's Apps and Apps listed in the config (sota.toml:compose_apps)
// If Apps are not specified in the config then all Target's Apps are returned
AppsContainer getApps(const Uptane::Target& t) const;
AppsContainer getAppsToUpdate(const Uptane::Target& t) const;
bool checkForAppsToUpdate(const Uptane::Target& target);
AppsContainer getAppsToUpdate(const Uptane::Target& t, AppsSyncReason& apps_and_reasons) const;
AppsSyncReason checkForAppsToUpdate(const Uptane::Target& target);
void setAppsNotChecked() { are_apps_checked_ = false; }
void handleRemovedApps(const Uptane::Target& target) const;
Json::Value getAppsState() const;
Expand Down
14 changes: 8 additions & 6 deletions src/liteclient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -771,22 +771,24 @@ bool LiteClient::isTargetActive(const Uptane::Target& target) const {
return target.filename() == current.filename() && target.sha256Hash() == current.sha256Hash();
}

bool LiteClient::appsInSync(const Uptane::Target& target) const {
bool LiteClient::appsInSync(const Uptane::Target& target) const { return appsToUpdate(target).empty(); }

ComposeAppManager::AppsSyncReason LiteClient::appsToUpdate(const Uptane::Target& target) const {
if (package_manager_->name() == ComposeAppManager::Name) {
auto* compose_pacman = dynamic_cast<ComposeAppManager*>(package_manager_.get());
if (compose_pacman == nullptr) {
LOG_ERROR << "Cannot downcast the package manager to a specific type";
return false;
return {};
}
LOG_INFO << "Checking status of Active Target (" << target.filename() << ")";
auto no_any_app_to_update = compose_pacman->checkForAppsToUpdate(target);
if (no_any_app_to_update) {
auto apps_to_update = compose_pacman->checkForAppsToUpdate(target);
if (apps_to_update.empty()) {
compose_pacman->handleRemovedApps(getCurrent());
}

return no_any_app_to_update;
return apps_to_update;
}
return true;
return {};
}

void LiteClient::setAppsNotChecked() {
Expand Down
2 changes: 2 additions & 0 deletions src/liteclient.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef AKTUALIZR_LITE_CLIENT_H_
#define AKTUALIZR_LITE_CLIENT_H_

#include "composeappmanager.h"
#include "downloader.h"
#include "gtest/gtest_prod.h"
#include "libaktualizr/config.h"
Expand Down Expand Up @@ -68,6 +69,7 @@ class LiteClient {
void reportAppsState();
bool isTargetActive(const Uptane::Target& target) const;
bool appsInSync(const Uptane::Target& target) const;
ComposeAppManager::AppsSyncReason appsToUpdate(const Uptane::Target& target) const;
void setAppsNotChecked();
std::string getDeviceID() const;
static void update_request_headers(std::shared_ptr<HttpClient>& http_client, const Uptane::Target& target,
Expand Down
Loading