diff --git a/include/multipass/daemon_rpc_context.h b/include/multipass/daemon_rpc_context.h
new file mode 100644
index 0000000000..9424032ef6
--- /dev/null
+++ b/include/multipass/daemon_rpc_context.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Canonical, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#pragma once
+
+#include
+
+#include
+
+#include
+#include
+
+namespace multipass
+{
+
+struct DaemonRpcContext
+{
+ virtual void set_value(grpc::Status status) = 0;
+ virtual ~DaemonRpcContext() = default;
+};
+
+template
+struct DaemonRpcContextImpl : DaemonRpcContext, private multipass::DisabledCopyMove
+{
+ DaemonRpcContextImpl(std::promise& promise,
+ grpc::ServerReaderWriterInterface* server,
+ logging::Level level,
+ logging::MultiplexingLogger& mpx)
+ : promise(promise),
+ // We have to construct the logger here since we can't move or copy it.
+ logger{std::make_optional>(level, mpx, server)}
+ {
+ }
+
+ void set_value(grpc::Status status) override
+ {
+ // Free any resources that depend on server here.
+ logger.reset();
+ promise.set_value(std::move(status));
+ }
+
+private:
+ std::promise& promise;
+ std::optional> logger;
+};
+
+} // namespace multipass
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index 2d5aa9846f..9d0b03bf68 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -24,6 +24,8 @@
#include
#include
#include
+
+#include
#include
#include
#include
@@ -968,8 +970,8 @@ mp::MemorySize compute_final_image_size(const mp::MemorySize image_size,
if (!command_line_value)
{
auto default_disk_size_as_struct = mp::MemorySize(mp::default_disk_size);
- disk_space =
- image_size < default_disk_size_as_struct ? default_disk_size_as_struct : image_size;
+ disk_space = image_size < default_disk_size_as_struct ? default_disk_size_as_struct
+ : image_size;
}
else if (*command_line_value < image_size)
{
@@ -1288,7 +1290,10 @@ mp::Daemon::Daemon(std::unique_ptr the_config)
mp::utils::backend_directory_path(config->cache_directory,
config->factory->get_backend_directory_name()),
*config->az_manager)},
- daemon_rpc{config->server_address, *config->cert_provider, config->client_cert_store.get()},
+ daemon_rpc{config->server_address,
+ *config->cert_provider,
+ config->client_cert_store.get(),
+ config->logger},
instance_mod_handler{register_instance_mod(
vm_instance_specs,
operative_instances,
@@ -1533,31 +1538,22 @@ void mp::Daemon::shutdown_grpc_server()
void mp::Daemon::create(const CreateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
- return create_vm(request, server, status_promise, /*start=*/false);
+ return create_vm(request, server, context, /*start=*/false);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::launch(const LaunchRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
- return create_vm(request, server, status_promise, /*start=*/true);
+ return create_vm(request, server, context, /*start=*/true);
}
catch (const mp::StartException& e)
{
@@ -1567,16 +1563,16 @@ catch (const mp::StartException& e)
operative_instances.erase(name);
persist_instances();
- status_promise->set_value(grpc::Status(grpc::StatusCode::ABORTED, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::ABORTED, e.what(), ""));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::purge(const PurgeRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
PurgeReply response;
@@ -1593,21 +1589,18 @@ try
persist_instances();
server->Write(response);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::find(const FindRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
FindReply response;
if (!request->search_string().empty())
@@ -1654,8 +1647,8 @@ try
auto remote_name = (!request->remote_name().empty() ||
(request->remote_name().empty() && vm_images_info.size() > 1 &&
remote != mp::release_remote))
- ? remote
- : "";
+ ? remote
+ : "";
add_aliases(response.mutable_images_info(), remote_name, info);
}
@@ -1694,21 +1687,18 @@ try
}
server->Write(response);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::info(const InfoRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
InfoReply response;
config->update_prompt->populate_if_time_to_show(response.mutable_update_info());
InstanceSnapshotsMap instance_snapshots_map;
@@ -1740,8 +1730,8 @@ try
const auto& name = vm.get_name();
const auto& it = instance_snapshots_map.find(name);
- const auto& snapshot_pick =
- it == instance_snapshots_map.end() ? SnapshotPick{{}, true} : it->second;
+ const auto& snapshot_pick = it == instance_snapshots_map.end() ? SnapshotPick{{}, true}
+ : it->second;
try
{
@@ -1790,21 +1780,18 @@ try
server->Write(response);
}
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::list(const ListRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
ListReply response;
config->update_prompt->populate_if_time_to_show(response.mutable_update_info());
@@ -1899,22 +1886,18 @@ try
}
server->Write(response);
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::networks(const NetworksRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
NetworksReply response;
config->update_prompt->populate_if_time_to_show(response.mutable_update_info());
@@ -1932,24 +1915,20 @@ try
}
server->Write(response);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::mount(const MountRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
if (!MP_SETTINGS.get_as(mp::mounts_key))
- return status_promise->set_value(grpc::Status(
+ return context->set_value(grpc::Status(
grpc::StatusCode::FAILED_PRECONDITION,
"Mounts are disabled on this installation of Multipass.\n\n"
"See https://canonical.com/multipass/docs/set-command#local.privileged-mounts for "
@@ -2006,8 +1985,8 @@ try
}
const auto mount_type = request->mount_type() == MountRequest_MountType_CLASSIC
- ? VMMount::MountType::Classic
- : VMMount::MountType::Native;
+ ? VMMount::MountType::Classic
+ : VMMount::MountType::Native;
VMMount vm_mount{request->source_path(), gid_mappings, uid_mappings, mount_type};
vm_mounts[target_path] = make_mount(vm.get(), target_path, vm_mount);
@@ -2020,7 +1999,7 @@ try
}
catch (const mp::SSHFSMissingError&)
{
- return status_promise->set_value(grpc_status_for_mount_error(name));
+ return context->set_value(grpc_status_for_mount_error(name));
}
catch (const std::exception& e)
{
@@ -2035,23 +2014,18 @@ try
persist_instances();
- status_promise->set_value(grpc_status_for(errors));
+ context->set_value(grpc_status_for(errors));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::recover(const RecoverRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
auto recover_reaction = require_existing_instances_reaction;
recover_reaction.operative_reaction.message_template =
"instance \"{}\" does not need to be recovered";
@@ -2078,23 +2052,18 @@ try
persist_instances();
}
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::ssh_info(const SSHInfoRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
auto [instance_selection, status] =
select_instances_and_react(operative_instances,
deleted_instances,
@@ -2113,24 +2082,20 @@ try
server->Write(response);
}
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::start(const StartRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
- auto timeout =
- request->timeout() > 0 ? std::chrono::seconds(request->timeout()) : mp::default_timeout;
+ auto timeout = request->timeout() > 0 ? std::chrono::seconds(request->timeout())
+ : mp::default_timeout;
if (!instances_running(operative_instances))
config->factory->hypervisor_health_check();
@@ -2146,9 +2111,9 @@ try
custom_reaction);
if (!status.ok())
- return status_promise->set_value({status.error_code(),
- "instance(s) missing",
- make_start_error_details(instance_selection)});
+ return context->set_value({status.error_code(),
+ "instance(s) missing",
+ make_start_error_details(instance_selection)});
bool complain_disabled_mounts = !MP_SETTINGS.get_as(mp::mounts_key);
@@ -2210,24 +2175,20 @@ try
server,
starting_vms,
timeout,
- status_promise,
+ context,
fmt::to_string(start_errors),
fmt::to_string(start_warnings)));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::stop(const StopRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
auto [instance_selection, status] =
select_instances_and_react(operative_instances,
deleted_instances,
@@ -2252,27 +2213,22 @@ try
status = cmd_vms(instance_selection.operative_selection, operation);
}
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const mp::VMStateInvalidException& e)
{
- status_promise->set_value(grpc::Status{grpc::StatusCode::FAILED_PRECONDITION, e.what()});
+ context->set_value(grpc::Status{grpc::StatusCode::FAILED_PRECONDITION, e.what()});
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what()));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what()));
}
void mp::Daemon::suspend(const SuspendRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
auto [instance_selection, status] =
select_instances_and_react(operative_instances,
deleted_instances,
@@ -2298,25 +2254,20 @@ try
});
}
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::restart(const RestartRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
- auto timeout =
- request->timeout() > 0 ? std::chrono::seconds(request->timeout()) : mp::default_timeout;
+ auto timeout = request->timeout() > 0 ? std::chrono::seconds(request->timeout())
+ : mp::default_timeout;
auto [instance_selection, status] =
select_instances_and_react(operative_instances,
@@ -2327,7 +2278,7 @@ try
if (!status.ok())
{
- return status_promise->set_value(status);
+ return context->set_value(status);
}
const auto& instance_targets = instance_selection.operative_selection;
@@ -2339,7 +2290,7 @@ try
if (!status.ok())
{
- return status_promise->set_value(status);
+ return context->set_value(status);
}
auto future_watcher = create_future_watcher();
@@ -2349,24 +2300,20 @@ try
server,
names_from(instance_targets),
timeout,
- status_promise,
+ context,
std::string(),
std::string()));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::delet(const DeleteRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
DeleteReply response;
auto [instance_selection, status] =
@@ -2401,7 +2348,7 @@ try
throw std::runtime_error("Cannot get confirmation from client. Aborting...");
if (!(purge_snapshots = client_response.purge_snapshots()))
- return status_promise->set_value(grpc::Status{grpc::CANCELLED, "Cancelled."});
+ return context->set_value(grpc::Status{grpc::CANCELLED, "Cancelled."});
}
// start with deleted instances, to avoid iterator invalidation when moving instances there
@@ -2422,8 +2369,8 @@ try
auto snapshot_pick_it = instance_snapshots_map.find(instance_name);
const auto& [pick, all] = snapshot_pick_it == instance_snapshots_map.end()
- ? SnapshotPick{{}, true}
- : snapshot_pick_it->second;
+ ? SnapshotPick{{}, true}
+ : snapshot_pick_it->second;
if (!all || !purge) // if we're not purging the instance, we need to delete
// specified snapshots
@@ -2440,27 +2387,22 @@ try
}
server->Write(response);
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const mp::VMStateInvalidException& e)
{
- status_promise->set_value(grpc::Status{grpc::StatusCode::FAILED_PRECONDITION, e.what()});
+ context->set_value(grpc::Status{grpc::StatusCode::FAILED_PRECONDITION, e.what()});
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what()));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what()));
}
void mp::Daemon::umount(const UmountRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
fmt::memory_buffer errors;
for (const auto& path_entry : request->target_paths())
{
@@ -2518,38 +2460,29 @@ try
persist_instances();
- status_promise->set_value(grpc_status_for(errors));
+ context->set_value(grpc_status_for(errors));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::version(const VersionRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
VersionReply reply;
reply.set_version(multipass::version_string);
config->update_prompt->populate(reply.mutable_update_info());
server->Write(reply);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
void mp::Daemon::get(const GetRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
GetReply reply;
auto key = request->key();
@@ -2558,26 +2491,22 @@ try
reply.set_value(val);
server->Write(reply);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
catch (const mp::UnrecognizedSettingException& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
}
void mp::Daemon::set(const SetRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
auto key = request->key();
auto val = request->val();
std::string bridge_name;
@@ -2599,7 +2528,7 @@ try
MP_SETTINGS.set(QString::fromStdString(key), QString::fromStdString(val));
mpl::debug(category, "Succeeded setting {}={}", key, val);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
catch (const mp::NonAuthorizedBridgeSettingsException& e)
{
@@ -2625,46 +2554,41 @@ catch (const mp::NonAuthorizedBridgeSettingsException& e)
mpl::debug(category, "Succeeded setting {}={}", key, val);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
else
{
mpl::debug(category, "User did not authorize, cancelling");
- status_promise->set_value(
- grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
}
catch (const mp::BridgeFailureException& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
}
catch (const mp::UnrecognizedSettingException& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
}
catch (const mp::InstanceStateSettingsException& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
catch (const mp::InvalidSettingException& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
}
void mp::Daemon::keys(const mp::KeysRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
KeysReply reply;
for (const auto& key : MP_SETTINGS.keys())
@@ -2673,29 +2597,24 @@ try
mpl::debug(category, "Returning {} settings keys", reply.settings_keys_size());
server->Write(reply);
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
}
void mp::Daemon::authenticate(
const AuthenticateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
auto stored_hash = MP_SETTINGS.get(mp::passphrase_key);
if (stored_hash.isNull() || stored_hash.isEmpty())
{
- return status_promise->set_value(grpc::Status(
+ return context->set_value(grpc::Status(
grpc::StatusCode::FAILED_PRECONDITION,
"Incorrect passphrase. No passphrase is set.\n\n"
"To authenticate, first ask an authenticated user to set a passphrase and share it "
@@ -2708,28 +2627,22 @@ try
if (stored_hash != hashed_passphrase)
{
- return status_promise->set_value(
- grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
- "Passphrase is not correct. Please try again."));
+ return context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Passphrase is not correct. Please try again."));
}
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
}
void mp::Daemon::snapshot(const mp::SnapshotRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
const auto& instance_name = request->instance();
auto [instance_trail, status] = find_instance_and_react(operative_instances,
deleted_instances,
@@ -2744,13 +2657,13 @@ try
using St = VirtualMachine::State;
if (auto state = vm_ptr->current_state(); state != St::off && state != St::stopped)
- return status_promise->set_value(
+ return context->set_value(
grpc::Status{grpc::FAILED_PRECONDITION,
"Multipass can only take snapshots of stopped instances."});
auto snapshot_name = request->snapshot();
if (!snapshot_name.empty() && !mp::utils::valid_hostname(snapshot_name))
- return status_promise->set_value(
+ return context->set_value(
grpc::Status{grpc::INVALID_ARGUMENT,
fmt::format(R"(Invalid snapshot name: "{}".)", snapshot_name)});
@@ -2764,27 +2677,22 @@ try
server->Write(reply);
}
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const SnapshotNameTakenException& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
}
void mp::Daemon::restore(const mp::RestoreRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
RestoreReply reply;
const auto& instance_name = request->instance();
auto [instance_trail, status] = find_instance_and_react(operative_instances,
@@ -2804,7 +2712,7 @@ try
using St = VirtualMachine::State;
if (auto state = vm_ptr->current_state(); state != St::off && state != St::stopped)
- return status_promise->set_value(
+ return context->set_value(
grpc::Status{grpc::FAILED_PRECONDITION,
"Multipass can only restore snapshots of stopped instances."});
@@ -2853,26 +2761,22 @@ try
server->Write(reply);
}
- status_promise->set_value(status);
+ context->set_value(status);
}
catch (const mp::NoSuchSnapshotException& e)
{
- status_promise->set_value(grpc::Status{grpc::StatusCode::NOT_FOUND, e.what(), ""});
+ context->set_value(grpc::Status{grpc::StatusCode::NOT_FOUND, e.what(), ""});
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
}
void mp::Daemon::clone(const CloneRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
const auto& source_name = request->source_name();
const auto [src_instance_trail, src_vm_status] =
find_instance_and_react(operative_instances,
@@ -2888,14 +2792,13 @@ try
if (source_vm_state != VirtualMachine::State::stopped &&
source_vm_state != VirtualMachine::State::off)
{
- return status_promise->set_value(
- grpc::Status{grpc::FAILED_PRECONDITION,
- "Multipass can only clone stopped instances."});
+ return context->set_value(grpc::Status{grpc::FAILED_PRECONDITION,
+ "Multipass can only clone stopped instances."});
}
const std::string destination_name = dest_name_for_clone(*request);
if (auto dest_vm_status = validate_dest_name(destination_name); !dest_vm_status.ok())
- return status_promise->set_value(std::move(dest_vm_status));
+ return context->set_value(std::move(dest_vm_status));
auto rollback_resources = sg::make_scope_guard([this, destination_name]() noexcept -> void {
top_catch_all(category, [this, destination_name]() {
@@ -2937,24 +2840,19 @@ try
server->Write(rpc_response);
rollback_resources.dismiss();
}
- status_promise->set_value(src_vm_status);
+ context->set_value(src_vm_status);
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what()));
+ context->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what()));
}
void mp::Daemon::daemon_info(
const DaemonInfoRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
DaemonInfoReply response;
QStorageInfo storage_info{config->data_directory};
@@ -2964,27 +2862,22 @@ try
response.set_memory(MP_PLATFORM.get_total_ram());
server->Write(response);
- status_promise->set_value(grpc::Status{});
+ context->set_value(grpc::Status{});
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::wait_ready(
const WaitReadyRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise)
+ DaemonRpcContext* context)
try
{
WaitReadyReply response;
- mpl::ClientLogger logger{
- mpl::level_from(request->verbosity_level()),
- *config->logger,
- server};
-
- logger.log(mpl::Level::debug, "daemon", "Checking connection to image servers...");
+ mpl::debug("daemon", "Checking connection to image servers...");
// We use wait_update_manifests_all_and_optionally_applied_force to check connectivity to image
// servers.
@@ -2992,32 +2885,28 @@ try
{
wait_update_manifests_all_and_optionally_applied_force(
/*force_manifest_network_download=*/false);
- logger.log(mpl::Level::debug, "daemon", "Successfully connected to image servers.");
- status_promise->set_value(grpc::Status::OK);
+ mpl::debug("daemon", "Successfully connected to image servers.");
+ context->set_value(grpc::Status::OK);
}
catch (const mp::DownloadException& e)
{
- logger.log(mpl::Level::warning,
- "daemon",
- fmt::format("Failed to connect to image servers: {}", e.what()));
+ mpl::warn("daemon", "Failed to connect to image servers: {}", e.what());
grpc::Status download_error_status{grpc::StatusCode::NOT_FOUND,
"cannot connect to the image servers",
""};
- status_promise->set_value(download_error_status);
+ context->set_value(download_error_status);
}
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::zones(const ZonesRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise) // clang-format off
+ DaemonRpcContext* context) // clang-format off
try // clang-format on
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()), *config->logger, server};
-
ZonesReply response{};
for (const auto& zone : config->az_manager->get_zones())
@@ -3028,21 +2917,19 @@ try // clang-format on
}
server->Write(response);
- status_promise->set_value(grpc::Status{});
+ context->set_value(grpc::Status{});
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::zones_state(
const ZonesStateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise) // clang-format off
+ DaemonRpcContext* context) // clang-format off
try // clang-format on
{
- mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()), *config->logger, server};
-
auto& az_manager = *config->az_manager;
if (request->zones().empty())
{
@@ -3059,15 +2946,15 @@ try // clang-format on
}
}
- status_promise->set_value(grpc::Status{});
+ context->set_value(grpc::Status{});
}
catch (const AvailabilityZoneNotFound& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));
}
catch (const std::exception& e)
{
- status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
+ context->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
void mp::Daemon::on_shutdown()
@@ -3155,17 +3042,16 @@ void mp::Daemon::release_resources(const std::string& instance)
void mp::Daemon::create_vm(const CreateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise,
+ DaemonRpcContext* context,
bool start)
{
auto checked_args = validate_create_arguments(request, config.get());
if (!checked_args.option_errors.error_codes().empty())
{
- return status_promise->set_value(
- grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
- "Invalid arguments supplied",
- checked_args.option_errors.SerializeAsString()));
+ return context->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid arguments supplied",
+ checked_args.option_errors.SerializeAsString()));
}
else if (auto& nets = checked_args.nets_need_bridging;
!nets.empty() && !request->permission_to_bridge())
@@ -3180,9 +3066,9 @@ void mp::Daemon::create_vm(const CreateRequest* request,
RepeatedPtrField from the range, then move-assigns that temporary in */
server->Write(reply);
- return status_promise->set_value(grpc::Status{grpc::StatusCode::FAILED_PRECONDITION,
- "Missing bridges",
- create_error.SerializeAsString()});
+ return context->set_value(grpc::Status{grpc::StatusCode::FAILED_PRECONDITION,
+ "Missing bridges",
+ create_error.SerializeAsString()});
}
auto name = name_from(checked_args.instance_name, *config->name_generator, operative_instances);
@@ -3197,12 +3083,12 @@ void mp::Daemon::create_vm(const CreateRequest* request,
assert(status.ok() == (instance_trail.index() == 2));
if (!status.ok())
- return status_promise->set_value(status);
+ return context->set_value(status);
if (preparing_instances.find(name) != preparing_instances.end())
- return status_promise->set_value({grpc::StatusCode::INVALID_ARGUMENT,
- fmt::format("instance \"{}\" is being prepared", name),
- ""});
+ return context->set_value({grpc::StatusCode::INVALID_ARGUMENT,
+ fmt::format("instance \"{}\" is being prepared", name),
+ ""});
if (!instances_running(operative_instances))
config->factory->hypervisor_health_check();
@@ -3217,7 +3103,7 @@ void mp::Daemon::create_vm(const CreateRequest* request,
QObject::connect(
prepare_future_watcher,
&QFutureWatcher::finished,
- [this, server, status_promise, name, timeout, start, prepare_future_watcher, log_level] {
+ [this, server, context, name, timeout, start, prepare_future_watcher, log_level] {
mpl::ClientLogger logger{log_level,
*config->logger,
server};
@@ -3272,13 +3158,13 @@ void mp::Daemon::create_vm(const CreateRequest* request,
server,
std::vector{name},
timeout,
- status_promise,
+ context,
std::string(),
std::string()));
}
else
{
- status_promise->set_value(grpc::Status::OK);
+ context->set_value(grpc::Status::OK);
}
}
catch (const std::exception& e)
@@ -3290,7 +3176,7 @@ void mp::Daemon::create_vm(const CreateRequest* request,
persist_instances();
});
- status_promise->set_value(
+ context->set_value(
grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), ""));
}
@@ -3627,11 +3513,11 @@ mp::MountHandler::UPtr mp::Daemon::make_mount(VirtualMachine* vm,
const VMMount& mount)
{
return mount.get_mount_type() == VMMount::MountType::Classic
- ? std::make_unique(vm,
- config->ssh_key_provider.get(),
- target,
- mount)
- : vm->make_native_mount_handler(target, mount);
+ ? std::make_unique(vm,
+ config->ssh_key_provider.get(),
+ target,
+ mount)
+ : vm->make_native_mount_handler(target, mount);
}
QFutureWatcher* mp::Daemon::create_future_watcher(
@@ -3743,7 +3629,7 @@ mp::Daemon::AsyncOperationStatus
mp::Daemon::async_wait_for_ready_all(grpc::ServerReaderWriterInterface* server,
const std::vector& vms,
const std::chrono::seconds& timeout,
- std::promise* status_promise,
+ DaemonRpcContext* context,
const std::string& start_errors,
const std::string& start_warnings)
{
@@ -3808,7 +3694,7 @@ mp::Daemon::async_wait_for_ready_all(grpc::ServerReaderWriterInterfaceset_value(async_op_result.status);
+ if (async_op_result.context)
+ async_op_result.context->set_value(async_op_result.status);
}
void mp::Daemon::update_manifests_all(const bool force_update)
@@ -3936,9 +3822,9 @@ void mp::Daemon::populate_instance_info(VirtualMachine& vm,
std::string mp::Daemon::dest_name_for_clone(const CloneRequest& request)
{
return request.has_destination_name()
- ? request.destination_name()
- : generate_next_clone_name(vm_instance_specs.at(request.source_name()).clone_count,
- request.source_name());
+ ? request.destination_name()
+ : generate_next_clone_name(vm_instance_specs.at(request.source_name()).clone_count,
+ request.source_name());
};
grpc::Status mp::Daemon::validate_dest_name(const std::string& name)
diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h
index 2929cbda33..ef722ad4e3 100644
--- a/src/daemon/daemon.h
+++ b/src/daemon/daemon.h
@@ -41,6 +41,7 @@
namespace multipass
{
struct DaemonConfig;
+struct DaemonRpcContext;
class SettingsHandler;
class Daemon : public QObject, public multipass::VMStatusMonitor
@@ -68,122 +69,124 @@ public slots:
virtual void create(const CreateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void launch(const LaunchRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void purge(const PurgeRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void find(const FindRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void info(const InfoRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void list(const ListRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void networks(const NetworksRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void mount(const MountRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void recover(const RecoverRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void ssh_info(const SSHInfoRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void start(const StartRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void stop(const StopRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void suspend(const SuspendRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void restart(const RestartRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void delet(const DeleteRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void umount(const UmountRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void version(const VersionRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void get(const GetRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void set(const SetRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void keys(const KeysRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void authenticate(
const AuthenticateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void clone(const CloneRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void snapshot(const SnapshotRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void restore(const RestoreRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void daemon_info(
const DaemonInfoRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
+
virtual void zones(const ZonesRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
+
virtual void zones_state(
const ZonesStateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
virtual void wait_ready(
const WaitReadyRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
private:
void release_resources(const std::string& instance);
void create_vm(const CreateRequest* request,
grpc::ServerReaderWriterInterface* server,
- std::promise* status_promise,
+ DaemonRpcContext* context,
bool start);
bool delete_vm(InstanceTable::iterator vm_it, bool purge, DeleteReply& response);
grpc::Status reboot_vm(VirtualMachine& vm);
@@ -212,7 +215,7 @@ public slots:
struct AsyncOperationStatus
{
grpc::Status status;
- std::promise* status_promise;
+ DaemonRpcContext* context;
};
// These async_* methods need to operate on instance names and look up the VMs again, lest they
@@ -227,7 +230,7 @@ public slots:
async_wait_for_ready_all(grpc::ServerReaderWriterInterface* server,
const std::vector& vms,
const std::chrono::seconds& timeout,
- std::promise* status_promise,
+ DaemonRpcContext* context,
const std::string& errors,
const std::string& start_warnings);
void finish_async_operation(const std::string& async_future_key);
diff --git a/src/daemon/daemon_rpc.cpp b/src/daemon/daemon_rpc.cpp
index 90a6f4fd10..87a503d014 100644
--- a/src/daemon/daemon_rpc.cpp
+++ b/src/daemon/daemon_rpc.cpp
@@ -17,6 +17,7 @@
#include "daemon_rpc.h"
+#include
#include
#include
#include
@@ -66,8 +67,8 @@ auto make_server(const std::string& server_address,
if (server == nullptr)
{
auto detail = check_is_server_running(server_address)
- ? " A multipass daemon is already running there."
- : "";
+ ? " A multipass daemon is already running there."
+ : "";
throw std::runtime_error(
fmt::format("Failed to start multipass gRPC service at {}.{}", server_address, detail));
}
@@ -85,14 +86,29 @@ auto server_socket_type_for(const std::string& server_address)
return mp::ServerSocketType::tcp;
}
-template
-grpc::Status emit_signal_and_wait_for_result(OperationSignal operation_signal)
+template
+concept HasVerbosityLevel = requires(T t) { t.verbosity_level(); };
+
+template
+grpc::Status emit_signal_and_wait_for_result(OperationSignal operation_signal,
+ grpc::ServerReaderWriterInterface* server,
+ U* request,
+ mpl::MultiplexingLogger& mpx)
{
- std::promise status_promise;
- auto status_future = status_promise.get_future();
- emit operation_signal(&status_promise);
+ auto level = [&request]() {
+ if constexpr (HasVerbosityLevel)
+ return mpl::level_from(request->verbosity_level());
+ else
+ return mpl::Level::info;
+ }();
- return status_future.get();
+ std::promise promise;
+ auto future = promise.get_future();
+ multipass::DaemonRpcContextImpl ctx{promise, server, level, mpx};
+ emit operation_signal(request,
+ static_cast*>(server),
+ static_cast(&ctx));
+ return future.get();
}
std::string client_cert_from(grpc::ServerContext* context)
@@ -133,11 +149,13 @@ void accept_cert(mp::CertStore* client_cert_store,
mp::DaemonRpc::DaemonRpc(const std::string& server_address,
const CertProvider& cert_provider,
- CertStore* client_cert_store)
+ CertStore* client_cert_store,
+ std::shared_ptr logger)
: server_address{server_address},
server{make_server(server_address, cert_provider, this)},
server_socket_type{server_socket_type_for(server_address)},
- client_cert_store{client_cert_store}
+ client_cert_store{client_cert_store},
+ logger(logger)
{
handle_socket_restrictions(server_address, client_cert_store->empty());
@@ -153,202 +171,218 @@ void mp::DaemonRpc::shutdown_and_wait()
grpc::Status mp::DaemonRpc::create(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- CreateRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_create, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_create,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::launch(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- LaunchRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_launch, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_launch,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::purge(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- PurgeRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_purge, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_purge,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::find(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- FindRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_find, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_find,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::info(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- InfoRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_info, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_info,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::list(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- ListRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_list, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_list,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::clone(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- CloneRequest request;
- server->Read(&request);
-
- auto adapted_on_clone = [this, &request, server](auto&& arg) -> void {
- this->on_clone(&request, server, std::forward(arg));
- };
-
- return verify_client_and_dispatch_operation(adapted_on_clone, client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_clone,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::networks(
grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- NetworksRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_networks, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_networks,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::mount(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- MountRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_mount, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_mount,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::recover(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- RecoverRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_recover, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_recover,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::ssh_info(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- SSHInfoRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_ssh_info, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_ssh_info,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::start(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- StartRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_start, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_start,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::stop(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- StopRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_stop, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_stop,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::suspend(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- SuspendRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_suspend, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_suspend,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::restart(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- RestartRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_restart, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_restart,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::delet(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- DeleteRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_delete, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_delete,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::umount(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- UmountRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_umount, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_umount,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::version(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- VersionRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_version, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_version,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::ping(grpc::ServerContext* context,
@@ -368,12 +402,13 @@ grpc::Status mp::DaemonRpc::ping(grpc::ServerContext* context,
grpc::Status mp::DaemonRpc::get(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- GetRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_get, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_get,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::authenticate(
@@ -383,8 +418,14 @@ grpc::Status mp::DaemonRpc::authenticate(
AuthenticateRequest request;
server->Read(&request);
- auto status = emit_signal_and_wait_for_result(
- std::bind(&DaemonRpc::on_authenticate, this, &request, server, std::placeholders::_1));
+ auto status = emit_signal_and_wait_for_result(std::bind(&DaemonRpc::on_authenticate,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ server,
+ &request,
+ *logger);
if (status.ok())
{
@@ -404,99 +445,111 @@ grpc::Status mp::DaemonRpc::authenticate(
grpc::Status mp::DaemonRpc::set(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- SetRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_set, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_set,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::keys(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- KeysRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_keys, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_keys,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::snapshot(
grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- SnapshotRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_snapshot, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_snapshot,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::restore(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- RestoreRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_restore, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_restore,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::daemon_info(
grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- DaemonInfoRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_daemon_info, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_daemon_info,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::wait_ready(
grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- WaitReadyRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_wait_ready, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_wait_ready,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::zones(grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- ZonesRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_zones, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_zones,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
grpc::Status mp::DaemonRpc::zones_state(
grpc::ServerContext* context,
grpc::ServerReaderWriter* server)
{
- ZonesStateRequest request;
- server->Read(&request);
-
- return verify_client_and_dispatch_operation(
- std::bind(&DaemonRpc::on_zones_state, this, &request, server, std::placeholders::_1),
- client_cert_from(context));
+ return verify_client_and_dispatch_operation(std::bind(&DaemonRpc::on_zones_state,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3),
+ client_cert_from(context),
+ server);
}
-template
-grpc::Status mp::DaemonRpc::verify_client_and_dispatch_operation(OperationSignal signal,
- const std::string& client_cert)
+template
+grpc::Status
+mp::DaemonRpc::verify_client_and_dispatch_operation(OperationSignal signal,
+ const std::string& client_cert,
+ grpc::ServerReaderWriterInterface* server)
{
+ U request{};
+ server->Read(&request);
if (server_socket_type == mp::ServerSocketType::unix && client_cert_store->empty())
{
try
@@ -518,5 +571,5 @@ grpc::Status mp::DaemonRpc::verify_client_and_dispatch_operation(OperationSignal
"(e.g. via 'multipass set local.passphrase')."};
}
- return emit_signal_and_wait_for_result(signal);
+ return emit_signal_and_wait_for_result(signal, server, &request, *logger);
}
diff --git a/src/daemon/daemon_rpc.h b/src/daemon/daemon_rpc.h
index 4764d45b5e..1d1e723050 100644
--- a/src/daemon/daemon_rpc.h
+++ b/src/daemon/daemon_rpc.h
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include
#include
@@ -31,6 +32,9 @@
namespace multipass
{
+
+struct DaemonRpcContext;
+
using CreateRequest = LaunchRequest;
using CreateReply = LaunchReply;
using CreateError = LaunchError;
@@ -52,105 +56,109 @@ class DaemonRpc : public QObject, public multipass::Rpc::Service, private Disabl
public:
DaemonRpc(const std::string& server_address,
const CertProvider& cert_provider,
- CertStore* client_cert_store);
+ CertStore* client_cert_store,
+ std::shared_ptr logger);
void shutdown_and_wait();
signals:
void on_create(const CreateRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_launch(const LaunchRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_purge(const PurgeRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_find(const FindRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_info(const InfoRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_list(const ListRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_clone(const CloneRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_networks(const NetworksRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_mount(const MountRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_recover(const RecoverRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_ssh_info(const SSHInfoRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_start(const StartRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_stop(const StopRequest* request,
grpc::ServerReaderWriter* server,
- std::promise* status_promise);
+ DaemonRpcContext* context);
void on_suspend(const SuspendRequest* request,
grpc::ServerReaderWriter