Skip to content

Commit

Permalink
feat(nvmet): Unify update commands.
Browse files Browse the repository at this point in the history
No more --existing.
  • Loading branch information
vifino committed Feb 13, 2024
1 parent ce67b57 commit 58c756d
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 12 deletions.
45 changes: 44 additions & 1 deletion src/bin/nvmet/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub enum CliNamespaceCommands {
/// NVMe Qualified Name of the Subsystem.
sub: String,
},
/// Add a namespace to an existing Subsystem.
/// Add a Namespace to an existing Subsystem.
Add {
/// NVMe Qualified Name of the Subsystem.
sub: String,
Expand All @@ -43,6 +43,29 @@ pub enum CliNamespaceCommands {
#[arg(long)]
nguid: Option<Uuid>,
},
/// Update an existing Namespace of a Subsystem.
Update {
/// NVMe Qualified Name of the Subsystem.
sub: String,

/// Namespace ID of the new namespace.
nsid: u32,

/// Path to the block device.
path: PathBuf,

/// Do not enable it after creation.
#[arg(long)]
disabled: bool,

/// Optionally set the UUID.
#[arg(long)]
uuid: Option<Uuid>,

/// Optionally set the NGUID.
#[arg(long)]
nguid: Option<Uuid>,
},
/// Remove a Namespace from a Subsystem.
Remove {
/// NVMe Qualified Name of the Subsystem.
Expand Down Expand Up @@ -109,6 +132,26 @@ impl CliNamespaceCommands {
vec![SubsystemDelta::AddNamespace(nsid, new_ns)],
)])?;
}
Self::Update {
sub,
nsid,
path,
disabled,
uuid,
nguid,
} => {
assert_valid_nqn(&sub)?;
let new_ns = Namespace {
enabled: !disabled,
device_path: path,
device_uuid: uuid,
device_nguid: nguid,
};
KernelConfig::apply_delta(vec![StateDelta::UpdateSubsystem(
sub,
vec![SubsystemDelta::UpdateNamespace(nsid, new_ns)],
)])?;
}
Self::Remove { sub, nsid } => {
assert_valid_nqn(&sub)?;
KernelConfig::apply_delta(vec![StateDelta::UpdateSubsystem(
Expand Down
53 changes: 42 additions & 11 deletions src/bin/nvmet/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,31 @@ pub enum CliPortCommands {
List,
/// Create a new Port.
Add {
/// Allow reconfiguring existing Port.
#[arg(long)]
existing: bool,
/// Port ID to use.
pid: u16,

/// Type of Port.
port_type: CliPortType,

/// Port Address to use.
///
/// For Tcp and Rdma port types, this should be an IP address and Port:
/// IPv4: 1.2.3.4:4420
/// IPv6: [::1]:4420
///
/// For Fibre Channel transport, this should be the WWNN/WWPN in the following format:
/// Long: nn-0x1000000044001123:pn-0x2000000055001123
/// Short: nn-1000000044001123:pn-2000000055001123
#[arg(
verbatim_doc_comment,
required_if_eq("port_type", "tcp"),
required_if_eq("port_type", "rdma"),
required_if_eq("port_type", "fc")
)]
address: Option<String>,
},
/// Update an existing Port.
Update {
/// Port ID to use.
pid: u16,

Expand Down Expand Up @@ -101,7 +122,6 @@ impl CliPortCommands {
}
}
Self::Add {
existing,
pid,
port_type,
address,
Expand All @@ -113,14 +133,25 @@ impl CliPortCommands {
CliPortType::Fc => PortType::FibreChannel(address.unwrap().parse()?),
};

let state_delta = if existing {
vec![StateDelta::UpdatePort(
pid,
vec![PortDelta::UpdatePortType(pt)],
)]
} else {
vec![StateDelta::AddPort(pid, Port::new(pt, BTreeSet::new()))]
let state_delta = vec![StateDelta::AddPort(pid, Port::new(pt, BTreeSet::new()))];
KernelConfig::apply_delta(state_delta)?;
}
Self::Update {
pid,
port_type,
address,
} => {
let pt = match port_type {
CliPortType::Loop => PortType::Loop,
CliPortType::Tcp => PortType::Tcp(address.unwrap().parse()?),
CliPortType::Rdma => PortType::Rdma(address.unwrap().parse()?),
CliPortType::Fc => PortType::FibreChannel(address.unwrap().parse()?),
};

let state_delta = vec![StateDelta::UpdatePort(
pid,
vec![PortDelta::UpdatePortType(pt)],
)];
KernelConfig::apply_delta(state_delta)?;
}
Self::Remove { pid } => {
Expand Down
40 changes: 40 additions & 0 deletions src/bin/nvmet/subsystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,31 @@ pub enum CliSubsystemCommands {
sub: String,

/// Set the model.
#[arg(long)]
model: Option<String>,

/// Set the serial.
#[arg(long)]
serial: Option<String>,
},
/// Update an existing Subsystem.
Update {
/// NVMe Qualified Name of the Subsystem.
/// This should follow the supported formats in the NVMe specification.
///
/// Examples:
///
/// - nqn.2014-08.com.example:nvme.host.sys.xyz
///
/// - nqn.2014-08.org.nvmexpress:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6
sub: String,

/// Set the model.
#[arg(long)]
model: Option<String>,

/// Set the serial.
#[arg(long)]
serial: Option<String>,
},
/// Remove an existing Subsystem.
Expand Down Expand Up @@ -102,6 +124,24 @@ impl CliSubsystemCommands {
},
)])?;
}
Self::Update { sub, model, serial } => {
assert_compliant_nqn(&sub)?;
let mut sub_delta = Vec::with_capacity(1);

if let Some(model) = model {
sub_delta.push(SubsystemDelta::UpdateModel(model));
}

if let Some(serial) = serial {
sub_delta.push(SubsystemDelta::UpdateSerial(serial));
}

if sub_delta.is_empty() {
return Err(Error::UpdateNoChanges.into());
} else {
KernelConfig::apply_delta(vec![StateDelta::UpdateSubsystem(sub, sub_delta)])?
}
}
Self::Remove { sub } => {
assert_valid_nqn(&sub)?;
KernelConfig::apply_delta(vec![StateDelta::RemoveSubsystem(sub)])?;
Expand Down
2 changes: 2 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub enum Error {
ExistingNamespace(u32, String),
#[error("Invalid UUID")]
InvalidUuid(#[from] uuid::Error),
#[error("Requested update, but specified no changes")]
UpdateNoChanges,
#[error("Unsupported config version: {0}")]
UnsupportedConfigVersion(u32),
}
4 changes: 4 additions & 0 deletions tests/loop.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,29 @@
# Create our subsystems.
node.succeed("nvmet subsystem add ${subnqn}")
node.succeed("nvmet subsystem update ${subnqn} --model Loop --serial 1337")
assert "${subnqn}" in node.succeed("nvmet subsystem list")
node.succeed("test -d /sys/kernel/config/nvmet/subsystems/${subnqn}")
node.succeed("nvmet subsystem show")
node.succeed("nvmet namespace add ${subnqn} 1 /dev/loop0")
node.succeed("nvmet namespace update ${subnqn} 1 /dev/loop0")
assert "1" in node.succeed("nvmet namespace list ${subnqn}")
node.succeed("test -d /sys/kernel/config/nvmet/subsystems/${subnqn}/namespaces/1")
assert "/dev/loop0" in node.succeed("cat /sys/kernel/config/nvmet/subsystems/${subnqn}/namespaces/1/device_path")
node.succeed("nvmet namespace show ${subnqn}")
# Create the loopback port.
node.succeed("nvmet port add 1 loop")
node.succeed("nvmet port update 1 loop")
assert "1" in node.succeed("nvmet port list")
node.succeed("test -d /sys/kernel/config/nvmet/ports/1")
assert "loop" in node.succeed("cat /sys/kernel/config/nvmet/ports/1/addr_trtype")
node.succeed("nvmet port add-subsystem 1 ${subnqn}")
assert "${subnqn}" in node.succeed("nvmet port list-subsystems 1")
node.succeed("test -h /sys/kernel/config/nvmet/ports/1/subsystems/${subnqn}")
node.fail("nvmet port list-subsystems 69")
node.succeed("nvmet port show")
assert "${subnqn}" in machine.succeed("nvme discover -t loop")
Expand Down
5 changes: 5 additions & 0 deletions tests/rdma.nix
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
# Create our subsystems.
target.succeed("nvmet subsystem add ${subnqn}")
target.succeed("nvmet subsystem update ${subnqn} --model RDMA --serial 1337")
assert "${subnqn}" in target.succeed("nvmet subsystem list")
target.succeed("test -d /sys/kernel/config/nvmet/subsystems/${subnqn}")
Expand All @@ -64,13 +65,16 @@
target.succeed("nvmet subsystem show")
target.succeed("nvmet namespace add ${subnqn} 1 /dev/loop0")
target.succeed("nvmet namespace update ${subnqn} 1 /dev/loop0")
assert "1" in target.succeed("nvmet namespace list ${subnqn}")
target.succeed("test -d /sys/kernel/config/nvmet/subsystems/${subnqn}/namespaces/1")
assert "/dev/loop0" in target.succeed("cat /sys/kernel/config/nvmet/subsystems/${subnqn}/namespaces/1/device_path")
target.succeed("nvmet namespace show ${subnqn}")
# Create the tcp port.
target.succeed("nvmet port add 1 rdma 0.0.0.0:4420")
target.succeed("nvmet port update 1 loop")
target.succeed("nvmet port update 1 rdma 0.0.0.0:4420")
assert "1" in target.succeed("nvmet port list")
target.succeed("test -d /sys/kernel/config/nvmet/ports/1")
assert "rdma" in target.succeed("cat /sys/kernel/config/nvmet/ports/1/addr_trtype")
Expand All @@ -81,6 +85,7 @@
target.succeed("nvmet port add-subsystem 1 ${subnqn}")
assert "${subnqn}" in target.succeed("nvmet port list-subsystems 1")
target.succeed("test -h /sys/kernel/config/nvmet/ports/1/subsystems/${subnqn}")
target.fail("nvmet port list-subsystems 69")
target.succeed("nvmet port show")
# State save/restore test.
Expand Down
5 changes: 5 additions & 0 deletions tests/tcp.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
# Create our subsystems.
target.succeed("nvmet subsystem add ${subnqn}")
target.succeed("nvmet subsystem update ${subnqn} --model TCP --serial 1337")
assert "${subnqn}" in target.succeed("nvmet subsystem list")
target.succeed("test -d /sys/kernel/config/nvmet/subsystems/${subnqn}")
Expand All @@ -59,13 +60,16 @@
target.succeed("nvmet subsystem show")
target.succeed("nvmet namespace add ${subnqn} 1 /dev/loop0")
target.succeed("nvmet namespace update ${subnqn} 1 /dev/loop0")
assert "1" in target.succeed("nvmet namespace list ${subnqn}")
target.succeed("test -d /sys/kernel/config/nvmet/subsystems/${subnqn}/namespaces/1")
assert "/dev/loop0" in target.succeed("cat /sys/kernel/config/nvmet/subsystems/${subnqn}/namespaces/1/device_path")
target.succeed("nvmet namespace show ${subnqn}")
# Create the tcp port.
target.succeed("nvmet port add 1 tcp 0.0.0.0:4420")
target.succeed("nvmet port update 1 loop")
target.succeed("nvmet port update 1 tcp 0.0.0.0:4420")
assert "1" in target.succeed("nvmet port list")
target.succeed("test -d /sys/kernel/config/nvmet/ports/1")
assert "tcp" in target.succeed("cat /sys/kernel/config/nvmet/ports/1/addr_trtype")
Expand All @@ -76,6 +80,7 @@
target.succeed("nvmet port add-subsystem 1 ${subnqn}")
assert "${subnqn}" in target.succeed("nvmet port list-subsystems 1")
target.succeed("test -h /sys/kernel/config/nvmet/ports/1/subsystems/${subnqn}")
target.fail("nvmet port list-subsystems 69")
target.succeed("nvmet port show")
# State save/restore test.
Expand Down

0 comments on commit 58c756d

Please sign in to comment.