diff --git a/about.toml b/about.toml index 10ad409..86eee69 100644 --- a/about.toml +++ b/about.toml @@ -1,4 +1,3 @@ -accepted = ["MIT", "Apache-2.0", "ISC", "BSD-3-Clause", "Unicode-3.0", "OpenSSL", "Zlib"] -workarounds = ["ring"] +accepted = ["MIT", "Apache-2.0", "ISC", "BSD-3-Clause", "Unicode-3.0", "Zlib"] targets = ["x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl"] private = { ignore = true } diff --git a/deny.toml b/deny.toml index 6be295a..9be4849 100644 --- a/deny.toml +++ b/deny.toml @@ -71,6 +71,7 @@ feature-depth = 1 # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ + { id = "RUSTSEC-2025-0069", reason = "We use only a small subset of that unmaintained daemonize crate and it's unlikely to change (if it does this needs to be reconsidered)" }, #"RUSTSEC-0000-0000", #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish @@ -89,7 +90,7 @@ ignore = [ # List of explicitly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. -allow = ["MIT", "Apache-2.0", "ISC", "BSD-3-Clause", "Unicode-3.0", "OpenSSL", "Zlib"] +allow = ["MIT", "Apache-2.0", "ISC", "BSD-3-Clause", "Unicode-3.0", "Zlib"] # The confidence threshold for detecting a license from license text. # The higher the value, the more closely the license text must be to the @@ -107,20 +108,20 @@ exceptions = [ # Some crates don't have (easily) machine readable licensing information, # adding a clarification entry for it allows you to manually specify the # licensing information -[[licenses.clarify]] +# [[licenses.clarify]] # The package spec the clarification applies to -crate = "ring" +# crate = "ring" # The SPDX expression for the license requirements of the crate -expression = "MIT AND ISC AND OpenSSL" +# expression = "MIT AND ISC" # One or more files in the crate's source used as the "source of truth" for # the license expression. If the contents match, the clarification will be used # when running the license check, otherwise the clarification will be ignored # and the crate will be checked normally, which may produce warnings or errors # depending on the rest of your configuration -license-files = [ +# license-files = [ # Each entry is a crate relative path, and the (opaque) hash of its contents -{ path = "LICENSE", hash = 0xbd0eed23 } -] +# { path = "LICENSE", hash = 0xbd0eed23 } +# ] [licenses.private] # If true, ignores workspace crates that aren't published, or are only diff --git a/mgmtd/src/db/import_v7.rs b/mgmtd/src/db/import_v7.rs index 361ba25..5f92ea7 100644 --- a/mgmtd/src/db/import_v7.rs +++ b/mgmtd/src/db/import_v7.rs @@ -65,14 +65,12 @@ pub fn import_v7(tx: &rusqlite::Transaction, base_path: &Path) -> Result<()> { fn check_format_conf(f: &Path) -> Result<()> { let s = std::fs::read_to_string(f)?; - // No need for fancy parsing, we only allow upgrading from this exact file - if s != "# This file was auto-generated. Do not modify it! -version=5 -nodeStates=1 -targetStates=1 -" - { - bail!("Unexpected format.conf:\n{s}"); + if s.matches("version").count() != 1 { + bail!("Unexpected version in format.conf: version field ambiguous or not found"); + } + + if !s.contains("\nversion=5\n") { + bail!("Unexpected version in format.conf: Expected \"version=5\""); } Ok(()) diff --git a/mgmtd/src/grpc/buddy_group.rs b/mgmtd/src/grpc/buddy_group.rs index 9f9d898..63f2753 100644 --- a/mgmtd/src/grpc/buddy_group.rs +++ b/mgmtd/src/grpc/buddy_group.rs @@ -235,9 +235,10 @@ pub(crate) async fn mirror_root_inode( needs_license(&ctx, LicensedFeature::Mirroring)?; fail_on_pre_shutdown(&ctx)?; + let offline_timeout = ctx.info.user_config.node_offline_timeout.as_secs(); let meta_root = ctx .db - .read_tx(|tx| { + .read_tx(move |tx| { let node_uid = match db::misc::get_meta_root(tx)? { MetaRoot::Normal(_, node_uid) => node_uid, MetaRoot::Mirrored(_) => bail!("Root inode is already mirrored"), @@ -267,7 +268,33 @@ pub(crate) async fn mirror_root_inode( })?; if clients > 0 { - bail!("This operation requires that all clients are disconnected/unmounted, but still has {clients} clients mounted."); + bail!( + "This operation requires that all clients are disconnected/unmounted. \ +{clients} clients are still mounted." + ); + } + + let mut server_stmt = tx.prepare(sql!( + "SELECT COUNT(*) FROM nodes + WHERE node_type = ?1 AND UNIXEPOCH('now') - UNIXEPOCH(last_contact) < ?2 + AND node_uid != ?3" + ))?; + + let metas = server_stmt.query_row( + params![NodeType::Meta.sql_variant(), offline_timeout, node_uid], + |row| row.get::<_, i64>(0), + )?; + let storages = server_stmt.query_row( + params![NodeType::Storage.sql_variant(), offline_timeout, node_uid], + |row| row.get::<_, i64>(0), + )?; + + if metas > 0 || storages > 0 { + bail!( + "This operation requires that all nodes except the root meta node are shut \ +down. {metas} meta nodes (excluding the root meta node) and {storages} storage nodes have \ +communicated during the last {offline_timeout}s." + ); } Ok(node_uid)