Skip to content

Commit

Permalink
MVP for Podman Machine with AppleHV
Browse files Browse the repository at this point in the history
this pr is the first pass at enabling podman machine to use the apple hypervisor. there are still several TODO
areas like host networking.  once the decision is handled on what host networking should look like, these TODOs
should be fairly quick to resolve.  they also will impact the remove methods.

you must also have vfkit (https://github.com/crc-org/vfkit)

Signed-off-by: Brent Baude <[email protected]>

[NO NEW TESTS NEEDED]

Signed-off-by: Brent Baude <[email protected]>
  • Loading branch information
baude committed May 2, 2023
1 parent cda2b6e commit dc7515d
Show file tree
Hide file tree
Showing 16 changed files with 1,308 additions and 38 deletions.
3 changes: 1 addition & 2 deletions cmd/podman/machine/platform.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build (amd64 && !windows) || (arm64 && !windows)
// +build amd64,!windows arm64,!windows
//go:build (amd64 && !windows && amd64 && !darwin) || (arm64 && !windows && arm64 && !darwin) || (amd64 && darwin)

package machine

Expand Down
36 changes: 36 additions & 0 deletions cmd/podman/machine/platform_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build darwin && arm64

package machine

import (
"fmt"
"os"

"github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/qemu"
"github.com/sirupsen/logrus"
)

func GetSystemProvider() (machine.VirtProvider, error) {
cfg, err := config.Default()
if err != nil {
return nil, err
}
provider := cfg.Machine.Provider
if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found {
provider = providerOverride
}
resolvedVMType, err := machine.ParseVMType(provider, machine.QemuVirt)
if err != nil {
return nil, err
}

logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
switch resolvedVMType {
case machine.QemuVirt:
return qemu.GetVirtualizationProvider(), nil
default:
return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String())
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/containers/storage v1.46.1
github.com/coreos/go-systemd/v22 v22.5.0
github.com/coreos/stream-metadata-go v0.4.1
github.com/crc-org/vfkit v0.0.5-0.20230427143911-8117c28876bc
github.com/cyphar/filepath-securejoin v0.2.3
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
github.com/docker/docker v23.0.5+incompatible
Expand Down
4 changes: 3 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ github.com/coreos/stream-metadata-go v0.4.1/go.mod h1:Lwjwqf1zwnVa7uy/v/KW28eUkd
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/crc-org/vfkit v0.0.5-0.20230427143911-8117c28876bc h1:fhuTRmFWKxI59UGqN/y1Pq9+KRnNrZ5bztFT2rTQTGM=
github.com/crc-org/vfkit v0.0.5-0.20230427143911-8117c28876bc/go.mod h1:sluZ7Q1ZKWwI+PzGwwNy74pplP99gzRqmEWJ246denE=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
Expand Down Expand Up @@ -694,7 +696,7 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
Expand Down
159 changes: 150 additions & 9 deletions pkg/machine/applehv/config.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,51 @@
//go:build arm64 && darwin
// +build arm64,darwin

package applehv

import "github.com/containers/podman/v4/pkg/machine"
import (
"errors"
"io/fs"
"path/filepath"
"time"

"github.com/containers/podman/v4/pkg/machine"
"github.com/docker/go-units"
"golang.org/x/sys/unix"
)

const (
defaultVFKitEndpoint = "http://localhost:8081"
)

type Virtualization struct {
artifact machine.Artifact
compression machine.ImageCompression
format machine.ImageFormat
}

type MMHardwareConfig struct {
CPUs uint16
DiskPath string
DiskSize uint64
Memory int32
}

func (v Virtualization) Artifact() machine.Artifact {
return machine.None
return machine.Metal
}

func (v Virtualization) CheckExclusiveActiveVM() (bool, string, error) {
return false, "", machine.ErrNotImplemented
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 Virtualization) Compression() machine.ImageCompression {
Expand All @@ -28,25 +57,137 @@ func (v Virtualization) Format() machine.ImageFormat {
}

func (v Virtualization) IsValidVMName(name string) (bool, error) {
return false, machine.ErrNotImplemented
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 Virtualization) List(opts machine.ListOptions) ([]*machine.ListResponse, error) {
return nil, machine.ErrNotImplemented
var (
response []*machine.ListResponse
)

mms, err := v.loadFromLocalJson()
if err != nil {
return nil, err
}

for _, mm := range mms {
vmState, err := mm.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 Virtualization) LoadVMByName(name string) (machine.VM, error) {
return nil, machine.ErrNotImplemented
m := MacMachine{Name: name}
return m.loadFromFile()
}

func (v Virtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) {
return nil, machine.ErrNotImplemented
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

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,
}

if err := m.writeConfig(); err != nil {
return nil, err
}
return m.loadFromFile()
}

func (v Virtualization) RemoveAndCleanMachines() error {
// This can be implemented when host networking is completed.
return machine.ErrNotImplemented
}

func (v Virtualization) VMType() string {
func (v Virtualization) VMType() machine.VMType {
return vmtype
}

func (v Virtualization) 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
}
Loading

0 comments on commit dc7515d

Please sign in to comment.