Giter Club home page Giter Club logo

nvmetcfg's Introduction

nvmetcfg - NVMe Target Configuration CLI for Linux

nvmetcfg is a tool to configure the NVMe Target (nvmet) subsystem for Linux.

  • Simple CLI commands with friendly help texts and error messages.
  • Show and configure Ports, Subsystems and Namespaces.
  • Strict checks to ensure only valid configuration gets applied.
  • Save the state in a simple yaml file and restore it later.
  • Full integration tests and unit tests ensure it functions as advertised.

Usage

nvmetcfg primarily provides the nvmet CLI tool. If you provide no arguments, you will see the main usage and subcommands:

NVMe-oF Target Configuration CLI

Usage: nvmet <COMMAND>

Commands:
  port       NVMe-oF Target Port Commands
  subsystem  NVMe-oF Target Subsystem Commands
  namespace  NVMe-oF Target Subsystem Namespace Commands
  state      NVMe-oF Target Subsystem State Management Commands
  help       Print this message or the help of the given subcommand(s)

Options:
  -h, --help  Print help

This should be familiar to anyone who has used clap-based CLIs before.

Each of the subcommands contains a usage as well. When in doubt, run help <subcommands>. Don't know what arguments to provide to port add? Run help port add.

Keep in mind that you need at least the nvmet module loaded. Given that this tool is modifying the kernel sysfs, manipulating the state requires running as root.

Alternatively, this project also provides a library for integration into other projects. In this case, consider the nvmet binary source code in src/bin/nvmet/ as the example.

TCP example

This is a simple example showing:

  • Creation of a 1G file /tmp/test.img.
  • Setup of /dev/loop0 to point to /tmp/test.img
  • Creation of a simple single-namespace subsystem nqn.2023-11.sh.tty:example-test-loop which is backed by /dev/loop0.
  • Creation of a NVMe over TCP port which binds to all IPv4 addresses on port 4420, the standard port.
  • Saving the current nvmet subsystem state, clearing it and restoring it.
# whoami
root
# modprobe nvmet 
# fallocate -l 1G /tmp/test.img
# losetup /dev/loop0 /tmp/test.img
# nvmet subsystem add nqn.2023-11.sh.tty:example-test-loop
# nvmet namespace add nqn.2023-11.sh.tty:example-test-loop 1 /dev/loop0
# nvmet subsystem show
Configured subsystems: 1
Subsystem: nqn.2023-11.sh.tty:example-test-loop
	Allow Any Host: true
	Number of Namespaces: 1
	Namespaces: 1
# nvmet namespace show nqn.2023-11.sh.tty:example-test-loop
Number of Namespaces: 1
Namespace 1:
	Enabled: true
	Device Path: /dev/loop0
	Device UUID: 75db752f-9c96-4e3b-ae08-e0feebe08138
	Device NGUID: 00000000-0000-0000-0000-000000000000
# nvmet port add 1 tcp 0.0.0.0:4420
# nvmet port add-subsystem 1 nqn.2023-11.sh.tty:example-test-loop
# nvmet port show
Configured ports: 1
Port 1:
	Type: Tcp(0.0.0.0:4420)
	Subsystems: 1
		nqn.2023-11.sh.tty:example-test-loop

# mkdir -p /etc/nvmetcfg
# nvmet state save /etc/nvmetcfg/state.yaml
Sucessfully written current state to file.
# nvmet state clear
Sucessfully cleared configuration: 2 state changes.
# nvmet state restore /etc/nvmetcfg/state.yaml
Sucessfully applied saved state: 2 state changes.
# nvmet state restore /etc/nvmetcfg/state.yaml
No changes made: System state has no changes compared to saved state.

Obviously, the show commands are not necessary for functionality, only for visual verification. If any of the commands fail, error messages will be printed.

For an example of the config file, check out examples/tcp.yaml. It should match what you'd get if running this, other than the random serial number.

Installation

NixOS

On NixOS, you can install the tool by adding github:vifino/nvmetcfg as a flake. It provides the well-known system-specific packages attribute, specifically .packages.${system}.nvmetcfg. Currently, the flake supports x86, x86_64 and aarch64 systems.

Alternatively, with NixOS or plain Nix on Linux, you can just temporarily run nvmet for testing:

modprobe nvmet
nix run github:vifino/nvmetcfg help

Of course, automatically loading the kernel modules is the way to go for actual usage:

{
  boot.kernelModules = [ "nvmet" ];
}

From Source

Just the usual lifecycle of Cargo-based Rust projects:

$ cargo build --release

Running it is simple:

$ sudo modprobe nvmet
$ sudo ./target/release/nvmet 

sudo is used here, but that's just to get the point across that you probably need to run this as root if you actually wanna modify the state.

Comparison with nvmet-cli

nvmet-cli is a Python project that has been there since the beginning. It is written by a maintainer of the kernel nvmet subsystem itself and does the job.

However, there are some things that I (vifino) disliked:

  • More or less a 1:1 mapping of config to sysfs instead of attempting to simplify redundancy.
  • Instead of being a tool you mostly use within your shell, it has it's own interactive shell.
    • This makes not just scripting harder, but also quick state inspection.. clunky.
  • The code and project structure seem suboptimal, in addition to being sparsely maintained.
  • I don't like interpreted languages running as root and touching my kernel.

This project is my attempt to create a tool that is more like the incredible nvme-cli. It reached my goal of feature parity and integrates better in my workflows.

nvmetcfg's People

Contributors

vifino avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

nvmetcfg's Issues

General Improvements

  • CI
    • Run Rust unittests
    • Test actual functionality with Nix tests
      • loop
      • tcp
      • rdma (rxe)
      • fc? fcoe? fcloop?
  • README !!! + ! ! !
    • Explain what this is, what works and why it is better than the alternatives.
    • Doesn't need to be perfect first try, but should have a decent quality.
  • Try to find reliable docs for nvmet apart from source code
  • Better error messages
    • Ideally with traces and without looking hella ugly.
  • Detailed traces with tracing
  • Show crate version and license?
  • Autoload nvmet module(s)
  • Implement delta application for State. Trait?
    • Could also have a load/store type thing that could be shared with kernel and config stores..
    • Config backends could just call the generic delta apply and always write out the whole state.
  • Check missing settings/variables
    • Check if buffered_io means normal files are supported
    • addr_treq?
    • cntlid_{min,max}?
    • pi_enable?
    • ana groups?
    • referrals?
  • State JSON flavoured in the way nvmet-cli does?
    • That contains redundant and unused data and isn't very nice. But might be worth supporting to enable an easier upgrade path?

[CI] Code Coverage

Thanks to 659af66 and 329cb4d, we have source-based instrument coverage!

You can see it tracked on codecov.
Coveralls required special stuff for multiple coverage uploads and that seemed too much of a hassle.

There are a couple of issues left until the coverage is gonna get anywhere near 100%:

I estimate we can get to 70-80% without doing anything about the issues above and just adding more test cases for the actual code.

Authentication Configuration

I read the nvme target source code again.
Turns out I was wrong about not needing host config.

Host configuration is required for authentication:

  • /hosts/<nqn>/dhchap_key
  • /hosts/<nqn>/dhchap_ctrl_key
  • /hosts/<nqn>/dhchap_hash
  • /hosts/<nqn>/dhchap_dhgroup

This might need a rethink, presumably requires tweaking the automatic allowed-hosts stuff as well.
I definitely do not want to have the config file contain hosts without encryption parameters.

Note: Needs CONFIG_NVME_TARGET_AUTH set, which isn't set by default and not explicitly on NixOS.

Encryption Configuration

If CONFIG_NVME_TARGET_TCP_TLS is set and ktls-utils is set up, we can configure encryption on a port.

This should just be /port/<pid>/treq and /port/<pid>/tsas, I think?

Subsystem Configuration

We should be able to configure subsystems as well.
This includes the associated namespaces.

  • State Gathering
  • Delta update
  • CLI commands

Configuration Save and Restore

Obviously, going through the whole effort of making an entire state representation and delta system wasn't just to waste time.

It was to accurately represent and apply configurations.

  • Serde Serialize/Deserialize
  • Configuration Save/Restore in Yaml
  • CLI commands

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.