From 11e39aa696ebb855078be8d3c7328dc9322daeef Mon Sep 17 00:00:00 2001 From: karencfv Date: Thu, 14 Mar 2024 15:05:04 -0700 Subject: [PATCH 01/18] Rename zone-network-cli to zone-setup-cli --- Cargo.lock | 2 +- Cargo.toml | 4 +-- package-manifest.toml | 26 +++++++++---------- smf/opte-interface-setup/manifest.xml | 2 +- smf/zone-network-setup/manifest.xml | 2 +- {zone-network-setup => zone-setup}/Cargo.toml | 2 +- .../src/bin/zone-setup.rs | 14 +++++----- 7 files changed, 26 insertions(+), 26 deletions(-) rename {zone-network-setup => zone-setup}/Cargo.toml (92%) rename zone-network-setup/src/bin/zone-networking.rs => zone-setup/src/bin/zone-setup.rs (95%) diff --git a/Cargo.lock b/Cargo.lock index 84f365e2f0..b5c06f6e3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11083,7 +11083,7 @@ dependencies = [ ] [[package]] -name = "zone-network-setup" +name = "zone-setup" version = "0.1.0" dependencies = [ "anyhow", diff --git a/Cargo.toml b/Cargo.toml index c27a4bef05..6ec5efc4a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ members = [ "wicket", "wicketd", "workspace-hack", - "zone-network-setup", + "zone-setup", ] default-members = [ @@ -156,7 +156,7 @@ default-members = [ "wicket-dbg", "wicket", "wicketd", - "zone-network-setup", + "zone-setup", ] resolver = "2" diff --git a/package-manifest.toml b/package-manifest.toml index a3e1fa133d..9f1fccb33a 100644 --- a/package-manifest.toml +++ b/package-manifest.toml @@ -103,7 +103,7 @@ only_for_targets.image = "standard" source.type = "composite" source.packages = [ "omicron-nexus.tar.gz", - "zone-network-setup.tar.gz", + "zone-setup.tar.gz", "zone-network-install.tar.gz", "opte-interface-setup.tar.gz" ] @@ -133,7 +133,7 @@ output.intermediate_only = true service_name = "oximeter" only_for_targets.image = "standard" source.type = "composite" -source.packages = [ "oximeter-collector.tar.gz", "zone-network-setup.tar.gz", "zone-network-install.tar.gz" ] +source.packages = [ "oximeter-collector.tar.gz", "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" [package.oximeter-collector] @@ -156,7 +156,7 @@ source.type = "composite" source.packages = [ "clickhouse_svc.tar.gz", "internal-dns-cli.tar.gz", - "zone-network-setup.tar.gz", + "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" @@ -182,7 +182,7 @@ source.type = "composite" source.packages = [ "clickhouse_keeper_svc.tar.gz", "internal-dns-cli.tar.gz", - "zone-network-setup.tar.gz", + "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" @@ -208,7 +208,7 @@ source.type = "composite" source.packages = [ "cockroachdb-service.tar.gz", "internal-dns-cli.tar.gz", - "zone-network-setup.tar.gz", + "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" @@ -244,7 +244,7 @@ source.type = "composite" source.packages = [ "dns-server.tar.gz", "internal-dns-customizations.tar.gz", - "zone-network-setup.tar.gz", + "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" @@ -256,7 +256,7 @@ source.type = "composite" source.packages = [ "dns-server.tar.gz", "external-dns-customizations.tar.gz", - "zone-network-setup.tar.gz", + "zone-setup.tar.gz", "zone-network-install.tar.gz", "opte-interface-setup.tar.gz" ] @@ -295,7 +295,7 @@ source.type = "composite" source.packages = [ "ntp-svc.tar.gz", "opte-interface-setup.tar.gz", - "zone-network-setup.tar.gz", + "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" @@ -445,7 +445,7 @@ output.intermediate_only = true service_name = "crucible" only_for_targets.image = "standard" source.type = "composite" -source.packages = [ "crucible.tar.gz", "zone-network-setup.tar.gz", "zone-network-install.tar.gz" ] +source.packages = [ "crucible.tar.gz", "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" @@ -453,7 +453,7 @@ output.type = "zone" service_name = "crucible_pantry" only_for_targets.image = "standard" source.type = "composite" -source.packages = [ "crucible-pantry.tar.gz", "zone-network-setup.tar.gz", "zone-network-install.tar.gz" ] +source.packages = [ "crucible-pantry.tar.gz", "zone-setup.tar.gz", "zone-network-install.tar.gz" ] output.type = "zone" # Packages not built within Omicron, but which must be imported. @@ -726,11 +726,11 @@ source.paths = [ output.type = "zone" output.intermediate_only = true -[package.zone-network-setup] -service_name = "zone-network-cli" +[package.zone-setup] +service_name = "zone-setup-cli" only_for_targets.image = "standard" source.type = "local" -source.rust.binary_names = ["zone-networking"] +source.rust.binary_names = ["zone-setup"] source.rust.release = true output.type = "zone" output.intermediate_only = true diff --git a/smf/opte-interface-setup/manifest.xml b/smf/opte-interface-setup/manifest.xml index 68641f56fc..dc1301d846 100644 --- a/smf/opte-interface-setup/manifest.xml +++ b/smf/opte-interface-setup/manifest.xml @@ -18,7 +18,7 @@ diff --git a/smf/zone-network-setup/manifest.xml b/smf/zone-network-setup/manifest.xml index a20ff949a4..8955f5adc0 100644 --- a/smf/zone-network-setup/manifest.xml +++ b/smf/zone-network-setup/manifest.xml @@ -18,7 +18,7 @@ diff --git a/zone-network-setup/Cargo.toml b/zone-setup/Cargo.toml similarity index 92% rename from zone-network-setup/Cargo.toml rename to zone-setup/Cargo.toml index 28854b82f7..eb0c0d63e1 100644 --- a/zone-network-setup/Cargo.toml +++ b/zone-setup/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "zone-network-setup" +name = "zone-setup" version = "0.1.0" edition = "2021" license = "MPL-2.0" diff --git a/zone-network-setup/src/bin/zone-networking.rs b/zone-setup/src/bin/zone-setup.rs similarity index 95% rename from zone-network-setup/src/bin/zone-networking.rs rename to zone-setup/src/bin/zone-setup.rs index e36afd6b03..c4c041b76a 100644 --- a/zone-network-setup/src/bin/zone-networking.rs +++ b/zone-setup/src/bin/zone-setup.rs @@ -64,12 +64,12 @@ async fn do_run() -> Result<(), CmdError> { level: dropshot::ConfigLoggingLevel::Info, if_exists: dropshot::ConfigLoggingIfExists::Append, } - .to_logger("zone-networking") + .to_logger("zone-setup") .map_err(|err| CmdError::Failure(anyhow!(err)))?; let matches = command!() .subcommand( - Command::new("set-up") + Command::new("common-networking") .about( "Sets up common networking configuration across all zones", ) @@ -96,7 +96,7 @@ async fn do_run() -> Result<(), CmdError> { ), ) .subcommand( - Command::new("opte-interface-set-up") + Command::new("opte-interface") .about("Sets up OPTE interface") .arg( arg!( @@ -122,18 +122,18 @@ async fn do_run() -> Result<(), CmdError> { ) .get_matches(); - if let Some(matches) = matches.subcommand_matches("set-up") { - set_up(matches, log.clone()).await?; + if let Some(matches) = matches.subcommand_matches("common-networking") { + common_nw_set_up(matches, log.clone()).await?; } - if let Some(matches) = matches.subcommand_matches("opte-interface-set-up") { + if let Some(matches) = matches.subcommand_matches("opte-interface") { opte_interface_set_up(matches, log.clone()).await?; } Ok(()) } -async fn set_up(matches: &ArgMatches, log: Logger) -> Result<(), CmdError> { +async fn common_nw_set_up(matches: &ArgMatches, log: Logger) -> Result<(), CmdError> { let datalink: &String = matches.get_one("datalink").unwrap(); let static_addr: &Ipv6Addr = matches.get_one("static_addr").unwrap(); let gateway: Ipv6Addr = *matches.get_one("gateway").unwrap(); From 746f36aa0eb7ae37b61553f34342dd1995a4e238 Mon Sep 17 00:00:00 2001 From: karencfv Date: Thu, 14 Mar 2024 16:54:47 -0700 Subject: [PATCH 02/18] Configure zone-setup cli for ntp zone --- smf/ntp/manifest/manifest.xml | 1 + zone-setup/src/bin/zone-setup.rs | 72 +++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/smf/ntp/manifest/manifest.xml b/smf/ntp/manifest/manifest.xml index 7783bbe76c..93c70d1bad 100644 --- a/smf/ntp/manifest/manifest.xml +++ b/smf/ntp/manifest/manifest.xml @@ -74,6 +74,7 @@ timeout_seconds="60" /> + diff --git a/zone-setup/src/bin/zone-setup.rs b/zone-setup/src/bin/zone-setup.rs index c4c041b76a..c50ba6db2d 100644 --- a/zone-setup/src/bin/zone-setup.rs +++ b/zone-setup/src/bin/zone-setup.rs @@ -5,7 +5,7 @@ //! CLI to set up zone networking use anyhow::anyhow; -use clap::{arg, command, ArgMatches, Command}; +use clap::{arg, command, Arg, ArgMatches, Command}; use illumos_utils::ipadm::Ipadm; use illumos_utils::route::{Gateway, Route}; use omicron_common::cmd::fatal; @@ -51,6 +51,29 @@ fn parse_opte_iface(s: &str) -> anyhow::Result { s.parse().map_err(|_| anyhow!("ERROR: Invalid OPTE interface")) } +fn parse_chrony_conf(s: &str) -> anyhow::Result { + if s == "unknown" { + return Err(anyhow!("ERROR: Missing chrony configuration file")); + }; + + // TODO: actually check the format of the string mends with "chrony.conf" + s.parse().map_err(|_| anyhow!("ERROR: Invalid chrony configuration file")) +} + +fn parse_chrony_tpl(s: &str) -> anyhow::Result { + if s == "unknown" { + return Err(anyhow!("ERROR: Missing chrony template")); + }; + + // TODO: actually check the format of the string matches one of internal + // or boundary NTP + s.parse().map_err(|_| anyhow!("ERROR: Invalid chrony template")) +} + +fn parse_boundary(s: &str) -> anyhow::Result { + s.parse().map_err(|_| anyhow!("ERROR: Invalid boundary input")) +} + #[tokio::main] async fn main() { if let Err(message) = do_run().await { @@ -120,6 +143,48 @@ async fn do_run() -> Result<(), CmdError> { .value_parser(parse_ip), ), ) + .subcommand( + Command::new("ntp") + .about("Start (set up), refresh and stop methods for NTP zone") + .subcommand( + Command::new("start") + .about("NTP zone setup and start chronyd daemon") + // TODO: Maybe I don't even need --file nor --template + .arg( + arg!(-f --file "Chrony configuration file") + .required(true) + .value_parser(parse_chrony_conf) + ) + .arg( + arg!(-t --template "Boundary or internal NTP configuration template") + .required(true) + .value_parser(parse_chrony_tpl), + ) + .arg( + arg!(-b --boundary "Whether this is a boundary or internal NTP zone") + .required(true) + .value_parser(parse_boundary), + ) + .arg( + Arg::new("servers") + .short('s') + .long("servers") + .value_delimiter(' ') + .help("List of NTP servers separated by a space") + .required(true) + // TODO: Add some parsing to this? + ) + .arg( + Arg::new("allow") + .short('a') + .long("allow") + .value_delimiter(' ') + .help("List of allowed IPv6 addresses separated by a space") + // Not required as this only appears in boundary NTP config + // TODO: Add some parsing to this? + ), + ), + ) .get_matches(); if let Some(matches) = matches.subcommand_matches("common-networking") { @@ -133,7 +198,10 @@ async fn do_run() -> Result<(), CmdError> { Ok(()) } -async fn common_nw_set_up(matches: &ArgMatches, log: Logger) -> Result<(), CmdError> { +async fn common_nw_set_up( + matches: &ArgMatches, + log: Logger, +) -> Result<(), CmdError> { let datalink: &String = matches.get_one("datalink").unwrap(); let static_addr: &Ipv6Addr = matches.get_one("static_addr").unwrap(); let gateway: Ipv6Addr = *matches.get_one("gateway").unwrap(); From 44e5a91ae7b2d10f2b3b5bf44603cf13d8361e8b Mon Sep 17 00:00:00 2001 From: karencfv Date: Tue, 2 Apr 2024 14:09:17 -0600 Subject: [PATCH 03/18] Generate chrony config --- smf/ntp/etc/inet/chrony.conf.boundary | 2 - smf/ntp/etc/inet/chrony.conf.internal | 2 - zone-setup/src/bin/zone-setup.rs | 149 ++++++++++++++++++++------ 3 files changed, 119 insertions(+), 34 deletions(-) diff --git a/smf/ntp/etc/inet/chrony.conf.boundary b/smf/ntp/etc/inet/chrony.conf.boundary index d13bc9c815..edd461db1e 100644 --- a/smf/ntp/etc/inet/chrony.conf.boundary +++ b/smf/ntp/etc/inet/chrony.conf.boundary @@ -3,8 +3,6 @@ # NTP servers outside the rack. # -pool @SERVER@ iburst maxdelay 0.1 maxsources 16 - driftfile /var/lib/chrony/drift ntsdumpdir /var/lib/chrony dumpdir /var/lib/chrony diff --git a/smf/ntp/etc/inet/chrony.conf.internal b/smf/ntp/etc/inet/chrony.conf.internal index 9e9ff3ddea..c237a76e1b 100644 --- a/smf/ntp/etc/inet/chrony.conf.internal +++ b/smf/ntp/etc/inet/chrony.conf.internal @@ -3,8 +3,6 @@ # boundary NTP servers within the rack. # -server @SERVER@ iburst minpoll 0 maxpoll 4 - driftfile /var/lib/chrony/drift ntsdumpdir /var/lib/chrony dumpdir /var/lib/chrony diff --git a/zone-setup/src/bin/zone-setup.rs b/zone-setup/src/bin/zone-setup.rs index c50ba6db2d..56ab43ea90 100644 --- a/zone-setup/src/bin/zone-setup.rs +++ b/zone-setup/src/bin/zone-setup.rs @@ -5,16 +5,33 @@ //! CLI to set up zone networking use anyhow::anyhow; -use clap::{arg, command, Arg, ArgMatches, Command}; +use clap::{arg, command, value_parser, Arg, ArgMatches, Command}; use illumos_utils::ipadm::Ipadm; use illumos_utils::route::{Gateway, Route}; use omicron_common::cmd::fatal; use omicron_common::cmd::CmdError; use slog::{info, Logger}; use std::fs; +use std::fs::OpenOptions; +use std::io::Write; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; pub const HOSTS_FILE: &str = "/etc/inet/hosts"; +//pub const CHRONY_CONFIG_FILE: &str = "/etc/inet/chrony.conf"; +//pub const INTERNAL_NTP_CONFIG_TPL: &str = "/etc/inet/chrony.conf.internal"; +//pub const BOUNDARY_NTP_CONFIG_TPL: &str = "/etc/inet/chrony.conf.boundary"; + +// TODO: Removeme, only for testing locally +pub const CHRONY_CONFIG_FILE: &str = "./smf/ntp/etc/inet/chrony.conf"; +pub const INTERNAL_NTP_CONFIG_TPL: &str = + "./smf/ntp/etc/inet/chrony.conf.internal"; +pub const BOUNDARY_NTP_CONFIG_TPL: &str = + "./smf/ntp/etc/inet/chrony.conf.boundary"; + +pub const COMMON_NW_CMD: &str = "common-networking"; +pub const OPTE_INTERFACE_CMD: &str = "opte-interface"; +pub const NTP_CMD: &str = "ntp"; +pub const NTP_START_CMD: &str = "start"; fn parse_ip(s: &str) -> anyhow::Result { if s == "unknown" { @@ -60,16 +77,6 @@ fn parse_chrony_conf(s: &str) -> anyhow::Result { s.parse().map_err(|_| anyhow!("ERROR: Invalid chrony configuration file")) } -fn parse_chrony_tpl(s: &str) -> anyhow::Result { - if s == "unknown" { - return Err(anyhow!("ERROR: Missing chrony template")); - }; - - // TODO: actually check the format of the string matches one of internal - // or boundary NTP - s.parse().map_err(|_| anyhow!("ERROR: Invalid chrony template")) -} - fn parse_boundary(s: &str) -> anyhow::Result { s.parse().map_err(|_| anyhow!("ERROR: Invalid boundary input")) } @@ -92,7 +99,7 @@ async fn do_run() -> Result<(), CmdError> { let matches = command!() .subcommand( - Command::new("common-networking") + Command::new(COMMON_NW_CMD) .about( "Sets up common networking configuration across all zones", ) @@ -119,7 +126,7 @@ async fn do_run() -> Result<(), CmdError> { ), ) .subcommand( - Command::new("opte-interface") + Command::new(OPTE_INTERFACE_CMD) .about("Sets up OPTE interface") .arg( arg!( @@ -144,22 +151,16 @@ async fn do_run() -> Result<(), CmdError> { ), ) .subcommand( - Command::new("ntp") + Command::new(NTP_CMD) .about("Start (set up), refresh and stop methods for NTP zone") .subcommand( Command::new("start") .about("NTP zone setup and start chronyd daemon") - // TODO: Maybe I don't even need --file nor --template .arg( arg!(-f --file "Chrony configuration file") - .required(true) + .default_value(CHRONY_CONFIG_FILE) .value_parser(parse_chrony_conf) ) - .arg( - arg!(-t --template "Boundary or internal NTP configuration template") - .required(true) - .value_parser(parse_chrony_tpl), - ) .arg( arg!(-b --boundary "Whether this is a boundary or internal NTP zone") .required(true) @@ -169,32 +170,120 @@ async fn do_run() -> Result<(), CmdError> { Arg::new("servers") .short('s') .long("servers") + .num_args(1..) .value_delimiter(' ') + .value_parser(value_parser!(String)) .help("List of NTP servers separated by a space") .required(true) // TODO: Add some parsing to this? ) .arg( - Arg::new("allow") - .short('a') - .long("allow") - .value_delimiter(' ') - .help("List of allowed IPv6 addresses separated by a space") - // Not required as this only appears in boundary NTP config - // TODO: Add some parsing to this? + arg!(-a --allow "Allowed IPv6 address") + .value_parser(parse_ipv6), ), ), ) .get_matches(); - if let Some(matches) = matches.subcommand_matches("common-networking") { + if let Some(matches) = matches.subcommand_matches(COMMON_NW_CMD) { common_nw_set_up(matches, log.clone()).await?; } - if let Some(matches) = matches.subcommand_matches("opte-interface") { + if let Some(matches) = matches.subcommand_matches(OPTE_INTERFACE_CMD) { opte_interface_set_up(matches, log.clone()).await?; } + if let Some(matches) = matches.subcommand_matches(NTP_CMD) { + ntp_smf_methods(matches, log.clone()).await?; + } + + Ok(()) +} + +async fn ntp_smf_methods( + matches: &ArgMatches, + log: Logger, +) -> Result<(), CmdError> { + if let Some(matches) = matches.subcommand_matches(NTP_START_CMD) { + ntp_smf_start(matches, log.clone()).await?; + } + + // TODO: Add refresh and stop + Ok(()) +} + +async fn ntp_smf_start( + matches: &ArgMatches, + log: Logger, +) -> Result<(), CmdError> { + let servers = + matches.get_many::("servers").unwrap().collect::>(); + let allow: Option<&Ipv6Addr> = matches.get_one("allow"); + + let file: &String = matches.get_one("file").unwrap(); + let is_boundary: &bool = matches.get_one("boundary").unwrap(); + println!( + "servers: {:?}\nfile: {}\nallow: {:?}\nboundary: {:?}", + servers, file, allow, is_boundary + ); + + let template = if *is_boundary { + BOUNDARY_NTP_CONFIG_TPL + } else { + INTERNAL_NTP_CONFIG_TPL + }; + info!(&log, "Generating chrony configuration file"; "configuration file" => ?file, "configuration template" => ?template, "allowed IPs" => ?allow, "servers" => ?servers, "is boundary" => ?is_boundary); + + // Generate config file + let mut contents = fs::read_to_string(template).map_err(|err| { + CmdError::Failure(anyhow!( + "Could not read chrony configuration template {}: {}", + template, + err + )) + })?; + let new_config = if *is_boundary { + let mut contents = contents.replace( + "@ALLOW@", + &allow.expect("Chrony allowed address not supplied").to_string(), + ); + for s in servers { + let str_line = + format!("pool {} iburst maxdelay 0.1 maxsources 16\n", s); + contents.push_str(&str_line) + } + contents + } else { + for s in servers { + let str_line = format!("server {} iburst minpoll 0 maxpoll 4\n", s); + contents.push_str(&str_line) + } + contents + }; + + let mut config_file = + OpenOptions::new().write(true).truncate(true).open(file).map_err( + |err| { + CmdError::Failure(anyhow!( + "Could not create chrony configuration file {}: {}", + file, + err + )) + }, + )?; + config_file.write(new_config.as_bytes()).map_err(|err| { + CmdError::Failure(anyhow!( + "Could not write to chrony configuration file {}: {}", + file, + err + )) + })?; + + // TODO: Check if file has changed + + // TODO: Update logadm + + // TODO: Start daemon Ok(()) } From 64c6c6b6bfda371831a9f011a2d9e066832f388c Mon Sep 17 00:00:00 2001 From: karencfv Date: Tue, 2 Apr 2024 14:49:00 -0600 Subject: [PATCH 04/18] Check if file has changed --- zone-setup/src/bin/zone-setup.rs | 61 +++++++++++++++++++------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/zone-setup/src/bin/zone-setup.rs b/zone-setup/src/bin/zone-setup.rs index 56ab43ea90..fee5990751 100644 --- a/zone-setup/src/bin/zone-setup.rs +++ b/zone-setup/src/bin/zone-setup.rs @@ -11,22 +11,15 @@ use illumos_utils::route::{Gateway, Route}; use omicron_common::cmd::fatal; use omicron_common::cmd::CmdError; use slog::{info, Logger}; -use std::fs; -use std::fs::OpenOptions; +use std::fs::{read_to_string, write, OpenOptions}; use std::io::Write; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use std::path::Path; pub const HOSTS_FILE: &str = "/etc/inet/hosts"; -//pub const CHRONY_CONFIG_FILE: &str = "/etc/inet/chrony.conf"; -//pub const INTERNAL_NTP_CONFIG_TPL: &str = "/etc/inet/chrony.conf.internal"; -//pub const BOUNDARY_NTP_CONFIG_TPL: &str = "/etc/inet/chrony.conf.boundary"; - -// TODO: Removeme, only for testing locally -pub const CHRONY_CONFIG_FILE: &str = "./smf/ntp/etc/inet/chrony.conf"; -pub const INTERNAL_NTP_CONFIG_TPL: &str = - "./smf/ntp/etc/inet/chrony.conf.internal"; -pub const BOUNDARY_NTP_CONFIG_TPL: &str = - "./smf/ntp/etc/inet/chrony.conf.boundary"; +pub const CHRONY_CONFIG_FILE: &str = "/etc/inet/chrony.conf"; +pub const INTERNAL_NTP_CONFIG_TPL: &str = "/etc/inet/chrony.conf.internal"; +pub const BOUNDARY_NTP_CONFIG_TPL: &str = "/etc/inet/chrony.conf.boundary"; pub const COMMON_NW_CMD: &str = "common-networking"; pub const OPTE_INTERFACE_CMD: &str = "opte-interface"; @@ -235,7 +228,7 @@ async fn ntp_smf_start( info!(&log, "Generating chrony configuration file"; "configuration file" => ?file, "configuration template" => ?template, "allowed IPs" => ?allow, "servers" => ?servers, "is boundary" => ?is_boundary); // Generate config file - let mut contents = fs::read_to_string(template).map_err(|err| { + let mut contents = read_to_string(template).map_err(|err| { CmdError::Failure(anyhow!( "Could not read chrony configuration template {}: {}", template, @@ -261,16 +254,32 @@ async fn ntp_smf_start( contents }; - let mut config_file = - OpenOptions::new().write(true).truncate(true).open(file).map_err( - |err| { - CmdError::Failure(anyhow!( - "Could not create chrony configuration file {}: {}", - file, - err - )) - }, - )?; + // We read the contents from the old configuration file if it existed + // so that we can verify if it changed. + let old_file = if Path::exists(Path::new(file)) { + Some(read_to_string(file).map_err(|err| { + CmdError::Failure(anyhow!( + "Could not read old chrony configuration file {}: {}", + file, + err + )) + })?) + } else { + None + }; + + let mut config_file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(file) + .map_err(|err| { + CmdError::Failure(anyhow!( + "Could not create chrony configuration file {}: {}", + file, + err + )) + })?; config_file.write(new_config.as_bytes()).map_err(|err| { CmdError::Failure(anyhow!( "Could not write to chrony configuration file {}: {}", @@ -279,7 +288,9 @@ async fn ntp_smf_start( )) })?; - // TODO: Check if file has changed + if old_file.clone().is_some_and(|f| f != new_config) { + info!(&log, "Chrony configuration file has changed"; "old configuration file" => ?old_file); + } // TODO: Update logadm @@ -320,7 +331,7 @@ async fn common_nw_set_up( .map_err(|err| CmdError::Failure(anyhow!(err)))?; info!(&log, "Populating hosts file for zone"; "zonename" => ?zonename); - fs::write( + write( HOSTS_FILE, format!( r#" From 17fc8cd5b5c6a6e39ed4664324647cc9a632c84a Mon Sep 17 00:00:00 2001 From: karencfv Date: Wed, 3 Apr 2024 20:36:44 -0600 Subject: [PATCH 05/18] temp lines in templates --- smf/ntp/etc/inet/chrony.conf.boundary | 3 +++ smf/ntp/etc/inet/chrony.conf.internal | 3 +++ 2 files changed, 6 insertions(+) diff --git a/smf/ntp/etc/inet/chrony.conf.boundary b/smf/ntp/etc/inet/chrony.conf.boundary index edd461db1e..5ced1e6559 100644 --- a/smf/ntp/etc/inet/chrony.conf.boundary +++ b/smf/ntp/etc/inet/chrony.conf.boundary @@ -3,6 +3,9 @@ # NTP servers outside the rack. # +# TODO: Removeme once svc-site-ntp file is gone +pool @SERVER@ iburst maxdelay 0.1 maxsources 16 + driftfile /var/lib/chrony/drift ntsdumpdir /var/lib/chrony dumpdir /var/lib/chrony diff --git a/smf/ntp/etc/inet/chrony.conf.internal b/smf/ntp/etc/inet/chrony.conf.internal index c237a76e1b..73c7685fdb 100644 --- a/smf/ntp/etc/inet/chrony.conf.internal +++ b/smf/ntp/etc/inet/chrony.conf.internal @@ -3,6 +3,9 @@ # boundary NTP servers within the rack. # +# TODO: Removeme once svc-site-ntp file is gone +server @SERVER@ iburst minpoll 0 maxpoll 4 + driftfile /var/lib/chrony/drift ntsdumpdir /var/lib/chrony dumpdir /var/lib/chrony From 19d47b539bbe5a835d7f33a575d80e0ed0588b36 Mon Sep 17 00:00:00 2001 From: karencfv Date: Thu, 4 Apr 2024 14:58:29 -0600 Subject: [PATCH 06/18] enable new start method --- illumos-utils/src/lib.rs | 2 ++ illumos-utils/src/zone.rs | 1 + smf/ntp/manifest/manifest.xml | 5 +++- zone-setup/src/bin/zone-setup.rs | 41 +++++++++++++++++++++++++++++++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/illumos-utils/src/lib.rs b/illumos-utils/src/lib.rs index 550170b0f2..d2ae779c6c 100644 --- a/illumos-utils/src/lib.rs +++ b/illumos-utils/src/lib.rs @@ -10,6 +10,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use cfg_if::cfg_if; pub mod addrobj; +pub mod chronyd; pub mod coreadm; pub mod destructor; pub mod dkio; @@ -24,6 +25,7 @@ pub mod route; pub mod running_zone; pub mod scf; pub mod svc; +pub mod svcadm; pub mod vmm_reservoir; pub mod zfs; pub mod zone; diff --git a/illumos-utils/src/zone.rs b/illumos-utils/src/zone.rs index 3f749fc352..8ce7fb58e6 100644 --- a/illumos-utils/src/zone.rs +++ b/illumos-utils/src/zone.rs @@ -17,6 +17,7 @@ use crate::dladm::{EtherstubVnic, VNIC_PREFIX_BOOTSTRAP, VNIC_PREFIX_CONTROL}; use crate::{execute, PFEXEC}; use omicron_common::address::SLED_PREFIX; +pub const CHRONYD: &str = "/usr/sbin/chronyd"; const DLADM: &str = "/usr/sbin/dladm"; pub const IPADM: &str = "/usr/sbin/ipadm"; pub const SVCADM: &str = "/usr/sbin/svcadm"; diff --git a/smf/ntp/manifest/manifest.xml b/smf/ntp/manifest/manifest.xml index 93c70d1bad..d3d81e7352 100644 --- a/smf/ntp/manifest/manifest.xml +++ b/smf/ntp/manifest/manifest.xml @@ -57,7 +57,10 @@ The service also always starts the binary with ASLR enabled, regardless of whether it was linked with -zaslr --> - + ?old_file); } + // End gen_config_file here + + // Update logadm + // + // The NTP zone delivers a logadm fragment into /etc/logadm.d/ that needs to + // be added to the system's /etc/logadm.conf. Unfortunately, the service which + // does this - system/logadm-upgrade - only processes files with mode 444 and + // root:sys ownership so we need to adjust things here (until omicron package + // supports including ownership and permissions in the generated tar files). + // + // TODO: There is an error here + // zone-setup: Could not create chrony logadm configuration file /etc/logadm.d/chrony.logadm.conf: Invalid argument (os error 22) + let mut options = OpenOptions::new(); + options.mode(444).create(true).open(LOGADM_CONFIG_FILE).map_err(|err| { + CmdError::Failure(anyhow!( + "Could not create chrony logadm configuration file {}: {}", + LOGADM_CONFIG_FILE, + err + )) + })?; - // TODO: Update logadm + chown(LOGADM_CONFIG_FILE, Some(0), Some(3)).map_err(|err| { + CmdError::Failure(anyhow!( + "Could not set ownership of logadm configuration file {}: {}", + LOGADM_CONFIG_FILE, + err + )) + })?; + + info!(&log, "Updating logadm"; "logadm config" => ?LOGADM_CONFIG_FILE); + Svcadm::refresh_logadm_upgrade() + .map_err(|err| CmdError::Failure(anyhow!(err)))?; // TODO: Start daemon + info!(&log, "Starting chronyd daemon"; "chrony config" => ?file); + Chronyd::start_daemon(file) + .map_err(|err| CmdError::Failure(anyhow!(err)))?; Ok(()) } From bb15ccc991eea0a0539faf0323560bfeac995bf4 Mon Sep 17 00:00:00 2001 From: karencfv Date: Fri, 5 Apr 2024 15:52:00 -0600 Subject: [PATCH 07/18] ntp start command works except for starting daemon bit --- illumos-utils/src/chronyd.rs | 24 ++++++++++++++ illumos-utils/src/svcadm.rs | 21 ++++++++++++ smf/ntp/etc/inet/chrony.conf.boundary | 2 +- smf/ntp/etc/inet/chrony.conf.internal | 2 +- smf/ntp/manifest/manifest.xml | 2 +- zone-setup/src/bin/zone-setup.rs | 46 +++++++++++++++++---------- 6 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 illumos-utils/src/chronyd.rs create mode 100644 illumos-utils/src/svcadm.rs diff --git a/illumos-utils/src/chronyd.rs b/illumos-utils/src/chronyd.rs new file mode 100644 index 0000000000..181efb6eef --- /dev/null +++ b/illumos-utils/src/chronyd.rs @@ -0,0 +1,24 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Utilities for interacting with chronyd. + +use crate::zone::CHRONYD; +use crate::{execute, ExecutionError, PFEXEC}; + +/// Wraps commands for interacting with chronyd. +pub struct Chronyd {} + +#[cfg_attr(any(test, feature = "testing"), mockall::automock)] +impl Chronyd { + pub fn start_daemon(file: &str) -> Result<(), ExecutionError> { + let mut cmd = std::process::Command::new(PFEXEC); + // TODO: This doesn't seem to be working. I think `execute()` + // doesn't like the "&", and it immediately exits after running. + // find a way to keep the process going. + let cmd = cmd.args(&[CHRONYD, "-d", "-f", file, "&"]); + execute(cmd)?; + Ok(()) + } +} diff --git a/illumos-utils/src/svcadm.rs b/illumos-utils/src/svcadm.rs new file mode 100644 index 0000000000..0d472187df --- /dev/null +++ b/illumos-utils/src/svcadm.rs @@ -0,0 +1,21 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Utilities for manipulating SMF services. + +use crate::zone::SVCADM; +use crate::{execute, ExecutionError, PFEXEC}; + +/// Wraps commands for interacting with svcadm. +pub struct Svcadm {} + +#[cfg_attr(any(test, feature = "testing"), mockall::automock)] +impl Svcadm { + pub fn refresh_logadm_upgrade() -> Result<(), ExecutionError> { + let mut cmd = std::process::Command::new(PFEXEC); + let cmd = cmd.args(&[SVCADM, "refresh", "logadm-upgrade"]); + execute(cmd)?; + Ok(()) + } +} diff --git a/smf/ntp/etc/inet/chrony.conf.boundary b/smf/ntp/etc/inet/chrony.conf.boundary index 5ced1e6559..58718e8752 100644 --- a/smf/ntp/etc/inet/chrony.conf.boundary +++ b/smf/ntp/etc/inet/chrony.conf.boundary @@ -4,7 +4,7 @@ # # TODO: Removeme once svc-site-ntp file is gone -pool @SERVER@ iburst maxdelay 0.1 maxsources 16 +# pool @SERVER@ iburst maxdelay 0.1 maxsources 16 driftfile /var/lib/chrony/drift ntsdumpdir /var/lib/chrony diff --git a/smf/ntp/etc/inet/chrony.conf.internal b/smf/ntp/etc/inet/chrony.conf.internal index 73c7685fdb..e7e0821c0c 100644 --- a/smf/ntp/etc/inet/chrony.conf.internal +++ b/smf/ntp/etc/inet/chrony.conf.internal @@ -4,7 +4,7 @@ # # TODO: Removeme once svc-site-ntp file is gone -server @SERVER@ iburst minpoll 0 maxpoll 4 +# server @SERVER@ iburst minpoll 0 maxpoll 4 driftfile /var/lib/chrony/drift ntsdumpdir /var/lib/chrony diff --git a/smf/ntp/manifest/manifest.xml b/smf/ntp/manifest/manifest.xml index d3d81e7352..5ee2fcaf6b 100644 --- a/smf/ntp/manifest/manifest.xml +++ b/smf/ntp/manifest/manifest.xml @@ -60,7 +60,7 @@ anyhow::Result { s.parse().map_err(|_| anyhow!("ERROR: Invalid OPTE interface")) } +fn parse_allow(s: &str) -> anyhow::Result { + if s == "unknown" { + return Err(anyhow!("ERROR: Missing allowed address range")); + }; + + s.parse().map_err(|_| anyhow!("ERROR: Invalid allowed address range")) +} + fn parse_chrony_conf(s: &str) -> anyhow::Result { if s == "unknown" { return Err(anyhow!("ERROR: Missing chrony configuration file")); }; - // TODO: actually check the format of the string mends with "chrony.conf" + // TODO: actually check the format of the string ends with "chrony.conf" s.parse().map_err(|_| anyhow!("ERROR: Invalid chrony configuration file")) } @@ -176,8 +183,8 @@ async fn do_run() -> Result<(), CmdError> { // TODO: Add some parsing to this? ) .arg( - arg!(-a --allow "Allowed IPv6 address") - .value_parser(parse_ipv6), + arg!(-a --allow "Allowed IPv6 range") + .value_parser(parse_allow), ), ), ) @@ -216,7 +223,7 @@ async fn ntp_smf_start( ) -> Result<(), CmdError> { let servers = matches.get_many::("servers").unwrap().collect::>(); - let allow: Option<&Ipv6Addr> = matches.get_one("allow"); + let allow: Option<&String> = matches.get_one("allow"); let file: &String = matches.get_one("file").unwrap(); let is_boundary: &bool = matches.get_one("boundary").unwrap(); @@ -306,17 +313,23 @@ async fn ntp_smf_start( // does this - system/logadm-upgrade - only processes files with mode 444 and // root:sys ownership so we need to adjust things here (until omicron package // supports including ownership and permissions in the generated tar files). - // - // TODO: There is an error here - // zone-setup: Could not create chrony logadm configuration file /etc/logadm.d/chrony.logadm.conf: Invalid argument (os error 22) - let mut options = OpenOptions::new(); - options.mode(444).create(true).open(LOGADM_CONFIG_FILE).map_err(|err| { - CmdError::Failure(anyhow!( - "Could not create chrony logadm configuration file {}: {}", + let mut perms = metadata(LOGADM_CONFIG_FILE) + .map_err(|err| { + CmdError::Failure(anyhow!( + "Could not retrieve chrony logadm configuration file {} metadata: {}", LOGADM_CONFIG_FILE, err )) - })?; + })? + .permissions(); + perms.set_readonly(true); + set_permissions(LOGADM_CONFIG_FILE, perms).map_err(|err| { + CmdError::Failure(anyhow!( + "Could not set 444 permissions on chrony logadm configuration file {}: {}", + LOGADM_CONFIG_FILE, + err + )) + })?; chown(LOGADM_CONFIG_FILE, Some(0), Some(3)).map_err(|err| { CmdError::Failure(anyhow!( @@ -330,7 +343,6 @@ async fn ntp_smf_start( Svcadm::refresh_logadm_upgrade() .map_err(|err| CmdError::Failure(anyhow!(err)))?; - // TODO: Start daemon info!(&log, "Starting chronyd daemon"; "chrony config" => ?file); Chronyd::start_daemon(file) .map_err(|err| CmdError::Failure(anyhow!(err)))?; From 8afbf7b94646e2064e574f7efce924d25fbeb3e4 Mon Sep 17 00:00:00 2001 From: karencfv Date: Tue, 9 Apr 2024 14:05:59 -0600 Subject: [PATCH 08/18] Add new chrony-setup service --- package-manifest.toml | 17 +++++++- sled-agent/src/services.rs | 7 ++++ .../etc/inet/chrony.conf.boundary | 33 +++++++++++++++ .../etc/inet/chrony.conf.internal | 32 ++++++++++++++ .../etc/logadm.d/chrony.logadm.conf | 2 + smf/chrony-setup/manifest.xml | 42 +++++++++++++++++++ smf/ntp/manifest/manifest.xml | 19 ++++++--- smf/ntp/method/svc-site-ntp | 4 +- zone-setup/src/bin/zone-setup.rs | 36 +++++++++++++++- 9 files changed, 182 insertions(+), 10 deletions(-) create mode 100644 smf/chrony-setup/etc/inet/chrony.conf.boundary create mode 100644 smf/chrony-setup/etc/inet/chrony.conf.internal create mode 100644 smf/chrony-setup/etc/logadm.d/chrony.logadm.conf create mode 100644 smf/chrony-setup/manifest.xml diff --git a/package-manifest.toml b/package-manifest.toml index 575ef87aa2..d57a09c32b 100644 --- a/package-manifest.toml +++ b/package-manifest.toml @@ -294,6 +294,7 @@ service_name = "ntp" only_for_targets.image = "standard" source.type = "composite" source.packages = [ + "chrony-setup.tar.gz", "ntp-svc.tar.gz", "opte-interface-setup.tar.gz", "zone-setup.tar.gz", @@ -307,8 +308,20 @@ only_for_targets.image = "standard" source.type = "local" source.paths = [ { from = "smf/ntp/manifest", to = "/var/svc/manifest/site/ntp" }, - { from = "smf/ntp/method", to = "/var/svc/method" }, - { from = "smf/ntp/etc", to = "/etc" }, + # TODO: Removeme + # { from = "smf/ntp/method", to = "/var/svc/method" }, + # { from = "smf/ntp/etc", to = "/etc" }, +] +output.intermediate_only = true +output.type = "zone" + +[package.chrony-setup] +service_name = "chrony-setup" +only_for_targets.image = "standard" +source.type = "local" +source.paths = [ + { from = "smf/chrony-setup/manifest.xml", to = "/var/svc/manifest/site/chrony-setup/manifest.xml" }, + { from = "smf/chrony-setup/etc", to = "/etc" }, ] output.intermediate_only = true output.type = "zone" diff --git a/sled-agent/src/services.rs b/sled-agent/src/services.rs index bfc0b91a71..ed5015c7bb 100644 --- a/sled-agent/src/services.rs +++ b/sled-agent/src/services.rs @@ -2019,6 +2019,12 @@ impl ServiceManager { } let ntp_service = ServiceBuilder::new("oxide/ntp") + .add_instance( + ServiceInstanceBuilder::new("default") + // .add_property_group(ntp_config), + ); + + let chrony_setup_service = ServiceBuilder::new("oxide/chrony-setup") .add_instance( ServiceInstanceBuilder::new("default") .add_property_group(ntp_config), @@ -2026,6 +2032,7 @@ impl ServiceManager { let mut profile = ProfileBuilder::new("omicron") .add_service(nw_setup_service) + .add_service(chrony_setup_service) .add_service(disabled_ssh_service) .add_service(dns_install_service) .add_service(dns_client_service) diff --git a/smf/chrony-setup/etc/inet/chrony.conf.boundary b/smf/chrony-setup/etc/inet/chrony.conf.boundary new file mode 100644 index 0000000000..58718e8752 --- /dev/null +++ b/smf/chrony-setup/etc/inet/chrony.conf.boundary @@ -0,0 +1,33 @@ +# +# Configuration file for a boundary NTP server - one which communicates with +# NTP servers outside the rack. +# + +# TODO: Removeme once svc-site-ntp file is gone +# pool @SERVER@ iburst maxdelay 0.1 maxsources 16 + +driftfile /var/lib/chrony/drift +ntsdumpdir /var/lib/chrony +dumpdir /var/lib/chrony +pidfile /var/run/chrony/chronyd.pid +logdir /var/log/chrony + +log measurements statistics tracking + +allow fe80::/10 +allow @ALLOW@ + +# Enable local reference mode, which keeps us operating as an NTP server that +# appears synchronised even if there are currently no active upstreams. When +# in this mode, we report as stratum 10 to clients. +local stratum 10 + +# makestep +# We allow chrony to step the system clock during the first three time updates +# if we are more than 0.1 seconds out. +makestep 0.1 3 + +# When a leap second occurs we slew the clock over approximately 37 seconds. +leapsecmode slew +maxslewrate 2708.333 + diff --git a/smf/chrony-setup/etc/inet/chrony.conf.internal b/smf/chrony-setup/etc/inet/chrony.conf.internal new file mode 100644 index 0000000000..e7e0821c0c --- /dev/null +++ b/smf/chrony-setup/etc/inet/chrony.conf.internal @@ -0,0 +1,32 @@ +# +# Configuration file for an internal NTP server - one which communicates with +# boundary NTP servers within the rack. +# + +# TODO: Removeme once svc-site-ntp file is gone +# server @SERVER@ iburst minpoll 0 maxpoll 4 + +driftfile /var/lib/chrony/drift +ntsdumpdir /var/lib/chrony +dumpdir /var/lib/chrony +pidfile /var/run/chrony/chronyd.pid +logdir /var/log/chrony + +log measurements statistics tracking + +# makestep +# We allow chrony to step the system clock if we are more than a day out, +# regardless of how many clock updates have occurred since boot. +# The boundary NTP servers are configured with local reference mode, which +# means that if they start up without external connectivity, they will appear +# as authoritative servers even if they are advertising January 1987 +# (which is the default system clock on a gimlet after boot). +# This configuration allows a one-off adjustment once RSS begins and the +# boundary servers are synchronised, after which the clock will advance +# monotonically forwards. +makestep 86400 -1 + +# When a leap second occurs we slew the clock over approximately 37 seconds. +leapsecmode slew +maxslewrate 2708.333 + diff --git a/smf/chrony-setup/etc/logadm.d/chrony.logadm.conf b/smf/chrony-setup/etc/logadm.d/chrony.logadm.conf new file mode 100644 index 0000000000..fc335d658a --- /dev/null +++ b/smf/chrony-setup/etc/logadm.d/chrony.logadm.conf @@ -0,0 +1,2 @@ +# Rotate chrony logs at 10MiB and keep 10 compressed old logs. +chrony_logs /var/log/chrony/*.log -C 10 -z 0 -s 10m -c -t '$file.$secs' diff --git a/smf/chrony-setup/manifest.xml b/smf/chrony-setup/manifest.xml new file mode 100644 index 0000000000..3d39a36196 --- /dev/null +++ b/smf/chrony-setup/manifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/smf/ntp/manifest/manifest.xml b/smf/ntp/manifest/manifest.xml index 5ee2fcaf6b..cc6d7abe56 100644 --- a/smf/ntp/manifest/manifest.xml +++ b/smf/ntp/manifest/manifest.xml @@ -39,6 +39,11 @@ + + + + @@ -59,30 +64,34 @@ --> - + + + + TODO: Why is this even being set as a property instead of direclty on the method?? +--> diff --git a/smf/ntp/method/svc-site-ntp b/smf/ntp/method/svc-site-ntp index 8b1e3c7d52..2c3e080f63 100755 --- a/smf/ntp/method/svc-site-ntp +++ b/smf/ntp/method/svc-site-ntp @@ -108,8 +108,8 @@ function update_logadm { case $action in start) - generate_config_file - update_logadm + # generate_config_file + # update_logadm start_daemon ;; refresh) diff --git a/zone-setup/src/bin/zone-setup.rs b/zone-setup/src/bin/zone-setup.rs index 090332591b..8d7bc935a2 100644 --- a/zone-setup/src/bin/zone-setup.rs +++ b/zone-setup/src/bin/zone-setup.rs @@ -27,6 +27,8 @@ pub const BOUNDARY_NTP_CONFIG_TPL: &str = "/etc/inet/chrony.conf.boundary"; pub const COMMON_NW_CMD: &str = "common-networking"; pub const OPTE_INTERFACE_CMD: &str = "opte-interface"; +pub const CHRONY_SETUP_CMD: &str = "chrony-setup"; +// TODO: Removeme before merging pub const NTP_CMD: &str = "ntp"; pub const NTP_START_CMD: &str = "start"; @@ -155,11 +157,41 @@ async fn do_run() -> Result<(), CmdError> { .value_parser(parse_ip), ), ) + .subcommand( + Command::new(CHRONY_SETUP_CMD) + .about("Sets up Chrony configuration for NTP zone") + .arg( + arg!(-f --file "Chrony configuration file") + .default_value(CHRONY_CONFIG_FILE) + .value_parser(parse_chrony_conf) + ) + .arg( + arg!(-b --boundary "Whether this is a boundary or internal NTP zone") + .required(true) + .value_parser(parse_boundary), + ) + .arg( + Arg::new("servers") + .short('s') + .long("servers") + .num_args(1..) + .value_delimiter(' ') + .value_parser(value_parser!(String)) + .help("List of NTP servers separated by a space") + .required(true) + // TODO: Add some parsing to this? + ) + .arg( + arg!(-a --allow "Allowed IPv6 range") + .value_parser(parse_allow), + ), + ) + // TODO: Removeme before merging .subcommand( Command::new(NTP_CMD) .about("Start (set up), refresh and stop methods for NTP zone") .subcommand( - Command::new("start") + Command::new(NTP_START_CMD) .about("NTP zone setup and start chronyd daemon") .arg( arg!(-f --file "Chrony configuration file") @@ -202,6 +234,8 @@ async fn do_run() -> Result<(), CmdError> { ntp_smf_methods(matches, log.clone()).await?; } + // TODO: Match on chrony setup + Ok(()) } From 3cbf2ccb17819a81b8b2f94ce8a2737b6e24b475 Mon Sep 17 00:00:00 2001 From: karencfv Date: Tue, 9 Apr 2024 14:35:23 -0600 Subject: [PATCH 09/18] Working --- zone-setup/src/bin/zone-setup.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/zone-setup/src/bin/zone-setup.rs b/zone-setup/src/bin/zone-setup.rs index 8d7bc935a2..462d54b7c4 100644 --- a/zone-setup/src/bin/zone-setup.rs +++ b/zone-setup/src/bin/zone-setup.rs @@ -6,7 +6,8 @@ use anyhow::anyhow; use clap::{arg, command, value_parser, Arg, ArgMatches, Command}; -use illumos_utils::chronyd::Chronyd; +// TODO: Removeme +// use illumos_utils::chronyd::Chronyd; use illumos_utils::ipadm::Ipadm; use illumos_utils::route::{Gateway, Route}; use illumos_utils::svcadm::Svcadm; @@ -230,11 +231,14 @@ async fn do_run() -> Result<(), CmdError> { opte_interface_set_up(matches, log.clone()).await?; } + // TODO: Removeme if let Some(matches) = matches.subcommand_matches(NTP_CMD) { ntp_smf_methods(matches, log.clone()).await?; } - // TODO: Match on chrony setup + if let Some(matches) = matches.subcommand_matches(CHRONY_SETUP_CMD) { + chrony_setup(matches, log.clone()).await?; + } Ok(()) } @@ -244,14 +248,14 @@ async fn ntp_smf_methods( log: Logger, ) -> Result<(), CmdError> { if let Some(matches) = matches.subcommand_matches(NTP_START_CMD) { - ntp_smf_start(matches, log.clone()).await?; + chrony_setup(matches, log.clone()).await?; } // TODO: Add refresh and stop Ok(()) } -async fn ntp_smf_start( +async fn chrony_setup( matches: &ArgMatches, log: Logger, ) -> Result<(), CmdError> { @@ -376,10 +380,10 @@ async fn ntp_smf_start( info!(&log, "Updating logadm"; "logadm config" => ?LOGADM_CONFIG_FILE); Svcadm::refresh_logadm_upgrade() .map_err(|err| CmdError::Failure(anyhow!(err)))?; - - info!(&log, "Starting chronyd daemon"; "chrony config" => ?file); - Chronyd::start_daemon(file) - .map_err(|err| CmdError::Failure(anyhow!(err)))?; + // TODO: Removeme + // info!(&log, "Starting chronyd daemon"; "chrony config" => ?file); + // Chronyd::start_daemon(file) + // .map_err(|err| CmdError::Failure(anyhow!(err)))?; Ok(()) } From 45deb922c6184bd92d07a8bbaac7a17f2e8c190d Mon Sep 17 00:00:00 2001 From: karencfv Date: Tue, 9 Apr 2024 18:36:32 -0600 Subject: [PATCH 10/18] clean up files --- package-manifest.toml | 3 - smf/ntp/etc/inet/chrony.conf.boundary | 33 ------ smf/ntp/etc/inet/chrony.conf.internal | 32 ------ smf/ntp/etc/logadm.d/chrony.logadm.conf | 2 - smf/ntp/manifest/manifest.xml | 17 ---- smf/ntp/method/svc-site-ntp | 128 ------------------------ 6 files changed, 215 deletions(-) delete mode 100644 smf/ntp/etc/inet/chrony.conf.boundary delete mode 100644 smf/ntp/etc/inet/chrony.conf.internal delete mode 100644 smf/ntp/etc/logadm.d/chrony.logadm.conf delete mode 100755 smf/ntp/method/svc-site-ntp diff --git a/package-manifest.toml b/package-manifest.toml index d57a09c32b..e50791face 100644 --- a/package-manifest.toml +++ b/package-manifest.toml @@ -308,9 +308,6 @@ only_for_targets.image = "standard" source.type = "local" source.paths = [ { from = "smf/ntp/manifest", to = "/var/svc/manifest/site/ntp" }, - # TODO: Removeme - # { from = "smf/ntp/method", to = "/var/svc/method" }, - # { from = "smf/ntp/etc", to = "/etc" }, ] output.intermediate_only = true output.type = "zone" diff --git a/smf/ntp/etc/inet/chrony.conf.boundary b/smf/ntp/etc/inet/chrony.conf.boundary deleted file mode 100644 index 58718e8752..0000000000 --- a/smf/ntp/etc/inet/chrony.conf.boundary +++ /dev/null @@ -1,33 +0,0 @@ -# -# Configuration file for a boundary NTP server - one which communicates with -# NTP servers outside the rack. -# - -# TODO: Removeme once svc-site-ntp file is gone -# pool @SERVER@ iburst maxdelay 0.1 maxsources 16 - -driftfile /var/lib/chrony/drift -ntsdumpdir /var/lib/chrony -dumpdir /var/lib/chrony -pidfile /var/run/chrony/chronyd.pid -logdir /var/log/chrony - -log measurements statistics tracking - -allow fe80::/10 -allow @ALLOW@ - -# Enable local reference mode, which keeps us operating as an NTP server that -# appears synchronised even if there are currently no active upstreams. When -# in this mode, we report as stratum 10 to clients. -local stratum 10 - -# makestep -# We allow chrony to step the system clock during the first three time updates -# if we are more than 0.1 seconds out. -makestep 0.1 3 - -# When a leap second occurs we slew the clock over approximately 37 seconds. -leapsecmode slew -maxslewrate 2708.333 - diff --git a/smf/ntp/etc/inet/chrony.conf.internal b/smf/ntp/etc/inet/chrony.conf.internal deleted file mode 100644 index e7e0821c0c..0000000000 --- a/smf/ntp/etc/inet/chrony.conf.internal +++ /dev/null @@ -1,32 +0,0 @@ -# -# Configuration file for an internal NTP server - one which communicates with -# boundary NTP servers within the rack. -# - -# TODO: Removeme once svc-site-ntp file is gone -# server @SERVER@ iburst minpoll 0 maxpoll 4 - -driftfile /var/lib/chrony/drift -ntsdumpdir /var/lib/chrony -dumpdir /var/lib/chrony -pidfile /var/run/chrony/chronyd.pid -logdir /var/log/chrony - -log measurements statistics tracking - -# makestep -# We allow chrony to step the system clock if we are more than a day out, -# regardless of how many clock updates have occurred since boot. -# The boundary NTP servers are configured with local reference mode, which -# means that if they start up without external connectivity, they will appear -# as authoritative servers even if they are advertising January 1987 -# (which is the default system clock on a gimlet after boot). -# This configuration allows a one-off adjustment once RSS begins and the -# boundary servers are synchronised, after which the clock will advance -# monotonically forwards. -makestep 86400 -1 - -# When a leap second occurs we slew the clock over approximately 37 seconds. -leapsecmode slew -maxslewrate 2708.333 - diff --git a/smf/ntp/etc/logadm.d/chrony.logadm.conf b/smf/ntp/etc/logadm.d/chrony.logadm.conf deleted file mode 100644 index fc335d658a..0000000000 --- a/smf/ntp/etc/logadm.d/chrony.logadm.conf +++ /dev/null @@ -1,2 +0,0 @@ -# Rotate chrony logs at 10MiB and keep 10 compressed old logs. -chrony_logs /var/log/chrony/*.log -C 10 -z 0 -s 10m -c -t '$file.$secs' diff --git a/smf/ntp/manifest/manifest.xml b/smf/ntp/manifest/manifest.xml index cc6d7abe56..6486491f03 100644 --- a/smf/ntp/manifest/manifest.xml +++ b/smf/ntp/manifest/manifest.xml @@ -63,7 +63,6 @@ regardless of whether it was linked with -zaslr --> - @@ -73,26 +72,10 @@ - - - -