diff --git a/api/v1/overlay_types.go b/api/v1/overlay_types.go index 191aaf340e611d5e8445be13fd31e3a3565516cc..31b827f0c7a168b9a3aaf900fcbae01609d01015 100644 --- a/api/v1/overlay_types.go +++ b/api/v1/overlay_types.go @@ -45,11 +45,12 @@ type OverlaySpec struct { // selecting the nodes that are going to be linked. Topology *TopologySpec `json:"topology,omitempty"` - // Field exclusive to the multi-domain overlay type. If specified in other types of overlays, the reosurce will launch an error and won't be created. - Neighbors []NeighborSpec `json:"neighbors,omitempty"` - // Template describes the virtual switch pod that will be created. SwitchTemplate *SwitchTemplateSpec `json:"switchTemplate"` + + // Interface number specifies how many interfaces the switch should have predefined (if used with multus) + //+kubebuilder:default:value=10 + InterfaceNumber int `json:"interfaceNumber,omitempty"` } // OverlayStatus defines the observed state of Overlay diff --git a/config/samples/l2sm_v1_overlay.yaml b/config/samples/l2sm_v1_overlay.yaml index 8df97f3501fb0d79cf2e0bb5d5ca6f9e52169761..626efb84690c2f56f826130be7f529bd9bfcd5bb 100644 --- a/config/samples/l2sm_v1_overlay.yaml +++ b/config/samples/l2sm_v1_overlay.yaml @@ -44,14 +44,6 @@ spec: valueFrom: fieldRef: fieldPath: spec.nodeName - - name: NVETHS - value: "10" - - name: CONTROLLERIP - value: "l2sm-controller-service" - - name: PODNAME - valueFrom: - fieldRef: - fieldPath: metadata.name imagePullPolicy: Always securityContext: capabilities: diff --git a/go.mod b/go.mod index f2b49960b6d990030acd7671fcf8b8ac0616c0da..f1b8f9098562d070a8106839199300c31c209dbf 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21.7 toolchain go1.22.5 require ( + github.com/Networks-it-uc3m/l2sm-switch v1.0.2 github.com/go-logr/logr v1.4.1 github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/gomega v1.30.0 @@ -12,7 +13,6 @@ require ( k8s.io/api v0.29.0 k8s.io/apimachinery v0.29.0 k8s.io/client-go v0.29.0 - github.com/Networks-it-uc3m/l2sm-switch v1.0.0 sigs.k8s.io/controller-runtime v0.17.0 ) diff --git a/go.sum b/go.sum index 3032b5cc403587524030d7eef7cce4d6b7015246..97080749ab21c6d30ac0c3405bac199fa96f1ce1 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/Networks-it-uc3m/l2sm-switch v1.0.0 h1:SQ2hFmObffhNV2jVSeSpqVGCm2/d6HZuQ02YzeCI+x0= github.com/Networks-it-uc3m/l2sm-switch v1.0.0/go.mod h1:zcfUyOLAiCEQza5QRTJoQsrOYdu+WQf/6rQNmhGb4WQ= +github.com/Networks-it-uc3m/l2sm-switch v1.0.1 h1:nMvK0K13UGloG+S/33/DhEvc+U5MvcBWKL/qqgEmylI= +github.com/Networks-it-uc3m/l2sm-switch v1.0.1/go.mod h1:zcfUyOLAiCEQza5QRTJoQsrOYdu+WQf/6rQNmhGb4WQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= diff --git a/internal/controller/overlay_controller.go b/internal/controller/overlay_controller.go index 64a61d37291abed64d19158ab23087e532eacec3..ebff2453a3e5c5749d18f4f76aac5671cc6a476f 100644 --- a/internal/controller/overlay_controller.go +++ b/internal/controller/overlay_controller.go @@ -22,6 +22,7 @@ import ( l2smv1 "github.com/Networks-it-uc3m/L2S-M/api/v1" "github.com/Networks-it-uc3m/L2S-M/internal/utils" + nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,6 +31,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" + + switchv1 "github.com/Networks-it-uc3m/l2sm-switch/api/v1" ) // OverlayReconciler reconciles a Overlay object @@ -160,6 +163,10 @@ func (r *OverlayReconciler) SetupWithManager(mgr ctrl.Manager) error { // return nil // } +type OverlayConfigJson struct { + ControllerIp string `json:"ControllerIp"` +} + type TopologySwitchJson struct { Nodes []NodeJson `json:"Nodes"` Links []l2smv1.Link `json:"Links"` @@ -176,13 +183,17 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay constructConfigMapForOverlay := func(overlay *l2smv1.Overlay) (*corev1.ConfigMap, error) { // Construct the TopologySwitchJson - topologySwitch := TopologySwitchJson{} + topologySwitch := switchv1.Topology{} + + overlayConfig := switchv1.OverlaySettings{ControllerIp: overlay.Spec.NetworkController.Domain, + InterfacesNumber: overlay.Spec.InterfaceNumber, + OverlayName: overlay.Name} overlayName := overlay.ObjectMeta.Name // Populate Nodes for _, nodeName := range overlay.Spec.Topology.Nodes { - node := NodeJson{ + node := switchv1.Node{ Name: nodeName, NodeIP: fmt.Sprintf("l2sm-switch-%s-%s", overlayName, nodeName), } @@ -190,7 +201,13 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay } // Populate Links - topologySwitch.Links = append(topologySwitch.Links, overlay.Spec.Topology.Links...) + for _, overlayLink := range overlay.Spec.Topology.Links { + link := switchv1.Link{ + EndpointNodeA: overlayLink.EndpointA, + EndpointNodeB: overlayLink.EndpointB, + } + topologySwitch.Links = append(topologySwitch.Links, link) + } // Convert TopologySwitchJson to JSON topologyJSON, err := json.Marshal(topologySwitch) @@ -198,6 +215,10 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay return nil, err } + configJSON, err := json.Marshal(overlayConfig) + if err != nil { + return nil, err + } configMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-topology", overlay.Name), @@ -205,6 +226,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay }, Data: map[string]string{ "topology.json": string(topologyJSON), + "config.json": string(configJSON), }, } if err := controllerutil.SetControllerReference(overlay, configMap, r.Scheme); err != nil { @@ -220,7 +242,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay return err } - constructNodeResourcesForOverlay := func(overlay *l2smv1.Overlay) ([]*appsv1.ReplicaSet, []*corev1.Service, error) { + constructNodeResourcesForOverlay := func(overlay *l2smv1.Overlay) ([]*appsv1.ReplicaSet, []*corev1.Service, []*nettypes.NetworkAttachmentDefinition, error) { // Define volume mounts to be added to each container volumeMounts := []corev1.VolumeMount{ @@ -229,6 +251,11 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay MountPath: "/etc/l2sm/", ReadOnly: true, }, + { + Name: "configuration", + MountPath: "/etc/l2sm/", + ReadOnly: true, + }, } // Update containers to include the volume mount @@ -256,11 +283,54 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay }, }, }, + { + Name: "configuration", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: configMap.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: "config.json", + Path: "config.json", + }, + }, + }, + }, + }, + } + + switchInterfacesAnnotations := GenerateAnnotations(overlay.Name, overlay.Spec.InterfaceNumber) + + var networkAttachmentDefinitions []*nettypes.NetworkAttachmentDefinition + var auxNetAttachDef *nettypes.NetworkAttachmentDefinition + + for i := 1; i <= overlay.Spec.InterfaceNumber; i++ { + auxNetAttachDef = &nettypes.NetworkAttachmentDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-veth%d", overlay.Name, i), + Namespace: overlay.Namespace, + Labels: map[string]string{"app": "l2sm"}, + }, + Spec: nettypes.NetworkAttachmentDefinitionSpec{ + Config: fmt.Sprintf(`{ + "cniVersion": "0.3.0", + "type": "bridge", + "bridge": "%s-br%d", + "mtu": 1400, + "device": "%s-veth%d", + "ipam": { + "type":"static" + } + }`, overlay.Name, i, overlay.Name, i), + }, + } + networkAttachmentDefinitions = append(networkAttachmentDefinitions, auxNetAttachDef) } var replicaSets []*appsv1.ReplicaSet var services []*corev1.Service - for _, node := range overlay.Spec.Topology.Nodes { name := fmt.Sprintf("%s-%s-%s", "l2sm-switch", node, utils.GenerateHash(overlay)) @@ -285,27 +355,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay "app": name, }, Annotations: map[string]string{ - "k8s.v1.cni.cncf.io/networks": `[{ - "name": "veth1", "ips": ["fe80::58d0:b8ff:fe42:debf/64"] - }, { - "name": "veth2", "ips": ["fe80::58d0:b8ff:fe42:debe/64"] - }, { - "name": "veth3", "ips": ["fe80::58d0:b8ff:fe42:debd/64"] - }, { - "name": "veth4", "ips": ["fe80::58d0:b8ff:fe42:debc/64"] - }, { - "name": "veth5", "ips": ["fe80::58d0:b8ff:fe42:debb/64"] - }, { - "name": "veth6", "ips": ["fe80::58d0:b8ff:fe42:deba/64"] - }, { - "name": "veth7", "ips": ["fe80::58d0:b8ff:fe42:deb9/64"] - }, { - "name": "veth8", "ips": ["fe80::58d0:b8ff:fe42:deb8/64"] - }, { - "name": "veth9", "ips": ["fe80::58d0:b8ff:fe42:deb7/64"] - }, { - "name": "veth10", "ips": ["fe80::58d0:b8ff:fe42:deb6/64"] - }]`, + MULTUS_ANNOTATION_KEY: switchInterfacesAnnotations, }, }, Spec: corev1.PodSpec{ @@ -326,7 +376,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay replicaSet.Labels[k] = v } if err := controllerutil.SetControllerReference(overlay, replicaSet, r.Scheme); err != nil { - return nil, nil, err + return nil, nil, nil, err } replicaSets = append(replicaSets, replicaSet) @@ -351,20 +401,24 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay } if err := controllerutil.SetControllerReference(overlay, service, r.Scheme); err != nil { - return nil, nil, err + return nil, nil, nil, err } services = append(services, service) } - return replicaSets, services, nil + return replicaSets, services, networkAttachmentDefinitions, nil } - replicaSets, services, err := constructNodeResourcesForOverlay(overlay) + replicaSets, services, netAttachDefs, err := constructNodeResourcesForOverlay(overlay) if err != nil { return err } - + for _, netAttachDef := range netAttachDefs { + if err = r.Client.Create(ctx, netAttachDef); err != nil { + return err + } + } for _, replicaSet := range replicaSets { if err = r.Client.Create(ctx, replicaSet); err != nil { return err diff --git a/internal/controller/pod_utils.go b/internal/controller/pod_utils.go index 3b0d20f13009353dbb0c1aca2db3422ef25d0204..6ebbbbbf5acce4c2f391b2c3cd207573df6885d4 100644 --- a/internal/controller/pod_utils.go +++ b/internal/controller/pod_utils.go @@ -154,3 +154,26 @@ func (r *PodReconciler) DetachNetAttachDef(ctx context.Context, multusNetAttachD return err } + +func GenerateAnnotations(overlayName string, ammount int) string { + annotationsString := []string{} + var newAnnotation string + for i := 1; i <= ammount; i++ { + newAnnotation = fmt.Sprintf(`{"name": "%s-veth%d", "ips": ["fe80::58d0:b8ff:fe%s:%s/64"]}`, overlayName, i, fmt.Sprintf("%02d", i), Generate4byteChunk) + annotationsString = append(annotationsString, newAnnotation) + } + + return "[" + strings.Join(annotationsString, ",") + "]" +} + +func Generate4byteChunk() string { + + // Generating the interface ID (64 bits) + interfaceID := rand.Uint64() + + // Formatting to a 16 character hexadecimal string + interfaceIDHex := fmt.Sprintf("%04x", interfaceID) + + return interfaceIDHex + +}