diff --git a/Cargo.lock b/Cargo.lock index 4135144f382..e9d377fed23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1338,6 +1338,21 @@ dependencies = [ "slog", ] +[[package]] +name = "clickhouse-admin-single-client" +version = "0.1.0" +dependencies = [ + "chrono", + "clickhouse-admin-types", + "omicron-uuid-kinds", + "omicron-workspace-hack", + "progenitor", + "reqwest 0.12.8", + "schemars", + "serde", + "slog", +] + [[package]] name = "clickhouse-admin-types" version = "0.1.0" @@ -5701,6 +5716,7 @@ dependencies = [ "chrono", "clickhouse-admin-keeper-client", "clickhouse-admin-server-client", + "clickhouse-admin-single-client", "clickhouse-admin-types", "cockroach-admin-client", "diesel", @@ -6555,6 +6571,7 @@ dependencies = [ "clap", "clickhouse-admin-keeper-client", "clickhouse-admin-server-client", + "clickhouse-admin-single-client", "cockroach-admin-client", "criterion", "crucible-agent-client", diff --git a/Cargo.toml b/Cargo.toml index 6168caee77e..c23df37cc9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "clients/bootstrap-agent-client", "clients/clickhouse-admin-keeper-client", "clients/clickhouse-admin-server-client", + "clients/clickhouse-admin-single-client", "clients/cockroach-admin-client", "clients/ddm-admin-client", "clients/dns-service-client", @@ -131,6 +132,7 @@ default-members = [ "clients/bootstrap-agent-client", "clients/clickhouse-admin-keeper-client", "clients/clickhouse-admin-server-client", + "clients/clickhouse-admin-single-client", "clients/cockroach-admin-client", "clients/ddm-admin-client", "clients/dns-service-client", @@ -318,6 +320,7 @@ clap = { version = "4.5", features = ["cargo", "derive", "env", "wrap_help"] } clickhouse-admin-api = { path = "clickhouse-admin/api" } clickhouse-admin-keeper-client = { path = "clients/clickhouse-admin-keeper-client" } clickhouse-admin-server-client = { path = "clients/clickhouse-admin-server-client" } +clickhouse-admin-single-client = { path = "clients/clickhouse-admin-single-client" } clickhouse-admin-types = { path = "clickhouse-admin/types" } clickward = { git = "https://github.com/oxidecomputer/clickward", rev = "ceec762e6a87d2a22bf56792a3025e145caa095e" } cockroach-admin-api = { path = "cockroach-admin/api" } diff --git a/clickhouse-admin/Cargo.toml b/clickhouse-admin/Cargo.toml index 84b04f6caaa..7fa999ed8c7 100644 --- a/clickhouse-admin/Cargo.toml +++ b/clickhouse-admin/Cargo.toml @@ -16,6 +16,7 @@ http.workspace = true illumos-utils.workspace = true omicron-common.workspace = true omicron-uuid-kinds.workspace = true +oximeter-db.workspace = true schemars.workspace = true slog.workspace = true slog-async.workspace = true @@ -35,7 +36,6 @@ dropshot.workspace = true expectorate.workspace = true nexus-test-utils.workspace = true omicron-test-utils.workspace = true -oximeter-db.workspace = true oximeter-test-utils.workspace = true openapi-lint.workspace = true openapiv3.workspace = true diff --git a/clickhouse-admin/api/src/lib.rs b/clickhouse-admin/api/src/lib.rs index 19cd2b3e8ec..c15f30fd6dc 100644 --- a/clickhouse-admin/api/src/lib.rs +++ b/clickhouse-admin/api/src/lib.rs @@ -8,7 +8,8 @@ use clickhouse_admin_types::{ ServerConfigurableSettings, }; use dropshot::{ - HttpError, HttpResponseCreated, HttpResponseOk, RequestContext, TypedBody, + HttpError, HttpResponseCreated, HttpResponseOk, + HttpResponseUpdatedNoContent, RequestContext, TypedBody, }; /// API interface for our clickhouse-admin-keeper server @@ -106,3 +107,24 @@ pub trait ClickhouseAdminServerApi { body: TypedBody, ) -> Result, HttpError>; } + +/// API interface for our clickhouse-admin-single server +/// +/// The single-node server is distinct from the both the multi-node servers +/// and its keepers. The sole purpose of this API is to serialize database +/// initialization requests from reconfigurator execution. Multi-node clusters +/// must eventually implement a similar interface, but the implementation will +/// obviously be more complex. +#[dropshot::api_description] +pub trait ClickhouseAdminSingleApi { + type Context; + + /// Idempotently initialize a single-node ClickHouse database. + #[endpoint { + method = PUT, + path = "/init" + }] + async fn init_db( + rqctx: RequestContext, + ) -> Result; +} diff --git a/clickhouse-admin/src/bin/clickhouse-admin-single.rs b/clickhouse-admin/src/bin/clickhouse-admin-single.rs new file mode 100644 index 00000000000..bc7097f980d --- /dev/null +++ b/clickhouse-admin/src/bin/clickhouse-admin-single.rs @@ -0,0 +1,72 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Single-node ClickHouse database admin binary. + +use anyhow::anyhow; +use camino::Utf8PathBuf; +use clap::Parser; +use omicron_clickhouse_admin::{ClickhouseCli, Config}; +use omicron_common::cmd::fatal; +use omicron_common::cmd::CmdError; +use std::net::{SocketAddr, SocketAddrV6}; + +#[derive(Debug, Parser)] +#[clap( + name = "clickhouse-admin-single", + about = "Single-node ClickHouse admin server" +)] +enum Args { + /// Start the single-node ClickHouse admin server + Run { + /// Address on which this server should run + #[clap(long, short = 'a', action)] + http_address: SocketAddrV6, + + /// Path to the server configuration file + #[clap(long, short, action)] + config: Utf8PathBuf, + + /// Address of the ClickHouse single-node database server + #[clap(long, short = 'l', action)] + listen_address: SocketAddrV6, + + /// Path to the clickhouse binary + #[clap(long, short, action)] + binary_path: Utf8PathBuf, + }, +} + +#[tokio::main] +async fn main() { + if let Err(err) = main_impl().await { + fatal(err); + } +} + +async fn main_impl() -> Result<(), CmdError> { + let args = Args::parse(); + + match args { + Args::Run { http_address, config, listen_address, binary_path } => { + let mut config = Config::from_file(&config) + .map_err(|err| CmdError::Failure(anyhow!(err)))?; + config.dropshot.bind_address = SocketAddr::V6(http_address); + let clickhouse_cli = + ClickhouseCli::new(binary_path, listen_address); + + let server = omicron_clickhouse_admin::start_single_admin_server( + clickhouse_cli, + config, + ) + .await + .map_err(|err| CmdError::Failure(anyhow!(err)))?; + server.await.map_err(|err| { + CmdError::Failure(anyhow!( + "server failed after starting: {err}" + )) + }) + } + } +} diff --git a/clickhouse-admin/src/context.rs b/clickhouse-admin/src/context.rs index 665d19528a6..a91b7d68fb9 100644 --- a/clickhouse-admin/src/context.rs +++ b/clickhouse-admin/src/context.rs @@ -4,6 +4,8 @@ use crate::{ClickhouseCli, Clickward}; use slog::Logger; +use std::sync::Arc; +use tokio::sync::Mutex; pub struct ServerContext { clickward: Clickward, @@ -28,3 +30,22 @@ impl ServerContext { &self.clickhouse_cli } } + +pub struct SingleServerContext { + clickhouse_cli: ClickhouseCli, + db_initialized: Arc>, +} + +impl SingleServerContext { + pub fn new(clickhouse_cli: ClickhouseCli) -> Self { + Self { clickhouse_cli, db_initialized: Arc::new(Mutex::new(false)) } + } + + pub fn clickhouse_cli(&self) -> &ClickhouseCli { + &self.clickhouse_cli + } + + pub fn db_initialized(&self) -> Arc> { + self.db_initialized.clone() + } +} diff --git a/clickhouse-admin/src/http_entrypoints.rs b/clickhouse-admin/src/http_entrypoints.rs index 49138b9cc3b..4ae0d1025be 100644 --- a/clickhouse-admin/src/http_entrypoints.rs +++ b/clickhouse-admin/src/http_entrypoints.rs @@ -2,7 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use crate::context::ServerContext; +use crate::context::{ServerContext, SingleServerContext}; use clickhouse_admin_api::*; use clickhouse_admin_types::{ ClickhouseKeeperClusterMembership, KeeperConf, KeeperConfig, @@ -10,23 +10,30 @@ use clickhouse_admin_types::{ ServerConfigurableSettings, }; use dropshot::{ - HttpError, HttpResponseCreated, HttpResponseOk, RequestContext, TypedBody, + ApiDescription, HttpError, HttpResponseCreated, HttpResponseOk, + HttpResponseUpdatedNoContent, RequestContext, TypedBody, }; use illumos_utils::svcadm::Svcadm; +use oximeter_db::{Client as OximeterClient, OXIMETER_VERSION}; +use slog::debug; use std::sync::Arc; -type ClickhouseApiDescription = dropshot::ApiDescription>; - -pub fn clickhouse_admin_server_api() -> ClickhouseApiDescription { +pub fn clickhouse_admin_server_api() -> ApiDescription> { clickhouse_admin_server_api_mod::api_description::() .expect("registered entrypoints") } -pub fn clickhouse_admin_keeper_api() -> ClickhouseApiDescription { +pub fn clickhouse_admin_keeper_api() -> ApiDescription> { clickhouse_admin_keeper_api_mod::api_description::() .expect("registered entrypoints") } +pub fn clickhouse_admin_single_api() -> ApiDescription> +{ + clickhouse_admin_single_api_mod::api_description::() + .expect("registered entrypoints") +} + enum ClickhouseAdminServerImpl {} impl ClickhouseAdminServerApi for ClickhouseAdminServerImpl { @@ -102,3 +109,38 @@ impl ClickhouseAdminKeeperApi for ClickhouseAdminKeeperImpl { Ok(HttpResponseOk(output)) } } + +enum ClickhouseAdminSingleImpl {} + +impl ClickhouseAdminSingleApi for ClickhouseAdminSingleImpl { + type Context = Arc; + + async fn init_db( + rqctx: RequestContext, + ) -> Result { + let log = &rqctx.log; + let ctx = rqctx.context(); + let initialized = ctx.db_initialized(); + let mut initialized = initialized.lock().await; + if !*initialized { + let address = ctx.clickhouse_cli().listen_address; + let client = OximeterClient::new(address.into(), log); + debug!( + log, + "initializing single-node ClickHouse \ + at {address} to version {OXIMETER_VERSION}" + ); + client + .initialize_db_with_version(false, OXIMETER_VERSION) + .await + .map_err(|e| { + HttpError::for_internal_error(format!( + "can't initialize single-node ClickHouse \ + at {address} to version {OXIMETER_VERSION}: {e}", + )) + })?; + *initialized = true; + } + Ok(HttpResponseUpdatedNoContent()) + } +} diff --git a/clickhouse-admin/src/lib.rs b/clickhouse-admin/src/lib.rs index 1697d24adc1..4e978424386 100644 --- a/clickhouse-admin/src/lib.rs +++ b/clickhouse-admin/src/lib.rs @@ -2,7 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use context::ServerContext; +use context::{ServerContext, SingleServerContext}; +use dropshot::{HttpServer, HttpServerStarter}; use omicron_common::FileKv; use slog::{debug, error, Drain}; use slog_dtrace::ProbeRegistration; @@ -31,15 +32,13 @@ pub enum StartError { InitializeHttpServer(#[source] Box), } -pub type Server = dropshot::HttpServer>; - /// Start the dropshot server for `clickhouse-admin-server` which /// manages clickhouse replica servers. pub async fn start_server_admin_server( clickward: Clickward, clickhouse_cli: ClickhouseCli, server_config: Config, -) -> Result { +) -> Result>, StartError> { let (drain, registration) = slog_dtrace::with_drain( server_config .log @@ -64,7 +63,7 @@ pub async fn start_server_admin_server( .with_log(log.new(slog::o!("component" => "ClickhouseCli"))), log.new(slog::o!("component" => "ServerContext")), ); - let http_server_starter = dropshot::HttpServerStarter::new( + let http_server_starter = HttpServerStarter::new( &server_config.dropshot, http_entrypoints::clickhouse_admin_server_api(), Arc::new(context), @@ -81,7 +80,7 @@ pub async fn start_keeper_admin_server( clickward: Clickward, clickhouse_cli: ClickhouseCli, server_config: Config, -) -> Result { +) -> Result>, StartError> { let (drain, registration) = slog_dtrace::with_drain( server_config .log @@ -106,7 +105,7 @@ pub async fn start_keeper_admin_server( .with_log(log.new(slog::o!("component" => "ClickhouseCli"))), log.new(slog::o!("component" => "ServerContext")), ); - let http_server_starter = dropshot::HttpServerStarter::new( + let http_server_starter = HttpServerStarter::new( &server_config.dropshot, http_entrypoints::clickhouse_admin_keeper_api(), Arc::new(context), @@ -116,3 +115,39 @@ pub async fn start_keeper_admin_server( Ok(http_server_starter.start()) } + +/// Start the dropshot server for `clickhouse-admin-single` which +/// manages a single-node ClickHouse database. +pub async fn start_single_admin_server( + clickhouse_cli: ClickhouseCli, + server_config: Config, +) -> Result>, StartError> { + let (drain, registration) = slog_dtrace::with_drain( + server_config + .log + .to_logger("clickhouse-admin-keeper") + .map_err(StartError::InitializeLogger)?, + ); + let log = slog::Logger::root(drain.fuse(), slog::o!(FileKv)); + match registration { + ProbeRegistration::Success => { + debug!(log, "registered DTrace probes"); + } + ProbeRegistration::Failed(err) => { + let err = StartError::RegisterDtraceProbes(err); + error!(log, "failed to register DTrace probes"; &err); + return Err(err); + } + } + + let context = SingleServerContext::new(clickhouse_cli); + let http_server_starter = HttpServerStarter::new( + &server_config.dropshot, + http_entrypoints::clickhouse_admin_single_api(), + Arc::new(context), + &log.new(slog::o!("component" => "dropshot")), + ) + .map_err(StartError::InitializeHttpServer)?; + + Ok(http_server_starter.start()) +} diff --git a/clickhouse-admin/tests/integration_test.rs b/clickhouse-admin/tests/integration_test.rs index eb26bec6684..12bf0d01879 100644 --- a/clickhouse-admin/tests/integration_test.rs +++ b/clickhouse-admin/tests/integration_test.rs @@ -279,3 +279,5 @@ async fn test_keeper_cluster_membership() -> anyhow::Result<()> { logctx.cleanup_successful(); Ok(()) } + +// TODO: single-node admin test diff --git a/clients/clickhouse-admin-single-client/Cargo.toml b/clients/clickhouse-admin-single-client/Cargo.toml new file mode 100644 index 00000000000..e8b2abf8602 --- /dev/null +++ b/clients/clickhouse-admin-single-client/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "clickhouse-admin-single-client" +version = "0.1.0" +edition = "2021" + +[dependencies] +chrono.workspace = true +clickhouse-admin-types.workspace = true +omicron-uuid-kinds.workspace = true +progenitor.workspace = true +reqwest = { workspace = true, features = [ "json", "rustls-tls", "stream" ] } +schemars.workspace = true +serde.workspace = true +slog.workspace = true +omicron-workspace-hack.workspace = true + +[lints] +workspace = true diff --git a/clients/clickhouse-admin-single-client/src/lib.rs b/clients/clickhouse-admin-single-client/src/lib.rs new file mode 100644 index 00000000000..11973108005 --- /dev/null +++ b/clients/clickhouse-admin-single-client/src/lib.rs @@ -0,0 +1,26 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! API for the clickhouse-admin-single server to manage a single-node +//! ClickHouse database. + +progenitor::generate_api!( + spec = "../../openapi/clickhouse-admin-single.json", + inner_type = slog::Logger, + pre_hook = (|log: &slog::Logger, request: &reqwest::Request| { + slog::debug!(log, "client request"; + "method" => %request.method(), + "uri" => %request.url(), + "body" => ?&request.body(), + ); + }), + post_hook = (|log: &slog::Logger, result: &Result<_, _>| { + slog::debug!(log, "client response"; "result" => ?result); + }), + derives = [schemars::JsonSchema], + replace = { + TypedUuidForOmicronZoneKind = omicron_uuid_kinds::OmicronZoneUuid, + ServerConfigurableSettings = clickhouse_admin_types::ServerConfigurableSettings, + } +); diff --git a/dev-tools/ls-apis/api-manifest.toml b/dev-tools/ls-apis/api-manifest.toml index f91aba74aa5..26003761669 100644 --- a/dev-tools/ls-apis/api-manifest.toml +++ b/dev-tools/ls-apis/api-manifest.toml @@ -156,6 +156,15 @@ This is the server running inside multi-node Clickhouse server zones that's \ responsible for local configuration and monitoring. """ +[[apis]] +client_package_name = "clickhouse-admin-single-client" +label = "Clickhouse Single-Node Cluster Admin" +server_package_name = "clickhouse-admin-api" +notes = """ +This is the server running inside single-node Clickhouse server zones that's \ +responsible for local configuration and monitoring. +""" + [[apis]] client_package_name = "cockroach-admin-client" label = "CockroachDB Cluster Admin" diff --git a/dev-tools/openapi-manager/src/spec.rs b/dev-tools/openapi-manager/src/spec.rs index dafcebac052..67e400b0c97 100644 --- a/dev-tools/openapi-manager/src/spec.rs +++ b/dev-tools/openapi-manager/src/spec.rs @@ -48,6 +48,17 @@ pub fn all_apis() -> Vec { filename: "clickhouse-admin-server.json", extra_validation: None, }, + ApiSpec { + title: "ClickHouse Single-Node Admin Server API", + version: "0.0.1", + description: "API for interacting with the Oxide \ + control plane's single-node ClickHouse database", + boundary: ApiBoundary::Internal, + api_description: + clickhouse_admin_api::clickhouse_admin_single_api_mod::stub_api_description, + filename: "clickhouse-admin-single.json", + extra_validation: None, + }, ApiSpec { title: "CockroachDB Cluster Admin API", version: "0.0.1", diff --git a/nexus/Cargo.toml b/nexus/Cargo.toml index d430009360c..6ba66e058f2 100644 --- a/nexus/Cargo.toml +++ b/nexus/Cargo.toml @@ -24,6 +24,7 @@ clap.workspace = true chrono.workspace = true clickhouse-admin-keeper-client.workspace = true clickhouse-admin-server-client.workspace = true +clickhouse-admin-single-client.workspace = true cockroach-admin-client.workspace = true crucible-agent-client.workspace = true crucible-pantry-client.workspace = true diff --git a/nexus/reconfigurator/execution/Cargo.toml b/nexus/reconfigurator/execution/Cargo.toml index 21d861ef51e..e07e4f5f756 100644 --- a/nexus/reconfigurator/execution/Cargo.toml +++ b/nexus/reconfigurator/execution/Cargo.toml @@ -14,6 +14,7 @@ anyhow.workspace = true camino.workspace = true clickhouse-admin-keeper-client.workspace = true clickhouse-admin-server-client.workspace = true +clickhouse-admin-single-client.workspace = true clickhouse-admin-types.workspace = true cockroach-admin-client.workspace = true chrono.workspace = true diff --git a/nexus/reconfigurator/execution/src/clickhouse.rs b/nexus/reconfigurator/execution/src/clickhouse.rs index e623952ed92..5514378d25d 100644 --- a/nexus/reconfigurator/execution/src/clickhouse.rs +++ b/nexus/reconfigurator/execution/src/clickhouse.rs @@ -9,6 +9,7 @@ use anyhow::anyhow; use camino::Utf8PathBuf; use clickhouse_admin_keeper_client::Client as ClickhouseKeeperClient; use clickhouse_admin_server_client::Client as ClickhouseServerClient; +use clickhouse_admin_single_client::Client as ClickhouseSingleClient; use clickhouse_admin_types::ClickhouseHost; use clickhouse_admin_types::KeeperConfigurableSettings; use clickhouse_admin_types::KeeperSettings; @@ -152,6 +153,36 @@ pub(crate) async fn deploy_nodes( Ok(()) } +pub(crate) async fn deploy_single_node( + opctx: &OpContext, + zones: &BTreeMap, +) -> Result<(), anyhow::Error> { + if let Some(zone) = zones + .values() + .flat_map(|zones| { + zones.zones.iter().find(|zone| zone.zone_type.is_clickhouse()) + }) + .next() + { + let admin_addr = SocketAddr::V6(SocketAddrV6::new( + zone.underlay_address, + CLICKHOUSE_ADMIN_PORT, + 0, + 0, + )); + let admin_url = format!("http://{admin_addr}"); + let log = opctx.log.new(slog::o!("admin_url" => admin_url.clone())); + let client = ClickhouseSingleClient::new(&admin_url, log.clone()); + client.init_db().await.map(|_| ()).map_err(|e| { + anyhow!( + "failed to initialize single-node clickhouse database: {e}", + ) + }) + } else { + Ok(()) + } +} + fn server_configs( zones: &BTreeMap, clickhouse_cluster_config: &ClickhouseClusterConfig, diff --git a/nexus/reconfigurator/execution/src/lib.rs b/nexus/reconfigurator/execution/src/lib.rs index e160ddc9a03..29ef249f1dd 100644 --- a/nexus/reconfigurator/execution/src/lib.rs +++ b/nexus/reconfigurator/execution/src/lib.rs @@ -173,6 +173,12 @@ pub async fn realize_blueprint_with_overrides( blueprint, ); + register_deploy_clickhouse_single_node_step( + &engine.for_component(ExecutionComponent::Clickhouse), + &opctx, + blueprint, + ); + let reassign_saga_output = register_reassign_sagas_step( &engine.for_component(ExecutionComponent::OmicronZones), &opctx, @@ -514,6 +520,27 @@ fn register_deploy_clickhouse_cluster_nodes_step<'a>( .register(); } +fn register_deploy_clickhouse_single_node_step<'a>( + registrar: &ComponentRegistrar<'_, 'a>, + opctx: &'a OpContext, + blueprint: &'a Blueprint, +) { + registrar + .new_step( + ExecutionStepId::Ensure, + "Deploy single-node clickhouse cluster", + move |_cx| async move { + clickhouse::deploy_single_node( + &opctx, + &blueprint.blueprint_zones, + ) + .await?; + StepSuccess::new(()).into() + }, + ) + .register(); +} + #[derive(Debug)] struct ReassignSagaOutput { needs_saga_recovery: bool, diff --git a/openapi/clickhouse-admin-single.json b/openapi/clickhouse-admin-single.json new file mode 100644 index 00000000000..74763957cad --- /dev/null +++ b/openapi/clickhouse-admin-single.json @@ -0,0 +1,66 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "ClickHouse Single-Node Admin Server API", + "description": "API for interacting with the Oxide control plane's single-node ClickHouse database", + "contact": { + "url": "https://oxide.computer", + "email": "api@oxide.computer" + }, + "version": "0.0.1" + }, + "paths": { + "/init": { + "put": { + "summary": "Idempotently initialize a single-node ClickHouse database.", + "operationId": "init_db", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + } + }, + "components": { + "schemas": { + "Error": { + "description": "Error information from a response.", + "type": "object", + "properties": { + "error_code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "request_id": { + "type": "string" + } + }, + "required": [ + "message", + "request_id" + ] + } + }, + "responses": { + "Error": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } +} diff --git a/package-manifest.toml b/package-manifest.toml index 2b5eecc2ec5..1e4a4e15325 100644 --- a/package-manifest.toml +++ b/package-manifest.toml @@ -155,15 +155,14 @@ output.type = "zone" output.intermediate_only = true [package.clickhouse] -# This service runs a single-node ClickHouse server. +# This service runs a single-node ClickHouse server +# and a small administrative Dropshot server. service_name = "clickhouse" only_for_targets.image = "standard" source.type = "composite" source.packages = [ "clickhouse_svc.tar.gz", "internal-dns-cli.tar.gz", - # TODO: This package is for solely for testing purposes. - # Remove once replicated clickhouse is up and running. "omicron-clickhouse-admin.tar.gz", "zone-setup.tar.gz", "zone-network-install.tar.gz" @@ -179,6 +178,7 @@ source.paths = [ { from = "smf/clickhouse/manifest.xml", to = "/var/svc/manifest/site/clickhouse/manifest.xml" }, { from = "smf/clickhouse/method_script.sh", to = "/opt/oxide/lib/svc/manifest/clickhouse.sh" }, { from = "smf/clickhouse/config.xml", to = "/opt/oxide/clickhouse/config.xml" }, + { from = "smf/clickhouse-admin-single", to = "/var/svc/manifest/site/clickhouse-admin-single" }, ] output.type = "zone" output.intermediate_only = true @@ -248,7 +248,7 @@ setup_hint = "Run `cargo xtask download clickhouse` to download the necessary bi service_name = "omicron-clickhouse-admin" only_for_targets.image = "standard" source.type = "local" -source.rust.binary_names = ["clickhouse-admin-keeper", "clickhouse-admin-server"] +source.rust.binary_names = ["clickhouse-admin-keeper", "clickhouse-admin-server", "clickhouse-admin-single"] source.rust.release = true # We specifically put the smf manifests with their corresponding container zones # so that both servers aren't started simultaneously diff --git a/sled-agent/src/services.rs b/sled-agent/src/services.rs index 368655aa9fd..911e54ad658 100644 --- a/sled-agent/src/services.rs +++ b/sled-agent/src/services.rs @@ -1615,10 +1615,11 @@ impl ServiceManager { CLICKHOUSE_BINARY, ); let clickhouse_admin_service = - ServiceBuilder::new("oxide/clickhouse-admin").add_instance( - ServiceInstanceBuilder::new("default") - .add_property_group(clickhouse_admin_config), - ); + ServiceBuilder::new("oxide/clickhouse-admin-single") + .add_instance( + ServiceInstanceBuilder::new("default") + .add_property_group(clickhouse_admin_config), + ); let profile = ProfileBuilder::new("omicron") .add_service(nw_setup_service) diff --git a/smf/clickhouse-admin-single/config.toml b/smf/clickhouse-admin-single/config.toml new file mode 100644 index 00000000000..86ee2c5d4b3 --- /dev/null +++ b/smf/clickhouse-admin-single/config.toml @@ -0,0 +1,10 @@ +[dropshot] +# 1 MiB; we don't expect any requests of more than nominal size. +request_body_max_bytes = 1048576 + +[log] +# Show log messages of this level and more severe +level = "info" +mode = "file" +path = "/dev/stdout" +if_exists = "append" diff --git a/smf/clickhouse-admin-single/manifest.xml b/smf/clickhouse-admin-single/manifest.xml new file mode 100644 index 00000000000..f2590201459 --- /dev/null +++ b/smf/clickhouse-admin-single/manifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +