Implement NFS Support stub (Phase 11 P0 #3)
NFS Support Features:
- nfs_server.rs: NFSv3 server stub
- nfs_server CLI tool: Port 2049, export directory
- nfsserve crate dependency (v0.11.0)
Implementation Status:
- NfsVfsServer: Placeholder implementation
- NfsConfig: Configuration struct
- CLI: nfs-server command with --port, --root, --share-name
Technical Details:
- nfsserve crate provides NFSFileSystem trait
- NFSFileSystem requires 14 async methods
- Current implementation is stub (pending API study)
Build: ✅ markbase-core + nfs feature
Tests: 495 markbase-core (without nfs feature)
Note: Full NFS server implementation requires studying nfsserve crate API
(expected time: 2-3 days for 500 lines)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -3048,6 +3048,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"lz4_flex 0.11.6",
|
"lz4_flex 0.11.6",
|
||||||
"md5 0.8.0",
|
"md5 0.8.0",
|
||||||
|
"nfsserve",
|
||||||
"nix 0.29.0",
|
"nix 0.29.0",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"poly1305 0.8.0",
|
"poly1305 0.8.0",
|
||||||
|
|||||||
BIN
data/auth.sqlite
BIN
data/auth.sqlite
Binary file not shown.
@@ -89,12 +89,16 @@ tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
|||||||
# === LDAP Authentication (Phase 2) ===
|
# === LDAP Authentication (Phase 2) ===
|
||||||
ldap3 = { version = "0.11", optional = true } # Async LDAP client (compatible with AD + OpenLDAP)
|
ldap3 = { version = "0.11", optional = true } # Async LDAP client (compatible with AD + OpenLDAP)
|
||||||
|
|
||||||
|
# === NFS Server (Phase 11) ===
|
||||||
|
nfsserve = { version = "0.11", optional = true } # NFSv3/NFSv4 server implementation
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [] # 默认不启用可选格式
|
default = [] # 默认不启用可选格式
|
||||||
optional-formats = ["unrar", "xz2", "sevenz-rust"] # 争议格式可选启用
|
optional-formats = ["unrar", "xz2", "sevenz-rust"] # 争议格式可选启用
|
||||||
smb-server = ["dep:smb-server"] # SMB server feature flag
|
smb-server = ["dep:smb-server"] # SMB server feature flag
|
||||||
async-vfs = ["dep:reqwest"] # Async VfsBackend trait + native async S3
|
async-vfs = ["dep:reqwest"] # Async VfsBackend trait + native async S3
|
||||||
ldap = ["dep:ldap3"] # LDAP authentication provider
|
ldap = ["dep:ldap3"] # LDAP authentication provider
|
||||||
|
nfs = ["dep:nfsserve"] # NFSv3/NFSv4 server feature flag
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# tempfile moved to dependencies (needed for archive extraction)
|
# tempfile moved to dependencies (needed for archive extraction)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod smb_server;
|
pub mod smb_server;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
#[cfg(feature = "nfs")]
|
||||||
|
pub mod nfs_server;
|
||||||
|
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
|
|
||||||
@@ -12,6 +14,8 @@ pub enum ToolsCommands {
|
|||||||
Test(test::TestCommand),
|
Test(test::TestCommand),
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
SmbServer(smb_server::SmbServerCommand),
|
SmbServer(smb_server::SmbServerCommand),
|
||||||
|
#[cfg(feature = "nfs")]
|
||||||
|
Nfs(nfs_server::NfsServerCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_tools_command(cmd: ToolsCommands) -> anyhow::Result<()> {
|
pub async fn handle_tools_command(cmd: ToolsCommands) -> anyhow::Result<()> {
|
||||||
@@ -19,6 +23,8 @@ pub async fn handle_tools_command(cmd: ToolsCommands) -> anyhow::Result<()> {
|
|||||||
ToolsCommands::Render(c) => render::handle_render_command(c)?,
|
ToolsCommands::Render(c) => render::handle_render_command(c)?,
|
||||||
ToolsCommands::Test(c) => test::handle_test_command(c)?,
|
ToolsCommands::Test(c) => test::handle_test_command(c)?,
|
||||||
ToolsCommands::SmbServer(c) => smb_server::handle_smb_server_command(c).await?,
|
ToolsCommands::SmbServer(c) => smb_server::handle_smb_server_command(c).await?,
|
||||||
|
#[cfg(feature = "nfs")]
|
||||||
|
ToolsCommands::Nfs(c) => nfs_server::run_nfs_server(c).await?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
41
markbase-core/src/cli/tools/nfs_server.rs
Normal file
41
markbase-core/src/cli/tools/nfs_server.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use clap::Args;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::vfs::{local_fs::LocalFs, nfs_server::{NfsVfsServer, NfsConfig}};
|
||||||
|
|
||||||
|
#[derive(Debug, Args)]
|
||||||
|
pub struct NfsServerCommand {
|
||||||
|
/// Port to listen on (default: 2049)
|
||||||
|
#[arg(short, long, default_value = "2049")]
|
||||||
|
port: u16,
|
||||||
|
|
||||||
|
/// Root directory to export
|
||||||
|
#[arg(short, long, default_value = "/tmp/nfs_export")]
|
||||||
|
root: PathBuf,
|
||||||
|
|
||||||
|
/// Share name (export name)
|
||||||
|
#[arg(short, long, default_value = "export")]
|
||||||
|
share_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_nfs_server(cmd: NfsServerCommand) -> anyhow::Result<()> {
|
||||||
|
println!("Starting NFS server on port {}", cmd.port);
|
||||||
|
println!("Export directory: {}", cmd.root.display());
|
||||||
|
println!("Share name: {}", cmd.share_name);
|
||||||
|
|
||||||
|
if !cmd.root.exists() {
|
||||||
|
std::fs::create_dir_all(&cmd.root)?;
|
||||||
|
println!("Created export directory: {}", cmd.root.display());
|
||||||
|
}
|
||||||
|
|
||||||
|
let vfs = Arc::new(LocalFs::new());
|
||||||
|
let server = NfsVfsServer::new(vfs, cmd.root.clone()).with_port(cmd.port);
|
||||||
|
|
||||||
|
println!("NFS server starting...");
|
||||||
|
server.start(cmd.port).await?;
|
||||||
|
|
||||||
|
println!("NFS server stopped");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -24,6 +24,8 @@ pub mod async_fs;
|
|||||||
pub mod async_s3_fs;
|
pub mod async_s3_fs;
|
||||||
#[cfg(feature = "async-vfs")]
|
#[cfg(feature = "async-vfs")]
|
||||||
pub mod async_smb_fs;
|
pub mod async_smb_fs;
|
||||||
|
#[cfg(feature = "nfs")]
|
||||||
|
pub mod nfs_server;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|||||||
63
markbase-core/src/vfs/nfs_server.rs
Normal file
63
markbase-core/src/vfs/nfs_server.rs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
use crate::vfs::{VfsBackend, VfsError};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct NfsVfsServer {
|
||||||
|
vfs: Arc<dyn VfsBackend>,
|
||||||
|
root: PathBuf,
|
||||||
|
port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NfsVfsServer {
|
||||||
|
pub fn new(vfs: Arc<dyn VfsBackend>, root: PathBuf) -> Self {
|
||||||
|
Self {
|
||||||
|
vfs,
|
||||||
|
root,
|
||||||
|
port: 2049,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_port(self, port: u16) -> Self {
|
||||||
|
Self { port, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start(&self, port: u16) -> Result<(), VfsError> {
|
||||||
|
#[cfg(feature = "nfs")]
|
||||||
|
{
|
||||||
|
println!("NFS server starting on port {}", port);
|
||||||
|
println!("Export directory: {}", self.root.display());
|
||||||
|
|
||||||
|
// TODO: Implement actual NFS server using nfsserve crate
|
||||||
|
// Current implementation is a placeholder
|
||||||
|
|
||||||
|
Err(VfsError::Unsupported("NFS server implementation pending (requires nfsserve crate API study)".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "nfs"))]
|
||||||
|
{
|
||||||
|
Err(VfsError::Unsupported("NFS server requires 'nfs' feature".to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NfsConfig {
|
||||||
|
pub port: u16,
|
||||||
|
pub root: PathBuf,
|
||||||
|
pub vfs: Arc<dyn VfsBackend>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NfsConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
port: 2049,
|
||||||
|
root: PathBuf::from("/"),
|
||||||
|
vfs: Arc::new(crate::vfs::local_fs::LocalFs::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NfsConfig {
|
||||||
|
pub fn build(&self) -> NfsVfsServer {
|
||||||
|
NfsVfsServer::new(self.vfs.clone(), self.root.clone()).with_port(self.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user