180 lines
No EOL
4.3 KiB
Go
180 lines
No EOL
4.3 KiB
Go
package checks
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"runtime"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/amidaware/rmmagent/agent/system"
|
|
"github.com/amidaware/rmmagent/agent/utils"
|
|
rmm "github.com/amidaware/rmmagent/shared"
|
|
ps "github.com/elastic/go-sysinfo"
|
|
"github.com/go-resty/resty/v2"
|
|
)
|
|
|
|
func CheckRunner(agentID string) {
|
|
sleepDelay := utils.RandRange(14, 22)
|
|
//a.Logger.Debugf("CheckRunner() init sleeping for %v seconds", sleepDelay)
|
|
time.Sleep(time.Duration(sleepDelay) * time.Second)
|
|
for {
|
|
interval, err := GetCheckInterval(agentID)
|
|
if err == nil && !ChecksRunning() {
|
|
if runtime.GOOS == "windows" {
|
|
_, err = system.CMD(system.GetProgramEXE(), []string{"-m", "checkrunner"}, 600, false)
|
|
if err != nil {
|
|
//a.Logger.Errorln("Checkrunner RunChecks", err)
|
|
}
|
|
} else {
|
|
RunChecks(agentID, false)
|
|
}
|
|
}
|
|
|
|
//a.Logger.Debugln("Checkrunner sleeping for", interval)
|
|
time.Sleep(time.Duration(interval) * time.Second)
|
|
}
|
|
}
|
|
|
|
func GetCheckInterval(agentID string) (int, error) {
|
|
r, err := a.rClient.R().SetResult(&rmm.CheckInfo{}).Get(fmt.Sprintf("/api/v3/%s/checkinterval/", a.AgentID))
|
|
if err != nil {
|
|
a.Logger.Debugln(err)
|
|
return 120, err
|
|
}
|
|
if r.IsError() {
|
|
a.Logger.Debugln("Checkinterval response code:", r.StatusCode())
|
|
return 120, fmt.Errorf("checkinterval response code: %v", r.StatusCode())
|
|
}
|
|
interval := r.Result().(*rmm.CheckInfo).Interval
|
|
return interval, nil
|
|
}
|
|
|
|
// ChecksRunning prevents duplicate checks from running
|
|
// Have to do it this way, can't use atomic because they can run from both rpc and tacticalagent services
|
|
func ChecksRunning() bool {
|
|
running := false
|
|
procs, err := ps.Processes()
|
|
if err != nil {
|
|
return running
|
|
}
|
|
Out:
|
|
for _, process := range procs {
|
|
p, err := process.Info()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if p.PID == 0 {
|
|
continue
|
|
}
|
|
if p.Exe != system.GetProgramEXE() {
|
|
continue
|
|
}
|
|
|
|
for _, arg := range p.Args {
|
|
if arg == "runchecks" || arg == "checkrunner" {
|
|
running = true
|
|
break Out
|
|
}
|
|
}
|
|
}
|
|
|
|
return running
|
|
}
|
|
|
|
func RunChecks(agentID string, force bool) error {
|
|
data := rmm.AllChecks{}
|
|
var url string
|
|
if force {
|
|
url = fmt.Sprintf("/api/v3/%s/runchecks/", agentID)
|
|
} else {
|
|
url = fmt.Sprintf("/api/v3/%s/checkrunner/", agentID)
|
|
}
|
|
|
|
r, err := a.rClient.R().Get(url)
|
|
if err != nil {
|
|
//a.Logger.Debugln(err)
|
|
return err
|
|
}
|
|
|
|
if r.IsError() {
|
|
//a.Logger.Debugln("Checkrunner response code:", r.StatusCode())
|
|
return nil
|
|
}
|
|
|
|
if err := json.Unmarshal(r.Body(), &data); err != nil {
|
|
//a.Logger.Debugln(err)
|
|
return err
|
|
}
|
|
|
|
var wg sync.WaitGroup
|
|
eventLogChecks := make([]rmm.Check, 0)
|
|
winServiceChecks := make([]rmm.Check, 0)
|
|
for _, check := range data.Checks {
|
|
switch check.CheckType {
|
|
case "diskspace":
|
|
wg.Add(1)
|
|
go func(c rmm.Check, wg *sync.WaitGroup, r *resty.Client) {
|
|
defer wg.Done()
|
|
utils.RandomCheckDelay()
|
|
a.SendDiskCheckResult(a.DiskCheck(c), r)
|
|
}(check, &wg, a.rClient)
|
|
case "cpuload":
|
|
wg.Add(1)
|
|
go func(c rmm.Check, wg *sync.WaitGroup, r *resty.Client) {
|
|
defer wg.Done()
|
|
a.CPULoadCheck(c, r)
|
|
}(check, &wg, a.rClient)
|
|
case "memory":
|
|
wg.Add(1)
|
|
go func(c rmm.Check, wg *sync.WaitGroup, r *resty.Client) {
|
|
defer wg.Done()
|
|
randomCheckDelay()
|
|
a.MemCheck(c, r)
|
|
}(check, &wg, a.rClient)
|
|
case "ping":
|
|
wg.Add(1)
|
|
go func(c rmm.Check, wg *sync.WaitGroup, r *resty.Client) {
|
|
defer wg.Done()
|
|
randomCheckDelay()
|
|
a.SendPingCheckResult(a.PingCheck(c), r)
|
|
}(check, &wg, a.rClient)
|
|
case "script":
|
|
wg.Add(1)
|
|
go func(c rmm.Check, wg *sync.WaitGroup, r *resty.Client) {
|
|
defer wg.Done()
|
|
randomCheckDelay()
|
|
a.ScriptCheck(c, r)
|
|
}(check, &wg, a.rClient)
|
|
case "winsvc":
|
|
winServiceChecks = append(winServiceChecks, check)
|
|
case "eventlog":
|
|
eventLogChecks = append(eventLogChecks, check)
|
|
default:
|
|
continue
|
|
}
|
|
}
|
|
|
|
if len(winServiceChecks) > 0 {
|
|
wg.Add(len(winServiceChecks))
|
|
go func(wg *sync.WaitGroup, r *resty.Client) {
|
|
for _, winSvcCheck := range winServiceChecks {
|
|
defer wg.Done()
|
|
a.SendWinSvcCheckResult(a.WinSvcCheck(winSvcCheck), r)
|
|
}
|
|
}(&wg, a.rClient)
|
|
}
|
|
|
|
if len(eventLogChecks) > 0 {
|
|
wg.Add(len(eventLogChecks))
|
|
go func(wg *sync.WaitGroup, r *resty.Client) {
|
|
for _, evtCheck := range eventLogChecks {
|
|
defer wg.Done()
|
|
a.EventLogCheck(evtCheck, r)
|
|
}
|
|
}(&wg, a.rClient)
|
|
}
|
|
|
|
wg.Wait()
|
|
return nil
|
|
} |