Save tenant config in pageserver directory

This commit is contained in:
Konstantin Knizhnik
2022-03-01 18:07:03 +03:00
committed by Anastasia Lubennikova
parent baac8ac410
commit 7e6eff4969
3 changed files with 54 additions and 4 deletions

View File

@@ -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>>()?;

View File

@@ -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

View File

@@ -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)
})?;