1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2010 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
163defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#ifndef UPDATE_ENGINE_PAYLOAD_CONSUMER_POSTINSTALL_RUNNER_ACTION_H_
1839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#define UPDATE_ENGINE_PAYLOAD_CONSUMER_POSTINSTALL_RUNNER_ACTION_H_
193defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
203defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <string>
210d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo#include <vector>
220d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
230d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo#include <brillo/message_loops/message_loop.h>
240d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo#include <gtest/gtest_prod.h>
256f03a3b868d4b632931400628763036f79c449f7Darin Petkov
2639910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/action.h"
27fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo#include "update_engine/common/boot_control_interface.h"
28fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo#include "update_engine/common/hardware_interface.h"
2939910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/install_plan.h"
303defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
313defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com// The Postinstall Runner Action is responsible for running the postinstall
323defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com// script of a successfully downloaded update.
333defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
343defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comnamespace chromeos_update_engine {
353defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
36b15a0b8eaf18c9e9341706df9f4ab59ce595a67cAlex Deymoclass BootControlInterface;
37b15a0b8eaf18c9e9341706df9f4ab59ce595a67cAlex Deymo
38d317e40be46e1b69f624a8165472c99fe6346a1eChris Sosaclass PostinstallRunnerAction : public InstallPlanAction {
393defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com public:
40fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo  PostinstallRunnerAction(BootControlInterface* boot_control,
41fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo                          HardwareInterface* hardware)
42fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo      : boot_control_(boot_control), hardware_(hardware) {}
431c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan
44d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo  // InstallPlanAction overrides.
45cbc2274c4160805bf726df872390112654816ca7Alex Deymo  void PerformAction() override;
46d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo  void SuspendAction() override;
47d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo  void ResumeAction() override;
48d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo  void TerminateProcessing() override;
493defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
500d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  class DelegateInterface {
510d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo   public:
520d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo    virtual ~DelegateInterface() = default;
530d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
540d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo    // Called whenever there is an overall progress update from the postinstall
550d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo    // programs.
560d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo    virtual void ProgressUpdate(double progress) = 0;
570d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  };
580d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
590d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  void set_delegate(DelegateInterface* delegate) { delegate_ = delegate; }
600d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
613defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  // Debugging/logging
623defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  static std::string StaticType() { return "PostinstallRunnerAction"; }
63cbc2274c4160805bf726df872390112654816ca7Alex Deymo  std::string Type() const override { return StaticType(); }
643defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
653defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com private:
6631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo  friend class PostinstallRunnerActionTest;
670d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  FRIEND_TEST(PostinstallRunnerActionTest, ProcessProgressLineTest);
6831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo
69e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo  void PerformPartitionPostinstall();
70e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo
710d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // Called whenever the |progress_fd_| has data available to read.
720d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  void OnProgressFdReady();
730d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
740d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // Updates the action progress according to the |line| passed from the
750d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // postinstall program. Valid lines are:
760d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  //     global_progress <frac>
770d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  //         <frac> should be between 0.0 and 1.0; sets the progress to the
780d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  //         <frac> value.
790d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  bool ProcessProgressLine(const std::string& line);
800d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
810d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // Report the progress to the delegate given that the postinstall operation
820d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // for |current_partition_| has a current progress of |frac|, a value between
830d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // 0 and 1 for that step.
840d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  void ReportProgress(double frac);
850d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
860d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // Cleanup the setup made when running postinstall for a given partition.
870d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // Unmount and remove the mountpoint directory if needed and cleanup the
880d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // status file descriptor and message loop task watching for it.
890d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  void Cleanup();
90d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo
916f03a3b868d4b632931400628763036f79c449f7Darin Petkov  // Subprocess::Exec callback.
92e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo  void CompletePartitionPostinstall(int return_code,
93e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo                                    const std::string& output);
94e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo
95b15a0b8eaf18c9e9341706df9f4ab59ce595a67cAlex Deymo  // Complete the Action with the passed |error_code| and mark the new slot as
96b15a0b8eaf18c9e9341706df9f4ab59ce595a67cAlex Deymo  // ready. Called when the post-install script was run for all the partitions.
97e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo  void CompletePostinstall(ErrorCode error_code);
986f03a3b868d4b632931400628763036f79c449f7Darin Petkov
99d317e40be46e1b69f624a8165472c99fe6346a1eChris Sosa  InstallPlan install_plan_;
100390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo
101390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  // The path where the filesystem will be mounted during post-install.
102390efedcb7e17587da765b6d682077cb7fa46ee1Alex Deymo  std::string fs_mount_dir_;
1036f03a3b868d4b632931400628763036f79c449f7Darin Petkov
104e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo  // The partition being processed on the list of partitions specified in the
105e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo  // InstallPlan.
106e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo  size_t current_partition_{0};
107e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo
1080d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // A non-negative value representing the estimated weight of each partition
1090d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // passed in the install plan. The weight is used to predict the overall
1100d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // progress from the individual progress of each partition and should
1110d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // correspond to the time it takes to run it.
1120d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  std::vector<double> partition_weight_;
1130d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
1140d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // The sum of all the weights in |partition_weight_|.
1150d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  double total_weight_{0};
1160d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
1170d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // The sum of all the weights in |partition_weight_| up to but not including
1180d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // the |current_partition_|.
1190d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  double accumulated_weight_{0};
1200d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
1210d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // The delegate used to notify of progress updates, if any.
1220d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  DelegateInterface* delegate_{nullptr};
1230d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
124b15a0b8eaf18c9e9341706df9f4ab59ce595a67cAlex Deymo  // The BootControlInerface used to mark the new slot as ready.
125b15a0b8eaf18c9e9341706df9f4ab59ce595a67cAlex Deymo  BootControlInterface* boot_control_;
12631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo
127fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo  // HardwareInterface used to signal powerwash.
128fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo  HardwareInterface* hardware_;
1291c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan
130fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo  // Whether the Powerwash was scheduled before invoking post-install script.
131fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo  // Used for cleaning up if post-install fails.
132fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo  bool powerwash_scheduled_{false};
13330dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold
134d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo  // Postinstall command currently running, or 0 if no program running.
135d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo  pid_t current_command_{0};
136d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo
1377f4bc3f009c711b5bd1bd145f7f53cd837ed6414Ben Chan  // True if |current_command_| has been suspended by SuspendAction().
1387f4bc3f009c711b5bd1bd145f7f53cd837ed6414Ben Chan  bool is_current_command_suspended_{false};
1397f4bc3f009c711b5bd1bd145f7f53cd837ed6414Ben Chan
1400d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // The parent progress file descriptor used to watch for progress reports from
1410d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // the postinstall program and the task watching for them.
1420d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  int progress_fd_{-1};
1430d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  brillo::MessageLoop::TaskId progress_task_{brillo::MessageLoop::kTaskIdNull};
1440d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
1450d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  // A buffer of a partial read line from the progress file descriptor.
1460d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo  std::string progress_buffer_;
1470d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo
1483defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com  DISALLOW_COPY_AND_ASSIGN(PostinstallRunnerAction);
1493defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com};
1503defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
1513defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}  // namespace chromeos_update_engine
1523defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
15339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#endif  // UPDATE_ENGINE_PAYLOAD_CONSUMER_POSTINSTALL_RUNNER_ACTION_H_
154