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

kubeovn / kube-ovn / 22942039048

11 Mar 2026 07:41AM UTC coverage: 22.922% (+0.002%) from 22.92%
22942039048

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%)

1 existing line in 1 file now uncovered.

12409 of 54135 relevant lines covered (22.92%)

0.27 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
        // re-enqueue subnets that reference this vlan, so they can proceed
139
        // if they were previously blocked by the vlan not being ready
140
        for _, subnet := range subnets {
×
141
                if subnet.Spec.Vlan == vlan.Name {
×
142
                        c.addOrUpdateSubnetQueue.Add(subnet.Name)
×
143
                }
×
144
        }
145

146
        return nil
×
147
}
148

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

182
func (c *Controller) handleUpdateVlan(key string) error {
×
183
        c.vlanKeyMutex.LockKey(key)
×
184
        defer func() { _ = c.vlanKeyMutex.UnlockKey(key) }()
×
185
        klog.Infof("handle update vlan %s", key)
×
186

×
187
        vlan, err := c.vlansLister.Get(key)
×
188
        if err != nil {
×
189
                if k8serrors.IsNotFound(err) {
×
190
                        return nil
×
191
                }
×
192
                klog.Error(err)
×
193
                return err
×
194
        }
195

196
        if vlan.Spec.Provider == "" {
×
197
                newVlan := vlan.DeepCopy()
×
198
                newVlan.Spec.Provider = c.config.DefaultProviderName
×
199
                if vlan, err = c.config.KubeOvnClient.KubeovnV1().Vlans().Update(context.Background(), newVlan, metav1.UpdateOptions{}); err != nil {
×
200
                        klog.Errorf("failed to update vlan %s: %v", vlan.Name, err)
×
201
                        return err
×
202
                }
×
203
        }
204
        newVlan := vlan.DeepCopy()
×
205
        if err = c.checkVlanConflict(newVlan); err != nil {
×
206
                klog.Errorf("failed to check vlan %s: %v", vlan.Name, err)
×
207
                return err
×
208
        }
×
209

210
        subnets, err := c.subnetsLister.List(labels.Everything())
×
211
        if err != nil {
×
212
                klog.Errorf("failed to list subnets: %v", err)
×
213
                return err
×
214
        }
×
215

216
        for _, subnet := range subnets {
×
217
                if subnet.Spec.Vlan == vlan.Name {
×
218
                        if err = c.setLocalnetTag(subnet.Name, vlan.Spec.ID); err != nil {
×
219
                                klog.Error(err)
×
220
                                return err
×
221
                        }
×
222
                }
223
        }
224

225
        return nil
×
226
}
227

228
func (c *Controller) handleDelVlan(key string) error {
×
229
        c.vlanKeyMutex.LockKey(key)
×
230
        defer func() { _ = c.vlanKeyMutex.UnlockKey(key) }()
×
231
        klog.Infof("handle delete vlan %s", key)
×
232

×
233
        subnet, err := c.subnetsLister.List(labels.Everything())
×
234
        if err != nil {
×
235
                klog.Errorf("failed to list subnets: %v", err)
×
236
                return err
×
237
        }
×
238

239
        for _, s := range subnet {
×
240
                if s.Spec.Vlan == key {
×
241
                        c.addOrUpdateSubnetQueue.Add(s.Name)
×
242
                }
×
243
        }
244

245
        providerNetworks, err := c.providerNetworksLister.List(labels.Everything())
×
246
        if err != nil && !k8serrors.IsNotFound(err) {
×
247
                klog.Errorf("failed to list provider networks: %v", err)
×
248
                return err
×
249
        }
×
250

251
        for _, pn := range providerNetworks {
×
252
                if err = c.updateProviderNetworkStatusForVlanDeletion(pn, key); err != nil {
×
253
                        klog.Error(err)
×
254
                        return err
×
255
                }
×
256
        }
257

258
        return nil
×
259
}
260

261
func (c *Controller) updateProviderNetworkStatusForVlanDeletion(pn *kubeovnv1.ProviderNetwork, vlan string) error {
×
262
        if !slices.Contains(pn.Status.Vlans, vlan) {
×
263
                return nil
×
264
        }
×
265

266
        newPn := pn.DeepCopy()
×
267
        newPn.Status.Vlans = util.RemoveString(newPn.Status.Vlans, vlan)
×
268
        _, err := c.config.KubeOvnClient.KubeovnV1().ProviderNetworks().UpdateStatus(context.Background(), newPn, metav1.UpdateOptions{})
×
269
        if err != nil {
×
270
                klog.Errorf("failed to update status of provider network %s: %v", pn.Name, err)
×
271
                return err
×
272
        }
×
273
        return nil
×
274
}
275

276
func (c *Controller) setLocalnetTag(subnet string, vlanID int) error {
×
277
        localnetPort := ovs.GetLocalnetName(subnet)
×
278
        if err := c.OVNNbClient.SetLogicalSwitchPortVlanTag(localnetPort, vlanID); err != nil {
×
279
                klog.Errorf("set localnet port %s vlan tag %d: %v", localnetPort, vlanID, err)
×
280
                return err
×
281
        }
×
282

283
        return nil
×
284
}
285

286
func (c *Controller) delLocalnet(subnet string) error {
×
287
        localnetPort := ovs.GetLocalnetName(subnet)
×
288
        if err := c.OVNNbClient.DeleteLogicalSwitchPort(localnetPort); err != nil {
×
289
                klog.Errorf("delete localnet port %s: %v", localnetPort, err)
×
290
                return err
×
291
        }
×
292

293
        return nil
×
294
}
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