Skip to content

Commit ce90495

Browse files
authored
Merge pull request kubernetes-sigs#1701 from alexandrevilain/add/networkMtu-config-in-spec
✨ Add option to customize private network MTU
2 parents f006db4 + cdf70ea commit ce90495

8 files changed

+243
-11
lines changed

api/v1alpha5/zz_generated.conversion.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1alpha6/conversion.go

+10
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ var v1alpha7OpenStackClusterRestorer = conversion.RestorerFor[*infrav1.OpenStack
123123
return &c.Spec.Router
124124
},
125125
},
126+
"networkMtu": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackCluster, int]{
127+
GetField: func(c *infrav1.OpenStackCluster) *int {
128+
return &c.Spec.NetworkMTU
129+
},
130+
},
126131
"bastion": conversion.HashedFieldRestorer[*infrav1.OpenStackCluster, *infrav1.Bastion]{
127132
GetField: func(c *infrav1.OpenStackCluster) **infrav1.Bastion {
128133
return &c.Spec.Bastion
@@ -190,6 +195,11 @@ var v1alpha7OpenStackClusterTemplateRestorer = conversion.RestorerFor[*infrav1.O
190195
return &c.Spec.Template.Spec.Router
191196
},
192197
},
198+
"networkMtu": conversion.UnconditionalFieldRestorer[*infrav1.OpenStackClusterTemplate, int]{
199+
GetField: func(c *infrav1.OpenStackClusterTemplate) *int {
200+
return &c.Spec.Template.Spec.NetworkMTU
201+
},
202+
},
193203
"bastion": conversion.HashedFieldRestorer[*infrav1.OpenStackClusterTemplate, *infrav1.Bastion]{
194204
GetField: func(c *infrav1.OpenStackClusterTemplate) **infrav1.Bastion {
195205
return &c.Spec.Template.Spec.Bastion

api/v1alpha6/zz_generated.conversion.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1alpha7/openstackcluster_types.go

+7
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ type OpenStackClusterSpec struct {
5050
// If NodeCIDR cannot be set this can be used to detect an existing subnet.
5151
Subnet SubnetFilter `json:"subnet,omitempty"`
5252

53+
// NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID.
54+
// This value will be used only if the Cluster actuator creates the network.
55+
// If leaved empty, the network will have the default MTU defined in Openstack network service.
56+
// To use this field, the Openstack installation requires the net-mtu neutron API extension.
57+
// +optional
58+
NetworkMTU int `json:"networkMtu,omitempty"`
59+
5360
// DNSNameservers is the list of nameservers for OpenStack Subnet being created.
5461
// Set this value when you need create a new network/subnet while the access
5562
// through DNS is required.

config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -4261,6 +4261,14 @@ spec:
42614261
tagsAny:
42624262
type: string
42634263
type: object
4264+
networkMtu:
4265+
description: NetworkMTU sets the maximum transmission unit (MTU) value
4266+
to address fragmentation for the private network ID. This value
4267+
will be used only if the Cluster actuator creates the network. If
4268+
leaved empty, the network will have the default MTU defined in Openstack
4269+
network service. To use this field, the Openstack installation requires
4270+
the net-mtu neutron API extension.
4271+
type: integer
42644272
nodeCidr:
42654273
description: NodeCIDR is the OpenStack Subnet to be created. Cluster
42664274
actuator will create a network, a subnet with NodeCIDR, and a router

config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,15 @@ spec:
21242124
tagsAny:
21252125
type: string
21262126
type: object
2127+
networkMtu:
2128+
description: NetworkMTU sets the maximum transmission unit
2129+
(MTU) value to address fragmentation for the private network
2130+
ID. This value will be used only if the Cluster actuator
2131+
creates the network. If leaved empty, the network will have
2132+
the default MTU defined in Openstack network service. To
2133+
use this field, the Openstack installation requires the
2134+
net-mtu neutron API extension.
2135+
type: integer
21272136
nodeCidr:
21282137
description: NodeCIDR is the OpenStack Subnet to be created.
21292138
Cluster actuator will create a network, a subnet with NodeCIDR,

pkg/cloud/services/networking/network.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type createOpts struct {
6363
AdminStateUp *bool `json:"admin_state_up,omitempty"`
6464
Name string `json:"name,omitempty"`
6565
PortSecurityEnabled *bool `json:"port_security_enabled,omitempty"`
66+
MTU *int `json:"mtu,omitempty"`
6667
}
6768

6869
func (c createOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
@@ -135,18 +136,17 @@ func (s *Service) ReconcileNetwork(openStackCluster *infrav1.OpenStackCluster, c
135136
return nil
136137
}
137138

138-
var opts createOpts
139+
opts := createOpts{
140+
AdminStateUp: gophercloud.Enabled,
141+
Name: networkName,
142+
}
143+
139144
if openStackCluster.Spec.DisablePortSecurity {
140-
opts = createOpts{
141-
AdminStateUp: gophercloud.Enabled,
142-
Name: networkName,
143-
PortSecurityEnabled: gophercloud.Disabled,
144-
}
145-
} else {
146-
opts = createOpts{
147-
AdminStateUp: gophercloud.Enabled,
148-
Name: networkName,
149-
}
145+
opts.PortSecurityEnabled = gophercloud.Disabled
146+
}
147+
148+
if openStackCluster.Spec.NetworkMTU > 0 {
149+
opts.MTU = &openStackCluster.Spec.NetworkMTU
150150
}
151151

152152
network, err := s.client.CreateNetwork(opts)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package networking
18+
19+
import (
20+
"testing"
21+
22+
"github.com/go-logr/logr"
23+
"github.com/golang/mock/gomock"
24+
"github.com/gophercloud/gophercloud"
25+
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
26+
. "github.com/onsi/gomega"
27+
"k8s.io/utils/pointer"
28+
29+
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
30+
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mock"
31+
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
32+
)
33+
34+
func Test_ReconcileNetwork(t *testing.T) {
35+
mockCtrl := gomock.NewController(t)
36+
defer mockCtrl.Finish()
37+
38+
clusterName := "test-cluster"
39+
expectedNetworkName := getNetworkName(clusterName)
40+
fakeNetworkID := "d08803fc-2fa5-4179-b9f7-8c43d0af2fe6"
41+
42+
tests := []struct {
43+
name string
44+
openStackCluster *infrav1.OpenStackCluster
45+
expect func(m *mock.MockNetworkClientMockRecorder)
46+
want *infrav1.OpenStackCluster
47+
}{
48+
{
49+
name: "ensures status set when reconciling an existing network",
50+
openStackCluster: &infrav1.OpenStackCluster{
51+
Spec: infrav1.OpenStackClusterSpec{},
52+
},
53+
expect: func(m *mock.MockNetworkClientMockRecorder) {
54+
m.
55+
ListNetwork(networks.ListOpts{Name: expectedNetworkName}).
56+
Return([]networks.Network{
57+
{
58+
ID: fakeNetworkID,
59+
Name: expectedNetworkName,
60+
},
61+
}, nil)
62+
},
63+
want: &infrav1.OpenStackCluster{
64+
Spec: infrav1.OpenStackClusterSpec{},
65+
Status: infrav1.OpenStackClusterStatus{
66+
Network: &infrav1.NetworkStatusWithSubnets{
67+
NetworkStatus: infrav1.NetworkStatus{
68+
ID: fakeNetworkID,
69+
Name: expectedNetworkName,
70+
Tags: []string{},
71+
},
72+
},
73+
},
74+
},
75+
},
76+
{
77+
name: "creation without any parameter",
78+
openStackCluster: &infrav1.OpenStackCluster{
79+
Spec: infrav1.OpenStackClusterSpec{},
80+
},
81+
expect: func(m *mock.MockNetworkClientMockRecorder) {
82+
m.
83+
ListNetwork(networks.ListOpts{Name: expectedNetworkName}).
84+
Return([]networks.Network{}, nil)
85+
86+
m.
87+
CreateNetwork(createOpts{
88+
AdminStateUp: gophercloud.Enabled,
89+
Name: expectedNetworkName,
90+
}).
91+
Return(&networks.Network{
92+
ID: fakeNetworkID,
93+
Name: expectedNetworkName,
94+
}, nil)
95+
},
96+
want: &infrav1.OpenStackCluster{
97+
Spec: infrav1.OpenStackClusterSpec{},
98+
Status: infrav1.OpenStackClusterStatus{
99+
Network: &infrav1.NetworkStatusWithSubnets{
100+
NetworkStatus: infrav1.NetworkStatus{
101+
ID: fakeNetworkID,
102+
Name: expectedNetworkName,
103+
Tags: []string{},
104+
},
105+
},
106+
},
107+
},
108+
},
109+
{
110+
name: "creation with disabled port security",
111+
openStackCluster: &infrav1.OpenStackCluster{
112+
Spec: infrav1.OpenStackClusterSpec{
113+
DisablePortSecurity: true,
114+
},
115+
},
116+
expect: func(m *mock.MockNetworkClientMockRecorder) {
117+
m.
118+
ListNetwork(networks.ListOpts{Name: expectedNetworkName}).
119+
Return([]networks.Network{}, nil)
120+
121+
m.
122+
CreateNetwork(createOpts{
123+
AdminStateUp: gophercloud.Enabled,
124+
Name: expectedNetworkName,
125+
PortSecurityEnabled: gophercloud.Disabled,
126+
}).
127+
Return(&networks.Network{
128+
ID: fakeNetworkID,
129+
Name: expectedNetworkName,
130+
}, nil)
131+
},
132+
want: &infrav1.OpenStackCluster{
133+
Spec: infrav1.OpenStackClusterSpec{},
134+
Status: infrav1.OpenStackClusterStatus{
135+
Network: &infrav1.NetworkStatusWithSubnets{
136+
NetworkStatus: infrav1.NetworkStatus{
137+
ID: fakeNetworkID,
138+
Name: expectedNetworkName,
139+
Tags: []string{},
140+
},
141+
},
142+
},
143+
},
144+
},
145+
{
146+
name: "creation with mtu set",
147+
openStackCluster: &infrav1.OpenStackCluster{
148+
Spec: infrav1.OpenStackClusterSpec{
149+
NetworkMTU: 1500,
150+
},
151+
},
152+
expect: func(m *mock.MockNetworkClientMockRecorder) {
153+
m.
154+
ListNetwork(networks.ListOpts{Name: expectedNetworkName}).
155+
Return([]networks.Network{}, nil)
156+
157+
m.
158+
CreateNetwork(createOpts{
159+
AdminStateUp: gophercloud.Enabled,
160+
Name: expectedNetworkName,
161+
MTU: pointer.Int(1500),
162+
}).
163+
Return(&networks.Network{
164+
ID: fakeNetworkID,
165+
Name: expectedNetworkName,
166+
}, nil)
167+
},
168+
want: &infrav1.OpenStackCluster{
169+
Spec: infrav1.OpenStackClusterSpec{},
170+
Status: infrav1.OpenStackClusterStatus{
171+
Network: &infrav1.NetworkStatusWithSubnets{
172+
NetworkStatus: infrav1.NetworkStatus{
173+
ID: fakeNetworkID,
174+
Name: expectedNetworkName,
175+
Tags: []string{},
176+
},
177+
},
178+
},
179+
},
180+
},
181+
}
182+
183+
for _, tt := range tests {
184+
t.Run(tt.name, func(t *testing.T) {
185+
g := NewWithT(t)
186+
mockClient := mock.NewMockNetworkClient(mockCtrl)
187+
tt.expect(mockClient.EXPECT())
188+
s := Service{
189+
client: mockClient,
190+
scope: scope.NewMockScopeFactory(mockCtrl, "", logr.Discard()),
191+
}
192+
err := s.ReconcileNetwork(tt.openStackCluster, clusterName)
193+
g.Expect(err).ShouldNot(HaveOccurred())
194+
})
195+
}
196+
}

0 commit comments

Comments
 (0)