mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
Currently, ctrld assumes that NetworkManager is not available if writing to /etc/NetworkManager/conf.d return directory not exist error. That would work on most Linux distros. However, cloud provider may do some hacks, causing ctrld confusion and think that NetworkManager is available. Fixing this by checking whether NetworkManager binary presents first. While at it, also fixing a bug when restarting NetworkManager failed causing ctrld hangs. The go-systemd library is not clear about this, but the waitCh channel won't never be closed if error occurred, so we must return immediately instead of receiving from it blindly.
90 lines
2.2 KiB
Go
90 lines
2.2 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/coreos/go-systemd/v22/dbus"
|
|
)
|
|
|
|
const (
|
|
nmConfDir = "/etc/NetworkManager/conf.d"
|
|
nmCtrldConfFilename = "99-ctrld.conf"
|
|
nmCtrldConfContent = `[main]
|
|
dns=none
|
|
systemd-resolved=false
|
|
`
|
|
nmSystemdUnitName = "NetworkManager.service"
|
|
)
|
|
|
|
var networkManagerCtrldConfFile = filepath.Join(nmConfDir, nmCtrldConfFilename)
|
|
|
|
// hasNetworkManager reports whether NetworkManager executable found.
|
|
func hasNetworkManager() bool {
|
|
exe, _ := exec.LookPath("NetworkManager")
|
|
return exe != ""
|
|
}
|
|
|
|
func setupNetworkManager() error {
|
|
if !hasNetworkManager() {
|
|
return nil
|
|
}
|
|
if content, _ := os.ReadFile(nmCtrldConfContent); string(content) == nmCtrldConfContent {
|
|
mainLog.Load().Debug().Msg("NetworkManager already setup, nothing to do")
|
|
return nil
|
|
}
|
|
err := os.WriteFile(networkManagerCtrldConfFile, []byte(nmCtrldConfContent), os.FileMode(0644))
|
|
if os.IsNotExist(err) {
|
|
mainLog.Load().Debug().Msg("NetworkManager is not available")
|
|
return nil
|
|
}
|
|
if err != nil {
|
|
mainLog.Load().Debug().Err(err).Msg("could not write NetworkManager ctrld config file")
|
|
return err
|
|
}
|
|
|
|
reloadNetworkManager()
|
|
mainLog.Load().Debug().Msg("setup NetworkManager done")
|
|
return nil
|
|
}
|
|
|
|
func restoreNetworkManager() error {
|
|
if !hasNetworkManager() {
|
|
return nil
|
|
}
|
|
err := os.Remove(networkManagerCtrldConfFile)
|
|
if os.IsNotExist(err) {
|
|
mainLog.Load().Debug().Msg("NetworkManager is not available")
|
|
return nil
|
|
}
|
|
if err != nil {
|
|
mainLog.Load().Debug().Err(err).Msg("could not remove NetworkManager ctrld config file")
|
|
return err
|
|
}
|
|
|
|
reloadNetworkManager()
|
|
mainLog.Load().Debug().Msg("restore NetworkManager done")
|
|
return nil
|
|
}
|
|
|
|
func reloadNetworkManager() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
|
defer cancel()
|
|
conn, err := dbus.NewSystemConnectionContext(ctx)
|
|
if err != nil {
|
|
mainLog.Load().Error().Err(err).Msg("could not create new system connection")
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
waitCh := make(chan string)
|
|
if _, err := conn.ReloadUnitContext(ctx, nmSystemdUnitName, "ignore-dependencies", waitCh); err != nil {
|
|
mainLog.Load().Debug().Err(err).Msg("could not reload NetworkManager")
|
|
return
|
|
}
|
|
<-waitCh
|
|
}
|