From fe8a7819fa7133d05d3973079119c85cf7d77f58 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 20 Mar 2024 14:21:08 +0100 Subject: [syslog] Add support to logging to syslog Original patch by Jakub Jirutka for Alpine Linux port. --- src/garage/Cargo.toml | 3 +++ src/garage/main.rs | 58 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/garage/Cargo.toml b/src/garage/Cargo.toml index b022049c..52861853 100644 --- a/src/garage/Cargo.toml +++ b/src/garage/Cargo.toml @@ -58,6 +58,7 @@ opentelemetry.workspace = true opentelemetry-prometheus = { workspace = true, optional = true } opentelemetry-otlp = { workspace = true, optional = true } prometheus = { workspace = true, optional = true } +syslog-tracing = { workspace = true, optional = true } [dev-dependencies] aws-config.workspace = true @@ -97,6 +98,8 @@ kubernetes-discovery = [ "garage_rpc/kubernetes-discovery" ] metrics = [ "garage_api/metrics", "opentelemetry-prometheus", "prometheus" ] # Exporter for the OpenTelemetry Collector. telemetry-otlp = [ "opentelemetry-otlp" ] +# Logging to syslog +syslog = [ "syslog-tracing" ] # NOTE: bundled-libs and system-libs should be treat as mutually exclusive; # exactly one of them should be enabled. diff --git a/src/garage/main.rs b/src/garage/main.rs index e489fff0..3fe96338 100644 --- a/src/garage/main.rs +++ b/src/garage/main.rs @@ -140,17 +140,8 @@ async fn main() { let opt = Opt::from_clap(&Opt::clap().version(version.as_str()).get_matches()); // Initialize logging as well as other libraries used in Garage - if std::env::var("RUST_LOG").is_err() { - let default_log = match &opt.cmd { - Command::Server => "netapp=info,garage=info", - _ => "netapp=warn,garage=warn", - }; - std::env::set_var("RUST_LOG", default_log) - } - tracing_subscriber::fmt() - .with_writer(std::io::stderr) - .with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env()) - .init(); + init_logging(&opt); + sodiumoxide::init().expect("Unable to init sodiumoxide"); let res = match opt.cmd { @@ -173,6 +164,51 @@ async fn main() { } } +fn init_logging(opt: &Opt) { + if std::env::var("RUST_LOG").is_err() { + let default_log = match &opt.cmd { + Command::Server => "netapp=info,garage=info", + _ => "netapp=warn,garage=warn", + }; + std::env::set_var("RUST_LOG", default_log) + } + + let env_filter = tracing_subscriber::filter::EnvFilter::from_default_env(); + + #[cfg(feature = "syslog")] + if std::env::var("GARAGE_LOG_TO_SYSLOG") + .map(|x| x == "1" || x == "true") + .unwrap_or(false) + { + use std::ffi::CStr; + use syslog_tracing::{Facility, Options, Syslog}; + + let syslog = Syslog::new( + CStr::from_bytes_with_nul(b"garage\0").unwrap(), + Options::LOG_PID | Options::LOG_PERROR, + Facility::Daemon, + ) + .expect("Unable to init syslog"); + + tracing_subscriber::fmt() + .with_writer(syslog) + .with_env_filter(env_filter) + .with_ansi(false) // disable ANSI escape sequences (colours) + .with_file(false) + .with_level(false) + .without_time() + .compact() + .init(); + + return; + } + + tracing_subscriber::fmt() + .with_writer(std::io::stderr) + .with_env_filter(env_filter) + .init(); +} + async fn cli_command(opt: Opt) -> Result<(), Error> { let config = if (opt.secrets.rpc_secret.is_none() && opt.secrets.rpc_secret_file.is_none()) || opt.rpc_host.is_none() -- cgit v1.2.3 From 84018be8622b582ad8853df042d10f0e122e6316 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 20 Mar 2024 14:36:13 +0100 Subject: [syslog] warning when syslog support is not enabled --- src/garage/main.rs | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/garage/main.rs b/src/garage/main.rs index 3fe96338..2f9ae508 100644 --- a/src/garage/main.rs +++ b/src/garage/main.rs @@ -175,32 +175,39 @@ fn init_logging(opt: &Opt) { let env_filter = tracing_subscriber::filter::EnvFilter::from_default_env(); - #[cfg(feature = "syslog")] if std::env::var("GARAGE_LOG_TO_SYSLOG") .map(|x| x == "1" || x == "true") .unwrap_or(false) { - use std::ffi::CStr; - use syslog_tracing::{Facility, Options, Syslog}; - - let syslog = Syslog::new( - CStr::from_bytes_with_nul(b"garage\0").unwrap(), - Options::LOG_PID | Options::LOG_PERROR, - Facility::Daemon, - ) - .expect("Unable to init syslog"); - - tracing_subscriber::fmt() - .with_writer(syslog) - .with_env_filter(env_filter) - .with_ansi(false) // disable ANSI escape sequences (colours) - .with_file(false) - .with_level(false) - .without_time() - .compact() - .init(); - - return; + #[cfg(feature = "syslog")] + { + use std::ffi::CStr; + use syslog_tracing::{Facility, Options, Syslog}; + + let syslog = Syslog::new( + CStr::from_bytes_with_nul(b"garage\0").unwrap(), + Options::LOG_PID | Options::LOG_PERROR, + Facility::Daemon, + ) + .expect("Unable to init syslog"); + + tracing_subscriber::fmt() + .with_writer(syslog) + .with_env_filter(env_filter) + .with_ansi(false) // disable ANSI escape sequences (colours) + .with_file(false) + .with_level(false) + .without_time() + .compact() + .init(); + + return; + } + #[cfg(not(feature = "syslog"))] + { + eprintln!("Syslog support is not enabled in this build."); + std::process::exit(1); + } } tracing_subscriber::fmt() -- cgit v1.2.3 From ba33bb31f1855a327b5adc676b92270c90f773e9 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 20 Mar 2024 15:20:25 +0100 Subject: [check-data-dir] add marker files in data directories (fix #601) --- src/block/layout.rs | 60 +++++++++++++++++++++++++++++++++++++++++----------- src/block/manager.rs | 12 +++++------ 2 files changed, 53 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/block/layout.rs b/src/block/layout.rs index e8339405..e78f3f08 100644 --- a/src/block/layout.rs +++ b/src/block/layout.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::path::PathBuf; use serde::{Deserialize, Serialize}; @@ -13,9 +14,12 @@ const DRIVE_NPART: usize = 1024; const HASH_DRIVE_BYTES: (usize, usize) = (2, 3); +const MARKER_FILE_NAME: &str = "garage-marker"; + #[derive(Serialize, Deserialize, Debug, Clone)] pub(crate) struct DataLayout { pub(crate) data_dirs: Vec, + markers: HashMap, /// Primary storage location (index in data_dirs) for each partition /// = the location where the data is supposed to be, blocks are always @@ -75,16 +79,17 @@ impl DataLayout { Ok(Self { data_dirs, + markers: HashMap::new(), part_prim, part_sec, }) } - pub(crate) fn update(&mut self, dirs: &DataDirEnum) -> Result<(), Error> { + pub(crate) fn update(self, dirs: &DataDirEnum) -> Result { // Make list of new data directories, exit if nothing changed let data_dirs = make_data_dirs(dirs)?; if data_dirs == self.data_dirs { - return Ok(()); + return Ok(self); } let total_cap = data_dirs.iter().filter_map(|x| x.capacity()).sum::(); @@ -214,11 +219,43 @@ impl DataLayout { } // Apply newly generated config - *self = Self { + Ok(Self { data_dirs, + markers: self.markers, part_prim, part_sec, - }; + }) + } + + pub(crate) fn check_markers(&mut self) -> Result<(), Error> { + let data_dirs = &self.data_dirs; + self.markers + .retain(|k, _| data_dirs.iter().any(|x| x.path == *k)); + + for dir in self.data_dirs.iter() { + let mut marker_path = dir.path.clone(); + marker_path.push(MARKER_FILE_NAME); + let existing_marker = std::fs::read_to_string(&marker_path).ok(); + match (existing_marker, self.markers.get(&dir.path)) { + (Some(m1), Some(m2)) => { + if m1 != *m2 { + return Err(Error::Message(format!("Mismatched content for marker file `{}` in data directory `{}`. If you moved data directories or changed their mountpoints, you should remove the `data_layout` file in Garage's metadata directory and restart Garage.", MARKER_FILE_NAME, dir.path.display()))); + } + } + (None, Some(_)) => { + return Err(Error::Message(format!("Could not find expected marker file `{}` in data directory `{}`, make sure this data directory is mounted correctly.", MARKER_FILE_NAME, dir.path.display()))); + } + (Some(mkr), None) => { + self.markers.insert(dir.path.clone(), mkr); + } + (None, None) => { + let mkr = hex::encode(garage_util::data::gen_uuid().as_slice()); + std::fs::write(&marker_path, &mkr)?; + self.markers.insert(dir.path.clone(), mkr); + } + } + } + Ok(()) } @@ -255,6 +292,7 @@ impl DataLayout { pub(crate) fn without_secondary_locations(&self) -> Self { Self { data_dirs: self.data_dirs.clone(), + markers: self.markers.clone(), part_prim: self.part_prim.clone(), part_sec: self.part_sec.iter().map(|_| vec![]).collect::>(), } @@ -322,14 +360,12 @@ fn make_data_dirs(dirs: &DataDirEnum) -> Result, Error> { fn dir_not_empty(path: &PathBuf) -> Result { for entry in std::fs::read_dir(&path)? { let dir = entry?; - if dir.file_type()?.is_dir() - && dir - .file_name() - .into_string() - .ok() - .and_then(|hex| hex::decode(&hex).ok()) - .is_some() - { + let ft = dir.file_type()?; + let name = dir.file_name().into_string().ok(); + if ft.is_file() && name.as_deref() == Some(MARKER_FILE_NAME) { + return Ok(true); + } + if ft.is_dir() && name.and_then(|hex| hex::decode(&hex).ok()).is_some() { return Ok(true); } } diff --git a/src/block/manager.rs b/src/block/manager.rs index ef7279e9..34d854b9 100644 --- a/src/block/manager.rs +++ b/src/block/manager.rs @@ -127,17 +127,15 @@ impl BlockManager { // Load or compute layout, i.e. assignment of data blocks to the different data directories let data_layout_persister: Persister = Persister::new(&system.metadata_dir, "data_layout"); - let data_layout = match data_layout_persister.load() { - Ok(mut layout) => { - layout - .update(&config.data_dir) - .ok_or_message("invalid data_dir config")?; - layout - } + let mut data_layout = match data_layout_persister.load() { + Ok(layout) => layout + .update(&config.data_dir) + .ok_or_message("invalid data_dir config")?, Err(_) => { DataLayout::initialize(&config.data_dir).ok_or_message("invalid data_dir config")? } }; + data_layout.check_markers()?; data_layout_persister .save(&data_layout) .expect("cannot save data_layout"); -- cgit v1.2.3 From f267609343a26c383526129ce97df5ac9c28e024 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Tue, 26 Mar 2024 15:39:17 +0100 Subject: [disable-k2v-test] disable tests::k2v::test_poll_item as it is not 100% reliable --- src/garage/tests/k2v/poll.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/garage/tests/k2v/poll.rs b/src/garage/tests/k2v/poll.rs index 277f8bc8..f09c0877 100644 --- a/src/garage/tests/k2v/poll.rs +++ b/src/garage/tests/k2v/poll.rs @@ -10,6 +10,7 @@ use crate::common; use crate::json_body; #[tokio::test] +#[ignore = "currently broken (works ~99% of the time)"] async fn test_poll_item() { let ctx = common::context(); let bucket = ctx.create_bucket("test-k2v-poll-item"); -- cgit v1.2.3 From 73551e9a2dbbd7ff5e9ed0451af68d10617188d1 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Tue, 26 Mar 2024 16:24:26 +0100 Subject: [disable-k2v-test] disable the other k2v poll test --- src/garage/tests/k2v/poll.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/garage/tests/k2v/poll.rs b/src/garage/tests/k2v/poll.rs index f09c0877..7c06cea9 100644 --- a/src/garage/tests/k2v/poll.rs +++ b/src/garage/tests/k2v/poll.rs @@ -10,7 +10,7 @@ use crate::common; use crate::json_body; #[tokio::test] -#[ignore = "currently broken (works ~99% of the time)"] +#[ignore = "currently broken"] async fn test_poll_item() { let ctx = common::context(); let bucket = ctx.create_bucket("test-k2v-poll-item"); @@ -99,6 +99,7 @@ async fn test_poll_item() { } #[tokio::test] +#[ignore = "currently broken"] async fn test_poll_range() { let ctx = common::context(); let bucket = ctx.create_bucket("test-k2v-poll-range"); -- cgit v1.2.3