File: ansible_management_service.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (147 lines) | stat: -rw-r--r-- 6,060 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_CROSTINI_ANSIBLE_ANSIBLE_MANAGEMENT_SERVICE_H_
#define CHROME_BROWSER_ASH_CROSTINI_ANSIBLE_ANSIBLE_MANAGEMENT_SERVICE_H_

#include <string>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/guest_os/guest_id.h"
#include "components/keyed_service/core/keyed_service.h"

class Profile;

namespace views {
class Widget;
}  // namespace views

namespace crostini {

struct AnsibleConfiguration {
  AnsibleConfiguration(std::string playbook,
                       base::FilePath path,
                       base::OnceCallback<void(bool success)> callback);
  AnsibleConfiguration(base::FilePath path,
                       base::OnceCallback<void(bool success)> callback);
  ~AnsibleConfiguration();

  std::string playbook;
  base::FilePath path;
  base::OnceCallback<void(bool success)> callback;
};

// TODO(okalitova): Install Ansible from backports repo once this is feasible.
extern const char kCrostiniDefaultAnsibleVersion[];

// AnsibleManagementService is responsible for Crostini default
// container management using Ansible.
class AnsibleManagementService : public KeyedService,
                                 public LinuxPackageOperationProgressObserver {
 public:
  // Observer class for Ansible Management Service related events.
  class Observer : public base::CheckedObserver {
   public:
    ~Observer() override = default;
    virtual void OnAnsibleSoftwareConfigurationStarted(
        const guest_os::GuestId& container_id) = 0;
    virtual void OnAnsibleSoftwareConfigurationProgress(
        const guest_os::GuestId& container_id,
        const std::vector<std::string>& status_lines) {}
    virtual void OnAnsibleSoftwareConfigurationFinished(
        const guest_os::GuestId& container_id,
        bool success) = 0;
    virtual void OnAnsibleSoftwareInstall(
        const guest_os::GuestId& container_id) {}
    virtual void OnApplyAnsiblePlaybook(const guest_os::GuestId& container_id) {
    }
    // Mainly for testing purposes only. Signals observers that the UI element
    // is ready for interaction for a particular configuration task.
    virtual void OnAnsibleSoftwareConfigurationUiPrompt(
        const guest_os::GuestId& container_id,
        bool interactive) {}
  };

  explicit AnsibleManagementService(Profile* profile);

  AnsibleManagementService(const AnsibleManagementService&) = delete;
  AnsibleManagementService& operator=(const AnsibleManagementService&) = delete;

  ~AnsibleManagementService() override;

  // Preconfigures a container with a specified Ansible playbook.
  virtual void ConfigureContainer(
      const guest_os::GuestId& container_id,
      base::FilePath playbook,
      base::OnceCallback<void(bool success)> callback);

  // LinuxPackageOperationProgressObserver:
  void OnInstallLinuxPackageProgress(const guest_os::GuestId& container_id,
                                     InstallLinuxPackageProgressStatus status,
                                     int progress_percent,
                                     const std::string& error_message) override;
  void OnUninstallPackageProgress(const guest_os::GuestId& container_id,
                                  UninstallPackageProgressStatus status,
                                  int progress_percent) override;

  virtual void OnApplyAnsiblePlaybookProgress(
      const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal);

  // Gets the input from the user-facing dialog to determine whether or not a
  // configuration task should be retried.
  void RetryConfiguration(const guest_os::GuestId& container_id);
  void CancelConfiguration(const guest_os::GuestId& container_id);
  void CompleteConfiguration(const guest_os::GuestId& container_id,
                             bool success);

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Sets up and returns a mock instance of AnsibleManagementService.
  static AnsibleManagementService* SetUpMockAnsibleManagementServiceForTesting(
      Profile* profile);
  views::Widget* GetDialogWidgetForTesting(
      const guest_os::GuestId& container_id);
  void AddConfigurationTaskForTesting(const guest_os::GuestId& container_id,
                                      views::Widget* widget);

 private:
  bool IsCancelled(const guest_os::GuestId& container_id);

  // Helper function to create the UI elements needed. We won't need to keep
  // track of this because it'll be self-destructing.
  void CreateUiElement(const guest_os::GuestId& container_id);

  void OnInstallAnsibleInContainer(const guest_os::GuestId& container_id,
                                   CrostiniResult result);
  void GetAnsiblePlaybookToApply(const guest_os::GuestId& container_id);
  void OnAnsiblePlaybookRetrieved(const guest_os::GuestId& container_id,
                                  bool success);
  void ApplyAnsiblePlaybook(const guest_os::GuestId& container_id);
  void OnApplyAnsiblePlaybook(
      const guest_os::GuestId& container_id,
      std::optional<vm_tools::cicerone::ApplyAnsiblePlaybookResponse> response);

  // Helper function that runs relevant callback and notifies observers.
  void OnConfigurationFinished(const guest_os::GuestId& container_id,
                               bool success);

  raw_ptr<Profile> profile_;
  base::ObserverList<Observer> observers_;
  std::map<guest_os::GuestId, std::unique_ptr<AnsibleConfiguration>>
      configuration_tasks_;

  // We don't really need to know about these, but keeping them so we can access
  // for testing purposes.
  std::map<guest_os::GuestId, raw_ptr<views::Widget, CtnExperimental>>
      ui_elements_;

  base::WeakPtrFactory<AnsibleManagementService> weak_ptr_factory_;
};

}  // namespace crostini

#endif  // CHROME_BROWSER_ASH_CROSTINI_ANSIBLE_ANSIBLE_MANAGEMENT_SERVICE_H_