Skip to content

Commit 57c9624

Browse files
committed
update cluster network name to overlay VM Network
Signed-off-by: Renuka Devi Rajendran <renuka.rajendran@suse.com>
1 parent d9f7492 commit 57c9624

File tree

10 files changed

+142
-109
lines changed

10 files changed

+142
-109
lines changed

cmd/webhook/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func run(ctx context.Context, cfg *rest.Config, options *config.Options) error {
137137
webhookServer := server.NewWebhookServer(ctx, cfg, name, options)
138138

139139
if err := webhookServer.RegisterMutators(
140-
nad.NewNadMutator(c.cnCache, c.vcCache),
140+
nad.NewNadMutator(c.cnCache, c.vcCache, c.nodeCache),
141141
vlanconfig.NewVlanConfigMutator(c.nodeCache),
142142
); err != nil {
143143
return fmt.Errorf("failed to register mutators: %v", err)

pkg/controller/agent/clusternetwork/controller.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,18 @@ const (
2323
)
2424

2525
type Handler struct {
26-
cnCache ctlnetworkv1.ClusterNetworkCache
27-
cnClient ctlnetworkv1.ClusterNetworkClient
28-
nadCache ctlcniv1.NetworkAttachmentDefinitionCache
29-
nadClient ctlcniv1.NetworkAttachmentDefinitionClient
26+
cnCache ctlnetworkv1.ClusterNetworkCache
27+
cnClient ctlnetworkv1.ClusterNetworkClient
28+
nadCache ctlcniv1.NetworkAttachmentDefinitionCache
3029
}
3130

3231
func Register(ctx context.Context, management *config.Management) error {
3332
cns := management.HarvesterNetworkFactory.Network().V1beta1().ClusterNetwork()
3433
nads := management.CniFactory.K8s().V1().NetworkAttachmentDefinition()
3534
handler := Handler{
36-
cnCache: cns.Cache(),
37-
cnClient: cns,
38-
nadClient: nads,
39-
nadCache: nads.Cache(),
35+
cnCache: cns.Cache(),
36+
cnClient: cns,
37+
nadCache: nads.Cache(),
4038
}
4139

4240
cns.OnChange(ctx, controllerName, handler.OnChange)

pkg/controller/agent/hostnetworkconfig/controller.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,13 @@ func (h *Handler) OnChange(_ string, hnc *networkv1.HostNetworkConfig) (*network
131131

132132
// node selector matches and host network interface already exists, skip processing
133133
if intfExists {
134-
logrus.Infof("hostnetwork config %s has been applied on this node already, update nodestatus and skip", hnc.Name)
134+
logrus.Infof("hostnetwork config %s has been applied on this node already, update nodestatus,tunnel interface annotation and skip", hnc.Name)
135+
136+
// intf exists but there could be change in underlay, need to update node annotation with new interface if needed
137+
if err := h.addNodeAnnotation(utils.GetClusterNetworkVlanDevice(hnc.Spec.ClusterNetwork, hnc.Spec.VlanID), hnc.Spec.Underlay); err != nil {
138+
return nil, fmt.Errorf("add node annotation to node %s for host network config %s failed, error: %w", h.nodeName, hnc.Name, err)
139+
}
140+
135141
err := h.setHostNetworkPerNodeStatus(hnc, true, nil)
136142
if err != nil {
137143
return nil, err

pkg/controller/manager/node/controller.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import (
1414

1515
networkv1 "github.com/harvester/harvester-network-controller/pkg/apis/network.harvesterhci.io/v1beta1"
1616
"github.com/harvester/harvester-network-controller/pkg/config"
17+
ctlcniv1 "github.com/harvester/harvester-network-controller/pkg/generated/controllers/k8s.cni.cncf.io/v1"
1718
ctlnetworkv1 "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io/v1beta1"
1819
"github.com/harvester/harvester-network-controller/pkg/utils"
20+
cniv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
1921
)
2022

2123
const controllerName = "harvester-network-manager-node-controller"
@@ -30,6 +32,8 @@ type Handler struct {
3032
lmClient ctlnetworkv1.LinkMonitorClient
3133
hostNetworkConfigClient ctlnetworkv1.HostNetworkConfigClient
3234
hostNetworkConfigCache ctlnetworkv1.HostNetworkConfigCache
35+
nadCache ctlcniv1.NetworkAttachmentDefinitionCache
36+
nadClient ctlcniv1.NetworkAttachmentDefinitionClient
3337
}
3438

3539
func Register(ctx context.Context, management *config.Management) error {
@@ -38,6 +42,7 @@ func Register(ctx context.Context, management *config.Management) error {
3842
vss := management.HarvesterNetworkFactory.Network().V1beta1().VlanStatus()
3943
lms := management.HarvesterNetworkFactory.Network().V1beta1().LinkMonitor()
4044
hns := management.HarvesterNetworkFactory.Network().V1beta1().HostNetworkConfig()
45+
nads := management.CniFactory.K8s().V1().NetworkAttachmentDefinition()
4146

4247
h := Handler{
4348
nodeClient: nodes,
@@ -49,6 +54,8 @@ func Register(ctx context.Context, management *config.Management) error {
4954
lmClient: lms,
5055
hostNetworkConfigClient: hns,
5156
hostNetworkConfigCache: hns.Cache(),
57+
nadClient: nads,
58+
nadCache: nads.Cache(),
5259
}
5360

5461
nodes.OnChange(ctx, controllerName, h.OnChange)
@@ -86,6 +93,10 @@ func (h Handler) OnChange(_ string, node *corev1.Node) (*corev1.Node, error) {
8693
return nil, fmt.Errorf("failed to update host network annotations, node: %s, error: %w", node.Name, err)
8794
}
8895

96+
if err := h.updateUnderlayForOverlayNetwork(node); err != nil {
97+
return nil, fmt.Errorf("failed to update underlay for overlay network, node: %s, error: %w", node.Name, err)
98+
}
99+
89100
return node, nil
90101
}
91102

@@ -305,3 +316,53 @@ func (h Handler) updateHostNetworkAnnotation(node *corev1.Node) error {
305316

306317
return nil
307318
}
319+
320+
func (h Handler) setNadClusterNetworkLabel(bridge string) (err error) {
321+
var nadList []*cniv1.NetworkAttachmentDefinition
322+
nadGetter := utils.NewNadGetter(h.nadCache)
323+
if nadList, err = nadGetter.ListAllNads(); err != nil {
324+
return fmt.Errorf("failed to list nads err %w", err)
325+
}
326+
327+
for _, nad := range nadList {
328+
if nad.DeletionTimestamp != nil {
329+
continue
330+
}
331+
332+
if !utils.IsOverlayNad(nad) {
333+
continue
334+
}
335+
336+
if utils.GetNadLabel(nad, utils.KeyClusterNetworkLabel) == bridge {
337+
continue
338+
}
339+
nadCopy := nad.DeepCopy()
340+
utils.SetNadLabel(nadCopy, utils.KeyClusterNetworkLabel, bridge)
341+
if _, err := h.nadClient.Update(nadCopy); err != nil {
342+
return err
343+
}
344+
}
345+
346+
return nil
347+
}
348+
349+
func (h Handler) updateUnderlayForOverlayNetwork(node *corev1.Node) error {
350+
if node.Annotations == nil {
351+
return nil
352+
}
353+
354+
iface, ok := node.Annotations[utils.KeyUnderlayIntf]
355+
if !ok || iface == "" {
356+
return nil
357+
}
358+
bridge, err := utils.GetClusterNetworkName(iface)
359+
if err != nil {
360+
return fmt.Errorf("failed to get bridge name from node %s annotation, error: %w", node.Name, err)
361+
}
362+
363+
if err := h.setNadClusterNetworkLabel(bridge); err != nil {
364+
return fmt.Errorf("failed to set NAD cluster network label for node %s, error: %w", node.Name, err)
365+
}
366+
367+
return nil
368+
}

pkg/utils/clusternetwork.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package utils
22

33
import (
44
"fmt"
5+
"strings"
56

67
networkv1 "github.com/harvester/harvester-network-controller/pkg/apis/network.harvesterhci.io/v1beta1"
78
)
@@ -34,3 +35,11 @@ func SetClusterNetworkVlanAnnotations(cn *networkv1.ClusterNetwork, vidstr, vidh
3435
cn.Annotations[KeyVlanIDSetStr] = vidstr
3536
cn.Annotations[KeyVlanIDSetStrHash] = vidhash
3637
}
38+
39+
func GetClusterNetworkName(iface string) (string, error) {
40+
cnName, _, found := strings.Cut(iface, BridgeSuffix)
41+
if !found {
42+
return "", fmt.Errorf("invalid interface format: %s", iface)
43+
}
44+
return cnName, nil
45+
}

pkg/webhook/hostnetworkconfig/validator.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,9 @@ func (v *Validator) Update(_ *admission.Request, oldObj, newObj runtime.Object)
165165
func (v *Validator) Delete(_ *admission.Request, oldObj runtime.Object) error {
166166
hnc := oldObj.(*networkv1.HostNetworkConfig)
167167

168-
if !hnc.Spec.Underlay {
169-
//delete hostnetworkconfig if its not serving as underlay
170-
return nil
171-
}
172-
173-
if err := v.checkifVMExistsForOverlayNADs(); err != nil {
174-
return fmt.Errorf(deleteErr, hnc.Name, err)
168+
//since ovn is already using the interface as underlay, user should disable it first in hostnetworkconfig before deleting it.
169+
if hnc.Spec.Underlay {
170+
return fmt.Errorf(deleteErr, hnc.Name, fmt.Errorf("underlay is enabled, disable underlay first"))
175171
}
176172

177173
return nil

pkg/webhook/hostnetworkconfig/validator_test.go

Lines changed: 5 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"strings"
55
"testing"
66

7-
"github.com/sirupsen/logrus"
87
"github.com/stretchr/testify/assert"
98
v1 "k8s.io/api/core/v1"
109
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -547,7 +546,6 @@ func TestCreateHostNetworkConfig(t *testing.T) {
547546
validator := NewHostNetworkConfigValidator(nadCache, cnCache, hncCache, vcCache, vsCache, nodeCache, vmCache)
548547

549548
err := validator.Create(nil, tc.newHostNetworkConfig)
550-
logrus.Infof("test case %s returned error: %v", tc.name, err)
551549
assert.True(t, tc.returnErr == (err != nil))
552550
if tc.returnErr {
553551
assert.NotNil(t, err)
@@ -932,7 +930,6 @@ func TestUpdateHostNetworkConfig(t *testing.T) {
932930
validator := NewHostNetworkConfigValidator(nadCache, cnCache, hncCache, vcCache, vsCache, nodeCache, vmCache)
933931

934932
err := validator.Update(nil, tc.currentHostNetworkConfig, tc.newHostNetworkConfig)
935-
logrus.Infof("test case %s returned error: %v", tc.name, err)
936933
assert.True(t, tc.returnErr == (err != nil))
937934
if tc.returnErr {
938935
assert.NotNil(t, err)
@@ -947,13 +944,10 @@ func TestDeleteHostNetworkConfig(t *testing.T) {
947944
name string
948945
returnErr bool
949946
errKey string
950-
currentCN *networkv1.ClusterNetwork
951-
currentNAD *cniv1.NetworkAttachmentDefinition
952947
currentHostNetworkConfig *networkv1.HostNetworkConfig
953-
currentVM *kubevirtv1.VirtualMachine
954948
}{
955949
{
956-
name: "delete hostnetworkconfig successfully when not used by any overlay VMs",
950+
name: "delete hostnetworkconfig successfully",
957951
returnErr: false,
958952
errKey: "",
959953
currentHostNetworkConfig: &networkv1.HostNetworkConfig{
@@ -962,62 +956,15 @@ func TestDeleteHostNetworkConfig(t *testing.T) {
962956
VlanID: 2012,
963957
Mode: "static",
964958
HostIPs: map[string]networkv1.IPAddr{"node1": "192.168.1.100/24"},
965-
Underlay: true,
959+
Underlay: false,
966960
},
967961
},
968962
},
969963
{
970-
name: "cannot delete hostnetworkconfig when used by overlay VMs",
964+
name: "cannot delete hostnetworkconfig when underlay is enabled",
971965
returnErr: true,
972-
errKey: "it's still used by VM(s)",
973-
currentCN: &networkv1.ClusterNetwork{
974-
ObjectMeta: metav1.ObjectMeta{
975-
Name: testCnName,
976-
Annotations: map[string]string{"test": "test"},
977-
},
978-
},
979-
currentNAD: &cniv1.NetworkAttachmentDefinition{
980-
ObjectMeta: metav1.ObjectMeta{
981-
Name: testNadName,
982-
Namespace: testNamespace,
983-
Annotations: map[string]string{"test": "test"},
984-
Labels: map[string]string{utils.KeyClusterNetworkLabel: testCnName, utils.KeyNetworkType: string(utils.OverlayNetwork)},
985-
},
986-
Spec: cniv1.NetworkAttachmentDefinitionSpec{
987-
Config: testNadConfig,
988-
},
989-
},
990-
currentVM: &kubevirtv1.VirtualMachine{
991-
ObjectMeta: metav1.ObjectMeta{
992-
Name: testVMName,
993-
Namespace: testNamespace,
994-
},
995-
Spec: kubevirtv1.VirtualMachineSpec{
996-
Template: &kubevirtv1.VirtualMachineInstanceTemplateSpec{
997-
Spec: kubevirtv1.VirtualMachineInstanceSpec{
998-
Networks: []kubevirtv1.Network{
999-
{
1000-
Name: "nic-1",
1001-
NetworkSource: kubevirtv1.NetworkSource{
1002-
Multus: &kubevirtv1.MultusNetwork{
1003-
NetworkName: testNamespace + "/" + testNadName, // same with nad namesapce
1004-
},
1005-
},
1006-
},
1007-
},
1008-
Domain: kubevirtv1.DomainSpec{
1009-
Devices: kubevirtv1.Devices{
1010-
Interfaces: []kubevirtv1.Interface{
1011-
{
1012-
Name: "nic-1",
1013-
},
1014-
},
1015-
},
1016-
},
1017-
}, // vmi.spec
1018-
},
1019-
},
1020-
},
966+
errKey: "disable underlay first",
967+
1021968
currentHostNetworkConfig: &networkv1.HostNetworkConfig{
1022969
Spec: networkv1.HostNetworkConfigSpec{
1023970
ClusterNetwork: testCnName,
@@ -1044,33 +991,10 @@ func TestDeleteHostNetworkConfig(t *testing.T) {
1044991

1045992
// client to inject test data
1046993
cnCache := fakeclients.ClusterNetworkCache(nchclientset.NetworkV1beta1().ClusterNetworks)
1047-
cnClient := fakeclients.ClusterNetworkClient(nchclientset.NetworkV1beta1().ClusterNetworks)
1048994
vcCache := fakeclients.VlanConfigCache(nchclientset.NetworkV1beta1().VlanConfigs)
1049995
vsCache := fakeclients.VlanStatusCache(nchclientset.NetworkV1beta1().VlanStatuses)
1050996
nodeCache := fakeclients.NodeCache(nchclientset.CoreV1().Nodes)
1051997

1052-
if tc.currentVM != nil {
1053-
err := nchclientset.Tracker().Add(tc.currentVM)
1054-
assert.Nil(t, err, "mock resource vm should add into fake controller tracker")
1055-
}
1056-
1057-
if tc.currentCN != nil {
1058-
_, err := cnClient.Create(tc.currentCN)
1059-
assert.NoError(t, err)
1060-
}
1061-
1062-
if tc.currentNAD != nil {
1063-
nadGvr := schema.GroupVersionResource{
1064-
Group: "k8s.cni.cncf.io",
1065-
Version: "v1",
1066-
Resource: "network-attachment-definitions",
1067-
}
1068-
1069-
if err := nchclientset.Tracker().Create(nadGvr, tc.currentNAD.DeepCopy(), tc.currentNAD.Namespace); err != nil {
1070-
t.Fatalf("failed to add nad %+v", tc.currentNAD)
1071-
}
1072-
}
1073-
1074998
if tc.currentHostNetworkConfig != nil {
1075999
hncClient := fakeclients.HostNetworkConfigClient(nchclientset.NetworkV1beta1().HostNetworkConfigs)
10761000
_, err := hncClient.Create(tc.currentHostNetworkConfig)

0 commit comments

Comments
 (0)