podman/pkg/machine/applehv/config.go

197 lines
4.4 KiB
Go

//go:build darwin
// +build darwin
package applehv
import (
"errors"
"fmt"
"io/fs"
"path/filepath"
"time"
"github.com/containers/podman/v4/pkg/machine"
vfConfig "github.com/crc-org/vfkit/pkg/config"
"github.com/docker/go-units"
"golang.org/x/sys/unix"
)
const (
defaultVFKitEndpoint = "http://localhost:8081"
ignitionSocketName = "ignition.sock"
)
type AppleHVVirtualization struct {
machine.Virtualization
}
type MMHardwareConfig struct {
CPUs uint16
DiskPath string
DiskSize uint64
Memory int32
}
func VirtualizationProvider() machine.VirtProvider {
return &AppleHVVirtualization{
machine.NewVirtualization(machine.AppleHV, machine.Xz, machine.Raw, vmtype),
}
}
func (v AppleHVVirtualization) CheckExclusiveActiveVM() (bool, string, error) {
fsVms, err := getVMInfos()
if err != nil {
return false, "", err
}
for _, vm := range fsVms {
if vm.Running || vm.Starting {
return true, vm.Name, nil
}
}
return false, "", nil
}
func (v AppleHVVirtualization) IsValidVMName(name string) (bool, error) {
mm := MacMachine{Name: name}
configDir, err := machine.GetConfDir(machine.AppleHvVirt)
if err != nil {
return false, err
}
if err := loadMacMachineFromJSON(configDir, &mm); err != nil {
return false, err
}
return true, nil
}
func (v AppleHVVirtualization) List(opts machine.ListOptions) ([]*machine.ListResponse, error) {
var (
response []*machine.ListResponse
)
mms, err := v.loadFromLocalJson()
if err != nil {
return nil, err
}
for _, mm := range mms {
vmState, err := mm.Vfkit.state()
if err != nil {
if errors.Is(err, unix.ECONNREFUSED) {
vmState = machine.Stopped
} else {
return nil, err
}
}
mlr := machine.ListResponse{
Name: mm.Name,
CreatedAt: mm.Created,
LastUp: mm.LastUp,
Running: vmState == machine.Running,
Starting: vmState == machine.Starting,
Stream: mm.ImageStream,
VMType: machine.AppleHvVirt.String(),
CPUs: mm.CPUs,
Memory: mm.Memory * units.MiB,
DiskSize: mm.DiskSize * units.GiB,
Port: mm.Port,
RemoteUsername: mm.RemoteUsername,
IdentityPath: mm.IdentityPath,
}
response = append(response, &mlr)
}
return response, nil
}
func (v AppleHVVirtualization) LoadVMByName(name string) (machine.VM, error) {
m := MacMachine{Name: name}
return m.loadFromFile()
}
func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) {
m := MacMachine{Name: opts.Name}
configDir, err := machine.GetConfDir(machine.AppleHvVirt)
if err != nil {
return nil, err
}
configPath, err := machine.NewMachineFile(getVMConfigPath(configDir, opts.Name), nil)
if err != nil {
return nil, err
}
m.ConfigPath = *configPath
dataDir, err := machine.GetDataDir(machine.AppleHvVirt)
if err != nil {
return nil, err
}
ignitionPath, err := machine.NewMachineFile(filepath.Join(configDir, m.Name)+".ign", nil)
if err != nil {
return nil, err
}
m.IgnitionFile = *ignitionPath
// Set creation time
m.Created = time.Now()
m.ResourceConfig = machine.ResourceConfig{
CPUs: opts.CPUS,
DiskSize: opts.DiskSize,
// Diskpath will be needed
Memory: opts.Memory,
}
bl := vfConfig.NewEFIBootloader(fmt.Sprintf("%s/%ss", dataDir, opts.Name), true)
m.Vfkit.VirtualMachine = vfConfig.NewVirtualMachine(uint(opts.CPUS), opts.Memory, bl)
if err := m.writeConfig(); err != nil {
return nil, err
}
return m.loadFromFile()
}
func (v AppleHVVirtualization) RemoveAndCleanMachines() error {
// This can be implemented when host networking is completed.
return machine.ErrNotImplemented
}
func (v AppleHVVirtualization) VMType() machine.VMType {
return vmtype
}
func (v AppleHVVirtualization) loadFromLocalJson() ([]*MacMachine, error) {
var (
jsonFiles []string
mms []*MacMachine
)
configDir, err := machine.GetConfDir(v.VMType())
if err != nil {
return nil, err
}
if err := filepath.WalkDir(configDir, func(input string, d fs.DirEntry, e error) error {
if e != nil {
return e
}
if filepath.Ext(d.Name()) == ".json" {
jsonFiles = append(jsonFiles, input)
}
return nil
}); err != nil {
return nil, err
}
for _, jsonFile := range jsonFiles {
mm := MacMachine{}
if err := loadMacMachineFromJSON(jsonFile, &mm); err != nil {
return nil, err
}
if err != nil {
return nil, err
}
mms = append(mms, &mm)
}
return mms, nil
}