From 6417fdee0a806ae5fa767b470ad3cae730a0549a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Thu, 12 Dec 2024 16:42:31 -0500 Subject: [PATCH 1/2] incusd/network/ovn: Return ErrTooMany when getting multiple records MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber --- internal/server/network/ovn/errors.go | 3 +++ internal/server/network/ovn/ovn_nb.go | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/server/network/ovn/errors.go b/internal/server/network/ovn/errors.go index 34f71cedd7c..2eb9ff02b31 100644 --- a/internal/server/network/ovn/errors.go +++ b/internal/server/network/ovn/errors.go @@ -12,5 +12,8 @@ var ErrExists = fmt.Errorf("object already exists") // ErrNotFound indicates that a DB record doesn't exist. var ErrNotFound = ovsdbClient.ErrNotFound +// ErrTooMany is returned when one match is expected but multiple are found. +var ErrTooMany = fmt.Errorf("too many objects found") + // ErrNotManaged indicates that a DB record wasn't created by Incus. var ErrNotManaged = fmt.Errorf("object not incus-managed") diff --git a/internal/server/network/ovn/ovn_nb.go b/internal/server/network/ovn/ovn_nb.go index 35e52674893..8b96d44cfb8 100644 --- a/internal/server/network/ovn/ovn_nb.go +++ b/internal/server/network/ovn/ovn_nb.go @@ -207,10 +207,14 @@ func (o *NB) get(ctx context.Context, m ovsdbModel.Model) error { return fmt.Errorf("Bad collection type") } - if rVal.Len() != 1 { + if rVal.Len() == 0 { return ovsdbClient.ErrNotFound } + if rVal.Len() > 1 { + return ErrTooMany + } + reflect.ValueOf(m).Elem().Set(rVal.Index(0)) return nil } From cf4fcf192a5bb182e18c268fdc98adc1bef1df65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Thu, 12 Dec 2024 16:14:45 -0500 Subject: [PATCH 2/2] incusd/network/ovn: Clear all existing records MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Occasionaly we end up with some duplicate DB records, so make sure that our logic clearly removes any existing record as part of refreshing the load balancer. Signed-off-by: Stéphane Graber --- internal/server/network/ovn/ovn_nb_actions.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/server/network/ovn/ovn_nb_actions.go b/internal/server/network/ovn/ovn_nb_actions.go index 333387b55ad..8ebb3df36a0 100644 --- a/internal/server/network/ovn/ovn_nb_actions.go +++ b/internal/server/network/ovn/ovn_nb_actions.go @@ -2975,8 +2975,12 @@ func (o *NB) CreateLoadBalancer(ctx context.Context, loadBalancerName OVNLoadBal } err := o.get(ctx, &lb) - if err == nil { - // Delete the load balancer. + if err == nil || err == ErrTooMany { + // Delete the load balancer (by name in case there are duplicates). + lb := ovnNB.LoadBalancer{ + Name: name, + } + deleteOps, err := o.client.Where(&lb).Delete() if err != nil { return err