Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 26 additions & 28 deletions pkg/openstack/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import (
"strings"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/gophercloud/pagination"
"github.com/mitchellh/mapstructure"
v1 "k8s.io/api/core/v1"
Expand All @@ -43,11 +43,13 @@ import (
"k8s.io/cloud-provider-openstack/pkg/util"
"k8s.io/cloud-provider-openstack/pkg/util/errors"
"k8s.io/cloud-provider-openstack/pkg/util/metadata"
"k8s.io/cloud-provider-openstack/pkg/util/openstack"
)

// Instances encapsulates an implementation of Instances for OpenStack.
type Instances struct {
compute *gophercloud.ServiceClient
network *gophercloud.ServiceClient
region string
regionProviderID bool
opts metadata.Opts
Expand Down Expand Up @@ -148,13 +150,20 @@ func (os *OpenStack) instances() (*Instances, bool) {
return nil, false
}

network, err := client.NewNetworkV2(os.provider, os.epOpts)
if err != nil {
klog.Errorf("unable to access network v2 API : %v", err)
return nil, false
}

regionalProviderID := false
if isRegionalProviderID := sysos.Getenv(RegionalProviderIDEnv); isRegionalProviderID == "true" {
regionalProviderID = true
}

return &Instances{
compute: compute,
network: network,
region: os.epOpts.Region,
regionProviderID: regionalProviderID,
opts: os.metadataOpts,
Expand Down Expand Up @@ -226,12 +235,12 @@ func (i *Instances) NodeAddressesByProviderID(ctx context.Context, providerID st
return []v1.NodeAddress{}, err
}

interfaces, err := getAttachedInterfacesByID(i.compute, server.ID)
ports, err := getAttachedPorts(i.network, server.ID)
if err != nil {
return []v1.NodeAddress{}, err
}

addresses, err := nodeAddresses(server, interfaces, i.networkingOpts)
addresses, err := nodeAddresses(server, ports, i.networkingOpts)
if err != nil {
return []v1.NodeAddress{}, err
}
Expand Down Expand Up @@ -332,11 +341,11 @@ func (i *Instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
return nil, err
}

interfaces, err := getAttachedInterfacesByID(i.compute, srv.ID)
ports, err := getAttachedPorts(i.network, srv.ID)
if err != nil {
return nil, err
}
addresses, err := nodeAddresses(srv, interfaces, i.networkingOpts)
addresses, err := nodeAddresses(srv, ports, i.networkingOpts)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -564,13 +573,13 @@ func getServerByName(client *gophercloud.ServiceClient, name types.NodeName) (*S
// * access IPs
// * metadata hostname
// * server object Addresses (floating type)
func nodeAddresses(srv *servers.Server, interfaces []attachinterfaces.Interface, networkingOpts NetworkingOpts) ([]v1.NodeAddress, error) {
func nodeAddresses(srv *servers.Server, ports []ports.Port, networkingOpts NetworkingOpts) ([]v1.NodeAddress, error) {
addrs := []v1.NodeAddress{}

// parse private IP addresses first in an ordered manner
for _, iface := range interfaces {
for _, fixedIP := range iface.FixedIPs {
if iface.PortState == "ACTIVE" {
for _, port := range ports {
for _, fixedIP := range port.FixedIPs {
if port.Status == "ACTIVE" {
isIPv6 := net.ParseIP(fixedIP.IPAddress).To4() == nil
if !(isIPv6 && networkingOpts.IPv6SupportDisabled) {
AddToNodeAddresses(&addrs,
Expand Down Expand Up @@ -683,31 +692,20 @@ func getAddressesByName(client *gophercloud.ServiceClient, name types.NodeName,
return nil, err
}

interfaces, err := getAttachedInterfacesByID(client, srv.ID)
ports, err := getAttachedPorts(client, srv.ID)
if err != nil {
return nil, err
}

return nodeAddresses(&srv.Server, interfaces, networkingOpts)
return nodeAddresses(&srv.Server, ports, networkingOpts)
}

// getAttachedInterfacesByID returns the node interfaces of the specified instance.
func getAttachedInterfacesByID(client *gophercloud.ServiceClient, serviceID string) ([]attachinterfaces.Interface, error) {
var interfaces []attachinterfaces.Interface

mc := metrics.NewMetricContext("server_os_interface", "list")
pager := attachinterfaces.List(client, serviceID)
err := pager.EachPage(func(page pagination.Page) (bool, error) {
s, err := attachinterfaces.ExtractInterfaces(page)
if err != nil {
return false, err
}
interfaces = append(interfaces, s...)
return true, nil
})
if mc.ObserveRequest(err) != nil {
return interfaces, err
// getAttachedPorts returns a list of ports attached to a server.
func getAttachedPorts(client *gophercloud.ServiceClient, serverID string) ([]ports.Port, error) {
listOpts := ports.ListOpts{
DeviceID: serverID,
DeviceOwner: "compute:nova",
}

return interfaces, nil
return openstack.GetPorts(client, listOpts)
}
12 changes: 10 additions & 2 deletions pkg/openstack/instancesv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
// InstancesV2 encapsulates an implementation of InstancesV2 for OpenStack.
type InstancesV2 struct {
compute *gophercloud.ServiceClient
network *gophercloud.ServiceClient
region string
regionProviderID bool
networkingOpts NetworkingOpts
Expand All @@ -56,13 +57,20 @@ func (os *OpenStack) instancesv2() (*InstancesV2, bool) {
return nil, false
}

network, err := client.NewNetworkV2(os.provider, os.epOpts)
if err != nil {
klog.Errorf("unable to access network v2 API : %v", err)
return nil, false
}

regionalProviderID := false
if isRegionalProviderID := sysos.Getenv(RegionalProviderIDEnv); isRegionalProviderID == "true" {
regionalProviderID = true
}

return &InstancesV2{
compute: compute,
network: network,
region: os.epOpts.Region,
regionProviderID: regionalProviderID,
networkingOpts: os.networkingOpts,
Expand Down Expand Up @@ -115,12 +123,12 @@ func (i *InstancesV2) InstanceMetadata(ctx context.Context, node *v1.Node) (*clo
return nil, err
}

interfaces, err := getAttachedInterfacesByID(i.compute, server.ID)
ports, err := getAttachedPorts(i.network, server.ID)
if err != nil {
return nil, err
}

addresses, err := nodeAddresses(&server.Server, interfaces, i.networkingOpts)
addresses, err := nodeAddresses(&server.Server, ports, i.networkingOpts)
if err != nil {
return nil, err
}
Expand Down
12 changes: 6 additions & 6 deletions pkg/openstack/loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ func getBoolFromServiceAnnotation(service *corev1.Service, annotationKey string,
}

// getSubnetIDForLB returns subnet-id for a specific node
func getSubnetIDForLB(compute *gophercloud.ServiceClient, node corev1.Node, preferredIPFamily corev1.IPFamily) (string, error) {
func getSubnetIDForLB(network *gophercloud.ServiceClient, node corev1.Node, preferredIPFamily corev1.IPFamily) (string, error) {
ipAddress, err := nodeAddressForLB(&node, preferredIPFamily)
if err != nil {
return "", err
Expand All @@ -718,13 +718,13 @@ func getSubnetIDForLB(compute *gophercloud.ServiceClient, node corev1.Node, pref
instanceID = instanceID[(ind + 1):]
}

interfaces, err := getAttachedInterfacesByID(compute, instanceID)
ports, err := getAttachedPorts(network, instanceID)
if err != nil {
return "", err
}

for _, intf := range interfaces {
for _, fixedIP := range intf.FixedIPs {
for _, port := range ports {
for _, fixedIP := range port.FixedIPs {
if fixedIP.IPAddress == ipAddress {
return fixedIP.SubnetID, nil
}
Expand Down Expand Up @@ -1554,7 +1554,7 @@ func (lbaas *LbaasV2) checkServiceUpdate(service *corev1.Service, nodes []*corev
} else {
svcConf.lbMemberSubnetID = getStringFromServiceAnnotation(service, ServiceAnnotationLoadBalancerSubnetID, lbaas.opts.SubnetID)
if len(svcConf.lbMemberSubnetID) == 0 && len(nodes) > 0 {
subnetID, err := getSubnetIDForLB(lbaas.compute, *nodes[0], svcConf.preferredIPFamily)
subnetID, err := getSubnetIDForLB(lbaas.network, *nodes[0], svcConf.preferredIPFamily)
if err != nil {
return fmt.Errorf("no subnet-id found for service %s: %v", serviceName, err)
}
Expand Down Expand Up @@ -1668,7 +1668,7 @@ func (lbaas *LbaasV2) checkService(service *corev1.Service, nodes []*corev1.Node
svcConf.lbMemberSubnetID = svcConf.lbSubnetID
}
if len(svcConf.lbNetworkID) == 0 && len(svcConf.lbSubnetID) == 0 {
subnetID, err := getSubnetIDForLB(lbaas.compute, *nodes[0], svcConf.preferredIPFamily)
subnetID, err := getSubnetIDForLB(lbaas.network, *nodes[0], svcConf.preferredIPFamily)
if err != nil {
return fmt.Errorf("failed to get subnet to create load balancer for service %s: %v", serviceName, err)
}
Expand Down
58 changes: 29 additions & 29 deletions pkg/openstack/openstack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import (
"time"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/spf13/pflag"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -360,10 +360,10 @@ func TestNodeAddresses(t *testing.T) {
PublicNetworkName: []string{"public"},
}

interfaces := []attachinterfaces.Interface{
ports := []ports.Port{
{
PortState: "ACTIVE",
FixedIPs: []attachinterfaces.FixedIP{
Status: "ACTIVE",
FixedIPs: []ports.IP{
{
IPAddress: "10.0.0.32",
},
Expand All @@ -374,7 +374,7 @@ func TestNodeAddresses(t *testing.T) {
},
}

addrs, err := nodeAddresses(&srv, interfaces, networkingOpts)
addrs, err := nodeAddresses(&srv, ports, networkingOpts)
if err != nil {
t.Fatalf("nodeAddresses returned error: %v", err)
}
Expand Down Expand Up @@ -439,10 +439,10 @@ func TestNodeAddressesCustomPublicNetwork(t *testing.T) {
PublicNetworkName: []string{"pub-net"},
}

interfaces := []attachinterfaces.Interface{
ports := []ports.Port{
{
PortState: "ACTIVE",
FixedIPs: []attachinterfaces.FixedIP{
Status: "ACTIVE",
FixedIPs: []ports.IP{
{
IPAddress: "10.0.0.32",
},
Expand All @@ -453,7 +453,7 @@ func TestNodeAddressesCustomPublicNetwork(t *testing.T) {
},
}

addrs, err := nodeAddresses(&srv, interfaces, networkingOpts)
addrs, err := nodeAddresses(&srv, ports, networkingOpts)
if err != nil {
t.Fatalf("nodeAddresses returned error: %v", err)
}
Expand Down Expand Up @@ -512,10 +512,10 @@ func TestNodeAddressesCustomPublicNetworkWithIntersectingFixedIP(t *testing.T) {
PublicNetworkName: []string{"pub-net"},
}

interfaces := []attachinterfaces.Interface{
ports := []ports.Port{
{
PortState: "ACTIVE",
FixedIPs: []attachinterfaces.FixedIP{
Status: "ACTIVE",
FixedIPs: []ports.IP{
{
IPAddress: "10.0.0.32",
},
Expand All @@ -530,7 +530,7 @@ func TestNodeAddressesCustomPublicNetworkWithIntersectingFixedIP(t *testing.T) {
},
}

addrs, err := nodeAddresses(&srv, interfaces, networkingOpts)
addrs, err := nodeAddresses(&srv, ports, networkingOpts)
if err != nil {
t.Fatalf("nodeAddresses returned error: %v", err)
}
Expand Down Expand Up @@ -600,10 +600,10 @@ func TestNodeAddressesMultipleCustomInternalNetworks(t *testing.T) {
InternalNetworkName: []string{"private", "also-private"},
}

interfaces := []attachinterfaces.Interface{
ports := []ports.Port{
{
PortState: "ACTIVE",
FixedIPs: []attachinterfaces.FixedIP{
Status: "ACTIVE",
FixedIPs: []ports.IP{
{
IPAddress: "10.0.0.32",
},
Expand All @@ -614,7 +614,7 @@ func TestNodeAddressesMultipleCustomInternalNetworks(t *testing.T) {
},
}

addrs, err := nodeAddresses(&srv, interfaces, networkingOpts)
addrs, err := nodeAddresses(&srv, ports, networkingOpts)
if err != nil {
t.Fatalf("nodeAddresses returned error: %v", err)
}
Expand Down Expand Up @@ -684,10 +684,10 @@ func TestNodeAddressesOneInternalNetwork(t *testing.T) {
InternalNetworkName: []string{"also-private"},
}

interfaces := []attachinterfaces.Interface{
ports := []ports.Port{
{
PortState: "ACTIVE",
FixedIPs: []attachinterfaces.FixedIP{
Status: "ACTIVE",
FixedIPs: []ports.IP{
{
IPAddress: "10.0.0.32",
},
Expand All @@ -698,7 +698,7 @@ func TestNodeAddressesOneInternalNetwork(t *testing.T) {
},
}

addrs, err := nodeAddresses(&srv, interfaces, networkingOpts)
addrs, err := nodeAddresses(&srv, ports, networkingOpts)
if err != nil {
t.Fatalf("nodeAddresses returned error: %v", err)
}
Expand Down Expand Up @@ -760,10 +760,10 @@ func TestNodeAddressesIPv6Disabled(t *testing.T) {
IPv6SupportDisabled: true,
}

interfaces := []attachinterfaces.Interface{
ports := []ports.Port{
{
PortState: "ACTIVE",
FixedIPs: []attachinterfaces.FixedIP{
Status: "ACTIVE",
FixedIPs: []ports.IP{
{
IPAddress: "10.0.0.32",
},
Expand All @@ -774,7 +774,7 @@ func TestNodeAddressesIPv6Disabled(t *testing.T) {
},
}

addrs, err := nodeAddresses(&srv, interfaces, networkingOpts)
addrs, err := nodeAddresses(&srv, ports, networkingOpts)
if err != nil {
t.Fatalf("nodeAddresses returned error: %v", err)
}
Expand Down Expand Up @@ -841,10 +841,10 @@ func TestNodeAddressesWithAddressSortOrderOptions(t *testing.T) {
AddressSortOrder: "10.0.0.0/8, 50.56.176.0/24, 2001:4800::/32",
}

interfaces := []attachinterfaces.Interface{
ports := []ports.Port{
{
PortState: "ACTIVE",
FixedIPs: []attachinterfaces.FixedIP{
Status: "ACTIVE",
FixedIPs: []ports.IP{
{
IPAddress: "10.0.0.32",
},
Expand All @@ -855,7 +855,7 @@ func TestNodeAddressesWithAddressSortOrderOptions(t *testing.T) {
},
}

addrs, err := nodeAddresses(&srv, interfaces, networkingOpts)
addrs, err := nodeAddresses(&srv, ports, networkingOpts)
if err != nil {
t.Fatalf("nodeAddresses returned error: %v", err)
}
Expand Down