mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2025-09-19 23:27:56 +08:00
add weedfuse
This commit is contained in:
@@ -4,9 +4,6 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrislusf/seaweedfs/weed/security"
|
|
||||||
"github.com/chrislusf/seaweedfs/weed/server"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
@@ -15,6 +12,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/security"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/server"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/chrislusf/seaweedfs/weed/filesys"
|
"github.com/chrislusf/seaweedfs/weed/filesys"
|
||||||
"github.com/chrislusf/seaweedfs/weed/glog"
|
"github.com/chrislusf/seaweedfs/weed/glog"
|
||||||
"github.com/chrislusf/seaweedfs/weed/util"
|
"github.com/chrislusf/seaweedfs/weed/util"
|
||||||
@@ -24,40 +25,63 @@ import (
|
|||||||
|
|
||||||
func runMount(cmd *Command, args []string) bool {
|
func runMount(cmd *Command, args []string) bool {
|
||||||
|
|
||||||
|
util.SetupProfiling(*mountCpuProfile, *mountMemProfile)
|
||||||
|
|
||||||
|
return RunMount(
|
||||||
|
*mountOptions.filer,
|
||||||
|
*mountOptions.filerMountRootPath,
|
||||||
|
*mountOptions.dir,
|
||||||
|
*mountOptions.collection,
|
||||||
|
*mountOptions.replication,
|
||||||
|
*mountOptions.dataCenter,
|
||||||
|
*mountOptions.chunkSizeLimitMB,
|
||||||
|
*mountOptions.allowOthers,
|
||||||
|
*mountOptions.ttlSec,
|
||||||
|
*mountOptions.dirListingLimit,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunMount(filer, filerMountRootPath, dir, collection, replication, dataCenter string, chunkSizeLimitMB int,
|
||||||
|
allowOthers bool, ttlSec int, dirListingLimit int) bool {
|
||||||
|
|
||||||
weed_server.LoadConfiguration("security", false)
|
weed_server.LoadConfiguration("security", false)
|
||||||
|
|
||||||
fmt.Printf("This is SeaweedFS version %s %s %s\n", util.VERSION, runtime.GOOS, runtime.GOARCH)
|
fmt.Printf("This is SeaweedFS version %s %s %s\n", util.VERSION, runtime.GOOS, runtime.GOARCH)
|
||||||
if *mountOptions.dir == "" {
|
if dir == "" {
|
||||||
fmt.Printf("Please specify the mount directory via \"-dir\"")
|
fmt.Printf("Please specify the mount directory via \"-dir\"")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if *mountOptions.chunkSizeLimitMB <= 0 {
|
if chunkSizeLimitMB <= 0 {
|
||||||
fmt.Printf("Please specify a reasonable buffer size.")
|
fmt.Printf("Please specify a reasonable buffer size.")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fuse.Unmount(*mountOptions.dir)
|
fuse.Unmount(dir)
|
||||||
|
|
||||||
|
uid, gid := uint32(0), uint32(0)
|
||||||
|
|
||||||
// detect mount folder mode
|
// detect mount folder mode
|
||||||
mountMode := os.ModeDir | 0755
|
mountMode := os.ModeDir | 0755
|
||||||
if fileInfo, err := os.Stat(*mountOptions.dir); err == nil {
|
fileInfo, err := os.Stat(dir)
|
||||||
|
if err == nil {
|
||||||
mountMode = os.ModeDir | fileInfo.Mode()
|
mountMode = os.ModeDir | fileInfo.Mode()
|
||||||
|
uid, gid = util.GetFileUidGid(fileInfo)
|
||||||
|
fmt.Printf("mount point owner uid=%d gid=%d mode=%s\n", uid, gid, fileInfo.Mode())
|
||||||
}
|
}
|
||||||
|
|
||||||
mountName := path.Base(*mountOptions.dir)
|
if uid == 0 {
|
||||||
|
if u, err := user.Current(); err == nil {
|
||||||
// detect current user
|
if parsedId, pe := strconv.ParseUint(u.Uid, 10, 32); pe == nil {
|
||||||
uid, gid := uint32(0), uint32(0)
|
uid = uint32(parsedId)
|
||||||
if u, err := user.Current(); err == nil {
|
}
|
||||||
if parsedId, pe := strconv.ParseUint(u.Uid, 10, 32); pe == nil {
|
if parsedId, pe := strconv.ParseUint(u.Gid, 10, 32); pe == nil {
|
||||||
uid = uint32(parsedId)
|
gid = uint32(parsedId)
|
||||||
}
|
}
|
||||||
if parsedId, pe := strconv.ParseUint(u.Gid, 10, 32); pe == nil {
|
fmt.Printf("current uid=%d gid=%d\n", uid, gid)
|
||||||
gid = uint32(parsedId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
util.SetupProfiling(*mountCpuProfile, *mountMemProfile)
|
mountName := path.Base(dir)
|
||||||
|
|
||||||
options := []fuse.MountOption{
|
options := []fuse.MountOption{
|
||||||
fuse.VolumeName(mountName),
|
fuse.VolumeName(mountName),
|
||||||
@@ -76,28 +100,28 @@ func runMount(cmd *Command, args []string) bool {
|
|||||||
fuse.WritebackCache(),
|
fuse.WritebackCache(),
|
||||||
fuse.AllowNonEmptyMount(),
|
fuse.AllowNonEmptyMount(),
|
||||||
}
|
}
|
||||||
if *mountOptions.allowOthers {
|
if allowOthers {
|
||||||
options = append(options, fuse.AllowOther())
|
options = append(options, fuse.AllowOther())
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := fuse.Mount(*mountOptions.dir, options...)
|
c, err := fuse.Mount(dir, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
util.OnInterrupt(func() {
|
util.OnInterrupt(func() {
|
||||||
fuse.Unmount(*mountOptions.dir)
|
fuse.Unmount(dir)
|
||||||
c.Close()
|
c.Close()
|
||||||
})
|
})
|
||||||
|
|
||||||
filerGrpcAddress, err := parseFilerGrpcAddress(*mountOptions.filer)
|
filerGrpcAddress, err := parseFilerGrpcAddress(filer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
mountRoot := *mountOptions.filerMountRootPath
|
mountRoot := filerMountRootPath
|
||||||
if mountRoot != "/" && strings.HasSuffix(mountRoot, "/") {
|
if mountRoot != "/" && strings.HasSuffix(mountRoot, "/") {
|
||||||
mountRoot = mountRoot[0 : len(mountRoot)-1]
|
mountRoot = mountRoot[0 : len(mountRoot)-1]
|
||||||
}
|
}
|
||||||
@@ -106,19 +130,21 @@ func runMount(cmd *Command, args []string) bool {
|
|||||||
FilerGrpcAddress: filerGrpcAddress,
|
FilerGrpcAddress: filerGrpcAddress,
|
||||||
GrpcDialOption: security.LoadClientTLS(viper.Sub("grpc"), "client"),
|
GrpcDialOption: security.LoadClientTLS(viper.Sub("grpc"), "client"),
|
||||||
FilerMountRootPath: mountRoot,
|
FilerMountRootPath: mountRoot,
|
||||||
Collection: *mountOptions.collection,
|
Collection: collection,
|
||||||
Replication: *mountOptions.replication,
|
Replication: replication,
|
||||||
TtlSec: int32(*mountOptions.ttlSec),
|
TtlSec: int32(ttlSec),
|
||||||
ChunkSizeLimit: int64(*mountOptions.chunkSizeLimitMB) * 1024 * 1024,
|
ChunkSizeLimit: int64(chunkSizeLimitMB) * 1024 * 1024,
|
||||||
DataCenter: *mountOptions.dataCenter,
|
DataCenter: dataCenter,
|
||||||
DirListingLimit: *mountOptions.dirListingLimit,
|
DirListingLimit: dirListingLimit,
|
||||||
EntryCacheTtl: 3 * time.Second,
|
EntryCacheTtl: 3 * time.Second,
|
||||||
MountUid: uid,
|
MountUid: uid,
|
||||||
MountGid: gid,
|
MountGid: gid,
|
||||||
MountMode: mountMode,
|
MountMode: mountMode,
|
||||||
|
MountCtime: fileInfo.ModTime(),
|
||||||
|
MountMtime: time.Now(),
|
||||||
}))
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fuse.Unmount(*mountOptions.dir)
|
fuse.Unmount(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the mount process has an error to report
|
// check if the mount process has an error to report
|
||||||
|
49
weed/command/weedfuse/weedfuse.go
Normal file
49
weed/command/weedfuse/weedfuse.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/command"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
options = flag.String("o", "", "comma separated options rw,uid=xxx,gid=xxx")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
device := flag.Arg(0)
|
||||||
|
mountPoint := flag.Arg(1)
|
||||||
|
|
||||||
|
fmt.Printf("source: %v\n", device)
|
||||||
|
fmt.Printf("target: %v\n", mountPoint)
|
||||||
|
|
||||||
|
maybeSetupPath()
|
||||||
|
|
||||||
|
parts := strings.SplitN(device, "/", 2)
|
||||||
|
filer, filerPath := parts[0], parts[1]
|
||||||
|
|
||||||
|
command.RunMount(
|
||||||
|
filer, "/"+filerPath, mountPoint, "", "000", "",
|
||||||
|
4, true, 0, 1000000)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func maybeSetupPath() {
|
||||||
|
// sudo mount -av may not include PATH in some linux, e.g., Ubuntu
|
||||||
|
hasPathEnv := false
|
||||||
|
for _, e := range os.Environ() {
|
||||||
|
if strings.HasPrefix(e, "PATH=") {
|
||||||
|
hasPathEnv = true
|
||||||
|
}
|
||||||
|
fmt.Println(e)
|
||||||
|
}
|
||||||
|
if !hasPathEnv {
|
||||||
|
os.Setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
|
||||||
|
}
|
||||||
|
}
|
@@ -34,9 +34,7 @@ func (dir *Dir) Attr(ctx context.Context, attr *fuse.Attr) error {
|
|||||||
attr.Valid = time.Second
|
attr.Valid = time.Second
|
||||||
|
|
||||||
if dir.Path == dir.wfs.option.FilerMountRootPath {
|
if dir.Path == dir.wfs.option.FilerMountRootPath {
|
||||||
attr.Uid = dir.wfs.option.MountUid
|
dir.setRootDirAttributes(attr)
|
||||||
attr.Gid = dir.wfs.option.MountGid
|
|
||||||
attr.Mode = dir.wfs.option.MountMode
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +70,16 @@ func (dir *Dir) Attr(ctx context.Context, attr *fuse.Attr) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dir *Dir) setRootDirAttributes(attr *fuse.Attr) {
|
||||||
|
attr.Uid = dir.wfs.option.MountUid
|
||||||
|
attr.Gid = dir.wfs.option.MountGid
|
||||||
|
attr.Mode = dir.wfs.option.MountMode
|
||||||
|
attr.Crtime = dir.wfs.option.MountCtime
|
||||||
|
attr.Ctime = dir.wfs.option.MountCtime
|
||||||
|
attr.Mtime = dir.wfs.option.MountMtime
|
||||||
|
attr.Atime = dir.wfs.option.MountMtime
|
||||||
|
}
|
||||||
|
|
||||||
func (dir *Dir) newFile(name string, entry *filer_pb.Entry) *File {
|
func (dir *Dir) newFile(name string, entry *filer_pb.Entry) *File {
|
||||||
return &File{
|
return &File{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@@ -32,6 +32,8 @@ type Option struct {
|
|||||||
MountUid uint32
|
MountUid uint32
|
||||||
MountGid uint32
|
MountGid uint32
|
||||||
MountMode os.FileMode
|
MountMode os.FileMode
|
||||||
|
MountCtime time.Time
|
||||||
|
MountMtime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = fs.FS(&WFS{})
|
var _ = fs.FS(&WFS{})
|
||||||
|
Reference in New Issue
Block a user