openstack: Autodetect LBaaS v1 vs v2

This removes the need to manually specify the version in all but unusual
cases.

For most installs this will effectively flip the default from
v1 (deprecated) to v2 so conservative existing installs may want to
manually configure "lb-version = v1" before upgrading.
pull/6/head
Angus Lees 2016-07-28 17:07:10 +10:00
parent 045663d43d
commit e4c354c329
3 changed files with 63 additions and 43 deletions

View File

@ -83,7 +83,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"`
@ -526,13 +526,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")
}
}
}