• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubeovn / kube-ovn / 22942056921

11 Mar 2026 07:42AM UTC coverage: 21.245% (-0.001%) from 21.246%
22942056921

push

github

changluyi
fix: reconcile subnet and localnet network_name on vlan provider change (#6393)

* fix: reconcile subnet and localnet network_name on vlan provider change

* fix

Signed-off-by: clyi <clyi@alauda.io>

* fix

Signed-off-by: clyi <clyi@alauda.io>

---------

Signed-off-by: clyi <clyi@alauda.io>

7 of 29 new or added lines in 2 files covered. (24.14%)

3 existing lines in 2 files now uncovered.

10641 of 50087 relevant lines covered (21.25%)

0.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pkg/controller/vlan.go
1
package controller
2

3
import (
4
        "context"
5
        "fmt"
6
        "slices"
7

8
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
9
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10
        "k8s.io/apimachinery/pkg/labels"
11
        "k8s.io/client-go/tools/cache"
12
        "k8s.io/klog/v2"
13

14
        kubeovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
15
        "github.com/kubeovn/kube-ovn/pkg/ovs"
16
        "github.com/kubeovn/kube-ovn/pkg/util"
17
)
18

19
func (c *Controller) enqueueAddVlan(obj any) {
×
20
        key := cache.MetaObjectToName(obj.(*kubeovnv1.Vlan)).String()
×
21
        klog.V(3).Infof("enqueue add vlan %s", key)
×
22
        c.addVlanQueue.Add(key)
×
23
}
×
24

NEW
25
func (c *Controller) enqueueUpdateVlan(oldObj, newObj any) {
×
NEW
26
        oldVlan := oldObj.(*kubeovnv1.Vlan)
×
NEW
27
        newVlan := newObj.(*kubeovnv1.Vlan)
×
NEW
28
        key := cache.MetaObjectToName(newVlan).String()
×
29
        klog.V(3).Infof("enqueue update vlan %s", key)
×
30
        c.updateVlanQueue.Add(key)
×
NEW
31

×
NEW
32
        if oldVlan.Spec.Provider == newVlan.Spec.Provider {
×
NEW
33
                return
×
NEW
34
        }
×
35

NEW
36
        klog.Infof("vlan %s provider changed from %s to %s, enqueue related subnets", newVlan.Name, oldVlan.Spec.Provider, newVlan.Spec.Provider)
×
NEW
37
        subnets, err := c.subnetsLister.List(labels.Everything())
×
NEW
38
        if err != nil {
×
NEW
39
                klog.Errorf("failed to list subnets when vlan %s provider changed: %v", newVlan.Name, err)
×
NEW
40
                return
×
NEW
41
        }
×
42

NEW
43
        for _, subnet := range subnets {
×
NEW
44
                if subnet.Spec.Vlan == newVlan.Name {
×
NEW
45
                        c.addOrUpdateSubnetQueue.Add(subnet.Name)
×
NEW
46
                }
×
47
        }
48
}
49

50
func (c *Controller) enqueueDelVlan(obj any) {
×
51
        var vlan *kubeovnv1.Vlan
×
52
        switch t := obj.(type) {
×
53
        case *kubeovnv1.Vlan:
×
54
                vlan = t
×
55
        case cache.DeletedFinalStateUnknown:
×
56
                v, ok := t.Obj.(*kubeovnv1.Vlan)
×
57
                if !ok {
×
58
                        klog.Warningf("unexpected object type: %T", t.Obj)
×
59
                        return
×
60
                }
×
61
                vlan = v
×
62
        default:
×
63
                klog.Warningf("unexpected type: %T", obj)
×
64
                return
×
65
        }
66

67
        key := cache.MetaObjectToName(vlan).String()
×
68
        klog.V(3).Infof("enqueue delete vlan %s", key)
×
69
        c.delVlanQueue.Add(key)
×
70
}
71

72
func (c *Controller) handleAddVlan(key string) error {
×
73
        c.vlanKeyMutex.LockKey(key)
×
74
        defer func() { _ = c.vlanKeyMutex.UnlockKey(key) }()
×
75
        klog.Infof("handle add vlan %s", key)
×
76

×
77
        cachedVlan, err := c.vlansLister.Get(key)
×
78
        if err != nil {
×
79
                if k8serrors.IsNotFound(err) {
×
80
                        return nil
×
81
                }
×
82
                klog.Error(err)
×
83
                return err
×
84
        }
85

86
        vlan := cachedVlan.DeepCopy()
×
87
        if vlan.Spec.Provider == "" {
×
88
                vlan.Spec.Provider = c.config.DefaultProviderName
×
89
                if vlan, err = c.config.KubeOvnClient.KubeovnV1().Vlans().Update(context.Background(), vlan, metav1.UpdateOptions{}); err != nil {
×
90
                        klog.Errorf("failed to update vlan %s, %v", vlan.Name, err)
×
91
                        return err
×
92
                }
×
93
        }
94

95
        subnets, err := c.subnetsLister.List(labels.Everything())
×
96
        if err != nil {
×
97
                klog.Errorf("failed to list subnets: %v", err)
×
98
                return err
×
99
        }
×
100

101
        var needUpdate bool
×
102
        for _, subnet := range subnets {
×
103
                if subnet.Spec.Vlan == vlan.Name && !slices.Contains(vlan.Status.Subnets, subnet.Name) {
×
104
                        vlan.Status.Subnets = append(vlan.Status.Subnets, subnet.Name)
×
105
                        needUpdate = true
×
106
                }
×
107
        }
108

109
        if needUpdate {
×
110
                vlan, err = c.config.KubeOvnClient.KubeovnV1().Vlans().UpdateStatus(context.Background(), vlan, metav1.UpdateOptions{})
×
111
                if err != nil {
×
112
                        klog.Errorf("failed to update status of vlan %s: %v", vlan.Name, err)
×
113
                        return err
×
114
                }
×
115
        }
116

117
        pn, err := c.providerNetworksLister.Get(vlan.Spec.Provider)
×
118
        if err != nil {
×
119
                klog.Errorf("failed to get provider network %s: %v", vlan.Spec.Provider, err)
×
120
                return err
×
121
        }
×
122

123
        if err = c.checkVlanConflict(vlan); err != nil {
×
124
                klog.Errorf("failed to check vlan %s: %v", vlan.Name, err)
×
125
                return err
×
126
        }
×
127

128
        if !slices.Contains(pn.Status.Vlans, vlan.Name) {
×
129
                newPn := pn.DeepCopy()
×
130
                newPn.Status.Vlans = append(newPn.Status.Vlans, vlan.Name)
×
131
                _, err = c.config.KubeOvnClient.KubeovnV1().ProviderNetworks().UpdateStatus(context.Background(), newPn, metav1.UpdateOptions{})
×
132
                if err != nil {
×
133
                        klog.Errorf("failed to update status of provider network %s: %v", pn.Name, err)
×
134
                        return err
×
135
                }
×
136
        }
137

138
        return nil
×
139
}
140

141
func (c *Controller) checkVlanConflict(vlan *kubeovnv1.Vlan) error {
×
142
        if vlan.Spec.ID == 0 {
×
143
                // no conflict if vlan id is 0
×
144
                return nil
×
145
        }
×
146
        // todo: check if vlan conflict in webhook
147
        vlans, err := c.vlansLister.List(labels.Everything())
×
148
        if err != nil {
×
149
                klog.Errorf("failed to list vlans: %v", err)
×
150
                return err
×
151
        }
×
152
        // check if new vlan conflict with old vlan
153
        var conflict bool
×
154
        var conflictErr error
×
155
        for _, v := range vlans {
×
156
                // different provider allow to have same vlan
×
157
                if vlan.Spec.Provider == v.Spec.Provider && vlan.Spec.ID == v.Spec.ID && vlan.Name != v.Name {
×
158
                        conflictErr = fmt.Errorf("provider %s new vlan %s conflict with old vlan %s", vlan.Spec.Provider, vlan.Name, v.Name)
×
159
                        klog.Error(conflictErr)
×
160
                        conflict = true
×
161
                }
×
162
        }
163
        if vlan.Status.Conflict != conflict {
×
164
                vlan.Status.Conflict = conflict
×
165
                vlan, err = c.config.KubeOvnClient.KubeovnV1().Vlans().UpdateStatus(context.Background(), vlan, metav1.UpdateOptions{})
×
166
                if err != nil {
×
167
                        klog.Errorf("failed to update conflict status of vlan %s: %v", vlan.Name, err)
×
168
                        return err
×
169
                }
×
170
        }
171
        return conflictErr
×
172
}
173

174
func (c *Controller) handleUpdateVlan(key string) error {
×
175
        c.vlanKeyMutex.LockKey(key)
×
176
        defer func() { _ = c.vlanKeyMutex.UnlockKey(key) }()
×
177
        klog.Infof("handle update vlan %s", key)
×
178

×
179
        vlan, err := c.vlansLister.Get(key)
×
180
        if err != nil {
×
181
                if k8serrors.IsNotFound(err) {
×
182
                        return nil
×
183
                }
×
184
                klog.Error(err)
×
185
                return err
×
186
        }
187

188
        if vlan.Spec.Provider == "" {
×
189
                newVlan := vlan.DeepCopy()
×
190
                newVlan.Spec.Provider = c.config.DefaultProviderName
×
191
                if vlan, err = c.config.KubeOvnClient.KubeovnV1().Vlans().Update(context.Background(), newVlan, metav1.UpdateOptions{}); err != nil {
×
192
                        klog.Errorf("failed to update vlan %s: %v", vlan.Name, err)
×
193
                        return err
×
194
                }
×
195
        }
196
        newVlan := vlan.DeepCopy()
×
197
        if err = c.checkVlanConflict(newVlan); err != nil {
×
198
                klog.Errorf("failed to check vlan %s: %v", vlan.Name, err)
×
199
                return err
×
200
        }
×
201

202
        subnets, err := c.subnetsLister.List(labels.Everything())
×
203
        if err != nil {
×
204
                klog.Errorf("failed to list subnets: %v", err)
×
205
                return err
×
206
        }
×
207

208
        for _, subnet := range subnets {
×
209
                if subnet.Spec.Vlan == vlan.Name {
×
210
                        if err = c.setLocalnetTag(subnet.Name, vlan.Spec.ID); err != nil {
×
211
                                klog.Error(err)
×
212
                                return err
×
213
                        }
×
214
                }
215
        }
216

217
        return nil
×
218
}
219

220
func (c *Controller) handleDelVlan(key string) error {
×
221
        c.vlanKeyMutex.LockKey(key)
×
222
        defer func() { _ = c.vlanKeyMutex.UnlockKey(key) }()
×
223
        klog.Infof("handle delete vlan %s", key)
×
224

×
225
        subnet, err := c.subnetsLister.List(labels.Everything())
×
226
        if err != nil {
×
227
                klog.Errorf("failed to list subnets: %v", err)
×
228
                return err
×
229
        }
×
230

231
        for _, s := range subnet {
×
232
                if s.Spec.Vlan == key {
×
233
                        c.addOrUpdateSubnetQueue.Add(s.Name)
×
234
                }
×
235
        }
236

237
        providerNetworks, err := c.providerNetworksLister.List(labels.Everything())
×
238
        if err != nil && !k8serrors.IsNotFound(err) {
×
239
                klog.Errorf("failed to list provider networks: %v", err)
×
240
                return err
×
241
        }
×
242

243
        for _, pn := range providerNetworks {
×
244
                if err = c.updateProviderNetworkStatusForVlanDeletion(pn, key); err != nil {
×
245
                        klog.Error(err)
×
246
                        return err
×
247
                }
×
248
        }
249

250
        return nil
×
251
}
252

253
func (c *Controller) updateProviderNetworkStatusForVlanDeletion(pn *kubeovnv1.ProviderNetwork, vlan string) error {
×
254
        if !slices.Contains(pn.Status.Vlans, vlan) {
×
255
                return nil
×
256
        }
×
257

258
        newPn := pn.DeepCopy()
×
259
        newPn.Status.Vlans = util.RemoveString(newPn.Status.Vlans, vlan)
×
260
        _, err := c.config.KubeOvnClient.KubeovnV1().ProviderNetworks().UpdateStatus(context.Background(), newPn, metav1.UpdateOptions{})
×
261
        if err != nil {
×
262
                klog.Errorf("failed to update status of provider network %s: %v", pn.Name, err)
×
263
                return err
×
264
        }
×
265
        return nil
×
266
}
267

268
func (c *Controller) setLocalnetTag(subnet string, vlanID int) error {
×
269
        localnetPort := ovs.GetLocalnetName(subnet)
×
270
        if err := c.OVNNbClient.SetLogicalSwitchPortVlanTag(localnetPort, vlanID); err != nil {
×
271
                klog.Errorf("set localnet port %s vlan tag %d: %v", localnetPort, vlanID, err)
×
272
                return err
×
273
        }
×
274

275
        return nil
×
276
}
277

278
func (c *Controller) delLocalnet(subnet string) error {
×
279
        localnetPort := ovs.GetLocalnetName(subnet)
×
280
        if err := c.OVNNbClient.DeleteLogicalSwitchPort(localnetPort); err != nil {
×
281
                klog.Errorf("delete localnet port %s: %v", localnetPort, err)
×
282
                return err
×
283
        }
×
284

285
        return nil
×
286
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc