Skip to content

Commit

Permalink
cli: Add param to delay App installation
Browse files Browse the repository at this point in the history
- Extend the CLI implementation to support update with delayed Apps
  installation.
- Add a new CLI param to specify the delayed App installation mode.

Signed-off-by: Mike Sul <[email protected]>
  • Loading branch information
mike-sul committed Nov 15, 2023
1 parent 7d5d6be commit 21f25da
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 10 deletions.
4 changes: 3 additions & 1 deletion include/aktualizr-lite/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class InstallResult {
Ok = 0,
OkBootFwNeedsCompletion,
NeedsCompletion,
AppsNeedCompletion,
BootFwNeedsCompletion,
Failed,
DownloadFailed,
Expand All @@ -116,7 +117,8 @@ class InstallResult {

// NOLINTNEXTLINE(hicpp-explicit-conversions,google-explicit-constructor)
operator bool() const {
return status == Status::Ok || status == Status::OkBootFwNeedsCompletion || status == Status::NeedsCompletion;
return status == Status::Ok || status == Status::OkBootFwNeedsCompletion || status == Status::NeedsCompletion ||
status == Status::AppsNeedCompletion;
}
};

Expand Down
8 changes: 6 additions & 2 deletions src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ std::string AkliteClient::GetDeviceID() const { return client_->getDeviceID(); }
class LiteInstall : public InstallContext {
public:
LiteInstall(std::shared_ptr<LiteClient> client, std::unique_ptr<Uptane::Target> t, std::string& reason,
InstallMode install_mode)
InstallMode install_mode = InstallMode::All)
: client_(std::move(client)), target_(std::move(t)), reason_(reason), mode_{install_mode} {}

InstallResult Install() override {
Expand All @@ -216,7 +216,11 @@ class LiteInstall : public InstallContext {
auto status = InstallResult::Status::Failed;
if (rc == data::ResultCode::Numeric::kNeedCompletion) {
if (client_->isPendingTarget(*target_)) {
status = InstallResult::Status::NeedsCompletion;
if (client_->getCurrent().sha256Hash() == target_->sha256Hash()) {
status = InstallResult::Status::AppsNeedCompletion;
} else {
status = InstallResult::Status::NeedsCompletion;
}
} else {
// If the install returns `kNeedCompletion` and the target being installed is not pending,
// then it means that the previous boot fw update requires reboot prior to running the new target update
Expand Down
14 changes: 12 additions & 2 deletions src/cli/cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,21 @@ static const std::unordered_map<InstallResult::Status, StatusCode> i2s = {
{InstallResult::Status::Ok, StatusCode::Ok},
{InstallResult::Status::OkBootFwNeedsCompletion, StatusCode::OkNeedsRebootForBootFw},
{InstallResult::Status::NeedsCompletion, StatusCode::InstallNeedsReboot},
{InstallResult::Status::AppsNeedCompletion, StatusCode::InstallAppsNeedFinalization},
{InstallResult::Status::BootFwNeedsCompletion, StatusCode::InstallNeedsRebootForBootFw},
{InstallResult::Status::DownloadFailed, StatusCode::InstallAppPullFailure},
};

StatusCode Install(AkliteClient &client, int version, const std::string &target_name) {
StatusCode Install(AkliteClient &client, int version, const std::string &target_name, const std::string &install_mode) {
const static std::unordered_map<std::string, InstallMode> str2Mode = {{"delay-app-install", InstallMode::OstreeOnly}};
InstallMode mode{InstallMode::All};
if (!install_mode.empty()) {
if (str2Mode.count(install_mode) == 0) {
LOG_WARNING << "Unsupported installation mode: " << install_mode << "; falling back to the default install mode";
} else {
mode = str2Mode.at(install_mode);
}
}
// Check if the device is in a correct state to start a new update
if (client.IsInstallationInProgress()) {
LOG_ERROR << "Cannot start Target installation since there is ongoing installation; target: "
Expand Down Expand Up @@ -75,7 +85,7 @@ StatusCode Install(AkliteClient &client, int version, const std::string &target_
LOG_INFO << "To New Target: " << target.Name();
}

const auto installer = client.Installer(target);
const auto installer = client.Installer(target, "", "", mode);
if (installer == nullptr) {
LOG_ERROR << "Unexpected error: installer couldn't find Target in the DB; try again later";
return StatusCode::UnknownError;
Expand Down
4 changes: 3 additions & 1 deletion src/cli/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ enum class StatusCode {
InstallAppPullFailure = 80,
InstallNeedsRebootForBootFw = 90,
InstallNeedsReboot = 100,
InstallAppsNeedFinalization = 105,
InstallRollbackOk = 110,
InstallRollbackNeedsReboot = 120,
InstallRollbackFailed = 130,
};

StatusCode Install(AkliteClient &client, int version = -1, const std::string &target_name = "");
StatusCode Install(AkliteClient &client, int version = -1, const std::string &target_name = "",
const std::string &install_mode = "");
StatusCode CompleteInstall(AkliteClient &client);

} // namespace cli
Expand Down
7 changes: 6 additions & 1 deletion src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,11 +435,15 @@ static int cli_install(LiteClient& client, const bpo::variables_map& params) {
target_name = version_str;
}
}
std::string install_mode;
if (params.count("install-mode") > 0) {
install_mode = params.at("install-mode").as<std::string>();
}

std::shared_ptr<LiteClient> client_ptr{&client, [](LiteClient* /*unused*/) {}};
AkliteClient akclient{client_ptr, false, true};

return static_cast<int>(cli::Install(akclient, version, target_name));
return static_cast<int>(cli::Install(akclient, version, target_name, install_mode));
}

static int cli_complete_install(LiteClient& client, const bpo::variables_map& params) {
Expand Down Expand Up @@ -498,6 +502,7 @@ bpo::variables_map parse_options(int argc, char** argv) {
("ostree-server", bpo::value<std::string>(), "URL of the Ostree repository")
("primary-ecu-hardware-id", bpo::value<std::string>(), "hardware ID of primary ecu")
("update-name", bpo::value<std::string>(), "optional name of the update when running \"update\". default=latest")
("install-mode", bpo::value<std::string>(), "Optional install mode. Supported modes: [delay-app-install]. By default both ostree and apps are installed before reboot")
#ifdef ALLOW_MANUAL_ROLLBACK
("clear-installed-versions", "DANGER - clear the history of installed updates before applying the given update. This is handy when doing test/debug and you need to rollback to an old version manually.")
#endif
Expand Down
10 changes: 7 additions & 3 deletions tests/apiclient_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,14 @@ TEST_F(ApiClientTest, InstallModeOstreeOnlyIfJustApps) {
ASSERT_EQ(DownloadResult::Status::Ok, dresult.status);

auto iresult = installer->Install();
ASSERT_EQ(InstallResult::Status::NeedsCompletion, iresult.status);
ASSERT_EQ(InstallResult::Status::AppsNeedCompletion, iresult.status);

auto ciresult = client.CompleteInstallation();
ASSERT_EQ(InstallResult::Status::Ok, ciresult.status);
{
liteclient = createLiteClient();
AkliteClient client(liteclient);
auto ciresult = client.CompleteInstallation();
ASSERT_EQ(InstallResult::Status::Ok, ciresult.status);
}
}

TEST_F(ApiClientTest, Secondaries) {
Expand Down

0 comments on commit 21f25da

Please sign in to comment.