Skip to content

Commit d014b87

Browse files
chriglMaysaMacedo
andauthored
[occm] cherrypick: LB - Fix floating ip subnet detection and ipv6 handling (kubernetes#2022)
* [occm] Skip External network with IPv6 for FIPs creation (kubernetes#1992) OpenStack does not support creation of floating IPs with IPv6. However, it's still possible to exist external networks with IPv6 Subnets, which could break the creation of Floating IPs for a load-balancer if CCM uses it. This commit avoids this issue by making sure only external networks with IPv4 Subnets are used when creating a Floating IP. * Improve retrival of external Network (kubernetes#2014) When attempting to fetch an external Network with IPv4 Subnets to create a Floating IP, it's possible that no Subnets from that Network are shared with the tenant, consequently it would not be possible to filter them by IPVersion and no Network would be used. This commit improve the detection of external Network by only allowing usage of Networks that is possible to detect at least one IPV4 Subnet or that is not possible to detect any info about the Subnets. Co-authored-by: Maysa De Macedo Souza <maysa.souza@ccc.ufcg.edu.br> Co-authored-by: Maysa De Macedo Souza <maysa.macedo95@gmail.com>
1 parent 58b9f9f commit d014b87

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

pkg/util/openstack/network.go

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
2424
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
2525
neutronports "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
26+
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
2627
"github.com/gophercloud/gophercloud/pagination"
2728

2829
"k8s.io/cloud-provider-openstack/pkg/metrics"
@@ -85,48 +86,57 @@ func GetFloatingIPByPortID(client *gophercloud.ServiceClient, portID string) (*f
8586

8687
// GetFloatingNetworkID returns a floating network ID.
8788
func GetFloatingNetworkID(client *gophercloud.ServiceClient) (string, error) {
88-
var floatingNetworkIds []string
89-
9089
type NetworkWithExternalExt struct {
9190
networks.Network
9291
external.NetworkExternalExt
9392
}
93+
var allNetworks []NetworkWithExternalExt
9494

9595
mc := metrics.NewMetricContext("network", "list")
96-
err := networks.List(client, networks.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
97-
var externalNetwork []NetworkWithExternalExt
98-
err := networks.ExtractNetworksInto(page, &externalNetwork)
99-
if err != nil {
100-
return false, err
101-
}
102-
103-
for _, externalNet := range externalNetwork {
104-
if externalNet.External {
105-
floatingNetworkIds = append(floatingNetworkIds, externalNet.ID)
106-
}
107-
}
108-
109-
if len(floatingNetworkIds) > 1 {
110-
return false, cpoerrors.ErrMultipleResults
111-
}
112-
return true, nil
113-
})
96+
page, err := networks.List(client, networks.ListOpts{}).AllPages()
11497
if err != nil {
115-
if cpoerrors.IsNotFound(err) {
116-
return "", mc.ObserveRequest(cpoerrors.ErrNotFound)
117-
}
98+
return "", mc.ObserveRequest(err)
99+
}
118100

119-
if err == cpoerrors.ErrMultipleResults {
120-
return floatingNetworkIds[0], mc.ObserveRequest(nil)
121-
}
101+
err = networks.ExtractNetworksInto(page, &allNetworks)
102+
if err != nil {
122103
return "", mc.ObserveRequest(err)
123104
}
124105

125-
if len(floatingNetworkIds) == 0 {
126-
return "", mc.ObserveRequest(cpoerrors.ErrNotFound)
106+
for _, network := range allNetworks {
107+
if network.External && len(network.Subnets) > 0 {
108+
mc := metrics.NewMetricContext("subnet", "list")
109+
page, err := subnets.List(client, subnets.ListOpts{NetworkID: network.ID}).AllPages()
110+
if err != nil {
111+
return "", mc.ObserveRequest(err)
112+
}
113+
subnetList, err := subnets.ExtractSubnets(page)
114+
if err != nil {
115+
return "", mc.ObserveRequest(err)
116+
}
117+
for _, networkSubnet := range network.Subnets {
118+
subnet := getSubnet(networkSubnet, subnetList)
119+
if subnet != nil {
120+
if subnet.IPVersion == 4 {
121+
return network.ID, nil
122+
}
123+
} else {
124+
return network.ID, nil
125+
}
126+
}
127+
}
127128
}
129+
return "", mc.ObserveRequest(cpoerrors.ErrNotFound)
130+
}
128131

129-
return floatingNetworkIds[0], mc.ObserveRequest(nil)
132+
// getSubnet checks if a Subnet is present in the list of Subnets the tenant has access to and returns it
133+
func getSubnet(networkSubnet string, subnetList []subnets.Subnet) *subnets.Subnet {
134+
for _, subnet := range subnetList {
135+
if subnet.ID == networkSubnet {
136+
return &subnet
137+
}
138+
}
139+
return nil
130140
}
131141

132142
// GetPorts gets all the filtered ports.

0 commit comments

Comments
 (0)