Added framework for alarms, code cleanup
This commit is contained in:
parent
f108090967
commit
2d99960f06
19
alarm/alarm.go
Normal file
19
alarm/alarm.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package alarm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Alarm interface {
|
||||||
|
Parse(string) (bool, error)
|
||||||
|
Alarm() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAlarm(name string, typename string) (Alarm, error) {
|
||||||
|
switch typename {
|
||||||
|
case "email":
|
||||||
|
return NewAlarmEmail(name), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown alarm name \"%s\"", name)
|
||||||
|
}
|
||||||
|
}
|
66
alarm/alarm_email.go
Normal file
66
alarm/alarm_email.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package alarm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TK_NONE = iota
|
||||||
|
TK_TO
|
||||||
|
TK_SMTP
|
||||||
|
TK_FROM
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type AlarmEmail struct {
|
||||||
|
Type string
|
||||||
|
Name string
|
||||||
|
From string
|
||||||
|
SMTP string
|
||||||
|
To []string
|
||||||
|
state int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAlarmEmail(name string) *AlarmEmail {
|
||||||
|
return &AlarmEmail{
|
||||||
|
Type: "email", Name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlarmEmail) Alarm() error {
|
||||||
|
fmt.Printf("email alarm")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlarmEmail) Parse(tk string) (bool, error) {
|
||||||
|
switch a.state {
|
||||||
|
case TK_NONE:
|
||||||
|
switch strings.ToLower(tk){
|
||||||
|
case "to":
|
||||||
|
a.state = TK_TO
|
||||||
|
case "from":
|
||||||
|
a.state = TK_FROM
|
||||||
|
case "smtp":
|
||||||
|
a.state = TK_SMTP
|
||||||
|
default:
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case TK_FROM:
|
||||||
|
a.From = tk
|
||||||
|
a.state = TK_NONE
|
||||||
|
|
||||||
|
case TK_SMTP:
|
||||||
|
a.SMTP = tk
|
||||||
|
a.state = TK_NONE
|
||||||
|
|
||||||
|
case TK_TO:
|
||||||
|
a.To = append(a.To, tk)
|
||||||
|
a.state = TK_NONE
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("invalid state in alarm_email")
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
10
alrmrc
10
alrmrc
@ -1,10 +1,10 @@
|
|||||||
set interval 30s
|
set interval 30s
|
||||||
|
|
||||||
#alarm people email
|
alarm people email
|
||||||
# to test1@localhost
|
to test1@localhost
|
||||||
# to test2@localhost
|
to test2@localhost
|
||||||
# smtp localhost
|
smtp localhost
|
||||||
# from alrm@localhost
|
from alrm@localhost
|
||||||
|
|
||||||
monitor group webservers
|
monitor group webservers
|
||||||
host www1.example.com address 10.11.135.101
|
host www1.example.com address 10.11.135.101
|
||||||
|
@ -4,12 +4,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AlrmCheck interface {
|
type Check interface {
|
||||||
Parse(string) (bool, error)
|
Parse(string) (bool, error)
|
||||||
Check(int) error
|
Check(int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCheck(name string, addr string) (AlrmCheck, error) {
|
func NewCheck(name string, addr string) (Check, error) {
|
||||||
switch name {
|
switch name {
|
||||||
case "ping":
|
case "ping":
|
||||||
return NewCheckPing(addr), nil
|
return NewCheckPing(addr), nil
|
||||||
|
@ -3,45 +3,65 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
"alrm/alarm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AlrmConfig struct {
|
type Config struct {
|
||||||
Groups map[string]*AlrmGroup
|
Groups map[string]*Group
|
||||||
|
Alarms map[string]alarm.Alarm
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig() *AlrmConfig {
|
func NewConfig() *Config {
|
||||||
return &AlrmConfig{
|
return &Config{
|
||||||
// Default check interval, 30 seconds
|
// Default check interval, 30 seconds
|
||||||
Interval: time.Second * 30,
|
Interval: time.Second * 30,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ac *AlrmConfig) NewGroup(name string) (*AlrmGroup, error) {
|
func (c *Config) NewAlarm(name string, typename string) (alarm.Alarm, error) {
|
||||||
if ac.Groups == nil {
|
if c.Alarms == nil {
|
||||||
ac.Groups = make(map[string]*AlrmGroup)
|
c.Alarms = make(map[string]alarm.Alarm)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := ac.Groups[name]; exists {
|
if _, exists := c.Alarms[name]; exists {
|
||||||
|
return nil, fmt.Errorf("alarm %s already exists", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := alarm.NewAlarm(name, typename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.Alarms[name] = a
|
||||||
|
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) NewGroup(name string) (*Group, error) {
|
||||||
|
if c.Groups == nil {
|
||||||
|
c.Groups = make(map[string]*Group)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists := c.Groups[name]; exists {
|
||||||
return nil, fmt.Errorf("group %s already exists", name)
|
return nil, fmt.Errorf("group %s already exists", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
group := &AlrmGroup{Name: name}
|
group := &Group{Name: name}
|
||||||
ac.Groups[name] = group
|
c.Groups[name] = group
|
||||||
return group, nil
|
return group, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ac *AlrmConfig) SetInterval(val string) error {
|
func (c *Config) SetInterval(val string) error {
|
||||||
interval, err := time.ParseDuration(val)
|
interval, err := time.ParseDuration(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ac.Interval = interval
|
c.Interval = interval
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadConfig(fn string, debuglvl int) (*AlrmConfig, error) {
|
func ReadConfig(fn string, debuglvl int) (*Config, error) {
|
||||||
parser := &Parser{DebugLevel: debuglvl}
|
parser := &Parser{DebugLevel: debuglvl}
|
||||||
config, err := parser.Parse(fn)
|
config, err := parser.Parse(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4,26 +4,26 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AlrmGroup struct {
|
type Group struct {
|
||||||
Name string
|
Name string
|
||||||
Hosts map[string]*AlrmHost
|
Hosts map[string]*Host
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ag *AlrmGroup) NewHost(name string) (*AlrmHost, error) {
|
func (ag *Group) NewHost(name string) (*Host, error) {
|
||||||
if ag.Hosts == nil {
|
if ag.Hosts == nil {
|
||||||
ag.Hosts = make(map[string]*AlrmHost)
|
ag.Hosts = make(map[string]*Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := ag.Hosts[name]; exists {
|
if _, exists := ag.Hosts[name]; exists {
|
||||||
return nil, fmt.Errorf("host %s already exists", name)
|
return nil, fmt.Errorf("host %s already exists", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
host := &AlrmHost{Name: name}
|
host := &Host{Name: name}
|
||||||
ag.Hosts[name] = host
|
ag.Hosts[name] = host
|
||||||
return host, nil
|
return host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ag *AlrmGroup) Check(debuglvl int) error {
|
func (ag *Group) Check(debuglvl int) error {
|
||||||
for _, host := range ag.Hosts {
|
for _, host := range ag.Hosts {
|
||||||
for _, chk := range host.Checks {
|
for _, chk := range host.Checks {
|
||||||
err := chk.Check(debuglvl)
|
err := chk.Check(debuglvl)
|
||||||
|
@ -4,20 +4,20 @@ import (
|
|||||||
"alrm/check"
|
"alrm/check"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AlrmHost struct {
|
type Host struct {
|
||||||
Name string
|
Name string
|
||||||
Address string
|
Address string
|
||||||
Checks []check.AlrmCheck
|
Checks []check.Check
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ah *AlrmHost) GetAddress() string {
|
func (ah *Host) GetAddress() string {
|
||||||
if ah.Address != "" {
|
if ah.Address != "" {
|
||||||
return ah.Address
|
return ah.Address
|
||||||
}
|
}
|
||||||
return ah.Name
|
return ah.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ah *AlrmHost) NewCheck(name string) (check.AlrmCheck, error) {
|
func (ah *Host) NewCheck(name string) (check.Check, error) {
|
||||||
chk, err := check.NewCheck(name, ah.GetAddress())
|
chk, err := check.NewCheck(name, ah.GetAddress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"alrm/alarm"
|
||||||
"alrm/check"
|
"alrm/check"
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -15,18 +16,21 @@ const (
|
|||||||
TK_GROUP
|
TK_GROUP
|
||||||
TK_HOST
|
TK_HOST
|
||||||
TK_CHECK
|
TK_CHECK
|
||||||
|
TK_ALARM
|
||||||
)
|
)
|
||||||
|
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
DebugLevel int
|
DebugLevel int
|
||||||
Line int
|
Line int
|
||||||
states []int
|
states []int
|
||||||
lasthost *AlrmHost
|
lastHost *Host
|
||||||
lastgroup *AlrmGroup
|
lastGroup *Group
|
||||||
lastcheck check.AlrmCheck
|
lastCheck check.Check
|
||||||
|
lastAlarm alarm.Alarm
|
||||||
|
lastAlarmName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
func (p *Parser) Parse(fn string) (*Config, error) {
|
||||||
file, err := os.Open(fn)
|
file, err := os.Open(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot open config \"%s\": %s", fn, err.Error())
|
return nil, fmt.Errorf("cannot open config \"%s\": %s", fn, err.Error())
|
||||||
@ -47,6 +51,8 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
|||||||
p.setState(TK_MONITOR)
|
p.setState(TK_MONITOR)
|
||||||
case "set":
|
case "set":
|
||||||
p.setState(TK_SET)
|
p.setState(TK_SET)
|
||||||
|
case "alarm":
|
||||||
|
p.setState(TK_ALARM)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid token in %s, line %d: \"%s\"",
|
return nil, fmt.Errorf("invalid token in %s, line %d: \"%s\"",
|
||||||
fn, p.Line, tk)
|
fn, p.Line, tk)
|
||||||
@ -90,8 +96,8 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TK_GROUP:
|
case TK_GROUP:
|
||||||
if p.lastgroup == nil {
|
if p.lastGroup == nil {
|
||||||
p.lastgroup, err = config.NewGroup(tk)
|
p.lastGroup, err = config.NewGroup(tk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s in %s, line %d",
|
return nil, fmt.Errorf("%s in %s, line %d",
|
||||||
err.Error(), fn, p.Line,
|
err.Error(), fn, p.Line,
|
||||||
@ -111,8 +117,8 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
|||||||
|
|
||||||
case TK_HOST:
|
case TK_HOST:
|
||||||
// If a host has no group, inherit the host name
|
// If a host has no group, inherit the host name
|
||||||
if p.lastgroup == nil {
|
if p.lastGroup == nil {
|
||||||
p.lastgroup, err = config.NewGroup(tk)
|
p.lastGroup, err = config.NewGroup(tk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s in %s, line %d",
|
return nil, fmt.Errorf("%s in %s, line %d",
|
||||||
err.Error(), fn, p.Line,
|
err.Error(), fn, p.Line,
|
||||||
@ -120,8 +126,8 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.lasthost == nil {
|
if p.lastHost == nil {
|
||||||
p.lasthost, err = p.lastgroup.NewHost(tk)
|
p.lastHost, err = p.lastGroup.NewHost(tk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s in %s, line %d",
|
return nil, fmt.Errorf("%s in %s, line %d",
|
||||||
err.Error(), fn, p.Line,
|
err.Error(), fn, p.Line,
|
||||||
@ -136,7 +142,7 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
|||||||
return nil, fmt.Errorf("empty address for host in %s, line %d",
|
return nil, fmt.Errorf("empty address for host in %s, line %d",
|
||||||
fn, p.Line)
|
fn, p.Line)
|
||||||
}
|
}
|
||||||
p.lasthost.Address = scan.Text()
|
p.lastHost.Address = scan.Text()
|
||||||
|
|
||||||
case "check":
|
case "check":
|
||||||
p.setState(TK_CHECK)
|
p.setState(TK_CHECK)
|
||||||
@ -147,21 +153,47 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TK_CHECK:
|
case TK_CHECK:
|
||||||
if p.lastcheck == nil {
|
if p.lastCheck == nil {
|
||||||
p.lastcheck, err = p.lasthost.NewCheck(tk)
|
p.lastCheck, err = p.lastHost.NewCheck(tk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s in %s, line %d",
|
return nil, fmt.Errorf("%s in %s, line %d",
|
||||||
err.Error(), fn, p.Line)
|
err.Error(), fn, p.Line)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cont, err := p.lastcheck.Parse(tk)
|
cont, err := p.lastCheck.Parse(tk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s in %s, line %d",
|
return nil, fmt.Errorf("%s in %s, line %d",
|
||||||
err.Error(), fn, p.Line)
|
err.Error(), fn, p.Line)
|
||||||
}
|
}
|
||||||
if !cont {
|
if !cont {
|
||||||
p.lastcheck = nil
|
p.lastCheck = nil
|
||||||
|
p.prevState()
|
||||||
|
goto stateswitch
|
||||||
|
}
|
||||||
|
|
||||||
|
case TK_ALARM:
|
||||||
|
if p.lastAlarm == nil {
|
||||||
|
if p.lastAlarmName == "" {
|
||||||
|
p.lastAlarmName = tk
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
p.lastAlarm, err = config.NewAlarm(p.lastAlarmName, tk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s in %s, line %d",
|
||||||
|
err.Error(), fn, p.Line)
|
||||||
|
}
|
||||||
|
p.lastAlarmName = ""
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cont, err := p.lastAlarm.Parse(tk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s in %s, line %d",
|
||||||
|
err.Error(), fn, p.Line)
|
||||||
|
}
|
||||||
|
if !cont {
|
||||||
|
p.lastAlarm = nil
|
||||||
p.prevState()
|
p.prevState()
|
||||||
goto stateswitch
|
goto stateswitch
|
||||||
}
|
}
|
||||||
@ -188,11 +220,11 @@ func (p *Parser) setState(state int) {
|
|||||||
case TK_SET, TK_MONITOR:
|
case TK_SET, TK_MONITOR:
|
||||||
fallthrough
|
fallthrough
|
||||||
case TK_GROUP:
|
case TK_GROUP:
|
||||||
p.lastgroup = nil
|
p.lastGroup = nil
|
||||||
fallthrough
|
fallthrough
|
||||||
case TK_HOST:
|
case TK_HOST:
|
||||||
p.lasthost = nil
|
p.lastHost = nil
|
||||||
p.lastcheck = nil
|
p.lastCheck = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.DebugLevel > 1 {
|
if p.DebugLevel > 1 {
|
||||||
@ -225,6 +257,8 @@ func (p *Parser) stateName() string {
|
|||||||
return "TK_HOST"
|
return "TK_HOST"
|
||||||
case TK_CHECK:
|
case TK_CHECK:
|
||||||
return "TK_CHECK"
|
return "TK_CHECK"
|
||||||
|
case TK_ALARM:
|
||||||
|
return "TK_ALARM"
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN"
|
return "UNKNOWN"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user