func detectInitd(root string) (InitSystem, error) { ctlpath := root + "etc/init.d/" result, err := util.FileExists(ctlpath) if err != nil { return nil, err } if !result { util.Debug("init.d not detected in " + ctlpath) return nil, nil } matches, err := filepath.Glob(ctlpath + "*") if err != nil { return nil, err } if !result { util.Debug("init.d not detected in " + ctlpath) return nil, nil } if len(matches) > 0 { util.Info("Detected init.d in " + ctlpath) return &Initd{ctlpath, root + "var/run/", pidForString}, nil } util.Info(ctlpath + " exists but appears to be empty") return nil, nil }
func (i *Initd) LookupService(serviceName string) (*ProcessStatus, error) { path := i.ctlPath + serviceName result, _ := util.FileExists(path) if !result { // service script does not exist in etc/init.d, not under // init.d control return nil, &ServiceError{i.Name(), serviceName, ErrServiceNotFound} } // First try to find the PID file with same name in /var/run. paths := []string{ i.varrunPath + serviceName + ".pid", i.varrunPath + serviceName + "/" + serviceName + ".pid", } for _, pidpath := range paths { st, err := i.readPidFile(pidpath) if err != nil { util.Info("Error processing PID file %s: %s", pidpath, err.Error()) continue } else if st != nil { return st, nil } else { util.Info("No such pidfile %s", pidpath) } } return &ProcessStatus{0, Down}, nil }
func verifyLicense(path string) (*License, error) { result, err := util.FileExists(path + "/license.bin") if err != nil { return nil, err } /* I am Alice. I have a public/private key. I generate and encrypt the license with my private key and Bob's public key. Bob's private key can decrypt the license. You cannot generate a license file unless you have Alice's private key. */ alicepub := [32]byte{ 0x2c, 0x6b, 0xe8, 0x2e, 0x1f, 0x62, 0x4a, 0x43, 0xe6, 0xd1, 0x69, 0xbc, 0x11, 0x4c, 0x05, 0x6f, 0xa4, 0xcd, 0x34, 0x8f, 0x9d, 0xdf, 0x07, 0x59, 0x82, 0x3f, 0x8a, 0x50, 0xcd, 0x20, 0x1e, 0x13, } bobprv := [32]byte{ 0x97, 0x95, 0xd6, 0xf1, 0xce, 0xf3, 0xb8, 0xf9, 0x05, 0x47, 0x6b, 0xb0, 0x69, 0x39, 0xad, 0xa5, 0xb3, 0x43, 0xcf, 0xf1, 0x8d, 0x32, 0xeb, 0x04, 0xc6, 0x6e, 0x64, 0x73, 0x62, 0xd8, 0x3f, 0x1b, } nonce := [24]byte{ 0x5e, 0xf8, 0x3d, 0xad, 0x43, 0x54, 0x2a, 0xe7, 0x8e, 0x13, 0x6c, 0xd7, 0x84, 0xd6, 0xc9, 0x61, 0xd6, 0x69, 0xc3, 0xcd, 0x1f, 0xd7, 0x8e, 0xbd, } if !result { fmt.Println("Unlicensed, non-production use only! Purchase at http://contribsys.com/inspeqtor") return &License{}, nil } enc, err := ioutil.ReadFile(path + "/license.bin") if err != nil { return nil, err } dec, ok := box.Open(nil, enc, &nonce, &alicepub, &bobprv) if !ok { return nil, errors.New("Invalid license file") } newdoc := &License{} err = json.Unmarshal(dec, newdoc) if err != nil { return nil, errors.New("Corrupt license file?") } if newdoc.HostLimit > 0 { fmt.Printf("Licensed to %s for up to %d hosts\n", newdoc.Org, newdoc.HostLimit) } else { fmt.Printf("Licensed to %s, unlimited hosts\n", newdoc.Org) } fmt.Println("") return newdoc, nil }
func ParseGlobal(rootDir string) (*ConfigFile, error) { path := rootDir + "/inspeqtor.conf" exists, err := util.FileExists(path) if err != nil { return nil, err } if exists { util.Debug("Parsing " + path) data, err := ioutil.ReadFile(path) if err != nil { return nil, err } s := lexer.NewLexer([]byte(data)) p := parser.NewParser() obj, err := p.Parse(s) if err != nil { return nil, err } ast := obj.(ast.Config) config := ConfigFile{Defaults, map[string]*AlertRoute{}} config.Variables = ast.Variables if val, has := ast.Variables["log_level"]; has { util.SetLogLevel(val) } parseValue(ast, &config.CycleTime, "cycle_time", 15) parseValue(ast, &config.DeployLength, "deploy_length", 300) parseValue(ast, &config.ExposePort, "expose_port", 4677) for _, v := range ast.Routes { ar, err := ValidateChannel(v.Name, v.Channel, v.Config) if err != nil { return nil, err } if _, ok := config.AlertRoutes[v.Name]; ok { return nil, fmt.Errorf("Duplicate alert config for '%s'", v.Name) } config.AlertRoutes[v.Name] = ar } return &config, nil } util.Info("No configuration file found at " + rootDir + "/inspector.conf") return &ConfigFile{Defaults, nil}, nil }
func (hs *hostStorage) collectLoadAverage() error { // TODO make this a one-time check so we don't incur the overhead // on every cycle. ok, err := util.FileExists(hs.path + "/loadavg") if err != nil { return err } var loadavgString string if ok { contentBytes, err := ioutil.ReadFile(hs.path + "/loadavg") if err != nil { return err } loadavgString = string(contentBytes) } else { cmd := exec.Command("sysctl", "-n", "vm.loadavg") cmd.Env = []string{"LANG=C"} sout, err := util.SafeRun(cmd) if err != nil { return err } lines, err := util.ReadLines(sout) if err != nil { return err } loadavgString = lines[0][2 : len(lines[0])-2] // trim braces } slices := strings.Split(loadavgString, " ") load1, err := strconv.ParseFloat(slices[0], 64) if err != nil { return err } load5, err := strconv.ParseFloat(slices[1], 64) if err != nil { return err } load15, err := strconv.ParseFloat(slices[2], 64) if err != nil { return err } hs.Save("load", "1", load1) hs.Save("load", "5", load5) hs.Save("load", "15", load15) return nil }
func (ps *processStorage) Collect(pid int) error { var err error ok, err := util.FileExists(ps.path) if err != nil { return err } if !ok { // we don't have the /proc filesystem, e.g. darwin or freebsd // use `ps` output instead. err = ps.capturePs(pid) if err != nil { return err } } else { err = ps.captureVM(pid) if err != nil { return err } err = ps.captureCPU(pid) if err != nil { return err } } for _, fn := range ps.dyncol { err = fn(pid, ps) if err != nil { return err } } for _, x := range ps.daemonSpecific { data, err := x.Capture() if err != nil { return err } for k, v := range data { ps.Save(x.Name(), k, v) } } return nil }
func (hs *hostStorage) collectCPU() error { ok, err := util.FileExists(hs.path + "/stat") if err != nil { return err } if ok { contents, err := ioutil.ReadFile(hs.path + "/stat") if err != nil { return err } lines := strings.Split(string(contents), "\n") line := lines[0] fields := strings.Fields(line) user, _ := strconv.ParseInt(fields[1], 10, 64) nice, _ := strconv.ParseInt(fields[2], 10, 64) system, _ := strconv.ParseInt(fields[3], 10, 64) iowait, _ := strconv.ParseInt(fields[5], 10, 64) irq, _ := strconv.ParseInt(fields[6], 10, 64) softIrq, _ := strconv.ParseInt(fields[7], 10, 64) steal, _ := strconv.ParseInt(fields[8], 10, 64) total := user + nice + system + iowait + irq + softIrq + steal // These are the five I can envision writing rules against. // Open an issue if you want access to the other values. hs.Save("cpu", "", float64(total)) hs.Save("cpu", "user", float64(user)) hs.Save("cpu", "system", float64(system)) hs.Save("cpu", "iowait", float64(iowait)) hs.Save("cpu", "steal", float64(steal)) } else { // TODO util.Info("Cannot collect host CPU metrics, not implemented on this platform") } return nil }
/* Parses the host-specific rules in /etc/inspeqtor/host.inq */ func ParseHost(global *ConfigFile, hostInq string) (*Host, error) { var host *Host result, err := util.FileExists(hostInq) if err != nil { return nil, err } if !result { return nil, fmt.Errorf("Missing required file: %s", hostInq) } util.DebugDebug("Parsing " + hostInq) data, err := ioutil.ReadFile(hostInq) if err != nil { return nil, err } s := lexer.NewLexer([]byte(data)) p := parser.NewParser() obj, err := p.Parse(s) if err != nil { return nil, err } switch x := obj.(type) { case *ast.HostCheck: host, err = BuildHost(global, x) if err != nil { return nil, err } util.DebugDebug("Host: %+v", *host) default: return nil, fmt.Errorf("Invalid host.inq configuration file") } return host, nil }
func detectUpstart(path string) (InitSystem, error) { result, err := util.FileExists(path) if err != nil { return nil, err } if !result { util.Debug("upstart not detected, no " + path) return nil, nil } matches, err := filepath.Glob(path + "/*.conf") if err != nil { return nil, err } if len(matches) > 0 { util.Info("Detected upstart in " + path) return &Upstart{path, nil}, nil } util.Debug("upstart not detected, empty " + path) return nil, nil }
func (rs *mysqlSource) buildArgs() []string { args := []string{"-B"} socket := false if rs.Socket != "" { result, err := util.FileExists(rs.Socket) if result && err == nil { socket = true } } if socket { args = append(args, "-S") args = append(args, rs.Socket) } else { if rs.Hostname != "" { args = append(args, "-h") args = append(args, rs.Hostname) } if rs.Port != "" { args = append(args, "-P") args = append(args, rs.Port) } } if rs.Username != "" { args = append(args, "-u") args = append(args, rs.Username) } if rs.Password != "" { args = append(args, "-p") args = append(args, rs.Password) } return args }
func (i *Initd) readPidFile(path string) (*ProcessStatus, error) { result, err := util.FileExists(path) if err != nil { return nil, err } if !result { return nil, nil } data, err := ioutil.ReadFile(path) if err != nil { return nil, err } pid, err := i.pidParser(data) if err != nil { return nil, err } err = syscall.Kill(pid, syscall.Signal(0)) if err != nil { return nil, err } return &ProcessStatus{pid, Up}, nil }
func detectSystemd(path string) (InitSystem, error) { result, err := util.FileExists(path) if err != nil { return nil, err } if !result { util.Debug("systemd not detected, no " + path) return nil, nil } matches, err := filepath.Glob(path + "/*.conf") if err != nil { return nil, err } if len(matches) > 0 { util.Info("Detected systemd in " + path) return &Systemd{path, "", ""}, nil } util.Debug("systemd not detected, empty " + path) return nil, nil }
func (hs *hostStorage) collectMemory() error { ok, err := util.FileExists(hs.path + "/meminfo") if err != nil { return err } if ok { contentBytes, err := ioutil.ReadFile(hs.path + "/meminfo") if err != nil { return err } lines := strings.Split(string(contentBytes), "\n") memMetrics := make(map[string]float64) for _, line := range lines { if line == "" { continue } results := meminfoParser.FindStringSubmatch(line) if results == nil { util.Warn("Unknown input: " + line) continue } val, err := strconv.ParseInt(results[2], 10, 64) if err != nil { util.Warn("Unexpected input: " + results[2] + " in " + line) return err } memMetrics[results[1]] = float64(val) } free := memMetrics["SwapFree"] total := memMetrics["SwapTotal"] if free == 0 { hs.Save("swap", "", 100) } else if free == total { hs.Save("swap", "", 0) } else { hs.Save("swap", "", float64(100-int8(100*(float64(free)/float64(total))))) } } else { cmd := exec.Command("sysctl", "-n", "vm.swapusage") cmd.Env = []string{"LANG=C"} sout, err := util.SafeRun(cmd) if err != nil { return err } lines, err := util.ReadLines(sout) if err != nil { return err } rest := lines[0] matches := swapRegexp.FindStringSubmatch(rest) total := matches[1] rest = matches[2] matches = swapRegexp.FindStringSubmatch(rest) used := matches[1] tot, err := strconv.ParseFloat(total[0:len(total)-1], 64) if err != nil { return err } usd, err := strconv.ParseFloat(used[0:len(used)-1], 64) if err != nil { return err } t := normalizeSwap(tot, rune(total[len(total)-1])) u := normalizeSwap(usd, rune(used[len(used)-1])) if t == 0 { hs.Save("swap", "", 100) } else { hs.Save("swap", "", float64(100*(u/t))) } } return nil }