Skip to content

Commit

Permalink
feat(bin/ofs): implement fuse for linux (#4179)
Browse files Browse the repository at this point in the history
* refactor: project structure

* feat: impl fuse for linux [wip]

* feat: impl fuse for linux

* refactor: use Operator::lister in readdir

* refactor: remove frontend folder

* chore: cleanup code

* chore: make clippy happy

* Update Cargo.lock

* fix: dependencies
  • Loading branch information
ho-229 authored Feb 22, 2024
1 parent 014893e commit acb8ef6
Show file tree
Hide file tree
Showing 6 changed files with 789 additions and 261 deletions.
25 changes: 18 additions & 7 deletions bin/ofs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 9 additions & 5 deletions bin/ofs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,10 @@ rust-version = "1.67"

[dependencies]
anyhow = "1"
async-trait = "0.1.75"
clap = { version = "4.5.1", features = ["derive", "env"] }
env_logger = "0.11"
fuse3 = { "version" = "0.6.1", "features" = ["tokio-runtime", "unprivileged"] }
env_logger = "0.11.2"
futures-util = "0.3.30"
libc = "0.2.151"
log = "0.4.20"
nix = { version = "0.27.1", features = ["user"] }
opendal = { version = "0.45.0", path = "../../core" }
tokio = { version = "1.34", features = [
"fs",
Expand All @@ -47,3 +43,11 @@ tokio = { version = "1.34", features = [
"io-std",
] }
url = "2.5.0"
chrono = "0.4.34"
sharded-slab = "0.1.7"
bytes = "1.5.0"

[target.'cfg(target_os = "linux")'.dependencies]
libc = "0.2.151"
fuse3 = { "version" = "0.6.1", "features" = ["tokio-runtime", "unprivileged"] }
nix = { version = "0.27.1", features = ["user"] }
62 changes: 3 additions & 59 deletions bin/ofs/src/bin/ofs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,69 +15,13 @@
// specific language governing permissions and limitations
// under the License.

use std::collections::HashMap;
use std::str::FromStr;

use anyhow::anyhow;
use anyhow::Context;
use anyhow::Result;
use clap::Parser;
use fuse3::path::Session;
use fuse3::MountOptions;
use ofs::Ofs;
use opendal::Operator;
use opendal::Scheme;
use url::Url;

#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();
fuse().await
}

#[derive(Parser, Debug)]
#[command(version, about)]
struct Config {
/// fuse mount path
#[arg(env = "OFS_MOUNT_PATH", index = 1)]
mount_path: String,

/// location of opendal service
/// format: <scheme>://?<key>=<value>&<key>=<value>
/// example: fs://root=/tmp
#[arg(env = "OFS_BACKEND", index = 2)]
backend: String,
}

async fn fuse() -> Result<()> {
let cfg = Config::try_parse().context("parse command line arguments")?;

let location = Url::parse(&cfg.backend)?;
if location.has_host() {
Err(anyhow!("Host part in a location is not supported."))?;
}
let cfg = ofs::Config::parse();

let scheme_str = location.scheme();

let op_args = location
.query_pairs()
.into_owned()
.collect::<HashMap<String, String>>();

let scheme = Scheme::from_str(scheme_str).context("unsupported scheme")?;
let op = Operator::via_map(scheme, op_args)?;

let mut mount_option = MountOptions::default();
mount_option.uid(nix::unistd::getuid().into());
mount_option.gid(nix::unistd::getgid().into());

let ofs = Ofs { op };

let mounthandle = Session::new(mount_option)
.mount_with_unprivileged(ofs, cfg.mount_path)
.await?;

mounthandle.await?;

Ok(())
env_logger::init();
ofs::new_app(cfg).await
}
33 changes: 33 additions & 0 deletions bin/ofs/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

use clap::Parser;
use url::Url;

#[derive(Parser, Debug)]
#[command(version, about)]
pub struct Config {
/// fuse mount path
#[arg(env = "OFS_MOUNT_PATH", index = 1)]
pub(crate) mount_path: String,

/// location of opendal service
/// format: <scheme>://?<key>=<value>&<key>=<value>
/// example: fs://?root=/tmp
#[arg(env = "OFS_BACKEND", index = 2)]
pub(crate) backend: Url,
}
Loading

0 comments on commit acb8ef6

Please sign in to comment.