github.com/pachyderm/pachyderm@v1.13.4/src/server/pfs/cmds/mount_unix.go (about) 1 // +build !windows 2 3 package cmds 4 5 import ( 6 "bufio" 7 "bytes" 8 "fmt" 9 "os" 10 "strings" 11 "syscall" 12 13 "github.com/pachyderm/pachyderm/src/client" 14 "github.com/pachyderm/pachyderm/src/client/pkg/errors" 15 "github.com/pachyderm/pachyderm/src/server/pfs/fuse" 16 "github.com/pachyderm/pachyderm/src/server/pkg/cmdutil" 17 18 "github.com/hanwen/go-fuse/v2/fs" 19 gofuse "github.com/hanwen/go-fuse/v2/fuse" 20 "github.com/spf13/cobra" 21 ) 22 23 const ( 24 name = "pfs" 25 ) 26 27 func parseRepoOpts(args []string) (map[string]*fuse.RepoOptions, error) { 28 result := make(map[string]*fuse.RepoOptions) 29 for _, arg := range args { 30 var repo string 31 var flag string 32 opts := &fuse.RepoOptions{} 33 repoAndRest := strings.Split(arg, "@") 34 if len(repoAndRest) == 1 { 35 // No branch specified 36 opts.Branch = "master" 37 repoAndFlag := strings.Split(repoAndRest[0], "+") 38 repo = repoAndFlag[0] 39 if len(repoAndFlag) > 1 { 40 flag = repoAndFlag[1] 41 } 42 } else { 43 repo = repoAndRest[0] 44 branchAndFlag := strings.Split(repoAndRest[1], "+") 45 opts.Branch = branchAndFlag[0] 46 if len(branchAndFlag) > 1 { 47 flag = branchAndFlag[1] 48 } 49 } 50 if flag != "" { 51 for _, c := range flag { 52 if c != 'w' && c != 'r' { 53 return nil, errors.Errorf("invalid format %q: unrecognized mode: %q", arg, c) 54 } 55 } 56 if strings.Contains("w", flag) { 57 opts.Write = true 58 } 59 } 60 if repo == "" { 61 return nil, errors.Errorf("invalid format %q: repo cannot be empty", arg) 62 } 63 result[repo] = opts 64 } 65 return result, nil 66 } 67 68 func mountCmds() []*cobra.Command { 69 var commands []*cobra.Command 70 71 var write bool 72 var debug bool 73 var repoOpts cmdutil.RepeatedStringArg 74 mount := &cobra.Command{ 75 Use: "{{alias}} <path/to/mount/point>", 76 Short: "Mount pfs locally. This command blocks.", 77 Long: "Mount pfs locally. This command blocks.", 78 Run: cmdutil.RunFixedArgs(1, func(args []string) error { 79 c, err := client.NewOnUserMachine("fuse") 80 if err != nil { 81 return err 82 } 83 defer c.Close() 84 mountPoint := args[0] 85 repoOpts, err := parseRepoOpts(repoOpts) 86 if err != nil { 87 return err 88 } 89 opts := &fuse.Options{ 90 Write: write, 91 Fuse: &fs.Options{ 92 MountOptions: gofuse.MountOptions{ 93 Debug: debug, 94 FsName: name, 95 Name: name, 96 }, 97 }, 98 RepoOptions: repoOpts, 99 } 100 // Prints a warning if we're on macOS 101 printWarning() 102 return fuse.Mount(c, mountPoint, opts) 103 }), 104 } 105 mount.Flags().BoolVarP(&write, "write", "w", false, "Allow writing to pfs through the mount.") 106 mount.Flags().BoolVarP(&debug, "debug", "d", false, "Turn on debug messages.") 107 mount.Flags().VarP(&repoOpts, "repos", "r", "Repos and branches / commits to mount, arguments should be of the form \"repo@branch+w\", where the trailing flag \"+w\" indicates write.") 108 mount.MarkFlagCustom("repos", "__pachctl_get_repo_branch") 109 commands = append(commands, cmdutil.CreateAlias(mount, "mount")) 110 111 var all bool 112 unmount := &cobra.Command{ 113 Use: "{{alias}} <path/to/mount/point>", 114 Short: "Unmount pfs.", 115 Long: "Unmount pfs.", 116 Run: cmdutil.RunBoundedArgs(0, 1, func(args []string) error { 117 if len(args) == 1 { 118 return syscall.Unmount(args[0], 0) 119 } 120 if all { 121 stdin := strings.NewReader(fmt.Sprintf(` 122 mount | grep fuse.%s | cut -f 3 -d " " 123 `, name)) 124 var stdout bytes.Buffer 125 if err := cmdutil.RunIO(cmdutil.IO{ 126 Stdin: stdin, 127 Stdout: &stdout, 128 Stderr: os.Stderr, 129 }, "sh"); err != nil { 130 return err 131 } 132 scanner := bufio.NewScanner(&stdout) 133 var mounts []string 134 for scanner.Scan() { 135 mounts = append(mounts, scanner.Text()) 136 } 137 if len(mounts) == 0 { 138 fmt.Println("No mounts found.") 139 return nil 140 } 141 fmt.Printf("This will unmount the following filesystems:\n") 142 for _, mount := range mounts { 143 fmt.Printf("%s\n", mount) 144 } 145 146 if ok, err := cmdutil.InteractiveConfirm(); err != nil { 147 return err 148 } else if !ok { 149 return errors.New("deploy aborted") 150 } 151 152 for _, mount := range mounts { 153 if err := syscall.Unmount(mount, 0); err != nil { 154 return err 155 } 156 } 157 } else { 158 return errors.Errorf("nothing to unmount specify a mounted filesystem or --all") 159 } 160 return nil 161 }), 162 } 163 unmount.Flags().BoolVarP(&all, "all", "a", false, "unmount all pfs mounts") 164 commands = append(commands, cmdutil.CreateAlias(unmount, "unmount")) 165 166 return commands 167 }