Skip to content

Commit dd11c0c

Browse files
committed
incusd/network/ovn: Add load-balancer health event handler
Closes #1315 Signed-off-by: Stéphane Graber <[email protected]> Sponsored-by: Luizalabs (https://luizalabs.com)
1 parent 0dcaa55 commit dd11c0c

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

internal/server/network/driver_ovn.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/flosch/pongo2"
1919
"github.com/mdlayher/netx/eui64"
2020
ovsClient "github.com/ovn-org/libovsdb/client"
21+
ovsdbModel "github.com/ovn-org/libovsdb/model"
2122

2223
"github.com/lxc/incus/v6/client"
2324
"github.com/lxc/incus/v6/internal/iprange"
@@ -32,6 +33,7 @@ import (
3233
"github.com/lxc/incus/v6/internal/server/locking"
3334
"github.com/lxc/incus/v6/internal/server/network/acl"
3435
networkOVN "github.com/lxc/incus/v6/internal/server/network/ovn"
36+
ovnSB "github.com/lxc/incus/v6/internal/server/network/ovn/schema/ovn-sb"
3537
"github.com/lxc/incus/v6/internal/server/network/ovs"
3638
"github.com/lxc/incus/v6/internal/server/project"
3739
"github.com/lxc/incus/v6/internal/server/state"
@@ -3140,6 +3142,106 @@ func (n *ovn) Start() error {
31403142
return fmt.Errorf("Failed applying BGP prefixes for load balancers: %w", err)
31413143
}
31423144

3145+
// Setup event handler for monitored services.
3146+
handler := networkOVN.EventHandler{
3147+
Tables: []string{"Service_Monitor"},
3148+
Hook: func(action string, table string, oldObject ovsdbModel.Model, newObject ovsdbModel.Model) {
3149+
// Skip invalid notifications.
3150+
if oldObject == nil && newObject == nil {
3151+
return
3152+
}
3153+
3154+
// Get the object.
3155+
dbObject := newObject
3156+
if dbObject == nil {
3157+
dbObject = oldObject
3158+
}
3159+
3160+
srvStatus, ok := dbObject.(*ovnSB.ServiceMonitor)
3161+
if !ok {
3162+
return
3163+
}
3164+
3165+
// Check if this is our network.
3166+
if !strings.HasPrefix(srvStatus.LogicalPort, fmt.Sprintf("incus-net%d-instance-", n.id)) {
3167+
return
3168+
}
3169+
3170+
// Locate affected load-balancers.
3171+
lbs, err := n.ovnnb.GetLoadBalancersByStatusUpdate(context.TODO(), *srvStatus)
3172+
if err != nil {
3173+
return
3174+
}
3175+
3176+
for _, lb := range lbs {
3177+
// Check for status of all backends on this load-balancer.
3178+
online, err := n.ovnsb.CheckLoadBalancerOnline(context.TODO(), lb)
3179+
if err != nil {
3180+
return
3181+
}
3182+
3183+
// Parse the name.
3184+
fields := strings.Split(lb.Name, "-")
3185+
listenAddr := net.ParseIP(fields[3])
3186+
if listenAddr == nil {
3187+
return
3188+
}
3189+
3190+
// Check if we have a matching UDP load-balancer.
3191+
fields[4] = "udp"
3192+
lbUDP, _ := n.ovnnb.GetLoadBalancer(context.TODO(), networkOVN.OVNLoadBalancer(strings.Join(fields, "-")))
3193+
if lbUDP != nil {
3194+
// UDP backends can't be checked, so have to assume online.
3195+
online = true
3196+
}
3197+
3198+
// Prepare advertisement.
3199+
ipVersion := uint(4)
3200+
if listenAddr.To4() == nil {
3201+
ipVersion = 6
3202+
}
3203+
3204+
bgpOwner := fmt.Sprintf("network_%d_load_balancer", n.id)
3205+
nextHopAddr := n.bgpNextHopAddress(ipVersion)
3206+
natEnabled := util.IsTrue(n.config[fmt.Sprintf("ipv%d.nat", ipVersion)])
3207+
_, netSubnet, _ := net.ParseCIDR(n.config[fmt.Sprintf("ipv%d.address", ipVersion)])
3208+
3209+
routeSubnetSize := 128
3210+
if ipVersion == 4 {
3211+
routeSubnetSize = 32
3212+
}
3213+
3214+
// Don't export internal address forwards (those inside the NAT enabled network's subnet).
3215+
if natEnabled && netSubnet != nil && netSubnet.Contains(listenAddr) {
3216+
return
3217+
}
3218+
3219+
_, ipRouteSubnet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", listenAddr.String(), routeSubnetSize))
3220+
if err != nil {
3221+
return
3222+
}
3223+
3224+
// Update the BGP state.
3225+
if online {
3226+
err = n.state.BGP.AddPrefix(*ipRouteSubnet, nextHopAddr, bgpOwner)
3227+
if err != nil {
3228+
return
3229+
}
3230+
} else {
3231+
err = n.state.BGP.RemovePrefix(*ipRouteSubnet, nextHopAddr)
3232+
if err != nil {
3233+
return
3234+
}
3235+
}
3236+
}
3237+
},
3238+
}
3239+
3240+
err = networkOVN.AddOVNSBHandler(fmt.Sprintf("network_%d", n.id), handler)
3241+
if err != nil {
3242+
return err
3243+
}
3244+
31433245
revert.Success()
31443246

31453247
// Ensure network is marked as available now its started.
@@ -3171,6 +3273,12 @@ func (n *ovn) Stop() error {
31713273
return err
31723274
}
31733275

3276+
// Clear event handler for monitored services.
3277+
err = networkOVN.RemoveOVNSBHandler(fmt.Sprintf("network_%d", n.id))
3278+
if err != nil {
3279+
return err
3280+
}
3281+
31743282
return nil
31753283
}
31763284

0 commit comments

Comments
 (0)