Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,5 @@ require (
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
)

replace github.com/Code-Hex/vz/v3 => github.com/norio-nomura/vz/v3 v3.7.2-0.20251122122159-6617c8faa123
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkk
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
github.com/Code-Hex/go-infinity-channel v1.0.0 h1:M8BWlfDOxq9or9yvF9+YkceoTkDI1pFAqvnP87Zh0Nw=
github.com/Code-Hex/go-infinity-channel v1.0.0/go.mod h1:5yUVg/Fqao9dAjcpzoQ33WwfdMWmISOrQloDRn3bsvY=
github.com/Code-Hex/vz/v3 v3.7.1 h1:EN1yNiyrbPq+dl388nne2NySo8I94EnPppvqypA65XM=
github.com/Code-Hex/vz/v3 v3.7.1/go.mod h1:1LsW0jqW0r0cQ+IeR4hHbjdqOtSidNCVMWhStMHGho8=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
Expand Down Expand Up @@ -209,6 +207,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/norio-nomura/vz/v3 v3.7.2-0.20251122122159-6617c8faa123 h1:3Xzg1W5gel17So2d2NSA+flx6yoyknx5nG9Pb6eZU6s=
github.com/norio-nomura/vz/v3 v3.7.2-0.20251122122159-6617c8faa123/go.mod h1:+0IVfZY7N/7Vv5KpZWbEgTRK6jMg4s7DVM+op2hdyrs=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
Expand Down
36 changes: 36 additions & 0 deletions pkg/driver/vz/vm_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@
}

for i, nw := range inst.Networks {
if nw.VZNAT != nil && *nw.VZNAT {

Check failure on line 361 in pkg/driver/vz/vm_darwin.go

View workflow job for this annotation

GitHub Actions / Lint Go (macos-26)

ifElseChain: rewrite if-else to switch statement (gocritic)
attachment, err := vz.NewNATNetworkDeviceAttachment()
if err != nil {
return err
Expand All @@ -368,6 +368,42 @@
return err
}
configurations = append(configurations, networkConfig)
} else if nw.VZShared != nil && *nw.VZShared {
config, err := vz.NewVmnetNetworkConfiguration(vz.SharedMode)
if err != nil {
return err
}
network, err := vz.NewVmnetNetwork(config)
if err != nil {
return err
}
attachment, err := vz.NewVmnetNetworkDeviceAttachment(network)
if err != nil {
return err
}
networkConfig, err := newVirtioNetworkDeviceConfiguration(attachment, nw.MACAddress)
if err != nil {
return err
}
configurations = append(configurations, networkConfig)
} else if nw.VZHost != nil && *nw.VZHost {
config, err := vz.NewVmnetNetworkConfiguration(vz.HostMode)
if err != nil {
return err
}
network, err := vz.NewVmnetNetwork(config)
if err != nil {
return err
}
attachment, err := vz.NewVmnetNetworkDeviceAttachment(network)
if err != nil {
return err
}
networkConfig, err := newVirtioNetworkDeviceConfiguration(attachment, nw.MACAddress)
if err != nil {
return err
}
configurations = append(configurations, networkConfig)
} else if nw.Lima != "" {
nwCfg, err := networks.LoadConfig()
if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions pkg/driver/vz/vz_driver_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ func validateConfig(_ context.Context, cfg *limatype.LimaYAML) error {

for i, nw := range cfg.Networks {
if unknown := reflectutil.UnknownNonEmptyFields(nw, "VZNAT",
"VZShared",
"VZHost",
"Lima",
"Socket",
"MACAddress",
Expand All @@ -276,6 +278,11 @@ func validateConfig(_ context.Context, cfg *limatype.LimaYAML) error {
); len(unknown) > 0 {
logrus.Warnf("vmType %s: ignoring networks[%d]: %+v", *cfg.VMType, i, unknown)
}
if (nw.VZShared != nil && *nw.VZShared) || (nw.VZHost != nil && *nw.VZHost) {
if macOSProductVersion.LessThan(*semver.New("26.0.0")) {
return fmt.Errorf("networks[%d]: VZShared and VZHost require macOS 26.0 or later", i)
}
}
}

switch audioDevice := *cfg.Audio.Device; audioDevice {
Expand Down
8 changes: 8 additions & 0 deletions pkg/limatmpl/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,14 @@ func (tmpl *Template) combineNetworks() {
tmpl.copyListEntryField(networks, dst, src, "vzNAT")
dest.VZNAT = nw.VZNAT
}
if dest.VZShared == nil && nw.VZShared != nil {
tmpl.copyListEntryField(networks, dst, src, "vzShared")
dest.VZShared = nw.VZShared
}
if dest.VZHost == nil && nw.VZHost != nil {
tmpl.copyListEntryField(networks, dst, src, "vzHost")
dest.VZHost = nw.VZHost
}
if dest.Metric == nil && nw.Metric != nil {
tmpl.copyListEntryField(networks, dst, src, "metric")
dest.Metric = nw.Metric
Expand Down
4 changes: 4 additions & 0 deletions pkg/limatype/lima_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ type Network struct {
Socket string `yaml:"socket,omitempty" json:"socket,omitempty"`
// VZNAT uses VZNATNetworkDeviceAttachment. Needs VZ. No root privilege is required.
VZNAT *bool `yaml:"vzNAT,omitempty" json:"vzNAT,omitempty"`
// VZShared, and VZHost use VZVmnetNetworkDeviceAttachment. Needs VZ. No root privilege is required.
// Requires macOS 26.0 or later.
VZShared *bool `yaml:"vzShared,omitempty" json:"vzShared,omitempty"`
VZHost *bool `yaml:"vzHost,omitempty" json:"vzHost,omitempty"`

MACAddress string `yaml:"macAddress,omitempty" json:"macAddress,omitempty"`
Interface string `yaml:"interface,omitempty" json:"interface,omitempty"`
Expand Down
44 changes: 44 additions & 0 deletions pkg/limayaml/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,22 +466,66 @@ func validateNetwork(y *limatype.LimaYAML) error {
if nw.VZNAT != nil && *nw.VZNAT {
errs = errors.Join(errs, fmt.Errorf("field `%s.lima` and field `%s.vzNAT` are mutually exclusive", field, field))
}
if nw.VZShared != nil && *nw.VZShared {
errs = errors.Join(errs, fmt.Errorf("field `%s.lima` and field `%s.vzShared` are mutually exclusive", field, field))
}
if nw.VZHost != nil && *nw.VZHost {
errs = errors.Join(errs, fmt.Errorf("field `%s.lima` and field `%s.vzHost` are mutually exclusive", field, field))
}
case nw.Socket != "":
if nw.VZNAT != nil && *nw.VZNAT {
errs = errors.Join(errs, fmt.Errorf("field `%s.socket` and field `%s.vzNAT` are mutually exclusive", field, field))
}
if nw.VZShared != nil && *nw.VZShared {
errs = errors.Join(errs, fmt.Errorf("field `%s.socket` and field `%s.vzShared` are mutually exclusive", field, field))
}
if nw.VZHost != nil && *nw.VZHost {
errs = errors.Join(errs, fmt.Errorf("field `%s.socket` and field `%s.vzHost` are mutually exclusive", field, field))
}
if fi, err := os.Stat(nw.Socket); err != nil && !errors.Is(err, os.ErrNotExist) {
errs = errors.Join(errs, err)
} else if err == nil && fi.Mode()&os.ModeSocket == 0 {
errs = errors.Join(errs, fmt.Errorf("field `%s.socket` %q points to a non-socket file", field, nw.Socket))
}
case nw.VZNAT != nil && *nw.VZNAT:
if nw.VZShared != nil && *nw.VZShared {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzNAT` and field `%s.vzShared` are mutually exclusive", field, field))
}
if nw.VZHost != nil && *nw.VZHost {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzNAT` and field `%s.vzHost` are mutually exclusive", field, field))
}
if nw.Lima != "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzNAT` and field `%s.lima` are mutually exclusive", field, field))
}
if nw.Socket != "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzNAT` and field `%s.socket` are mutually exclusive", field, field))
}
case nw.VZShared != nil && *nw.VZShared:
if nw.VZNAT != nil && *nw.VZNAT {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzShared` and field `%s.vzNAT` are mutually exclusive", field, field))
}
if nw.VZHost != nil && *nw.VZHost {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzShared` and field `%s.vzHost` are mutually exclusive", field, field))
}
if nw.Lima != "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzShared` and field `%s.lima` are mutually exclusive", field, field))
}
if nw.Socket != "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzShared` and field `%s.socket` are mutually exclusive", field, field))
}
case nw.VZHost != nil && *nw.VZHost:
if nw.VZNAT != nil && *nw.VZNAT {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzHost` and field `%s.vzNAT` are mutually exclusive", field, field))
}
if nw.VZShared != nil && *nw.VZShared {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzHost` and field `%s.vzShared` are mutually exclusive", field, field))
}
if nw.Lima != "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzHost` and field `%s.lima` are mutually exclusive", field, field))
}
if nw.Socket != "" {
errs = errors.Join(errs, fmt.Errorf("field `%s.vzHost` and field `%s.socket` are mutually exclusive", field, field))
}
default:
errs = errors.Join(errs, fmt.Errorf("field `%s.lima` or field `%s.socket must be set", field, field))
}
Expand Down
3 changes: 3 additions & 0 deletions templates/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,9 @@ networks:
# The "vzNAT" IP address is accessible from the host, but not from other guests.
# Needs `vmType: vz`
# - vzNAT: true
# requires `vmType: vz` and macOS 26.0 or later.
# - vzShared: true
# - vzHost: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with lima: shared, maybe we these one should be like vz: shared ?


# Port forwarding rules. Forwarding between ports 22 and ssh.localPort cannot be overridden.
# Rules are checked sequentially until the first one matches.
Expand Down
Loading