mirror of
https://github.com/abiosoft/colima.git
synced 2026-05-17 12:10:34 +00:00
net: add support for bridge mode
Signed-off-by: Abiola Ibrahim <git@abiosoft.com>
This commit is contained in:
+10
-4
@@ -31,8 +31,8 @@ var startCmd = &cobra.Command{
|
||||
ctx := cmd.Context()
|
||||
|
||||
var processes []process.Process
|
||||
if daemonArgs.vmnet {
|
||||
processes = append(processes, vmnet.New())
|
||||
if daemonArgs.vmnet.enabled {
|
||||
processes = append(processes, vmnet.New(daemonArgs.vmnet.mode, daemonArgs.vmnet.netInterface))
|
||||
}
|
||||
if daemonArgs.inotify.enabled {
|
||||
processes = append(processes, inotify.New())
|
||||
@@ -79,7 +79,11 @@ var statusCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
var daemonArgs struct {
|
||||
vmnet bool
|
||||
vmnet struct {
|
||||
enabled bool
|
||||
mode string
|
||||
netInterface string
|
||||
}
|
||||
inotify struct {
|
||||
enabled bool
|
||||
dirs []string
|
||||
@@ -96,7 +100,9 @@ func init() {
|
||||
daemonCmd.AddCommand(stopCmd)
|
||||
daemonCmd.AddCommand(statusCmd)
|
||||
|
||||
startCmd.Flags().BoolVar(&daemonArgs.vmnet, "vmnet", false, "start vmnet")
|
||||
startCmd.Flags().BoolVar(&daemonArgs.vmnet.enabled, "vmnet", false, "start vmnet")
|
||||
startCmd.Flags().StringVar(&daemonArgs.vmnet.mode, "vmnet-mode", "shared", "vmnet mode (shared, bridged)")
|
||||
startCmd.Flags().StringVar(&daemonArgs.vmnet.netInterface, "vmnet-interface", "en0", "vmnet interface for bridged mode")
|
||||
startCmd.Flags().BoolVar(&daemonArgs.inotify.enabled, "inotify", false, "start inotify")
|
||||
startCmd.Flags().StringSliceVar(&daemonArgs.inotify.dirs, "inotify-dir", nil, "set inotify directories")
|
||||
startCmd.Flags().StringVar(&daemonArgs.inotify.runtime, "inotify-runtime", "docker", "set runtime")
|
||||
|
||||
@@ -186,6 +186,8 @@ func init() {
|
||||
if util.MacOS() {
|
||||
// network address
|
||||
startCmd.Flags().BoolVar(&startCmdArgs.Network.Address, "network-address", false, "assign reachable IP address to the VM")
|
||||
startCmd.Flags().StringVar(&startCmdArgs.Network.Mode, "network-mode", "shared", "network mode (shared, bridged)")
|
||||
startCmd.Flags().StringVar(&startCmdArgs.Network.BridgeInterface, "network-interface", "en0", "host network interface to use for bridged mode")
|
||||
|
||||
// vm type
|
||||
if util.MacOS13OrNewer() {
|
||||
@@ -374,6 +376,10 @@ func setFixedConfigs(conf *config.Config) {
|
||||
log.Warnln("network address cannot be disabled once enabled")
|
||||
conf.Network.Address = true
|
||||
}
|
||||
if fixedConf.Network.Mode != "" {
|
||||
warnIfNotEqual("network mode", conf.Network.Mode, fixedConf.Network.Mode)
|
||||
conf.Network.Mode = fixedConf.Network.Mode
|
||||
}
|
||||
}
|
||||
|
||||
func prepareConfig(cmd *cobra.Command) {
|
||||
@@ -513,6 +519,12 @@ func prepareConfig(cmd *cobra.Command) {
|
||||
if !cmd.Flag("network-address").Changed {
|
||||
startCmdArgs.Network.Address = current.Network.Address
|
||||
}
|
||||
if !cmd.Flag("network-mode").Changed {
|
||||
startCmdArgs.Network.Mode = current.Network.Mode
|
||||
}
|
||||
if !cmd.Flag("network-interface").Changed {
|
||||
startCmdArgs.Network.BridgeInterface = current.Network.BridgeInterface
|
||||
}
|
||||
if util.MacOS13OrNewer() {
|
||||
if !cmd.Flag("vm-type").Changed {
|
||||
startCmdArgs.VMType = current.VMType
|
||||
|
||||
+6
-4
@@ -77,10 +77,12 @@ type Kubernetes struct {
|
||||
|
||||
// Network is VM network configuration
|
||||
type Network struct {
|
||||
Address bool `yaml:"address"`
|
||||
DNSResolvers []net.IP `yaml:"dns"`
|
||||
DNSHosts map[string]string `yaml:"dnsHosts"`
|
||||
HostAddresses bool `yaml:"hostAddresses"`
|
||||
Address bool `yaml:"address"`
|
||||
DNSResolvers []net.IP `yaml:"dns"`
|
||||
DNSHosts map[string]string `yaml:"dnsHosts"`
|
||||
HostAddresses bool `yaml:"hostAddresses"`
|
||||
Mode string `yaml:"mode"` // shared, bridged
|
||||
BridgeInterface string `yaml:"interface"`
|
||||
}
|
||||
|
||||
// Mount is volume mount
|
||||
|
||||
+3
-1
@@ -94,6 +94,8 @@ func (l processManager) Start(ctx context.Context, conf config.Config) error {
|
||||
|
||||
if conf.Network.Address {
|
||||
args = append(args, "--vmnet")
|
||||
args = append(args, "--vmnet-mode", conf.Network.Mode)
|
||||
args = append(args, "--vmnet-interface", conf.Network.BridgeInterface)
|
||||
}
|
||||
if conf.MountINotify {
|
||||
args = append(args, "--inotify")
|
||||
@@ -125,7 +127,7 @@ func processesFromConfig(conf config.Config) []process.Process {
|
||||
var processes []process.Process
|
||||
|
||||
if conf.Network.Address {
|
||||
processes = append(processes, vmnet.New())
|
||||
processes = append(processes, vmnet.New(conf.Network.Mode, conf.Network.BridgeInterface))
|
||||
}
|
||||
if conf.MountINotify {
|
||||
processes = append(processes, inotify.New())
|
||||
|
||||
@@ -23,36 +23,39 @@ func (f *inotifyProcess) monitorContainerVolumes(ctx context.Context, c chan<- [
|
||||
fetch := func() ([]string, error) {
|
||||
var vols []string
|
||||
|
||||
// docker
|
||||
if f.runtime != containerd.Name {
|
||||
switch f.runtime {
|
||||
|
||||
case docker.Name:
|
||||
vols, err := f.fetchVolumes(docker.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching docker volumes: %w", err)
|
||||
}
|
||||
return vols, nil
|
||||
}
|
||||
|
||||
// containerd
|
||||
var namespaces []string
|
||||
out, err := f.guest.RunOutput("sudo", "nerdctl", "namespace", "list", "-q")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retrieving containerd namespaces: %w", err)
|
||||
}
|
||||
if out != "" {
|
||||
namespaces = strings.Fields(out)
|
||||
}
|
||||
|
||||
for _, ns := range namespaces {
|
||||
v, err := f.fetchVolumes("sudo", "nerdctl", "--namespace", ns)
|
||||
case containerd.Name:
|
||||
var namespaces []string
|
||||
out, err := f.guest.RunOutput("sudo", "nerdctl", "namespace", "list", "-q")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retrieving containerd volumes: %w", err)
|
||||
return nil, fmt.Errorf("error retrieving containerd namespaces: %w", err)
|
||||
}
|
||||
if len(v) > 0 {
|
||||
vols = append(vols, v...)
|
||||
if out != "" {
|
||||
namespaces = strings.Fields(out)
|
||||
}
|
||||
|
||||
for _, ns := range namespaces {
|
||||
v, err := f.fetchVolumes("sudo", "nerdctl", "--namespace", ns)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retrieving containerd volumes: %w", err)
|
||||
}
|
||||
if len(v) > 0 {
|
||||
vols = append(vols, v...)
|
||||
}
|
||||
}
|
||||
|
||||
return vols, nil
|
||||
}
|
||||
|
||||
return vols, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -26,9 +26,17 @@ const (
|
||||
|
||||
var _ process.Process = (*vmnetProcess)(nil)
|
||||
|
||||
func New() process.Process { return &vmnetProcess{} }
|
||||
func New(mode, netInterface string) process.Process {
|
||||
return &vmnetProcess{
|
||||
mode: mode,
|
||||
netInterface: netInterface,
|
||||
}
|
||||
}
|
||||
|
||||
type vmnetProcess struct{}
|
||||
type vmnetProcess struct {
|
||||
mode string
|
||||
netInterface string
|
||||
}
|
||||
|
||||
func (*vmnetProcess) Alive(ctx context.Context) error {
|
||||
info := Info()
|
||||
@@ -60,7 +68,7 @@ func (*vmnetProcess) Alive(ctx context.Context) error {
|
||||
func (*vmnetProcess) Name() string { return Name }
|
||||
|
||||
// Start implements process.BgProcess
|
||||
func (*vmnetProcess) Start(ctx context.Context) error {
|
||||
func (v *vmnetProcess) Start(ctx context.Context) error {
|
||||
info := Info()
|
||||
socket := info.Socket.File()
|
||||
pid := info.PidFile
|
||||
@@ -73,14 +81,26 @@ func (*vmnetProcess) Start(ctx context.Context) error {
|
||||
|
||||
go func() {
|
||||
// rootfully start the vmnet daemon
|
||||
command := cli.CommandInteractive("sudo", BinaryPath,
|
||||
"--vmnet-mode", "shared",
|
||||
"--socket-group", "staff",
|
||||
"--vmnet-gateway", NetGateway,
|
||||
"--vmnet-dhcp-end", NetDHCPEnd,
|
||||
"--pidfile", pid,
|
||||
socket,
|
||||
)
|
||||
var command *exec.Cmd
|
||||
|
||||
if v.mode == "bridged" {
|
||||
command = cli.CommandInteractive("sudo", BinaryPath,
|
||||
"--vmnet-mode", "bridged",
|
||||
"--socket-group", "staff",
|
||||
"--vmnet-interface", v.netInterface,
|
||||
"--pidfile", pid,
|
||||
socket,
|
||||
)
|
||||
} else {
|
||||
command = cli.CommandInteractive("sudo", BinaryPath,
|
||||
"--vmnet-mode", "shared",
|
||||
"--socket-group", "staff",
|
||||
"--vmnet-gateway", NetGateway,
|
||||
"--vmnet-dhcp-end", NetDHCPEnd,
|
||||
"--pidfile", pid,
|
||||
socket,
|
||||
)
|
||||
}
|
||||
|
||||
if cli.Settings.Verbose {
|
||||
command.Env = append(command.Env, os.Environ()...)
|
||||
|
||||
@@ -59,6 +59,17 @@ network:
|
||||
# Default: false
|
||||
address: false
|
||||
|
||||
# Network mode for the virtual machine (shared, bridged).
|
||||
# NOTE: this is currently macOS only and ignored on Linux.
|
||||
# Default: shared
|
||||
mode: shared
|
||||
|
||||
# Network interface to use for bridged mode.
|
||||
# This is only used when mode is set to bridged.
|
||||
# NOTE: this is currently macOS only and ignored on Linux.
|
||||
# Default: en0
|
||||
interface: en0
|
||||
|
||||
# Custom DNS resolvers for the virtual machine.
|
||||
#
|
||||
# EXAMPLE
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# starting vmnet daemon
|
||||
%staff ALL=(root:wheel) NOPASSWD:NOSETENV: /opt/colima/bin/socket_vmnet --vmnet-mode shared --socket-group staff --vmnet-gateway 192.168.106.1 --vmnet-dhcp-end 192.168.106.254 *
|
||||
%staff ALL=(root:wheel) NOPASSWD:NOSETENV: /opt/colima/bin/socket_vmnet --vmnet-mode bridged --socket-group staff *
|
||||
# terminating vmnet daemon
|
||||
%staff ALL=(root:wheel) NOPASSWD:NOSETENV: /usr/bin/pkill -F /opt/colima/run/*.pid
|
||||
# validating vmnet daemon
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
func (l *limaVM) startDaemon(ctx context.Context, conf config.Config) (context.Context, error) {
|
||||
// vmnet is used by QEMU and always used by incus (even with VZ)
|
||||
useVmnet := conf.VMType == limaconfig.QEMU || conf.Runtime == incus.Name
|
||||
useVmnet := conf.VMType == limaconfig.QEMU || conf.Runtime == incus.Name || conf.Network.Mode == "bridged"
|
||||
|
||||
// network daemon is only needed for vmnet
|
||||
conf.Network.Address = conf.Network.Address && useVmnet
|
||||
|
||||
@@ -33,8 +33,10 @@ func (l *limaVM) setupDNS(conf config.Config) error {
|
||||
internalIP := limautil.InternalIPAddress(config.CurrentProfile().ID)
|
||||
|
||||
// extra dns entries
|
||||
dnsHosts[conf.Hostname] = localhostAddr
|
||||
dnsHosts["colima.internal"] = internalIP
|
||||
if (conf.Hostname) != "" {
|
||||
dnsHosts[conf.Hostname] = localhostAddr
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
|
||||
@@ -133,8 +133,8 @@ func newConf(ctx context.Context, conf config.Config) (l limaconfig.Config, err
|
||||
|
||||
reachableIPAddress := true
|
||||
if conf.Network.Address {
|
||||
// incus always uses vmnet
|
||||
if l.VMType == limaconfig.VZ && conf.Runtime != incus.Name {
|
||||
// vmnet is always used for incus runtime or bridged mode
|
||||
if l.VMType == limaconfig.VZ && conf.Runtime != incus.Name && conf.Network.Mode != "bridged" {
|
||||
l.Networks = append(l.Networks, limaconfig.Network{
|
||||
VZNAT: true,
|
||||
Interface: limautil.NetInterface,
|
||||
|
||||
Reference in New Issue
Block a user