2019-12-08 03:59:58 -05:00
|
|
|
|
package rpc
|
2019-12-07 05:14:40 -05:00
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2021-01-13 09:30:28 -05:00
|
|
|
|
"fmt"
|
2021-04-07 09:11:59 -04:00
|
|
|
|
"log"
|
2021-01-16 01:11:51 -05:00
|
|
|
|
"strings"
|
2020-10-24 09:29:05 -04:00
|
|
|
|
"time"
|
2019-12-07 05:14:40 -05:00
|
|
|
|
|
2020-11-10 21:07:45 -05:00
|
|
|
|
"github.com/naiba/nezha/model"
|
|
|
|
|
pb "github.com/naiba/nezha/proto"
|
|
|
|
|
"github.com/naiba/nezha/service/dao"
|
2019-12-07 05:14:40 -05:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type NezhaHandler struct {
|
|
|
|
|
Auth *AuthHandler
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 11:45:49 -05:00
|
|
|
|
func (s *NezhaHandler) ReportTask(c context.Context, r *pb.TaskResult) (*pb.Receipt, error) {
|
2019-12-09 05:14:31 -05:00
|
|
|
|
var err error
|
2021-01-18 20:59:04 -05:00
|
|
|
|
var clientID uint64
|
|
|
|
|
if clientID, err = s.Auth.Check(c); err != nil {
|
2021-01-15 11:45:49 -05:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2021-01-18 20:59:04 -05:00
|
|
|
|
if r.GetType() == model.TaskTypeHTTPGET {
|
2021-01-16 01:11:51 -05:00
|
|
|
|
// SSL 证书报警
|
2021-01-17 02:43:34 -05:00
|
|
|
|
var errMsg string
|
|
|
|
|
if strings.HasPrefix(r.GetData(), "SSL证书错误:") {
|
2021-03-02 10:08:40 -05:00
|
|
|
|
// 排除 i/o timeont、connection timeout、EOF 错误
|
2021-03-19 22:05:16 -04:00
|
|
|
|
if !strings.HasSuffix(r.GetData(), "timeout") &&
|
2021-04-07 09:11:59 -04:00
|
|
|
|
!strings.HasSuffix(r.GetData(), "EOF") &&
|
2021-03-19 22:05:16 -04:00
|
|
|
|
!strings.HasSuffix(r.GetData(), "timed out") {
|
2021-02-25 07:00:16 -05:00
|
|
|
|
errMsg = r.GetData()
|
|
|
|
|
}
|
2021-01-17 02:43:34 -05:00
|
|
|
|
} else {
|
|
|
|
|
var last model.MonitorHistory
|
2021-01-25 20:12:48 -05:00
|
|
|
|
var newCert = strings.Split(r.GetData(), "|")
|
|
|
|
|
if len(newCert) > 1 {
|
2021-01-17 02:56:02 -05:00
|
|
|
|
expiresNew, _ := time.Parse("2006-01-02 15:04:05 -0700 MST", newCert[1])
|
2021-01-16 01:11:51 -05:00
|
|
|
|
// 证书过期提醒
|
2021-01-25 20:12:48 -05:00
|
|
|
|
if expiresNew.Before(time.Now().AddDate(0, 0, 7)) {
|
2021-01-16 01:11:51 -05:00
|
|
|
|
errMsg = fmt.Sprintf(
|
|
|
|
|
"SSL证书将在七天内过期,过期时间:%s。",
|
2021-01-17 02:56:02 -05:00
|
|
|
|
expiresNew.Format("2006-01-02 15:04:05"))
|
2021-01-16 01:11:51 -05:00
|
|
|
|
}
|
2021-01-25 20:12:48 -05:00
|
|
|
|
// 证书变更提醒
|
|
|
|
|
if err := dao.DB.Where("monitor_id = ? AND data LIKE ?", r.GetId(), "%|%").Order("id DESC").First(&last).Error; err == nil {
|
|
|
|
|
var oldCert = strings.Split(last.Data, "|")
|
|
|
|
|
var expiresOld time.Time
|
|
|
|
|
if len(oldCert) > 1 {
|
|
|
|
|
expiresOld, _ = time.Parse("2006-01-02 15:04:05 -0700 MST", oldCert[1])
|
|
|
|
|
}
|
|
|
|
|
if last.Data != "" && oldCert[0] != newCert[0] && !expiresNew.Equal(expiresOld) {
|
|
|
|
|
errMsg = fmt.Sprintf(
|
|
|
|
|
"SSL证书变更,旧:%s, %s 过期;新:%s, %s 过期。",
|
|
|
|
|
oldCert[0], expiresOld.Format("2006-01-02 15:04:05"), newCert[0], expiresNew.Format("2006-01-02 15:04:05"))
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-16 01:11:51 -05:00
|
|
|
|
}
|
2021-01-17 02:43:34 -05:00
|
|
|
|
}
|
|
|
|
|
if errMsg != "" {
|
|
|
|
|
var monitor model.Monitor
|
|
|
|
|
dao.DB.First(&monitor, "id = ?", r.GetId())
|
2021-01-23 20:41:35 -05:00
|
|
|
|
dao.SendNotification(fmt.Sprintf("服务监控:%s %s", monitor.Name, errMsg), true)
|
2021-01-15 11:45:49 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-18 20:59:04 -05:00
|
|
|
|
if r.GetType() == model.TaskTypeCommand {
|
|
|
|
|
// 处理上报的计划任务
|
|
|
|
|
dao.CronLock.RLock()
|
2021-01-23 02:32:04 -05:00
|
|
|
|
defer dao.CronLock.RUnlock()
|
2021-01-18 20:59:04 -05:00
|
|
|
|
cr := dao.Crons[r.GetId()]
|
2021-01-23 02:32:04 -05:00
|
|
|
|
if cr != nil {
|
|
|
|
|
if cr.PushSuccessful && r.GetSuccessful() {
|
2021-01-23 20:41:35 -05:00
|
|
|
|
dao.SendNotification(fmt.Sprintf("成功计划任务:%s ,服务器:%d,日志:\n%s", cr.Name, clientID, r.GetData()), false)
|
2021-01-23 02:32:04 -05:00
|
|
|
|
}
|
|
|
|
|
if !r.GetSuccessful() {
|
2021-01-23 20:41:35 -05:00
|
|
|
|
dao.SendNotification(fmt.Sprintf("失败计划任务:%s ,服务器:%d,日志:\n%s", cr.Name, clientID, r.GetData()), false)
|
2021-01-23 02:32:04 -05:00
|
|
|
|
}
|
|
|
|
|
dao.DB.Model(cr).Updates(model.Cron{
|
|
|
|
|
LastExecutedAt: time.Now().Add(time.Second * -1 * time.Duration(r.GetDelay())),
|
|
|
|
|
LastResult: r.GetSuccessful(),
|
|
|
|
|
})
|
2021-01-18 20:59:04 -05:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 存入历史记录
|
|
|
|
|
mh := model.PB2MonitorHistory(r)
|
|
|
|
|
if err := dao.DB.Create(&mh).Error; err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2021-01-15 11:45:49 -05:00
|
|
|
|
}
|
2019-12-07 05:14:40 -05:00
|
|
|
|
return &pb.Receipt{Proced: true}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 11:45:49 -05:00
|
|
|
|
func (s *NezhaHandler) RequestTask(h *pb.Host, stream pb.NezhaService_RequestTaskServer) error {
|
2021-01-08 08:04:50 -05:00
|
|
|
|
var clientID uint64
|
2019-12-09 05:14:31 -05:00
|
|
|
|
var err error
|
|
|
|
|
if clientID, err = s.Auth.Check(stream.Context()); err != nil {
|
2019-12-07 05:14:40 -05:00
|
|
|
|
return err
|
|
|
|
|
}
|
2019-12-10 04:57:57 -05:00
|
|
|
|
closeCh := make(chan error)
|
2021-01-17 09:05:59 -05:00
|
|
|
|
dao.ServerLock.RLock()
|
2021-01-15 11:45:49 -05:00
|
|
|
|
dao.ServerList[clientID].TaskStream = stream
|
|
|
|
|
dao.ServerList[clientID].TaskClose = closeCh
|
2021-01-17 09:05:59 -05:00
|
|
|
|
dao.ServerLock.RUnlock()
|
2019-12-10 04:57:57 -05:00
|
|
|
|
select {
|
|
|
|
|
case err = <-closeCh:
|
|
|
|
|
return err
|
2019-12-09 03:02:49 -05:00
|
|
|
|
}
|
2019-12-07 05:14:40 -05:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 11:45:49 -05:00
|
|
|
|
func (s *NezhaHandler) ReportSystemState(c context.Context, r *pb.State) (*pb.Receipt, error) {
|
|
|
|
|
var clientID uint64
|
|
|
|
|
var err error
|
|
|
|
|
if clientID, err = s.Auth.Check(c); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
state := model.PB2State(r)
|
|
|
|
|
dao.ServerLock.RLock()
|
|
|
|
|
defer dao.ServerLock.RUnlock()
|
2021-01-18 00:45:06 -05:00
|
|
|
|
dao.ServerList[clientID].LastActive = time.Now()
|
2021-01-15 11:45:49 -05:00
|
|
|
|
dao.ServerList[clientID].State = &state
|
|
|
|
|
return &pb.Receipt{Proced: true}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *NezhaHandler) ReportSystemInfo(c context.Context, r *pb.Host) (*pb.Receipt, error) {
|
2021-01-08 08:04:50 -05:00
|
|
|
|
var clientID uint64
|
2019-12-09 05:14:31 -05:00
|
|
|
|
var err error
|
|
|
|
|
if clientID, err = s.Auth.Check(c); err != nil {
|
2019-12-07 05:14:40 -05:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2019-12-13 04:56:14 -05:00
|
|
|
|
host := model.PB2Host(r)
|
2019-12-10 04:57:57 -05:00
|
|
|
|
dao.ServerLock.RLock()
|
|
|
|
|
defer dao.ServerLock.RUnlock()
|
2021-04-07 09:11:59 -04:00
|
|
|
|
log.Println(dao.Conf.IgnoredIPNotificationServerIDs)
|
2021-01-15 22:23:42 -05:00
|
|
|
|
if dao.Conf.EnableIPChangeNotification &&
|
2021-04-07 09:11:59 -04:00
|
|
|
|
dao.Conf.IgnoredIPNotificationServerIDs[clientID] != struct{}{} &&
|
2021-01-15 22:23:42 -05:00
|
|
|
|
dao.ServerList[clientID].Host != nil &&
|
2021-01-13 09:30:28 -05:00
|
|
|
|
dao.ServerList[clientID].Host.IP != "" &&
|
|
|
|
|
host.IP != "" &&
|
|
|
|
|
dao.ServerList[clientID].Host.IP != host.IP {
|
2021-01-23 20:41:35 -05:00
|
|
|
|
dao.SendNotification(fmt.Sprintf(
|
2021-01-16 01:11:51 -05:00
|
|
|
|
"IP变更提醒 服务器:%s ,旧IP:%s,新IP:%s。",
|
2021-01-23 05:15:11 -05:00
|
|
|
|
dao.ServerList[clientID].Name, dao.ServerList[clientID].Host.IP, host.IP), true)
|
2021-01-13 09:30:28 -05:00
|
|
|
|
}
|
2019-12-13 04:56:14 -05:00
|
|
|
|
dao.ServerList[clientID].Host = &host
|
2019-12-07 05:14:40 -05:00
|
|
|
|
return &pb.Receipt{Proced: true}, nil
|
|
|
|
|
}
|