| // Copyright 2018 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef VM_TOOLS_CICERONE_SERVICE_H_ | |
| #define VM_TOOLS_CICERONE_SERVICE_H_ | |
| #include <cstdint> | |
| #include <map> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include <utility> | |
| #include <vector> | |
| #include <base/check.h> | |
| #include <base/files/file_descriptor_watcher_posix.h> | |
| #include <base/files/file_path.h> | |
| #include <base/files/file_path_watcher.h> | |
| #include <base/functional/callback.h> | |
| #include <base/logging.h> | |
| #include <base/memory/ref_counted.h> | |
| #include <base/memory/weak_ptr.h> | |
| #include <base/sequence_checker.h> | |
| #include <base/threading/thread.h> | |
| #include <brillo/process/process.h> | |
| #include <dbus/bus.h> | |
| #include <dbus/exported_object.h> | |
| #include <dbus/message.h> | |
| #include <grpcpp/grpcpp.h> | |
| #include <vm_applications/apps.pb.h> | |
| #include <vm_cicerone/cicerone_service.pb.h> | |
| #include <vm_concierge/concierge_service.pb.h> | |
| #include <vm_protos/proto_bindings/container_host.pb.h> | |
| #include <vm_sk_forwarding/sk_forwarding.pb.h> | |
| #include <chromeos/dbus/service_constants.h> | |
| #include "vm_tools/cicerone/container.h" | |
| #include "vm_tools/cicerone/container_listener_impl.h" | |
| #include "vm_tools/cicerone/crash_listener_impl.h" | |
| #include "vm_tools/cicerone/dbus_adaptors/org.chromium.VmCicerone.h" | |
| #include "vm_tools/cicerone/guest_metrics.h" | |
| #include "vm_tools/cicerone/shadercached_helper.h" | |
| #include "vm_tools/cicerone/shill_client.h" | |
| #include "vm_tools/cicerone/tremplin_listener_impl.h" | |
| #include "vm_tools/cicerone/virtual_machine.h" | |
| namespace vm_tools::cicerone { | |
| // VM Container Service responsible for responding to DBus method calls for | |
| // interacting with VM containers. | |
| class Service : public org::chromium::VmCiceroneInterface { | |
| public: | |
| // Creates a new Service instance. |quit_closure| is posted to the TaskRunner | |
| // for the current thread when this process receives a SIGTERM. |bus| is a | |
| // connection to the SYSTEM dbus. | |
| // Normally, services are bound to a AF_VSOCK and AF_UNIX socket. For unit | |
| // tests, the services only listen on an AF_UNIX socket by giving | |
| // |unix_socket_path_for_testing| a value. | |
| static std::unique_ptr<Service> Create( | |
| base::OnceClosure quit_closure, | |
| const std::optional<base::FilePath>& unix_socket_path_for_testing, | |
| scoped_refptr<dbus::Bus> bus); | |
| ~Service(); | |
| ContainerListenerImpl* GetContainerListenerImpl() const { | |
| return container_listener_.get(); | |
| } | |
| TremplinListenerImpl* GetTremplinListenerImpl() const { | |
| return tremplin_listener_.get(); | |
| } | |
| CrashListenerImpl* GetCrashListenerImpl() const { | |
| return crash_listener_.get(); | |
| } | |
| // For testing only. Pretend that the Tremplin server for the given VM is | |
| // actually at |tremplin_address| instead of the normal vsock address. Must | |
| // be called after the VM is created but before the corresponding | |
| // ConnectTremplin is called. | |
| bool SetTremplinStubOfVmForTesting( | |
| const std::string& owner_id, | |
| const std::string& vm_name, | |
| std::unique_ptr<vm_tools::tremplin::Tremplin::StubInterface> | |
| mock_tremplin_stub); | |
| // For testing only. Force the given VM to add a container with the indicated | |
| // security token. A VM with |owner_id|, |vm_name| must already exist. This is | |
| // the only way to get a consistent security token for unit tests & fuzz | |
| // tests. Returns true on success. | |
| bool CreateContainerWithTokenForTesting(const std::string& owner_id, | |
| const std::string& vm_name, | |
| const std::string& container_name, | |
| const std::string& container_token); | |
| // Stop Service from starting GRPC servers in a testing environment. Must | |
| // be called before calling Service::Init (and therefore Service::Create). | |
| static void DisableGrpcForTesting(); | |
| // For testing only. Replace |guest_metrics_| with a mock. | |
| void SetGuestMetricsForTesting(std::unique_ptr<GuestMetrics> guest_metrics) { | |
| guest_metrics_ = std::move(guest_metrics); | |
| } | |
| GuestMetrics* guest_metrics_for_testing() { return guest_metrics_.get(); } | |
| // For testing only. Disable initialization of |guest_metrics_|. | |
| static void DisableGuestMetricsCreation() { create_guest_metrics_ = false; } | |
| // Connect to the Tremplin instance on the VM with the given |cid|. | |
| void ConnectTremplin(const uint32_t cid, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // The status of an ongoing LXD container create operation. | |
| enum class CreateStatus { | |
| UNKNOWN, | |
| CREATED, | |
| DOWNLOAD_TIMED_OUT, | |
| CANCELLED, | |
| FAILED, | |
| }; | |
| // The status of an ongoing LXD container start operation. | |
| enum class StartStatus { | |
| UNKNOWN, | |
| STARTED, | |
| CANCELLED, | |
| FAILED, | |
| STARTING, | |
| }; | |
| // The status of an ongoing LXD container stop operation. | |
| enum class StopStatus { | |
| UNKNOWN, | |
| STOPPED, | |
| STOPPING, | |
| CANCELLED, | |
| FAILED, | |
| }; | |
| // Notifies the service that a VM with |cid| has finished its create | |
| // operation of |container_name| with |status|. |failure_reason| will describe | |
| // the failure reason if status != CREATED. Sets |result| to true if the VM | |
| // cid is known. Signals |event| when done. | |
| void LxdContainerCreated(const uint32_t cid, | |
| std::string container_name, | |
| CreateStatus status, | |
| std::string failure_reason, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Notifies the service that a VM with |cid| is downloading a container | |
| // |container_name| with |download_progress| percentage complete. Sets | |
| // |result| to true if the VM cid is known. Signals |event| when done. | |
| void LxdContainerDownloading(const uint32_t cid, | |
| std::string container_name, | |
| int download_progress, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Notifies the service that a VM with |cid| has finished its delete | |
| // operation of |container_name| with |status|. |failure_reason| will describe | |
| // the failure reason if status != DELETED. Sets |result| to true if the VM | |
| // cid is known. Signals |event| when done. | |
| void LxdContainerDeleted( | |
| const uint32_t cid, | |
| std::string container_name, | |
| vm_tools::tremplin::ContainerDeletionProgress::Status status, | |
| std::string failure_reason, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Notifies the service that a VM with |cid| is starting a container | |
| // |container_name| with status |status|. |failure_reason| will describe the | |
| // failure reason if status == FAILED. Sets |result| to true if the VM cid | |
| // is known. Signals |event| when done. | |
| void LxdContainerStarting(const uint32_t cid, | |
| std::string container_name, | |
| StartStatus status, | |
| std::string failure_reason, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Notifies the service that a VM with |cid| is stopping a container | |
| // |container_name| with status |status|. |failure_reason| will describe the | |
| // failure reason if status == FAILED. Sets |result| to true if the VM cid | |
| // is known. Signals |event| when done. | |
| void LxdContainerStopping(const uint32_t cid, | |
| std::string container_name, | |
| StopStatus status, | |
| std::string failure_reason, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Notifies the service that a container with |container_token| and running | |
| // in a VM |cid| has completed startup. Sets |result| to true if this maps to | |
| // a currently running VM and |container_token| matches a security token for | |
| // that VM; false otherwise. Signals |event| when done. | |
| void ContainerStartupCompleted(const std::string& container_token, | |
| const uint32_t cid, | |
| const uint32_t garcon_vsock_port, | |
| const uint32_t sftp_port, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Notifies the service that a container with |container_name| or | |
| // |container_token| and running in a VM with |cid| is shutting down. Sets | |
| // |result| to true if this maps to a currently running VM and | |
| // |container_token| matches a security token for that VM; false otherwise. | |
| // Signals |event| when done. Callers from within the VM (tremplin) may set | |
| // |container_name|, but callers from wihtin a container (garcon) should not | |
| // be trusted to use |container_name| and must use |container_token|. | |
| void ContainerShutdown(std::string container_name, | |
| std::string container_token, | |
| const uint32_t cid, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Notifies the service of a change in |listening_tcp4_ports| for the VM with | |
| // |cid|. Sets |result| to true if this maps to a currently running VM; false | |
| // otherwise. Signals |event| when done. | |
| void UpdateListeningPorts( | |
| std::map<std::string, std::vector<uint16_t>> listening_tcp4_ports, | |
| const uint32_t cid, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform listeners on update for the progress or | |
| // completion of container export. It will use |cid| to resolve the request to | |
| // a VM. |progress_signal| should have all related fields set |result| is set | |
| // to true on success, false otherwise. Signals |event| when done. | |
| void ContainerExportProgress( | |
| const uint32_t cid, | |
| ExportLxdContainerProgressSignal* progress_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform listeners on update for the progress or | |
| // completion of container import. It will use |cid| to resolve the request to | |
| // a VM. |progress_signal| should have all related fields set |result| is set | |
| // to true on success, false otherwise. Signals |event| when done. | |
| void ContainerImportProgress( | |
| const uint32_t cid, | |
| ImportLxdContainerProgressSignal* progress_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform listeners of progress or completion of a | |
| // container upgrade. It will use |cid| to resolve the request to | |
| // a VM. |progress_signal| should have all related fields set |result| is set | |
| // to true on success, false otherwise. Signals |event| when done. | |
| void ContainerUpgradeProgress(const uint32_t cid, | |
| UpgradeContainerProgressSignal* progress_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform listeners of progress or completion of | |
| // starting lxd. It will use |cid| to resolve the request to a VM. | |
| // |progress_signal| should have all related fields set. |result| is set to | |
| // true on success, false otherwise. Signals |event| when done. | |
| void StartLxdProgress(const uint32_t cid, | |
| StartLxdProgressSignal* progress_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| void PendingUpdateApplicationListCalls(const std::string& container_token, | |
| const uint32_t cid, | |
| const uint32_t count, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // This will send a D-Bus message to Chrome to inform it of the current | |
| // installed application list for a container. It will use |cid| to | |
| // resolve the request to a VM and then |container_token| to resolve it to a | |
| // container. |app_list| should be populated with the list of installed | |
| // applications but the vm & container names should be left blank; it must | |
| // remain valid for the lifetime of this call. |result| is set to true on | |
| // success, false otherwise. Signals |event| when done. | |
| void UpdateApplicationList(const std::string& container_token, | |
| const uint32_t cid, | |
| vm_tools::apps::ApplicationList* app_list, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus message to Chrome to tell it to open the |url| in a new tab. | |
| // |result| is set to true on success, false otherwise. Signals | |
| // |event| when done. | |
| void OpenUrl(const std::string& container_token, | |
| const std::string& url, | |
| uint32_t cid, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus message to Chrome to open a SelectFile dialog. |files| is | |
| // a list of the files selected by the user. Signals |event| when done. | |
| void SelectFile(const std::string& container_token, | |
| const uint32_t cid, | |
| vm_tools::apps::SelectFileRequest* select_file, | |
| std::vector<std::string>* files, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform listeners on update for the progress or | |
| // completion of a Linux package install. It will use |cid| to | |
| // resolve the request to a VM and then |container_token| to resolve it to a | |
| // container. |progress_signal| should have all related fields from the | |
| // container request set in it. |result| is set to true on success, false | |
| // otherwise. Signals |event| when done. | |
| void InstallLinuxPackageProgress( | |
| const std::string& container_token, | |
| const uint32_t cid, | |
| InstallLinuxPackageProgressSignal* progress_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform Chrome about the progress or completion of a | |
| // Linux package uninstall. It will use |cid| to resolve the request to a VM | |
| // and then |container_token| to resolve it to a container. |progress_signal| | |
| // should have all related fields from the container request set in it. | |
| // |result| is set to true on success, false otherwise. Signals |event| when | |
| // done. | |
| void UninstallPackageProgress(const std::string& container_token, | |
| const uint32_t cid, | |
| UninstallPackageProgressSignal* progress_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform listeners on update for the progress or | |
| // completion of a Ansible playbook application. It will use |cid| to | |
| // resolve the request to a VM and then |container_token| to resolve it to a | |
| // container. |progress_signal| should have all related fields from the | |
| // container request set in it. |result| is set to true on success, false | |
| // otherwise. Signals |event| when done. | |
| void ApplyAnsiblePlaybookProgress( | |
| const std::string& container_token, | |
| const uint32_t cid, | |
| ApplyAnsiblePlaybookProgressSignal* progress_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus message to Chrome to tell it to open a terminal that is | |
| // connected back to the VM/container and if there are params in | |
| // |terminal_params| then those should be executed in that terminal. | |
| // It will use |cid| to resolve the request to a VM and then | |
| // |container_token| to resolve it to a container. |result| is set to true on | |
| // success, false otherwise. Signals |event| when done. | |
| void OpenTerminal(const std::string& container_token, | |
| vm_tools::apps::TerminalParams terminal_params, | |
| const uint32_t cid, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus message to Chrome to update the list of file extensions to | |
| // MIME type mapping in the container, the mappings are contained in | |
| // |mime_types|. It will use |cid| to resolve the request to a VM and then | |
| // |container_token| to resolve it to a container. |result| is set to true on | |
| // success, false otherwise. Signals |event| when done. | |
| void UpdateMimeTypes(const std::string& container_token, | |
| vm_tools::apps::MimeTypes mime_types, | |
| const uint32_t cid, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform that a file has changed within the watched | |
| // directory. It will use |cid| to resolve the request to a VM and then | |
| // |container_token| to resolve it to a container. |triggered_signal| should | |
| // have all related fields from the container request set in it. |result| is | |
| // set to true on success, false otherwise. Signals |event| when done. | |
| void FileWatchTriggered(const std::string& container_token, | |
| const uint32_t cid, | |
| FileWatchTriggeredSignal* triggered_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus signal to inform that a container is running low on disk | |
| // space. It will use |cid| to resolve the request to a VM and then | |
| // |container_token| to resolve it to a container. |triggered_signal| should | |
| // have all related fields from the container request set in it. |result| is | |
| // set to true on success, false otherwise. Signals |event| when done. | |
| void LowDiskSpaceTriggered(const std::string& container_token, | |
| const uint32_t cid, | |
| LowDiskSpaceTriggeredSignal* triggered_signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Gets the VirtualMachine that corresponds to a container at |cid| | |
| // or the |vm_token| for the VM itself and sets |vm_out| to the | |
| // VirtualMachine, |owner_id_out| to the owner id of the VM, and |name_out| to | |
| // the name of the VM. Returns false if no such mapping exists. | |
| bool GetVirtualMachineForCidOrToken(const uint32_t cid, | |
| const std::string& vm_token, | |
| VirtualMachine** vm_out, | |
| std::string* owner_id_out, | |
| std::string* name_out); | |
| // Sends a D-Bus message to Chrome to forward Security Key request to gnubbyd | |
| // service. It will use |cid| to resolve the request to a VM in order to make | |
| // sure request is forwarded to the extension in the VM owner's profile. | |
| // |security_key_message| contains serialized message for | |
| // |security_key_response| contains the gnubbyd response on the request. In | |
| // case of failure |security_key_response| is empty. | |
| // Signals |event| when done. | |
| void ForwardSecurityKeyMessage( | |
| const uint32_t cid, | |
| vm_tools::sk_forwarding::ForwardSecurityKeyMessageRequest | |
| security_key_message, | |
| vm_tools::sk_forwarding::ForwardSecurityKeyMessageResponse* | |
| security_key_response, | |
| base::WaitableEvent* event); | |
| // Passes metrics from a container. Used by e.g. Borealis, for IO and swap | |
| // metrics. | |
| void ReportMetrics(const std::string& container_token, | |
| const uint32_t cid, | |
| const vm_tools::container::ReportMetricsRequest& request, | |
| vm_tools::container::ReportMetricsResponse* result, | |
| base::WaitableEvent* event); | |
| // Install shader cache DLC and optionally mount for the VM specified. | |
| void InstallVmShaderCache( | |
| const uint32_t cid, | |
| const vm_tools::container::InstallShaderCacheRequest* request, | |
| std::string* error_out, | |
| base::WaitableEvent* event); | |
| // Uninstall shader cache, unmount the shader cache DLC for all VMs. | |
| void UninstallVmShaderCache( | |
| const uint32_t cid, | |
| const vm_tools::container::UninstallShaderCacheRequest* request, | |
| std::string* error_out, | |
| base::WaitableEvent* event); | |
| // Uninstall shader cache, unmount the shader cache DLC for all VMs. | |
| void UnmountVmShaderCache( | |
| const uint32_t cid, | |
| const vm_tools::container::UnmountShaderCacheRequest* request, | |
| std::string* error_out, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus message to request that sleep be inhibited. | |
| void InhibitScreensaver(const std::string& container_token, | |
| const uint32_t cid, | |
| InhibitScreensaverSignal* signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| // Sends a D-Bus message to request that sleep be Uninhibited. | |
| void UninhibitScreensaver(const std::string& container_token, | |
| const uint32_t cid, | |
| UninhibitScreensaverSignal* signal, | |
| bool* result, | |
| base::WaitableEvent* event); | |
| base::WeakPtr<Service> GetWeakPtrForTesting() { | |
| return weak_ptr_factory_.GetWeakPtr(); | |
| } | |
| private: | |
| // Fills |signal_proto| with VM and owner using |cid| to lookup. | |
| template <typename T> | |
| bool FillVmInfoByCid(const uint32_t cid, T* signal_proto) { | |
| DCHECK(sequence_checker_.CalledOnValidSequence()); | |
| CHECK(signal_proto); | |
| VirtualMachine* vm; | |
| std::string owner_id; | |
| std::string vm_name; | |
| if (!GetVirtualMachineForCidOrToken(cid, "", &vm, &owner_id, &vm_name)) { | |
| LOG(ERROR) << "Could not get virtual machine for cid"; | |
| return false; | |
| } | |
| signal_proto->set_vm_name(std::move(vm_name)); | |
| signal_proto->set_owner_id(std::move(owner_id)); | |
| return true; | |
| } | |
| // Fills |signal_proto| with VM and owner using |cid| and |container_token| to | |
| // lookup VM, owner, and container name. | |
| template <typename T> | |
| bool FillVmInfoByCidAndContainerToken(const std::string& container_token, | |
| const uint32_t cid, | |
| T* signal_proto) { | |
| DCHECK(sequence_checker_.CalledOnValidSequence()); | |
| CHECK(signal_proto); | |
| VirtualMachine* vm; | |
| std::string owner_id; | |
| std::string vm_name; | |
| if (!GetVirtualMachineForCidOrToken(cid, container_token, &vm, &owner_id, | |
| &vm_name)) { | |
| LOG(ERROR) << "Could not get virtual machine for cid"; | |
| return false; | |
| } | |
| std::string container_name = vm->GetContainerNameForToken(container_token); | |
| if (container_name.empty()) { | |
| LOG(ERROR) << "Could not get container name for token"; | |
| return false; | |
| } | |
| signal_proto->set_vm_name(std::move(vm_name)); | |
| signal_proto->set_container_name(std::move(container_name)); | |
| signal_proto->set_owner_id(std::move(owner_id)); | |
| return true; | |
| } | |
| explicit Service(base::OnceClosure quit_closure, | |
| scoped_refptr<dbus::Bus> bus); | |
| Service(const Service&) = delete; | |
| Service& operator=(const Service&) = delete; | |
| // Initializes the service by exporting our DBus methods, taking ownership of | |
| // its name, and starting our gRPC servers. If |unix_socket_path_for_testing| | |
| // has a value, the services are bound only to an AF_UNIX socket in that | |
| // directory instead of the normal VSOCK and AF_UNIX socket. | |
| bool Init(const std::optional<base::FilePath>& unix_socket_path_for_testing); | |
| // Handles the termination of a child process. | |
| void HandleChildExit(); | |
| // Handles a SIGTERM. | |
| void HandleSigterm(); | |
| // Handles notification a VM is starting. | |
| EmptyMessage NotifyVmStarted(const NotifyVmStartedRequest& request) override; | |
| // Handles a notification a VM is stopping. | |
| EmptyMessage NotifyVmStopping( | |
| const NotifyVmStoppingRequest& request) override; | |
| // Handles a notification a VM has stopped. | |
| EmptyMessage NotifyVmStopped(const NotifyVmStoppedRequest& request) override; | |
| // Handles a request to get a security token to associate with a container. | |
| ContainerTokenResponse GetContainerToken( | |
| const ContainerTokenRequest& request) override; | |
| // Handles a request to launch an application in a container. | |
| LaunchContainerApplicationResponse LaunchContainerApplication( | |
| const LaunchContainerApplicationRequest& request) override; | |
| // Handles a request to get application icons in a container. | |
| ContainerAppIconResponse GetContainerAppIcon( | |
| const ContainerAppIconRequest& request) override; | |
| // Handles a request to launch vshd in a container. | |
| LaunchVshdResponse LaunchVshd(const LaunchVshdRequest& request) override; | |
| // Handles a request to get Linux package info from a container. | |
| LinuxPackageInfoResponse GetLinuxPackageInfo( | |
| const LinuxPackageInfoRequest& request) override; | |
| // Handles a request to install a Linux package file in a container. | |
| InstallLinuxPackageResponse InstallLinuxPackage( | |
| const InstallLinuxPackageRequest& request) override; | |
| // Handles a request to uninstall the Linux package that owns the indicated | |
| // .desktop file. | |
| UninstallPackageOwningFileResponse UninstallPackageOwningFile( | |
| const UninstallPackageOwningFileRequest& request) override; | |
| // Handles a request to create an LXD container. | |
| CreateLxdContainerResponse CreateLxdContainer( | |
| const CreateLxdContainerRequest& request) override; | |
| // Handles a request to delete an LXD container. | |
| DeleteLxdContainerResponse DeleteLxdContainer( | |
| const DeleteLxdContainerRequest& request) override; | |
| // Handles a request to start an LXD container. | |
| StartLxdContainerResponse StartLxdContainer( | |
| const StartLxdContainerRequest& request) override; | |
| // Handles a request to stop an LXD container. | |
| StopLxdContainerResponse StopLxdContainer( | |
| const StopLxdContainerRequest& request) override; | |
| // Handles a request to set the default timezone for an LXD instance. | |
| SetTimezoneResponse SetTimezone(const SetTimezoneRequest& request) override; | |
| // Handles a request to get the primary username for an LXD container. | |
| GetLxdContainerUsernameResponse GetLxdContainerUsername( | |
| const GetLxdContainerUsernameRequest& request) override; | |
| // Handles a request to set up the user for an LXD container. | |
| SetUpLxdContainerUserResponse SetUpLxdContainerUser( | |
| const SetUpLxdContainerUserRequest& request) override; | |
| // Handles a request to export an LXD container. | |
| ExportLxdContainerResponse ExportLxdContainer( | |
| const ExportLxdContainerRequest& request) override; | |
| // Handles a request to import an LXD container. | |
| ImportLxdContainerResponse ImportLxdContainer( | |
| const ImportLxdContainerRequest& request) override; | |
| // Handles a request to cancel an ongoing LXD container export. | |
| CancelExportLxdContainerResponse CancelExportLxdContainer( | |
| const CancelExportLxdContainerRequest& request) override; | |
| // Handles a request to cancel an ongoing LXD container import. | |
| CancelImportLxdContainerResponse CancelImportLxdContainer( | |
| const CancelImportLxdContainerRequest& request) override; | |
| // Handles a request to connect to chunnel. | |
| ConnectChunnelResponse ConnectChunnel( | |
| const ConnectChunnelRequest& request) override; | |
| // Handles a request to get debug information. | |
| GetDebugInformationResponse GetDebugInformation( | |
| const GetDebugInformationRequest& request) override; | |
| // Handles a request to apply Ansible playbook to a container. | |
| ApplyAnsiblePlaybookResponse ApplyAnsiblePlaybook( | |
| const ApplyAnsiblePlaybookRequest& request) override; | |
| // Handles a request to allow sideloading Arc (android) apps from the | |
| // container. | |
| ConfigureForArcSideloadResponse ConfigureForArcSideload( | |
| const ConfigureForArcSideloadRequest& request) override; | |
| // Handles a request to upgrade a container. | |
| UpgradeContainerResponse UpgradeContainer( | |
| const UpgradeContainerRequest& request) override; | |
| // Handles a request to cancel an ongoing container upgrade. | |
| CancelUpgradeContainerResponse CancelUpgradeContainer( | |
| const CancelUpgradeContainerRequest& request) override; | |
| // Handles a request to start LXD. | |
| StartLxdResponse StartLxd(const StartLxdRequest& request) override; | |
| // Handles a request to add a file watch. | |
| AddFileWatchResponse AddFileWatch( | |
| const AddFileWatchRequest& request) override; | |
| // Handles a request to remove a file watch. | |
| RemoveFileWatchResponse RemoveFileWatch( | |
| const RemoveFileWatchRequest& request) override; | |
| // Handles a request to add a mapping between vsh and the session data such as | |
| // the container shell pid. | |
| RegisterVshSessionResponse RegisterVshSession( | |
| const RegisterVshSessionRequest& request) override; | |
| // Handles a request to retrieve vsh session data. | |
| GetVshSessionResponse GetVshSession( | |
| const GetVshSessionRequest& request) override; | |
| // Handles a notification from Chrome in response to a SelectFile() request. | |
| EmptyMessage FileSelected(const FileSelectedSignal& request) override; | |
| // Handles a request to attach a USB port to a container. | |
| AttachUsbToContainerResponse AttachUsbToContainer( | |
| const AttachUsbToContainerRequest& request) override; | |
| // Handles a request to detach a USB port from a container. | |
| DetachUsbFromContainerResponse DetachUsbFromContainer( | |
| const DetachUsbFromContainerRequest& request) override; | |
| // Handles a request to list containers. | |
| ListRunningContainersResponse ListRunningContainers( | |
| const ListRunningContainersRequest& request) override; | |
| // Handles a request to get session info from Garcon. | |
| GetGarconSessionInfoResponse GetGarconSessionInfo( | |
| const GetGarconSessionInfoRequest& request) override; | |
| // Handles a request to update the devices available to a container. | |
| UpdateContainerDevicesResponse UpdateContainerDevices( | |
| const UpdateContainerDevicesRequest& request) override; | |
| // Registers |hostname| and |ip| with the hostname resolver service so that | |
| // the container is reachable from a known hostname. | |
| void RegisterHostname(const std::string& hostname, const std::string& ip); | |
| // Unregisters containers associated with this |vm| with |owner_id| and | |
| // |vm_name|. All hostnames are removed from the hostname resolver service, | |
| // and the ContainerShutdown signal is sent via D-Bus. | |
| void UnregisterVmContainers(VirtualMachine* vm, | |
| const std::string& owner_id, | |
| const std::string& vm_name); | |
| // Unregisters |hostname| with the hostname resolver service. | |
| void UnregisterHostname(const std::string& hostname); | |
| // Callback for when the crosdns D-Bus service goes online (or is online | |
| // already) so we can then register the NameOwnerChanged callback. | |
| void OnCrosDnsServiceAvailable(bool service_is_available); | |
| // Callback for when the crosdns D-Bus service restarts so we can | |
| // re-register any of our hostnames that are active. | |
| void OnCrosDnsNameOwnerChanged(const std::string& old_owner, | |
| const std::string& new_owner); | |
| // Callback for when the localtime file is changed so that we can update | |
| // the timezone for containers. | |
| void OnLocaltimeFileChanged(const base::FilePath& path, bool error); | |
| void OnSignalReadable(); | |
| // Handles default service changes from shill. | |
| void OnDefaultNetworkServiceChanged(); | |
| // Send all listening ports to chunneld. | |
| void SendListeningPorts(); | |
| // Returns true if a metric reporting operation will be within the rules for | |
| // rate limiting, false if it should be blocked. This will also increment the | |
| // rate limit counter as a side effect. | |
| bool CheckReportMetricsRateLimit(const std::string& vm_name); | |
| // Gets a VirtualMachine pointer to the registered VM with corresponding | |
| // |owner_id| and |vm_name|. Returns a nullptr if not found. | |
| VirtualMachine* FindVm(const std::string& owner_id, | |
| const std::string& vm_name); | |
| // File descriptor for SIGTERM/SIGCHLD event. | |
| base::ScopedFD signal_fd_; | |
| std::unique_ptr<base::FileDescriptorWatcher::Controller> watcher_; | |
| // The shill D-Bus client. | |
| std::unique_ptr<ShillClient> shill_client_; | |
| // Key for VMs in the map, which is the owner ID and VM name as a pair. | |
| using VmKey = std::pair<std::string, std::string>; | |
| // Running VMs. | |
| std::map<VmKey, std::unique_ptr<VirtualMachine>> vms_; | |
| // Map of TCP4 ports to forwarding targets. | |
| using TcpForwardTarget = std::pair<std::string, std::string>; | |
| std::map<uint16_t, TcpForwardTarget> listening_tcp4_ports_; | |
| // Map of SelectFile() dialogs currently open. | |
| std::map<std::string, base::OnceCallback<void(std::vector<std::string>)>> | |
| select_file_dialogs_; | |
| // Connection to the system bus. | |
| scoped_refptr<dbus::Bus> bus_; | |
| dbus::ObjectProxy* vm_applications_service_proxy_; // Owned by |bus_|. | |
| dbus::ObjectProxy* url_handler_service_proxy_; // Owned by |bus_|. | |
| dbus::ObjectProxy* chunneld_service_proxy_; // Owned by |bus_|. | |
| dbus::ObjectProxy* crosdns_service_proxy_; // Owned by |bus_|. | |
| dbus::ObjectProxy* concierge_service_proxy_; // Owned by |bus_|. | |
| dbus::ObjectProxy* vm_sk_forwarding_service_proxy_; // Owned by |bus_|. | |
| dbus::ObjectProxy* shadercached_proxy_; // Owned by |bus_|. | |
| std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_; | |
| org::chromium::VmCiceroneAdaptor cicerone_adaptor_{this}; | |
| // The ContainerListener service. | |
| std::unique_ptr<ContainerListenerImpl> container_listener_; | |
| // Thread on which the ContainerListener service lives. | |
| base::Thread grpc_thread_container_{"gRPC Container Server Thread"}; | |
| // The server where the ContainerListener service lives. | |
| std::shared_ptr<grpc::Server> grpc_server_container_; | |
| // The TremplinListener service. | |
| std::unique_ptr<TremplinListenerImpl> tremplin_listener_; | |
| // Thread on which the TremplinListener service lives. | |
| base::Thread grpc_thread_tremplin_{"gRPC Tremplin Server Thread"}; | |
| // The server where the TremplinListener service lives. | |
| std::shared_ptr<grpc::Server> grpc_server_tremplin_; | |
| // The CrashListener service. | |
| std::unique_ptr<CrashListenerImpl> crash_listener_; | |
| // Thread on which the CrashListener service lives. | |
| base::Thread grpc_thread_crash_{"gRPC Crash Server Thread"}; | |
| // The server where the CrashListener service lives. | |
| std::shared_ptr<grpc::Server> grpc_server_crash_; | |
| // Closure that's posted to the current thread's TaskRunner when the service | |
| // receives a SIGTERM. | |
| base::OnceClosure quit_closure_; | |
| // Ensure calls are made on the right thread. | |
| base::SequenceChecker sequence_checker_; | |
| // Map of hostnames/IPs we have registered so we can re-register them if the | |
| // resolver service restarts. | |
| std::map<std::string, std::string> hostname_mappings_; | |
| // IP address registered for 'linuxhost' so we can swap this out on OpenUrl | |
| // calls. | |
| std::string linuxhost_ip_; | |
| // Owner of the primary VM, we only do hostname mappings for the primary VM. | |
| std::string primary_owner_id_; | |
| // Handle to the SSH port forwarding process. | |
| brillo::ProcessImpl ssh_process_; | |
| // Watcher to monitor changes to the system timezone file. | |
| base::FilePathWatcher localtime_watcher_; | |
| // Handler and accumulator for guest metrics. | |
| std::unique_ptr<GuestMetrics> guest_metrics_; | |
| // Helper for shadercached requests | |
| std::unique_ptr<ShadercachedHelper> shadercached_helper_; | |
| // Should Service create GuestMetric instance on initialization? Used for | |
| // testing. | |
| static bool create_guest_metrics_; | |
| // Should Service start GRPC servers for ContainerListener and | |
| // TremplinListener Used for testing | |
| static bool run_grpc_; | |
| // Per-VM rate limiting for metric reporting. | |
| struct RateLimitState { | |
| uint32_t count; | |
| base::TimeTicks window_start; | |
| }; | |
| std::map<std::string, RateLimitState> metric_rate_limit_state_; | |
| base::WeakPtrFactory<Service> weak_ptr_factory_; | |
| }; | |
| } // namespace vm_tools::cicerone | |
| #endif // VM_TOOLS_CICERONE_SERVICE_H_ |