Skip to content
Snippets Groups Projects
Commit 51b062a7 authored by Alex de Cock Buning's avatar Alex de Cock Buning
Browse files

overlays: parametrized network attachment definitions number

NetAttachDefs resources from multus now are created with the overlay, using the specified number inside the spec. By default it's still defined to 10 interfaces
parent ade7a040
No related branches found
No related tags found
No related merge requests found
...@@ -45,11 +45,12 @@ type OverlaySpec struct { ...@@ -45,11 +45,12 @@ type OverlaySpec struct {
// selecting the nodes that are going to be linked. // selecting the nodes that are going to be linked.
Topology *TopologySpec `json:"topology,omitempty"` 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. // Template describes the virtual switch pod that will be created.
SwitchTemplate *SwitchTemplateSpec `json:"switchTemplate"` 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 // OverlayStatus defines the observed state of Overlay
......
...@@ -44,14 +44,6 @@ spec: ...@@ -44,14 +44,6 @@ spec:
valueFrom: valueFrom:
fieldRef: fieldRef:
fieldPath: spec.nodeName fieldPath: spec.nodeName
- name: NVETHS
value: "10"
- name: CONTROLLERIP
value: "l2sm-controller-service"
- name: PODNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
imagePullPolicy: Always imagePullPolicy: Always
securityContext: securityContext:
capabilities: capabilities:
......
...@@ -5,6 +5,7 @@ go 1.21.7 ...@@ -5,6 +5,7 @@ go 1.21.7
toolchain go1.22.5 toolchain go1.22.5
require ( require (
github.com/Networks-it-uc3m/l2sm-switch v1.0.2
github.com/go-logr/logr v1.4.1 github.com/go-logr/logr v1.4.1
github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/ginkgo/v2 v2.14.0
github.com/onsi/gomega v1.30.0 github.com/onsi/gomega v1.30.0
...@@ -12,7 +13,6 @@ require ( ...@@ -12,7 +13,6 @@ require (
k8s.io/api v0.29.0 k8s.io/api v0.29.0
k8s.io/apimachinery v0.29.0 k8s.io/apimachinery v0.29.0
k8s.io/client-go 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 sigs.k8s.io/controller-runtime v0.17.0
) )
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
l2smv1 "github.com/Networks-it-uc3m/L2S-M/api/v1" l2smv1 "github.com/Networks-it-uc3m/L2S-M/api/v1"
"github.com/Networks-it-uc3m/L2S-M/internal/utils" "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" appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
...@@ -30,6 +31,8 @@ import ( ...@@ -30,6 +31,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log"
switchv1 "github.com/Networks-it-uc3m/l2sm-switch/api/v1"
) )
// OverlayReconciler reconciles a Overlay object // OverlayReconciler reconciles a Overlay object
...@@ -160,6 +163,10 @@ func (r *OverlayReconciler) SetupWithManager(mgr ctrl.Manager) error { ...@@ -160,6 +163,10 @@ func (r *OverlayReconciler) SetupWithManager(mgr ctrl.Manager) error {
// return nil // return nil
// } // }
type OverlayConfigJson struct {
ControllerIp string `json:"ControllerIp"`
}
type TopologySwitchJson struct { type TopologySwitchJson struct {
Nodes []NodeJson `json:"Nodes"` Nodes []NodeJson `json:"Nodes"`
Links []l2smv1.Link `json:"Links"` Links []l2smv1.Link `json:"Links"`
...@@ -176,13 +183,17 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -176,13 +183,17 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
constructConfigMapForOverlay := func(overlay *l2smv1.Overlay) (*corev1.ConfigMap, error) { constructConfigMapForOverlay := func(overlay *l2smv1.Overlay) (*corev1.ConfigMap, error) {
// Construct the TopologySwitchJson // 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 overlayName := overlay.ObjectMeta.Name
// Populate Nodes // Populate Nodes
for _, nodeName := range overlay.Spec.Topology.Nodes { for _, nodeName := range overlay.Spec.Topology.Nodes {
node := NodeJson{ node := switchv1.Node{
Name: nodeName, Name: nodeName,
NodeIP: fmt.Sprintf("l2sm-switch-%s-%s", overlayName, nodeName), NodeIP: fmt.Sprintf("l2sm-switch-%s-%s", overlayName, nodeName),
} }
...@@ -190,7 +201,13 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -190,7 +201,13 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
} }
// Populate Links // 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 // Convert TopologySwitchJson to JSON
topologyJSON, err := json.Marshal(topologySwitch) topologyJSON, err := json.Marshal(topologySwitch)
...@@ -198,6 +215,10 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -198,6 +215,10 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
return nil, err return nil, err
} }
configJSON, err := json.Marshal(overlayConfig)
if err != nil {
return nil, err
}
configMap := &corev1.ConfigMap{ configMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-topology", overlay.Name), Name: fmt.Sprintf("%s-topology", overlay.Name),
...@@ -205,6 +226,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -205,6 +226,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
}, },
Data: map[string]string{ Data: map[string]string{
"topology.json": string(topologyJSON), "topology.json": string(topologyJSON),
"config.json": string(configJSON),
}, },
} }
if err := controllerutil.SetControllerReference(overlay, configMap, r.Scheme); err != nil { if err := controllerutil.SetControllerReference(overlay, configMap, r.Scheme); err != nil {
...@@ -220,7 +242,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -220,7 +242,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
return err 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 // Define volume mounts to be added to each container
volumeMounts := []corev1.VolumeMount{ volumeMounts := []corev1.VolumeMount{
...@@ -229,6 +251,11 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -229,6 +251,11 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
MountPath: "/etc/l2sm/", MountPath: "/etc/l2sm/",
ReadOnly: true, ReadOnly: true,
}, },
{
Name: "configuration",
MountPath: "/etc/l2sm/",
ReadOnly: true,
},
} }
// Update containers to include the volume mount // Update containers to include the volume mount
...@@ -256,11 +283,54 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -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 replicaSets []*appsv1.ReplicaSet
var services []*corev1.Service var services []*corev1.Service
for _, node := range overlay.Spec.Topology.Nodes { for _, node := range overlay.Spec.Topology.Nodes {
name := fmt.Sprintf("%s-%s-%s", "l2sm-switch", node, utils.GenerateHash(overlay)) name := fmt.Sprintf("%s-%s-%s", "l2sm-switch", node, utils.GenerateHash(overlay))
...@@ -285,27 +355,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -285,27 +355,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
"app": name, "app": name,
}, },
Annotations: map[string]string{ Annotations: map[string]string{
"k8s.v1.cni.cncf.io/networks": `[{ MULTUS_ANNOTATION_KEY: switchInterfacesAnnotations,
"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"]
}]`,
}, },
}, },
Spec: corev1.PodSpec{ Spec: corev1.PodSpec{
...@@ -326,7 +376,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -326,7 +376,7 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
replicaSet.Labels[k] = v replicaSet.Labels[k] = v
} }
if err := controllerutil.SetControllerReference(overlay, replicaSet, r.Scheme); err != nil { if err := controllerutil.SetControllerReference(overlay, replicaSet, r.Scheme); err != nil {
return nil, nil, err return nil, nil, nil, err
} }
replicaSets = append(replicaSets, replicaSet) replicaSets = append(replicaSets, replicaSet)
...@@ -351,20 +401,24 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay ...@@ -351,20 +401,24 @@ func (r *OverlayReconciler) createExternalResources(ctx context.Context, overlay
} }
if err := controllerutil.SetControllerReference(overlay, service, r.Scheme); err != nil { if err := controllerutil.SetControllerReference(overlay, service, r.Scheme); err != nil {
return nil, nil, err return nil, nil, nil, err
} }
services = append(services, service) 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 { if err != nil {
return err return err
} }
for _, netAttachDef := range netAttachDefs {
if err = r.Client.Create(ctx, netAttachDef); err != nil {
return err
}
}
for _, replicaSet := range replicaSets { for _, replicaSet := range replicaSets {
if err = r.Client.Create(ctx, replicaSet); err != nil { if err = r.Client.Create(ctx, replicaSet); err != nil {
return err return err
......
...@@ -154,3 +154,26 @@ func (r *PodReconciler) DetachNetAttachDef(ctx context.Context, multusNetAttachD ...@@ -154,3 +154,26 @@ func (r *PodReconciler) DetachNetAttachDef(ctx context.Context, multusNetAttachD
return err 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
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment