github.com/adrianjagielak/goofys@v0.24.1-0.20230810095418-94919a5d2254/api/api.go (about)

     1  package goofys
     2  
     3  import (
     4  	. "github.com/kahing/goofys/api/common"
     5  	"github.com/kahing/goofys/internal"
     6  
     7  	"context"
     8  	"fmt"
     9  	"os"
    10  	"os/exec"
    11  	"time"
    12  
    13  	"github.com/jacobsa/fuse"
    14  	"github.com/jacobsa/fuse/fuseutil"
    15  	"github.com/sirupsen/logrus"
    16  )
    17  
    18  var log = GetLogger("main")
    19  
    20  func Mount(
    21  	ctx context.Context,
    22  	bucketName string,
    23  	flags *FlagStorage) (fs *Goofys, mfs *fuse.MountedFileSystem, err error) {
    24  
    25  	if flags.DebugS3 {
    26  		SetCloudLogLevel(logrus.DebugLevel)
    27  	}
    28  
    29  	// Mount the file system.
    30  	mountCfg := &fuse.MountConfig{
    31  		FSName:                  bucketName,
    32  		Subtype:                 "goofys",
    33  		Options:                 flags.MountOptions,
    34  		ErrorLogger:             GetStdLogger(NewLogger("fuse"), logrus.ErrorLevel),
    35  		DisableWritebackCaching: true,
    36  	}
    37  
    38  	if flags.DebugFuse {
    39  		fuseLog := GetLogger("fuse")
    40  		fuseLog.Level = logrus.DebugLevel
    41  		log.Level = logrus.DebugLevel
    42  		mountCfg.DebugLogger = GetStdLogger(fuseLog, logrus.DebugLevel)
    43  	}
    44  
    45  	if flags.Backend == nil {
    46  		if spec, err := internal.ParseBucketSpec(bucketName); err == nil {
    47  			switch spec.Scheme {
    48  			case "adl":
    49  				auth, err := AzureAuthorizerConfig{
    50  					Log: GetLogger("adlv1"),
    51  				}.Authorizer()
    52  				if err != nil {
    53  					err = fmt.Errorf("couldn't load azure credentials: %v",
    54  						err)
    55  					return nil, nil, err
    56  				}
    57  				flags.Backend = &ADLv1Config{
    58  					Endpoint:   spec.Bucket,
    59  					Authorizer: auth,
    60  				}
    61  				// adlv1 doesn't really have bucket
    62  				// names, but we will rebuild the
    63  				// prefix
    64  				bucketName = ""
    65  				if spec.Prefix != "" {
    66  					bucketName = ":" + spec.Prefix
    67  				}
    68  			case "wasb":
    69  				config, err := AzureBlobConfig(flags.Endpoint, spec.Bucket, "blob")
    70  				if err != nil {
    71  					return nil, nil, err
    72  				}
    73  				flags.Backend = &config
    74  				if config.Container != "" {
    75  					bucketName = config.Container
    76  				} else {
    77  					bucketName = spec.Bucket
    78  				}
    79  				if config.Prefix != "" {
    80  					spec.Prefix = config.Prefix
    81  				}
    82  				if spec.Prefix != "" {
    83  					bucketName += ":" + spec.Prefix
    84  				}
    85  			case "abfs":
    86  				config, err := AzureBlobConfig(flags.Endpoint, spec.Bucket, "dfs")
    87  				if err != nil {
    88  					return nil, nil, err
    89  				}
    90  				flags.Backend = &config
    91  				if config.Container != "" {
    92  					bucketName = config.Container
    93  				} else {
    94  					bucketName = spec.Bucket
    95  				}
    96  				if config.Prefix != "" {
    97  					spec.Prefix = config.Prefix
    98  				}
    99  				if spec.Prefix != "" {
   100  					bucketName += ":" + spec.Prefix
   101  				}
   102  
   103  				flags.Backend = &ADLv2Config{
   104  					Endpoint:   config.Endpoint,
   105  					Authorizer: &config,
   106  				}
   107  				bucketName = spec.Bucket
   108  				if spec.Prefix != "" {
   109  					bucketName += ":" + spec.Prefix
   110  				}
   111  			case "gs":
   112  				config := NewGCSConfig()
   113  				bucketName = spec.Bucket
   114  				flags.Backend = config
   115  			}
   116  		}
   117  	}
   118  
   119  	fs = NewGoofys(ctx, bucketName, flags)
   120  	if fs == nil {
   121  		err = fmt.Errorf("Mount: initialization failed")
   122  		return
   123  	}
   124  	server := fuseutil.NewFileSystemServer(FusePanicLogger{fs})
   125  
   126  	mfs, err = fuse.Mount(flags.MountPoint, server, mountCfg)
   127  	if err != nil {
   128  		err = fmt.Errorf("Mount: %v", err)
   129  		return
   130  	}
   131  
   132  	if len(flags.Cache) != 0 {
   133  		log.Infof("Starting catfs %v", flags.Cache)
   134  		catfs := exec.Command("catfs", flags.Cache...)
   135  		lvl := logrus.InfoLevel
   136  		if flags.DebugFuse {
   137  			lvl = logrus.DebugLevel
   138  			catfs.Env = append(catfs.Env, "RUST_LOG=debug")
   139  		} else {
   140  			catfs.Env = append(catfs.Env, "RUST_LOG=info")
   141  		}
   142  		catfsLog := GetLogger("catfs")
   143  		catfsLog.Formatter.(*LogHandle).Lvl = &lvl
   144  		catfs.Stderr = catfsLog.Writer()
   145  		err = catfs.Start()
   146  		if err != nil {
   147  			err = fmt.Errorf("Failed to start catfs: %v", err)
   148  
   149  			// sleep a bit otherwise can't unmount right away
   150  			time.Sleep(time.Second)
   151  			err2 := TryUnmount(flags.MountPoint)
   152  			if err2 != nil {
   153  				err = fmt.Errorf("%v. Failed to unmount: %v", err, err2)
   154  			}
   155  		}
   156  
   157  		go func() {
   158  			err := catfs.Wait()
   159  			log.Errorf("catfs exited: %v", err)
   160  
   161  			if err != nil {
   162  				// if catfs terminated cleanly, it
   163  				// should have unmounted this,
   164  				// otherwise we will do it ourselves
   165  				err2 := TryUnmount(flags.MountPointArg)
   166  				if err2 != nil {
   167  					log.Errorf("Failed to unmount: %v", err2)
   168  				}
   169  			}
   170  
   171  			if flags.MountPointArg != flags.MountPoint {
   172  				err2 := TryUnmount(flags.MountPoint)
   173  				if err2 != nil {
   174  					log.Errorf("Failed to unmount: %v", err2)
   175  				}
   176  			}
   177  
   178  			if err != nil {
   179  				os.Exit(1)
   180  			}
   181  		}()
   182  	}
   183  
   184  	return
   185  }
   186  
   187  // expose Goofys related functions and types for extending and mounting elsewhere
   188  var (
   189  	MassageMountFlags = internal.MassageMountFlags
   190  	NewGoofys         = internal.NewGoofys
   191  	TryUnmount        = internal.TryUnmount
   192  	MyUserAndGroup    = internal.MyUserAndGroup
   193  )
   194  
   195  type (
   196  	Goofys = internal.Goofys
   197  )