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
|
||||
|
||||
#alarm people email
|
||||
# to test1@localhost
|
||||
# to test2@localhost
|
||||
# smtp localhost
|
||||
# from alrm@localhost
|
||||
alarm people email
|
||||
to test1@localhost
|
||||
to test2@localhost
|
||||
smtp localhost
|
||||
from alrm@localhost
|
||||
|
||||
monitor group webservers
|
||||
host www1.example.com address 10.11.135.101
|
||||
|
@ -4,12 +4,12 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type AlrmCheck interface {
|
||||
type Check interface {
|
||||
Parse(string) (bool, error)
|
||||
Check(int) error
|
||||
}
|
||||
|
||||
func NewCheck(name string, addr string) (AlrmCheck, error) {
|
||||
func NewCheck(name string, addr string) (Check, error) {
|
||||
switch name {
|
||||
case "ping":
|
||||
return NewCheckPing(addr), nil
|
||||
|
@ -3,45 +3,65 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"alrm/alarm"
|
||||
)
|
||||
|
||||
type AlrmConfig struct {
|
||||
Groups map[string]*AlrmGroup
|
||||
type Config struct {
|
||||
Groups map[string]*Group
|
||||
Alarms map[string]alarm.Alarm
|
||||
Interval time.Duration
|
||||
}
|
||||
|
||||
func NewConfig() *AlrmConfig {
|
||||
return &AlrmConfig{
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
// Default check interval, 30 seconds
|
||||
Interval: time.Second * 30,
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *AlrmConfig) NewGroup(name string) (*AlrmGroup, error) {
|
||||
if ac.Groups == nil {
|
||||
ac.Groups = make(map[string]*AlrmGroup)
|
||||
func (c *Config) NewAlarm(name string, typename string) (alarm.Alarm, error) {
|
||||
if c.Alarms == nil {
|
||||
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)
|
||||
}
|
||||
|
||||
group := &AlrmGroup{Name: name}
|
||||
ac.Groups[name] = group
|
||||
group := &Group{Name: name}
|
||||
c.Groups[name] = group
|
||||
return group, nil
|
||||
}
|
||||
|
||||
func (ac *AlrmConfig) SetInterval(val string) error {
|
||||
func (c *Config) SetInterval(val string) error {
|
||||
interval, err := time.ParseDuration(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ac.Interval = interval
|
||||
c.Interval = interval
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadConfig(fn string, debuglvl int) (*AlrmConfig, error) {
|
||||
func ReadConfig(fn string, debuglvl int) (*Config, error) {
|
||||
parser := &Parser{DebugLevel: debuglvl}
|
||||
config, err := parser.Parse(fn)
|
||||
if err != nil {
|
||||
|
@ -4,26 +4,26 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type AlrmGroup struct {
|
||||
type Group struct {
|
||||
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 {
|
||||
ag.Hosts = make(map[string]*AlrmHost)
|
||||
ag.Hosts = make(map[string]*Host)
|
||||
}
|
||||
|
||||
if _, exists := ag.Hosts[name]; exists {
|
||||
return nil, fmt.Errorf("host %s already exists", name)
|
||||
}
|
||||
|
||||
host := &AlrmHost{Name: name}
|
||||
host := &Host{Name: name}
|
||||
ag.Hosts[name] = host
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func (ag *AlrmGroup) Check(debuglvl int) error {
|
||||
func (ag *Group) Check(debuglvl int) error {
|
||||
for _, host := range ag.Hosts {
|
||||
for _, chk := range host.Checks {
|
||||
err := chk.Check(debuglvl)
|
||||
|
@ -4,20 +4,20 @@ import (
|
||||
"alrm/check"
|
||||
)
|
||||
|
||||
type AlrmHost struct {
|
||||
type Host struct {
|
||||
Name string
|
||||
Address string
|
||||
Checks []check.AlrmCheck
|
||||
Checks []check.Check
|
||||
}
|
||||
|
||||
func (ah *AlrmHost) GetAddress() string {
|
||||
func (ah *Host) GetAddress() string {
|
||||
if ah.Address != "" {
|
||||
return ah.Address
|
||||
}
|
||||
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())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"alrm/alarm"
|
||||
"alrm/check"
|
||||
"bufio"
|
||||
"fmt"
|
||||
@ -15,18 +16,21 @@ const (
|
||||
TK_GROUP
|
||||
TK_HOST
|
||||
TK_CHECK
|
||||
TK_ALARM
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
DebugLevel int
|
||||
Line int
|
||||
states []int
|
||||
lasthost *AlrmHost
|
||||
lastgroup *AlrmGroup
|
||||
lastcheck check.AlrmCheck
|
||||
DebugLevel int
|
||||
Line int
|
||||
states []int
|
||||
lastHost *Host
|
||||
lastGroup *Group
|
||||
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)
|
||||
if err != nil {
|
||||
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)
|
||||
case "set":
|
||||
p.setState(TK_SET)
|
||||
case "alarm":
|
||||
p.setState(TK_ALARM)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid token in %s, line %d: \"%s\"",
|
||||
fn, p.Line, tk)
|
||||
@ -90,8 +96,8 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
||||
}
|
||||
|
||||
case TK_GROUP:
|
||||
if p.lastgroup == nil {
|
||||
p.lastgroup, err = config.NewGroup(tk)
|
||||
if p.lastGroup == nil {
|
||||
p.lastGroup, err = config.NewGroup(tk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s in %s, line %d",
|
||||
err.Error(), fn, p.Line,
|
||||
@ -111,8 +117,8 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
||||
|
||||
case TK_HOST:
|
||||
// If a host has no group, inherit the host name
|
||||
if p.lastgroup == nil {
|
||||
p.lastgroup, err = config.NewGroup(tk)
|
||||
if p.lastGroup == nil {
|
||||
p.lastGroup, err = config.NewGroup(tk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s in %s, line %d",
|
||||
err.Error(), fn, p.Line,
|
||||
@ -120,8 +126,8 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if p.lasthost == nil {
|
||||
p.lasthost, err = p.lastgroup.NewHost(tk)
|
||||
if p.lastHost == nil {
|
||||
p.lastHost, err = p.lastGroup.NewHost(tk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s in %s, line %d",
|
||||
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",
|
||||
fn, p.Line)
|
||||
}
|
||||
p.lasthost.Address = scan.Text()
|
||||
p.lastHost.Address = scan.Text()
|
||||
|
||||
case "check":
|
||||
p.setState(TK_CHECK)
|
||||
@ -147,21 +153,47 @@ func (p *Parser) Parse(fn string) (*AlrmConfig, error) {
|
||||
}
|
||||
|
||||
case TK_CHECK:
|
||||
if p.lastcheck == nil {
|
||||
p.lastcheck, err = p.lasthost.NewCheck(tk)
|
||||
if p.lastCheck == nil {
|
||||
p.lastCheck, err = p.lastHost.NewCheck(tk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s in %s, line %d",
|
||||
err.Error(), fn, p.Line)
|
||||
}
|
||||
continue
|
||||
}
|
||||
cont, err := p.lastcheck.Parse(tk)
|
||||
cont, err := p.lastCheck.Parse(tk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s in %s, line %d",
|
||||
err.Error(), fn, p.Line)
|
||||
}
|
||||
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()
|
||||
goto stateswitch
|
||||
}
|
||||
@ -188,11 +220,11 @@ func (p *Parser) setState(state int) {
|
||||
case TK_SET, TK_MONITOR:
|
||||
fallthrough
|
||||
case TK_GROUP:
|
||||
p.lastgroup = nil
|
||||
p.lastGroup = nil
|
||||
fallthrough
|
||||
case TK_HOST:
|
||||
p.lasthost = nil
|
||||
p.lastcheck = nil
|
||||
p.lastHost = nil
|
||||
p.lastCheck = nil
|
||||
}
|
||||
|
||||
if p.DebugLevel > 1 {
|
||||
@ -225,6 +257,8 @@ func (p *Parser) stateName() string {
|
||||
return "TK_HOST"
|
||||
case TK_CHECK:
|
||||
return "TK_CHECK"
|
||||
case TK_ALARM:
|
||||
return "TK_ALARM"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user