github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/daemon/graphdriver/lcow/remotefs.go (about) 1 // +build windows 2 3 package lcow // import "github.com/demonoid81/moby/daemon/graphdriver/lcow" 4 5 import ( 6 "bytes" 7 "fmt" 8 "io" 9 "runtime" 10 "strings" 11 "sync" 12 13 "github.com/Microsoft/hcsshim" 14 "github.com/Microsoft/opengcs/service/gcsutils/remotefs" 15 "github.com/demonoid81/moby/pkg/archive" 16 "github.com/demonoid81/moby/pkg/containerfs" 17 "github.com/sirupsen/logrus" 18 ) 19 20 type lcowfs struct { 21 root string 22 d *Driver 23 mappedDisks []hcsshim.MappedVirtualDisk 24 vmID string 25 currentSVM *serviceVM 26 sync.Mutex 27 } 28 29 var _ containerfs.ContainerFS = &lcowfs{} 30 31 // ErrNotSupported is an error for unsupported operations in the remotefs 32 var ErrNotSupported = fmt.Errorf("not supported") 33 34 // Functions to implement the ContainerFS interface 35 func (l *lcowfs) Path() string { 36 return l.root 37 } 38 39 func (l *lcowfs) ResolveScopedPath(path string, rawPath bool) (string, error) { 40 logrus.Debugf("remotefs.resolvescopedpath inputs: %s %s ", path, l.root) 41 42 arg1 := l.Join(l.root, path) 43 if !rawPath { 44 // The l.Join("/", path) will make path an absolute path and then clean it 45 // so if path = ../../X, it will become /X. 46 arg1 = l.Join(l.root, l.Join("/", path)) 47 } 48 arg2 := l.root 49 50 output := &bytes.Buffer{} 51 if err := l.runRemoteFSProcess(nil, output, remotefs.ResolvePathCmd, arg1, arg2); err != nil { 52 return "", err 53 } 54 55 logrus.Debugf("remotefs.resolvescopedpath success. Output: %s\n", output.String()) 56 return output.String(), nil 57 } 58 59 func (l *lcowfs) OS() string { 60 return "linux" 61 } 62 63 func (l *lcowfs) Architecture() string { 64 return runtime.GOARCH 65 } 66 67 // Other functions that are used by docker like the daemon Archiver/Extractor 68 func (l *lcowfs) ExtractArchive(src io.Reader, dst string, opts *archive.TarOptions) error { 69 logrus.Debugf("remotefs.ExtractArchve inputs: %s %+v", dst, opts) 70 71 tarBuf := &bytes.Buffer{} 72 if err := remotefs.WriteTarOptions(tarBuf, opts); err != nil { 73 return fmt.Errorf("failed to marshall tar opts: %s", err) 74 } 75 76 input := io.MultiReader(tarBuf, src) 77 if err := l.runRemoteFSProcess(input, nil, remotefs.ExtractArchiveCmd, dst); err != nil { 78 return fmt.Errorf("failed to extract archive to %s: %s", dst, err) 79 } 80 return nil 81 } 82 83 func (l *lcowfs) ArchivePath(src string, opts *archive.TarOptions) (io.ReadCloser, error) { 84 logrus.Debugf("remotefs.ArchivePath: %s %+v", src, opts) 85 86 tarBuf := &bytes.Buffer{} 87 if err := remotefs.WriteTarOptions(tarBuf, opts); err != nil { 88 return nil, fmt.Errorf("failed to marshall tar opts: %s", err) 89 } 90 91 r, w := io.Pipe() 92 go func() { 93 defer w.Close() 94 if err := l.runRemoteFSProcess(tarBuf, w, remotefs.ArchivePathCmd, src); err != nil { 95 logrus.Debugf("REMOTEFS: Failed to extract archive: %s %+v %s", src, opts, err) 96 } 97 }() 98 return r, nil 99 } 100 101 // Helper functions 102 func (l *lcowfs) startVM() error { 103 l.Lock() 104 defer l.Unlock() 105 if l.currentSVM != nil { 106 return nil 107 } 108 109 svm, err := l.d.startServiceVMIfNotRunning(l.vmID, l.mappedDisks, fmt.Sprintf("lcowfs.startVM")) 110 if err != nil { 111 return err 112 } 113 114 if err = svm.createUnionMount(l.root, l.mappedDisks...); err != nil { 115 return err 116 } 117 l.currentSVM = svm 118 return nil 119 } 120 121 func (l *lcowfs) runRemoteFSProcess(stdin io.Reader, stdout io.Writer, args ...string) error { 122 if err := l.startVM(); err != nil { 123 return err 124 } 125 126 // Append remotefs prefix and setup as a command line string 127 cmd := fmt.Sprintf("%s %s", remotefs.RemotefsCmd, strings.Join(args, " ")) 128 stderr := &bytes.Buffer{} 129 if err := l.currentSVM.runProcess(cmd, stdin, stdout, stderr); err != nil { 130 return err 131 } 132 133 eerr, err := remotefs.ReadError(stderr) 134 if eerr != nil { 135 // Process returned an error so return that. 136 return remotefs.ExportedToError(eerr) 137 } 138 return err 139 }