blob: 69f525ee0672ef8189bcc9618f0906965b628483 [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 SRC_VIRTUALIZATION_BIN_LINUX_RUNNER_GUEST_H_
#define SRC_VIRTUALIZATION_BIN_LINUX_RUNNER_GUEST_H_
#include <fuchsia/virtualization/cpp/fidl.h>
#include <lib/async/cpp/executor.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fpromise/bridge.h>
#include <lib/fpromise/promise.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/trace/event.h>
#include <zircon/types.h>
#include <deque>
#include <memory>
#include "src/virtualization/bin/linux_runner/crash_listener.h"
#include "src/virtualization/bin/linux_runner/log_collector.h"
#include "src/virtualization/lib/grpc/grpc_vsock_server.h"
#include "src/virtualization/third_party/vm_tools/container_guest.grpc.pb.h"
#include "src/virtualization/third_party/vm_tools/container_host.grpc.pb.h"
#include "src/virtualization/third_party/vm_tools/tremplin.grpc.pb.h"
#include "src/virtualization/third_party/vm_tools/vm_guest.grpc.pb.h"
#include <grpc++/grpc++.h>
namespace linux_runner {
struct GuestConfig {
std::string_view env_label;
size_t stateful_image_size;
};
struct GuestInfo {
uint32_t cid;
fuchsia::virtualization::ContainerStatus container_status;
int32_t download_percent;
std::string failure_reason;
};
using GuestInfoCallback = fit::function<void(GuestInfo)>;
class Guest : public vm_tools::StartupListener::Service,
public vm_tools::tremplin::TremplinListener::Service,
public vm_tools::container::ContainerListener::Service {
public:
// Creates a new |Guest|
static zx_status_t CreateAndStart(sys::ComponentContext* context, GuestConfig config,
GuestInfoCallback callback, std::unique_ptr<Guest>* guest);
Guest(sys::ComponentContext* context, GuestConfig config, GuestInfoCallback callback,
fuchsia::virtualization::RealmPtr env_v1,
fuchsia::virtualization::TerminaGuestManagerPtr env_v2);
~Guest();
// Retry the container startup workflow.
//
// Creating the container can fail under expected situations (ex: no network connectivity) so
// we provide a way to retry that workflow.
//
// This must only be used in response to a previous failure to start the container, which is
// indicated by a ContainerStatus::FAILED message sent to the GuestInfoCallback.
void RetryContainerStartup() { CreateContainer(); }
private:
fpromise::promise<> Start();
fpromise::promise<std::unique_ptr<GrpcVsockServer>, zx_status_t> StartGrpcServer();
void StartGuest();
void MountExtrasPartition();
void MountVmTools();
void ConfigureNetwork();
void StartTermina();
void LaunchContainerShell();
void AddMagmaDeviceToContainer();
void SetupGPUDriversInContainer();
void CreateContainer();
void StartContainer();
void SetupUser();
void DumpContainerDebugInfo();
// |vm_tools::StartupListener::Service|
grpc::Status VmReady(grpc::ServerContext* context, const vm_tools::EmptyMessage* request,
vm_tools::EmptyMessage* response) override;
// |vm_tools::tremplin::TremplinListener::Service|
grpc::Status TremplinReady(grpc::ServerContext* context,
const ::vm_tools::tremplin::TremplinStartupInfo* request,
vm_tools::tremplin::EmptyMessage* response) override;
grpc::Status UpdateCreateStatus(grpc::ServerContext* context,
const vm_tools::tremplin::ContainerCreationProgress* request,
vm_tools::tremplin::EmptyMessage* response) override;
grpc::Status UpdateDeletionStatus(::grpc::ServerContext* context,
const ::vm_tools::tremplin::ContainerDeletionProgress* request,
::vm_tools::tremplin::EmptyMessage* response) override;
grpc::Status UpdateStartStatus(::grpc::ServerContext* context,
const ::vm_tools::tremplin::ContainerStartProgress* request,
::vm_tools::tremplin::EmptyMessage* response) override;
grpc::Status UpdateExportStatus(::grpc::ServerContext* context,
const ::vm_tools::tremplin::ContainerExportProgress* request,
::vm_tools::tremplin::EmptyMessage* response) override;
grpc::Status UpdateImportStatus(::grpc::ServerContext* context,
const ::vm_tools::tremplin::ContainerImportProgress* request,
::vm_tools::tremplin::EmptyMessage* response) override;
grpc::Status ContainerShutdown(::grpc::ServerContext* context,
const ::vm_tools::tremplin::ContainerShutdownInfo* request,
::vm_tools::tremplin::EmptyMessage* response) override;
// |vm_tools::container::ContainerListener::Service|
grpc::Status ContainerReady(grpc::ServerContext* context,
const vm_tools::container::ContainerStartupInfo* request,
vm_tools::EmptyMessage* response) override;
grpc::Status ContainerShutdown(grpc::ServerContext* context,
const vm_tools::container::ContainerShutdownInfo* request,
vm_tools::EmptyMessage* response) override;
grpc::Status UpdateApplicationList(
grpc::ServerContext* context,
const vm_tools::container::UpdateApplicationListRequest* request,
vm_tools::EmptyMessage* response) override;
grpc::Status OpenUrl(grpc::ServerContext* context,
const vm_tools::container::OpenUrlRequest* request,
vm_tools::EmptyMessage* response) override;
grpc::Status InstallLinuxPackageProgress(
grpc::ServerContext* context,
const vm_tools::container::InstallLinuxPackageProgressInfo* request,
vm_tools::EmptyMessage* response) override;
grpc::Status UninstallPackageProgress(
grpc::ServerContext* context,
const vm_tools::container::UninstallPackageProgressInfo* request,
vm_tools::EmptyMessage* response) override;
grpc::Status OpenTerminal(grpc::ServerContext* context,
const vm_tools::container::OpenTerminalRequest* request,
vm_tools::EmptyMessage* response) override;
grpc::Status UpdateMimeTypes(grpc::ServerContext* context,
const vm_tools::container::UpdateMimeTypesRequest* request,
vm_tools::EmptyMessage* response) override;
void PostContainerStatus(fuchsia::virtualization::ContainerStatus container_status);
void PostContainerDownloadProgress(int32_t download_progress);
void PostContainerFailure(std::string failure_reason);
async_dispatcher_t* async_;
async::Executor executor_;
sys::ComponentContext* context_;
GuestConfig config_;
GuestInfoCallback callback_;
std::unique_ptr<GrpcVsockServer> grpc_server_;
fuchsia::virtualization::HostVsockEndpointPtr socket_endpoint_;
fuchsia::virtualization::RealmPtr guest_env_v1_;
fuchsia::virtualization::TerminaGuestManagerPtr guest_env_v2_;
fuchsia::virtualization::GuestPtr guest_controller_;
uint32_t guest_cid_ = fuchsia::virtualization::DEFAULT_GUEST_CID;
std::unique_ptr<vm_tools::Maitred::Stub> maitred_;
std::unique_ptr<vm_tools::tremplin::Tremplin::Stub> tremplin_;
std::unique_ptr<vm_tools::container::Garcon::Stub> garcon_;
CrashListener crash_listener_;
LogCollector log_collector_;
fuchsia::sys::LauncherPtr launcher_;
// A flow ID used to track the time from the time the VM is created until
// the time the guest has reported itself as ready via the VmReady RPC in the
// vm_tools::StartupListener::Service.
const trace_async_id_t vm_ready_nonce_ = TRACE_NONCE();
};
} // namespace linux_runner
#endif // SRC_VIRTUALIZATION_BIN_LINUX_RUNNER_GUEST_H_