...
1 package server
2
3 import (
4 "bufio"
5 "io/ioutil"
6 "os"
7 "os/exec"
8 "path"
9 "strings"
10 "time"
11
12 "github.com/kvaps/dnsmasq-controller/pkg/conf"
13 ctrl "sigs.k8s.io/controller-runtime"
14 )
15
16 var (
17 serverLog = ctrl.Log.WithName("server")
18 dnsmasqLog = ctrl.Log.WithName("dnsmasq")
19 )
20
21 func Start() error {
22 config := conf.GetConfig()
23 oldGen := 0
24
25 dnsmasqBinary, err := exec.LookPath("dnsmasq")
26 if err != nil {
27 panic("dnsmasq binary is not found!")
28 }
29
30 err = setupDir(config.DnsmasqConfDir, config.CleanupDir)
31 if err != nil {
32 panic(err)
33 }
34
35 args := []string{
36 "dnsmasq",
37 "--no-daemon",
38 "--no-hosts",
39 "--conf-dir=" + config.DnsmasqConfDir,
40 }
41
42 if config.EnableDNS {
43 args = append(args,
44 "--addn-hosts="+config.DnsmasqConfDir+"/hosts",
45 )
46 } else {
47 args = append(args, "--port=0")
48 }
49 if config.EnableDHCP {
50 args = append(args,
51 "--dhcp-hostsfile="+config.DnsmasqConfDir+"/dhcp-hosts",
52 "--dhcp-optsfile="+config.DnsmasqConfDir+"/dhcp-opts",
53 )
54 }
55
56 args = append(args, config.DnsmasqOptions...)
57
58 serverLog.Info("Starting dnsmasq: " + strings.Join(args, " "))
59 cmd := serverStart(dnsmasqBinary, args)
60 go func() {
61 for {
62 newGen := config.Generation
63 time.Sleep(time.Duration(config.SyncDelay) * time.Second)
64 if newGen != oldGen {
65 serverLog.Info("Configuration changed, restarting dnsmasq.")
66 serverStop(cmd)
67 cmd = serverStart(dnsmasqBinary, args)
68 serverLog.Info("Configuration reloaded.")
69 oldGen = newGen
70 }
71 }
72 }()
73
74 return nil
75 }
76
77 func serverStart(dnsmasqBinary string, args []string) *exec.Cmd {
78 cmd := &exec.Cmd{
79 Path: dnsmasqBinary,
80 Args: args,
81 }
82 stderr, err := cmd.StderrPipe()
83 if err != nil {
84 panic(err)
85 }
86 if err := cmd.Start(); err != nil {
87 panic(err)
88 }
89 buf := bufio.NewReader(stderr)
90 go func() {
91 for {
92 line, _, err := buf.ReadLine()
93 if err != nil {
94 break
95 }
96 dnsmasqLog.Info(string(line))
97 }
98 }()
99 return cmd
100 }
101
102 func serverStop(cmd *exec.Cmd) {
103 timer := time.AfterFunc(1*time.Second, func() {
104 err := cmd.Process.Kill()
105 if err != nil {
106 panic(err)
107 }
108 })
109 cmd.Wait()
110 timer.Stop()
111 }
112
113 func setupDir(p string, cleanup bool) error {
114 dir, err := ioutil.ReadDir(p)
115 if cleanup {
116 for _, d := range dir {
117 err = os.RemoveAll(path.Join([]string{p, d.Name()}...))
118 if err != nil {
119 return err
120 }
121 }
122 }
123
124 dirs := []string{"/", "/hosts", "/dhcp-hosts", "/dhcp-opts"}
125 for _, dir := range dirs {
126 if _, err := os.Stat(p + dir); os.IsNotExist(err) {
127 err := os.MkdirAll(p+dir, os.ModePerm)
128 if err != nil {
129 return err
130 }
131 }
132 }
133 return nil
134 }
135
View as plain text