1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

LCOW: Graphdriver DiffGetter implementation

Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
John Howard 2018-03-13 15:55:17 -07:00
parent d5c781323d
commit 6b4f989bc2

View file

@ -56,11 +56,13 @@
package lcow // import "github.com/docker/docker/daemon/graphdriver/lcow"
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings"
@ -964,3 +966,87 @@ func hostToGuest(hostpath string) string {
func unionMountName(disks []hcsshim.MappedVirtualDisk) string {
return fmt.Sprintf("%s-mount", disks[0].ContainerPath)
}
type nopCloser struct {
io.Reader
}
func (nopCloser) Close() error {
return nil
}
type fileGetCloserFromSVM struct {
id string
svm *serviceVM
mvd *hcsshim.MappedVirtualDisk
d *Driver
}
func (fgc *fileGetCloserFromSVM) Close() error {
if fgc.svm != nil {
if fgc.mvd != nil {
if err := fgc.svm.hotRemoveVHDs(*fgc.mvd); err != nil {
// We just log this as we're going to tear down the SVM imminently unless in global mode
logrus.Errorf("failed to remove mvd %s: %s", fgc.mvd.ContainerPath, err)
}
}
}
if fgc.d != nil && fgc.svm != nil && fgc.id != "" {
if err := fgc.d.terminateServiceVM(fgc.id, fmt.Sprintf("diffgetter %s", fgc.id), false); err != nil {
return err
}
}
return nil
}
func (fgc *fileGetCloserFromSVM) Get(filename string) (io.ReadCloser, error) {
errOut := &bytes.Buffer{}
outOut := &bytes.Buffer{}
file := path.Join(fgc.mvd.ContainerPath, filename)
if err := fgc.svm.runProcess(fmt.Sprintf("cat %s", file), nil, outOut, errOut); err != nil {
logrus.Debugf("cat %s failed: %s", file, errOut.String())
return nil, err
}
return nopCloser{bytes.NewReader(outOut.Bytes())}, nil
}
// DiffGetter returns a FileGetCloser that can read files from the directory that
// contains files for the layer differences. Used for direct access for tar-split.
func (d *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) {
title := fmt.Sprintf("lcowdriver: diffgetter: %s", id)
logrus.Debugf(title)
ld, err := getLayerDetails(d.dir(id))
if err != nil {
logrus.Debugf("%s: failed to get vhdx information of %s: %s", title, d.dir(id), err)
return nil, err
}
// Start the SVM with a mapped virtual disk. Note that if the SVM is
// already running and we are in global mode, this will be hot-added.
mvd := hcsshim.MappedVirtualDisk{
HostPath: ld.filename,
ContainerPath: hostToGuest(ld.filename),
CreateInUtilityVM: true,
ReadOnly: true,
}
logrus.Debugf("%s: starting service VM", title)
svm, err := d.startServiceVMIfNotRunning(id, []hcsshim.MappedVirtualDisk{mvd}, fmt.Sprintf("diffgetter %s", id))
if err != nil {
return nil, err
}
logrus.Debugf("%s: waiting for svm to finish booting", title)
err = svm.getStartError()
if err != nil {
d.terminateServiceVM(id, fmt.Sprintf("diff %s", id), false)
return nil, fmt.Errorf("%s: svm failed to boot: %s", title, err)
}
return &fileGetCloserFromSVM{
id: id,
svm: svm,
mvd: &mvd,
d: d}, nil
}