mirror of
				https://github.com/containers/podman.git
				synced 2025-10-26 02:35:43 +08:00 
			
		
		
		
	 fa4f11facc
			
		
	
	fa4f11facc
	
	
	
		
			
			Includes fixes for new lint warnings from unparam and usestdlibvars. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
		
			
				
	
	
		
			276 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build amd64 || arm64
 | |
| 
 | |
| package machine
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"net"
 | |
| 	"net/http"
 | |
| 	"net/url"
 | |
| 	"os"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/containers/common/pkg/strongunits"
 | |
| 	"github.com/containers/podman/v5/pkg/machine/compression"
 | |
| 	"github.com/containers/podman/v5/pkg/machine/define"
 | |
| 	"github.com/containers/podman/v5/pkg/machine/env"
 | |
| 	"github.com/containers/podman/v5/pkg/machine/vmconfigs"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	DefaultMachineName string = "podman-machine-default"
 | |
| 	apiUpTimeout              = 20 * time.Second
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	ForwarderBinaryName = "gvproxy"
 | |
| )
 | |
| 
 | |
| type Download struct {
 | |
| 	Arch                  string
 | |
| 	Artifact              define.Artifact
 | |
| 	CacheDir              string
 | |
| 	CompressionType       compression.ImageCompression
 | |
| 	DataDir               string
 | |
| 	Format                define.ImageFormat
 | |
| 	ImageName             string
 | |
| 	LocalPath             string
 | |
| 	LocalUncompressedFile string
 | |
| 	Sha256sum             string
 | |
| 	Size                  int64
 | |
| 	URL                   *url.URL
 | |
| 	VMKind                define.VMType
 | |
| 	VMName                string
 | |
| }
 | |
| 
 | |
| type ListOptions struct{}
 | |
| 
 | |
| type ListResponse struct {
 | |
| 	Name               string
 | |
| 	CreatedAt          time.Time
 | |
| 	LastUp             time.Time
 | |
| 	Running            bool
 | |
| 	Starting           bool
 | |
| 	Stream             string
 | |
| 	VMType             string
 | |
| 	CPUs               uint64
 | |
| 	Memory             strongunits.MiB
 | |
| 	DiskSize           strongunits.GiB
 | |
| 	Port               int
 | |
| 	RemoteUsername     string
 | |
| 	IdentityPath       string
 | |
| 	UserModeNetworking bool
 | |
| }
 | |
| 
 | |
| type SSHOptions struct {
 | |
| 	Username string
 | |
| 	Args     []string
 | |
| }
 | |
| 
 | |
| type StartOptions struct {
 | |
| 	NoInfo  bool
 | |
| 	Quiet   bool
 | |
| 	Rosetta bool
 | |
| }
 | |
| 
 | |
| type StopOptions struct{}
 | |
| 
 | |
| type RemoveOptions struct {
 | |
| 	Force        bool
 | |
| 	SaveImage    bool
 | |
| 	SaveIgnition bool
 | |
| }
 | |
| 
 | |
| type ResetOptions struct {
 | |
| 	Force bool
 | |
| }
 | |
| 
 | |
| type InspectOptions struct{}
 | |
| 
 | |
| // TODO This can be removed when WSL is refactored into podman 5
 | |
| type VM interface {
 | |
| 	Init(opts define.InitOptions) (bool, error)
 | |
| 	Inspect() (*InspectInfo, error)
 | |
| 	Remove(name string, opts RemoveOptions) (string, func() error, error)
 | |
| 	Set(name string, opts define.SetOptions) ([]error, error)
 | |
| 	SSH(name string, opts SSHOptions) error
 | |
| 	Start(name string, opts StartOptions) error
 | |
| 	State(bypass bool) (define.Status, error)
 | |
| 	Stop(name string, opts StopOptions) error
 | |
| }
 | |
| 
 | |
| type DistributionDownload interface {
 | |
| 	HasUsableCache() (bool, error)
 | |
| 	Get() *Download
 | |
| 	CleanCache() error
 | |
| }
 | |
| type InspectInfo struct {
 | |
| 	ConfigDir          define.VMFile
 | |
| 	ConnectionInfo     ConnectionConfig
 | |
| 	Created            time.Time
 | |
| 	LastUp             time.Time
 | |
| 	Name               string
 | |
| 	Resources          vmconfigs.ResourceConfig
 | |
| 	SSHConfig          vmconfigs.SSHConfig
 | |
| 	State              define.Status
 | |
| 	UserModeNetworking bool
 | |
| 	Rootful            bool
 | |
| 	Rosetta            bool
 | |
| }
 | |
| 
 | |
| // ImageConfig describes the bootable image for the VM
 | |
| type ImageConfig struct {
 | |
| 	// IgnitionFile is the path to the filesystem where the
 | |
| 	// ignition file was written (if needs one)
 | |
| 	IgnitionFile define.VMFile `json:"IgnitionFilePath"`
 | |
| 	// ImageStream is the update stream for the image
 | |
| 	ImageStream string
 | |
| 	// ImageFile is the fq path to
 | |
| 	ImagePath define.VMFile `json:"ImagePath"`
 | |
| }
 | |
| 
 | |
| // ConnectionConfig contains connections like sockets, etc.
 | |
| type ConnectionConfig struct {
 | |
| 	// PodmanSocket is the exported podman service socket
 | |
| 	PodmanSocket *define.VMFile `json:"PodmanSocket"`
 | |
| 	// PodmanPipe is the exported podman service named pipe (Windows hosts only)
 | |
| 	PodmanPipe *define.VMFile `json:"PodmanPipe"`
 | |
| }
 | |
| 
 | |
| type APIForwardingState int
 | |
| 
 | |
| const (
 | |
| 	NoForwarding APIForwardingState = iota
 | |
| 	ClaimUnsupported
 | |
| 	NotInstalled
 | |
| 	MachineLocal
 | |
| 	DockerGlobal
 | |
| )
 | |
| 
 | |
| // TODO THis should be able to be removed once WSL is refactored for podman5
 | |
| type Virtualization struct {
 | |
| 	artifact    define.Artifact
 | |
| 	compression compression.ImageCompression
 | |
| 	format      define.ImageFormat
 | |
| 	vmKind      define.VMType
 | |
| }
 | |
| 
 | |
| func (p *Virtualization) Artifact() define.Artifact {
 | |
| 	return p.artifact
 | |
| }
 | |
| 
 | |
| func (p *Virtualization) Compression() compression.ImageCompression {
 | |
| 	return p.compression
 | |
| }
 | |
| 
 | |
| func (p *Virtualization) Format() define.ImageFormat {
 | |
| 	return p.format
 | |
| }
 | |
| 
 | |
| func (p *Virtualization) VMType() define.VMType {
 | |
| 	return p.vmKind
 | |
| }
 | |
| 
 | |
| func (p *Virtualization) NewDownload(vmName string) (Download, error) {
 | |
| 	cacheDir, err := env.GetCacheDir(p.VMType())
 | |
| 	if err != nil {
 | |
| 		return Download{}, err
 | |
| 	}
 | |
| 
 | |
| 	dataDir, err := env.GetDataDir(p.VMType())
 | |
| 	if err != nil {
 | |
| 		return Download{}, err
 | |
| 	}
 | |
| 
 | |
| 	return Download{
 | |
| 		Artifact:        p.Artifact(),
 | |
| 		CacheDir:        cacheDir,
 | |
| 		CompressionType: p.Compression(),
 | |
| 		DataDir:         dataDir,
 | |
| 		Format:          p.Format(),
 | |
| 		VMKind:          p.VMType(),
 | |
| 		VMName:          vmName,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func NewVirtualization(artifact define.Artifact, compression compression.ImageCompression, format define.ImageFormat, vmKind define.VMType) Virtualization {
 | |
| 	return Virtualization{
 | |
| 		artifact,
 | |
| 		compression,
 | |
| 		format,
 | |
| 		vmKind,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func dialSocket(socket string, timeout time.Duration) (net.Conn, error) {
 | |
| 	scheme := "unix"
 | |
| 	if strings.Contains(socket, "://") {
 | |
| 		url, err := url.Parse(socket)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		scheme = url.Scheme
 | |
| 		socket = url.Path
 | |
| 	}
 | |
| 
 | |
| 	ctx, cancel := context.WithTimeout(context.Background(), timeout)
 | |
| 	defer cancel()
 | |
| 	var dial func() (net.Conn, error)
 | |
| 	switch scheme {
 | |
| 	default:
 | |
| 		fallthrough
 | |
| 	case "unix":
 | |
| 		dial = func() (net.Conn, error) {
 | |
| 			var dialer net.Dialer
 | |
| 			return dialer.DialContext(ctx, "unix", socket)
 | |
| 		}
 | |
| 	case "npipe":
 | |
| 		dial = func() (net.Conn, error) {
 | |
| 			return DialNamedPipe(ctx, socket)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	backoff := 500 * time.Millisecond
 | |
| 	for {
 | |
| 		conn, err := dial()
 | |
| 		if !errors.Is(err, os.ErrNotExist) {
 | |
| 			return conn, err
 | |
| 		}
 | |
| 
 | |
| 		select {
 | |
| 		case <-time.After(backoff):
 | |
| 			backoff *= 2
 | |
| 		case <-ctx.Done():
 | |
| 			return nil, ctx.Err()
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func WaitAndPingAPI(sock string) {
 | |
| 	client := http.Client{
 | |
| 		Transport: &http.Transport{
 | |
| 			DialContext: func(context.Context, string, string) (net.Conn, error) {
 | |
| 				con, err := dialSocket(sock, apiUpTimeout)
 | |
| 				if err != nil {
 | |
| 					return nil, err
 | |
| 				}
 | |
| 				if err := con.SetDeadline(time.Now().Add(apiUpTimeout)); err != nil {
 | |
| 					return nil, err
 | |
| 				}
 | |
| 				return con, nil
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	resp, err := client.Get("http://host/_ping")
 | |
| 	if err == nil {
 | |
| 		defer resp.Body.Close()
 | |
| 	}
 | |
| 	if err != nil || resp.StatusCode != http.StatusOK {
 | |
| 		logrus.Warn("API socket failed ping test")
 | |
| 	}
 | |
| }
 |