Merge pull request #29726 from anguslees/lb-autodetect

Automatic merge from submit-queue

openstack: Autodetect LBaaS v1 vs v2

```release-note
* openstack: autodetect LBaaS v1/v2 by querying for available extensions.  For most installs, this effectively changes the default from v1 to v2.  Existing installs can add "lb-version = v1" to the provider config file to continue to use v1.
```

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.kubernetes.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.kubernetes.io/reviews/kubernetes/kubernetes/29726)
<!-- Reviewable:end -->
This commit is contained in:
Kubernetes Submit Queue 2016-08-12 09:02:42 -07:00 committed by GitHub
commit 37deb8193e
3 changed files with 63 additions and 43 deletions

View File

@ -78,7 +78,7 @@ type LoadBalancer struct {
}
type LoadBalancerOpts struct {
LBVersion string `gcfg:"lb-version"` // v1 or v2
LBVersion string `gcfg:"lb-version"` // overrides autodetection. v1 or v2
SubnetId string `gcfg:"subnet-id"` // required
FloatingNetworkId string `gcfg:"floating-network-id"`
LBMethod string `gcfg:"lb-method"`
@ -390,13 +390,35 @@ func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) {
return nil, false
}
lbversion := os.lbOpts.LBVersion
if lbversion == "" {
// No version specified, try newest supported by server
netExts, err := networkExtensions(network)
if err != nil {
glog.Warningf("Failed to list neutron extensions: %v", err)
return nil, false
}
if netExts["lbaasv2"] {
lbversion = "v2"
} else if netExts["lbaas"] {
lbversion = "v1"
} else {
glog.Warningf("Failed to find neutron LBaaS extension (v1 or v2)")
return nil, false
}
glog.V(3).Infof("Using LBaaS extension %v", lbversion)
}
glog.V(1).Info("Claiming to support LoadBalancer")
if os.lbOpts.LBVersion == "v2" {
return &LbaasV2{LoadBalancer{network, compute, os.lbOpts}}, true
} else {
} else if lbversion == "v1" {
return &LbaasV1{LoadBalancer{network, compute, os.lbOpts}}, true
} else {
glog.Warningf("Config error: unrecognised lb-version \"%v\"", lbversion)
return nil, false
}
}

View File

@ -20,6 +20,7 @@ import (
"time"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
@ -55,6 +56,24 @@ type LbaasV2 struct {
LoadBalancer
}
func networkExtensions(client *gophercloud.ServiceClient) (map[string]bool, error) {
seen := make(map[string]bool)
pager := extensions.List(client)
err := pager.EachPage(func(page pagination.Page) (bool, error) {
exts, err := extensions.ExtractExtensions(page)
if err != nil {
return false, err
}
for _, ext := range exts {
seen[ext.Alias] = true
}
return true, nil
})
return seen, err
}
func getPortIDByIP(client *gophercloud.ServiceClient, ipAddress string) (string, error) {
var portID string

View File

@ -205,50 +205,29 @@ func TestLoadBalancer(t *testing.T) {
t.Skipf("No config found in environment")
}
cfg.LoadBalancer.LBVersion = "v1"
versions := []string{"v1", "v2", ""}
os, err := newOpenStack(cfg)
if err != nil {
t.Fatalf("Failed to construct/authenticate OpenStack: %s", err)
}
for _, v := range versions {
t.Logf("Trying LBVersion = '%s'\n", v)
cfg.LoadBalancer.LBVersion = v
lb, ok := os.LoadBalancer()
if !ok {
t.Fatalf("LoadBalancer() returned false - perhaps your stack doesn't support Neutron?")
}
os, err := newOpenStack(cfg)
if err != nil {
t.Fatalf("Failed to construct/authenticate OpenStack: %s", err)
}
_, exists, err := lb.GetLoadBalancer(testClusterName, &api.Service{ObjectMeta: api.ObjectMeta{Name: "noexist"}})
if err != nil {
t.Fatalf("GetLoadBalancer(\"noexist\") returned error: %s", err)
}
if exists {
t.Fatalf("GetLoadBalancer(\"noexist\") returned exists")
}
}
lb, ok := os.LoadBalancer()
if !ok {
t.Fatalf("LoadBalancer() returned false - perhaps your stack doesn't support Neutron?")
}
func TestLoadBalancerV2(t *testing.T) {
cfg, ok := configFromEnv()
if !ok {
t.Skipf("No config found in environment")
}
cfg.LoadBalancer.LBVersion = "v2"
os, err := newOpenStack(cfg)
if err != nil {
t.Fatalf("Failed to construct/authenticate OpenStack: %s", err)
}
lbaas, ok := os.LoadBalancer()
if !ok {
t.Fatalf("LoadBalancer() returned false - perhaps your stack doesn't support Neutron?")
}
_, exists, err := lbaas.GetLoadBalancer(testClusterName, &api.Service{ObjectMeta: api.ObjectMeta{Name: "noexist"}})
if err != nil {
t.Fatalf("GetLoadBalancer(\"noexist\") returned error: %s", err)
}
if exists {
t.Fatalf("GetLoadBalancer(\"noexist\") returned exists")
_, exists, err := lb.GetLoadBalancer(testClusterName, &api.Service{ObjectMeta: api.ObjectMeta{Name: "noexist"}})
if err != nil {
t.Fatalf("GetLoadBalancer(\"noexist\") returned error: %s", err)
}
if exists {
t.Fatalf("GetLoadBalancer(\"noexist\") returned exists")
}
}
}