1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)
// newDNSMasqFile creates a new instance of a dnsNameFile
func newDNSMasqFile(domainName, networkInterface, networkName string) (dnsNameFile, error) {
dnsMasqBinary, err := exec.LookPath("dnsmasq")
if err != nil {
return dnsNameFile{}, errors.Errorf("the dnsmasq cni plugin requires the dnsmasq binary be in PATH")
}
masqConf := dnsNameFile{
ConfigFile: makePath(networkName, confFileName),
Domain: domainName,
PidFile: makePath(networkName, pidFileName),
NetworkInterface: networkInterface,
AddOnHostsFile: makePath(networkName, hostsFileName),
Binary: dnsMasqBinary,
}
return masqConf, nil
}
// hup sends a sighup to a running dnsmasq to reload its hosts file. if
// there is no instance of the dnsmasq, then it simply starts it.
func (d dnsNameFile) hup() error {
// First check for pidfile; if it does not exist, we just
// start the service
if _, err := os.Stat(d.PidFile); os.IsNotExist(err) {
return d.start()
}
pid, err := d.getProcess()
if err != nil {
return err
}
if !isRunning(pid) {
return d.start()
}
return pid.Signal(unix.SIGHUP)
}
// isRunning sends a signal 0 to the pid to determine if it
// responds or not
func isRunning(pid *os.Process) bool {
if err := pid.Signal(syscall.Signal(0)); err != nil {
return false
}
return true
}
// start starts the dnsmasq instance.
func (d dnsNameFile) start() error {
args := []string{
"-u",
"root",
fmt.Sprintf("--conf-file=%s", d.ConfigFile),
}
cmd := exec.Command(d.Binary, args...)
return cmd.Run()
}
// stop stops the dnsmasq instance.
func (d dnsNameFile) stop() error {
pid, err := d.getProcess()
if err != nil {
return err
}
return pid.Kill()
}
// getProcess reads the PID for the dnsmasq instance and returns an
// *os.Process. Returns an error if the PID does not exist.
func (d dnsNameFile) getProcess() (*os.Process, error) {
pidFileContents, err := ioutil.ReadFile(d.PidFile)
if err != nil {
return nil, err
}
pid, err := strconv.Atoi(strings.TrimSpace(string(pidFileContents)))
if err != nil {
return nil, err
}
return os.FindProcess(pid)
}
// makePath formats a path name given a domain and suffix
func makePath(networkName, fileName string) string {
// the generic path for where conf, host, pid files are kept is:
// /run/containers/cni/dnsmasq/<network-name>/
return filepath.Join(dnsNameConfPath, networkName, fileName)
}
|