You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
6.1 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package command
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/chrislusf/seaweedfs/weed/glog"
  6. "github.com/chrislusf/seaweedfs/weed/mount"
  7. "github.com/chrislusf/seaweedfs/weed/mount/meta_cache"
  8. "github.com/chrislusf/seaweedfs/weed/mount/unmount"
  9. "github.com/chrislusf/seaweedfs/weed/pb"
  10. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  11. "github.com/chrislusf/seaweedfs/weed/security"
  12. "github.com/chrislusf/seaweedfs/weed/storage/types"
  13. "github.com/hanwen/go-fuse/v2/fuse"
  14. "net/http"
  15. "os"
  16. "os/user"
  17. "runtime"
  18. "strconv"
  19. "strings"
  20. "time"
  21. "github.com/chrislusf/seaweedfs/weed/util"
  22. "github.com/chrislusf/seaweedfs/weed/util/grace"
  23. )
  24. func runMount2(cmd *Command, args []string) bool {
  25. if *mountOptions.debug {
  26. go http.ListenAndServe(fmt.Sprintf(":%d", *mountOptions.debugPort), nil)
  27. }
  28. grace.SetupProfiling(*mountCpuProfile, *mountMemProfile)
  29. if *mountReadRetryTime < time.Second {
  30. *mountReadRetryTime = time.Second
  31. }
  32. util.RetryWaitTime = *mountReadRetryTime
  33. umask, umaskErr := strconv.ParseUint(*mountOptions.umaskString, 8, 64)
  34. if umaskErr != nil {
  35. fmt.Printf("can not parse umask %s", *mountOptions.umaskString)
  36. return false
  37. }
  38. if len(args) > 0 {
  39. return false
  40. }
  41. return RunMount2(&mount2Options, os.FileMode(umask))
  42. }
  43. func RunMount2(option *Mount2Options, umask os.FileMode) bool {
  44. // basic checks
  45. chunkSizeLimitMB := *mountOptions.chunkSizeLimitMB
  46. if chunkSizeLimitMB <= 0 {
  47. fmt.Printf("Please specify a reasonable buffer size.")
  48. return false
  49. }
  50. // try to connect to filer
  51. filerAddresses := pb.ServerAddresses(*option.filer).ToAddresses()
  52. util.LoadConfiguration("security", false)
  53. grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
  54. var cipher bool
  55. var err error
  56. for i := 0; i < 10; i++ {
  57. err = pb.WithOneOfGrpcFilerClients(false, filerAddresses, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  58. resp, err := client.GetFilerConfiguration(context.Background(), &filer_pb.GetFilerConfigurationRequest{})
  59. if err != nil {
  60. return fmt.Errorf("get filer grpc address %v configuration: %v", filerAddresses, err)
  61. }
  62. cipher = resp.Cipher
  63. return nil
  64. })
  65. if err != nil {
  66. glog.V(0).Infof("failed to talk to filer %v: %v", filerAddresses, err)
  67. glog.V(0).Infof("wait for %d seconds ...", i+1)
  68. time.Sleep(time.Duration(i+1) * time.Second)
  69. }
  70. }
  71. if err != nil {
  72. glog.Errorf("failed to talk to filer %v: %v", filerAddresses, err)
  73. return true
  74. }
  75. filerMountRootPath := *option.filerMountRootPath
  76. // clean up mount point
  77. dir := util.ResolvePath(*option.dir)
  78. if dir == "" {
  79. fmt.Printf("Please specify the mount directory via \"-dir\"")
  80. return false
  81. }
  82. unmount.Unmount(dir)
  83. // detect mount folder mode
  84. if *option.dirAutoCreate {
  85. os.MkdirAll(dir, os.FileMode(0777)&^umask)
  86. }
  87. fileInfo, err := os.Stat(dir)
  88. // collect uid, gid
  89. uid, gid := uint32(0), uint32(0)
  90. mountMode := os.ModeDir | 0777
  91. if err == nil {
  92. mountMode = os.ModeDir | os.FileMode(0777)&^umask
  93. uid, gid = util.GetFileUidGid(fileInfo)
  94. fmt.Printf("mount point owner uid=%d gid=%d mode=%s\n", uid, gid, mountMode)
  95. } else {
  96. fmt.Printf("can not stat %s\n", dir)
  97. return false
  98. }
  99. // detect uid, gid
  100. if uid == 0 {
  101. if u, err := user.Current(); err == nil {
  102. if parsedId, pe := strconv.ParseUint(u.Uid, 10, 32); pe == nil {
  103. uid = uint32(parsedId)
  104. }
  105. if parsedId, pe := strconv.ParseUint(u.Gid, 10, 32); pe == nil {
  106. gid = uint32(parsedId)
  107. }
  108. fmt.Printf("current uid=%d gid=%d\n", uid, gid)
  109. }
  110. }
  111. // mapping uid, gid
  112. uidGidMapper, err := meta_cache.NewUidGidMapper(*option.uidMap, *option.gidMap)
  113. if err != nil {
  114. fmt.Printf("failed to parse %s %s: %v\n", *option.uidMap, *option.gidMap, err)
  115. return false
  116. }
  117. // Ensure target mount point availability
  118. if isValid := checkMountPointAvailable(dir); !isValid {
  119. glog.Fatalf("Expected mount to still be active, target mount point: %s, please check!", dir)
  120. return true
  121. }
  122. // mount fuse
  123. fuseMountOptions := &fuse.MountOptions{
  124. AllowOther: *option.allowOthers,
  125. Options: nil,
  126. MaxBackground: 128,
  127. MaxWrite: 1024 * 1024 * 2,
  128. MaxReadAhead: 1024 * 1024 * 2,
  129. IgnoreSecurityLabels: false,
  130. RememberInodes: false,
  131. FsName: *option.filer + ":" + filerMountRootPath,
  132. Name: "seaweedfs",
  133. SingleThreaded: false,
  134. DisableXAttrs: false,
  135. Debug: true,
  136. EnableLocks: false,
  137. ExplicitDataCacheControl: false,
  138. // SyncRead: false, // set to false to enable the FUSE_CAP_ASYNC_READ capability
  139. DirectMount: true,
  140. DirectMountFlags: 0,
  141. // EnableAcl: false,
  142. }
  143. // find mount point
  144. mountRoot := filerMountRootPath
  145. if mountRoot != "/" && strings.HasSuffix(mountRoot, "/") {
  146. mountRoot = mountRoot[0 : len(mountRoot)-1]
  147. }
  148. seaweedFileSystem := mount.NewSeaweedFileSystem(&mount.Option{
  149. MountDirectory: dir,
  150. FilerAddresses: filerAddresses,
  151. GrpcDialOption: grpcDialOption,
  152. FilerMountRootPath: mountRoot,
  153. Collection: *option.collection,
  154. Replication: *option.replication,
  155. TtlSec: int32(*option.ttlSec),
  156. DiskType: types.ToDiskType(*option.diskType),
  157. ChunkSizeLimit: int64(chunkSizeLimitMB) * 1024 * 1024,
  158. ConcurrentWriters: *option.concurrentWriters,
  159. CacheDir: *option.cacheDir,
  160. CacheSizeMB: *option.cacheSizeMB,
  161. DataCenter: *option.dataCenter,
  162. MountUid: uid,
  163. MountGid: gid,
  164. MountMode: mountMode,
  165. MountCtime: fileInfo.ModTime(),
  166. MountMtime: time.Now(),
  167. Umask: umask,
  168. VolumeServerAccess: *mountOptions.volumeServerAccess,
  169. Cipher: cipher,
  170. UidGidMapper: uidGidMapper,
  171. })
  172. server, err := fuse.NewServer(seaweedFileSystem, dir, fuseMountOptions)
  173. if err != nil {
  174. glog.Fatalf("Mount fail: %v", err)
  175. }
  176. grace.OnInterrupt(func() {
  177. unmount.Unmount(dir)
  178. })
  179. seaweedFileSystem.StartBackgroundTasks()
  180. fmt.Printf("This is SeaweedFS version %s %s %s\n", util.Version(), runtime.GOOS, runtime.GOARCH)
  181. server.Serve()
  182. return true
  183. }