mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-08 07:14:19 +08:00
@@ -18,8 +18,9 @@ const (
|
||||
EIP_MODE_INSTANCE_PUBLICIP = "public_ip"
|
||||
EIP_MODE_STANDALONE_EIP = "elastic_ip"
|
||||
|
||||
EIP_ASSOCIATE_TYPE_SERVER = "server"
|
||||
EIP_ASSOCIATE_TYPE_NAT_GATEWAY = "natgateway"
|
||||
EIP_ASSOCIATE_TYPE_SERVER = "server"
|
||||
EIP_ASSOCIATE_TYPE_NAT_GATEWAY = "natgateway"
|
||||
EIP_ASSOCIATE_TYPE_LOADBALANCER = "loadbalancer"
|
||||
|
||||
EIP_STATUS_READY = "ready"
|
||||
EIP_STATUS_UNKNOWN = "unknown"
|
||||
|
||||
@@ -460,6 +460,8 @@ type ICloudLoadbalancer interface {
|
||||
GetChargeType() string
|
||||
GetEgressMbps() int
|
||||
|
||||
GetIEIP() (ICloudEIP, error)
|
||||
|
||||
Delete() error
|
||||
|
||||
Start() error
|
||||
|
||||
@@ -725,6 +725,8 @@ func syncRegionLoadbalancers(ctx context.Context, userCred mcclient.TokenCredent
|
||||
lockman.LockObject(ctx, &localLbs[i])
|
||||
defer lockman.ReleaseObject(ctx, &localLbs[i])
|
||||
|
||||
syncLoadbalancerEip(ctx, userCred, provider, &localLbs[i], remoteLbs[i])
|
||||
|
||||
syncLoadbalancerBackendgroups(ctx, userCred, syncResults, provider, &localLbs[i], remoteLbs[i], syncRange)
|
||||
syncLoadbalancerListeners(ctx, userCred, syncResults, provider, &localLbs[i], remoteLbs[i], syncRange)
|
||||
|
||||
@@ -732,6 +734,21 @@ func syncRegionLoadbalancers(ctx context.Context, userCred mcclient.TokenCredent
|
||||
}
|
||||
}
|
||||
|
||||
func syncLoadbalancerEip(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, localLb *SLoadbalancer, remoteLb cloudprovider.ICloudLoadbalancer) {
|
||||
eip, err := remoteLb.GetIEIP()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIEIP for Loadbalancer %s failed %s", remoteLb.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
return
|
||||
}
|
||||
result := localLb.SyncLoadbalancerEip(ctx, userCred, provider, eip)
|
||||
msg := result.Result()
|
||||
log.Infof("SyncEip for Loadbalancer %s result: %s", localLb.Name, msg)
|
||||
if result.IsError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func syncLoadbalancerListeners(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localLoadbalancer *SLoadbalancer, remoteLoadbalancer cloudprovider.ICloudLoadbalancer, syncRange *SSyncRange) {
|
||||
remoteListeners, err := remoteLoadbalancer.GetILoadBalancerListeners()
|
||||
if err != nil {
|
||||
|
||||
@@ -503,6 +503,21 @@ func (self *SElasticip) GetAssociateVM() *SGuest {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetAssociateLoadbalancer() *SLoadbalancer {
|
||||
if self.AssociateType == api.EIP_ASSOCIATE_TYPE_LOADBALANCER && len(self.AssociateId) > 0 {
|
||||
_lb, err := LoadbalancerManager.FetchById(self.AssociateId)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
lb := _lb.(*SLoadbalancer)
|
||||
if lb.PendingDeleted {
|
||||
return nil
|
||||
}
|
||||
return lb
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) GetAssociateNatGateway() *SNatGateway {
|
||||
if self.AssociateType == api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY && len(self.AssociateId) > 0 {
|
||||
natGateway, err := NatGatewayManager.FetchById(self.AssociateId)
|
||||
@@ -520,6 +535,7 @@ func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenC
|
||||
}
|
||||
var vm *SGuest
|
||||
var nat *SNatGateway
|
||||
var lb *SLoadbalancer
|
||||
switch self.AssociateType {
|
||||
case api.EIP_ASSOCIATE_TYPE_SERVER:
|
||||
vm = self.GetAssociateVM()
|
||||
@@ -531,6 +547,11 @@ func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenC
|
||||
if nat == nil {
|
||||
log.Errorf("dissociate Nat gateway not exists???")
|
||||
}
|
||||
case api.EIP_ASSOCIATE_TYPE_LOADBALANCER:
|
||||
lb = self.GetAssociateLoadbalancer()
|
||||
if lb == nil {
|
||||
log.Errorf("dissociate loadbalancer not exists???")
|
||||
}
|
||||
}
|
||||
|
||||
_, err := db.Update(self, func() error {
|
||||
@@ -553,12 +574,41 @@ func (self *SElasticip) Dissociate(ctx context.Context, userCred mcclient.TokenC
|
||||
db.OpsLog.LogEvent(nat, db.ACT_EIP_DETACH, self.GetShortDesc(ctx), userCred)
|
||||
}
|
||||
|
||||
if lb != nil {
|
||||
db.OpsLog.LogDetachEvent(ctx, lb, self, userCred, self.GetShortDesc(ctx))
|
||||
db.OpsLog.LogEvent(self, db.ACT_EIP_DETACH, lb.GetShortDesc(ctx), userCred)
|
||||
db.OpsLog.LogEvent(lb, db.ACT_EIP_DETACH, self.GetShortDesc(ctx), userCred)
|
||||
}
|
||||
|
||||
if self.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
|
||||
self.Delete(ctx, userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) AssociateLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *SLoadbalancer) error {
|
||||
if lb.PendingDeleted {
|
||||
return fmt.Errorf("loadbalancer is deleted")
|
||||
}
|
||||
if len(self.AssociateType) > 0 {
|
||||
return fmt.Errorf("EIP has been associated!!")
|
||||
}
|
||||
_, err := db.Update(self, func() error {
|
||||
self.AssociateType = api.EIP_ASSOCIATE_TYPE_LOADBALANCER
|
||||
self.AssociateId = lb.Id
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
db.OpsLog.LogAttachEvent(ctx, lb, self, userCred, self.GetShortDesc(ctx))
|
||||
db.OpsLog.LogEvent(self, db.ACT_EIP_ATTACH, lb.GetShortDesc(ctx), userCred)
|
||||
db.OpsLog.LogEvent(lb, db.ACT_EIP_ATTACH, self.GetShortDesc(ctx), userCred)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticip) AssociateVM(ctx context.Context, userCred mcclient.TokenCredential, vm *SGuest) error {
|
||||
if vm.PendingDeleted || vm.Deleted {
|
||||
return fmt.Errorf("vm is deleted")
|
||||
|
||||
@@ -485,6 +485,12 @@ func (lb *SLoadbalancer) GetCustomizeColumns(ctx context.Context, userCred mccli
|
||||
}
|
||||
}
|
||||
|
||||
eip, _ := lb.GetEip()
|
||||
if eip != nil {
|
||||
extra.Set("eip", jsonutils.NewString(eip.IpAddr))
|
||||
extra.Set("eip_mode", jsonutils.NewString(eip.Mode))
|
||||
}
|
||||
|
||||
if lb.BackendGroupId != "" {
|
||||
lbbg, err := LoadbalancerBackendGroupManager.FetchById(lb.BackendGroupId)
|
||||
if err != nil {
|
||||
@@ -710,6 +716,105 @@ func (lb *SLoadbalancer) syncLoadbalancerNetwork(ctx context.Context, userCred m
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SLoadbalancer) DeleteEip(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
eip, err := self.GetEip()
|
||||
if err != nil {
|
||||
log.Errorf("Delete eip fail for get Eip %s", err)
|
||||
return err
|
||||
}
|
||||
if eip == nil {
|
||||
return nil
|
||||
}
|
||||
if eip.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
|
||||
err = eip.RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
log.Errorf("Delete eip on delete server fail %s", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = eip.Dissociate(ctx, userCred)
|
||||
if err != nil {
|
||||
log.Errorf("Dissociate eip on delete server fail %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SLoadbalancer) GetEip() (*SElasticip, error) {
|
||||
return ElasticipManager.getEipForInstance(api.EIP_ASSOCIATE_TYPE_LOADBALANCER, self.Id)
|
||||
}
|
||||
|
||||
func (self *SLoadbalancer) SyncLoadbalancerEip(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extEip cloudprovider.ICloudEIP) compare.SyncResult {
|
||||
result := compare.SyncResult{}
|
||||
|
||||
eip, err := self.GetEip()
|
||||
if err != nil {
|
||||
result.Error(fmt.Errorf("getEip error %s", err))
|
||||
return result
|
||||
}
|
||||
|
||||
if eip == nil && extEip == nil {
|
||||
// do nothing
|
||||
} else if eip == nil && extEip != nil {
|
||||
// add
|
||||
neip, err := ElasticipManager.getEipByExtEip(ctx, userCred, extEip, provider, self.GetRegion(), provider.GetOwnerId())
|
||||
if err != nil {
|
||||
log.Errorf("getEipByExtEip error %v", err)
|
||||
result.AddError(err)
|
||||
} else {
|
||||
err = neip.AssociateLoadbalancer(ctx, userCred, self)
|
||||
if err != nil {
|
||||
log.Errorf("AssociateVM error %v", err)
|
||||
result.AddError(err)
|
||||
} else {
|
||||
result.Add()
|
||||
}
|
||||
}
|
||||
} else if eip != nil && extEip == nil {
|
||||
// remove
|
||||
err = eip.Dissociate(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
} else {
|
||||
result.Delete()
|
||||
}
|
||||
} else {
|
||||
// sync
|
||||
if eip.IpAddr != extEip.GetIpAddr() {
|
||||
// remove then add
|
||||
err = eip.Dissociate(ctx, userCred)
|
||||
if err != nil {
|
||||
// fail to remove
|
||||
result.DeleteError(err)
|
||||
} else {
|
||||
result.Delete()
|
||||
neip, err := ElasticipManager.getEipByExtEip(ctx, userCred, extEip, provider, self.GetRegion(), provider.GetOwnerId())
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
err = neip.AssociateLoadbalancer(ctx, userCred, self)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
result.Add()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do nothing
|
||||
err := eip.SyncWithCloudEip(ctx, userCred, provider, extEip, provider.GetOwnerId())
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
} else {
|
||||
result.Update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) SyncWithCloudLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, extLb cloudprovider.ICloudLoadbalancer, syncOwnerId mcclient.IIdentityProvider) error {
|
||||
lockman.LockObject(ctx, lb)
|
||||
defer lockman.ReleaseObject(ctx, lb)
|
||||
|
||||
@@ -295,6 +295,11 @@ func (lb *SLoadbalancer) purge(ctx context.Context, userCred mcclient.TokenCrede
|
||||
return err
|
||||
}
|
||||
|
||||
err = lb.DeleteEip(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = lb.purgeBackendGroups(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -176,6 +177,15 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancer(ctx co
|
||||
if err := lb.SyncWithCloudLoadbalancer(ctx, userCred, iLoadbalancer, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//公网lb,需要同步public ip
|
||||
if lb.AddressType == api.LB_ADDR_TYPE_INTERNET {
|
||||
publicIp, err := iLoadbalancer.GetIEIP()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "iLoadbalancer.GetIEIP()")
|
||||
}
|
||||
lb.SyncLoadbalancerEip(ctx, userCred, lb.GetCloudprovider(), publicIp)
|
||||
}
|
||||
|
||||
lbbgs, err := iLoadbalancer.GetILoadBalancerBackendGroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -60,6 +60,7 @@ func (self *LoadbalancerDeleteTask) OnInit(ctx context.Context, obj db.IStandalo
|
||||
func (self *LoadbalancerDeleteTask) OnLoadbalancerDeleteComplete(ctx context.Context, lb *models.SLoadbalancer, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(lb, db.ACT_DELETE, lb.GetShortDesc(ctx), self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, lb, logclient.ACT_DELOCATE, nil, self.UserCred, true)
|
||||
lb.DeleteEip(ctx, self.UserCred)
|
||||
lb.LBPendingDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
27
pkg/multicloud/loadbalancer_base.go
Normal file
27
pkg/multicloud/loadbalancer_base.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package multicloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SLoadbalancerBase struct {
|
||||
SResourceBase
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancerBase) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -17,6 +17,10 @@ package aliyun
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -53,6 +57,7 @@ type BackendServers struct {
|
||||
}
|
||||
|
||||
type SLoadbalancer struct {
|
||||
multicloud.SLoadbalancerBase
|
||||
region *SRegion
|
||||
|
||||
LoadBalancerId string //负载均衡实例ID。
|
||||
@@ -68,14 +73,14 @@ type SLoadbalancer struct {
|
||||
ListenerPorts ListenerPorts
|
||||
ListenerPortsAndProtocol ListenerPortsAndProtocol
|
||||
BackendServers BackendServers
|
||||
CreateTime string //负载均衡实例的创建时间。
|
||||
MasterZoneId string //实例的主可用区ID。
|
||||
SlaveZoneId string //实例的备可用区ID。
|
||||
InternetChargeType string //公网实例的计费方式。取值:paybybandwidth:按带宽计费 paybytraffic:按流量计费(默认值) 说明 当 PayType参数的值为PrePay时,只支持按带宽计费。
|
||||
PayType string //实例的计费类型,取值:PayOnDemand:按量付费 PrePay:预付费
|
||||
ResourceGroupId string //企业资源组ID。
|
||||
LoadBalancerSpec string //负载均衡实例的的性能规格
|
||||
Bandwidth int //按带宽计费的公网型实例的带宽峰值
|
||||
CreateTime time.Time //负载均衡实例的创建时间。
|
||||
MasterZoneId string //实例的主可用区ID。
|
||||
SlaveZoneId string //实例的备可用区ID。
|
||||
InternetChargeType TInternetChargeType //公网实例的计费方式。取值:paybybandwidth:按带宽计费 paybytraffic:按流量计费(默认值) 说明 当 PayType参数的值为PrePay时,只支持按带宽计费。
|
||||
PayType string //实例的计费类型,取值:PayOnDemand:按量付费 PrePay:预付费
|
||||
ResourceGroupId string //企业资源组ID。
|
||||
LoadBalancerSpec string //负载均衡实例的的性能规格
|
||||
Bandwidth int //按带宽计费的公网型实例的带宽峰值
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetName() string {
|
||||
@@ -259,6 +264,10 @@ func (lb *SLoadbalancer) GetChargeType() string {
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetCreatedAt() time.Time {
|
||||
return lb.CreateTime
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetEgressMbps() int {
|
||||
if lb.Bandwidth < 1 {
|
||||
return 0
|
||||
@@ -279,6 +288,32 @@ func (lb *SLoadbalancer) GetILoadBalancerBackendGroupById(groupId string) (cloud
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
if lb.AddressType == "internet" {
|
||||
eip := SEipAddress{
|
||||
region: lb.region,
|
||||
IpAddress: lb.Address,
|
||||
InstanceId: lb.GetGlobalId(),
|
||||
InstanceType: EIP_INTANNCE_TYPE_SLB,
|
||||
Status: EIP_STATUS_INUSE,
|
||||
AllocationId: lb.GetGlobalId(),
|
||||
AllocationTime: lb.CreateTime,
|
||||
Bandwidth: lb.Bandwidth,
|
||||
InternetChargeType: lb.InternetChargeType,
|
||||
}
|
||||
return &eip, nil
|
||||
}
|
||||
eips, total, err := lb.region.GetEips("", lb.LoadBalancerId, 0, 1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "lb.region.GetEips(%s)", lb.LoadBalancerId)
|
||||
}
|
||||
if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
eips[0].region = lb.region
|
||||
return &eips[0], nil
|
||||
}
|
||||
|
||||
func (region *SRegion) loadbalancerOperation(loadbalancerId, status string) error {
|
||||
params := map[string]string{}
|
||||
params["RegionId"] = region.RegionId
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -47,6 +48,7 @@ todo:
|
||||
|
||||
// https://cloud.tencent.com/document/api/214/30694#LoadBalancer
|
||||
type SLoadbalancer struct {
|
||||
multicloud.SLoadbalancerBase
|
||||
region *SRegion
|
||||
|
||||
Status int64 `json:"Status"` // 0:创建中,1:正常运行
|
||||
@@ -343,6 +345,20 @@ func (self *SLoadbalancer) GetILoadBalancerBackendGroups() ([]cloudprovider.IClo
|
||||
return ibgs, nil
|
||||
}
|
||||
|
||||
func (self *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
if self.LoadBalancerType == "OPEN" && len(self.LoadBalancerVips) > 0 {
|
||||
return &SEipAddress{
|
||||
region: self.region,
|
||||
AddressId: self.LoadBalancerID,
|
||||
AddressIp: self.LoadBalancerVips[0],
|
||||
AddressType: EIP_STATUS_BIND,
|
||||
InstanceId: self.LoadBalancerID,
|
||||
CreatedTime: self.CreateTime,
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetLoadbalancers(ids []string) ([]SLoadbalancer, error) {
|
||||
params := map[string]string{}
|
||||
for i, id := range ids {
|
||||
|
||||
Reference in New Issue
Block a user