Commit 49ace2d5 authored by Olya Kalitova's avatar Olya Kalitova Committed by Commit Bot

Add configuration step to Crostini installer dialog

Adds configuration step to Crostini installer dialog steps. That step is
present only when CrostiniAnsibleInfrastructure feature flag is enabled.

Bug: 1022784
Change-Id: Ia0201eb75780be5691774a9546ae2c43c91c8b03
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1910232
Commit-Queue: Olya Kalitova <okalitova@chromium.org>
Reviewed-by: default avatarPeter Kasting <pkasting@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarNic Hollingum <hollingum@google.com>
Cr-Commit-Position: refs/heads/master@{#719108}
parent a20c9812
......@@ -3498,6 +3498,9 @@
<message name="IDS_CROSTINI_INSTALLER_START_CONTAINER_MESSAGE" desc="Text shown in the Crostini installer dialog when the container inside the VM is starting">
This process may take a few minutes. Starting the Linux container.
</message>
<message name="IDS_CROSTINI_INSTALLER_CONFIGURE_CONTAINER_MESSAGE" desc="Text shown in the Crostini installer dialog when the container inside the VM is being configured" translateable="false">
Configuring the Linux container. This might take up to 30 minutes.
</message>
<message name="IDS_CROSTINI_INSTALLER_SETUP_CONTAINER_MESSAGE" desc="Text shown in the Crostini installer dialog when the container inside the VM is being set up">
This process may take a few minutes. Setting up the Linux container.
</message>
......@@ -3531,6 +3534,9 @@
<message name="IDS_CROSTINI_INSTALLER_START_CONTAINER_ERROR" desc="Text shown in the Crostini installer dialog when the container fails to start inside the VM">
The Linux container didn't start. Please try again.
</message>
<message name="IDS_CROSTINI_INSTALLER_CONFIGURE_CONTAINER_ERROR" desc="Text shown in the Crostini installer dialog when the container fails to be configured inside the VM" translateable="false">
The was an error while configuring Linux. Contact your administrator.
</message>
<message name="IDS_CROSTINI_INSTALLER_SETUP_CONTAINER_ERROR" desc="Text shown in the Crostini installer dialog when the container fails to be set up inside the VM">
The Linux container setup did not complete. Please try again.
</message>
......
......@@ -802,6 +802,8 @@ source_set("chromeos") {
"concierge_helper_service.h",
"crostini/ansible/ansible_management_service.cc",
"crostini/ansible/ansible_management_service.h",
"crostini/ansible/ansible_management_service_factory.cc",
"crostini/ansible/ansible_management_service_factory.h",
"crostini/ansible/ansible_management_util.cc",
"crostini/ansible/ansible_management_util.h",
"crostini/ansible/pending_software_changes.cc",
......
......@@ -9,6 +9,7 @@
#include "base/no_destructor.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_service_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_manager_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h"
......@@ -22,39 +23,6 @@ namespace crostini {
namespace {
class AnsibleManagementServiceFactory
: public BrowserContextKeyedServiceFactory {
public:
static AnsibleManagementService* GetForProfile(Profile* profile) {
return static_cast<AnsibleManagementService*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
static AnsibleManagementServiceFactory* GetInstance() {
static base::NoDestructor<AnsibleManagementServiceFactory> factory;
return factory.get();
}
private:
friend class base::NoDestructor<AnsibleManagementServiceFactory>;
AnsibleManagementServiceFactory()
: BrowserContextKeyedServiceFactory(
"AnsibleManagementService",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(CrostiniManagerFactory::GetInstance());
}
~AnsibleManagementServiceFactory() override = default;
// BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override {
Profile* profile = Profile::FromBrowserContext(context);
return new AnsibleManagementService(profile);
}
};
chromeos::CiceroneClient* GetCiceroneClient() {
return chromeos::DBusThreadManager::Get()->GetCiceroneClient();
}
......@@ -75,16 +43,16 @@ void AnsibleManagementService::ConfigureDefaultContainer(
DCHECK(!configuration_finished_callback_);
configuration_finished_callback_ = std::move(callback);
// TODO(okalitova): Reflect configuration progress in installer view when
// Crostini is being installed.
// Popup dialog is shown in case Crostini has already been installed.
if (!CrostiniManager::GetForProfile(profile_)->GetInstallerViewStatus())
ShowCrostiniAnsibleSoftwareConfigView(profile_);
for (auto& observer : observers_) {
observer.OnAnsibleSoftwareConfigurationStarted();
}
CrostiniManager::GetForProfile(profile_)
->AddLinuxPackageOperationProgressObserver(this);
CrostiniManager::GetForProfile(profile_)->InstallLinuxPackageFromApt(
kCrostiniDefaultVmName, kCrostiniDefaultContainerName,
kCrostiniDefaultAnsibleVersion,
......@@ -245,10 +213,10 @@ void AnsibleManagementService::OnUninstallPackageProgress(
void AnsibleManagementService::OnConfigurationFinished(bool success) {
DCHECK(configuration_finished_callback_);
std::move(configuration_finished_callback_).Run(success);
for (auto& observer : observers_) {
observer.OnAnsibleSoftwareConfigurationFinished(success);
}
std::move(configuration_finished_callback_).Run(success);
}
} // namespace crostini
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_service_factory.h"
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_service.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
namespace crostini {
// static
AnsibleManagementService* AnsibleManagementServiceFactory::GetForProfile(
Profile* profile) {
return static_cast<AnsibleManagementService*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
// static
AnsibleManagementServiceFactory*
AnsibleManagementServiceFactory::GetInstance() {
static base::NoDestructor<AnsibleManagementServiceFactory> factory;
return factory.get();
}
AnsibleManagementServiceFactory::AnsibleManagementServiceFactory()
: BrowserContextKeyedServiceFactory(
"AnsibleManagementService",
BrowserContextDependencyManager::GetInstance()) {}
AnsibleManagementServiceFactory::~AnsibleManagementServiceFactory() = default;
// BrowserContextKeyedServiceFactory:
KeyedService* AnsibleManagementServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
Profile* profile = Profile::FromBrowserContext(context);
return new AnsibleManagementService(profile);
}
} // namespace crostini
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_ANSIBLE_ANSIBLE_MANAGEMENT_SERVICE_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_CROSTINI_ANSIBLE_ANSIBLE_MANAGEMENT_SERVICE_FACTORY_H_
#include "base/no_destructor.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
class Profile;
namespace crostini {
class AnsibleManagementService;
class AnsibleManagementServiceFactory
: public BrowserContextKeyedServiceFactory {
public:
static AnsibleManagementService* GetForProfile(Profile* profile);
static AnsibleManagementServiceFactory* GetInstance();
private:
friend class base::NoDestructor<AnsibleManagementServiceFactory>;
AnsibleManagementServiceFactory();
~AnsibleManagementServiceFactory() override;
// BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(AnsibleManagementServiceFactory);
};
} // namespace crostini
#endif // CHROME_BROWSER_CHROMEOS_CROSTINI_ANSIBLE_ANSIBLE_MANAGEMENT_SERVICE_FACTORY_H_
......@@ -14,6 +14,7 @@
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_service_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_manager_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
#include "chrome/browser/chromeos/crostini/crostini_terminal.h"
......@@ -57,6 +58,7 @@ class CrostiniInstallerFactory : public BrowserContextKeyedServiceFactory {
"CrostiniInstallerService",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(crostini::CrostiniManagerFactory::GetInstance());
DependsOn(crostini::AnsibleManagementServiceFactory::GetInstance());
}
// BrowserContextKeyedServiceFactory:
......@@ -112,6 +114,8 @@ SetupResult ErrorToSetupResult(InstallerError error) {
return SetupResult::kErrorStartingTermina;
case InstallerError::kErrorStartingContainer:
return SetupResult::kErrorStartingContainer;
case InstallerError::kErrorConfiguringContainer:
return SetupResult::kErrorConfiguringContainer;
case InstallerError::kErrorOffline:
return SetupResult::kErrorOffline;
case InstallerError::kErrorFetchingSshKeys:
......@@ -146,6 +150,8 @@ SetupResult InstallStateToCancelledSetupResult(
return SetupResult::kUserCancelledSetupContainer;
case InstallerState::kStartContainer:
return SetupResult::kUserCancelledStartContainer;
case InstallerState::kConfigureContainer:
return SetupResult::kUserCancelledConfiguringContainer;
case InstallerState::kFetchSshKeys:
return SetupResult::kUserCancelledFetchSshKeys;
case InstallerState::kMountContainer:
......@@ -355,10 +361,35 @@ void CrostiniInstaller::OnContainerSetup(bool success) {
return;
}
UpdateInstallingState(InstallerState::kStartContainer);
ansible_management_service_observer_.Add(
AnsibleManagementService::GetForProfile(profile_));
}
void CrostiniInstaller::OnContainerStarted(CrostiniResult result) {
void CrostiniInstaller::OnAnsibleSoftwareConfigurationStarted() {
DCHECK_EQ(installing_state_, InstallerState::kStartContainer);
UpdateInstallingState(InstallerState::kConfigureContainer);
}
void CrostiniInstaller::OnAnsibleSoftwareConfigurationFinished(bool success) {
DCHECK_EQ(installing_state_, InstallerState::kConfigureContainer);
ansible_management_service_observer_.Remove(
AnsibleManagementService::GetForProfile(profile_));
if (!success) {
LOG(ERROR) << "Failed to configure container";
HandleError(InstallerError::kErrorConfiguringContainer);
return;
}
}
void CrostiniInstaller::OnContainerStarted(CrostiniResult result) {
if (result == CrostiniResult::CONTAINER_CONFIGURATION_FAILED) {
DCHECK_EQ(state_, State::ERROR);
return;
}
DCHECK(installing_state_ == InstallerState::kStartContainer ||
installing_state_ == InstallerState::kConfigureContainer);
if (result != CrostiniResult::SUCCESS) {
LOG(ERROR) << "Failed to start container with error code: "
......@@ -410,37 +441,43 @@ void CrostiniInstaller::RunProgressCallback() {
break;
case InstallerState::kInstallImageLoader:
state_start_mark = 0.0;
state_end_mark = 0.25;
state_end_mark = 0.20;
state_max_seconds = 30;
break;
case InstallerState::kStartConcierge:
state_start_mark = 0.25;
state_end_mark = 0.26;
state_start_mark = 0.20;
state_end_mark = 0.21;
break;
case InstallerState::kCreateDiskImage:
state_start_mark = 0.26;
state_end_mark = 0.27;
state_start_mark = 0.21;
state_end_mark = 0.22;
break;
case InstallerState::kStartTerminaVm:
state_start_mark = 0.27;
state_end_mark = 0.35;
state_start_mark = 0.22;
state_end_mark = 0.28;
state_max_seconds = 8;
break;
case InstallerState::kCreateContainer:
state_start_mark = 0.35;
state_end_mark = 0.90;
state_start_mark = 0.28;
state_end_mark = 0.72;
state_max_seconds = 180;
break;
case InstallerState::kSetupContainer:
state_start_mark = 0.90;
state_end_mark = 0.95;
state_start_mark = 0.72;
state_end_mark = 0.76;
state_max_seconds = 8;
break;
case InstallerState::kStartContainer:
state_start_mark = 0.95;
state_end_mark = 0.99;
state_start_mark = 0.76;
state_end_mark = 0.79;
state_max_seconds = 8;
break;
case InstallerState::kConfigureContainer:
state_start_mark = 0.79;
state_end_mark = 0.99;
// Ansible installation and playbook application.
state_max_seconds = 140 + 300;
break;
case InstallerState::kFetchSshKeys:
state_start_mark = 0.99;
state_end_mark = 1;
......@@ -461,6 +498,8 @@ void CrostiniInstaller::RunProgressCallback() {
state_fraction =
0.5 * (state_fraction + 0.01 * container_download_percent_);
}
// TODO(https://crbug.com/1000173): Calculate configure container step
// progress based on real progress.
double progress =
state_start_mark + base::ClampToRange(state_fraction, 0.0, 1.0) *
......
......@@ -7,6 +7,8 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_service.h"
#include "chrome/browser/chromeos/crostini/crostini_installer_types.mojom.h"
#include "chrome/browser/chromeos/crostini/crostini_installer_ui_delegate.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
......@@ -22,7 +24,8 @@ namespace crostini {
class CrostiniInstaller : public KeyedService,
public CrostiniManager::RestartObserver,
public CrostiniInstallerUIDelegate {
public CrostiniInstallerUIDelegate,
public AnsibleManagementService::Observer {
public:
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
......@@ -53,7 +56,10 @@ class CrostiniInstaller : public KeyedService,
kErrorInsufficientDiskSpace = 22,
kMaxValue = kErrorInsufficientDiskSpace,
kErrorConfiguringContainer = 23,
kUserCancelledConfiguringContainer = 24,
kMaxValue = kUserCancelledConfiguringContainer,
};
static CrostiniInstaller* GetForProfile(Profile* profile);
......@@ -84,6 +90,10 @@ class CrostiniInstaller : public KeyedService,
void OnSshKeysFetched(bool success) override;
void OnContainerMounted(bool success) override;
// AnsibleManagementService::Observer:
void OnAnsibleSoftwareConfigurationStarted() override;
void OnAnsibleSoftwareConfigurationFinished(bool success) override;
// Return true if internal state allows starting installation.
bool CanInstall();
......@@ -135,6 +145,9 @@ class CrostiniInstaller : public KeyedService,
ResultCallback result_callback_;
base::OnceClosure cancel_callback_;
ScopedObserver<AnsibleManagementService, AnsibleManagementService::Observer>
ansible_management_service_observer_{this};
base::WeakPtrFactory<CrostiniInstaller> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CrostiniInstaller);
......
......@@ -15,6 +15,7 @@ enum InstallerState {
kStartContainer, // Starting the container inside the Termina VM.
kFetchSshKeys, // Fetch ssh keys from concierge.
kMountContainer, // Do sshfs mount of container.
kConfigureContainer, // Configuring the container inside the Termina VM.
};
enum InstallerError {
......@@ -29,4 +30,5 @@ enum InstallerError {
kErrorMountingContainer,
kErrorSettingUpContainer,
kErrorInsufficientDiskSpace,
kErrorConfiguringContainer,
};
......@@ -11,6 +11,7 @@
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_test_helper.h"
#include "chrome/browser/chromeos/crostini/crostini_installer_types.mojom.h"
#include "chrome/browser/chromeos/crostini/crostini_installer_ui_delegate.h"
#include "chrome/browser/chromeos/crostini/crostini_test_helper.h"
......@@ -140,6 +141,8 @@ class CrostiniInstallerTest : public testing::Test {
}
void Install() {
CrostiniManager::GetForProfile(profile_.get())
->SetInstallerViewStatus(true);
crostini_installer_->Install(
CrostiniManager::RestartOptions{},
base::BindRepeating(&MockCallbacks::OnProgress,
......@@ -210,6 +213,51 @@ TEST_F(CrostiniInstallerTest, InstallFlow) {
<< "Installer should recover to installable state";
}
TEST_F(CrostiniInstallerTest, InstallFlowWithAnsibleInfra) {
AnsibleManagementTestHelper test_helper(profile_.get());
test_helper.SetUpAnsibleInfra();
double last_progress = 0.0;
auto greater_equal_last_progress = Truly(
[&last_progress](double progress) { return progress >= last_progress; });
ExpectationSet expectation_set;
expectation_set +=
EXPECT_CALL(mock_callbacks_,
OnProgress(_, AllOf(greater_equal_last_progress, Le(1.0))))
.WillRepeatedly(SaveArg<1>(&last_progress));
expectation_set +=
EXPECT_CALL(*disk_mount_manager_mock_,
MountPath("sshfs://test@hostname:", _, _, _, _, _))
.WillOnce(Invoke(&mount_path_waiter_, &MountPathWaiter::MountPath));
// |OnProgress()| should not happens after |OnFinished()|
EXPECT_CALL(mock_callbacks_, OnFinished(InstallerError::kNone))
.After(expectation_set);
Install();
base::RunLoop().RunUntilIdle();
test_helper.SendSucceededApplySignal();
mount_path_waiter_.WaitForMountPathCalled();
ASSERT_TRUE(mount_path_waiter_.get_mount_point_info());
disk_mount_manager_mock_->NotifyMountEvent(
chromeos::disks::DiskMountManager::MountEvent::MOUNTING,
chromeos::MountError::MOUNT_ERROR_NONE,
*mount_path_waiter_.get_mount_point_info());
task_environment_.RunUntilIdle();
histogram_tester_.ExpectUniqueSample(
"Crostini.SetupResult",
static_cast<base::HistogramBase::Sample>(
CrostiniInstaller::SetupResult::kSuccess),
1);
EXPECT_TRUE(crostini_installer_->CanInstall())
<< "Installer should recover to installable state";
}
TEST_F(CrostiniInstallerTest, CancelBeforeStart) {
crostini_installer_->CancelBeforeStart();
......
......@@ -2151,8 +2151,7 @@ void CrostiniManager::OnDefaultContainerConfigured(bool success) {
CrostiniResult result = CrostiniResult::SUCCESS;
if (!success) {
LOG(ERROR) << "Failed to configure default Crostini container";
// TODO(https://crbug.com/998124): Add a proper error.
result = CrostiniResult::UNKNOWN_ERROR;
result = CrostiniResult::CONTAINER_CONFIGURATION_FAILED;
}
InvokeAndErasePendingContainerCallbacks(
......
......@@ -1585,7 +1585,7 @@ TEST_F(CrostiniManagerAnsibleInfraTest, StartContainerAnsibleInstallFailure) {
crostini_manager()->StartLxdContainer(
kCrostiniDefaultVmName, kCrostiniDefaultContainerName,
base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(),
CrostiniResult::UNKNOWN_ERROR));
CrostiniResult::CONTAINER_CONFIGURATION_FAILED));
run_loop()->Run();
}
......@@ -1599,7 +1599,8 @@ TEST_F(CrostiniManagerAnsibleInfraTest, StartContainerApplyFailure) {
crostini_manager()->StartLxdContainer(
kCrostiniDefaultVmName, kCrostiniDefaultContainerName,
base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(),
CrostiniResult::UNKNOWN_ERROR));
CrostiniResult::CONTAINER_CONFIGURATION_FAILED));
base::RunLoop().RunUntilIdle();
ansible_management_test_helper_->SendSucceededInstallSignal();
......
......@@ -70,7 +70,8 @@ enum class CrostiniResult {
UPGRADE_CONTAINER_FAILED = 44,
CANCEL_UPGRADE_CONTAINER_FAILED = 45,
CONCIERGE_START_FAILED = 46,
kMaxValue = CONCIERGE_START_FAILED,
CONTAINER_CONFIGURATION_FAILED = 47,
kMaxValue = CONTAINER_CONFIGURATION_FAILED,
};
enum class InstallLinuxPackageProgressStatus {
......
......@@ -236,6 +236,9 @@ Polymer({
case InstallerState.kStartContainer:
messageId = 'startContainerMessage';
break;
case InstallerState.kConfigureContainer:
messageId = 'configureContainerMessage';
break;
case InstallerState.kFetchSshKeys:
messageId = 'fetchSshKeysMessage';
break;
......@@ -272,6 +275,9 @@ Polymer({
case InstallerError.kErrorStartingContainer:
messageId = 'startContainerError';
break;
case InstallerError.kErrorConfiguringContainer:
messageId = 'configureContainerError';
break;
case InstallerError.kErrorOffline:
messageId = 'offlineError';
break;
......
......@@ -84,6 +84,9 @@ base::string16 GetErrorMessage(InstallerError error) {
case InstallerError::kErrorStartingContainer:
return l10n_util::GetStringUTF16(
IDS_CROSTINI_INSTALLER_START_CONTAINER_ERROR);
case InstallerError::kErrorConfiguringContainer:
return l10n_util::GetStringUTF16(
IDS_CROSTINI_INSTALLER_CONFIGURE_CONTAINER_ERROR);
case InstallerError::kErrorOffline:
return l10n_util::GetStringFUTF16(IDS_CROSTINI_INSTALLER_OFFLINE_ERROR,
ui::GetChromeOSDeviceName());
......@@ -447,6 +450,9 @@ void CrostiniInstallerView::SetMessageLabel() {
case InstallerState::kStartContainer:
message_id = IDS_CROSTINI_INSTALLER_START_CONTAINER_MESSAGE;
break;
case InstallerState::kConfigureContainer:
message_id = IDS_CROSTINI_INSTALLER_CONFIGURE_CONTAINER_MESSAGE;
break;
case InstallerState::kFetchSshKeys:
message_id = IDS_CROSTINI_INSTALLER_FETCH_SSH_KEYS_MESSAGE;
break;
......
......@@ -47,6 +47,8 @@ void AddStringResources(content::WebUIDataSource* source) {
{"createDiskImageError", IDS_CROSTINI_INSTALLER_CREATE_DISK_IMAGE_ERROR},
{"startTerminaVmError", IDS_CROSTINI_INSTALLER_START_TERMINA_VM_ERROR},
{"startContainerError", IDS_CROSTINI_INSTALLER_START_CONTAINER_ERROR},
{"configureContainerError",
IDS_CROSTINI_INSTALLER_CONFIGURE_CONTAINER_ERROR},
{"fetchSshKeysError", IDS_CROSTINI_INSTALLER_FETCH_SSH_KEYS_ERROR},
{"mountContainerError", IDS_CROSTINI_INSTALLER_MOUNT_CONTAINER_ERROR},
{"setupContainerError", IDS_CROSTINI_INSTALLER_SETUP_CONTAINER_ERROR},
......@@ -58,6 +60,8 @@ void AddStringResources(content::WebUIDataSource* source) {
{"startTerminaVmMessage",
IDS_CROSTINI_INSTALLER_START_TERMINA_VM_MESSAGE},
{"startContainerMessage", IDS_CROSTINI_INSTALLER_START_CONTAINER_MESSAGE},
{"configureContainerMessage",
IDS_CROSTINI_INSTALLER_CONFIGURE_CONTAINER_MESSAGE},
{"setupContainerMessage", IDS_CROSTINI_INSTALLER_SETUP_CONTAINER_MESSAGE},
{"fetchSshKeysMessage", IDS_CROSTINI_INSTALLER_FETCH_SSH_KEYS_MESSAGE},
{"mountContainerMessage", IDS_CROSTINI_INSTALLER_MOUNT_CONTAINER_MESSAGE},
......
......@@ -12288,6 +12288,14 @@ Called by update_net_error_codes.py.-->
<int value="37" label="CONTAINER_EXPORT_IMPORT_CANCELLED"/>
<int value="38" label="RESTART_ABORTED"/>
<int value="39" label="RESTART_FAILED_VM_STOPPED"/>
<int value="40" label="UPGRADE_CONTAINER_STARTED"/>
<int value="41" label="UPGRADE_CONTAINER_ALREADY_RUNNING"/>
<int value="42" label="UPGRADE_CONTAINER_NOT_SUPPORTED"/>
<int value="43" label="UPGRADE_CONTAINER_ALREADY_UPGRADED"/>
<int value="44" label="UPGRADE_CONTAINER_FAILED"/>
<int value="45" label="CANCEL_UPGRADE_CONTAINER_FAILED"/>
<int value="46" label="CONCIERGE_START_FAILED"/>
<int value="47" label="CONTAINER_CONFIGURATION_FAILED"/>
</enum>
<enum name="CrostiniSettingsEvent">
......@@ -12319,6 +12327,8 @@ Called by update_net_error_codes.py.-->
<int value="20" label="User Cancelled While Fetching SSH Keys"/>
<int value="21" label="User Cancelled While Mounting Container"/>
<int value="22" label="Insufficient Disk Space"/>
<int value="23" label="Error Configuring Container"/>
<int value="24" label="User Cancelled While Configuring Container"/>
</enum>
<enum name="CrostiniUISurface">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment