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.

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