Skip to content

Commit b960688

Browse files
committed
feat: Add support for Cisco NXOS VPCs
* Multi-Chassis Link Aggregation (MC-LAG) is quite vendor and platform specific. We don't see much intersection in their respective configuration to justify a common API type. Instead, we move forward with a platform specific API exclusive to Cisco NXOS devices. * This commit adds new types, controller, and provider to configure virtual Port Channels (vPCs) via the operator.
1 parent a834714 commit b960688

25 files changed

+1246
-370
lines changed

PROJECT

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,13 @@ resources:
118118
kind: ISIS
119119
path: github.com/ironcore-dev/network-operator/api/v1alpha1
120120
version: v1alpha1
121+
- api:
122+
crdVersion: v1
123+
namespaced: true
124+
controller: true
125+
domain: cloud.sap
126+
group: networking
127+
kind: NXOSVPC
128+
path: github.com/ironcore-dev/network-operator/api/v1alpha1
129+
version: v1alpha1
121130
version: "3"

Tiltfile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ local_resource('controller-gen', 'make generate', ignore=['*/*/zz_generated.deep
2222

2323
docker_build('ghcr.io/ironcore-dev/gnmi-test-server:latest', './test/gnmi')
2424

25-
provider = os.getenv('PROVIDER', 'openconfig')
25+
provider = os.getenv('PROVIDER', 'cisco-nxos-gnmi')
2626

2727
manager = kustomize('config/develop')
2828
manager = str(manager).replace('--provider=openconfig', '--provider={}'.format(provider))
@@ -78,6 +78,11 @@ k8s_resource(new_name='managementaccess', objects=['managementaccess:managementa
7878
k8s_yaml('./config/samples/v1alpha1_isis.yaml')
7979
k8s_resource(new_name='underlay', objects=['underlay:isis'], resource_deps=['lo0', 'lo1', 'eth1-1', 'eth1-2'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
8080

81+
# TODO: add resource_deps=['po1', 'po2'] when port-channel resource is implemented
82+
k8s_yaml('./config/samples/v1alpha1_nxosvpc.yaml')
83+
k8s_resource(new_name='vpc', objects=['nxosvpc:nxosvpc'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
84+
85+
8186
print('🚀 network-operator development environment')
8287
print('👉 Edit the code inside the api/, cmd/, or internal/ directories')
8388
print('👉 Tilt will automatically rebuild and redeploy when changes are detected')

api/v1alpha1/nxosvpc_types.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import (
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
)
9+
10+
// NXOSVPCSpec defines the desired state of NXOSVPC (Cisco's NXOS Virtual Port Channel)
11+
type NXOSVPCSpec struct {
12+
// DeviceName is the name of the Device this object belongs to. The Device object must exist in the same namespace.
13+
// Immutable.
14+
// +required
15+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="DeviceRef is immutable"
16+
DeviceRef LocalObjectReference `json:"deviceRef"`
17+
18+
// DomainID is the vPC domain ID.
19+
// +required
20+
// +kubebuilder:validation:Minimum=1
21+
// +kubebuilder:validation:Maximum=1000
22+
DomainID int32 `json:"domainId"`
23+
24+
// AdminState is the administrative state of the vPC domain.
25+
// +required
26+
// +kubebuilder:default="enabled"
27+
// +kubebuilder:validation:Enum=enabled;disabled
28+
AdminState string `json:"adminState,omitempty"`
29+
30+
// RolePriority is the role priority for this vPC domain.
31+
// +required
32+
// +kubebuilder:validation:Minimum=1
33+
// +kubebuilder:validation:Maximum=65535
34+
RolePriority uint16 `json:"rolePriority"`
35+
36+
// SystemPriority is the system priority for this vPC domain.
37+
// +required
38+
// +kubebuilder:validation:Minimum=1
39+
// +kubebuilder:validation:Maximum=65535
40+
SystemPriority uint16 `json:"systemPriority"`
41+
42+
// DelayRestoreSVI is the delay in bringing up bringing-up the interface-vlan
43+
// +required
44+
// +kubebuilder:validation:Minimum=1
45+
// +kubebuilder:validation:Maximum=3600
46+
DelayRestoreSVI uint16 `json:"delayRestoreSVI"`
47+
48+
// DelayRestoreVPC is the delay in bringing up the vPC links after restoring the peer-link
49+
// +required
50+
// +kubebuilder:validation:Minimum=1
51+
// +kubebuilder:validation:Maximum=3600
52+
DelayRestoreVPC uint16 `json:"delayRestoreVPC"`
53+
54+
// +required
55+
FastConvergence AdminSt `json:"fastConvergence"`
56+
57+
// +required
58+
Peer Peer `json:"peer"`
59+
}
60+
61+
// AdminSt represents administrative state (enabled/disabled)
62+
type AdminSt struct {
63+
// +required
64+
Enabled bool `json:"enabled"`
65+
}
66+
67+
type Peer struct {
68+
// +required
69+
KeepAlive KeepAlive `json:"keepalive"`
70+
71+
// +required
72+
AutoRecovery AutoRecovery `json:"autoRecovery"`
73+
74+
// +required
75+
Switch AdminSt `json:"switch"`
76+
77+
// +required
78+
Gateway AdminSt `json:"gateway"`
79+
80+
// Router defines layer3 peer-router settings
81+
// +required
82+
Router AdminSt `json:"router"`
83+
}
84+
85+
type KeepAlive struct {
86+
// Destination is the destination IP address
87+
// +required
88+
Destination string `json:"destination"`
89+
90+
// Source is the source IP address
91+
// +required
92+
Source string `json:"source"`
93+
94+
// +optional
95+
VRF string `json:"vrf,omitempty"`
96+
}
97+
98+
// AutoRecovery holds autorecovery settings.
99+
// +kubebuilder:validation:XValidation:rule="self.enabled ? has(self.reloadDelay) : !has(self.reloadDelay)",message="reloadDelay must be set when enabled and absent when disabled"
100+
type AutoRecovery struct {
101+
// +required
102+
Enabled bool `json:"enabled,omitempty"`
103+
104+
// +optional
105+
// +kubebuilder:validation:Minimum=60
106+
// +kubebuilder:validation:Maximum=3600
107+
ReloadDelay uint32 `json:"reloadDelay,omitempty"`
108+
}
109+
110+
// NXOSVPCStatus defines the observed state of NXOSVPC.
111+
type NXOSVPCStatus struct {
112+
// The conditions are a list of status objects that describe the state of the VPC.
113+
//+listType=map
114+
//+listMapKey=type
115+
//+patchStrategy=merge
116+
//+patchMergeKey=type
117+
//+optional
118+
Conditions []metav1.Condition `json:"conditions,omitempty"`
119+
}
120+
121+
// +kubebuilder:object:root=true
122+
// +kubebuilder:subresource:status
123+
// +kubebuilder:resource:path=nxosvpcs
124+
// +kubebuilder:resource:singular=nxosvpc
125+
// +kubebuilder:resource:shortName=vpc
126+
// +kubebuilder:printcolumn:name="Domain",type=string,JSONPath=`.spec.domainId`
127+
// +kubebuilder:printcolumn:name="AdminState",type=string,JSONPath=`.spec.adminState`
128+
// +kubebuilder:printcolumn:name="Device",type=string,JSONPath=`.spec.deviceRef.name`
129+
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
130+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
131+
132+
// NXOSVPC is the Schema for the nxosvpcs API
133+
type NXOSVPC struct {
134+
metav1.TypeMeta `json:",inline"`
135+
metav1.ObjectMeta `json:"metadata,omitempty"`
136+
137+
// spec defines the desired state of NXOSVPC
138+
// +required
139+
Spec NXOSVPCSpec `json:"spec,omitempty"`
140+
141+
// status defines the observed state of NXOSVPC
142+
// +optional
143+
Status NXOSVPCStatus `json:"status,omitempty,omitzero"`
144+
}
145+
146+
// +kubebuilder:object:root=true
147+
148+
// NXOSVPCList contains a list of NXOSVPC
149+
type NXOSVPCList struct {
150+
metav1.TypeMeta `json:",inline"`
151+
metav1.ListMeta `json:"metadata,omitempty"`
152+
Items []NXOSVPC `json:"items"`
153+
}
154+
155+
func init() {
156+
SchemeBuilder.Register(&NXOSVPC{}, &NXOSVPCList{})
157+
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 164 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)