moby--moby/vendor/github.com/Microsoft/opengcs/client/vhdtotar.go

70 lines
2.6 KiB
Go
Raw Permalink Normal View History

// +build windows
package client
import (
"fmt"
"io"
"os"
"github.com/sirupsen/logrus"
)
// VhdToTar does what is says - it exports a VHD in a specified
// folder (either a read-only layer.vhd, or a read-write sandbox.vhd) to a
// ReadCloser containing a tar-stream of the layers contents.
func (config *Config) VhdToTar(vhdFile string, uvmMountPath string, isSandbox bool, vhdSize int64) (io.ReadCloser, error) {
logrus.Debugf("opengcs: VhdToTar: %s isSandbox: %t", vhdFile, isSandbox)
if config.Uvm == nil {
return nil, fmt.Errorf("cannot VhdToTar as no utility VM is in configuration")
}
defer config.DebugGCS()
vhdHandle, err := os.Open(vhdFile)
if err != nil {
return nil, fmt.Errorf("opengcs: VhdToTar: failed to open %s: %s", vhdFile, err)
}
defer vhdHandle.Close()
logrus.Debugf("opengcs: VhdToTar: exporting %s, size %d, isSandbox %t", vhdHandle.Name(), vhdSize, isSandbox)
// Different binary depending on whether a RO layer or a RW sandbox
command := "vhd2tar"
if isSandbox {
command = fmt.Sprintf("exportSandbox -path %s", uvmMountPath)
}
// Start the binary in the utility VM
process, err := config.createUtilsProcess(command)
if err != nil {
return nil, fmt.Errorf("opengcs: VhdToTar: %s: failed to create utils process %s: %s", vhdHandle.Name(), command, err)
}
if !isSandbox {
// Send the VHD contents to the utility VM processes stdin handle if not a sandbox
logrus.Debugf("opengcs: VhdToTar: copying the layer VHD into the utility VM")
if _, err = copyWithTimeout(process.Stdin, vhdHandle, vhdSize, config.UvmTimeoutSeconds, fmt.Sprintf("vhdtotarstream: sending %s to %s", vhdHandle.Name(), command)); err != nil {
process.Process.Close()
return nil, fmt.Errorf("opengcs: VhdToTar: %s: failed to copyWithTimeout on the stdin pipe (to utility VM): %s", vhdHandle.Name(), err)
}
}
// Start a goroutine which copies the stdout (ie the tar stream)
reader, writer := io.Pipe()
go func() {
defer writer.Close()
defer process.Process.Close()
logrus.Debugf("opengcs: VhdToTar: copying tar stream back from the utility VM")
bytes, err := copyWithTimeout(writer, process.Stdout, vhdSize, config.UvmTimeoutSeconds, fmt.Sprintf("vhdtotarstream: copy tarstream from %s", command))
if err != nil {
logrus.Errorf("opengcs: VhdToTar: %s: copyWithTimeout on the stdout pipe (from utility VM) failed: %s", vhdHandle.Name(), err)
}
logrus.Debugf("opengcs: VhdToTar: copied %d bytes of the tarstream of %s from the utility VM", bytes, vhdHandle.Name())
}()
// Return the read-side of the pipe connected to the goroutine which is reading from the stdout of the process in the utility VM
return reader, nil
}