| #ifndef INSTALL_INSTALLER_H_ |
| #define INSTALL_INSTALLER_H_ |
| |
| #include <cstdint> |
| #include <fstream> |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/time/time.h" |
| #include "nlohmann/json.hpp" |
| |
| namespace bloom_install { |
| |
| // Represents a software package to be installed. |
| struct Package { |
| std::string name; |
| std::string activation_script_path; |
| std::string install_script_path; |
| bool operator==(const Package& other) const { |
| return name == other.name && |
| activation_script_path == other.activation_script_path && |
| install_script_path == other.install_script_path; |
| } |
| }; |
| |
| // Defines the possible states of the installation process for logging. |
| enum class State : std::uint8_t { |
| kStarting, |
| kCheckingActivation, |
| kSkipped, |
| kInstalling, |
| kSuccess, |
| kFailureRetry, |
| kFailureFatal, |
| kUnknown |
| }; |
| |
| // Defines the specific event codes for logging. |
| enum class LogCode : std::uint8_t { |
| kInitStart, |
| kInstallHalt, |
| kInstallComplete, |
| kPkgActivationCheckStart, |
| kPkgActivationSkip, |
| kPkgInstallProceed, |
| kPkgInstallStart, |
| kPkgInstallSuccess, |
| kPkgInstallFailRetry, |
| kPkgInstallFailFatal, |
| kUnknown |
| }; |
| |
| // Handles logging of installation progress to a file in JSON format. |
| class ProgressLogger { |
| public: |
| explicit ProgressLogger(const std::string& log_file_path); |
| |
| // Logs a progress message using a type-safe LogCode enum. |
| void Log(State state, absl::Duration elapsed_time, const std::string& message, |
| LogCode code, int retries = -1); |
| |
| bool IsHealthy() const; |
| |
| private: |
| static std::string StateToString(State state) { |
| switch (state) { |
| case State::kStarting: |
| return "starting"; |
| case State::kCheckingActivation: |
| return "checking_activation"; |
| case State::kSkipped: |
| return "skipped"; |
| case State::kInstalling: |
| return "installing"; |
| case State::kSuccess: |
| return "success"; |
| case State::kFailureRetry: |
| return "failure_retry"; |
| case State::kFailureFatal: |
| return "failure_fatal"; |
| default: |
| return "unknown"; |
| } |
| } |
| // Converts a LogCode enum to its string representation. |
| static std::string LogCodeToString(LogCode code) { |
| switch (code) { |
| case LogCode::kInitStart: |
| return "init_start"; |
| case LogCode::kInstallHalt: |
| return "install_halt"; |
| case LogCode::kInstallComplete: |
| return "install_complete"; |
| case LogCode::kPkgActivationCheckStart: |
| return "pkg_activation_check_start"; |
| case LogCode::kPkgActivationSkip: |
| return "pkg_activation_skip"; |
| case LogCode::kPkgInstallProceed: |
| return "pkg_install_proceed"; |
| case LogCode::kPkgInstallStart: |
| return "pkg_install_start"; |
| case LogCode::kPkgInstallSuccess: |
| return "pkg_install_success"; |
| case LogCode::kPkgInstallFailRetry: |
| return "pkg_install_fail_retry"; |
| case LogCode::kPkgInstallFailFatal: |
| return "pkg_install_fail_fatal"; |
| default: |
| return "unknown"; |
| } |
| } |
| |
| std::string log_file_path_; |
| std::ofstream log_file_; |
| bool is_healthy_; |
| }; |
| |
| namespace internal { |
| |
| // Reports generic installation status to a file. |
| // This class implements the contract between the installer and its consumers. |
| // Do not use this class directly. |
| class StatusReporter { |
| public: |
| static StatusReporter Create(const std::string& status_path, |
| int total_packages); |
| // Writes the initial "IN_PROGRESS" status. |
| void Start(const std::string& message); |
| // Records a successfully completed package and updates progress. |
| void RecordSuccess(const std::string& message); |
| // Finalizes the status file as "SUCCESS" or "FAILURE". |
| void Complete(bool success, const std::string& message); |
| |
| private: |
| // Private constructor forces use of the factory method. |
| StatusReporter(const std::string& status_path, int total_packages); |
| // Writes the current state to the JSON file. |
| void WriteStatus(); |
| // Updates the progress fields in the JSON object. |
| void UpdateProgress(const std::string& message); |
| |
| std::string status_path_; |
| int total_packages_; |
| int packages_completed_ = 0; |
| nlohmann::json status_json_; |
| }; |
| } // namespace internal |
| |
| // Defines configuration options for the Installer. |
| struct InstallerOptions { |
| std::vector<Package> packages; |
| int max_retries = 3; |
| std::string log_path = "/var/google/install/progress_internal.log"; |
| std::string status_path = "/var/google/install/progress_status.json"; |
| // Activation check scripts will be persisted in this directory. |
| std::string activation_check_dir = "/var/google/firmware_bundle/"; |
| }; |
| |
| // Manages the installation of a list of software packages. |
| class Installer { |
| public: |
| explicit Installer(const InstallerOptions& options); |
| // Post install runs the activation check and install scripts for each |
| // package. Returns true if all packages are installed successfully, false |
| // otherwise. It also persists the activation check scripts to the activation |
| // check directory. |
| bool PostInstall(); |
| // Activation check runs the activation check scripts for each package. |
| void ActivationCheck(); |
| |
| private: |
| bool InstallPackage(const Package& package); |
| |
| const InstallerOptions options_; |
| ProgressLogger logger_; |
| internal::StatusReporter status_reporter_; |
| }; |
| |
| std::vector<Package> ParsePostInstallPackages(const std::string& tar_file_path); |
| |
| int ActivationMain(const std::string& activation_check_dir); |
| |
| int PostInstallMain(const std::string& inventory_dir, |
| const std::string& install_lock_file_path, |
| const std::string& bundle_tar_file_path, |
| const std::string& activation_check_dir); |
| |
| } // namespace bloom_install |
| |
| #endif // INSTALL_INSTALLER_H_ |