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

network update #227

Merged
merged 17 commits into from
Mar 19, 2022
Merged
Prev Previous commit
Next Next commit
net: vmnet works
  • Loading branch information
abiosoft committed Mar 13, 2022
commit ad19f3b0a4a453e90dcf45a9420216c8fcd784fb
17 changes: 9 additions & 8 deletions cmd/vmnet/vmnet.go
Original file line number Diff line number Diff line change
@@ -25,34 +25,35 @@ const vmnetBinary = "/opt/colima/bin/vde_vmnet"

// PTPFile returns path to the ptp socket file.
func PTPFile() (string, error) {
s, err := networkPath()
dir, err := Dir()
if err != nil {
return s, err
return dir, err
}

return filepath.Join(s, vmnetFileName+".ptp"), nil
return filepath.Join(dir, vmnetFileName+".ptp"), nil
}

func networkPath() (string, error) {
// Dir is the network configuration directory.
func Dir() (string, error) {
dir := filepath.Join(config.Dir(), "network")
if err := os.MkdirAll(dir, 0755); err != nil {
return "", fmt.Errorf("error creating network directory: %w", err)
}
return dir, nil
}

// rootCmd represents the base command when called without any subcommands
// vmnetCmd represents the base command when called without any subcommands
var vmnetCmd = &cobra.Command{
Use: "vmnet",
Short: "vde_vmnet manager",
Long: `vde_vmnet manager to start and stop vde_vmnet daemons.`,
Short: "vde_vmnet runner",
Long: `vde_vmnet runner for vde_vmnet daemons.`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
cmd.SilenceUsage = true
cmd.SilenceErrors = true
},
}

// kubernetesStartCmd represents the kubernetes start command
// startCmd represents the kubernetes start command
var startCmd = &cobra.Command{
Use: "start",
Short: "start daemon",
4 changes: 3 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ import (

const AppName = "colima"

var profile = ProfileInfo{ID: AppName, DisplayName: AppName}
var profile = ProfileInfo{ID: AppName, DisplayName: AppName, ShortName: AppName}

// SetProfile sets the profile name for the application.
// This is an avenue to test Colima without breaking an existing stable setup.
@@ -29,6 +29,7 @@ func SetProfile(profileName string) {
// use a prefix to prevent possible name clashes
profile.ID = "colima-" + profileName
profile.DisplayName = "colima [profile=" + profileName + "]"
profile.ShortName = profileName
}

// Profile returns the current application profile.
@@ -38,6 +39,7 @@ func Profile() ProfileInfo { return profile }
type ProfileInfo struct {
ID string
DisplayName string
ShortName string
}

// VersionInfo is the application version info.
File renamed without changes.
29 changes: 29 additions & 0 deletions embedded/network/vmnet.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>{{.Label}}</string>
<key>ProgramArguments</key>
<array>
<string>sudo</string>
<string>{{.Binary}}</string>
<string>start</string>
<string>{{.Profile}}</string>
</array>
<key>StandardErrorPath</key>
<string>{{.Stderr}}</string>
<key>StandardOutPath</key>
<string>{{.Stdout}}</string>
<key>RunAtLoad</key>
<true />
<key>KeepAlive</key>
<dict>
<key>PathState</key>
<dict>
<key>{{.PidFile}}</key>
<true />
</dict>
</dict>
</dict>
</plist>
88 changes: 88 additions & 0 deletions environment/vm/lima/launchd_vmnet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package lima

import (
"fmt"
"os"
"path/filepath"

"github.com/abiosoft/colima/cmd/vmnet"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/embedded"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/util"
)

type launchdManager struct {
host environment.HostActions
}

func (l launchdManager) Dir() string {
home := util.HomeDir()
return filepath.Join(home, "Library", "LaunchAgents")
}

func (l launchdManager) Label() string {
return packageNamePrefix + "." + config.Profile().ID
}

func (l launchdManager) File() string {
return filepath.Join(l.Dir(), l.Label()+".plist")
}

func (l launchdManager) Running() bool {
return l.host.RunQuiet("launchctl", "list", l.Label()) == nil
}

func (l launchdManager) Start() error {
return l.host.RunQuiet("launchctl", "load", l.File())
}

func (l launchdManager) Kill() error {
return l.host.RunQuiet("launchctl", "unload", l.File())
}

const packageNamePrefix = "com.abiosoft.colima"
const colimaVmnetBinary = "/opt/colima/bin/colima-vmnet"

func (l launchdManager) createVmnetScript() error {
if err := os.MkdirAll(l.Dir(), 0755); err != nil {
return fmt.Errorf("error creating launchd directory: %w", err)
}

if stat, err := os.Stat(l.File()); err == nil {
if stat.IsDir() {
return fmt.Errorf("launchd file: directory not expected at '%s'", l.File())
}
}

vmnetDir, err := vmnet.Dir()
if err != nil {
return fmt.Errorf("error starting network: %w", err)
}

var values = struct {
Label string
Profile string
Binary string
Stderr string
Stdout string
PidFile string
}{
Label: l.Label(),
Profile: config.Profile().ShortName,
Binary: colimaVmnetBinary,
Stdout: filepath.Join(vmnetDir, "vmnet.stdout"),
Stderr: filepath.Join(vmnetDir, "vmnet.stderr"),
PidFile: filepath.Join(vmnetDir, "vmnet.pid"),
}

plist, err := embedded.FS.ReadFile("network/vmnet.plist")
if err != nil {
return fmt.Errorf("error preparing launchd file: %w", err)
}
if err := util.WriteTemplate(string(plist), l.File(), values); err != nil {
return fmt.Errorf("error writing launchd file: %w", err)
}

return nil
}
34 changes: 33 additions & 1 deletion environment/vm/lima/lima.go
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@ func New(host environment.HostActions) environment.VM {
host: host.WithEnv(env),
home: home,
CommandChain: cli.New("vm"),
vmnet: launchdManager{host: host},
}
}

@@ -82,6 +83,9 @@ type limaVM struct {

// lima config directory
home string

// vmnetManager
vmnet launchdManager
}

func (l limaVM) Dependencies() []string {
@@ -90,15 +94,41 @@ func (l limaVM) Dependencies() []string {
}
}

func (l limaVM) prepareNetwork() {
a := l.Init()
log := l.Logger()

a.Stage("preparing network")

a.Add(func() error {
if l.vmnet.Running() {
l.vmnet.Kill()
}
return nil
})

a.Add(l.vmnet.createVmnetScript)
a.Add(l.vmnet.Start)

// network failure is not fatal
if err := a.Exec(); err != nil {
log.Warnln(fmt.Errorf("error starting network: %w", err))
} else {
// delay a bit to prevent race condition with vmnet
time.Sleep(time.Second * 2)
}
}

func (l *limaVM) Start(conf config.Config) error {
a := l.Init()

if l.Created() {
return l.resume(conf)
}

a.Stage("creating and starting")
l.prepareNetwork() // this is correct, the file should exist

a.Stage("creating and starting")
configFile := filepath.Join(os.TempDir(), config.Profile().ID+".yaml")

a.Add(func() error {
@@ -138,6 +168,8 @@ func (l limaVM) resume(conf config.Config) error {
return nil
}

l.prepareNetwork()

configFile := filepath.Join(l.limaConfDir(), "lima.yaml")

a.Add(func() error {
13 changes: 8 additions & 5 deletions environment/vm/lima/yaml.go
Original file line number Diff line number Diff line change
@@ -47,15 +47,18 @@ func newConf(conf config.Config) (l Config, err error) {

// networking on Lima is limited to macOS
if runtime.GOOS == "darwin" {
ptpFile, err := vmnet.PTPFile()
if err != nil {
logrus.Warn("error setting up networking, VM will not have a reachable IP address: %w", err)
} else {
// only set network settings if vmnet startup is successful
func() {
ptpFile, err := vmnet.PTPFile()
if err != nil {
logrus.Warn(fmt.Errorf("error setting up networking, VM will not have a reachable IP address: %w", err))
return
}
l.Networks = append(l.Networks, Network{
VNL: ptpFile,
SwitchPort: 65535, // this is fixed
})
}
}()
}

// port forwarding