| // Copyright 2018 The Chromium OS 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 VM_TOOLS_CICERONE_SERVICE_H_ |
| #define VM_TOOLS_CICERONE_SERVICE_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/callback.h> |
| #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/logging.h> |
| #include <base/macros.h> |
| #include <base/memory/ref_counted.h> |
| #include <base/memory/weak_ptr.h> |
| #include <base/optional.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/proto_bindings/apps.pb.h> |
| #include <vm_cicerone/proto_bindings/cicerone_service.pb.h> |
| #include <vm_concierge/proto_bindings/concierge_service.pb.h> |
| #include <vm_sk_forwarding/proto_bindings/sk_forwarding.pb.h> |
| #include <vm_disk_management/proto_bindings/disk_management.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/shill_client.h" |
| #include "vm_tools/cicerone/tremplin_listener_impl.h" |
| #include "vm_tools/cicerone/virtual_machine.h" |
| |
| namespace vm_tools { |
| namespace cicerone { |
| |
| // VM Container Service responsible for responding to DBus method calls for |
| // interacting with VM containers. |
| class Service final { |
| 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::Closure quit_closure, |
| const base::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(); |
| |
| // 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, |
| }; |
| |
| // 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 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, |
| 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); |
| |
| // Sends a D-Bus message to Chrome to request information about the VM disk, |
| // how much space is available and how much it could be expanded by. It uses |
| // |cid| and |container_token| to identify the source and somewhat verify that |
| // it is borealis (the only VM this method is available for). |result| is |
| // filled with information about the disk, if the request fails, than the |
| // error field will be set to !0. Signals |event| when done. |
| void GetDiskInfo(const std::string& container_token, |
| const uint32_t cid, |
| vm_tools::disk_management::GetDiskInfoResponse* result, |
| base::WaitableEvent* event); |
| |
| // Sends a D-Bus message to Chrome to request that the VM disk be expanded by |
| // |space_requested| bytes. It uses |cid| and |container_token| to identify |
| // the source and somewhat verify that it is borealis (the only VM this method |
| // is available for). If a resize occurs, |result| will be filled with the |
| // information of how many bytes the disk was expanded by, if the request |
| // fails, than the error field will be set to !0. Signals |event| when done. |
| void RequestSpace(const std::string& container_token, |
| const uint32_t cid, |
| const uint64_t space_requested, |
| vm_tools::disk_management::RequestSpaceResponse* result, |
| base::WaitableEvent* event); |
| |
| // Sends a D-Bus message to Chrome to notify it that the VM disk can be |
| // shrunk by |space_to_release| bytes. It uses |cid| and |container_token| to |
| // identify the source and somewhat verify that it is borealis (the only VM |
| // this method is available for). If a resize occurs, |result| will be filled |
| // with the information of how many bytes the disk was shrunk by, if the |
| // request fails, than the error field will be set to !0. Signals |event| when |
| // done. |
| void ReleaseSpace(const std::string& container_token, |
| const uint32_t cid, |
| const uint64_t space_to_release, |
| vm_tools::disk_management::ReleaseSpaceResponse* result, |
| base::WaitableEvent* event); |
| |
| private: |
| // Sends the |signal_name| D-Bus signal with |signal_proto| as its contents. |
| // It will use |cid| to lookup VM and owner, and set these fields on |
| // |signal_proto| before sending it. |
| template <typename T> |
| bool SendSignal(const std::string& signal_name, |
| 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; |
| } |
| |
| dbus::Signal signal(kVmCiceroneInterface, signal_name); |
| signal_proto->set_vm_name(std::move(vm_name)); |
| signal_proto->set_owner_id(std::move(owner_id)); |
| dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(*signal_proto); |
| exported_object_->SendSignal(&signal); |
| return true; |
| } |
| |
| // Sends the |signal_name| D-Bus signal with |signal_proto| as its contents. |
| // It will use |cid| and |container_token| to lookup VM, owner, and container |
| // name, and set these fields on |signal_proto| before sending it. |
| template <typename T> |
| bool SendSignal(const std::string& signal_name, |
| 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; |
| } |
| |
| dbus::Signal signal(kVmCiceroneInterface, signal_name); |
| 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)); |
| dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(*signal_proto); |
| exported_object_->SendSignal(&signal); |
| return true; |
| } |
| |
| // Sends the disk-related |method_name| D-Bus method with |input_proto| as |
| // its contents. It will use |cid| and |container_token| to lookup VM, owner, |
| // and container name, and set these fields on the |origin| of |input_proto| |
| // before sending it and storing the response in |output_proto|. |
| template <typename I, typename O> |
| bool SendDiskMethod(const std::string& method_name, |
| const std::string& container_token, |
| const uint32_t cid, |
| I* input_proto, |
| O* output_proto) { |
| DCHECK(sequence_checker_.CalledOnValidSequence()); |
| CHECK(output_proto); |
| output_proto->set_error(1); |
| 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; |
| } |
| |
| std::string container_name = vm->GetContainerNameForToken(container_token); |
| if (container_name.empty()) { |
| LOG(ERROR) << "Could not get container name for token"; |
| return false; |
| } |
| |
| vm_tools::disk_management::MessageOrigin* origin = |
| new vm_tools::disk_management::MessageOrigin(); |
| origin->set_vm_name(vm_name); |
| origin->set_container_name(container_name); |
| origin->set_owner_id(owner_id); |
| input_proto->set_allocated_origin(origin); |
| dbus::MethodCall method_call( |
| vm_tools::disk_management::kVmDiskManagementServiceInterface, |
| method_name); |
| dbus::MessageWriter(&method_call).AppendProtoAsArrayOfBytes(*input_proto); |
| std::unique_ptr<dbus::Response> dbus_response = |
| vm_disk_management_service_proxy_->CallMethodAndBlock( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); |
| |
| dbus::MessageReader reader(dbus_response.get()); |
| O response; |
| if (!reader.PopArrayOfBytesAsProto(&response)) { |
| LOG(ERROR) << "Unable to parse GetDiskInfoReponse from response"; |
| output_proto->set_error(1); |
| } else { |
| *output_proto = response; |
| } |
| return true; |
| } |
| |
| explicit Service(base::Closure 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 base::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. |
| std::unique_ptr<dbus::Response> NotifyVmStarted( |
| dbus::MethodCall* method_call); |
| |
| // Handles a notification a VM is stopping. |
| std::unique_ptr<dbus::Response> NotifyVmStopping( |
| dbus::MethodCall* method_call); |
| |
| // Handles a notification a VM has stopped. |
| std::unique_ptr<dbus::Response> NotifyVmStopped( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to get a security token to associate with a container. |
| std::unique_ptr<dbus::Response> GetContainerToken( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to launch an application in a container. |
| std::unique_ptr<dbus::Response> LaunchContainerApplication( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to get application icons in a container. |
| std::unique_ptr<dbus::Response> GetContainerAppIcon( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to launch vshd in a container. |
| std::unique_ptr<dbus::Response> LaunchVshd(dbus::MethodCall* method_call); |
| |
| // Handles a request to get Linux package info from a container. |
| std::unique_ptr<dbus::Response> GetLinuxPackageInfo( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to install a Linux package file in a container. |
| std::unique_ptr<dbus::Response> InstallLinuxPackage( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to uninstall the Linux package that owns the indicated |
| // .desktop file. |
| std::unique_ptr<dbus::Response> UninstallPackageOwningFile( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to create an LXD container. |
| std::unique_ptr<dbus::Response> CreateLxdContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to delete an LXD container. |
| std::unique_ptr<dbus::Response> DeleteLxdContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to start an LXD container. |
| std::unique_ptr<dbus::Response> StartLxdContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to set the default timezone for an LXD instance. |
| std::unique_ptr<dbus::Response> SetTimezone(dbus::MethodCall* method_call); |
| |
| // Handles a request to get the primary username for an LXD container. |
| std::unique_ptr<dbus::Response> GetLxdContainerUsername( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to set up the user for an LXD container. |
| std::unique_ptr<dbus::Response> SetUpLxdContainerUser( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to export an LXD container. |
| std::unique_ptr<dbus::Response> ExportLxdContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to cancel an ongoing LXD container export. |
| std::unique_ptr<dbus::Response> CancelExportLxdContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to import an LXD container. |
| std::unique_ptr<dbus::Response> ImportLxdContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to cancel an ongoing LXD container import. |
| std::unique_ptr<dbus::Response> CancelImportLxdContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to connect to chunnel. |
| std::unique_ptr<dbus::Response> ConnectChunnel(dbus::MethodCall* method_call); |
| |
| // Handles a request to get debug information. |
| std::unique_ptr<dbus::Response> GetDebugInformation( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to apply Ansible playbook to a container. |
| std::unique_ptr<dbus::Response> ApplyAnsiblePlaybook( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to allow sideloading Arc (android) apps from the |
| // container. |
| std::unique_ptr<dbus::Response> ConfigureForArcSideload( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to upgrade a container. |
| std::unique_ptr<dbus::Response> UpgradeContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to cancel an ongoing container upgrade. |
| std::unique_ptr<dbus::Response> CancelUpgradeContainer( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to start LXD. |
| std::unique_ptr<dbus::Response> StartLxd(dbus::MethodCall* method_call); |
| |
| // Handles a request to add a file watch. |
| std::unique_ptr<dbus::Response> AddFileWatch(dbus::MethodCall* method_call); |
| |
| // Handles a request to remove a file watch. |
| std::unique_ptr<dbus::Response> RemoveFileWatch( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to add a mapping between vsh and the session data such as |
| // the container shell pid. |
| std::unique_ptr<dbus::Response> RegisterVshSession( |
| dbus::MethodCall* method_call); |
| |
| // Handles a request to retrieve vsh session data. |
| std::unique_ptr<dbus::Response> GetVshSession(dbus::MethodCall* method_call); |
| |
| // Handles a notification from Chrome in response to a SelectFile() request. |
| std::unique_ptr<dbus::Response> FileSelected(dbus::MethodCall* method_call); |
| |
| // Gets the container's SSH keys from concierge. |
| bool GetContainerSshKeys(const std::string& owner_id, |
| const std::string& vm_name, |
| const std::string& container_name, |
| std::string* host_pubkey_out, |
| std::string* host_privkey_out, |
| std::string* container_pubkey_out, |
| std::string* container_privkey_out, |
| std::string* hostname_out, |
| std::string* error_out); |
| |
| // 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(); |
| |
| // 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::ExportedObject* exported_object_; // Owned by |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* vm_disk_management_service_proxy_; // Owned by |bus_|. |
| |
| // 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::Closure 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_; |
| |
| // Should Service start GRPC servers for ContainerListener and |
| // TremplinListener Used for testing |
| static bool run_grpc_; |
| |
| base::WeakPtrFactory<Service> weak_ptr_factory_; |
| }; |
| |
| } // namespace cicerone |
| } // namespace vm_tools |
| |
| #endif // VM_TOOLS_CICERONE_SERVICE_H_ |