mirror of https://github.com/containers/podman.git
197 lines
4.4 KiB
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
|
|
}
|