Skip to content

Commit d3d3473

Browse files
committed
Transform Profile into an interface
We previously allowed to use the Neutron `binding:profile` via `ports.bindingProfile` but this API is not declared as stable from the [Neutron API description](https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port). Instead, we now explicitly support two use cases: * OVS Hardware Offload * Trusted Virtual Functions (VF) Here is an example on how to use `ports.bindingProfile` for enabling OVS Hardware Offload: ```yaml profile: OVSHWOffload: true ``` Here is an example on how to use `ports.bindingProfile` for enabling "trusted-mode" to the VF: ```yaml profile: TrustedVF: true ``` Convertion is supported from both v1alpha5 & v1alpha6 to v1alpha7.
1 parent b21411b commit d3d3473

14 files changed

+253
-48
lines changed

api/v1alpha5/conversion.go

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package v1alpha5
1818

1919
import (
20+
"strings"
21+
2022
conversion "k8s.io/apimachinery/pkg/conversion"
2123
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
2224
ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion"
@@ -26,6 +28,8 @@ import (
2628

2729
var _ ctrlconversion.Convertible = &OpenStackCluster{}
2830

31+
const trueString = "true"
32+
2933
func (r *OpenStackCluster) ConvertTo(dstRaw ctrlconversion.Hub) error {
3034
dst := dstRaw.(*infrav1.OpenStackCluster)
3135

@@ -193,7 +197,19 @@ func Convert_v1alpha7_LoadBalancer_To_v1alpha5_LoadBalancer(in *infrav1.LoadBala
193197

194198
func Convert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *PortOpts, s conversion.Scope) error {
195199
// value specs and propagate uplink status have been added in v1alpha7 but have no equivalent in v1alpha5
196-
return autoConvert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in, out, s)
200+
err := autoConvert_v1alpha7_PortOpts_To_v1alpha5_PortOpts(in, out, s)
201+
if err != nil {
202+
return err
203+
}
204+
205+
out.Profile = make(map[string]string)
206+
if in.Profile.OVSHWOffload {
207+
(out.Profile)["capabilities"] = "[\"switchdev\"]"
208+
}
209+
if in.Profile.TrustedVF {
210+
(out.Profile)["trusted"] = trueString
211+
}
212+
return nil
197213
}
198214

199215
func Convert_Slice_v1alpha5_Network_To_Slice_v1alpha7_Network(in *[]Network, out *[]infrav1.Network, s conversion.Scope) error {
@@ -227,7 +243,19 @@ func Convert_v1alpha7_APIServerLoadBalancer_To_v1alpha5_APIServerLoadBalancer(in
227243

228244
func Convert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *infrav1.PortOpts, s conversion.Scope) error {
229245
// SecurityGroups have been removed in v1alpha7.
230-
return autoConvert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in, out, s)
246+
err := autoConvert_v1alpha5_PortOpts_To_v1alpha7_PortOpts(in, out, s)
247+
if err != nil {
248+
return err
249+
}
250+
251+
// Profile is now a struct in v1alpha7.
252+
if strings.Contains(in.Profile["capabilities"], "switchdev") {
253+
out.Profile.OVSHWOffload = true
254+
}
255+
if in.Profile["trusted"] == trueString {
256+
out.Profile.TrustedVF = true
257+
}
258+
return nil
231259
}
232260

233261
func Convert_v1alpha5_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error {
@@ -333,3 +361,27 @@ func Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetParam(in *infrav1.SubnetFil
333361

334362
return nil
335363
}
364+
365+
func Convert_Map_string_To_Interface_To_v1alpha7_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ conversion.Scope) error {
366+
for k, v := range in {
367+
if k == "capabilities" {
368+
if strings.Contains(v, "switchdev") {
369+
out.OVSHWOffload = true
370+
}
371+
}
372+
if k == "trusted" && v == trueString {
373+
out.TrustedVF = true
374+
}
375+
}
376+
return nil
377+
}
378+
379+
func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
380+
if in.OVSHWOffload {
381+
(out)["capabilities"] = "[\"switchdev\"]"
382+
}
383+
if in.TrustedVF {
384+
(out)["trusted"] = trueString
385+
}
386+
return nil
387+
}

api/v1alpha5/zz_generated.conversion.go

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

api/v1alpha6/conversion.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package v1alpha6
1818

1919
import (
20+
"strings"
21+
2022
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2123
conversion "k8s.io/apimachinery/pkg/conversion"
2224
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
@@ -25,6 +27,8 @@ import (
2527
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
2628
)
2729

30+
const trueString = "true"
31+
2832
/*
2933
* HOW THIS WORKS
3034
*
@@ -401,6 +405,14 @@ func Convert_v1alpha6_PortOpts_To_v1alpha7_PortOpts(in *PortOpts, out *infrav1.P
401405
for i := range in.SecurityGroups {
402406
out.SecurityGroupFilters = append(out.SecurityGroupFilters, infrav1.SecurityGroupFilter{ID: in.SecurityGroups[i]})
403407
}
408+
409+
// Profile is now a struct in v1alpha7.
410+
if strings.Contains(in.Profile["capabilities"], "switchdev") {
411+
out.Profile.OVSHWOffload = true
412+
}
413+
if in.Profile["trusted"] == trueString {
414+
out.Profile.TrustedVF = true
415+
}
404416
return nil
405417
}
406418

@@ -426,7 +438,19 @@ func Convert_Slice_v1alpha7_Network_To_Slice_v1alpha6_Network(in *[]infrav1.Netw
426438

427439
func Convert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *PortOpts, s conversion.Scope) error {
428440
// value specs and propagate uplink status have been added in v1alpha7 but have no equivalent in v1alpha5
429-
return autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in, out, s)
441+
err := autoConvert_v1alpha7_PortOpts_To_v1alpha6_PortOpts(in, out, s)
442+
if err != nil {
443+
return err
444+
}
445+
446+
out.Profile = make(map[string]string)
447+
if in.Profile.OVSHWOffload {
448+
(out.Profile)["capabilities"] = "[\"switchdev\"]"
449+
}
450+
if in.Profile.TrustedVF {
451+
(out.Profile)["trusted"] = trueString
452+
}
453+
return nil
430454
}
431455

432456
func Convert_v1alpha6_Instance_To_v1alpha7_BastionStatus(in *Instance, out *infrav1.BastionStatus, _ conversion.Scope) error {
@@ -532,3 +556,27 @@ func Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetParam(in *infrav1.SubnetFil
532556

533557
return nil
534558
}
559+
560+
func Convert_Map_string_To_Interface_To_v1alpha7_BindingProfile(in map[string]string, out *infrav1.BindingProfile, _ conversion.Scope) error {
561+
for k, v := range in {
562+
if k == "capabilities" {
563+
if strings.Contains(v, "switchdev") {
564+
out.OVSHWOffload = true
565+
}
566+
}
567+
if k == "trusted" && v == trueString {
568+
out.TrustedVF = true
569+
}
570+
}
571+
return nil
572+
}
573+
574+
func Convert_v1alpha7_BindingProfile_To_Map_string_To_Interface(in *infrav1.BindingProfile, out map[string]string, _ conversion.Scope) error {
575+
if in.OVSHWOffload {
576+
(out)["capabilities"] = "[\"switchdev\"]"
577+
}
578+
if in.TrustedVF {
579+
(out)["trusted"] = trueString
580+
}
581+
return nil
582+
}

api/v1alpha6/conversion_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,14 @@ func TestPortOptsConvertTo(t *testing.T) {
418418
{ID: uuids[0]},
419419
{ID: uuids[1]},
420420
}
421+
legacyPortProfile := map[string]string{
422+
"capabilities": "[\"switchdev\"]",
423+
"trusted": "true",
424+
}
425+
convertedPortProfile := infrav1.BindingProfile{
426+
OVSHWOffload: true,
427+
TrustedVF: true,
428+
}
421429

422430
tests := []struct {
423431
name string
@@ -430,19 +438,23 @@ func TestPortOptsConvertTo(t *testing.T) {
430438
// The list of security group UUIDs should be translated to proper SecurityGroupParams
431439
name: "SecurityGroups to SecurityGroupFilters",
432440
spokePortOpts: []PortOpts{{
441+
Profile: legacyPortProfile,
433442
SecurityGroups: uuids,
434443
}},
435444
hubPortOpts: []infrav1.PortOpts{{
445+
Profile: convertedPortProfile,
436446
SecurityGroupFilters: securityGroupsUuids,
437447
}},
438448
},
439449
{
440450
name: "Merge SecurityGroups and SecurityGroupFilters",
441451
spokePortOpts: []PortOpts{{
452+
Profile: legacyPortProfile,
442453
SecurityGroups: uuids,
443454
SecurityGroupFilters: securityGroupFilter,
444455
}},
445456
hubPortOpts: []infrav1.PortOpts{{
457+
Profile: convertedPortProfile,
446458
SecurityGroupFilters: securityGroupFilterMerged,
447459
}},
448460
},

api/v1alpha6/zz_generated.conversion.go

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

api/v1alpha7/types.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,11 @@ type PortOpts struct {
102102
// The virtual network interface card (vNIC) type that is bound to the neutron port.
103103
VNICType string `json:"vnicType,omitempty"`
104104

105-
// A dictionary that enables the application running on the specified
106-
// host to pass and receive virtual network interface (VIF) port-specific
107-
// information to the plug-in.
108-
Profile map[string]string `json:"profile,omitempty"`
105+
// Profile is a set of key-value pairs that are used for binding details.
106+
// We intentionally don't expose this as a map[string]string because we only want to enable
107+
// the users to set the values of the keys that are known to work in OpenStack Networking API.
108+
// See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port
109+
Profile BindingProfile `json:"profile,omitempty"`
109110

110111
// DisablePortSecurity enables or disables the port security when set.
111112
// When not set, it takes the value of the corresponding field at the network level.
@@ -128,6 +129,14 @@ type PortOpts struct {
128129
ValueSpecs []ValueSpec `json:"valueSpecs,omitempty"`
129130
}
130131

132+
type BindingProfile struct {
133+
// OVSHWOffload enables or disables the OVS hardware offload feature.
134+
OVSHWOffload bool `json:"ovsHWOffload,omitempty"`
135+
136+
// TrustedVF enables or disables the “trusted mode” for the VF.
137+
TrustedVF bool `json:"trustedVF,omitempty"`
138+
}
139+
131140
type FixedIP struct {
132141
// Subnet is an openstack subnet query that will return the id of a subnet to create
133142
// the fixed IP of a port in. This query must not return more than one subnet.

api/v1alpha7/zz_generated.deepcopy.go

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

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3928,12 +3928,21 @@ spec:
39283928
type: string
39293929
type: object
39303930
profile:
3931-
additionalProperties:
3932-
type: string
3933-
description: A dictionary that enables the application
3934-
running on the specified host to pass and receive
3935-
virtual network interface (VIF) port-specific information
3936-
to the plug-in.
3931+
description: Profile is a set of key-value pairs that
3932+
are used for binding details. We intentionally don't
3933+
expose this as a map[string]string because we only
3934+
want to enable the users to set the values of the
3935+
keys that are known to work in OpenStack Networking
3936+
API. See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port
3937+
properties:
3938+
ovsHWOffload:
3939+
description: OVSHWOffload enables or disables the
3940+
OVS hardware offload feature.
3941+
type: boolean
3942+
trustedVF:
3943+
description: TrustedVF enables or disables the “trusted
3944+
mode” for the VF.
3945+
type: boolean
39373946
type: object
39383947
projectId:
39393948
type: string

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,12 +1768,21 @@ spec:
17681768
type: string
17691769
type: object
17701770
profile:
1771-
additionalProperties:
1772-
type: string
1773-
description: A dictionary that enables the application
1774-
running on the specified host to pass and
1775-
receive virtual network interface (VIF) port-specific
1776-
information to the plug-in.
1771+
description: Profile is a set of key-value pairs
1772+
that are used for binding details. We intentionally
1773+
don't expose this as a map[string]string because
1774+
we only want to enable the users to set the
1775+
values of the keys that are known to work
1776+
in OpenStack Networking API. See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port
1777+
properties:
1778+
ovsHWOffload:
1779+
description: OVSHWOffload enables or disables
1780+
the OVS hardware offload feature.
1781+
type: boolean
1782+
trustedVF:
1783+
description: TrustedVF enables or disables
1784+
the “trusted mode” for the VF.
1785+
type: boolean
17771786
type: object
17781787
projectId:
17791788
type: string

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,11 +1305,20 @@ spec:
13051305
type: string
13061306
type: object
13071307
profile:
1308-
additionalProperties:
1309-
type: string
1310-
description: A dictionary that enables the application running
1311-
on the specified host to pass and receive virtual network
1312-
interface (VIF) port-specific information to the plug-in.
1308+
description: Profile is a set of key-value pairs that are used
1309+
for binding details. We intentionally don't expose this as
1310+
a map[string]string because we only want to enable the users
1311+
to set the values of the keys that are known to work in OpenStack
1312+
Networking API. See https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port
1313+
properties:
1314+
ovsHWOffload:
1315+
description: OVSHWOffload enables or disables the OVS hardware
1316+
offload feature.
1317+
type: boolean
1318+
trustedVF:
1319+
description: TrustedVF enables or disables the “trusted
1320+
mode” for the VF.
1321+
type: boolean
13131322
type: object
13141323
projectId:
13151324
type: string

0 commit comments

Comments
 (0)