Commit 799e7f9f authored by Josh Pratt's avatar Josh Pratt Committed by Commit Bot

Track Vm state while 'running' (starting, started, stopping)

This allows CrostiniManager to handle states where a VM hasn't finished
starting/stopping fully.

BUG=880165

Change-Id: Ia94bf4059c4bfbf41c3fe920873fa7c8bc2aea18
Reviewed-on: https://chromium-review.googlesource.com/1212206Reviewed-by: default avatarNicholas Verne <nverne@chromium.org>
Commit-Queue: Josh Pratt <jopra@chromium.org>
Cr-Commit-Position: refs/heads/master@{#589449}
parent 82e47566
...@@ -381,26 +381,46 @@ class CrostiniManager::CrostiniRestarter ...@@ -381,26 +381,46 @@ class CrostiniManager::CrostiniRestarter
CrostiniManager::RestartId CrostiniManager::RestartId
CrostiniManager::CrostiniRestarter::next_restart_id_ = 0; CrostiniManager::CrostiniRestarter::next_restart_id_ = 0;
void CrostiniManager::SetVmState(std::string vm_name, VmState vm_state) {
auto vm_info = running_vms_.find(std::move(vm_name));
if (vm_info != running_vms_.end()) {
vm_info->second.first = vm_state;
return;
}
// This can happen normally when StopVm is called right after start up.
LOG(WARNING) << "Attempted to set state for unknown vm: " << vm_name;
}
bool CrostiniManager::IsVmRunning(std::string vm_name) { bool CrostiniManager::IsVmRunning(std::string vm_name) {
return running_vms_.find(std::move(vm_name)) != running_vms_.end(); auto vm_info = running_vms_.find(std::move(vm_name));
if (vm_info != running_vms_.end()) {
return vm_info->second.first == VmState::STARTED;
}
return false;
} }
base::Optional<vm_tools::concierge::VmInfo> CrostiniManager::GetVmInfo( base::Optional<vm_tools::concierge::VmInfo> CrostiniManager::GetVmInfo(
std::string vm_name) { std::string vm_name) {
auto it = running_vms_.find(std::move(vm_name)); auto it = running_vms_.find(std::move(vm_name));
if (it != running_vms_.end()) if (it != running_vms_.end())
return it->second; return it->second.second;
return base::nullopt; return base::nullopt;
} }
void CrostiniManager::AddRunningVmForTesting( void CrostiniManager::AddRunningVmForTesting(
std::string vm_name, std::string vm_name,
vm_tools::concierge::VmInfo vm_info) { vm_tools::concierge::VmInfo vm_info) {
running_vms_[std::move(vm_name)] = std::move(vm_info); running_vms_[std::move(vm_name)] =
std::make_pair(VmState::STARTED, std::move(vm_info));
} }
bool CrostiniManager::IsContainerRunning(std::string vm_name, bool CrostiniManager::IsContainerRunning(std::string vm_name,
std::string container_name) { std::string container_name) {
if (!IsVmRunning(vm_name)) {
return false;
}
// TODO(jopra): Ensure the container not marked running if the vm is not
// running.
auto range = running_containers_.equal_range(std::move(vm_name)); auto range = running_containers_.equal_range(std::move(vm_name));
for (auto it = range.first; it != range.second; ++it) { for (auto it = range.first; it != range.second; ++it) {
if (it->second == container_name) { if (it->second == container_name) {
...@@ -674,8 +694,7 @@ void CrostiniManager::DestroyDiskImage( ...@@ -674,8 +694,7 @@ void CrostiniManager::DestroyDiskImage(
weak_ptr_factory_.GetWeakPtr(), std::move(callback))); weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} }
void CrostiniManager::ListVmDisks( void CrostiniManager::ListVmDisks(ListVmDisksCallback callback) {
ListVmDisksCallback callback) {
vm_tools::concierge::ListVmDisksRequest request; vm_tools::concierge::ListVmDisksRequest request;
request.set_cryptohome_id(CryptohomeIdForProfile(profile_)); request.set_cryptohome_id(CryptohomeIdForProfile(profile_));
request.set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT); request.set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT);
...@@ -726,6 +745,8 @@ void CrostiniManager::StopVm(std::string name, StopVmCallback callback) { ...@@ -726,6 +745,8 @@ void CrostiniManager::StopVm(std::string name, StopVmCallback callback) {
return; return;
} }
SetVmState(name, VmState::STOPPING);
vm_tools::concierge::StopVmRequest request; vm_tools::concierge::StopVmRequest request;
request.set_owner_id(owner_id_); request.set_owner_id(owner_id_);
request.set_name(name); request.set_name(name);
...@@ -1149,31 +1170,34 @@ void CrostiniManager::OnStartTerminaVm( ...@@ -1149,31 +1170,34 @@ void CrostiniManager::OnStartTerminaVm(
std::move(callback).Run(ConciergeClientResult::VM_START_FAILED); std::move(callback).Run(ConciergeClientResult::VM_START_FAILED);
return; return;
} }
// Wait for the Tremplin signal if the vm isn't already marked "running".
if (running_vms_.find(vm_name) == running_vms_.end()) { // If the vm is already marked "running" run the callback.
VLOG(1) << "Awaiting TremplinStartedSignal for " << owner_id_ << ", " if (IsVmRunning(vm_name)) {
<< vm_name; std::move(callback).Run(ConciergeClientResult::SUCCESS);
// Record the container start and run the callback after the VM starts.
tremplin_started_callbacks_.emplace(
vm_name,
base::BindOnce(&CrostiniManager::OnStartTremplin,
weak_ptr_factory_.GetWeakPtr(), vm_name,
std::move(response.vm_info()), std::move(callback),
ConciergeClientResult::SUCCESS));
return; return;
} }
std::move(callback).Run(ConciergeClientResult::SUCCESS);
// Otherwise, record the container start and run the callback after the VM
// starts.
VLOG(1) << "Awaiting TremplinStartedSignal for " << owner_id_ << ", "
<< vm_name;
running_vms_[vm_name] =
std::make_pair(VmState::STARTING, std::move(response.vm_info()));
tremplin_started_callbacks_.emplace(
vm_name,
base::BindOnce(&CrostiniManager::OnStartTremplin,
weak_ptr_factory_.GetWeakPtr(), vm_name,
std::move(callback), ConciergeClientResult::SUCCESS));
} }
void CrostiniManager::OnStartTremplin(std::string vm_name, void CrostiniManager::OnStartTremplin(std::string vm_name,
vm_tools::concierge::VmInfo vm_info,
StartTerminaVmCallback callback, StartTerminaVmCallback callback,
ConciergeClientResult result) { ConciergeClientResult result) {
// Record the running vm. // Record the running vm.
VLOG(1) << "Received TremplinStartedSignal, VM: " << owner_id_ << ", " VLOG(1) << "Received TremplinStartedSignal, VM: " << owner_id_ << ", "
<< vm_name; << vm_name;
running_vms_[vm_name] = std::move(vm_info); SetVmState(vm_name, VmState::STARTED);
// Run the original callback. // Run the original callback.
std::move(callback).Run(result); std::move(callback).Run(result);
......
...@@ -55,6 +55,12 @@ enum class InstallLinuxPackageProgressStatus { ...@@ -55,6 +55,12 @@ enum class InstallLinuxPackageProgressStatus {
INSTALLING, INSTALLING,
}; };
enum class VmState {
STARTING,
STARTED,
STOPPING,
};
// Return type when getting app icons from within a container. // Return type when getting app icons from within a container.
struct Icon { struct Icon {
std::string desktop_file_id; std::string desktop_file_id;
...@@ -347,7 +353,9 @@ class CrostiniManager : public KeyedService, ...@@ -347,7 +353,9 @@ class CrostiniManager : public KeyedService,
std::string container_name, std::string container_name,
RemoveCrostiniCallback callback); RemoveCrostiniCallback callback);
void SetVmState(std::string vm_name, VmState vm_state);
bool IsVmRunning(std::string vm_name); bool IsVmRunning(std::string vm_name);
// Returns null if VM is not running. // Returns null if VM is not running.
base::Optional<vm_tools::concierge::VmInfo> GetVmInfo(std::string vm_name); base::Optional<vm_tools::concierge::VmInfo> GetVmInfo(std::string vm_name);
void AddRunningVmForTesting(std::string vm_name, void AddRunningVmForTesting(std::string vm_name,
...@@ -381,8 +389,9 @@ class CrostiniManager : public KeyedService, ...@@ -381,8 +389,9 @@ class CrostiniManager : public KeyedService,
base::Optional<vm_tools::concierge::ListVmDisksResponse> reply); base::Optional<vm_tools::concierge::ListVmDisksResponse> reply);
// Callback for ConciergeClient::StartTerminaVm. Called after the Concierge // Callback for ConciergeClient::StartTerminaVm. Called after the Concierge
// service method finishes. |callback| is called if the container has already // service method finishes. Updates running containers list then calls the
// been started, otherwise it is passed to OnStartTremplin. // |callback| if the container has already been started, otherwise passes the
// callback to OnStartTremplin.
void OnStartTerminaVm( void OnStartTerminaVm(
std::string vm_name, std::string vm_name,
StartTerminaVmCallback callback, StartTerminaVmCallback callback,
...@@ -392,7 +401,6 @@ class CrostiniManager : public KeyedService, ...@@ -392,7 +401,6 @@ class CrostiniManager : public KeyedService,
// Tremplin service starts. Updates running containers list and then calls the // Tremplin service starts. Updates running containers list and then calls the
// |callback|. // |callback|.
void OnStartTremplin(std::string vm_name, void OnStartTremplin(std::string vm_name,
vm_tools::concierge::VmInfo vm_info,
StartTerminaVmCallback callback, StartTerminaVmCallback callback,
ConciergeClientResult result); ConciergeClientResult result);
...@@ -506,7 +514,8 @@ class CrostiniManager : public KeyedService, ...@@ -506,7 +514,8 @@ class CrostiniManager : public KeyedService,
// start. // start.
std::multimap<std::string, base::OnceClosure> tremplin_started_callbacks_; std::multimap<std::string, base::OnceClosure> tremplin_started_callbacks_;
std::map<std::string, vm_tools::concierge::VmInfo> running_vms_; std::map<std::string, std::pair<VmState, vm_tools::concierge::VmInfo>>
running_vms_;
// Running containers as keyed by vm name. // Running containers as keyed by vm name.
std::multimap<std::string, std::string> running_containers_; std::multimap<std::string, std::string> running_containers_;
......
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