github.com/containers/podman/v4@v4.9.4/pkg/machine/applehv/config.go (about)

     1  //go:build darwin
     2  // +build darwin
     3  
     4  package applehv
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"io/fs"
    10  	"path/filepath"
    11  	"time"
    12  
    13  	"github.com/containers/podman/v4/pkg/machine"
    14  	"github.com/containers/podman/v4/pkg/machine/compression"
    15  	"github.com/containers/podman/v4/pkg/machine/define"
    16  	vfConfig "github.com/crc-org/vfkit/pkg/config"
    17  	"github.com/docker/go-units"
    18  	"golang.org/x/sys/unix"
    19  )
    20  
    21  const (
    22  	localhostURI       = "http://localhost"
    23  	ignitionSocketName = "ignition.sock"
    24  )
    25  
    26  type AppleHVVirtualization struct {
    27  	machine.Virtualization
    28  }
    29  
    30  type MMHardwareConfig struct {
    31  	CPUs     uint16
    32  	DiskPath string
    33  	DiskSize uint64
    34  	Memory   int32
    35  }
    36  
    37  func VirtualizationProvider() machine.VirtProvider {
    38  	return &AppleHVVirtualization{
    39  		machine.NewVirtualization(define.AppleHV, compression.Xz, define.Raw, vmtype),
    40  	}
    41  }
    42  
    43  func (v AppleHVVirtualization) CheckExclusiveActiveVM() (bool, string, error) {
    44  	fsVms, err := getVMInfos()
    45  	if err != nil {
    46  		return false, "", err
    47  	}
    48  	for _, vm := range fsVms {
    49  		if vm.Running || vm.Starting {
    50  			return true, vm.Name, nil
    51  		}
    52  	}
    53  
    54  	return false, "", nil
    55  }
    56  
    57  func (v AppleHVVirtualization) IsValidVMName(name string) (bool, error) {
    58  	configDir, err := machine.GetConfDir(machine.AppleHvVirt)
    59  	if err != nil {
    60  		return false, err
    61  	}
    62  	fqName := filepath.Join(configDir, fmt.Sprintf("%s.json", name))
    63  	if _, err := loadMacMachineFromJSON(fqName); err != nil {
    64  		return false, err
    65  	}
    66  	return true, nil
    67  }
    68  
    69  func (v AppleHVVirtualization) List(opts machine.ListOptions) ([]*machine.ListResponse, error) {
    70  	var (
    71  		response []*machine.ListResponse
    72  	)
    73  
    74  	mms, err := v.loadFromLocalJson()
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	for _, mm := range mms {
    80  		vmState, err := mm.Vfkit.state()
    81  		if err != nil {
    82  			if errors.Is(err, unix.ECONNREFUSED) {
    83  				vmState = machine.Stopped
    84  			} else {
    85  				return nil, err
    86  			}
    87  		}
    88  
    89  		mlr := machine.ListResponse{
    90  			Name:           mm.Name,
    91  			CreatedAt:      mm.Created,
    92  			LastUp:         mm.LastUp,
    93  			Running:        vmState == machine.Running,
    94  			Starting:       vmState == machine.Starting,
    95  			Stream:         mm.ImageStream,
    96  			VMType:         machine.AppleHvVirt.String(),
    97  			CPUs:           mm.CPUs,
    98  			Memory:         mm.Memory * units.MiB,
    99  			DiskSize:       mm.DiskSize * units.GiB,
   100  			Port:           mm.Port,
   101  			RemoteUsername: mm.RemoteUsername,
   102  			IdentityPath:   mm.IdentityPath,
   103  		}
   104  		response = append(response, &mlr)
   105  	}
   106  	return response, nil
   107  }
   108  
   109  func (v AppleHVVirtualization) LoadVMByName(name string) (machine.VM, error) {
   110  	m := MacMachine{Name: name}
   111  	return m.loadFromFile()
   112  }
   113  
   114  func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) {
   115  	m := MacMachine{Name: opts.Name}
   116  
   117  	if len(opts.USBs) > 0 {
   118  		return nil, fmt.Errorf("USB host passtrough not supported for applehv machines")
   119  	}
   120  
   121  	configDir, err := machine.GetConfDir(machine.AppleHvVirt)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	configPath, err := define.NewMachineFile(getVMConfigPath(configDir, opts.Name), nil)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	m.ConfigPath = *configPath
   131  
   132  	dataDir, err := machine.GetDataDir(machine.AppleHvVirt)
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  
   137  	if err := machine.SetIgnitionFile(&m.IgnitionFile, vmtype, m.Name); err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	// Set creation time
   142  	m.Created = time.Now()
   143  
   144  	m.ResourceConfig = machine.ResourceConfig{
   145  		CPUs:     opts.CPUS,
   146  		DiskSize: opts.DiskSize,
   147  		// Diskpath will be needed
   148  		Memory: opts.Memory,
   149  	}
   150  	bl := vfConfig.NewEFIBootloader(fmt.Sprintf("%s/%ss", dataDir, opts.Name), true)
   151  	m.Vfkit.VirtualMachine = vfConfig.NewVirtualMachine(uint(opts.CPUS), opts.Memory, bl)
   152  
   153  	if err := m.writeConfig(); err != nil {
   154  		return nil, err
   155  	}
   156  	return m.loadFromFile()
   157  }
   158  
   159  func (v AppleHVVirtualization) RemoveAndCleanMachines() error {
   160  	// This can be implemented when host networking is completed.
   161  	return machine.ErrNotImplemented
   162  }
   163  
   164  func (v AppleHVVirtualization) VMType() machine.VMType {
   165  	return vmtype
   166  }
   167  
   168  func (v AppleHVVirtualization) loadFromLocalJson() ([]*MacMachine, error) {
   169  	var (
   170  		jsonFiles []string
   171  		mms       []*MacMachine
   172  	)
   173  	configDir, err := machine.GetConfDir(v.VMType())
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  	if err := filepath.WalkDir(configDir, func(input string, d fs.DirEntry, e error) error {
   178  		if e != nil {
   179  			return e
   180  		}
   181  		if filepath.Ext(d.Name()) == ".json" {
   182  			jsonFiles = append(jsonFiles, input)
   183  		}
   184  		return nil
   185  	}); err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	for _, jsonFile := range jsonFiles {
   190  		mm, err := loadMacMachineFromJSON(jsonFile)
   191  		if err != nil {
   192  			return nil, err
   193  		}
   194  		if err != nil {
   195  			return nil, err
   196  		}
   197  		mms = append(mms, mm)
   198  	}
   199  	return mms, nil
   200  }