Code Monkey home page Code Monkey logo

nbd's Introduction

nbd

An attempt at an NBD server in Rust.

The project is in its very early stages and is a bit of a mess. However, it is capable of doing things:

How to use?

# Clone the project
$ git clone https://github.com/bennyz/nbd.git
$ cd nbd/

# Build it
$ cargo build --release
$ ./target/release/nbd --help
nbd 0.0.1

USAGE:
    nbd [OPTIONS] <FILE> [ARGS]

ARGS:
    <FILE>           The file we want to export
    <NAME>           The name of the export, empty by default [default: ]
    <DESCRIPTION>    The description of the export, empty by default [default: ]

OPTIONS:
    -h, --help       Print help information
        --unix       Whether to use a UNIX socket (additionally) along with the TCP socket by
                     default uses /tmp/nbd.sock, in the future it will be configurable
    -V, --version    Print version information

Examples

Note: These examples rely on third-party clients, like qemu-img, projects from nbdkit (nbdinfo) and nbd-client

$ qemu-img create -f raw export-file 1G
Formatting 'export-file', fmt=raw size=1073741824 
$ ./target/release/nbd export-file myexport exporty
Listening on port 10809

On a separate shell:

$ qemu-img info nbd://localhost
image: nbd://localhost:10809
file format: raw
virtual size: 1 GiB (1073741824 bytes)
disk size: unavailable

$ nbdinfo nbd://localhost
protocol: newstyle-fixed without TLS
export="myexport":
        description: exporty
        export-size: 1073741824 (1G)
        content: data
        uri: nbd://localhost:10809/
        is_rotational: false
        is_read_only: false
        can_cache: false
        can_df: false
        can_fast_zero: false
        can_flush: false
        can_fua: false
        can_multi_conn: true
        can_trim: false
        can_zero: false
        block_size_minimum: 1
        block_size_preferred: 4096
        block_size_maximum: 33554432

We can even create a usable file system!

$ sudo modprobe nbd
$ sudo nbd-client localhost 10809 /dev/nbd0
Warning: the oldstyle protocol is no longer supported.
This method now uses the newstyle protocol with a default export
Negotiation: ..size = 1024MB
Connected /dev/nbd0

# Now our export is available via /dev/nbd0
# Let's create an XFS filesystem on it!
$ sudo mkfs.xfs /dev/nbd0
meta-data=/dev/nbd0              isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=0 inobtcount=0
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

# We can then mount it and use it!
$ sudo mount /dev/nbd0 mnt
$ touch mnt/first_file

# Close things up
$ sudo umount /dev/nbd0
$ sudo nbd-client -d /dev/nbd0

# We can then reconnect
$ sudo nbd-client localhost 10809 /dev/nbd0
Warning: the oldstyle protocol is no longer supported.
This method now uses the newstyle protocol with a default export
Negotiation: ..size = 1024MB
Connected /dev/nbd0

$ sudo mount /dev/nbd0 mnt
# The file is there!
$ ls mnt
first_file

nbd's People

Contributors

bennyz avatar

Watchers

 avatar  avatar

nbd's Issues

Support different backends

Currently the server only works with simple paths, and probably only with files on a file system. To make this more robust, the concept of a Backend needs to be introduced. For example, there will be the simple file system Backend which will expose files, a memory Backend for exposing bytes directly from memory and more. This will likely be a trait, with methods like read_at and block_status.

Support UNIX socket

Supporting UNIX socket should be fairly easy, the following snippet can be used:

    #[clap(long)]
    unix: bool,
}

fn main() {
    let args = Args::parse();
    if !Path::exists(Path::new(&args.file)) {
        panic!("{} does not exist!", args.file);
    }

    let mut export = Export {
        name: args.name,
        description: args.description,
        path: args.file,
        multiconn: true,
        ..Default::default()
    };

    export.init_export().unwrap();

    if args.unix {
        println!("Starting unix socket server");
        let server: Arc<Server<UnixStream>> = Arc::new(nbd::Server::new(export));

        let listener = UnixListener::bind("/tmp/nbd.sock").unwrap();
        for conn in listener.incoming() {
            match conn {
                Ok(stream) => {
                    let client_addr = stream.local_addr().unwrap();
                    println!("client_addr {:?}", client_addr);
                    let client = Client::new(
                        stream,
                        client_addr
                            .as_pathname()
                            .unwrap()
                            .to_str()
                            .unwrap()
                            .to_string(),
                    );
                    let clone = Arc::clone(&server);
                    thread::spawn(move || {
                        clone.handle(client).unwrap();
                    });
                }
                Err(e) => {
                    eprintln!("error: {}", e)
                }
            }
        }

Add UNIX socket examples

./target/release/nbd export-file exporty "can be accessed via UNIX socket" --unix
$ nbdinfo "nbd+unix://?socket=/tmp/nbd.sock"
protocol: newstyle-fixed without TLS
export="exporty":
        description: can be accessed via UNIX socket
        export-size: 1073741824 (1G)
        content: SGI XFS filesystem data (blksz 4096, inosz 512, v2 dirs)
        uri: nbd+unix:///?socket=/tmp/nbd.sock
        is_rotational: false
        is_read_only: false
        can_cache: false
        can_df: false
        can_fast_zero: false
        can_flush: false
        can_fua: false
        can_multi_conn: true
        can_trim: false
        can_zero: false
        block_size_minimum: 1
        block_size_preferred: 4096
        block_size_maximum: 33554432

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.