Implement resizing of zpool
This commit is contained in:
parent
f410517ffa
commit
f0725c503f
10 changed files with 234 additions and 17 deletions
13
rust/program/disko-zpool-expand/Cargo.toml
Normal file
13
rust/program/disko-zpool-expand/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "disko-zpool-expand"
|
||||
edition = "2024"
|
||||
version = "1.0.0"
|
||||
metadata.crane.name = "disko-zpool-expand"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
common = { path = "../../lib/common" }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
hakari = { version = "0.1", path = "../../lib/hakari" }
|
117
rust/program/disko-zpool-expand/src/main.rs
Normal file
117
rust/program/disko-zpool-expand/src/main.rs
Normal file
|
@ -0,0 +1,117 @@
|
|||
use serde::Deserialize;
|
||||
use std::{collections::BTreeMap, path::PathBuf};
|
||||
|
||||
use anyhow::Context as _;
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
fn main() {
|
||||
common::entrypoint(program);
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
#[command(subcommand)]
|
||||
pub command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum Commands {
|
||||
/// Expands the partitions based on a zpool and brings the pool up to the new size.
|
||||
#[command(name = "expand-zpool")]
|
||||
ExpandZpool(ExpandZpool),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, clap::Args)]
|
||||
pub struct ExpandZpool {
|
||||
/// Name of the pool to expand
|
||||
pool_name: String,
|
||||
}
|
||||
|
||||
fn program() -> anyhow::Result<()> {
|
||||
let args = Args::parse();
|
||||
match args.command {
|
||||
Commands::ExpandZpool(pool) => expand_zpool(pool),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ZpoolStatus {
|
||||
pools: BTreeMap<String, ZpoolStatusPool>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ZpoolStatusPool {
|
||||
state: Option<ZpoolState>,
|
||||
vdevs: BTreeMap<String, ZpoolStatusVdev>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Deserialize, PartialEq)]
|
||||
enum ZpoolState {
|
||||
#[serde(rename = "ONLINE")]
|
||||
Online,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ZpoolStatusVdev {
|
||||
vdevs: BTreeMap<String, ZpoolStatusVdevVdev>,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct ZpoolStatusVdevVdev {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
fn expand_zpool(p: ExpandZpool) -> anyhow::Result<()> {
|
||||
let mut proc = common::proc::Command::new("zpool");
|
||||
proc.args(["status", "--json", &p.pool_name]);
|
||||
let result: ZpoolStatus = proc
|
||||
.try_spawn_to_json()
|
||||
.context("Could not get zpool status")?;
|
||||
|
||||
let pool = result
|
||||
.pools
|
||||
.get(&p.pool_name)
|
||||
.context("Could not find requested pool in status output")?;
|
||||
|
||||
if !pool
|
||||
.state
|
||||
.as_ref()
|
||||
.is_some_and(|st| *st == ZpoolState::Online)
|
||||
{
|
||||
return Err(anyhow::format_err!("Zpool {} is not online", p.pool_name));
|
||||
}
|
||||
|
||||
for vdev in pool.vdevs.values() {
|
||||
for vdev in vdev.vdevs.values() {
|
||||
let partition_dev = vdev.path.display().to_string();
|
||||
let Some(dev) = partition_dev.strip_suffix("-part1") else {
|
||||
return Err(anyhow::format_err!(
|
||||
"Expected vdev path {} to end with -part1",
|
||||
vdev.path.display()
|
||||
));
|
||||
};
|
||||
let mut proc = common::proc::Command::new("growpart");
|
||||
proc.args([dev, "1"]);
|
||||
let (stdout, _stderr, status) = proc.spawn_into_parts()?;
|
||||
if !status.success() && !stdout.starts_with("NOCHANGE: ") {
|
||||
return Err(anyhow::format_err!(
|
||||
"Could not resize partitin for {}, err: {stdout}",
|
||||
vdev.path.display()
|
||||
));
|
||||
}
|
||||
// let name = partition_dev
|
||||
// .split("/")
|
||||
// .last()
|
||||
// .expect("Should always have at least one element");
|
||||
let mut proc = common::proc::Command::new("zpool");
|
||||
proc.args(["online", "-e", &p.pool_name, &partition_dev]);
|
||||
proc.try_spawn_to_string().with_context(|| {
|
||||
format!(
|
||||
"Could not bring zpool {} online with expand flag",
|
||||
p.pool_name
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue