From 23b579fac36b19188e2a4f4c8e5268182cdaa150 Mon Sep 17 00:00:00 2001 From: Arnaldo Garcia Rincon Date: Wed, 22 Jun 2022 23:47:50 +0000 Subject: [PATCH 1/2] sources: remove unused crate servicedog Signed-off-by: Arnaldo Garcia Rincon --- packages/os/os.spec | 11 +- sources/Cargo.lock | 18 -- sources/Cargo.toml | 1 - sources/api/servicedog/Cargo.toml | 26 --- sources/api/servicedog/README.md | 20 -- sources/api/servicedog/README.tpl | 9 - sources/api/servicedog/build.rs | 3 - sources/api/servicedog/src/main.rs | 358 ----------------------------- 8 files changed, 1 insertion(+), 445 deletions(-) delete mode 100644 sources/api/servicedog/Cargo.toml delete mode 100644 sources/api/servicedog/README.md delete mode 100644 sources/api/servicedog/README.tpl delete mode 100644 sources/api/servicedog/build.rs delete mode 100644 sources/api/servicedog/src/main.rs diff --git a/packages/os/os.spec b/packages/os/os.spec index 14df13f505f..56451f91c7c 100644 --- a/packages/os/os.spec +++ b/packages/os/os.spec @@ -158,11 +158,6 @@ Summary: Dispatches Bottlerocket update commands %description -n %{_cross_os}thar-be-updates %{summary}. -%package -n %{_cross_os}servicedog -Summary: Manipulates systemd units based on setting changes -%description -n %{_cross_os}servicedog -%{summary}. - %package -n %{_cross_os}host-containers Summary: Manages system- and user-defined host containers Requires: %{_cross_os}host-ctr @@ -327,7 +322,6 @@ echo "** Output from non-static builds:" -p bork \ -p thar-be-settings \ -p thar-be-updates \ - -p servicedog \ -p host-containers \ -p storewolf \ -p settings-committer \ @@ -374,7 +368,7 @@ install -d %{buildroot}%{_cross_bindir} for p in \ apiserver \ early-boot-config netdog sundog schnauzer bork corndog \ - thar-be-settings thar-be-updates servicedog host-containers \ + thar-be-settings thar-be-updates host-containers \ storewolf settings-committer \ migrator prairiedog certdog \ signpost updog metricdog logdog \ @@ -514,9 +508,6 @@ install -p -m 0644 %{S:300} %{buildroot}%{_cross_udevrulesdir}/80-ephemeral-stor %{_cross_bindir}/thar-be-updates %{_cross_tmpfilesdir}/thar-be-updates.conf -%files -n %{_cross_os}servicedog -%{_cross_bindir}/servicedog - %files -n %{_cross_os}host-containers %{_cross_bindir}/host-containers %{_cross_unitdir}/host-containers@.service diff --git a/sources/Cargo.lock b/sources/Cargo.lock index 2d890fb50b5..12bc3dc19b6 100644 --- a/sources/Cargo.lock +++ b/sources/Cargo.lock @@ -3178,24 +3178,6 @@ dependencies = [ "serde", ] -[[package]] -name = "servicedog" -version = "0.1.0" -dependencies = [ - "apiclient", - "constants", - "datastore", - "generate-readme", - "http", - "log", - "models", - "serde", - "serde_json", - "simplelog", - "snafu", - "tokio", -] - [[package]] name = "settings-committer" version = "0.1.0" diff --git a/sources/Cargo.toml b/sources/Cargo.toml index b4a33b90b5d..1cff66788d8 100644 --- a/sources/Cargo.toml +++ b/sources/Cargo.toml @@ -13,7 +13,6 @@ members = [ "api/sundog", "api/schnauzer", "api/pluto", - "api/servicedog", "api/host-containers", "api/static-pods", "api/storewolf", diff --git a/sources/api/servicedog/Cargo.toml b/sources/api/servicedog/Cargo.toml deleted file mode 100644 index cf64819e1e0..00000000000 --- a/sources/api/servicedog/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "servicedog" -version = "0.1.0" -authors = ["Zac Mrowicki "] -license = "Apache-2.0 OR MIT" -edition = "2018" -publish = false -build = "build.rs" -# Don't rebuild crate just because of changes to README. -exclude = ["README.md"] - -[dependencies] -apiclient = { path = "../apiclient", version = "0.1.0" } -constants = { path = "../../constants", version = "0.1.0" } -datastore = { path = "../datastore", version = "0.1.0" } -http = "0.2" -log = "0.4" -models = { path = "../../models", version = "0.1.0" } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1" -simplelog = "0.12" -snafu = "0.7" -tokio = { version = "~1.14", default-features = false, features = ["macros", "rt-multi-thread"] } # LTS - -[build-dependencies] -generate-readme = { version = "0.1", path = "../../generate-readme" } diff --git a/sources/api/servicedog/README.md b/sources/api/servicedog/README.md deleted file mode 100644 index f7ad4a2094e..00000000000 --- a/sources/api/servicedog/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# servicedog - -Current version: 0.1.0 - -## Background - -servicedog is a simple systemd unit supervisor. -Its job is to start/stop and enable/disable systemd units based on a setting value it is told to query. - -When a setting changes, thar-be-settings does its job and renders configuration files and calls all restart-commands for any affected services. -For settings that represent the desire state of a service, servicedog can be included in the list of restart-commands to manipulate the state of the service based on the value of the setting. -It's provided the name of a setting to query, as well as the systemd unit to act on. -First it queries the value of the setting; the only supported values at this time are "true" and "false". -If the setting is true, servicedog attempts to start and enable the given systemd unit. If the setting is false, it stops and disables the unit. -As its very last step, service dog calls `systemd daemon-reload` to ensure all changes take affect. - - -## Colophon - -This text was generated using [cargo-readme](https://crates.io/crates/cargo-readme), and includes the rustdoc from `src/main.rs`. \ No newline at end of file diff --git a/sources/api/servicedog/README.tpl b/sources/api/servicedog/README.tpl deleted file mode 100644 index bf207d023ff..00000000000 --- a/sources/api/servicedog/README.tpl +++ /dev/null @@ -1,9 +0,0 @@ -# {{crate}} - -Current version: {{version}} - -{{readme}} - -## Colophon - -This text was generated using [cargo-readme](https://crates.io/crates/cargo-readme), and includes the rustdoc from `src/main.rs`. diff --git a/sources/api/servicedog/build.rs b/sources/api/servicedog/build.rs deleted file mode 100644 index 5b3a661c3f5..00000000000 --- a/sources/api/servicedog/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - generate_readme::from_main().unwrap(); -} diff --git a/sources/api/servicedog/src/main.rs b/sources/api/servicedog/src/main.rs deleted file mode 100644 index de727e58d17..00000000000 --- a/sources/api/servicedog/src/main.rs +++ /dev/null @@ -1,358 +0,0 @@ -/*! -# Background - -servicedog is a simple systemd unit supervisor. -Its job is to start/stop and enable/disable systemd units based on a setting value it is told to query. - -When a setting changes, thar-be-settings does its job and renders configuration files and calls all restart-commands for any affected services. -For settings that represent the desire state of a service, servicedog can be included in the list of restart-commands to manipulate the state of the service based on the value of the setting. -It's provided the name of a setting to query, as well as the systemd unit to act on. -First it queries the value of the setting; the only supported values at this time are "true" and "false". -If the setting is true, servicedog attempts to start and enable the given systemd unit. If the setting is false, it stops and disables the unit. -As its very last step, service dog calls `systemd daemon-reload` to ensure all changes take affect. - -*/ - -#![deny(rust_2018_idioms)] - -#[macro_use] -extern crate log; - -use constants; -use simplelog::{Config as LogConfig, LevelFilter, SimpleLogger}; -use snafu::{ensure, OptionExt, ResultExt}; -use std::env; -use std::ffi::OsStr; -use std::process::{self, Command}; -use std::str::FromStr; - -use datastore::serialization::to_pairs_with_prefix; -use datastore::{Key, KeyType}; - -mod error { - use http::StatusCode; - use snafu::Snafu; - use std::process::{Command, Output}; - - use datastore::{self, serialization}; - - #[derive(Debug, Snafu)] - #[snafu(visibility(pub(super)))] - pub(super) enum Error { - #[snafu(display("Error sending {} to {}: {}", method, uri, source))] - APIRequest { - method: String, - uri: String, - source: apiclient::Error, - }, - - #[snafu(display("Error {} when sending {} to {}: {}", code, method, uri, response_body))] - APIResponse { - method: String, - uri: String, - code: StatusCode, - response_body: String, - }, - - #[snafu(display( - "Error deserializing response as JSON from {} to {}: {}", - method, - uri, - source - ))] - ResponseJson { - method: &'static str, - uri: String, - source: serde_json::Error, - }, - - #[snafu(display("Error serializing settings: {} ", source))] - SerializeSettings { source: serialization::Error }, - - #[snafu(display("Unable to create key '{}': {}", key, source))] - InvalidKey { - key: String, - source: datastore::Error, - }, - - #[snafu(display( - "Unknown value for '{}': got '{}', expected 'true' or 'false'", - setting, - state - ))] - UnknownSettingState { setting: String, state: String }, - - #[snafu(display("Setting '{}' does not exist in the data store", setting))] - NonexistentSetting { setting: String }, - - #[snafu(display("Failed to execute '{:?}': {}", command, source))] - ExecutionFailure { - command: Command, - source: std::io::Error, - }, - - #[snafu(display("Systemd command failed - stderr: {}", - std::str::from_utf8(&output.stderr).unwrap_or_else(|_| "")))] - SystemdCommandFailure { output: Output }, - - #[snafu(display("Logger setup error: {}", source))] - Logger { source: log::SetLoggerError }, - } -} - -type Result = std::result::Result; - -/// SettingState represents the possible states of systemd units for Bottlerocket -enum SettingState { - Enabled, - Disabled, -} - -impl SettingState { - /// Query the datastore for a given setting and return the corresponding - /// SettingState. - async fn query(setting: S) -> Result - where - S: AsRef, - { - match query_setting_value(&setting).await?.as_ref() { - "true" => Ok(SettingState::Enabled), - "false" => Ok(SettingState::Disabled), - other => { - return error::UnknownSettingStateSnafu { - setting: setting.as_ref(), - state: other, - } - .fail() - } - } - } -} - -/// Query the datastore for a given setting and return the setting's value. -// Currently getting the value of a setting requires a few gyrations. The -// API returns a nested structure that can be deserialized to a Settings struct. -// We can then serialize this structure to a map of -// dotted.key.setting -> value. Using this map we can get the setting value. -// FIXME remove this when we have an API client. -async fn query_setting_value(key_str: S) -> Result -where - S: AsRef, -{ - let key_str = key_str.as_ref(); - let key = Key::new(KeyType::Data, key_str).context(error::InvalidKeySnafu { key: key_str })?; - debug!("Querying the API for setting: {}", key_str); - - let uri = format!("{}?keys={}", constants::API_SETTINGS_URI, key_str); - let (code, response_body) = apiclient::raw_request(constants::API_SOCKET, &uri, "GET", None) - .await - .context(error::APIRequestSnafu { - method: "GET", - uri: uri.to_string(), - })?; - ensure!( - code.is_success(), - error::APIResponseSnafu { - method: "GET", - uri, - code, - response_body, - } - ); - - // Build a Settings struct from the response string - let settings: model::Settings = serde_json::from_str(&response_body) - .context(error::ResponseJsonSnafu { method: "GET", uri })?; - - // Serialize the Settings struct into key/value pairs. This builds the dotted - // string representation of the setting - let setting_keypair = - to_pairs_with_prefix("settings", &settings).context(error::SerializeSettingsSnafu)?; - debug!("Retrieved setting keypair: {:#?}", &setting_keypair); - - // (Hopefully) get the value from the map using the dotted string supplied - // to the function - Ok(setting_keypair - .get(&key) - .context(error::NonexistentSettingSnafu { setting: key_str })? - .to_string()) -} - -/// SystemdUnit stores the systemd unit being manipulated -struct SystemdUnit { - unit: String, -} - -// FIXME: In the future we should probably look into interfacing directly -// with systemd either via dbus or Rust bindings to systemd -impl SystemdUnit { - fn new(unit: S) -> Self - where - S: AsRef, - { - SystemdUnit { - unit: unit.as_ref().to_string(), - } - } - - /// Starts the current systemd unit with the `--no-block` option - fn start_no_block(&self) -> Result<()> { - systemctl(&["start", "--no-block", &self.unit]) - } - - /// Stops the current systemd unit - fn stop(&self) -> Result<()> { - systemctl(&["stop", &self.unit]) - } - - /// Enables the current systemd unit - fn enable(&self) -> Result<()> { - systemctl(&["enable", &self.unit]) - } - - /// Disables the current systemd unit - fn disable(&self) -> Result<()> { - systemctl(&["disable", &self.unit]) - } -} - -/// Calls `systemd daemon-reload` which reloads the systemd configuration. -/// According to docs, this *shouldn't* be necessary but experience -/// has show this isn't always the case. It shouldn't hurt to call it -fn systemd_daemon_reload() -> Result<()> { - systemctl(&["daemon-reload"]) -} - -/// Wrapper around process::Command that does error handling. -fn systemctl(args: I) -> Result<()> -where - I: IntoIterator, - S: AsRef, -{ - // Instantiate command before adding args. Command::new() returns - // a `Command` whereas `.args()` returns a `&mut Command`. We use - // `Command` in our error reporting, which does not play nice with - // mutable references. - let mut command = Command::new(constants::SYSTEMCTL_BIN); - command.args(args); - let output = command - .output() - .context(error::ExecutionFailureSnafu { command })?; - - ensure!( - output.status.success(), - error::SystemdCommandFailureSnafu { output } - ); - Ok(()) -} - -/// Store the args we receive on the command line -struct Args { - log_level: LevelFilter, - setting: String, - systemd_unit: String, -} - -/// Print a usage message in the event a bad arg is passed -fn usage() -> ! { - let program_name = env::args().next().unwrap_or_else(|| "program".to_string()); - eprintln!( - r"Usage: {} - [ -s | --setting SETTING ] - [ -u | --systemd-unit UNIT ] - [ --log-level trace|debug|info|warn|error ]", - program_name - ); - process::exit(2); -} - -/// Prints a more specific message before exiting through usage(). -fn usage_msg>(msg: S) -> ! { - eprintln!("{}\n", msg.as_ref()); - usage(); -} - -/// Parse the args to the program and return an Args struct -fn parse_args(args: env::Args) -> Args { - let mut log_level = None; - let mut setting = None; - let mut systemd_unit = None; - - let mut iter = args.skip(1); - while let Some(arg) = iter.next() { - match arg.as_ref() { - "--log-level" => { - let log_level_str = iter - .next() - .unwrap_or_else(|| usage_msg("Did not give argument to --log-level")); - log_level = Some(LevelFilter::from_str(&log_level_str).unwrap_or_else(|_| { - usage_msg(format!("Invalid log level '{}'", log_level_str)) - })); - } - - "-s" | "--setting" => { - setting = Some( - iter.next() - .unwrap_or_else(|| usage_msg("Did not give argument to -s | --setting")), - ) - } - - "-u" | "--systemd-unit" => { - systemd_unit = - Some(iter.next().unwrap_or_else(|| { - usage_msg("Did not give argument to -u | --systemd-unit") - })) - } - - _ => usage(), - } - } - - Args { - log_level: log_level.unwrap_or_else(|| LevelFilter::Info), - setting: setting.unwrap_or_else(|| usage_msg("-s|--setting is a required argument")), - systemd_unit: systemd_unit - .unwrap_or_else(|| usage_msg("-u|--systemd-unit is a required argument")), - } -} - -async fn run() -> Result<()> { - // Parse and store the args passed to the program - let args = parse_args(env::args()); - - // SimpleLogger will send errors to stderr and anything less to stdout. - SimpleLogger::init(args.log_level, LogConfig::default()).context(error::LoggerSnafu)?; - - info!("servicedog started for unit {}", &args.systemd_unit); - - let systemd_unit = SystemdUnit::new(&args.systemd_unit); - - match SettingState::query(args.setting).await? { - SettingState::Enabled => { - info!("Starting and enabling unit {}", &args.systemd_unit); - systemd_daemon_reload()?; - systemd_unit.enable()?; - // Don't block on starting the unit - systemd_unit.start_no_block()?; - } - - SettingState::Disabled => { - info!("Stopping and disabling unit {}", &args.systemd_unit); - systemd_unit.stop()?; - systemd_unit.disable()?; - systemd_daemon_reload()?; - } - }; - Ok(()) -} - -// Returning a Result from main makes it print a Debug representation of the error, but with Snafu -// we have nice Display representations of the error, so we wrap "main" (run) and print any error. -// https://github.com/shepmaster/snafu/issues/110 -#[tokio::main] -async fn main() { - if let Err(e) = run().await { - eprintln!("{}", e); - process::exit(1); - } -} From 07b16ba4bf38791a9a5297b9459f2f9247c23d94 Mon Sep 17 00:00:00 2001 From: Arnaldo Garcia Rincon Date: Wed, 22 Jun 2022 23:49:19 +0000 Subject: [PATCH 2/2] sources: remove unused crate growpart Signed-off-by: Arnaldo Garcia Rincon --- GLOSSARY.md | 1 - packages/os/Cargo.toml | 1 - packages/os/os.spec | 15 -- sources/Cargo.lock | 34 ---- sources/Cargo.toml | 2 - sources/growpart/Cargo.toml | 19 --- sources/growpart/README.md | 12 -- sources/growpart/README.tpl | 9 - sources/growpart/build.rs | 3 - sources/growpart/src/diskpart.rs | 223 ------------------------- sources/growpart/src/diskpart/error.rs | 86 ---------- sources/growpart/src/main.rs | 59 ------- 12 files changed, 464 deletions(-) delete mode 100644 sources/growpart/Cargo.toml delete mode 100644 sources/growpart/README.md delete mode 100644 sources/growpart/README.tpl delete mode 100644 sources/growpart/build.rs delete mode 100644 sources/growpart/src/diskpart.rs delete mode 100644 sources/growpart/src/diskpart/error.rs delete mode 100644 sources/growpart/src/main.rs diff --git a/GLOSSARY.md b/GLOSSARY.md index 6476d601997..86b0cf7dd61 100644 --- a/GLOSSARY.md +++ b/GLOSSARY.md @@ -9,7 +9,6 @@ * **gptprio:** A structure of bits in GPT partition headers that specifies priority, tries remaining, and whether the partition booted successfully before. signpost sets these and GRUB uses them to determine which partition set to boot. * [**ghostdog**](sources/ghostdog): A program used to manage ephemeral disks. -* [**growpart**](sources/growpart): A program used to expand disk partitions upon boot. * **host containers**: Containers that run in a separate instance of containerd than "user" containers spawned by an orchestrator (e.g. Kubernetes). Used for system maintenance and connectivity. * [**host-ctr**](sources/host-ctr): The program started by `host-containers@.service` for each host container. diff --git a/packages/os/Cargo.toml b/packages/os/Cargo.toml index fc52b92aa62..bf31f077174 100644 --- a/packages/os/Cargo.toml +++ b/packages/os/Cargo.toml @@ -13,7 +13,6 @@ source-groups = [ "metricdog", "parse-datetime", "ghostdog", - "growpart", "updater", "webpki-roots-shim", "logdog", diff --git a/packages/os/os.spec b/packages/os/os.spec index 56451f91c7c..1170a9f9307 100644 --- a/packages/os/os.spec +++ b/packages/os/os.spec @@ -68,7 +68,6 @@ Requires: %{_cross_os}corndog Requires: %{_cross_os}certdog Requires: %{_cross_os}early-boot-config Requires: %{_cross_os}ghostdog -Requires: %{_cross_os}growpart Requires: %{_cross_os}host-containers Requires: %{_cross_os}logdog Requires: %{_cross_os}metricdog @@ -183,11 +182,6 @@ Summary: Tool to manage ephemeral disks %description -n %{_cross_os}ghostdog %{summary}. -%package -n %{_cross_os}growpart -Summary: Tool to grow partitions -%description -n %{_cross_os}growpart -%{summary}. - %package -n %{_cross_os}signpost Summary: Bottlerocket GPT priority querier/switcher %description -n %{_cross_os}signpost @@ -331,7 +325,6 @@ echo "** Output from non-static builds:" -p logdog \ -p metricdog \ -p ghostdog \ - -p growpart \ -p corndog \ -p bootstrap-containers \ -p prairiedog \ @@ -398,11 +391,6 @@ for p in apiclient ; do install -p -m 0755 ${HOME}/.cache/.static/%{__cargo_target_static}/release/${p} %{buildroot}%{_cross_bindir} done -install -d %{buildroot}%{_cross_sbindir} -for p in growpart ; do - install -p -m 0755 ${HOME}/.cache/%{__cargo_target}/release/${p} %{buildroot}%{_cross_sbindir} -done - install -d %{buildroot}%{_cross_datadir}/migrations for version_path in %{_builddir}/sources/api/migration/migrations/v[0-9]*; do [ -e "${version_path}" ] || continue @@ -534,9 +522,6 @@ install -p -m 0644 %{S:300} %{buildroot}%{_cross_udevrulesdir}/80-ephemeral-stor %{_cross_bindir}/ghostdog %{_cross_udevrulesdir}/80-ephemeral-storage.rules -%files -n %{_cross_os}growpart -%{_cross_sbindir}/growpart - %files -n %{_cross_os}signpost %{_cross_bindir}/signpost %{_cross_unitdir}/mark-successful-boot.service diff --git a/sources/Cargo.lock b/sources/Cargo.lock index 12bc3dc19b6..4dc4a5c7141 100644 --- a/sources/Cargo.lock +++ b/sources/Cargo.lock @@ -1508,18 +1508,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "growpart" -version = "0.1.0" -dependencies = [ - "block-party", - "generate-readme", - "gptman", - "inotify", - "libc", - "snafu", -] - [[package]] name = "h2" version = "0.3.13" @@ -1783,28 +1771,6 @@ dependencies = [ "serde", ] -[[package]] -name = "inotify" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf888f9575c290197b2c948dc9e9ff10bd1a39ad1ea8585f734585fa6b9d3f9" -dependencies = [ - "bitflags", - "futures-core", - "inotify-sys", - "libc", - "tokio", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - [[package]] name = "instant" version = "0.1.12" diff --git a/sources/Cargo.toml b/sources/Cargo.toml index 1cff66788d8..bd65be2aab1 100644 --- a/sources/Cargo.toml +++ b/sources/Cargo.toml @@ -74,8 +74,6 @@ members = [ "ghostdog", - "growpart", - "metricdog", "cfsignal", diff --git a/sources/growpart/Cargo.toml b/sources/growpart/Cargo.toml deleted file mode 100644 index 83502c6c22b..00000000000 --- a/sources/growpart/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "growpart" -version = "0.1.0" -authors = ["Ben Cressey "] -license = "Apache-2.0 OR MIT" -edition = "2018" -publish = false -# Don't rebuild crate just because of changes to README. -exclude = ["README.md"] - -[dependencies] -gptman = { version = "1", default-features = false } -snafu = "0.7" -libc = "0.2" -block-party = { path = "../updater/block-party", version = "0.1.0" } -inotify = "0.10" - -[build-dependencies] -generate-readme = { version = "0.1", path = "../generate-readme" } diff --git a/sources/growpart/README.md b/sources/growpart/README.md deleted file mode 100644 index f4d4df9fa4e..00000000000 --- a/sources/growpart/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# growpart - -Current version: 0.1.0 - -## Introduction - -growpart is a helper program to expand a partition to fill all available sectors on the -underlying block device. - -## Colophon - -This text was generated from `README.tpl` using [cargo-readme](https://crates.io/crates/cargo-readme), and includes the rustdoc from `src/main.rs`. \ No newline at end of file diff --git a/sources/growpart/README.tpl b/sources/growpart/README.tpl deleted file mode 100644 index 7b992c507f5..00000000000 --- a/sources/growpart/README.tpl +++ /dev/null @@ -1,9 +0,0 @@ -# {{crate}} - -Current version: {{version}} - -{{readme}} - -## Colophon - -This text was generated from `README.tpl` using [cargo-readme](https://crates.io/crates/cargo-readme), and includes the rustdoc from `src/main.rs`. diff --git a/sources/growpart/build.rs b/sources/growpart/build.rs deleted file mode 100644 index 5b3a661c3f5..00000000000 --- a/sources/growpart/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - generate_readme::from_main().unwrap(); -} diff --git a/sources/growpart/src/diskpart.rs b/sources/growpart/src/diskpart.rs deleted file mode 100644 index 420f0f741c8..00000000000 --- a/sources/growpart/src/diskpart.rs +++ /dev/null @@ -1,223 +0,0 @@ -/*! -This module handles the filesystem and block device interactions necessary to -load, resize, and save a partition table back to disk. -*/ - -pub(crate) mod error; -use error::Result; - -use block_party::BlockDevice; -use gptman::{GPTPartitionEntry, GPT}; -use inotify::{EventMask, Inotify, WatchMask}; -use snafu::{ensure, OptionExt, ResultExt}; -use std::fs; -use std::path::{Path, PathBuf}; - -pub struct DiskPart { - gpt: GPT, - device: PathBuf, - watcher: WatchPart, -} - -impl DiskPart { - /// Given a path to a partition, find the underlying disk and load the GPT label. - pub(crate) fn new

(path: P) -> Result - where - P: AsRef, - { - let path = path.as_ref(); - let disk = Self::find_disk(path)?; - let device = disk.path(); - let gpt = Self::load_gpt(&device)?; - println!("read partition table from {}", disk); - - let used_partitions = gpt.iter().filter(|(_num, part)| part.is_used()).count(); - ensure!( - used_partitions == 1, - error::MultiplePartitionsSnafu { - path, - count: used_partitions - } - ); - - let watcher = WatchPart::new(path)?; - - Ok(Self { - device, - gpt, - watcher, - }) - } - - /// Grow a single partition to fill the available capacity on the device. - pub(crate) fn grow(&mut self) -> Result<()> { - let gpt = &mut self.gpt; - let part = 1; - let current = &gpt[part]; - let partition_name = current.partition_name.clone(); - let partition_type_guid = current.partition_type_guid; - let unique_partition_guid = current.unique_partition_guid; - let path = &self.device; - - // Remove all existing partitions so that the space shows up as free. - gpt.remove(part) - .context(error::RemovePartitionSnafu { part, path })?; - - // First usable LBA is just after the primary label. We want partitions aligned on 1 MB - // boundaries, so the first one occurs at 2048 sectors. - let starting_lba = 2048; - - // Max size gives us the sector count between starting and ending LBA, but doesn't give - // us the last LBA, which we must solve for next. - let max_size: u64 = gpt - .get_maximum_partition_size() - .context(error::FindMaxSizeSnafu { path })?; - - // We know the first LBA, and we know the sector count, so we can calculate the last LBA. - let ending_lba = starting_lba + max_size - 1; - - gpt[part] = GPTPartitionEntry { - starting_lba, - ending_lba, - attribute_bits: 0, - partition_name, - partition_type_guid, - unique_partition_guid, - }; - - Ok(()) - } - - /// Write the GPT label back to the device. - pub(crate) fn write(&mut self) -> Result<()> { - let path = &self.device; - - let mut f = fs::OpenOptions::new() - .write(true) - .open(path) - .context(error::DeviceOpenSnafu { path })?; - - self.gpt - .header - .update_from(&mut f, self.gpt.sector_size) - .context(error::UpdateGeometrySnafu { path })?; - - self.gpt - .write_into(&mut f) - .context(error::WritePartitionTableSnafu { path })?; - - println!("wrote partition table to {}", path.display()); - - Ok(()) - } - - /// Wait for the partition symlinks to reappear. - pub(crate) fn sync(&mut self) -> Result<()> { - self.watcher.wait() - } - - /// Find the block device that holds the specified partition. - fn find_disk

(path: P) -> Result - where - P: AsRef, - { - let path = path.as_ref(); - - let partition_path = - fs::canonicalize(path).context(error::CanonicalizeLinkSnafu { path })?; - - let partition_device = BlockDevice::from_device_node(&partition_path).context( - error::FindBlockDeviceSnafu { - path: &partition_path, - }, - )?; - - let disk = partition_device - .disk() - .context(error::FindDiskSnafu { - path: &partition_path, - })? - .context(error::NotPartitionSnafu { - path: &partition_path, - })?; - - Ok(disk) - } - - /// Load the GPT disk label from the device. - fn load_gpt

(path: P) -> Result - where - P: AsRef, - { - let path = path.as_ref(); - let mut f = fs::File::open(path).context(error::DeviceOpenSnafu { path })?; - let gpt = GPT::find_from(&mut f).context(error::ReadPartitionTableSnafu { path })?; - Ok(gpt) - } -} - -struct WatchPart { - inotify: Inotify, - filename: PathBuf, -} - -impl WatchPart { - /// Given a path to a partition, set up an inotify watch that will record - /// create and delete events. - fn new

(path: P) -> Result - where - P: AsRef, - { - let path = path.as_ref(); - let dirname = path - .parent() - .context(error::FindParentDirectorySnafu { path })?; - - let filename = path - .file_name() - .context(error::FindFileNameSnafu { path })?; - let filename = Path::new(filename).to_path_buf(); - - // When the kernel reloads the partition table, we expect two events, when udev deletes and - // then recreates the path. This isn't synchronized with our code, so to avoid races we need - // to watch for both events. - let mut inotify = Inotify::init().context(error::InitInotifySnafu)?; - inotify - .add_watch(&dirname, WatchMask::CREATE | WatchMask::DELETE) - .context(error::AddInotifyWatchSnafu)?; - - Ok(WatchPart { inotify, filename }) - } - - /// Poll the inotify watch until the create and delete events are found. - fn wait(&mut self) -> Result<()> { - let mut need_create = true; - let mut need_delete = true; - let mut buf = [0; 1024]; - - while need_create || need_delete { - let events = self - .inotify - .read_events_blocking(&mut buf) - .context(error::ReadInotifyEventsSnafu)?; - - for event in events { - if let Some(event_file) = event.name { - if self.filename != Path::new(event_file) { - continue; - } - - if event.mask == EventMask::DELETE { - println!("saw {} link deleted", self.filename.display()); - need_delete = false; - } else if event.mask == EventMask::CREATE { - println!("saw {} link created", self.filename.display()); - need_create = false; - } - } - } - } - - Ok(()) - } -} diff --git a/sources/growpart/src/diskpart/error.rs b/sources/growpart/src/diskpart/error.rs deleted file mode 100644 index c46ebace870..00000000000 --- a/sources/growpart/src/diskpart/error.rs +++ /dev/null @@ -1,86 +0,0 @@ -use snafu::Snafu; - -#[derive(Debug, Snafu)] -#[snafu(visibility(pub))] -pub enum Error { - #[snafu(display("Failed to canonicalize link for '{}': {}", path.display(), source))] - CanonicalizeLink { - path: std::path::PathBuf, - source: std::io::Error, - }, - - #[snafu(display("Failed to find block device for '{}': {}", path.display(), source))] - FindBlockDevice { - path: std::path::PathBuf, - source: block_party::Error, - }, - - #[snafu(display("Failed to find disk for '{}': {}", path.display(), source))] - FindDisk { - path: std::path::PathBuf, - source: block_party::Error, - }, - - #[snafu(display("Expected partition for '{}'", path.display()))] - NotPartition { path: std::path::PathBuf }, - - #[snafu(display("Failed to open '{}': {}", path.display(), source))] - DeviceOpen { - path: std::path::PathBuf, - source: std::io::Error, - }, - - #[snafu(display("Failed to read partition table from '{}': {}", path.display(), source))] - ReadPartitionTable { - path: std::path::PathBuf, - source: gptman::Error, - }, - - #[snafu(display("Found {} partitions on '{}', can only resize with 1", count, path.display()))] - MultiplePartitions { - path: std::path::PathBuf, - count: usize, - }, - - #[snafu(display("Failed to update geometry for '{}': {}", path.display(), source))] - UpdateGeometry { - path: std::path::PathBuf, - source: gptman::Error, - }, - - #[snafu(display("Failed to write partition table to '{}': {}", path.display(), source))] - WritePartitionTable { - path: std::path::PathBuf, - source: gptman::Error, - }, - - #[snafu(display("Failed to remove partition {} from '{}': {}", part, path.display(), source))] - RemovePartition { - part: u32, - path: std::path::PathBuf, - source: gptman::Error, - }, - - #[snafu(display("Failed to find maximum partition size for '{}': {}", path.display(), source))] - FindMaxSize { - path: std::path::PathBuf, - source: gptman::Error, - }, - - #[snafu(display("Failed to initialize inotify: {}", source))] - InitInotify { source: std::io::Error }, - - #[snafu(display("Failed to add inotify watch: {}", source))] - AddInotifyWatch { source: std::io::Error }, - - #[snafu(display("Failed to read inotify events: {}", source))] - ReadInotifyEvents { source: std::io::Error }, - - #[snafu(display("Failed to find parent directory for '{}'", path.display()))] - FindParentDirectory { path: std::path::PathBuf }, - - #[snafu(display("Failed to find file name for '{}'", path.display()))] - FindFileName { path: std::path::PathBuf }, -} - -pub type Result = std::result::Result; diff --git a/sources/growpart/src/main.rs b/sources/growpart/src/main.rs deleted file mode 100644 index f8ebbd2c94e..00000000000 --- a/sources/growpart/src/main.rs +++ /dev/null @@ -1,59 +0,0 @@ -/*! -# Introduction - -growpart is a helper program to expand a partition to fill all available sectors on the -underlying block device. -*/ - -mod diskpart; -use diskpart::error::Result; -use diskpart::DiskPart; -use std::env; -use std::path::PathBuf; - -/// Stores user-supplied arguments. -#[derive(Debug)] -struct Args { - partition: PathBuf, -} - -/// Informs the user about proper usage of the program and exits. -fn usage() -> ! { - let program_name = env::args().next().unwrap_or_else(|| "program".to_string()); - eprintln!(r"Usage: {} PARTITION", program_name); - std::process::exit(2); -} - -/// Prints a more specific message before exiting through usage(). -fn usage_msg>(msg: S) -> ! { - eprintln!("{}\n", msg.as_ref()); - usage(); -} - -/// Parses user arguments into an Args structure. -fn parse_args() -> Result { - let partition = env::args() - .nth(1) - .unwrap_or_else(|| usage_msg("Did not specify partition")); - let partition = PathBuf::from(partition); - Ok(Args { partition }) -} - -fn run() -> Result<()> { - let args = parse_args()?; - let mut diskpart = DiskPart::new(args.partition)?; - diskpart.grow()?; - diskpart.write()?; - diskpart.sync()?; - Ok(()) -} - -// Returning a Result from main makes it print a Debug representation of the error, but with Snafu -// we have nice Display representations of the error, so we wrap "main" (run) and print any error. -// https://github.com/shepmaster/snafu/issues/110 -fn main() { - if let Err(e) = run() { - eprintln!("{}", e); - std::process::exit(1); - } -}