diff options
author | Alberto Sartori <alberto.sartori@huawei.com> | 2023-01-23 18:31:14 +0100 |
---|---|---|
committer | Alberto Sartori <alberto.sartori@huawei.com> | 2023-02-02 17:57:19 +0100 |
commit | bd66d45945dc186a0d08db7d9845ef657d549577 (patch) | |
tree | 51fa0b9c630ed388fc8aa36f5314b30fdc6bd5ff /src/buildtool/execution_api/execution_service/server_implementation.cpp | |
parent | 0658ef369e9dc27ca3a16075fc0f9e20931a2350 (diff) | |
download | justbuild-bd66d45945dc186a0d08db7d9845ef657d549577.tar.gz |
execution-service: add new subcommand execute
This subcommand starts a single node remote execution service honoring
the just native remote protocol.
If the flag --compatible is provided, the execution service will honor
the original remote build execution protocol.
New command line args supported by this subcommand:
-p,--port INT: Execution service will listen to this port. If unset,
the service will listen to the first available one.
--info-file TEXT: Write the used port, interface, and pid to this file
in JSON format. If the file exists, it will be overwritten.
-i,--interface TEXT: Interface to use. If unset, the loopback device
is used.
--pid-file TEXT Write pid to this file in plain txt. If the file
exists, it will be overwritten.
--tls-server-cert TEXT: Path to the TLS server certificate.
--tls-server-key TEXT: Path to the TLS server key.
Co-authored by: Klaus Aehlig <klaus.aehlig@huawei.com>
Diffstat (limited to 'src/buildtool/execution_api/execution_service/server_implementation.cpp')
-rw-r--r-- | src/buildtool/execution_api/execution_service/server_implementation.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/buildtool/execution_api/execution_service/server_implementation.cpp b/src/buildtool/execution_api/execution_service/server_implementation.cpp new file mode 100644 index 00000000..d38a11d5 --- /dev/null +++ b/src/buildtool/execution_api/execution_service/server_implementation.cpp @@ -0,0 +1,135 @@ +// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/buildtool/execution_api/execution_service/server_implementation.hpp" + +#include <iostream> +#include <memory> + +#include <sys/types.h> + +#include "fmt/format.h" +#include "grpcpp/grpcpp.h" +#include "nlohmann/json.hpp" +#include "src/buildtool/auth/authentication.hpp" +#include "src/buildtool/execution_api/execution_service/ac_server.hpp" +#include "src/buildtool/execution_api/execution_service/bytestream_server.hpp" +#include "src/buildtool/execution_api/execution_service/capabilities_server.hpp" +#include "src/buildtool/execution_api/execution_service/cas_server.hpp" +#include "src/buildtool/execution_api/execution_service/execution_server.hpp" +#include "src/buildtool/execution_api/remote/config.hpp" +#include "src/buildtool/logging/logger.hpp" + +namespace { +template <typename T> +auto TryWrite(std::string const& file, T const& content) noexcept -> bool { + std::ofstream of{file}; + if (!of.good()) { + Logger::Log(LogLevel::Error, + "Could not open {}. Make sure to have write permissions", + file); + return false; + } + of << content; + return true; +} +} // namespace + +auto ServerImpl::Run() -> bool { + ExecutionServiceImpl es{}; + ActionCacheServiceImpl ac{}; + CASServiceImpl cas{}; + BytestreamServiceImpl b{}; + CapabilitiesServiceImpl cap{}; + + grpc::ServerBuilder builder; + + builder.RegisterService(&es) + .RegisterService(&ac) + .RegisterService(&cas) + .RegisterService(&b) + .RegisterService(&cap); + + std::shared_ptr<grpc::ServerCredentials> creds; + if (Auth::GetAuthMethod() == AuthMethod::kTLS) { + auto tls_opts = grpc::SslServerCredentialsOptions{}; + + tls_opts.pem_root_certs = Auth::TLS::CACert(); + grpc::SslServerCredentialsOptions::PemKeyCertPair keycert = { + Auth::TLS::ServerKey(), Auth::TLS::ServerCert()}; + + tls_opts.pem_key_cert_pairs.emplace_back(keycert); + + creds = grpc::SslServerCredentials(tls_opts); + } + else { + creds = grpc::InsecureServerCredentials(); + } + + builder.AddListeningPort( + fmt::format("{}:{}", interface_, port_), creds, &port_); + + auto server = builder.BuildAndStart(); + if (!server) { + Logger::Log(LogLevel::Error, "Could not start execution service"); + return false; + } + + auto pid = getpid(); + + nlohmann::json const& info = { + {"interface", interface_}, {"port", port_}, {"pid", pid}}; + + if (!pid_file_.empty()) { + if (!TryWrite(pid_file_, pid)) { + server->Shutdown(); + return false; + } + } + + auto const& info_str = nlohmann::to_string(info); + Logger::Log(LogLevel::Info, + fmt::format("execution service started: {}", info_str)); + + if (!info_file_.empty()) { + if (!TryWrite(info_file_, info_str)) { + server->Shutdown(); + return false; + } + } + + server->Wait(); + return true; +} + +[[nodiscard]] auto ServerImpl::SetInfoFile(std::string const& x) noexcept + -> bool { + Instance().info_file_ = x; + return true; +} + +[[nodiscard]] auto ServerImpl::SetPidFile(std::string const& x) noexcept + -> bool { + Instance().pid_file_ = x; + return true; +} + +[[nodiscard]] auto ServerImpl::SetPort(int const x) noexcept -> bool { + auto port_num = ParsePort(x); + if (!port_num) { + return false; + } + Instance().port_ = static_cast<int>(*port_num); + return true; +}
\ No newline at end of file |