package server import ( "bufio" "io/ioutil" "os" "os/exec" "path" "strings" "time" "github.com/kvaps/dnsmasq-controller/pkg/conf" ctrl "sigs.k8s.io/controller-runtime" ) var ( serverLog = ctrl.Log.WithName("server") dnsmasqLog = ctrl.Log.WithName("dnsmasq") ) func Start() error { config := conf.GetConfig() oldGen := 0 dnsmasqBinary, err := exec.LookPath("dnsmasq") if err != nil { panic("dnsmasq binary is not found!") } err = setupDir(config.DnsmasqConfDir, config.CleanupDir) if err != nil { panic(err) } args := []string{ "dnsmasq", "--no-daemon", "--no-hosts", "--conf-dir=" + config.DnsmasqConfDir, } if config.EnableDNS { args = append(args, "--addn-hosts="+config.DnsmasqConfDir+"/hosts", ) } else { args = append(args, "--port=0") } if config.EnableDHCP { args = append(args, "--dhcp-hostsfile="+config.DnsmasqConfDir+"/dhcp-hosts", "--dhcp-optsfile="+config.DnsmasqConfDir+"/dhcp-opts", ) } args = append(args, config.DnsmasqOptions...) serverLog.Info("Starting dnsmasq: " + strings.Join(args, " ")) cmd := serverStart(dnsmasqBinary, args) go func() { for { newGen := config.Generation time.Sleep(time.Duration(config.SyncDelay) * time.Second) if newGen != oldGen { serverLog.Info("Configuration changed, restarting dnsmasq.") serverStop(cmd) cmd = serverStart(dnsmasqBinary, args) serverLog.Info("Configuration reloaded.") oldGen = newGen } } }() return nil } func serverStart(dnsmasqBinary string, args []string) *exec.Cmd { cmd := &exec.Cmd{ Path: dnsmasqBinary, Args: args, } stderr, err := cmd.StderrPipe() if err != nil { panic(err) } if err := cmd.Start(); err != nil { panic(err) } buf := bufio.NewReader(stderr) go func() { for { line, _, err := buf.ReadLine() if err != nil { break } dnsmasqLog.Info(string(line)) } }() return cmd } func serverStop(cmd *exec.Cmd) { timer := time.AfterFunc(1*time.Second, func() { err := cmd.Process.Kill() if err != nil { panic(err) } }) cmd.Wait() timer.Stop() } func setupDir(p string, cleanup bool) error { dir, err := ioutil.ReadDir(p) if cleanup { for _, d := range dir { err = os.RemoveAll(path.Join([]string{p, d.Name()}...)) if err != nil { return err } } } dirs := []string{"/", "/hosts", "/dhcp-hosts", "/dhcp-opts"} for _, dir := range dirs { if _, err := os.Stat(p + dir); os.IsNotExist(err) { err := os.MkdirAll(p+dir, os.ModePerm) if err != nil { return err } } } return nil }