github.com/t2y/goofys@v0.19.1-0.20190123053037-27053313e616/api/api.go (about) 1 package goofys 2 3 import ( 4 "github.com/kahing/goofys/internal" 5 6 "context" 7 "fmt" 8 "net" 9 "net/http" 10 "os" 11 "os/exec" 12 "time" 13 14 "github.com/aws/aws-sdk-go/aws" 15 "github.com/aws/aws-sdk-go/aws/credentials" 16 17 "github.com/jacobsa/fuse" 18 "github.com/jacobsa/fuse/fuseutil" 19 "github.com/jinzhu/copier" 20 "github.com/sirupsen/logrus" 21 ) 22 23 var log = GetLogger("main") 24 25 type Config struct { 26 // File system 27 MountOptions map[string]string 28 MountPoint string 29 30 Cache []string 31 DirMode os.FileMode 32 FileMode os.FileMode 33 Uid uint32 34 Gid uint32 35 36 // S3 37 Endpoint string 38 Region string 39 RegionSet bool 40 StorageClass string 41 AccessKey string 42 SecretKey string 43 Profile string 44 UseContentType bool 45 UseSSE bool 46 UseKMS bool 47 KMSKeyID string 48 ACL string 49 50 // Tuning 51 Cheap bool 52 ExplicitDir bool 53 StatCacheTTL time.Duration 54 TypeCacheTTL time.Duration 55 HTTPTimeout time.Duration 56 57 // Debugging 58 DebugFuse bool 59 DebugS3 bool 60 Foreground bool 61 } 62 63 func Mount( 64 ctx context.Context, 65 bucketName string, 66 config *Config) (fs *Goofys, mfs *fuse.MountedFileSystem, err error) { 67 68 var flags FlagStorage 69 copier.Copy(&flags, config) 70 71 awsConfig := (&aws.Config{ 72 Region: &flags.Region, 73 Logger: GetLogger("s3"), 74 //LogLevel: aws.LogLevel(aws.LogDebug), 75 }).WithHTTPClient(&http.Client{ 76 Transport: &http.Transport{ 77 Proxy: http.ProxyFromEnvironment, 78 DialContext: (&net.Dialer{ 79 Timeout: 30 * time.Second, 80 KeepAlive: 30 * time.Second, 81 DualStack: true, 82 }).DialContext, 83 MaxIdleConns: 1000, 84 MaxIdleConnsPerHost: 1000, 85 IdleConnTimeout: 90 * time.Second, 86 TLSHandshakeTimeout: 10 * time.Second, 87 ExpectContinueTimeout: 10 * time.Second, 88 }, 89 Timeout: flags.HTTPTimeout, 90 }) 91 92 if config.AccessKey != "" { 93 awsConfig.Credentials = credentials.NewStaticCredentials(config.AccessKey, config.SecretKey, "") 94 } else if len(flags.Profile) > 0 { 95 awsConfig.Credentials = credentials.NewSharedCredentials("", flags.Profile) 96 } 97 98 if len(flags.Endpoint) > 0 { 99 awsConfig.Endpoint = &flags.Endpoint 100 } 101 102 awsConfig.S3ForcePathStyle = aws.Bool(true) 103 104 fs = NewGoofys(ctx, bucketName, awsConfig, &flags) 105 if fs == nil { 106 err = fmt.Errorf("Mount: initialization failed") 107 return 108 } 109 server := fuseutil.NewFileSystemServer(fs) 110 111 fuseLog := GetLogger("fuse") 112 113 // Mount the file system. 114 mountCfg := &fuse.MountConfig{ 115 FSName: bucketName, 116 Options: flags.MountOptions, 117 ErrorLogger: GetStdLogger(NewLogger("fuse"), logrus.ErrorLevel), 118 DisableWritebackCaching: true, 119 } 120 121 if flags.DebugFuse { 122 fuseLog.Level = logrus.DebugLevel 123 log.Level = logrus.DebugLevel 124 mountCfg.DebugLogger = GetStdLogger(fuseLog, logrus.DebugLevel) 125 } 126 127 mfs, err = fuse.Mount(flags.MountPoint, server, mountCfg) 128 if err != nil { 129 err = fmt.Errorf("Mount: %v", err) 130 return 131 } 132 133 if len(flags.Cache) != 0 { 134 log.Infof("Starting catfs %v", flags.Cache) 135 catfs := exec.Command("catfs", flags.Cache...) 136 lvl := logrus.InfoLevel 137 if flags.DebugFuse { 138 lvl = logrus.DebugLevel 139 catfs.Env = append(catfs.Env, "RUST_LOG=debug") 140 } else { 141 catfs.Env = append(catfs.Env, "RUST_LOG=info") 142 } 143 catfsLog := GetLogger("catfs") 144 catfsLog.Formatter.(*LogHandle).Lvl = &lvl 145 catfs.Stderr = catfsLog.Writer() 146 err = catfs.Start() 147 if err != nil { 148 err = fmt.Errorf("Failed to start catfs: %v", err) 149 150 // sleep a bit otherwise can't unmount right away 151 time.Sleep(time.Second) 152 err2 := TryUnmount(flags.MountPoint) 153 if err2 != nil { 154 err = fmt.Errorf("%v. Failed to unmount: %v", err, err2) 155 } 156 } 157 158 go func() { 159 err := catfs.Wait() 160 log.Errorf("catfs exited: %v", err) 161 162 if err != nil { 163 // if catfs terminated cleanly, it 164 // should have unmounted this, 165 // otherwise we will do it ourselves 166 err2 := TryUnmount(flags.MountPointArg) 167 if err2 != nil { 168 log.Errorf("Failed to unmount: %v", err2) 169 } 170 } 171 172 if flags.MountPointArg != flags.MountPoint { 173 err2 := TryUnmount(flags.MountPoint) 174 if err2 != nil { 175 log.Errorf("Failed to unmount: %v", err2) 176 } 177 } 178 179 if err != nil { 180 os.Exit(1) 181 } 182 }() 183 } 184 185 return 186 } 187 188 // expose Goofys related functions and types for extending and mounting elsewhere 189 var ( 190 GetStdLogger = internal.GetStdLogger 191 InitLoggers = internal.InitLoggers 192 MassageMountFlags = internal.MassageMountFlags 193 GetLogger = internal.GetLogger 194 NewGoofys = internal.NewGoofys 195 NewLogger = internal.NewLogger 196 TryUnmount = internal.TryUnmount 197 MyUserAndGroup = internal.MyUserAndGroup 198 ) 199 200 type ( 201 Goofys = internal.Goofys 202 FlagStorage = internal.FlagStorage 203 LogHandle = internal.LogHandle 204 )