diff --git a/pkg/cloudprovider/providers/openstack/openstack.go b/pkg/cloudprovider/providers/openstack/openstack.go index 422cc72deb7..455717ae69d 100644 --- a/pkg/cloudprovider/providers/openstack/openstack.go +++ b/pkg/cloudprovider/providers/openstack/openstack.go @@ -74,11 +74,13 @@ func (d *MyDuration) UnmarshalText(text []byte) error { type LoadBalancer struct { network *gophercloud.ServiceClient compute *gophercloud.ServiceClient + lb *gophercloud.ServiceClient opts LoadBalancerOpts } type LoadBalancerOpts struct { LBVersion string `gcfg:"lb-version"` // overrides autodetection. Only support v2. + UseOctavia bool `gcfg:"use-octavia"` // uses Octavia V2 service catalog endpoint SubnetId string `gcfg:"subnet-id"` // overrides autodetection. FloatingNetworkId string `gcfg:"floating-network-id"` // If specified, will create floating ip for loadbalancer, or do not create floating ip. LBMethod string `gcfg:"lb-method"` // default to ROUND_ROBIN. @@ -507,6 +509,11 @@ func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) { return nil, false } + lb, err := os.NewLoadBalancerV2() + if err != nil { + return nil, false + } + // LBaaS v1 is deprecated in the OpenStack Liberty release. // Currently kubernetes OpenStack cloud provider just support LBaaS v2. lbVersion := os.lbOpts.LBVersion @@ -517,7 +524,7 @@ func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) { glog.V(1).Info("Claiming to support LoadBalancer") - return &LbaasV2{LoadBalancer{network, compute, os.lbOpts}}, true + return &LbaasV2{LoadBalancer{network, compute, lb, os.lbOpts}}, true } func isNotFound(err error) bool { diff --git a/pkg/cloudprovider/providers/openstack/openstack_client.go b/pkg/cloudprovider/providers/openstack/openstack_client.go index 7d18ce42b08..b8563e3c753 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_client.go +++ b/pkg/cloudprovider/providers/openstack/openstack_client.go @@ -62,3 +62,21 @@ func (os *OpenStack) NewBlockStorageV2() (*gophercloud.ServiceClient, error) { } return storage, nil } + +func (os *OpenStack) NewLoadBalancerV2() (*gophercloud.ServiceClient, error) { + var lb *gophercloud.ServiceClient + var err error + if os.lbOpts.UseOctavia { + lb, err = openstack.NewLoadBalancerV2(os.provider, gophercloud.EndpointOpts{ + Region: os.region, + }) + } else { + lb, err = openstack.NewNetworkV2(os.provider, gophercloud.EndpointOpts{ + Region: os.region, + }) + } + if err != nil { + return nil, fmt.Errorf("failed to find load-balancer v2 endpoint for region %s: %v", os.region, err) + } + return lb, nil +} diff --git a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go index 19c6fb17a36..98b5b44ed77 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go +++ b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go @@ -442,7 +442,7 @@ func (lbaas *LbaasV2) createLoadBalancer(service *v1.Service, name string, inter createOpts.VipAddress = loadBalancerIP } - loadbalancer, err := loadbalancers.Create(lbaas.network, createOpts).Extract() + loadbalancer, err := loadbalancers.Create(lbaas.lb, createOpts).Extract() if err != nil { return nil, fmt.Errorf("error creating loadbalancer %v: %v", createOpts, err) } @@ -451,7 +451,7 @@ func (lbaas *LbaasV2) createLoadBalancer(service *v1.Service, name string, inter func (lbaas *LbaasV2) GetLoadBalancer(clusterName string, service *v1.Service) (*v1.LoadBalancerStatus, bool, error) { loadBalancerName := cloudprovider.GetLoadBalancerName(service) - loadbalancer, err := getLoadbalancerByName(lbaas.network, loadBalancerName) + loadbalancer, err := getLoadbalancerByName(lbaas.lb, loadBalancerName) if err == ErrNotFound { return nil, false, nil } @@ -639,7 +639,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv } name := cloudprovider.GetLoadBalancerName(apiService) - loadbalancer, err := getLoadbalancerByName(lbaas.network, name) + loadbalancer, err := getLoadbalancerByName(lbaas.lb, name) if err != nil { if err != ErrNotFound { return nil, fmt.Errorf("error getting loadbalancer %s: %v", name, err) @@ -654,14 +654,14 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv glog.V(2).Infof("LoadBalancer %s already exists", name) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) lbmethod := v2pools.LBMethod(lbaas.opts.LBMethod) if lbmethod == "" { lbmethod = v2pools.LBMethodRoundRobin } - oldListeners, err := getListenersByLoadBalancerID(lbaas.network, loadbalancer.ID) + oldListeners, err := getListenersByLoadBalancerID(lbaas.lb, loadbalancer.ID) if err != nil { return nil, fmt.Errorf("error getting LB %s listeners: %v", name, err) } @@ -669,7 +669,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv listener := getListenerForPort(oldListeners, port) if listener == nil { glog.V(4).Infof("Creating listener for port %d", int(port.Port)) - listener, err = listeners.Create(lbaas.network, listeners.CreateOpts{ + listener, err = listeners.Create(lbaas.lb, listeners.CreateOpts{ Name: fmt.Sprintf("listener_%s_%d", name, portIndex), Protocol: listeners.Protocol(port.Protocol), ProtocolPort: int(port.Port), @@ -679,7 +679,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv // Unknown error, retry later return nil, fmt.Errorf("error creating LB listener: %v", err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } glog.V(4).Infof("Listener for %s port %d: %s", string(port.Protocol), int(port.Port), listener.ID) @@ -687,14 +687,14 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv // After all ports have been processed, remaining listeners are removed as obsolete. // Pop valid listeners. oldListeners = popListener(oldListeners, listener.ID) - pool, err := getPoolByListenerID(lbaas.network, loadbalancer.ID, listener.ID) + pool, err := getPoolByListenerID(lbaas.lb, loadbalancer.ID, listener.ID) if err != nil && err != ErrNotFound { // Unknown error, retry later return nil, fmt.Errorf("error getting pool for listener %s: %v", listener.ID, err) } if pool == nil { glog.V(4).Infof("Creating pool for listener %s", listener.ID) - pool, err = v2pools.Create(lbaas.network, v2pools.CreateOpts{ + pool, err = v2pools.Create(lbaas.lb, v2pools.CreateOpts{ Name: fmt.Sprintf("pool_%s_%d", name, portIndex), Protocol: v2pools.Protocol(port.Protocol), LBMethod: lbmethod, @@ -705,11 +705,11 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv // Unknown error, retry later return nil, fmt.Errorf("error creating pool for listener %s: %v", listener.ID, err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } glog.V(4).Infof("Pool for listener %s: %s", listener.ID, pool.ID) - members, err := getMembersByPoolID(lbaas.network, pool.ID) + members, err := getMembersByPoolID(lbaas.lb, pool.ID) if err != nil && !isNotFound(err) { return nil, fmt.Errorf("error getting pool members %s: %v", pool.ID, err) } @@ -727,7 +727,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv if !memberExists(members, addr, int(port.NodePort)) { glog.V(4).Infof("Creating member for pool %s", pool.ID) - _, err := v2pools.CreateMember(lbaas.network, pool.ID, v2pools.CreateMemberOpts{ + _, err := v2pools.CreateMember(lbaas.lb, pool.ID, v2pools.CreateMemberOpts{ ProtocolPort: int(port.NodePort), Address: addr, SubnetID: lbaas.opts.SubnetId, @@ -736,7 +736,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv return nil, fmt.Errorf("error creating LB pool member for node: %s, %v", node.Name, err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } else { // After all members have been processed, remaining members are deleted as obsolete. members = popMember(members, addr, int(port.NodePort)) @@ -748,17 +748,17 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv // Delete obsolete members for this pool for _, member := range members { glog.V(4).Infof("Deleting obsolete member %s for pool %s address %s", member.ID, pool.ID, member.Address) - err := v2pools.DeleteMember(lbaas.network, pool.ID, member.ID).ExtractErr() + err := v2pools.DeleteMember(lbaas.lb, pool.ID, member.ID).ExtractErr() if err != nil && !isNotFound(err) { return nil, fmt.Errorf("error deleting obsolete member %s for pool %s address %s: %v", member.ID, pool.ID, member.Address, err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } monitorID := pool.MonitorID if monitorID == "" && lbaas.opts.CreateMonitor { glog.V(4).Infof("Creating monitor for pool %s", pool.ID) - monitor, err := v2monitors.Create(lbaas.network, v2monitors.CreateOpts{ + monitor, err := v2monitors.Create(lbaas.lb, v2monitors.CreateOpts{ PoolID: pool.ID, Type: string(port.Protocol), Delay: int(lbaas.opts.MonitorDelay.Duration.Seconds()), @@ -768,7 +768,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv if err != nil { return nil, fmt.Errorf("error creating LB pool healthmonitor: %v", err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) monitorID = monitor.ID } else if lbaas.opts.CreateMonitor == false { glog.V(4).Infof("Do not create monitor for pool %s when create-monitor is false", pool.ID) @@ -783,7 +783,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv for _, listener := range oldListeners { glog.V(4).Infof("Deleting obsolete listener %s:", listener.ID) // get pool for listener - pool, err := getPoolByListenerID(lbaas.network, loadbalancer.ID, listener.ID) + pool, err := getPoolByListenerID(lbaas.lb, loadbalancer.ID, listener.ID) if err != nil && err != ErrNotFound { return nil, fmt.Errorf("error getting pool for obsolete listener %s: %v", listener.ID, err) } @@ -792,46 +792,46 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv monitorID := pool.MonitorID if monitorID != "" { glog.V(4).Infof("Deleting obsolete monitor %s for pool %s", monitorID, pool.ID) - err = v2monitors.Delete(lbaas.network, monitorID).ExtractErr() + err = v2monitors.Delete(lbaas.lb, monitorID).ExtractErr() if err != nil && !isNotFound(err) { return nil, fmt.Errorf("error deleting obsolete monitor %s for pool %s: %v", monitorID, pool.ID, err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } // get and delete pool members - members, err := getMembersByPoolID(lbaas.network, pool.ID) + members, err := getMembersByPoolID(lbaas.lb, pool.ID) if err != nil && !isNotFound(err) { return nil, fmt.Errorf("error getting members for pool %s: %v", pool.ID, err) } if members != nil { for _, member := range members { glog.V(4).Infof("Deleting obsolete member %s for pool %s address %s", member.ID, pool.ID, member.Address) - err := v2pools.DeleteMember(lbaas.network, pool.ID, member.ID).ExtractErr() + err := v2pools.DeleteMember(lbaas.lb, pool.ID, member.ID).ExtractErr() if err != nil && !isNotFound(err) { return nil, fmt.Errorf("error deleting obsolete member %s for pool %s address %s: %v", member.ID, pool.ID, member.Address, err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } } glog.V(4).Infof("Deleting obsolete pool %s for listener %s", pool.ID, listener.ID) // delete pool - err = v2pools.Delete(lbaas.network, pool.ID).ExtractErr() + err = v2pools.Delete(lbaas.lb, pool.ID).ExtractErr() if err != nil && !isNotFound(err) { return nil, fmt.Errorf("error deleting obsolete pool %s for listener %s: %v", pool.ID, listener.ID, err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } // delete listener - err = listeners.Delete(lbaas.network, listener.ID).ExtractErr() + err = listeners.Delete(lbaas.lb, listener.ID).ExtractErr() if err != nil && !isNotFound(err) { return nil, fmt.Errorf("error deleteting obsolete listener: %v", err) } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) glog.V(2).Infof("Deleted obsolete listener: %s", listener.ID) } portID := loadbalancer.VipPortID - floatIP, err := getFloatingIPByPortID(lbaas.network, portID) + floatIP, err := getFloatingIPByPortID(lbaas.lb, portID) if err != nil && err != ErrNotFound { return nil, fmt.Errorf("error getting floating ip for port %s: %v", portID, err) } @@ -1068,7 +1068,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service return fmt.Errorf("no ports provided to openstack load balancer") } - loadbalancer, err := getLoadbalancerByName(lbaas.network, loadBalancerName) + loadbalancer, err := getLoadbalancerByName(lbaas.lb, loadBalancerName) if err != nil { return err } @@ -1083,7 +1083,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service } var listenerIDs []string lbListeners := make(map[portKey]listeners.Listener) - allListeners, err := getListenersByLoadBalancerID(lbaas.network, loadbalancer.ID) + allListeners, err := getListenersByLoadBalancerID(lbaas.lb, loadbalancer.ID) if err != nil { return fmt.Errorf("error getting listeners for LB %s: %v", loadBalancerName, err) } @@ -1096,7 +1096,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service // Get all pools for this loadbalancer, by listener ID. lbPools := make(map[string]v2pools.Pool) for _, listenerID := range listenerIDs { - pool, err := getPoolByListenerID(lbaas.network, loadbalancer.ID, listenerID) + pool, err := getPoolByListenerID(lbaas.lb, loadbalancer.ID, listenerID) if err != nil { return fmt.Errorf("error getting pool for listener %s: %v", listenerID, err) } @@ -1131,7 +1131,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service } // Find existing pool members (by address) for this port - getMembers, err := getMembersByPoolID(lbaas.network, pool.ID) + getMembers, err := getMembersByPoolID(lbaas.lb, pool.ID) if err != nil { return fmt.Errorf("error getting pool members %s: %v", pool.ID, err) } @@ -1146,7 +1146,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service // Already exists, do not create member continue } - _, err := v2pools.CreateMember(lbaas.network, pool.ID, v2pools.CreateMemberOpts{ + _, err := v2pools.CreateMember(lbaas.lb, pool.ID, v2pools.CreateMemberOpts{ Address: addr, ProtocolPort: int(port.NodePort), SubnetID: lbaas.opts.SubnetId, @@ -1154,7 +1154,7 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service if err != nil { return err } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } // Remove any old members for this port @@ -1163,11 +1163,11 @@ func (lbaas *LbaasV2) UpdateLoadBalancer(clusterName string, service *v1.Service // Still present, do not delete member continue } - err = v2pools.DeleteMember(lbaas.network, pool.ID, member.ID).ExtractErr() + err = v2pools.DeleteMember(lbaas.lb, pool.ID, member.ID).ExtractErr() if err != nil && !isNotFound(err) { return err } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } } @@ -1265,7 +1265,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1. loadBalancerName := cloudprovider.GetLoadBalancerName(service) glog.V(4).Infof("EnsureLoadBalancerDeleted(%v, %v)", clusterName, loadBalancerName) - loadbalancer, err := getLoadbalancerByName(lbaas.network, loadBalancerName) + loadbalancer, err := getLoadbalancerByName(lbaas.lb, loadBalancerName) if err != nil && err != ErrNotFound { return err } @@ -1288,7 +1288,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1. } // get all listeners associated with this loadbalancer - listenerList, err := getListenersByLoadBalancerID(lbaas.network, loadbalancer.ID) + listenerList, err := getListenersByLoadBalancerID(lbaas.lb, loadbalancer.ID) if err != nil { return fmt.Errorf("error getting LB %s listeners: %v", loadbalancer.ID, err) } @@ -1297,7 +1297,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1. var poolIDs []string var monitorIDs []string for _, listener := range listenerList { - pool, err := getPoolByListenerID(lbaas.network, loadbalancer.ID, listener.ID) + pool, err := getPoolByListenerID(lbaas.lb, loadbalancer.ID, listener.ID) if err != nil && err != ErrNotFound { return fmt.Errorf("error getting pool for listener %s: %v", listener.ID, err) } @@ -1313,7 +1313,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1. // get all members associated with each poolIDs var memberIDs []string for _, pool := range poolIDs { - membersList, err := getMembersByPoolID(lbaas.network, pool) + membersList, err := getMembersByPoolID(lbaas.lb, pool) if err != nil && !isNotFound(err) { return fmt.Errorf("error getting pool members %s: %v", pool, err) } @@ -1324,47 +1324,47 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1. // delete all monitors for _, monitorID := range monitorIDs { - err := v2monitors.Delete(lbaas.network, monitorID).ExtractErr() + err := v2monitors.Delete(lbaas.lb, monitorID).ExtractErr() if err != nil && !isNotFound(err) { return err } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } // delete all members and pools for _, poolID := range poolIDs { // delete all members for this pool for _, memberID := range memberIDs { - err := v2pools.DeleteMember(lbaas.network, poolID, memberID).ExtractErr() + err := v2pools.DeleteMember(lbaas.lb, poolID, memberID).ExtractErr() if err != nil && !isNotFound(err) { return err } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } // delete pool - err := v2pools.Delete(lbaas.network, poolID).ExtractErr() + err := v2pools.Delete(lbaas.lb, poolID).ExtractErr() if err != nil && !isNotFound(err) { return err } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } // delete all listeners for _, listener := range listenerList { - err := listeners.Delete(lbaas.network, listener.ID).ExtractErr() + err := listeners.Delete(lbaas.lb, listener.ID).ExtractErr() if err != nil && !isNotFound(err) { return err } - waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) + waitLoadbalancerActiveProvisioningStatus(lbaas.lb, loadbalancer.ID) } // delete loadbalancer - err = loadbalancers.Delete(lbaas.network, loadbalancer.ID).ExtractErr() + err = loadbalancers.Delete(lbaas.lb, loadbalancer.ID).ExtractErr() if err != nil && !isNotFound(err) { return err } - waitLoadbalancerDeleted(lbaas.network, loadbalancer.ID) + waitLoadbalancerDeleted(lbaas.lb, loadbalancer.ID) // Delete the Security Group if lbaas.opts.ManageSecurityGroups {