mirror of
https://github.com/containers/podman.git
synced 2025-08-02 17:22:30 +08:00
Introduce Windows WSL implementation of podman machine
[NO NEW TESTS NEEDED] for now Signed-off-by: Jason Greene <jason.greene@redhat.com>
This commit is contained in:

committed by
Jason T. Greene

parent
73a54ea54d
commit
803defbe50
@ -1,8 +1,9 @@
|
||||
// +build amd64,!windows arm64,!windows
|
||||
// +build amd64 arm64
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -17,6 +18,7 @@ import (
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/ulikunitz/xz"
|
||||
"github.com/vbauerster/mpb/v6"
|
||||
"github.com/vbauerster/mpb/v6/decor"
|
||||
)
|
||||
@ -43,7 +45,7 @@ func NewGenericDownloader(vmType, vmName, pullPath string) (DistributionDownload
|
||||
return nil, err
|
||||
}
|
||||
if len(getURL.Scheme) > 0 {
|
||||
urlSplit := strings.Split(pullPath, "/")
|
||||
urlSplit := strings.Split(getURL.Path, "/")
|
||||
imageName = urlSplit[len(urlSplit)-1]
|
||||
dl.LocalUncompressedFile = filepath.Join(dataDir, imageName)
|
||||
dl.URL = getURL
|
||||
@ -63,39 +65,48 @@ func NewGenericDownloader(vmType, vmName, pullPath string) (DistributionDownload
|
||||
return gd, nil
|
||||
}
|
||||
|
||||
func (g GenericDownload) getLocalUncompressedName() string {
|
||||
func (d Download) getLocalUncompressedName() string {
|
||||
var (
|
||||
extension string
|
||||
)
|
||||
switch {
|
||||
case strings.HasSuffix(g.LocalPath, ".bz2"):
|
||||
case strings.HasSuffix(d.LocalPath, ".bz2"):
|
||||
extension = ".bz2"
|
||||
case strings.HasSuffix(g.LocalPath, ".gz"):
|
||||
case strings.HasSuffix(d.LocalPath, ".gz"):
|
||||
extension = ".gz"
|
||||
case strings.HasSuffix(g.LocalPath, ".xz"):
|
||||
case strings.HasSuffix(d.LocalPath, ".xz"):
|
||||
extension = ".xz"
|
||||
}
|
||||
uncompressedFilename := filepath.Join(filepath.Dir(g.LocalUncompressedFile), g.VMName+"_"+g.ImageName)
|
||||
uncompressedFilename := filepath.Join(filepath.Dir(d.LocalPath), d.VMName+"_"+d.ImageName)
|
||||
return strings.TrimSuffix(uncompressedFilename, extension)
|
||||
}
|
||||
|
||||
func (g GenericDownload) DownloadImage() error {
|
||||
// If we have a URL for this "downloader", we now pull it
|
||||
if g.URL != nil {
|
||||
if err := DownloadVMImage(g.URL, g.LocalPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return Decompress(g.LocalPath, g.getLocalUncompressedName())
|
||||
}
|
||||
|
||||
func (g GenericDownload) Get() *Download {
|
||||
return &g.Download
|
||||
}
|
||||
|
||||
func (g GenericDownload) HasUsableCache() (bool, error) {
|
||||
// If we have a URL for this "downloader", we now pull it
|
||||
return g.URL == nil, nil
|
||||
}
|
||||
|
||||
func DownloadImage(d DistributionDownload) error {
|
||||
// check if the latest image is already present
|
||||
ok, err := d.HasUsableCache()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
if err := DownloadVMImage(d.Get().URL, d.Get().LocalPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return Decompress(d.Get().LocalPath, d.Get().getLocalUncompressedName())
|
||||
}
|
||||
|
||||
// DownloadVMImage downloads a VM image from url to given path
|
||||
// with download status
|
||||
func DownloadVMImage(downloadURL fmt.Stringer, localImagePath string) error {
|
||||
func DownloadVMImage(downloadURL *url2.URL, localImagePath string) error {
|
||||
out, err := os.Create(localImagePath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -120,7 +131,7 @@ func DownloadVMImage(downloadURL fmt.Stringer, localImagePath string) error {
|
||||
return fmt.Errorf("error downloading VM image %s: %s", downloadURL, resp.Status)
|
||||
}
|
||||
size := resp.ContentLength
|
||||
urlSplit := strings.Split(downloadURL.String(), "/")
|
||||
urlSplit := strings.Split(downloadURL.Path, "/")
|
||||
prefix := "Downloading VM image: " + urlSplit[len(urlSplit)-1]
|
||||
onComplete := prefix + ": done"
|
||||
|
||||
@ -177,24 +188,50 @@ func Decompress(localPath, uncompressedPath string) error {
|
||||
// Will error out if file without .xz already exists
|
||||
// Maybe extracting then renameing is a good idea here..
|
||||
// depends on xz: not pre-installed on mac, so it becomes a brew dependency
|
||||
func decompressXZ(src string, output io.Writer) error {
|
||||
cmd := exec.Command("xzcat", "-k", src)
|
||||
//cmd := exec.Command("xz", "-d", "-k", "-v", src)
|
||||
stdOut, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
func decompressXZ(src string, output io.WriteCloser) error {
|
||||
var read io.Reader
|
||||
var cmd *exec.Cmd
|
||||
// Prefer xz utils for fastest performance, fallback to go xi2 impl
|
||||
if _, err := exec.LookPath("xzcat"); err == nil {
|
||||
cmd = exec.Command("xzcat", "-k", src)
|
||||
read, err = cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Stderr = os.Stderr
|
||||
} else {
|
||||
file, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
// This XZ implementation is reliant on buffering. It is also 3x+ slower than XZ utils.
|
||||
// Consider replacing with a faster implementation (e.g. xi2) if podman machine is
|
||||
// updated with a larger image for the distribution base.
|
||||
buf := bufio.NewReader(file)
|
||||
read, err = xz.NewReader(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
//cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
if _, err := io.Copy(output, stdOut); err != nil {
|
||||
if _, err := io.Copy(output, read); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
output.Close()
|
||||
done <- true
|
||||
}()
|
||||
return cmd.Run()
|
||||
|
||||
if cmd != nil {
|
||||
return cmd.Run()
|
||||
}
|
||||
<-done
|
||||
return nil
|
||||
}
|
||||
|
||||
func decompressEverythingElse(src string, output io.Writer) error {
|
||||
func decompressEverythingElse(src string, output io.WriteCloser) error {
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -207,6 +244,9 @@ func decompressEverythingElse(src string, output io.Writer) error {
|
||||
if err := uncompressStream.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if err := output.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(output, uncompressStream)
|
||||
|
Reference in New Issue
Block a user