diff --git a/plugins/ipam/dhcp/README.md b/plugins/ipam/dhcp/README.md index 885eb09f..55e5396c 100644 --- a/plugins/ipam/dhcp/README.md +++ b/plugins/ipam/dhcp/README.md @@ -16,6 +16,9 @@ $ rm -f /run/cni/dhcp.sock $ ./dhcp daemon ``` +If given `-pidfile ` arguments after 'daemon', the dhcp plugin will write +its PID to the given file. + Alternatively, you can use systemd socket activation protocol. Be sure that the .socket file uses /run/cni/dhcp.sock as the socket path. diff --git a/plugins/ipam/dhcp/daemon.go b/plugins/ipam/dhcp/daemon.go index c6660b7e..0b1dadfe 100644 --- a/plugins/ipam/dhcp/daemon.go +++ b/plugins/ipam/dhcp/daemon.go @@ -18,7 +18,7 @@ import ( "encoding/json" "errors" "fmt" - "log" + "io/ioutil" "net" "net/http" "net/rpc" @@ -141,19 +141,29 @@ func getListener() (net.Listener, error) { } } -func runDaemon() { +func runDaemon(pidfilePath string) error { // since other goroutines (on separate threads) will change namespaces, // ensure the RPC server does not get scheduled onto those runtime.LockOSThread() + // Write the pidfile + if pidfilePath != "" { + if !filepath.IsAbs(pidfilePath) { + return fmt.Errorf("Error writing pidfile %q: path not absolute", pidfilePath) + } + if err := ioutil.WriteFile(pidfilePath, []byte(fmt.Sprintf("%d", os.Getpid())), 0644); err != nil { + return fmt.Errorf("Error writing pidfile %q: %v", pidfilePath, err) + } + } + l, err := getListener() if err != nil { - log.Printf("Error getting listener: %v", err) - return + return fmt.Errorf("Error getting listener: %v", err) } dhcp := newDHCP() rpc.Register(dhcp) rpc.HandleHTTP() http.Serve(l, nil) + return nil } diff --git a/plugins/ipam/dhcp/main.go b/plugins/ipam/dhcp/main.go index 9289957a..2e55c27a 100644 --- a/plugins/ipam/dhcp/main.go +++ b/plugins/ipam/dhcp/main.go @@ -15,7 +15,9 @@ package main import ( + "flag" "fmt" + "log" "net/rpc" "os" "path/filepath" @@ -30,7 +32,15 @@ const socketPath = "/run/cni/dhcp.sock" func main() { if len(os.Args) > 1 && os.Args[1] == "daemon" { - runDaemon() + var pidfilePath string + daemonFlags := flag.NewFlagSet("daemon", flag.ExitOnError) + daemonFlags.StringVar(&pidfilePath, "pidfile", "", "optional path to write daemon PID to") + daemonFlags.Parse(os.Args[2:]) + + if err := runDaemon(pidfilePath); err != nil { + log.Printf(err.Error()) + os.Exit(1) + } } else { skel.PluginMain(cmdAdd, cmdDel, version.All) }