Implement Rollback to previously booted partitions.
This CL implements rollback to whatever partition we ran from before.
We expose this functionality via dbus under AttemptRollback and expose
a new command-line option to update_engine_client that a developer can
use.
BUG=chromium:242665
TEST=Unittests, full update, update + rollback and verified.
Change-Id: Ie59f90b9a0b777dc1329592449090c70892236bf
Reviewed-on: https://gerrit.chromium.org/gerrit/58427
Commit-Queue: Chris Sosa <sosa@chromium.org>
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: Chris Sosa <sosa@chromium.org>
diff --git a/update_attempter.cc b/update_attempter.cc
index 3aa6a1e..3a6988e 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -77,6 +77,8 @@
return "UPDATE_STATUS_UPDATED_NEED_REBOOT";
case UPDATE_STATUS_REPORTING_ERROR_EVENT:
return "UPDATE_STATUS_REPORTING_ERROR_EVENT";
+ case UPDATE_STATUS_ATTEMPTING_ROLLBACK:
+ return "UPDATE_STATUS_ATTEMPTING_ROLLBACK";
default:
return "unknown status";
}
@@ -433,6 +435,15 @@
omaha_request_params_->waiting_period().InSeconds());
}
+void UpdateAttempter::BuildPostInstallActions(
+ InstallPlanAction* previous_action) {
+ shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
+ new PostinstallRunnerAction());
+ actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
+ BondActions(previous_action,
+ postinstall_runner_action.get());
+}
+
void UpdateAttempter::BuildUpdateActions(bool interactive) {
CHECK(!processor_->IsRunning());
processor_->set_delegate(this);
@@ -483,8 +494,6 @@
new FilesystemCopierAction(false, true));
shared_ptr<FilesystemCopierAction> kernel_filesystem_verifier_action(
new FilesystemCopierAction(true, true));
- shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
- new PostinstallRunnerAction);
shared_ptr<OmahaRequestAction> update_complete_action(
new OmahaRequestAction(system_state_,
new OmahaEvent(OmahaEvent::kTypeUpdateComplete),
@@ -506,16 +515,8 @@
actions_.push_back(shared_ptr<AbstractAction>(download_action));
actions_.push_back(shared_ptr<AbstractAction>(download_finished_action));
actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action));
- actions_.push_back(shared_ptr<AbstractAction>(
- kernel_filesystem_verifier_action));
- actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
- actions_.push_back(shared_ptr<AbstractAction>(update_complete_action));
-
- // Enqueue the actions
- for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin();
- it != actions_.end(); ++it) {
- processor_->EnqueueAction(it->get());
- }
+ actions_.push_back(shared_ptr<AbstractAction>(
+ kernel_filesystem_verifier_action));
// Bond them together. We have to use the leaf-types when calling
// BondActions().
@@ -531,8 +532,52 @@
filesystem_verifier_action.get());
BondActions(filesystem_verifier_action.get(),
kernel_filesystem_verifier_action.get());
- BondActions(kernel_filesystem_verifier_action.get(),
- postinstall_runner_action.get());
+
+ BuildPostInstallActions(kernel_filesystem_verifier_action.get());
+
+ actions_.push_back(shared_ptr<AbstractAction>(update_complete_action));
+
+ // Enqueue the actions
+ for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin();
+ it != actions_.end(); ++it) {
+ processor_->EnqueueAction(it->get());
+ }
+}
+
+void UpdateAttempter::Rollback(bool powerwash) {
+ CHECK(!processor_->IsRunning());
+ processor_->set_delegate(this);
+
+ LOG(INFO) << "Setting rollback options.";
+ InstallPlan install_plan;
+ TEST_AND_RETURN(utils::GetInstallDev(utils::BootDevice(),
+ &install_plan.install_path));
+ install_plan.kernel_install_path = utils::BootKernelDevice(
+ install_plan.install_path);
+ install_plan.powerwash_required = powerwash;
+
+ LOG(INFO) << "Using this install plan:";
+ install_plan.Dump();
+
+ shared_ptr<InstallPlanAction> install_plan_action(
+ new InstallPlanAction(install_plan));
+ actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));
+
+ BuildPostInstallActions(install_plan_action.get());
+
+ // Enqueue the actions
+ for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin();
+ it != actions_.end(); ++it) {
+ processor_->EnqueueAction(it->get());
+ }
+ SetStatusAndNotify(UPDATE_STATUS_ATTEMPTING_ROLLBACK,
+ kUpdateNoticeUnspecified);
+
+ // Just in case we didn't update boot flags yet, make sure they're updated
+ // before any update processing starts. This also schedules the start of the
+ // actions we just posted.
+ start_action_processor_ = true;
+ UpdateBootFlags();
}
void UpdateAttempter::CheckForUpdate(const string& app_version,
@@ -574,7 +619,6 @@
// Delegate methods:
void UpdateAttempter::ProcessingDone(const ActionProcessor* processor,
ErrorCode code) {
- CHECK(response_handler_action_);
LOG(INFO) << "Processing Done.";
actions_.clear();
@@ -1132,4 +1176,5 @@
prefs_->Delete(kPrefsUpdateCheckCount);
return false;
}
+
} // namespace chromeos_update_engine