mirror of
https://github.com/containers/podman.git
synced 2025-07-03 09:17:15 +08:00
Refactor key machine objects
In #20538, I was asked to consider refactoring the new OCI pull code from within the generic machine directory. This is something I had tried when originally coding it but it became apparent that a much larger refactor to prevent circular deps was needed. Because I did not want to pollute the initial PR with that refactor, I asked for the PR to merge first. This is the refactor that needed to be done. Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
@ -11,6 +11,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
vfConfig "github.com/crc-org/vfkit/pkg/config"
|
||||
"github.com/docker/go-units"
|
||||
"golang.org/x/sys/unix"
|
||||
@ -34,7 +36,7 @@ type MMHardwareConfig struct {
|
||||
|
||||
func VirtualizationProvider() machine.VirtProvider {
|
||||
return &AppleHVVirtualization{
|
||||
machine.NewVirtualization(machine.AppleHV, machine.Xz, machine.Raw, vmtype),
|
||||
machine.NewVirtualization(define.AppleHV, compression.Xz, define.Raw, vmtype),
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,7 +118,7 @@ func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configPath, err := machine.NewMachineFile(getVMConfigPath(configDir, opts.Name), nil)
|
||||
configPath, err := define.NewMachineFile(getVMConfigPath(configDir, opts.Name), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -127,7 +129,7 @@ func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ignitionPath, err := machine.NewMachineFile(filepath.Join(configDir, m.Name)+".ign", nil)
|
||||
ignitionPath, err := define.NewMachineFile(filepath.Join(configDir, m.Name)+".ign", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// serveIgnitionOverSock allows podman to open a small httpd instance on the vsock between the host
|
||||
// and guest to inject the ignitionfile into fcos
|
||||
func (m *MacMachine) serveIgnitionOverSock(ignitionSocket *machine.VMFile) error {
|
||||
func (m *MacMachine) serveIgnitionOverSock(ignitionSocket *define.VMFile) error {
|
||||
logrus.Debugf("reading ignition file: %s", m.IgnitionFile.GetPath())
|
||||
ignFile, err := m.IgnitionFile.Read()
|
||||
if err != nil {
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"github.com/containers/common/pkg/config"
|
||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/strongunits"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
@ -45,13 +46,13 @@ const (
|
||||
type VfkitHelper struct {
|
||||
LogLevel logrus.Level
|
||||
Endpoint string
|
||||
VfkitBinaryPath *machine.VMFile
|
||||
VfkitBinaryPath *define.VMFile
|
||||
VirtualMachine *vfConfig.VirtualMachine
|
||||
}
|
||||
|
||||
type MacMachine struct {
|
||||
// ConfigPath is the fully qualified path to the configuration file
|
||||
ConfigPath machine.VMFile
|
||||
ConfigPath define.VMFile
|
||||
// HostUser contains info about host user
|
||||
machine.HostUser
|
||||
// ImageConfig describes the bootable image
|
||||
@ -61,7 +62,7 @@ type MacMachine struct {
|
||||
// Name of VM
|
||||
Name string
|
||||
// ReadySocket tells host when vm is booted
|
||||
ReadySocket machine.VMFile
|
||||
ReadySocket define.VMFile
|
||||
// ResourceConfig is physical attrs of the VM
|
||||
machine.ResourceConfig
|
||||
// SSHConfig for accessing the remote vm
|
||||
@ -74,9 +75,9 @@ type MacMachine struct {
|
||||
LastUp time.Time
|
||||
// The VFKit endpoint where we can interact with the VM
|
||||
Vfkit VfkitHelper
|
||||
LogPath machine.VMFile
|
||||
GvProxyPid machine.VMFile
|
||||
GvProxySock machine.VMFile
|
||||
LogPath define.VMFile
|
||||
GvProxyPid define.VMFile
|
||||
GvProxySock define.VMFile
|
||||
|
||||
// Used at runtime for serializing write operations
|
||||
lock *lockfile.LockFile
|
||||
@ -84,7 +85,7 @@ type MacMachine struct {
|
||||
|
||||
// setGVProxyInfo sets the VM's gvproxy pid and socket files
|
||||
func (m *MacMachine) setGVProxyInfo(runtimeDir string) error {
|
||||
gvProxyPid, err := machine.NewMachineFile(filepath.Join(runtimeDir, "gvproxy.pid"), nil)
|
||||
gvProxyPid, err := define.NewMachineFile(filepath.Join(runtimeDir, "gvproxy.pid"), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -95,7 +96,7 @@ func (m *MacMachine) setGVProxyInfo(runtimeDir string) error {
|
||||
|
||||
// setVfkitInfo stores the default devices, sets the vfkit endpoint, and
|
||||
// locates/stores the path to the binary
|
||||
func (m *MacMachine) setVfkitInfo(cfg *config.Config, readySocket machine.VMFile) error {
|
||||
func (m *MacMachine) setVfkitInfo(cfg *config.Config, readySocket define.VMFile) error {
|
||||
defaultDevices, err := getDefaultDevices(m.ImagePath.GetPath(), m.LogPath.GetPath(), readySocket.GetPath())
|
||||
if err != nil {
|
||||
return err
|
||||
@ -105,7 +106,7 @@ func (m *MacMachine) setVfkitInfo(cfg *config.Config, readySocket machine.VMFile
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vfkitBinaryPath, err := machine.NewMachineFile(vfkitPath, nil)
|
||||
vfkitBinaryPath, err := define.NewMachineFile(vfkitPath, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -217,7 +218,7 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
|
||||
m.ImagePath = *imagePath
|
||||
m.ImageStream = strm.String()
|
||||
|
||||
logPath, err := machine.NewMachineFile(filepath.Join(dataDir, fmt.Sprintf("%s.log", m.Name)), nil)
|
||||
logPath, err := define.NewMachineFile(filepath.Join(dataDir, fmt.Sprintf("%s.log", m.Name)), nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -490,7 +491,7 @@ func (m *MacMachine) SSH(name string, opts machine.SSHOptions) error {
|
||||
|
||||
// deleteIgnitionSocket retrieves the ignition socket, deletes it, and returns a
|
||||
// pointer to the `VMFile`
|
||||
func (m *MacMachine) deleteIgnitionSocket() (*machine.VMFile, error) {
|
||||
func (m *MacMachine) deleteIgnitionSocket() (*define.VMFile, error) {
|
||||
ignitionSocket, err := m.getIgnitionSock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -556,7 +557,7 @@ func (m *MacMachine) addVolumesToVfKit() error {
|
||||
}
|
||||
|
||||
func (m *MacMachine) Start(name string, opts machine.StartOptions) error {
|
||||
var ignitionSocket *machine.VMFile
|
||||
var ignitionSocket *define.VMFile
|
||||
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
@ -996,13 +997,13 @@ func (m *MacMachine) dockerSock() (string, error) {
|
||||
return filepath.Join(dd, "podman.sock"), nil
|
||||
}
|
||||
|
||||
func (m *MacMachine) forwardSocketPath() (*machine.VMFile, error) {
|
||||
func (m *MacMachine) forwardSocketPath() (*define.VMFile, error) {
|
||||
sockName := "podman.sock"
|
||||
path, err := machine.GetDataDir(machine.AppleHvVirt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Resolving data dir: %s", err.Error())
|
||||
}
|
||||
return machine.NewMachineFile(filepath.Join(path, sockName), &sockName)
|
||||
return define.NewMachineFile(filepath.Join(path, sockName), &sockName)
|
||||
}
|
||||
|
||||
// resizeDisk uses os truncate to resize (only larger) a raw disk. the input size
|
||||
@ -1034,7 +1035,7 @@ func (m *MacMachine) isFirstBoot() (bool, error) {
|
||||
return m.LastUp == never, nil
|
||||
}
|
||||
|
||||
func (m *MacMachine) getIgnitionSock() (*machine.VMFile, error) {
|
||||
func (m *MacMachine) getIgnitionSock() (*define.VMFile, error) {
|
||||
dataDir, err := machine.GetDataDir(machine.AppleHvVirt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1044,7 +1045,7 @@ func (m *MacMachine) getIgnitionSock() (*machine.VMFile, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return machine.NewMachineFile(filepath.Join(dataDir, ignitionSocketName), nil)
|
||||
return define.NewMachineFile(filepath.Join(dataDir, ignitionSocketName), nil)
|
||||
}
|
||||
|
||||
func (m *MacMachine) getRuntimeDir() (string, error) {
|
||||
|
91
pkg/machine/compression/compression_test.go
Normal file
91
pkg/machine/compression/compression_test.go
Normal file
@ -0,0 +1,91 @@
|
||||
package compression
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test_compressionFromFile(t *testing.T) {
|
||||
type args struct {
|
||||
path string
|
||||
}
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want ImageCompression
|
||||
}{
|
||||
{
|
||||
name: "xz",
|
||||
args: args{
|
||||
path: "/tmp/foo.xz",
|
||||
},
|
||||
want: Xz,
|
||||
},
|
||||
{
|
||||
name: "gzip",
|
||||
args: args{
|
||||
path: "/tmp/foo.gz",
|
||||
},
|
||||
want: Gz,
|
||||
},
|
||||
{
|
||||
name: "bz2",
|
||||
args: args{
|
||||
path: "/tmp/foo.bz2",
|
||||
},
|
||||
want: Bz2,
|
||||
},
|
||||
{
|
||||
name: "default is xz",
|
||||
args: args{
|
||||
path: "/tmp/foo",
|
||||
},
|
||||
want: Xz,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := KindFromFile(tt.args.path); got != tt.want {
|
||||
t.Errorf("KindFromFile() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageCompression_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
c ImageCompression
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "xz",
|
||||
c: Xz,
|
||||
want: "xz",
|
||||
},
|
||||
{
|
||||
name: "gz",
|
||||
c: Gz,
|
||||
want: "gz",
|
||||
},
|
||||
{
|
||||
name: "bz2",
|
||||
c: Bz2,
|
||||
want: "bz2",
|
||||
},
|
||||
{
|
||||
name: "zip",
|
||||
c: Zip,
|
||||
want: "zip",
|
||||
},
|
||||
{
|
||||
name: "xz is default",
|
||||
c: 99,
|
||||
want: "xz",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.c.String(); got != tt.want {
|
||||
t.Errorf("String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
36
pkg/machine/compression/config.go
Normal file
36
pkg/machine/compression/config.go
Normal file
@ -0,0 +1,36 @@
|
||||
package compression
|
||||
|
||||
import "strings"
|
||||
|
||||
type ImageCompression int64
|
||||
|
||||
const (
|
||||
Xz ImageCompression = iota
|
||||
Zip
|
||||
Gz
|
||||
Bz2
|
||||
)
|
||||
|
||||
func KindFromFile(path string) ImageCompression {
|
||||
switch {
|
||||
case strings.HasSuffix(path, Bz2.String()):
|
||||
return Bz2
|
||||
case strings.HasSuffix(path, Gz.String()):
|
||||
return Gz
|
||||
case strings.HasSuffix(path, Zip.String()):
|
||||
return Zip
|
||||
}
|
||||
return Xz
|
||||
}
|
||||
|
||||
func (c ImageCompression) String() string {
|
||||
switch c {
|
||||
case Gz:
|
||||
return "gz"
|
||||
case Zip:
|
||||
return "zip"
|
||||
case Bz2:
|
||||
return "bz2"
|
||||
}
|
||||
return "xz"
|
||||
}
|
184
pkg/machine/compression/decompress.go
Normal file
184
pkg/machine/compression/decompress.go
Normal file
@ -0,0 +1,184 @@
|
||||
package compression
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/ulikunitz/xz"
|
||||
)
|
||||
|
||||
func Decompress(localPath *define.VMFile, uncompressedPath string) error {
|
||||
var isZip bool
|
||||
uncompressedFileWriter, err := os.OpenFile(uncompressedPath, os.O_CREATE|os.O_RDWR, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sourceFile, err := localPath.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasSuffix(localPath.GetPath(), ".zip") {
|
||||
isZip = true
|
||||
}
|
||||
prefix := "Copying uncompressed file"
|
||||
compressionType := archive.DetectCompression(sourceFile)
|
||||
if compressionType != archive.Uncompressed || isZip {
|
||||
prefix = "Extracting compressed file"
|
||||
}
|
||||
prefix += ": " + filepath.Base(uncompressedPath)
|
||||
if compressionType == archive.Xz {
|
||||
return decompressXZ(prefix, localPath.GetPath(), uncompressedFileWriter)
|
||||
}
|
||||
if isZip && runtime.GOOS == "windows" {
|
||||
return decompressZip(prefix, localPath.GetPath(), uncompressedFileWriter)
|
||||
}
|
||||
return decompressEverythingElse(prefix, localPath.GetPath(), uncompressedFileWriter)
|
||||
}
|
||||
|
||||
// Will error out if file without .Xz already exists
|
||||
// Maybe extracting then renaming is a good idea here..
|
||||
// depends on Xz: not pre-installed on mac, so it becomes a brew dependency
|
||||
func decompressXZ(prefix string, src string, output io.WriteCloser) error {
|
||||
var read io.Reader
|
||||
var cmd *exec.Cmd
|
||||
|
||||
stat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
p, bar := utils.ProgressBar(prefix, stat.Size(), prefix+": done")
|
||||
proxyReader := bar.ProxyReader(file)
|
||||
defer func() {
|
||||
if err := proxyReader.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Prefer Xz utils for fastest performance, fallback to go xi2 impl
|
||||
if _, err := exec.LookPath("xz"); err == nil {
|
||||
cmd = exec.Command("xz", "-d", "-c")
|
||||
cmd.Stdin = proxyReader
|
||||
read, err = cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Stderr = os.Stderr
|
||||
} else {
|
||||
// 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(proxyReader)
|
||||
read, err = xz.NewReader(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
if _, err := io.Copy(output, read); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
output.Close()
|
||||
done <- true
|
||||
}()
|
||||
|
||||
if cmd != nil {
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Wait()
|
||||
return cmd.Wait()
|
||||
}
|
||||
<-done
|
||||
p.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func decompressEverythingElse(prefix string, src string, output io.WriteCloser) error {
|
||||
stat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p, bar := utils.ProgressBar(prefix, stat.Size(), prefix+": done")
|
||||
proxyReader := bar.ProxyReader(f)
|
||||
defer func() {
|
||||
if err := proxyReader.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
uncompressStream, _, err := compression.AutoDecompress(proxyReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := uncompressStream.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if err := output.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(output, uncompressStream)
|
||||
p.Wait()
|
||||
return err
|
||||
}
|
||||
|
||||
func decompressZip(prefix string, src string, output io.WriteCloser) error {
|
||||
zipReader, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(zipReader.File) != 1 {
|
||||
return errors.New("machine image files should consist of a single compressed file")
|
||||
}
|
||||
f, err := zipReader.File[0].Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
if err := output.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
size := int64(zipReader.File[0].CompressedSize64)
|
||||
p, bar := utils.ProgressBar(prefix, size, prefix+": done")
|
||||
proxyReader := bar.ProxyReader(f)
|
||||
defer func() {
|
||||
if err := proxyReader.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
_, err = io.Copy(output, proxyReader)
|
||||
p.Wait()
|
||||
return err
|
||||
}
|
@ -15,6 +15,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/storage/pkg/homedir"
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -64,11 +66,11 @@ var (
|
||||
|
||||
type Download struct {
|
||||
Arch string
|
||||
Artifact Artifact
|
||||
Artifact define.Artifact
|
||||
CacheDir string
|
||||
CompressionType ImageCompression
|
||||
CompressionType compression.ImageCompression
|
||||
DataDir string
|
||||
Format ImageFormat
|
||||
Format define.ImageFormat
|
||||
ImageName string
|
||||
LocalPath string
|
||||
LocalUncompressedFile string
|
||||
@ -162,7 +164,7 @@ type DistributionDownload interface {
|
||||
CleanCache() error
|
||||
}
|
||||
type InspectInfo struct {
|
||||
ConfigPath VMFile
|
||||
ConfigPath define.VMFile
|
||||
ConnectionInfo ConnectionConfig
|
||||
Created time.Time
|
||||
Image ImageConfig
|
||||
@ -269,15 +271,6 @@ func ConfDirPrefix() (string, error) {
|
||||
return confDir, nil
|
||||
}
|
||||
|
||||
// GuardedRemoveAll functions much like os.RemoveAll but
|
||||
// will not delete certain catastrophic paths.
|
||||
func GuardedRemoveAll(path string) error {
|
||||
if path == "" || path == "/" {
|
||||
return fmt.Errorf("refusing to recursively delete `%s`", path)
|
||||
}
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
// ResourceConfig describes physical attributes of the machine
|
||||
type ResourceConfig struct {
|
||||
// CPUs to be assigned to the VM
|
||||
@ -288,77 +281,6 @@ type ResourceConfig struct {
|
||||
Memory uint64
|
||||
}
|
||||
|
||||
const maxSocketPathLength int = 103
|
||||
|
||||
type VMFile struct {
|
||||
// Path is the fully qualified path to a file
|
||||
Path string
|
||||
// Symlink is a shortened version of Path by using
|
||||
// a symlink
|
||||
Symlink *string `json:"symlink,omitempty"`
|
||||
}
|
||||
|
||||
// GetPath returns the working path for a machinefile. it returns
|
||||
// the symlink unless one does not exist
|
||||
func (m *VMFile) GetPath() string {
|
||||
if m.Symlink == nil {
|
||||
return m.Path
|
||||
}
|
||||
return *m.Symlink
|
||||
}
|
||||
|
||||
// Delete removes the machinefile symlink (if it exists) and
|
||||
// the actual path
|
||||
func (m *VMFile) Delete() error {
|
||||
if m.Symlink != nil {
|
||||
if err := os.Remove(*m.Symlink); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
logrus.Errorf("unable to remove symlink %q", *m.Symlink)
|
||||
}
|
||||
}
|
||||
if err := os.Remove(m.Path); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read the contents of a given file and return in []bytes
|
||||
func (m *VMFile) Read() ([]byte, error) {
|
||||
return os.ReadFile(m.GetPath())
|
||||
}
|
||||
|
||||
// NewMachineFile is a constructor for VMFile
|
||||
func NewMachineFile(path string, symlink *string) (*VMFile, error) {
|
||||
if len(path) < 1 {
|
||||
return nil, errors.New("invalid machine file path")
|
||||
}
|
||||
if symlink != nil && len(*symlink) < 1 {
|
||||
return nil, errors.New("invalid symlink path")
|
||||
}
|
||||
mf := VMFile{Path: path}
|
||||
if symlink != nil && len(path) > maxSocketPathLength {
|
||||
if err := mf.makeSymlink(symlink); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &mf, nil
|
||||
}
|
||||
|
||||
// makeSymlink for macOS creates a symlink in $HOME/.podman/
|
||||
// for a machinefile like a socket
|
||||
func (m *VMFile) makeSymlink(symlink *string) error {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sl := filepath.Join(homeDir, ".podman", *symlink)
|
||||
// make the symlink dir and throw away if it already exists
|
||||
if err := os.MkdirAll(filepath.Dir(sl), 0700); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
m.Symlink = &sl
|
||||
return os.Symlink(m.Path, sl)
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
ReadOnly bool
|
||||
Source string
|
||||
@ -371,11 +293,11 @@ type Mount struct {
|
||||
type ImageConfig struct {
|
||||
// IgnitionFile is the path to the filesystem where the
|
||||
// ignition file was written (if needs one)
|
||||
IgnitionFile VMFile `json:"IgnitionFilePath"`
|
||||
IgnitionFile define.VMFile `json:"IgnitionFilePath"`
|
||||
// ImageStream is the update stream for the image
|
||||
ImageStream string
|
||||
// ImageFile is the fq path to
|
||||
ImagePath VMFile `json:"ImagePath"`
|
||||
ImagePath define.VMFile `json:"ImagePath"`
|
||||
}
|
||||
|
||||
// HostUser describes the host user
|
||||
@ -401,9 +323,9 @@ type SSHConfig struct {
|
||||
// ConnectionConfig contains connections like sockets, etc.
|
||||
type ConnectionConfig struct {
|
||||
// PodmanSocket is the exported podman service socket
|
||||
PodmanSocket *VMFile `json:"PodmanSocket"`
|
||||
PodmanSocket *define.VMFile `json:"PodmanSocket"`
|
||||
// PodmanPipe is the exported podman service named pipe (Windows hosts only)
|
||||
PodmanPipe *VMFile `json:"PodmanPipe"`
|
||||
PodmanPipe *define.VMFile `json:"PodmanPipe"`
|
||||
}
|
||||
|
||||
type VMType int64
|
||||
@ -455,10 +377,10 @@ func ParseVMType(input string, emptyFallback VMType) (VMType, error) {
|
||||
}
|
||||
|
||||
type VirtProvider interface { //nolint:interfacebloat
|
||||
Artifact() Artifact
|
||||
Artifact() define.Artifact
|
||||
CheckExclusiveActiveVM() (bool, string, error)
|
||||
Compression() ImageCompression
|
||||
Format() ImageFormat
|
||||
Compression() compression.ImageCompression
|
||||
Format() define.ImageFormat
|
||||
IsValidVMName(name string) (bool, error)
|
||||
List(opts ListOptions) ([]*ListResponse, error)
|
||||
LoadVMByName(name string) (VM, error)
|
||||
@ -469,21 +391,21 @@ type VirtProvider interface { //nolint:interfacebloat
|
||||
}
|
||||
|
||||
type Virtualization struct {
|
||||
artifact Artifact
|
||||
compression ImageCompression
|
||||
format ImageFormat
|
||||
artifact define.Artifact
|
||||
compression compression.ImageCompression
|
||||
format define.ImageFormat
|
||||
vmKind VMType
|
||||
}
|
||||
|
||||
func (p *Virtualization) Artifact() Artifact {
|
||||
func (p *Virtualization) Artifact() define.Artifact {
|
||||
return p.artifact
|
||||
}
|
||||
|
||||
func (p *Virtualization) Compression() ImageCompression {
|
||||
func (p *Virtualization) Compression() compression.ImageCompression {
|
||||
return p.compression
|
||||
}
|
||||
|
||||
func (p *Virtualization) Format() ImageFormat {
|
||||
func (p *Virtualization) Format() define.ImageFormat {
|
||||
return p.format
|
||||
}
|
||||
|
||||
@ -513,7 +435,7 @@ func (p *Virtualization) NewDownload(vmName string) (Download, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewVirtualization(artifact Artifact, compression ImageCompression, format ImageFormat, vmKind VMType) Virtualization {
|
||||
func NewVirtualization(artifact define.Artifact, compression compression.ImageCompression, format define.ImageFormat, vmKind VMType) Virtualization {
|
||||
return Virtualization{
|
||||
artifact,
|
||||
compression,
|
||||
@ -579,10 +501,10 @@ func (dl Download) NewFcosDownloader(imageStream FCOSStream) (DistributionDownlo
|
||||
// AcquireVMImage determines if the image is already in a FCOS stream. If so,
|
||||
// retrieves the image path of the uncompressed file. Otherwise, the user has
|
||||
// provided an alternative image, so we set the image path and download the image.
|
||||
func (dl Download) AcquireVMImage(imagePath string) (*VMFile, FCOSStream, error) {
|
||||
func (dl Download) AcquireVMImage(imagePath string) (*define.VMFile, FCOSStream, error) {
|
||||
var (
|
||||
err error
|
||||
imageLocation *VMFile
|
||||
imageLocation *define.VMFile
|
||||
fcosStream FCOSStream
|
||||
)
|
||||
|
||||
@ -600,7 +522,7 @@ func (dl Download) AcquireVMImage(imagePath string) (*VMFile, FCOSStream, error)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
imageLocation, err = NewMachineFile(dd.Get().LocalUncompressedFile, nil)
|
||||
imageLocation, err = define.NewMachineFile(dd.Get().LocalUncompressedFile, nil)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
34
pkg/machine/define/image_format.go
Normal file
34
pkg/machine/define/image_format.go
Normal file
@ -0,0 +1,34 @@
|
||||
package define
|
||||
|
||||
type ImageFormat int64
|
||||
|
||||
const (
|
||||
Qcow ImageFormat = iota
|
||||
Vhdx
|
||||
Tar
|
||||
Raw
|
||||
)
|
||||
|
||||
func (imf ImageFormat) Kind() string {
|
||||
switch imf {
|
||||
case Vhdx:
|
||||
return "vhdx"
|
||||
case Tar:
|
||||
return "tar"
|
||||
case Raw:
|
||||
return "raw"
|
||||
}
|
||||
return "qcow2"
|
||||
}
|
||||
|
||||
func (imf ImageFormat) KindWithCompression() string {
|
||||
switch imf {
|
||||
case Vhdx:
|
||||
return "vhdx.zip"
|
||||
case Tar:
|
||||
return "tar.xz"
|
||||
case Raw:
|
||||
return "raw.gz"
|
||||
}
|
||||
return "qcow2.xz"
|
||||
}
|
74
pkg/machine/define/image_format_test.go
Normal file
74
pkg/machine/define/image_format_test.go
Normal file
@ -0,0 +1,74 @@
|
||||
package define
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestImageFormat_Kind(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
imf ImageFormat
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "vhdx",
|
||||
imf: Vhdx,
|
||||
want: "vhdx",
|
||||
},
|
||||
{
|
||||
name: "qcow2",
|
||||
imf: Qcow,
|
||||
want: "qcow2",
|
||||
},
|
||||
{
|
||||
name: "raw",
|
||||
imf: Raw,
|
||||
want: "raw",
|
||||
},
|
||||
{
|
||||
name: "tar",
|
||||
imf: Tar,
|
||||
want: "tar",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.imf.Kind(); got != tt.want {
|
||||
t.Errorf("Kind() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageFormat_KindWithCompression(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
imf ImageFormat
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "vhdx.zip",
|
||||
imf: Vhdx,
|
||||
want: "vhdx.zip",
|
||||
},
|
||||
{
|
||||
name: "qcow2",
|
||||
imf: Qcow,
|
||||
want: "qcow2.xz",
|
||||
},
|
||||
{
|
||||
name: "raw.gz",
|
||||
imf: Raw,
|
||||
want: "raw.gz",
|
||||
}, {
|
||||
name: "tar.xz",
|
||||
imf: Tar,
|
||||
want: "tar.xz",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.imf.KindWithCompression(); got != tt.want {
|
||||
t.Errorf("String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
20
pkg/machine/define/machine_artifact.go
Normal file
20
pkg/machine/define/machine_artifact.go
Normal file
@ -0,0 +1,20 @@
|
||||
package define
|
||||
|
||||
type Artifact int64
|
||||
|
||||
const (
|
||||
Qemu Artifact = iota
|
||||
HyperV
|
||||
AppleHV
|
||||
None
|
||||
)
|
||||
|
||||
func (a Artifact) String() string {
|
||||
switch a {
|
||||
case HyperV:
|
||||
return "hyperv"
|
||||
case AppleHV:
|
||||
return "applehv"
|
||||
}
|
||||
return "qemu"
|
||||
}
|
35
pkg/machine/define/machine_artifact_test.go
Normal file
35
pkg/machine/define/machine_artifact_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package define
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_artifact_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
a Artifact
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "qemu",
|
||||
a: Qemu,
|
||||
want: "qemu",
|
||||
},
|
||||
{
|
||||
name: "hyperv",
|
||||
a: HyperV,
|
||||
want: "hyperv",
|
||||
}, {
|
||||
name: "applehv",
|
||||
a: AppleHV,
|
||||
want: "applehv",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.a.String(); got != tt.want {
|
||||
t.Errorf("String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
80
pkg/machine/define/vmfile.go
Normal file
80
pkg/machine/define/vmfile.go
Normal file
@ -0,0 +1,80 @@
|
||||
package define
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const MaxSocketPathLength int = 103
|
||||
|
||||
type VMFile struct {
|
||||
// Path is the fully qualified path to a file
|
||||
Path string
|
||||
// Symlink is a shortened version of Path by using
|
||||
// a symlink
|
||||
Symlink *string `json:"symlink,omitempty"`
|
||||
}
|
||||
|
||||
// GetPath returns the working path for a machinefile. it returns
|
||||
// the symlink unless one does not exist
|
||||
func (m *VMFile) GetPath() string {
|
||||
if m.Symlink == nil {
|
||||
return m.Path
|
||||
}
|
||||
return *m.Symlink
|
||||
}
|
||||
|
||||
// Delete removes the machinefile symlink (if it exists) and
|
||||
// the actual path
|
||||
func (m *VMFile) Delete() error {
|
||||
if m.Symlink != nil {
|
||||
if err := os.Remove(*m.Symlink); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
logrus.Errorf("unable to remove symlink %q", *m.Symlink)
|
||||
}
|
||||
}
|
||||
if err := os.Remove(m.Path); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read the contents of a given file and return in []bytes
|
||||
func (m *VMFile) Read() ([]byte, error) {
|
||||
return os.ReadFile(m.GetPath())
|
||||
}
|
||||
|
||||
// NewMachineFile is a constructor for VMFile
|
||||
func NewMachineFile(path string, symlink *string) (*VMFile, error) {
|
||||
if len(path) < 1 {
|
||||
return nil, errors.New("invalid machine file path")
|
||||
}
|
||||
if symlink != nil && len(*symlink) < 1 {
|
||||
return nil, errors.New("invalid symlink path")
|
||||
}
|
||||
mf := VMFile{Path: path}
|
||||
if symlink != nil && len(path) > MaxSocketPathLength {
|
||||
if err := mf.makeSymlink(symlink); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &mf, nil
|
||||
}
|
||||
|
||||
// makeSymlink for macOS creates a symlink in $HOME/.podman/
|
||||
// for a machinefile like a socket
|
||||
func (m *VMFile) makeSymlink(symlink *string) error {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sl := filepath.Join(homeDir, ".podman", *symlink)
|
||||
// make the symlink dir and throw away if it already exists
|
||||
if err := os.MkdirAll(filepath.Dir(sl), 0700); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
m.Symlink = &sl
|
||||
return os.Symlink(m.Path, sl)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
//go:build (amd64 && !windows) || (arm64 && !windows)
|
||||
// +build amd64,!windows arm64,!windows
|
||||
|
||||
package qemu
|
||||
package define
|
||||
|
||||
import (
|
||||
"os"
|
||||
@ -9,7 +9,6 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/test/utils"
|
||||
)
|
||||
|
||||
@ -41,7 +40,7 @@ func TestMachineFile_GetPath(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &machine.VMFile{
|
||||
m := &VMFile{
|
||||
Path: tt.fields.Path, //nolint: scopelint
|
||||
Symlink: tt.fields.Symlink, //nolint: scopelint
|
||||
}
|
||||
@ -75,7 +74,7 @@ func TestNewMachineFile(t *testing.T) {
|
||||
sym := "my.sock"
|
||||
longSym := filepath.Join(homedir, ".podman", sym)
|
||||
|
||||
m := machine.VMFile{
|
||||
m := VMFile{
|
||||
Path: p,
|
||||
Symlink: nil,
|
||||
}
|
||||
@ -86,7 +85,7 @@ func TestNewMachineFile(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *machine.VMFile
|
||||
want *VMFile
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@ -98,7 +97,7 @@ func TestNewMachineFile(t *testing.T) {
|
||||
{
|
||||
name: "Good with short symlink",
|
||||
args: args{p, &sym},
|
||||
want: &machine.VMFile{Path: p},
|
||||
want: &VMFile{Path: p},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
@ -116,14 +115,14 @@ func TestNewMachineFile(t *testing.T) {
|
||||
{
|
||||
name: "Good with long symlink",
|
||||
args: args{longp, &sym},
|
||||
want: &machine.VMFile{Path: longp, Symlink: &longSym},
|
||||
want: &VMFile{Path: longp, Symlink: &longSym},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := machine.NewMachineFile(tt.args.path, tt.args.symlink)
|
||||
got, err := NewMachineFile(tt.args.path, tt.args.symlink)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewMachineFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
. "github.com/onsi/gomega/gexec"
|
||||
@ -188,7 +189,7 @@ var _ = Describe("podman machine init", func() {
|
||||
_, err = os.CreateTemp(tmpDir, "example")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
mount := tmpDir + ":/testmountdir"
|
||||
defer func() { _ = machine.GuardedRemoveAll(tmpDir) }()
|
||||
defer func() { _ = utils.GuardedRemoveAll(tmpDir) }()
|
||||
|
||||
name := randomString()
|
||||
i := new(initMachine)
|
||||
|
@ -12,7 +12,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/provider"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@ -77,11 +80,11 @@ var _ = BeforeSuite(func() {
|
||||
Fail(fmt.Sprintf("unable to download machine image: %q", err))
|
||||
}
|
||||
GinkgoWriter.Println("Download took: ", time.Since(now).String())
|
||||
diskImage, err := machine.NewMachineFile(fqImageName+compressionExtension, nil)
|
||||
diskImage, err := define.NewMachineFile(fqImageName+compressionExtension, nil)
|
||||
if err != nil {
|
||||
Fail(fmt.Sprintf("unable to create vmfile %q: %v", fqImageName+compressionExtension, err))
|
||||
}
|
||||
if err := machine.Decompress(diskImage, fqImageName); err != nil {
|
||||
if err := compression.Decompress(diskImage, fqImageName); err != nil {
|
||||
Fail(fmt.Sprintf("unable to decompress image file: %q", err))
|
||||
}
|
||||
} else {
|
||||
@ -149,7 +152,7 @@ func teardown(origHomeDir string, testDir string, mb *machineTestBuilder) {
|
||||
GinkgoWriter.Printf("error occurred rm'ing machine: %q\n", err)
|
||||
}
|
||||
}
|
||||
if err := machine.GuardedRemoveAll(testDir); err != nil {
|
||||
if err := utils.GuardedRemoveAll(testDir); err != nil {
|
||||
Fail(fmt.Sprintf("failed to remove test dir: %q", err))
|
||||
}
|
||||
// this needs to be last in teardown
|
||||
|
@ -11,9 +11,10 @@ import (
|
||||
url2 "net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/coreos/stream-metadata-go/fedoracoreos"
|
||||
"github.com/coreos/stream-metadata-go/release"
|
||||
"github.com/coreos/stream-metadata-go/stream"
|
||||
@ -21,31 +22,12 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ImageCompression int64
|
||||
type Artifact int64
|
||||
type ImageFormat int64
|
||||
|
||||
const (
|
||||
// Used for testing the latest podman in fcos
|
||||
// special builds
|
||||
podmanTesting = "podman-testing"
|
||||
PodmanTestingHost = "fedorapeople.org"
|
||||
PodmanTestingURL = "groups/podman/testing"
|
||||
|
||||
Xz ImageCompression = iota
|
||||
Zip
|
||||
Gz
|
||||
Bz2
|
||||
|
||||
Qemu Artifact = iota
|
||||
HyperV
|
||||
AppleHV
|
||||
None
|
||||
|
||||
Qcow ImageFormat = iota
|
||||
Vhdx
|
||||
Tar
|
||||
Raw
|
||||
)
|
||||
|
||||
//
|
||||
@ -56,64 +38,6 @@ const (
|
||||
// typed strongly
|
||||
//
|
||||
|
||||
func (a Artifact) String() string {
|
||||
switch a {
|
||||
case HyperV:
|
||||
return "hyperv"
|
||||
case AppleHV:
|
||||
return "applehv"
|
||||
}
|
||||
return "qemu"
|
||||
}
|
||||
|
||||
func (imf ImageFormat) String() string {
|
||||
switch imf {
|
||||
case Vhdx:
|
||||
return "vhdx.zip"
|
||||
case Tar:
|
||||
return "tar.xz"
|
||||
case Raw:
|
||||
return "raw.gz"
|
||||
}
|
||||
return "qcow2.xz"
|
||||
}
|
||||
|
||||
func (imf ImageFormat) string() string {
|
||||
switch imf {
|
||||
case Vhdx:
|
||||
return "vhdx"
|
||||
case Tar:
|
||||
return "tar"
|
||||
case Raw:
|
||||
return "raw"
|
||||
}
|
||||
return "qcow2"
|
||||
}
|
||||
|
||||
func (c ImageCompression) String() string {
|
||||
switch c {
|
||||
case Gz:
|
||||
return "gz"
|
||||
case Zip:
|
||||
return "zip"
|
||||
case Bz2:
|
||||
return "bz2"
|
||||
}
|
||||
return "xz"
|
||||
}
|
||||
|
||||
func compressionFromFile(path string) ImageCompression {
|
||||
switch {
|
||||
case strings.HasSuffix(path, Bz2.String()):
|
||||
return Bz2
|
||||
case strings.HasSuffix(path, Gz.String()):
|
||||
return Gz
|
||||
case strings.HasSuffix(path, Zip.String()):
|
||||
return Zip
|
||||
}
|
||||
return Xz
|
||||
}
|
||||
|
||||
type FcosDownload struct {
|
||||
Download
|
||||
}
|
||||
@ -123,7 +47,7 @@ func (f FcosDownload) Get() *Download {
|
||||
}
|
||||
|
||||
type FcosDownloadInfo struct {
|
||||
CompressionType ImageCompression
|
||||
CompressionType compression.ImageCompression
|
||||
Location string
|
||||
Release string
|
||||
Sha256Sum string
|
||||
@ -219,7 +143,7 @@ func (dl Download) GetFCOSDownload(imageStream FCOSStream) (*FcosDownloadInfo, e
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to pull VM image: no targetArch in stream")
|
||||
}
|
||||
qcow2, ok := arches.Media.Qemu.Artifacts[Qcow.String()]
|
||||
qcow2, ok := arches.Media.Qemu.Artifacts[define.Qcow.KindWithCompression()]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to pull VM image: no qcow2.xz format in stream")
|
||||
}
|
||||
@ -251,9 +175,9 @@ func (dl Download) GetFCOSDownload(imageStream FCOSStream) (*FcosDownloadInfo, e
|
||||
if formats == nil {
|
||||
return nil, fmt.Errorf("unable to pull VM image: no formats in stream")
|
||||
}
|
||||
formatType, ok := formats[dl.Format.String()]
|
||||
formatType, ok := formats[dl.Format.KindWithCompression()]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to pull VM image: no %s format in stream", dl.Format.String())
|
||||
return nil, fmt.Errorf("unable to pull VM image: no %s format in stream", dl.Format.KindWithCompression())
|
||||
}
|
||||
disk := formatType.Disk
|
||||
if disk == nil {
|
||||
|
@ -7,146 +7,6 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_compressionFromFile(t *testing.T) {
|
||||
type args struct {
|
||||
path string
|
||||
}
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want ImageCompression
|
||||
}{
|
||||
{
|
||||
name: "xz",
|
||||
args: args{
|
||||
path: "/tmp/foo.xz",
|
||||
},
|
||||
want: Xz,
|
||||
},
|
||||
{
|
||||
name: "gzip",
|
||||
args: args{
|
||||
path: "/tmp/foo.gz",
|
||||
},
|
||||
want: Gz,
|
||||
},
|
||||
{
|
||||
name: "bz2",
|
||||
args: args{
|
||||
path: "/tmp/foo.bz2",
|
||||
},
|
||||
want: Bz2,
|
||||
},
|
||||
{
|
||||
name: "default is xz",
|
||||
args: args{
|
||||
path: "/tmp/foo",
|
||||
},
|
||||
want: Xz,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := compressionFromFile(tt.args.path); got != tt.want {
|
||||
t.Errorf("compressionFromFile() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageCompression_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
c ImageCompression
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "xz",
|
||||
c: Xz,
|
||||
want: "xz",
|
||||
},
|
||||
{
|
||||
name: "gz",
|
||||
c: Gz,
|
||||
want: "gz",
|
||||
},
|
||||
{
|
||||
name: "bz2",
|
||||
c: Bz2,
|
||||
want: "bz2",
|
||||
},
|
||||
{
|
||||
name: "zip",
|
||||
c: Zip,
|
||||
want: "zip",
|
||||
},
|
||||
{
|
||||
name: "xz is default",
|
||||
c: 99,
|
||||
want: "xz",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.c.String(); got != tt.want {
|
||||
t.Errorf("String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageFormat_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
imf ImageFormat
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "vhdx.zip",
|
||||
imf: Vhdx,
|
||||
want: "vhdx.zip",
|
||||
},
|
||||
{
|
||||
name: "qcow2",
|
||||
imf: Qcow,
|
||||
want: "qcow2.xz",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.imf.String(); got != tt.want {
|
||||
t.Errorf("String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_artifact_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
a Artifact
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "qemu",
|
||||
a: Qemu,
|
||||
want: "qemu",
|
||||
},
|
||||
{
|
||||
name: "hyperv",
|
||||
a: HyperV,
|
||||
want: "hyperv",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.a.String(); got != tt.want {
|
||||
t.Errorf("String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFCOSStream_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
psutil "github.com/shirou/gopsutil/v3/process"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -82,7 +83,7 @@ func waitOnProcess(processID int) error {
|
||||
}
|
||||
|
||||
// CleanupGVProxy reads the --pid-file for gvproxy attempts to stop it
|
||||
func CleanupGVProxy(f VMFile) error {
|
||||
func CleanupGVProxy(f define.VMFile) error {
|
||||
gvPid, err := f.Read()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read gvproxy pid file %s: %v", f.GetPath(), err)
|
||||
|
@ -14,6 +14,8 @@ import (
|
||||
|
||||
"github.com/containers/libhvee/pkg/hypervctl"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -24,7 +26,7 @@ type HyperVVirtualization struct {
|
||||
|
||||
func VirtualizationProvider() machine.VirtProvider {
|
||||
return &HyperVVirtualization{
|
||||
machine.NewVirtualization(machine.HyperV, machine.Zip, machine.Vhdx, vmtype),
|
||||
machine.NewVirtualization(define.HyperV, compression.Zip, define.Vhdx, vmtype),
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,14 +119,14 @@ func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configPath, err := machine.NewMachineFile(getVMConfigPath(configDir, opts.Name), nil)
|
||||
configPath, err := define.NewMachineFile(getVMConfigPath(configDir, opts.Name), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.ConfigPath = *configPath
|
||||
|
||||
ignitionPath, err := machine.NewMachineFile(filepath.Join(configDir, m.Name)+".ign", nil)
|
||||
ignitionPath, err := define.NewMachineFile(filepath.Join(configDir, m.Name)+".ign", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -139,7 +141,7 @@ func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
|
||||
}
|
||||
|
||||
// Set the proxy pid file
|
||||
gvProxyPid, err := machine.NewMachineFile(filepath.Join(dataDir, "gvproxy.pid"), nil)
|
||||
gvProxyPid, err := define.NewMachineFile(filepath.Join(dataDir, "gvproxy.pid"), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||
"github.com/containers/libhvee/pkg/hypervctl"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/strongunits"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
@ -44,7 +45,7 @@ const (
|
||||
|
||||
type HyperVMachine struct {
|
||||
// ConfigPath is the fully qualified path to the configuration file
|
||||
ConfigPath machine.VMFile
|
||||
ConfigPath define.VMFile
|
||||
// HostUser contains info about host user
|
||||
machine.HostUser
|
||||
// ImageConfig describes the bootable image
|
||||
@ -68,7 +69,7 @@ type HyperVMachine struct {
|
||||
// LastUp contains the last recorded uptime
|
||||
LastUp time.Time
|
||||
// GVProxy will write its PID here
|
||||
GvProxyPid machine.VMFile
|
||||
GvProxyPid define.VMFile
|
||||
// MountVsocks contains the currently-active vsocks, mapped to the
|
||||
// directory they should be mounted on.
|
||||
MountVsocks map[string]uint64
|
||||
@ -873,13 +874,13 @@ func (m *HyperVMachine) dockerSock() (string, error) {
|
||||
return filepath.Join(dd, "podman.sock"), nil
|
||||
}
|
||||
|
||||
func (m *HyperVMachine) forwardSocketPath() (*machine.VMFile, error) {
|
||||
func (m *HyperVMachine) forwardSocketPath() (*define.VMFile, error) {
|
||||
sockName := "podman.sock"
|
||||
path, err := machine.GetDataDir(machine.HyperVVirt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Resolving data dir: %s", err.Error())
|
||||
}
|
||||
return machine.NewMachineFile(filepath.Join(path, sockName), &sockName)
|
||||
return define.NewMachineFile(filepath.Join(path, sockName), &sockName)
|
||||
}
|
||||
|
||||
func (m *HyperVMachine) writeConfig() error {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package machine
|
||||
package ocipull
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -6,14 +6,13 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/version"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/containers/podman/v4/version"
|
||||
)
|
||||
|
||||
// quay.io/libpod/podman-machine-images:4.6
|
||||
@ -30,9 +29,9 @@ type OSVersion struct {
|
||||
|
||||
type Disker interface {
|
||||
Pull() error
|
||||
Decompress(compressedFile *VMFile) (*VMFile, error)
|
||||
Decompress(compressedFile *define.VMFile) (*define.VMFile, error)
|
||||
DiskEndpoint() string
|
||||
Unpack() (*VMFile, error)
|
||||
Unpack() (*define.VMFile, error)
|
||||
}
|
||||
|
||||
type OCIOpts struct {
|
||||
@ -81,11 +80,11 @@ func (o *OSVersion) majorMinor() string {
|
||||
return fmt.Sprintf("%d.%d", o.Major, o.Minor)
|
||||
}
|
||||
|
||||
func (o *OSVersion) diskImage(diskFlavor ImageFormat) string {
|
||||
return fmt.Sprintf("%s/%s/%s:%s-%s", registry, repo, diskImages, o.majorMinor(), diskFlavor.string())
|
||||
func (o *OSVersion) diskImage(diskFlavor define.ImageFormat) string {
|
||||
return fmt.Sprintf("%s/%s/%s:%s-%s", registry, repo, diskImages, o.majorMinor(), diskFlavor.Kind())
|
||||
}
|
||||
|
||||
func unpackOCIDir(ociTb, machineImageDir string) (*VMFile, error) {
|
||||
func unpackOCIDir(ociTb, machineImageDir string) (*define.VMFile, error) {
|
||||
imageFileName, err := findTarComponent(ociTb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -121,7 +120,7 @@ func unpackOCIDir(ociTb, machineImageDir string) (*VMFile, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewMachineFile(unpackedFileName, nil)
|
||||
return define.NewMachineFile(unpackedFileName, nil)
|
||||
}
|
||||
|
||||
func localOCIDiskImageDir(blobDirPath string, localBlob *types.BlobInfo) string {
|
@ -1,4 +1,4 @@
|
||||
package machine
|
||||
package ocipull
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
@ -11,7 +11,8 @@ import (
|
||||
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/podman/v4/pkg/machine/ocipull"
|
||||
diskcompression "github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -38,7 +39,7 @@ func NewOCIDir(ctx context.Context, inputDir, machineImageDir, vmName string) *L
|
||||
}
|
||||
|
||||
func (l *LocalBlobDir) Pull() error {
|
||||
localBlob, err := ocipull.GetLocalBlob(l.ctx, l.DiskEndpoint())
|
||||
localBlob, err := GetLocalBlob(l.ctx, l.DiskEndpoint())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -46,15 +47,15 @@ func (l *LocalBlobDir) Pull() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LocalBlobDir) Decompress(compressedFile *VMFile) (*VMFile, error) {
|
||||
func (l *LocalBlobDir) Decompress(compressedFile *define.VMFile) (*define.VMFile, error) {
|
||||
finalName := finalFQImagePathName(l.vmName, l.imageName)
|
||||
if err := Decompress(compressedFile, finalName); err != nil {
|
||||
if err := diskcompression.Decompress(compressedFile, finalName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewMachineFile(finalName, nil)
|
||||
return define.NewMachineFile(finalName, nil)
|
||||
}
|
||||
|
||||
func (l *LocalBlobDir) Unpack() (*VMFile, error) {
|
||||
func (l *LocalBlobDir) Unpack() (*define.VMFile, error) {
|
||||
tbPath := localOCIDiskImageDir(l.blobDirPath, l.blob)
|
||||
unPackedFile, err := unpackOCIDir(tbPath, l.machineImageDir)
|
||||
if err != nil {
|
@ -1,4 +1,4 @@
|
||||
package machine
|
||||
package ocipull
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -8,7 +8,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/podman/v4/pkg/machine/ocipull"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -18,14 +20,14 @@ type Versioned struct {
|
||||
blobDirPath string
|
||||
cacheDir string
|
||||
ctx context.Context
|
||||
imageFormat ImageFormat
|
||||
imageFormat define.ImageFormat
|
||||
imageName string
|
||||
machineImageDir string
|
||||
machineVersion *OSVersion
|
||||
vmName string
|
||||
}
|
||||
|
||||
func newVersioned(ctx context.Context, machineImageDir, vmName string) (*Versioned, error) {
|
||||
func NewVersioned(ctx context.Context, machineImageDir, vmName string) (*Versioned, error) {
|
||||
imageCacheDir := filepath.Join(machineImageDir, "cache")
|
||||
if err := os.MkdirAll(imageCacheDir, 0777); err != nil {
|
||||
return nil, err
|
||||
@ -47,7 +49,7 @@ func (d *Versioned) versionedOCICacheDir() string {
|
||||
}
|
||||
|
||||
func (d *Versioned) identifyImageNameFromOCIDir() (string, error) {
|
||||
imageManifest, err := ocipull.ReadImageManifestFromOCIPath(d.ctx, d.versionedOCICacheDir())
|
||||
imageManifest, err := ReadImageManifestFromOCIPath(d.ctx, d.versionedOCICacheDir())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -61,7 +63,7 @@ func (d *Versioned) identifyImageNameFromOCIDir() (string, error) {
|
||||
func (d *Versioned) pull(path string) error {
|
||||
fmt.Printf("Pulling %s\n", d.DiskEndpoint())
|
||||
logrus.Debugf("pulling %s to %s", d.DiskEndpoint(), path)
|
||||
return ocipull.Pull(d.ctx, d.DiskEndpoint(), path, ocipull.PullOptions{})
|
||||
return Pull(d.ctx, d.DiskEndpoint(), path, PullOptions{})
|
||||
}
|
||||
|
||||
func (d *Versioned) Pull() error {
|
||||
@ -72,7 +74,7 @@ func (d *Versioned) Pull() error {
|
||||
remoteDescriptor *v1.Descriptor
|
||||
)
|
||||
|
||||
remoteDiskImage := d.machineVersion.diskImage(Qcow)
|
||||
remoteDiskImage := d.machineVersion.diskImage(define.Qcow)
|
||||
logrus.Debugf("podman disk image name: %s", remoteDiskImage)
|
||||
|
||||
// is there a valid oci dir in our cache
|
||||
@ -80,12 +82,12 @@ func (d *Versioned) Pull() error {
|
||||
|
||||
if hasCache {
|
||||
logrus.Debug("checking remote registry")
|
||||
remoteDescriptor, err = ocipull.GetRemoteDescriptor(d.ctx, remoteDiskImage)
|
||||
remoteDescriptor, err = GetRemoteDescriptor(d.ctx, remoteDiskImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("working with local cache: %s", d.versionedOCICacheDir())
|
||||
localBlob, err = ocipull.GetLocalBlob(d.ctx, d.versionedOCICacheDir())
|
||||
localBlob, err = GetLocalBlob(d.ctx, d.versionedOCICacheDir())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -97,7 +99,7 @@ func (d *Versioned) Pull() error {
|
||||
}
|
||||
if !hasCache || isUpdatable {
|
||||
if hasCache {
|
||||
if err := GuardedRemoveAll(d.versionedOCICacheDir()); err != nil {
|
||||
if err := utils.GuardedRemoveAll(d.versionedOCICacheDir()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -113,7 +115,7 @@ func (d *Versioned) Pull() error {
|
||||
d.imageName = imageName
|
||||
|
||||
if localBlob == nil {
|
||||
localBlob, err = ocipull.GetLocalBlob(d.ctx, d.versionedOCICacheDir())
|
||||
localBlob, err = GetLocalBlob(d.ctx, d.versionedOCICacheDir())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -124,7 +126,7 @@ func (d *Versioned) Pull() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Versioned) Unpack() (*VMFile, error) {
|
||||
func (d *Versioned) Unpack() (*define.VMFile, error) {
|
||||
tbPath := localOCIDiskImageDir(d.blobDirPath, d.blob)
|
||||
unpackedFile, err := unpackOCIDir(tbPath, d.machineImageDir)
|
||||
if err != nil {
|
||||
@ -134,14 +136,14 @@ func (d *Versioned) Unpack() (*VMFile, error) {
|
||||
return unpackedFile, nil
|
||||
}
|
||||
|
||||
func (d *Versioned) Decompress(compressedFile *VMFile) (*VMFile, error) {
|
||||
imageCompression := compressionFromFile(d.imageName)
|
||||
func (d *Versioned) Decompress(compressedFile *define.VMFile) (*define.VMFile, error) {
|
||||
imageCompression := compression.KindFromFile(d.imageName)
|
||||
strippedImageName := strings.TrimSuffix(d.imageName, fmt.Sprintf(".%s", imageCompression.String()))
|
||||
finalName := finalFQImagePathName(d.vmName, strippedImageName)
|
||||
if err := Decompress(compressedFile, finalName); err != nil {
|
||||
if err := compression.Decompress(compressedFile, finalName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewMachineFile(finalName, nil)
|
||||
return define.NewMachineFile(finalName, nil)
|
||||
}
|
||||
|
||||
func (d *Versioned) localOCIDiskImageDir(localBlob *types.BlobInfo) string {
|
@ -4,8 +4,6 @@
|
||||
package machine
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -13,18 +11,15 @@ import (
|
||||
"net/http"
|
||||
url2 "net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/ocipull"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/ulikunitz/xz"
|
||||
"github.com/vbauerster/mpb/v8"
|
||||
"github.com/vbauerster/mpb/v8/decor"
|
||||
)
|
||||
|
||||
// GenericDownload is used when a user provides a URL
|
||||
@ -90,7 +85,7 @@ func supportedURL(path string) (url *url2.URL) {
|
||||
|
||||
func (dl Download) GetLocalUncompressedFile(dataDir string) string {
|
||||
compressedFilename := dl.VMName + "_" + dl.ImageName
|
||||
extension := compressionFromFile(compressedFilename)
|
||||
extension := compression.KindFromFile(compressedFilename)
|
||||
uncompressedFile := strings.TrimSuffix(compressedFilename, fmt.Sprintf(".%s", extension.String()))
|
||||
dl.LocalUncompressedFile = filepath.Join(dataDir, uncompressedFile)
|
||||
return dl.LocalUncompressedFile
|
||||
@ -134,33 +129,11 @@ func DownloadImage(d DistributionDownload) error {
|
||||
}
|
||||
}()
|
||||
}
|
||||
localPath, err := NewMachineFile(d.Get().LocalPath, nil)
|
||||
localPath, err := define.NewMachineFile(d.Get().LocalPath, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return Decompress(localPath, d.Get().LocalUncompressedFile)
|
||||
}
|
||||
|
||||
func progressBar(prefix string, size int64, onComplete string) (*mpb.Progress, *mpb.Bar) {
|
||||
p := mpb.New(
|
||||
mpb.WithWidth(80), // Do not go below 80, see bug #17718
|
||||
mpb.WithRefreshRate(180*time.Millisecond),
|
||||
)
|
||||
|
||||
bar := p.AddBar(size,
|
||||
mpb.BarFillerClearOnComplete(),
|
||||
mpb.PrependDecorators(
|
||||
decor.OnComplete(decor.Name(prefix), onComplete),
|
||||
),
|
||||
mpb.AppendDecorators(
|
||||
decor.OnComplete(decor.CountersKibiByte("%.1f / %.1f"), ""),
|
||||
),
|
||||
)
|
||||
if size == 0 {
|
||||
bar.SetTotal(0, true)
|
||||
}
|
||||
|
||||
return p, bar
|
||||
return compression.Decompress(localPath, d.Get().LocalUncompressedFile)
|
||||
}
|
||||
|
||||
// DownloadVMImage downloads a VM image from url to given path
|
||||
@ -193,7 +166,7 @@ func DownloadVMImage(downloadURL *url2.URL, imageName string, localImagePath str
|
||||
prefix := "Downloading VM image: " + imageName
|
||||
onComplete := prefix + ": done"
|
||||
|
||||
p, bar := progressBar(prefix, size, onComplete)
|
||||
p, bar := utils.ProgressBar(prefix, size, onComplete)
|
||||
|
||||
proxyReader := bar.ProxyReader(resp.Body)
|
||||
defer func() {
|
||||
@ -210,170 +183,6 @@ func DownloadVMImage(downloadURL *url2.URL, imageName string, localImagePath str
|
||||
return nil
|
||||
}
|
||||
|
||||
func Decompress(localPath *VMFile, uncompressedPath string) error {
|
||||
var isZip bool
|
||||
uncompressedFileWriter, err := os.OpenFile(uncompressedPath, os.O_CREATE|os.O_RDWR, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sourceFile, err := localPath.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasSuffix(localPath.GetPath(), ".zip") {
|
||||
isZip = true
|
||||
}
|
||||
prefix := "Copying uncompressed file"
|
||||
compressionType := archive.DetectCompression(sourceFile)
|
||||
if compressionType != archive.Uncompressed || isZip {
|
||||
prefix = "Extracting compressed file"
|
||||
}
|
||||
prefix += ": " + filepath.Base(uncompressedPath)
|
||||
if compressionType == archive.Xz {
|
||||
return decompressXZ(prefix, localPath.GetPath(), uncompressedFileWriter)
|
||||
}
|
||||
if isZip && runtime.GOOS == "windows" {
|
||||
return decompressZip(prefix, localPath.GetPath(), uncompressedFileWriter)
|
||||
}
|
||||
return decompressEverythingElse(prefix, localPath.GetPath(), uncompressedFileWriter)
|
||||
}
|
||||
|
||||
// Will error out if file without .Xz already exists
|
||||
// Maybe extracting then renaming is a good idea here..
|
||||
// depends on Xz: not pre-installed on mac, so it becomes a brew dependency
|
||||
func decompressXZ(prefix string, src string, output io.WriteCloser) error {
|
||||
var read io.Reader
|
||||
var cmd *exec.Cmd
|
||||
|
||||
stat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
p, bar := progressBar(prefix, stat.Size(), prefix+": done")
|
||||
proxyReader := bar.ProxyReader(file)
|
||||
defer func() {
|
||||
if err := proxyReader.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Prefer Xz utils for fastest performance, fallback to go xi2 impl
|
||||
if _, err := exec.LookPath("xz"); err == nil {
|
||||
cmd = exec.Command("xz", "-d", "-c")
|
||||
cmd.Stdin = proxyReader
|
||||
read, err = cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Stderr = os.Stderr
|
||||
} else {
|
||||
// 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(proxyReader)
|
||||
read, err = xz.NewReader(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
if _, err := io.Copy(output, read); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
output.Close()
|
||||
done <- true
|
||||
}()
|
||||
|
||||
if cmd != nil {
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Wait()
|
||||
return cmd.Wait()
|
||||
}
|
||||
<-done
|
||||
p.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func decompressEverythingElse(prefix string, src string, output io.WriteCloser) error {
|
||||
stat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p, bar := progressBar(prefix, stat.Size(), prefix+": done")
|
||||
proxyReader := bar.ProxyReader(f)
|
||||
defer func() {
|
||||
if err := proxyReader.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
uncompressStream, _, err := compression.AutoDecompress(proxyReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := uncompressStream.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if err := output.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(output, uncompressStream)
|
||||
p.Wait()
|
||||
return err
|
||||
}
|
||||
|
||||
func decompressZip(prefix string, src string, output io.WriteCloser) error {
|
||||
zipReader, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(zipReader.File) != 1 {
|
||||
return errors.New("machine image files should consist of a single compressed file")
|
||||
}
|
||||
f, err := zipReader.File[0].Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
if err := output.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
size := int64(zipReader.File[0].CompressedSize64)
|
||||
p, bar := progressBar(prefix, size, prefix+": done")
|
||||
proxyReader := bar.ProxyReader(f)
|
||||
defer func() {
|
||||
if err := proxyReader.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
_, err = io.Copy(output, proxyReader)
|
||||
p.Wait()
|
||||
return err
|
||||
}
|
||||
|
||||
func RemoveImageAfterExpire(dir string, expire time.Duration) error {
|
||||
now := time.Now()
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
@ -393,13 +202,13 @@ func RemoveImageAfterExpire(dir string, expire time.Duration) error {
|
||||
|
||||
// AcquireAlternateImage downloads the alternate image the user provided, which
|
||||
// can be a file path or URL
|
||||
func (dl Download) AcquireAlternateImage(inputPath string) (*VMFile, error) {
|
||||
func (dl Download) AcquireAlternateImage(inputPath string) (*define.VMFile, error) {
|
||||
g, err := NewGenericDownloader(dl.VMKind, dl.VMName, inputPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imagePath, err := NewMachineFile(g.Get().LocalUncompressedFile, nil)
|
||||
imagePath, err := define.NewMachineFile(g.Get().LocalUncompressedFile, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -411,23 +220,23 @@ func (dl Download) AcquireAlternateImage(inputPath string) (*VMFile, error) {
|
||||
return imagePath, nil
|
||||
}
|
||||
|
||||
func isOci(input string) (bool, *OCIKind, error) {
|
||||
func isOci(input string) (bool, *ocipull.OCIKind, error) {
|
||||
inputURL, err := url2.Parse(input)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
switch inputURL.Scheme {
|
||||
case OCIDir.String():
|
||||
return true, &OCIDir, nil
|
||||
case OCIRegistry.String():
|
||||
return true, &OCIRegistry, nil
|
||||
case ocipull.OCIDir.String():
|
||||
return true, &ocipull.OCIDir, nil
|
||||
case ocipull.OCIRegistry.String():
|
||||
return true, &ocipull.OCIRegistry, nil
|
||||
}
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
func Pull(input, machineName string, vp VirtProvider) (*VMFile, FCOSStream, error) {
|
||||
func Pull(input, machineName string, vp VirtProvider) (*define.VMFile, FCOSStream, error) {
|
||||
var (
|
||||
disk Disker
|
||||
disk ocipull.Disker
|
||||
)
|
||||
|
||||
ociBased, ociScheme, err := isOci(input)
|
||||
@ -442,7 +251,7 @@ func Pull(input, machineName string, vp VirtProvider) (*VMFile, FCOSStream, erro
|
||||
}
|
||||
return dl.AcquireVMImage(input)
|
||||
}
|
||||
oopts := OCIOpts{
|
||||
oopts := ocipull.OCIOpts{
|
||||
Scheme: ociScheme,
|
||||
}
|
||||
dataDir, err := GetDataDir(vp.VMType())
|
||||
@ -450,9 +259,9 @@ func Pull(input, machineName string, vp VirtProvider) (*VMFile, FCOSStream, erro
|
||||
return nil, 0, err
|
||||
}
|
||||
if ociScheme.IsOCIDir() {
|
||||
strippedOCIDir := StripOCIReference(input)
|
||||
strippedOCIDir := ocipull.StripOCIReference(input)
|
||||
oopts.Dir = &strippedOCIDir
|
||||
disk = NewOCIDir(context.Background(), input, dataDir, machineName)
|
||||
disk = ocipull.NewOCIDir(context.Background(), input, dataDir, machineName)
|
||||
} else {
|
||||
// a use of a containers image type here might be
|
||||
// tighter
|
||||
@ -461,7 +270,7 @@ func Pull(input, machineName string, vp VirtProvider) (*VMFile, FCOSStream, erro
|
||||
if len(strippedInput) > 0 {
|
||||
return nil, 0, errors.New("image names are not supported yet")
|
||||
}
|
||||
disk, err = newVersioned(context.Background(), dataDir, machineName)
|
||||
disk, err = ocipull.NewVersioned(context.Background(), dataDir, machineName)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
)
|
||||
|
||||
// QemuCmd is an alias around a string slice to prevent the need to migrate the
|
||||
@ -30,7 +30,7 @@ func (q *QemuCmd) SetCPUs(c uint64) {
|
||||
}
|
||||
|
||||
// SetIgnitionFile specifies the machine's ignition file
|
||||
func (q *QemuCmd) SetIgnitionFile(file machine.VMFile) {
|
||||
func (q *QemuCmd) SetIgnitionFile(file define.VMFile) {
|
||||
*q = append(*q, "-fw_cfg", "name=opt/com.coreos/config,file="+file.GetPath())
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ func (q *QemuCmd) SetNetwork() {
|
||||
}
|
||||
|
||||
// SetSerialPort adds a serial port to the machine for readiness
|
||||
func (q *QemuCmd) SetSerialPort(readySocket, vmPidFile machine.VMFile, name string) {
|
||||
func (q *QemuCmd) SetSerialPort(readySocket, vmPidFile define.VMFile, name string) {
|
||||
*q = append(*q,
|
||||
"-device", "virtio-serial",
|
||||
// qemu needs to establish the long name; other connections can use the symlink'd
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -77,14 +79,14 @@ func (p *QEMUVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, e
|
||||
}
|
||||
|
||||
// set VM ignition file
|
||||
ignitionFile, err := machine.NewMachineFile(filepath.Join(vmConfigDir, vm.Name+".ign"), nil)
|
||||
ignitionFile, err := define.NewMachineFile(filepath.Join(vmConfigDir, vm.Name+".ign"), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vm.IgnitionFile = *ignitionFile
|
||||
|
||||
// set VM image file
|
||||
imagePath, err := machine.NewMachineFile(opts.ImagePath, nil)
|
||||
imagePath, err := define.NewMachineFile(opts.ImagePath, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -299,7 +301,7 @@ func (p *QEMUVirtualization) RemoveAndCleanMachines() error {
|
||||
}
|
||||
prevErr = err
|
||||
} else {
|
||||
err := machine.GuardedRemoveAll(dataDir)
|
||||
err := utils.GuardedRemoveAll(dataDir)
|
||||
if err != nil {
|
||||
if prevErr != nil {
|
||||
logrus.Error(prevErr)
|
||||
@ -316,7 +318,7 @@ func (p *QEMUVirtualization) RemoveAndCleanMachines() error {
|
||||
}
|
||||
prevErr = err
|
||||
} else {
|
||||
err := machine.GuardedRemoveAll(confDir)
|
||||
err := utils.GuardedRemoveAll(confDir)
|
||||
if err != nil {
|
||||
if prevErr != nil {
|
||||
logrus.Error(prevErr)
|
||||
@ -333,7 +335,7 @@ func (p *QEMUVirtualization) VMType() machine.VMType {
|
||||
|
||||
func VirtualizationProvider() machine.VirtProvider {
|
||||
return &QEMUVirtualization{
|
||||
machine.NewVirtualization(machine.Qemu, machine.Xz, machine.Qcow, vmtype),
|
||||
machine.NewVirtualization(define.Qemu, compression.Xz, define.Qcow, vmtype),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"github.com/containers/common/pkg/config"
|
||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/rootless"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
@ -46,7 +47,7 @@ const (
|
||||
|
||||
type MachineVM struct {
|
||||
// ConfigPath is the path to the configuration file
|
||||
ConfigPath machine.VMFile
|
||||
ConfigPath define.VMFile
|
||||
// The command line representation of the qemu command
|
||||
CmdLine QemuCmd
|
||||
// HostUser contains info about host user
|
||||
@ -58,13 +59,13 @@ type MachineVM struct {
|
||||
// Name of VM
|
||||
Name string
|
||||
// PidFilePath is the where the Proxy PID file lives
|
||||
PidFilePath machine.VMFile
|
||||
PidFilePath define.VMFile
|
||||
// VMPidFilePath is the where the VM PID file lives
|
||||
VMPidFilePath machine.VMFile
|
||||
VMPidFilePath define.VMFile
|
||||
// QMPMonitor is the qemu monitor object for sending commands
|
||||
QMPMonitor Monitor
|
||||
// ReadySocket tells host when vm is booted
|
||||
ReadySocket machine.VMFile
|
||||
ReadySocket define.VMFile
|
||||
// ResourceConfig is physical attrs of the VM
|
||||
machine.ResourceConfig
|
||||
// SSHConfig for accessing the remote vm
|
||||
@ -82,7 +83,7 @@ type MachineVM struct {
|
||||
|
||||
type Monitor struct {
|
||||
// Address portion of the qmp monitor (/tmp/tmp.sock)
|
||||
Address machine.VMFile
|
||||
Address define.VMFile
|
||||
// Network portion of the qmp monitor (unix)
|
||||
Network string
|
||||
// Timeout in seconds for qmp monitor transactions
|
||||
@ -105,9 +106,9 @@ func migrateVM(configPath string, config []byte, vm *MachineVM) error {
|
||||
return err
|
||||
}
|
||||
|
||||
pidFilePath := machine.VMFile{Path: pidFile}
|
||||
pidFilePath := define.VMFile{Path: pidFile}
|
||||
qmpMonitor := Monitor{
|
||||
Address: machine.VMFile{Path: old.QMPMonitor.Address},
|
||||
Address: define.VMFile{Path: old.QMPMonitor.Address},
|
||||
Network: old.QMPMonitor.Network,
|
||||
Timeout: old.QMPMonitor.Timeout,
|
||||
}
|
||||
@ -116,18 +117,18 @@ func migrateVM(configPath string, config []byte, vm *MachineVM) error {
|
||||
return err
|
||||
}
|
||||
virtualSocketPath := filepath.Join(socketPath, "podman", vm.Name+"_ready.sock")
|
||||
readySocket := machine.VMFile{Path: virtualSocketPath}
|
||||
readySocket := define.VMFile{Path: virtualSocketPath}
|
||||
|
||||
vm.HostUser = machine.HostUser{}
|
||||
vm.ImageConfig = machine.ImageConfig{}
|
||||
vm.ResourceConfig = machine.ResourceConfig{}
|
||||
vm.SSHConfig = machine.SSHConfig{}
|
||||
|
||||
ignitionFilePath, err := machine.NewMachineFile(old.IgnitionFilePath, nil)
|
||||
ignitionFilePath, err := define.NewMachineFile(old.IgnitionFilePath, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imagePath, err := machine.NewMachineFile(old.ImagePath, nil)
|
||||
imagePath, err := define.NewMachineFile(old.ImagePath, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1030,7 +1031,7 @@ func NewQMPMonitor(network, name string, timeout time.Duration) (Monitor, error)
|
||||
if timeout == 0 {
|
||||
timeout = defaultQMPTimeout
|
||||
}
|
||||
address, err := machine.NewMachineFile(filepath.Join(rtDir, "qmp_"+name+".sock"), nil)
|
||||
address, err := define.NewMachineFile(filepath.Join(rtDir, "qmp_"+name+".sock"), nil)
|
||||
if err != nil {
|
||||
return Monitor{}, err
|
||||
}
|
||||
@ -1350,14 +1351,14 @@ func (v *MachineVM) userGlobalSocketLink() (string, error) {
|
||||
return filepath.Join(filepath.Dir(path), "podman.sock"), err
|
||||
}
|
||||
|
||||
func (v *MachineVM) forwardSocketPath() (*machine.VMFile, error) {
|
||||
func (v *MachineVM) forwardSocketPath() (*define.VMFile, error) {
|
||||
sockName := "podman.sock"
|
||||
path, err := machine.GetDataDir(machine.QemuVirt)
|
||||
if err != nil {
|
||||
logrus.Errorf("Resolving data dir: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return machine.NewMachineFile(filepath.Join(path, sockName), &sockName)
|
||||
return define.NewMachineFile(filepath.Join(path, sockName), &sockName)
|
||||
}
|
||||
|
||||
func (v *MachineVM) setConfigPath() error {
|
||||
@ -1366,7 +1367,7 @@ func (v *MachineVM) setConfigPath() error {
|
||||
return err
|
||||
}
|
||||
|
||||
configPath, err := machine.NewMachineFile(filepath.Join(vmConfigDir, v.Name)+".json", nil)
|
||||
configPath, err := define.NewMachineFile(filepath.Join(vmConfigDir, v.Name)+".json", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1385,11 +1386,11 @@ func (v *MachineVM) setPIDSocket() error {
|
||||
socketDir := filepath.Join(rtPath, "podman")
|
||||
vmPidFileName := fmt.Sprintf("%s_vm.pid", v.Name)
|
||||
proxyPidFileName := fmt.Sprintf("%s_proxy.pid", v.Name)
|
||||
vmPidFilePath, err := machine.NewMachineFile(filepath.Join(socketDir, vmPidFileName), &vmPidFileName)
|
||||
vmPidFilePath, err := define.NewMachineFile(filepath.Join(socketDir, vmPidFileName), &vmPidFileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
proxyPidFilePath, err := machine.NewMachineFile(filepath.Join(socketDir, proxyPidFileName), &proxyPidFileName)
|
||||
proxyPidFilePath, err := define.NewMachineFile(filepath.Join(socketDir, proxyPidFileName), &proxyPidFileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -7,22 +7,22 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestQemuCmd(t *testing.T) {
|
||||
ignFile, err := machine.NewMachineFile(t.TempDir()+"demo-ignition-file.ign", nil)
|
||||
ignFile, err := define.NewMachineFile(t.TempDir()+"demo-ignition-file.ign", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
machineAddrFile, err := machine.NewMachineFile(t.TempDir()+"tmp.sock", nil)
|
||||
machineAddrFile, err := define.NewMachineFile(t.TempDir()+"tmp.sock", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
readySocket, err := machine.NewMachineFile(t.TempDir()+"readySocket.sock", nil)
|
||||
readySocket, err := define.NewMachineFile(t.TempDir()+"readySocket.sock", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
vmPidFile, err := machine.NewMachineFile(t.TempDir()+"vmpidfile.pid", nil)
|
||||
vmPidFile, err := define.NewMachineFile(t.TempDir()+"vmpidfile.pid", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
monitor := Monitor{
|
||||
|
@ -7,12 +7,14 @@ import (
|
||||
"net"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
)
|
||||
|
||||
// SetSocket creates a new machine file for the socket and assigns it to
|
||||
// `socketLoc`
|
||||
func SetSocket(socketLoc *VMFile, path string, symlink *string) error {
|
||||
socket, err := NewMachineFile(path, symlink)
|
||||
func SetSocket(socketLoc *define.VMFile, path string, symlink *string) error {
|
||||
socket, err := define.NewMachineFile(path, symlink)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -10,6 +10,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -19,7 +22,7 @@ type WSLVirtualization struct {
|
||||
|
||||
func VirtualizationProvider() machine.VirtProvider {
|
||||
return &WSLVirtualization{
|
||||
machine.NewVirtualization(machine.None, machine.Xz, machine.Tar, vmtype),
|
||||
machine.NewVirtualization(define.None, compression.Xz, define.Tar, vmtype),
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +199,7 @@ func (p *WSLVirtualization) RemoveAndCleanMachines() error {
|
||||
}
|
||||
prevErr = err
|
||||
} else {
|
||||
err := machine.GuardedRemoveAll(dataDir)
|
||||
err := utils.GuardedRemoveAll(dataDir)
|
||||
if err != nil {
|
||||
if prevErr != nil {
|
||||
logrus.Error(prevErr)
|
||||
@ -213,7 +216,7 @@ func (p *WSLVirtualization) RemoveAndCleanMachines() error {
|
||||
}
|
||||
prevErr = err
|
||||
} else {
|
||||
err := machine.GuardedRemoveAll(confDir)
|
||||
err := utils.GuardedRemoveAll(confDir)
|
||||
if err != nil {
|
||||
if prevErr != nil {
|
||||
logrus.Error(prevErr)
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -43,9 +44,9 @@ func NewFedoraDownloader(vmType machine.VMType, vmName, releaseStream string) (m
|
||||
f := FedoraDownload{
|
||||
Download: machine.Download{
|
||||
Arch: machine.GetFcosArch(),
|
||||
Artifact: machine.None,
|
||||
Artifact: define.None,
|
||||
CacheDir: cacheDir,
|
||||
Format: machine.Tar,
|
||||
Format: define.Tar,
|
||||
ImageName: imageName,
|
||||
LocalPath: filepath.Join(cacheDir, imageName),
|
||||
URL: downloadURL,
|
||||
|
@ -19,8 +19,10 @@ import (
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/wsl/wutil"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
"github.com/containers/storage/pkg/homedir"
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -480,22 +482,22 @@ func (v *MachineVM) unprovisionWSL() error {
|
||||
}
|
||||
distDir := filepath.Join(vmDataDir, "wsldist")
|
||||
distTarget := filepath.Join(distDir, v.Name)
|
||||
return machine.GuardedRemoveAll(distTarget)
|
||||
return utils.GuardedRemoveAll(distTarget)
|
||||
}
|
||||
|
||||
func (v *MachineVM) removeMachineConfig() error {
|
||||
return machine.GuardedRemoveAll(v.ConfigPath)
|
||||
return utils.GuardedRemoveAll(v.ConfigPath)
|
||||
}
|
||||
|
||||
func (v *MachineVM) removeMachineImage() error {
|
||||
return machine.GuardedRemoveAll(v.ImagePath)
|
||||
return utils.GuardedRemoveAll(v.ImagePath)
|
||||
}
|
||||
|
||||
func (v *MachineVM) removeSSHKeys() error {
|
||||
if err := machine.GuardedRemoveAll(fmt.Sprintf("%s.pub", v.IdentityPath)); err != nil {
|
||||
if err := utils.GuardedRemoveAll(fmt.Sprintf("%s.pub", v.IdentityPath)); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
return machine.GuardedRemoveAll(v.IdentityPath)
|
||||
return utils.GuardedRemoveAll(v.IdentityPath)
|
||||
}
|
||||
|
||||
func (v *MachineVM) removeSystemConnections() error {
|
||||
@ -1635,7 +1637,7 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun
|
||||
logrus.Error(err)
|
||||
}
|
||||
for _, f := range files {
|
||||
if err := machine.GuardedRemoveAll(f); err != nil {
|
||||
if err := utils.GuardedRemoveAll(f); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
@ -1804,15 +1806,15 @@ func (v *MachineVM) Inspect() (*machine.InspectInfo, error) {
|
||||
|
||||
connInfo := new(machine.ConnectionConfig)
|
||||
machinePipe := toDist(v.Name)
|
||||
connInfo.PodmanPipe = &machine.VMFile{Path: `\\.\pipe\` + machinePipe}
|
||||
connInfo.PodmanPipe = &define.VMFile{Path: `\\.\pipe\` + machinePipe}
|
||||
|
||||
created, lastUp, _ := v.updateTimeStamps(state == machine.Running)
|
||||
return &machine.InspectInfo{
|
||||
ConfigPath: machine.VMFile{Path: v.ConfigPath},
|
||||
ConfigPath: define.VMFile{Path: v.ConfigPath},
|
||||
ConnectionInfo: *connInfo,
|
||||
Created: created,
|
||||
Image: machine.ImageConfig{
|
||||
ImagePath: machine.VMFile{Path: v.ImagePath},
|
||||
ImagePath: define.VMFile{Path: v.ImagePath},
|
||||
ImageStream: v.ImageStream,
|
||||
},
|
||||
LastUp: lastUp,
|
||||
|
@ -10,12 +10,15 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/pkg/cgroups"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/chrootarchive"
|
||||
"github.com/godbus/dbus/v5"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vbauerster/mpb/v8"
|
||||
"github.com/vbauerster/mpb/v8/decor"
|
||||
)
|
||||
|
||||
// ExecCmd executes a command with args and returns its output as a string along
|
||||
@ -242,3 +245,34 @@ func MaybeMoveToSubCgroup() error {
|
||||
})
|
||||
return maybeMoveToSubCgroupSyncErr
|
||||
}
|
||||
|
||||
// GuardedRemoveAll functions much like os.RemoveAll but
|
||||
// will not delete certain catastrophic paths.
|
||||
func GuardedRemoveAll(path string) error {
|
||||
if path == "" || path == "/" {
|
||||
return fmt.Errorf("refusing to recursively delete `%s`", path)
|
||||
}
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
func ProgressBar(prefix string, size int64, onComplete string) (*mpb.Progress, *mpb.Bar) {
|
||||
p := mpb.New(
|
||||
mpb.WithWidth(80), // Do not go below 80, see bug #17718
|
||||
mpb.WithRefreshRate(180*time.Millisecond),
|
||||
)
|
||||
|
||||
bar := p.AddBar(size,
|
||||
mpb.BarFillerClearOnComplete(),
|
||||
mpb.PrependDecorators(
|
||||
decor.OnComplete(decor.Name(prefix), onComplete),
|
||||
),
|
||||
mpb.AppendDecorators(
|
||||
decor.OnComplete(decor.CountersKibiByte("%.1f / %.1f"), ""),
|
||||
),
|
||||
)
|
||||
if size == 0 {
|
||||
bar.SetTotal(0, true)
|
||||
}
|
||||
|
||||
return p, bar
|
||||
}
|
||||
|
Reference in New Issue
Block a user