Allow update_engine to skip post-install
The postinstall steps take long time to finish, even though most of them
are optional. Therefore, reuse the flag run_post_install in InstallPlan
to allow skipping optional postinstalls.
Bug: 136185424
Test: cancel the update during post-install, apply again with the header
"RUN_POST_INSTALL=0", check the optional post-installs are skipped
Change-Id: Ic5ab89b079dfd547714fd3d1664e044900f9eebe
diff --git a/common/constants.cc b/common/constants.cc
index 310f1b2..5bfb2b6 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -119,8 +119,7 @@
// Set "SWITCH_SLOT_ON_REBOOT=0" to skip marking the updated partitions active.
// The default is 1 (always switch slot if update succeeded).
const char kPayloadPropertySwitchSlotOnReboot[] = "SWITCH_SLOT_ON_REBOOT";
-// Set "RUN_POST_INSTALL=0" to skip running post install, this will only be
-// honored if we're resuming an update and post install has already succeeded.
+// Set "RUN_POST_INSTALL=0" to skip running optional post install.
// The default is 1 (always run post install).
const char kPayloadPropertyRunPostInstall[] = "RUN_POST_INSTALL";
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index c0c3956..0f48493 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -70,10 +70,17 @@
partition_weight_.resize(install_plan_.partitions.size());
total_weight_ = 0;
for (size_t i = 0; i < install_plan_.partitions.size(); ++i) {
+ auto& partition = install_plan_.partitions[i];
+ if (!install_plan_.run_post_install && partition.postinstall_optional) {
+ partition.run_postinstall = false;
+ LOG(INFO) << "Skipping optional post-install for partition "
+ << partition.name << " according to install plan.";
+ }
+
// TODO(deymo): This code sets the weight to all the postinstall commands,
// but we could remember how long they took in the past and use those
// values.
- partition_weight_[i] = install_plan_.partitions[i].run_postinstall;
+ partition_weight_[i] = partition.run_postinstall;
total_weight_ += partition_weight_[i];
}
accumulated_weight_ = 0;
@@ -83,11 +90,6 @@
}
void PostinstallRunnerAction::PerformPartitionPostinstall() {
- if (!install_plan_.run_post_install) {
- LOG(INFO) << "Skipping post-install according to install plan.";
- return CompletePostinstall(ErrorCode::kSuccess);
- }
-
if (install_plan_.download_url.empty()) {
LOG(INFO) << "Skipping post-install during rollback";
return CompletePostinstall(ErrorCode::kSuccess);
diff --git a/payload_consumer/postinstall_runner_action_unittest.cc b/payload_consumer/postinstall_runner_action_unittest.cc
index caee5e2..e9313f1 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -102,6 +102,8 @@
bool powerwash_required,
bool is_rollback);
+ void RunPostinstallActionWithInstallPlan(const InstallPlan& install_plan);
+
public:
void ResumeRunningAction() {
ASSERT_NE(nullptr, postinstall_action_);
@@ -171,9 +173,6 @@
const string& postinstall_program,
bool powerwash_required,
bool is_rollback) {
- ActionProcessor processor;
- processor_ = &processor;
- auto feeder_action = std::make_unique<ObjectFeederAction<InstallPlan>>();
InstallPlan::Partition part;
part.name = "part";
part.target_path = device_path;
@@ -184,6 +183,14 @@
install_plan.download_url = "http://127.0.0.1:8080/update";
install_plan.powerwash_required = powerwash_required;
install_plan.is_rollback = is_rollback;
+ RunPostinstallActionWithInstallPlan(install_plan);
+}
+
+void PostinstallRunnerActionTest::RunPostinstallActionWithInstallPlan(
+ const chromeos_update_engine::InstallPlan& install_plan) {
+ ActionProcessor processor;
+ processor_ = &processor;
+ auto feeder_action = std::make_unique<ObjectFeederAction<InstallPlan>>();
feeder_action->set_obj(install_plan);
auto runner_action = std::make_unique<PostinstallRunnerAction>(
&fake_boot_control_, &fake_hardware_);
@@ -305,6 +312,27 @@
EXPECT_FALSE(fake_hardware_.GetIsRollbackPowerwashScheduled());
}
+TEST_F(PostinstallRunnerActionTest, RunAsRootSkipOptionalPostinstallTest) {
+ InstallPlan::Partition part;
+ part.name = "part";
+ part.target_path = "/dev/null";
+ part.run_postinstall = true;
+ part.postinstall_path = kPostinstallDefaultScript;
+ part.postinstall_optional = true;
+ InstallPlan install_plan;
+ install_plan.partitions = {part};
+ install_plan.download_url = "http://127.0.0.1:8080/update";
+
+ // Optional postinstalls will be skipped, and the postinstall action succeeds.
+ RunPostinstallActionWithInstallPlan(install_plan);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
+
+ part.postinstall_optional = false;
+ install_plan.partitions = {part};
+ RunPostinstallActionWithInstallPlan(install_plan);
+ EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
+}
+
// Check that the failures from the postinstall script cause the action to
// fail.
TEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) {
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index 263498b..cc891e7 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -233,20 +233,8 @@
install_plan_.switch_slot_on_reboot =
GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true);
- install_plan_.run_post_install = true;
- // Optionally skip post install if and only if:
- // a) we're resuming
- // b) post install has already succeeded before
- // c) RUN_POST_INSTALL is set to 0.
- if (install_plan_.is_resume && prefs_->Exists(kPrefsPostInstallSucceeded)) {
- bool post_install_succeeded = false;
- if (prefs_->GetBoolean(kPrefsPostInstallSucceeded,
- &post_install_succeeded) &&
- post_install_succeeded) {
- install_plan_.run_post_install =
- GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true);
- }
- }
+ install_plan_.run_post_install =
+ GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true);
// Skip writing verity if we're resuming and verity has already been written.
install_plan_.write_verity = true;