/
main.go
137 lines (118 loc) · 3.33 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"bytes"
"flag"
"fmt"
"log"
"net/smtp"
"os"
"path/filepath"
"strings"
"time"
"github.com/xswordsx/hddwatcher/lib"
"github.com/dustin/go-humanize"
)
var (
configFile string
printVersion bool
)
func init() {
flag.StringVar(&configFile, "c", "config.toml", "Config file (TOML format)")
flag.BoolVar(&printVersion, "v", false, "Print version information and exit")
flag.Parse()
}
type mailTemplateInput struct {
Hostname string
Letter string
Limit string
Free, Total, Used string
UsedPercent float32
FreePercent float32
Version string
}
func main() {
if printVersion {
fmt.Printf("hddwatcher version %s built at %s commit %s\n", version, builtAt, commit)
return
}
logger := log.New(os.Stdout, "[hddwatcher] ", log.LstdFlags|log.Lmsgprefix)
// Read config
if configFile == "" {
fmt.Println("Must pass config file.")
flag.Usage()
os.Exit(1)
}
absPath, _ := filepath.Abs(configFile)
logger.Printf("Reading config file %q", absPath)
cfg, err := configFromFile(configFile)
if err != nil {
logger.Fatal(err)
}
logger.Println("Validating configuration sanity")
acceptableLanguages := make([]string, 0, len(subjects))
for k := range subjects {
acceptableLanguages = append(acceptableLanguages, k[:])
}
if err := cfg.validate(acceptableLanguages); err != nil {
logger.Fatal(err)
}
logger.Println(" > Config OK")
// Check disk space
logger.Printf("Checking disk space for %q", cfg.Drive.Path)
_, total, free, err := lib.GetSpace(cfg.Drive.Path)
if err != nil {
// TODO
logger.Fatal(err)
}
logger.Printf(" > Free space: %s", humanize.IBytes(uint64(free)))
logger.Printf(" > Total space: %s", humanize.IBytes(uint64(total)))
if cfg.Drive.LimitBytes < free {
logger.Printf(
"Limit (< %s on %q) not reached - skipping email notification",
humanize.IBytes(uint64(cfg.Drive.LimitBytes)),
cfg.Drive.Path,
)
logger.Println("Done")
return
}
// MAIL
t := templates.Lookup(cfg.Mail.Language + ".html")
if t == nil {
log.Fatalf("no template for language %q", cfg.Mail.Language)
}
b := bytes.Buffer{}
hn, _ := os.Hostname()
i := mailTemplateInput{
Hostname: hn,
Letter: cfg.Drive.Path,
Limit: humanize.IBytes(cfg.Drive.LimitBytes),
Free: humanize.IBytes(free),
Total: humanize.IBytes(total),
Used: humanize.IBytes(total - free),
FreePercent: 100.0 * float32(free) / float32(total),
Version: version,
}
i.UsedPercent = 100 - i.FreePercent
if err := t.Execute(&b, i); err != nil {
logger.Fatalf("Cannot execute template %q: %v", t.Name(), err)
}
start := time.Now()
logger.Printf("Sending notification to %d recepients", len(cfg.Mail.RecepientList))
auth := smtp.PlainAuth("", cfg.Mail.Username, cfg.Mail.Password, cfg.Mail.Server)
// The "To:" header is omited so that all recepients
// receive a Bcc.
base := strings.Join([]string{
fmt.Sprintf("From: %s", cfg.Mail.Sender),
fmt.Sprintf("Subject: " + subjects[cfg.Mail.Language]),
"Content-Type: text/html; charset=utf-8",
"",
}, "\r\n")
body := []byte(base + b.String())
addr := fmt.Sprintf("%s:%d", cfg.Mail.Server, cfg.Mail.Port)
err = smtp.SendMail(addr, auth, cfg.Mail.Sender, cfg.Mail.RecepientList, body)
if err != nil {
log.Fatalf("error sending message: %v", err)
}
logger.Printf("Sending emails took %v", time.Since(start))
logger.Printf("Done")
}