71 lines
1.7 KiB
Go
71 lines
1.7 KiB
Go
package watchdog
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.g3e.fr/syonad/two/internal/netns"
|
|
"git.g3e.fr/syonad/two/internal/state"
|
|
"git.g3e.fr/syonad/two/internal/watchdog/notify"
|
|
"git.g3e.fr/syonad/two/pkg/db/kv"
|
|
|
|
"github.com/dgraph-io/badger/v4"
|
|
)
|
|
|
|
const vpcBridge = "br-public"
|
|
|
|
func vpcIfaceNames(vpcName string) (host, ns string, err error) {
|
|
parts := strings.SplitN(vpcName, "-", 2)
|
|
if len(parts) < 2 || parts[1] == "" {
|
|
return "", "", fmt.Errorf("vpc name %q has no identifier after the dash, interface names cannot be derived", vpcName)
|
|
}
|
|
return "vp-" + parts[1] + "-e", "vp-" + parts[1] + "-i", nil
|
|
}
|
|
|
|
func CheckVPCs(db *badger.DB, n notify.Notifier) error {
|
|
pairs, err := kv.ListByPrefix(db, prefixVPC)
|
|
if err != nil {
|
|
return fmt.Errorf("watchdog: listing vpcs: %w", err)
|
|
}
|
|
|
|
for _, name := range resourceNames(pairs, prefixVPC) {
|
|
st, err := state.Get(db, prefixVPC+name)
|
|
if err != nil {
|
|
n.Notify(kindVPC, name, fmt.Sprintf("state unreadable in database: %v", err))
|
|
continue
|
|
}
|
|
if st != state.Running {
|
|
continue
|
|
}
|
|
checkVPC(name, n)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func checkVPC(name string, n notify.Notifier) {
|
|
hostVeth, nsVeth, err := vpcIfaceNames(name)
|
|
if err != nil {
|
|
n.Notify(kindVPC, name, err.Error())
|
|
return
|
|
}
|
|
|
|
if !netns.Exist(name) {
|
|
n.Notify(kindVPC, name, "netns missing (/var/run/netns/"+name+")")
|
|
return
|
|
}
|
|
|
|
if p := linkProblem(hostVeth); p != "" {
|
|
n.Notify(kindVPC, name, p)
|
|
}
|
|
|
|
if err := netns.Call(name, func() error {
|
|
for _, iface := range []string{nsVeth, vpcBridge} {
|
|
if p := linkProblem(iface); p != "" {
|
|
n.Notify(kindVPC, name, p+" (in netns)")
|
|
}
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
n.Notify(kindVPC, name, fmt.Sprintf("cannot enter netns: %v", err))
|
|
}
|
|
}
|