From e63104e3a88e842466a7e02270f0c57257b34fd2 Mon Sep 17 00:00:00 2001 From: Andrei Toterman Date: Wed, 18 Dec 2024 23:00:49 +0100 Subject: [PATCH] add daemon gRPC boilerplate for AZs --- src/daemon/daemon.cpp | 33 +++++++++++++++++++++++++++++++++ src/daemon/daemon.h | 6 ++++++ src/daemon/daemon_rpc.cpp | 22 ++++++++++++++++++++++ src/daemon/daemon_rpc.h | 10 ++++++++++ src/rpc/multipass.proto | 32 ++++++++++++++++++++++++++++++++ tests/mock_client_rpc.h | 24 ++++++++++++++++++++++++ tests/mock_daemon.h | 12 ++++++++++++ 7 files changed, 139 insertions(+) diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 9675858258..e4ffbb0f20 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -579,6 +579,8 @@ auto connect_rpc(mp::DaemonRpc& rpc, mp::Daemon& daemon) QObject::connect(&rpc, &mp::DaemonRpc::on_snapshot, &daemon, &mp::Daemon::snapshot); QObject::connect(&rpc, &mp::DaemonRpc::on_restore, &daemon, &mp::Daemon::restore); QObject::connect(&rpc, &mp::DaemonRpc::on_daemon_info, &daemon, &mp::Daemon::daemon_info); + QObject::connect(&rpc, &mp::DaemonRpc::on_zones, &daemon, &mp::Daemon::zones); + QObject::connect(&rpc, &mp::DaemonRpc::on_zones_state, &daemon, &mp::Daemon::zones_state); } enum class InstanceGroup @@ -2800,6 +2802,37 @@ catch (const std::exception& e) status_promise->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 +try // clang-format on +{ + mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()), *config->logger, server}; + + ZonesReply response{}; + + server->Write(response); + status_promise->set_value(grpc::Status{}); +} +catch (const std::exception& e) +{ + status_promise->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 +try // clang-format on +{ + mpl::ClientLogger logger{mpl::level_from(request->verbosity_level()), *config->logger, server}; + + status_promise->set_value(grpc::Status{}); +} +catch (const std::exception& e) +{ + status_promise->set_value(grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, e.what(), "")); +} + void mp::Daemon::on_shutdown() { } diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h index af7919043e..4ca1e975ae 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -155,6 +155,12 @@ public slots: virtual void daemon_info(const DaemonInfoRequest* request, grpc::ServerReaderWriterInterface* server, std::promise* status_promise); + virtual void zones(const ZonesRequest* request, + grpc::ServerReaderWriterInterface* server, + std::promise* status_promise); + virtual void zones_state(const ZonesStateRequest* request, + grpc::ServerReaderWriterInterface* server, + std::promise* status_promise); private: void release_resources(const std::string& instance); diff --git a/src/daemon/daemon_rpc.cpp b/src/daemon/daemon_rpc.cpp index e094da55e0..650f9532da 100644 --- a/src/daemon/daemon_rpc.cpp +++ b/src/daemon/daemon_rpc.cpp @@ -418,6 +418,28 @@ grpc::Status mp::DaemonRpc::daemon_info(grpc::ServerContext* context, client_cert_from(context)); } +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)); +} + +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)); +} + template grpc::Status mp::DaemonRpc::verify_client_and_dispatch_operation(OperationSignal signal, const std::string& client_cert) { diff --git a/src/daemon/daemon_rpc.h b/src/daemon/daemon_rpc.h index 2b3c3828d4..36ae07ec71 100644 --- a/src/daemon/daemon_rpc.h +++ b/src/daemon/daemon_rpc.h @@ -112,6 +112,12 @@ class DaemonRpc : public QObject, public multipass::Rpc::Service, private Disabl void on_daemon_info(const DaemonInfoRequest* request, grpc::ServerReaderWriter* server, std::promise* status_promise); + void on_zones(const ZonesRequest* request, + grpc::ServerReaderWriter* server, + std::promise* status_promise); + void on_zones_state(const ZonesStateRequest* request, + grpc::ServerReaderWriter* server, + std::promise* status_promise); private: template @@ -167,6 +173,10 @@ class DaemonRpc : public QObject, public multipass::Rpc::Service, private Disabl grpc::ServerReaderWriter* server) override; grpc::Status daemon_info(grpc::ServerContext* context, grpc::ServerReaderWriter* server) override; + grpc::Status zones(grpc::ServerContext* context, + grpc::ServerReaderWriter* server) override; + grpc::Status zones_state(grpc::ServerContext* context, + grpc::ServerReaderWriter* server) override; }; } // namespace multipass #endif // MULTIPASS_DAEMON_RPC_H diff --git a/src/rpc/multipass.proto b/src/rpc/multipass.proto index 8ee6b9c2b1..a6a4b08074 100644 --- a/src/rpc/multipass.proto +++ b/src/rpc/multipass.proto @@ -45,6 +45,8 @@ service Rpc { rpc restore (stream RestoreRequest) returns (stream RestoreReply); rpc clone (stream CloneRequest) returns (stream CloneReply); rpc daemon_info (stream DaemonInfoRequest) returns (stream DaemonInfoReply); + rpc zones (stream ZonesRequest) returns (stream ZonesReply); + rpc zones_state (stream ZonesStateRequest) returns (stream ZonesStateReply); } message LaunchRequest { @@ -73,6 +75,7 @@ message LaunchRequest { bool permission_to_bridge = 13; int32 timeout = 14; string password = 15; + string zone = 16; } message LaunchError { @@ -82,6 +85,8 @@ message LaunchError { INVALID_DISK_SIZE = 2; INVALID_HOSTNAME = 3; INVALID_NETWORK = 4; + INVALID_ZONE = 5; + ZONE_UNAVAILABLE = 6; } repeated ErrorCodes error_codes = 1; } @@ -250,6 +255,8 @@ message DetailedInfoItem { InstanceDetails instance_info = 7; SnapshotDetails snapshot_info = 8; } + + Zone zone = 9; } message InfoReply { @@ -271,6 +278,7 @@ message ListVMInstance { repeated string ipv4 = 3; repeated string ipv6 = 4; string current_release = 5; + Zone zone = 6; } message ListVMSnapshot { @@ -550,3 +558,27 @@ message DaemonInfoReply { uint32 cpus = 3; uint64 memory = 4; } + +message Zone { + string name = 1; + bool available = 2; +} + +message ZonesRequest { + int32 verbosity_level = 1; +} + +message ZonesReply { + string log_line = 1; + repeated Zone zones = 2; +} + +message ZonesStateRequest { + int32 verbosity_level = 1; + bool available = 2; + repeated string zones = 3; +} + +message ZonesStateReply { + string log_line = 1; +} diff --git a/tests/mock_client_rpc.h b/tests/mock_client_rpc.h index 0f85c4b341..2e2b0f4bcd 100644 --- a/tests/mock_client_rpc.h +++ b/tests/mock_client_rpc.h @@ -236,6 +236,30 @@ class MockRpcStub : public multipass::Rpc::StubInterface PrepareAsyncdaemon_infoRaw, (grpc::ClientContext * context, grpc::CompletionQueue* cq), (override)); + MOCK_METHOD((grpc::ClientReaderWriterInterface*), + zonesRaw, + (grpc::ClientContext * context), + (override)); + MOCK_METHOD((grpc::ClientAsyncReaderWriterInterface*), + AsynczonesRaw, + (grpc::ClientContext * context, grpc::CompletionQueue* cq, void* tag), + (override)); + MOCK_METHOD((grpc::ClientAsyncReaderWriterInterface*), + PrepareAsynczonesRaw, + (grpc::ClientContext * context, grpc::CompletionQueue* cq), + (override)); + MOCK_METHOD((grpc::ClientReaderWriterInterface*), + zones_stateRaw, + (grpc::ClientContext * context), + (override)); + MOCK_METHOD((grpc::ClientAsyncReaderWriterInterface*), + Asynczones_stateRaw, + (grpc::ClientContext * context, grpc::CompletionQueue* cq, void* tag), + (override)); + MOCK_METHOD((grpc::ClientAsyncReaderWriterInterface*), + PrepareAsynczones_stateRaw, + (grpc::ClientContext * context, grpc::CompletionQueue* cq), + (override)); }; } // namespace multipass::test diff --git a/tests/mock_daemon.h b/tests/mock_daemon.h index 2167cf3f81..577db29f37 100644 --- a/tests/mock_daemon.h +++ b/tests/mock_daemon.h @@ -142,6 +142,18 @@ struct MockDaemon : public Daemon (grpc::ServerReaderWriterInterface*), std::promise*), (override)); + MOCK_METHOD(void, + zones, + (const ZonesRequest*, + (grpc::ServerReaderWriterInterface*), + std::promise*), + (override)); + MOCK_METHOD(void, + zones_state, + (const ZonesStateRequest*, + (grpc::ServerReaderWriterInterface*), + std::promise*), + (override)); template void set_promise_value(const Request*, grpc::ServerReaderWriterInterface*,