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)
}
|