From 9fd901b7b21fad6adda3fa4afc77987302c2391b Mon Sep 17 00:00:00 2001 From: John Spray Date: Wed, 1 Nov 2023 17:54:02 +0000 Subject: [PATCH] neon_local: remote storage by default & enable multiple pageservers in init --- control_plane/src/bin/neon_local.rs | 56 +++++++++++++++++++++-------- control_plane/src/pageserver.rs | 7 ++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/control_plane/src/bin/neon_local.rs b/control_plane/src/bin/neon_local.rs index bc68eeaa8a..8ad78abf56 100644 --- a/control_plane/src/bin/neon_local.rs +++ b/control_plane/src/bin/neon_local.rs @@ -11,13 +11,13 @@ use compute_api::spec::ComputeMode; use control_plane::attachment_service::AttachmentService; use control_plane::endpoint::ComputeControlPlane; use control_plane::local_env::LocalEnv; -use control_plane::pageserver::PageServerNode; +use control_plane::pageserver::{PageServerNode, PAGESERVER_REMOTE_STORAGE_DIR}; use control_plane::safekeeper::SafekeeperNode; use control_plane::{broker, local_env}; use pageserver_api::models::TimelineInfo; use pageserver_api::{ - DEFAULT_HTTP_LISTEN_ADDR as DEFAULT_PAGESERVER_HTTP_ADDR, - DEFAULT_PG_LISTEN_ADDR as DEFAULT_PAGESERVER_PG_ADDR, + DEFAULT_HTTP_LISTEN_PORT as DEFAULT_PAGESERVER_HTTP_PORT, + DEFAULT_PG_LISTEN_PORT as DEFAULT_PAGESERVER_PG_PORT, }; use postgres_backend::AuthType; use safekeeper_api::{ @@ -46,8 +46,8 @@ const DEFAULT_PG_VERSION: &str = "15"; const DEFAULT_PAGESERVER_CONTROL_PLANE_API: &str = "http://127.0.0.1:1234/"; -fn default_conf() -> String { - format!( +fn default_conf(num_pageservers: u16) -> String { + let mut template = format!( r#" # Default built-in configuration, defined in main.rs control_plane_api = '{DEFAULT_PAGESERVER_CONTROL_PLANE_API}' @@ -55,21 +55,33 @@ control_plane_api = '{DEFAULT_PAGESERVER_CONTROL_PLANE_API}' [broker] listen_addr = '{DEFAULT_BROKER_ADDR}' -[[pageservers]] -id = {DEFAULT_PAGESERVER_ID} -listen_pg_addr = '{DEFAULT_PAGESERVER_PG_ADDR}' -listen_http_addr = '{DEFAULT_PAGESERVER_HTTP_ADDR}' -pg_auth_type = '{trust_auth}' -http_auth_type = '{trust_auth}' - [[safekeepers]] id = {DEFAULT_SAFEKEEPER_ID} pg_port = {DEFAULT_SAFEKEEPER_PG_PORT} http_port = {DEFAULT_SAFEKEEPER_HTTP_PORT} "#, - trust_auth = AuthType::Trust, - ) + ); + + for i in 0..num_pageservers { + let pageserver_id = NodeId(DEFAULT_PAGESERVER_ID.0 + i as u64); + let pg_port = DEFAULT_PAGESERVER_PG_PORT + i; + let http_port = DEFAULT_PAGESERVER_HTTP_PORT + i; + + template += &format!( + r#" +[[pageservers]] +id = {pageserver_id} +listen_pg_addr = '127.0.0.1:{pg_port}' +listen_http_addr = '127.0.0.1:{http_port}' +pg_auth_type = '{trust_auth}' +http_auth_type = '{trust_auth}' +"#, + trust_auth = AuthType::Trust, + ) + } + + template } /// @@ -295,6 +307,9 @@ fn parse_timeline_id(sub_match: &ArgMatches) -> anyhow::Result anyhow::Result { + let num_pageservers = init_match + .get_one::("num-pageservers") + .expect("num-pageservers arg has a default"); // Create config file let toml_file: String = if let Some(config_path) = init_match.get_one::("config") { // load and parse the file @@ -306,7 +321,7 @@ fn handle_init(init_match: &ArgMatches) -> anyhow::Result { })? } else { // Built-in default config - default_conf() + default_conf(*num_pageservers) }; let pg_version = init_match @@ -320,6 +335,9 @@ fn handle_init(init_match: &ArgMatches) -> anyhow::Result { env.init(pg_version, force) .context("Failed to initialize neon repository")?; + // Create remote storage location for default LocalFs remote storage + std::fs::create_dir(env.base_data_dir.join(PAGESERVER_REMOTE_STORAGE_DIR))?; + // Initialize pageserver, create initial tenant and timeline. for ps_conf in &env.pageservers { PageServerNode::from_env(&env, ps_conf) @@ -1224,6 +1242,13 @@ fn cli() -> Command { .help("Force initialization even if the repository is not empty") .required(false); + let num_pageservers_arg = Arg::new("num-pageservers") + .value_parser(value_parser!(u16)) + .long("num-pageservers") + .help("How many pageservers to create (default 1)") + .required(false) + .default_value("1"); + Command::new("Neon CLI") .arg_required_else_help(true) .version(GIT_VERSION) @@ -1231,6 +1256,7 @@ fn cli() -> Command { Command::new("init") .about("Initialize a new Neon repository, preparing configs for services to start with") .arg(pageserver_config_args.clone()) + .arg(num_pageservers_arg.clone()) .arg( Arg::new("config") .long("config") diff --git a/control_plane/src/pageserver.rs b/control_plane/src/pageserver.rs index 0746dde4ef..50d83cca77 100644 --- a/control_plane/src/pageserver.rs +++ b/control_plane/src/pageserver.rs @@ -31,6 +31,9 @@ use utils::{ use crate::local_env::PageServerConf; use crate::{background_process, local_env::LocalEnv}; +/// Directory within .neon which will be used by default for LocalFs remote storage. +pub const PAGESERVER_REMOTE_STORAGE_DIR: &str = "remote_storage"; + #[derive(Error, Debug)] pub enum PageserverHttpError { #[error("Reqwest error: {0}")] @@ -115,6 +118,9 @@ impl PageServerNode { let broker_endpoint_param = format!("broker_endpoint='{}'", self.env.broker.client_url()); + let remote_storage_param = + format!("remote_storage={{local_path='../{PAGESERVER_REMOTE_STORAGE_DIR}'}}"); + let mut overrides = vec![ id, pg_distrib_dir_param, @@ -123,6 +129,7 @@ impl PageServerNode { listen_http_addr_param, listen_pg_addr_param, broker_endpoint_param, + remote_storage_param, ]; if let Some(control_plane_api) = &self.env.control_plane_api {