mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-24 00:20:37 +00:00
Save tenant config in pageserver directory
This commit is contained in:
committed by
Anastasia Lubennikova
parent
baac8ac410
commit
7e6eff4969
@@ -1,3 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
use std::net::TcpStream;
|
||||
use std::path::PathBuf;
|
||||
@@ -342,10 +343,22 @@ impl PageServerNode {
|
||||
pub fn tenant_create(
|
||||
&self,
|
||||
new_tenant_id: Option<ZTenantId>,
|
||||
settings: HashMap<&str, &str>
|
||||
) -> anyhow::Result<Option<ZTenantId>> {
|
||||
let tenant_id_string = self
|
||||
.http_request(Method::POST, format!("{}/tenant", self.http_base_url))
|
||||
.json(&TenantCreateRequest::new(tenantid))
|
||||
.json(&TenantCreateRequest {
|
||||
new_tenant_id,
|
||||
checkpoint_distance: settings
|
||||
.get("checkpoint_distance")
|
||||
.map(|x| x.parse::<u64>().unwrap()),
|
||||
compaction_period: settings.get("compaction_period").map(|x| x.to_string()),
|
||||
gc_horizon: settings
|
||||
.get("gc_horizon")
|
||||
.map(|x| x.parse::<u64>().unwrap()),
|
||||
gc_period: settings.get("gc_period").map(|x| x.to_string()),
|
||||
pitr_interval: settings.get("pitr_interval").map(|x| x.to_string()),
|
||||
})
|
||||
.send()?
|
||||
.error_from_body()?
|
||||
.json::<Option<String>>()?;
|
||||
|
||||
@@ -5,19 +5,25 @@
|
||||
//! See also `settings.md` for better description on every parameter.
|
||||
|
||||
use anyhow::{bail, ensure, Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use toml_edit;
|
||||
use toml_edit::{Document, Item};
|
||||
use tracing::*;
|
||||
use zenith_utils::bin_ser::BeSer;
|
||||
use zenith_utils::postgres_backend::AuthType;
|
||||
use zenith_utils::zid::{ZNodeId, ZTenantId, ZTimelineId};
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::env;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use std::num::{NonZeroU32, NonZeroUsize};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::layered_repository::TIMELINES_SEGMENT_NAME;
|
||||
use crate::virtual_file::VirtualFile;
|
||||
|
||||
pub mod defaults {
|
||||
use const_format::formatcp;
|
||||
@@ -139,7 +145,9 @@ pub struct PageServerConf {
|
||||
pub remote_storage_config: Option<RemoteStorageConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub const TENANT_CONFIG_NAME: &str = "config";
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct TenantConf {
|
||||
pub checkpoint_distance: u64,
|
||||
pub compaction_period: Duration,
|
||||
@@ -174,6 +182,30 @@ impl<T> BuilderValue<T> {
|
||||
Self::NotSet => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(&self, conf: &'static PageServerConf, tenantid: ZTenantId) -> Result<()> {
|
||||
let _enter = info_span!("saving tenant config").entered();
|
||||
let path = conf.tenant_path(&tenantid).join(TENANT_CONFIG_NAME);
|
||||
let mut file =
|
||||
VirtualFile::open_with_options(&path, OpenOptions::new().write(true).create_new(true))?;
|
||||
let config_bytes = self.ser()?;
|
||||
if file.write(&config_bytes)? != config_bytes.len() {
|
||||
bail!("Could not write all the metadata bytes in a single call");
|
||||
}
|
||||
file.sync_all()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load(conf: &'static PageServerConf, tenantid: ZTenantId) -> Result<TenantConf> {
|
||||
let _enter = info_span!("loading tenant config").entered();
|
||||
let path = conf.tenant_path(&tenantid).join(TENANT_CONFIG_NAME);
|
||||
let content = std::fs::read(&path);
|
||||
match content {
|
||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(Self::from(conf)),
|
||||
Ok(config_bytes) => Ok(TenantConf::des(&config_bytes)?),
|
||||
Err(err) => bail!(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// needed to simplify config construction
|
||||
|
||||
@@ -164,7 +164,8 @@ fn main() -> Result<()> {
|
||||
.subcommand(App::new("create")
|
||||
.arg(tenant_id_arg.clone())
|
||||
.arg(timeline_id_arg.clone().help("Use a specific timeline id when creating a tenant and its initial timeline"))
|
||||
)
|
||||
.arg(Arg::new("config").short('c').takes_value(true).multiple_occurrences(true).required(false))
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
App::new("pageserver")
|
||||
@@ -521,8 +522,12 @@ fn handle_tenant(tenant_match: &ArgMatches, env: &mut local_env::LocalEnv) -> Re
|
||||
}
|
||||
Some(("create", create_match)) => {
|
||||
let initial_tenant_id = parse_tenant_id(create_match)?;
|
||||
let tenant_conf: HashMap<_, _> = create_match
|
||||
.values_of("config")
|
||||
.map(|vals| vals.flat_map(|c| c.split_once(':')).collect())
|
||||
.unwrap_or(HashMap::new());
|
||||
let new_tenant_id = pageserver
|
||||
.tenant_create(initial_tenant_id)?
|
||||
.tenant_create(initial_tenant_id, tenant_conf)?
|
||||
.ok_or_else(|| {
|
||||
anyhow!("Tenant with id {:?} was already created", initial_tenant_id)
|
||||
})?;
|
||||
|
||||
Reference in New Issue
Block a user