Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vz: support .[]networks.vzNAT networking #1207

Merged
merged 1 commit into from
Nov 27, 2022
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ jobs:
run: make
- name: Install
run: sudo make install
- name: Validate examples (except vmnet.yaml)
run: find examples -name '*.yaml' | grep -v 'vmnet.yaml' | xargs limactl validate
- name: Uninstall
run: sudo make uninstall

Expand Down Expand Up @@ -89,6 +87,8 @@ jobs:
run: make
- name: Install
run: make install
- name: Validate examples
run: find examples -name '*.yaml' | xargs limactl validate
- name: Install test dependencies
# QEMU: required by Lima itself
# bash: required by test-example.sh (OS version of bash is too old)
Expand Down
43 changes: 40 additions & 3 deletions docs/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,16 @@ During initial cloud-init bootstrap, `iptables` may not yet be installed. In tha

If `useHostResolver` is false, then DNS servers can be configured manually in `lima.yaml` via the `dns` setting. If that list is empty, then Lima will either use the slirp DNS (on Linux), or the nameservers from the first host interface in service order that has an assigned IPv4 address (on macOS).

## Managed VMNet networks (192.168.105.0/24)
## VMNet networks

VMNet assigns a "real" IP address that is reachable from the host.

The configuration steps are different across QEMU and VZ:
- [QEMU](#qemu)
- [VZ](#vz)

### QEMU
#### Managed (192.168.105.0/24)

Either [`socket_vmnet`](https://github.com/lima-vm/socket_vmnet) (since Lima v0.12) or [`vde_vmnet`](https://github.com/lima-vm/vde_vmnet) (Deprecated)
is required for adding another guest IP that is accessible from the host and other guests.
Expand All @@ -51,6 +60,11 @@ Starting with version v0.7.0 lima can manage the networking daemons automaticall
`$LIMA_HOME/_config/networks.yaml`. If this file doesn't already exist, it will be created with these default
settings:

<details>
<summary>Default</summary>

<p>

```yaml
# Path to socket_vmnet executable. Because socket_vmnet is invoked via sudo it should be
# installed where only root can modify/replace it. This means also none of the
Expand Down Expand Up @@ -92,6 +106,10 @@ networks:
netmask: 255.255.255.0
```

</p>

</details>

Instances can then reference these networks from their `lima.yaml` file:

```yaml
Expand Down Expand Up @@ -120,7 +138,7 @@ be done via:
limactl sudoers | sudo tee /etc/sudoers.d/lima
```

## Unmanaged VMNet networks
#### Unmanaged
For Lima >= 0.12:
```yaml
networks:
Expand All @@ -131,7 +149,11 @@ networks:
# - socket: "/var/run/socket_vmnet"
```

For older Lima releases:
<details>
<summary>For older Lima releases</summary>

<p>

```yaml
networks:
# vnl (virtual network locator) points to the vde_switch socket directory,
Expand All @@ -147,3 +169,18 @@ networks:
# # Interface name, defaults to "lima0", "lima1", etc.
# interface: ""
```
</p>

</details>

### VZ

For VZ instances, the "vzNAT" network can be configured as follows:
```yaml
networks:
- vzNAT: true
```

The range of the IP address is not specifiable.

The "vzNAT" network does not need the `socket_vmnet` binary and the `sudoers` file.
1 change: 0 additions & 1 deletion docs/vmtype.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,4 @@ mountType: "virtiofs"

### Known Issues
- "vz" doesn't support `legacyBoot: true` option, so guest machine like centos-stream, archlinux, oraclelinux will not work
- Host to guest networking (`networks` section in lima yaml) is not supported
- When running lima using "vz", `${LIMA_HOME}/<INSTANCE>/serial.log` will not contain kernel boot logs
3 changes: 3 additions & 0 deletions examples/experimental/vz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ mounts:
- location: "/tmp/lima"
writable: true
mountType: "virtiofs"

networks:
- vzNAT: true
4 changes: 3 additions & 1 deletion examples/vmnet.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Example to enable vmnet.framework
# Example to enable vmnet.framework for QEMU.
# VZ users should refer to experimental/vz.yaml

# This example requires Lima v0.7.0 or later.
# Older versions of Lima were using a different syntax for supporting vmnet.framework.
images:
Expand Down
3 changes: 3 additions & 0 deletions pkg/limayaml/limayaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ type Network struct {
Lima string `yaml:"lima,omitempty" json:"lima,omitempty"`
// Socket is a QEMU-compatible socket
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"`

// VNLDeprecated is a Virtual Network Locator (https://github.com/rd235/vdeplug4/commit/089984200f447abb0e825eb45548b781ba1ebccd).
// On macOS, only VDE2-compatible form (optionally with vde:// prefix) is supported.
// VNLDeprecated is deprecated. Use Socket.
Expand Down
22 changes: 22 additions & 0 deletions pkg/limayaml/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ func validateNetwork(y LimaYAML, warn bool) error {
if nw.Socket != "" {
return fmt.Errorf("field `%s.lima` and field `%s.socket` are mutually exclusive", field, field)
}
if nw.VZNAT != nil && *nw.VZNAT {
return fmt.Errorf("field `%s.lima` and field `%s.vzNAT` are mutually exclusive", field, field)
}
if nw.VNLDeprecated != "" {
return fmt.Errorf("field `%s.lima` and field `%s.vnl` are mutually exclusive", field, field)
}
Expand All @@ -285,6 +288,9 @@ func validateNetwork(y LimaYAML, warn bool) error {
return fmt.Errorf("field `%s.lima` references network %q which is not defined in networks.yaml", field, nw.Lima)
}
} else if nw.Socket != "" {
if nw.VZNAT != nil && *nw.VZNAT {
return fmt.Errorf("field `%s.socket` and field `%s.vzNAT` are mutually exclusive", field, field)
}
if nw.VNLDeprecated != "" {
return fmt.Errorf("field `%s.socket` and field `%s.vnl` are mutually exclusive", field, field)
}
Expand All @@ -296,6 +302,22 @@ func validateNetwork(y LimaYAML, warn bool) error {
} else if err == nil && fi.Mode()&os.ModeSocket == 0 {
return fmt.Errorf("field `%s.socket` %q points to a non-socket file", field, nw.Socket)
}
} else if nw.VZNAT != nil && *nw.VZNAT {
if y.VMType == nil || *y.VMType != VZ {
return fmt.Errorf("field `%s.vzNAT` requires `vmType` to be %q", field, VZ)
}
if nw.Lima != "" {
return fmt.Errorf("field `%s.vzNAT` and field `%s.lima` are mutually exclusive", field, field)
}
if nw.Socket != "" {
return fmt.Errorf("field `%s.vzNAT` and field `%s.socket` are mutually exclusive", field, field)
}
if nw.VNLDeprecated != "" {
return fmt.Errorf("field `%s.vzNAT` and field `%s.vnl` are mutually exclusive", field, field)
}
if nw.SwitchPortDeprecated != 0 {
return fmt.Errorf("field `%s.switchPort` cannot be used with field `%s.vzNAT`", field, field)
}
} else {
if nw.VNLDeprecated == "" {
return fmt.Errorf("field `%s.lima`, field `%s.socket`, or field `%s.vnl` must be set", field, field, field)
Expand Down
42 changes: 31 additions & 11 deletions pkg/vz/vm_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,33 +191,53 @@ func attachSerialPort(driver *driver.BaseDriver, config *vz.VirtualMachineConfig
return err
}

func attachNetwork(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration, networkConn *os.File) error {
//slirp network using gvisor netstack
fileAttachment, err := vz.NewFileHandleNetworkDeviceAttachment(networkConn)
func newVirtioNetworkDeviceConfiguration(attachment vz.NetworkDeviceAttachment, macStr string) (*vz.VirtioNetworkDeviceConfiguration, error) {
networkConfig, err := vz.NewVirtioNetworkDeviceConfiguration(attachment)
if err != nil {
return err
return nil, err
}
err = fileAttachment.SetMaximumTransmissionUnit(1500)
mac, err := net.ParseMAC(macStr)
if err != nil {
return err
return nil, err
}
networkConfig, err := vz.NewVirtioNetworkDeviceConfiguration(fileAttachment)
address, err := vz.NewMACAddress(mac)
if err != nil {
return nil, err
}
networkConfig.SetMACAddress(address)
return networkConfig, nil
}

func attachNetwork(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration, networkConn *os.File) error {
//slirp network using gvisor netstack
fileAttachment, err := vz.NewFileHandleNetworkDeviceAttachment(networkConn)
if err != nil {
return err
}
mac, err := net.ParseMAC(limayaml.MACAddress(driver.Instance.Dir))
err = fileAttachment.SetMaximumTransmissionUnit(1500)
if err != nil {
return err
}
address, err := vz.NewMACAddress(mac)
networkConfig, err := newVirtioNetworkDeviceConfiguration(fileAttachment, limayaml.MACAddress(driver.Instance.Dir))
if err != nil {
return err
}
networkConfig.SetMACAddress(address)

configurations := []*vz.VirtioNetworkDeviceConfiguration{
networkConfig,
}
for _, nw := range driver.Instance.Networks {
if nw.VZNAT != nil && *nw.VZNAT {
attachment, err := vz.NewNATNetworkDeviceAttachment()
if err != nil {
return err
}
networkConfig, err = newVirtioNetworkDeviceConfiguration(attachment, nw.MACAddress)
if err != nil {
return err
}
configurations = append(configurations, networkConfig)
}
}
vmConfig.SetNetworkDevicesVirtualMachineConfiguration(configurations)
return nil
}
Expand Down