f-29: watchdog: add checksubnet #29
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
ea60c0db54
commit
0fa84b8320
7 changed files with 497 additions and 2 deletions
134
internal/watchdog/check_subnet.go
Normal file
134
internal/watchdog/check_subnet.go
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
package watchdog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.g3e.fr/syonad/two/internal/dhcp"
|
||||
"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 (
|
||||
modeVxlan = "vxlan"
|
||||
modeBridge = "bridge"
|
||||
)
|
||||
|
||||
func subnetIfaceNames(subnetName string) (hostVeth, nsVeth, bridge string, err error) {
|
||||
parts := strings.SplitN(subnetName, "-", 2)
|
||||
if len(parts) < 2 || parts[1] == "" {
|
||||
return "", "", "", fmt.Errorf("nom de subnet %q sans identifiant après le tiret, interfaces indéductibles", subnetName)
|
||||
}
|
||||
id := parts[1]
|
||||
return "v-" + id + "-e", "v-" + id + "-i", "br-" + id, nil
|
||||
}
|
||||
|
||||
func dnsmasqName(vpc, bridge string) string {
|
||||
return vpc + "_" + bridge
|
||||
}
|
||||
|
||||
func CheckSubnets(db *badger.DB, u unitChecker, n notify.Notifier) error {
|
||||
pairs, err := kv.ListByPrefix(db, prefixSubnet)
|
||||
if err != nil {
|
||||
return fmt.Errorf("watchdog: lecture des subnets: %w", err)
|
||||
}
|
||||
|
||||
for _, name := range resourceNames(pairs, prefixSubnet) {
|
||||
st, err := state.Get(db, prefixSubnet+name)
|
||||
if err != nil {
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("état illisible en base: %v", err))
|
||||
continue
|
||||
}
|
||||
if st != state.Running {
|
||||
continue
|
||||
}
|
||||
checkSubnet(db, name, u, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkSubnet(db *badger.DB, name string, u unitChecker, n notify.Notifier) {
|
||||
hostVeth, nsVeth, bridge, err := subnetIfaceNames(name)
|
||||
if err != nil {
|
||||
n.Notify(kindSubnet, name, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
vpc, err := kv.GetFromDB(db, prefixSubnet+name+"/vpc")
|
||||
if err != nil {
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("vpc illisible en base: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
mode, err := kv.GetFromDB(db, prefixSubnet+name+"/mode")
|
||||
if err != nil {
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("mode illisible en base: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
if p := linkProblem(hostVeth); p != "" {
|
||||
n.Notify(kindSubnet, name, p)
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case modeVxlan:
|
||||
if p := linkProblem(bridge); p != "" {
|
||||
n.Notify(kindSubnet, name, p+" (host)")
|
||||
}
|
||||
checkVxlanIface(db, name, n)
|
||||
case modeBridge:
|
||||
default:
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("mode inconnu %q", mode))
|
||||
}
|
||||
|
||||
checkSubnetNetns(name, vpc, nsVeth, bridge, n)
|
||||
|
||||
dnsName := dnsmasqName(vpc, bridge)
|
||||
conf := filepath.Join(dhcp.DefaultConfDir, dnsName+".conf")
|
||||
if _, err := os.Stat(conf); err != nil {
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("config dnsmasq absente (%s): %v", conf, err))
|
||||
}
|
||||
|
||||
checkUnit(kindSubnet, name, "dnsmasq@"+dnsName+".service", u, n)
|
||||
}
|
||||
|
||||
func checkVxlanIface(db *badger.DB, name string, n notify.Notifier) {
|
||||
raw, err := kv.GetFromDB(db, prefixSubnet+name+"/vxlan_id")
|
||||
if err != nil {
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("vxlan_id illisible en base: %v", err))
|
||||
return
|
||||
}
|
||||
id, err := strconv.Atoi(raw)
|
||||
if err != nil {
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("vxlan_id invalide %q: %v", raw, err))
|
||||
return
|
||||
}
|
||||
if p := linkProblem(fmt.Sprintf("vxlan-%d", id)); p != "" {
|
||||
n.Notify(kindSubnet, name, p)
|
||||
}
|
||||
}
|
||||
|
||||
func checkSubnetNetns(name, vpc, nsVeth, bridge string, n notify.Notifier) {
|
||||
if !netns.Exist(vpc) {
|
||||
n.Notify(kindSubnet, name, "netns "+vpc+" absent (/var/run/netns/"+vpc+")")
|
||||
return
|
||||
}
|
||||
|
||||
if err := netns.Call(vpc, func() error {
|
||||
for _, iface := range []string{nsVeth, bridge} {
|
||||
if p := linkProblem(iface); p != "" {
|
||||
n.Notify(kindSubnet, name, p+" (dans le netns "+vpc+")")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
n.Notify(kindSubnet, name, fmt.Sprintf("entrée dans le netns %s impossible: %v", vpc, err))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue