@@ -18,6 +18,7 @@ import (
18
18
"github.com/flosch/pongo2"
19
19
"github.com/mdlayher/netx/eui64"
20
20
ovsClient "github.com/ovn-org/libovsdb/client"
21
+ ovsdbModel "github.com/ovn-org/libovsdb/model"
21
22
22
23
"github.com/lxc/incus/v6/client"
23
24
"github.com/lxc/incus/v6/internal/iprange"
@@ -32,6 +33,7 @@ import (
32
33
"github.com/lxc/incus/v6/internal/server/locking"
33
34
"github.com/lxc/incus/v6/internal/server/network/acl"
34
35
networkOVN "github.com/lxc/incus/v6/internal/server/network/ovn"
36
+ ovnSB "github.com/lxc/incus/v6/internal/server/network/ovn/schema/ovn-sb"
35
37
"github.com/lxc/incus/v6/internal/server/network/ovs"
36
38
"github.com/lxc/incus/v6/internal/server/project"
37
39
"github.com/lxc/incus/v6/internal/server/state"
@@ -3140,6 +3142,106 @@ func (n *ovn) Start() error {
3140
3142
return fmt .Errorf ("Failed applying BGP prefixes for load balancers: %w" , err )
3141
3143
}
3142
3144
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
+
3143
3245
revert .Success ()
3144
3246
3145
3247
// Ensure network is marked as available now its started.
@@ -3171,6 +3273,12 @@ func (n *ovn) Stop() error {
3171
3273
return err
3172
3274
}
3173
3275
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
+
3174
3282
return nil
3175
3283
}
3176
3284
0 commit comments