mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 06:09:39 +08:00
fix: vpc eip misc fixes: 1. eip filter 2. lb filter 3. create eip when (#14343)
lb creating Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
@@ -92,6 +92,12 @@ type LoadbalancerListInput struct {
|
||||
ChargeType []string `json:"charge_type"`
|
||||
// 套餐名称
|
||||
LoadbalancerSpec []string `json:"loadbalancer_spec"`
|
||||
|
||||
// filter for EIP
|
||||
WithEip *bool `json:"with_eip"`
|
||||
WithoutEip *bool `json:"without_eip"`
|
||||
EipAssociable *bool `json:"eip_associable"`
|
||||
UsableLoadbalancerForEip string `json:"usable_loadbalancer_for_eip"`
|
||||
}
|
||||
|
||||
type LoadbalancerAgentListInput struct {
|
||||
@@ -253,6 +259,16 @@ type LoadbalancerCreateInput struct {
|
||||
// 套餐名称
|
||||
LoadbalancerSpec string `json:"loadbalancer_spec"`
|
||||
|
||||
// 弹性公网IP带宽
|
||||
// 指定此参数后会创建新的弹性公网IP并绑定到新建的负载均衡
|
||||
EipBw int `json:"eip_bw,omitzero"`
|
||||
// 弹性公网IP线路类型
|
||||
EipBgpType string `json:"eip_bgp_type,omitzero"`
|
||||
// 弹性公网IP计费类型
|
||||
EipChargeType string `json:"eip_charge_type,omitempty"`
|
||||
// 是否跟随主机删除而自动释放
|
||||
EipAutoDellocate bool `json:"eip_auto_dellocate,omitempty"`
|
||||
|
||||
// EIP ID
|
||||
Eip string `json:"eip"`
|
||||
|
||||
|
||||
@@ -231,6 +231,16 @@ func (manager *SElasticipManager) ListItemFilter(
|
||||
q = q.Equals("cloudregion_id", lb.CloudregionId)
|
||||
if len(lb.ManagerId) > 0 {
|
||||
q = q.Equals("manager_id", lb.ManagerId)
|
||||
} else {
|
||||
zone, _ := lb.GetZone()
|
||||
networks := NetworkManager.Query().SubQuery()
|
||||
wires := WireManager.Query().SubQuery()
|
||||
|
||||
sq := networks.Query(networks.Field("id")).Join(wires, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id"))).
|
||||
Filter(sqlchemy.Equals(wires.Field("zone_id"), zone.Id)).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(q.Field("network_id"), sq))
|
||||
gns := LoadbalancernetworkManager.Query("network_id").Equals("loadbalancer_id", lb.Id).SubQuery()
|
||||
q = q.Filter(sqlchemy.NotIn(q.Field("network_id"), gns))
|
||||
}
|
||||
q = q.IsNullOrEmpty("associate_type")
|
||||
default:
|
||||
|
||||
@@ -203,6 +203,79 @@ func (man *SLoadbalancerManager) ListItemFilter(
|
||||
q = q.Filter(sqlchemy.OR(c1, c2))
|
||||
}
|
||||
|
||||
// eip filters
|
||||
usableLbForEipFilter := query.UsableLoadbalancerForEip
|
||||
if len(usableLbForEipFilter) > 0 {
|
||||
eipObj, err := ElasticipManager.FetchByIdOrName(userCred, usableLbForEipFilter)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("eip %s not found", usableLbForEipFilter)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
eip := eipObj.(*SElasticip)
|
||||
|
||||
if len(eip.NetworkId) > 0 {
|
||||
// kvm
|
||||
sq := LoadbalancernetworkManager.Query("loadbalancer_id").Equals("network_id", eip.NetworkId).SubQuery()
|
||||
q = q.NotIn("id", sq)
|
||||
if cp := eip.GetCloudprovider(); cp == nil || cp.Provider == api.CLOUD_PROVIDER_ONECLOUD {
|
||||
gnq := LoadbalancernetworkManager.Query().SubQuery()
|
||||
nq := NetworkManager.Query().SubQuery()
|
||||
wq := WireManager.Query().SubQuery()
|
||||
vq := VpcManager.Query().SubQuery()
|
||||
q.Join(gnq, sqlchemy.Equals(gnq.Field("loadbalancer_id"), q.Field("id")))
|
||||
q.Join(nq, sqlchemy.Equals(nq.Field("id"), gnq.Field("network_id")))
|
||||
q.Join(wq, sqlchemy.Equals(wq.Field("id"), nq.Field("wire_id")))
|
||||
q.Join(vq, sqlchemy.Equals(vq.Field("id"), wq.Field("vpc_id")))
|
||||
q.Filter(sqlchemy.IsNullOrEmpty(gnq.Field("eip_id")))
|
||||
q.Filter(sqlchemy.NotEquals(vq.Field("id"), api.DEFAULT_VPC_ID))
|
||||
// vpc provider thing will be handled ok below
|
||||
}
|
||||
}
|
||||
|
||||
if eip.ManagerId != "" {
|
||||
q = q.Equals("manager_id", eip.ManagerId)
|
||||
} else {
|
||||
q = q.IsNullOrEmpty("manager_id")
|
||||
}
|
||||
region, err := eip.GetRegion()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "eip.GetRegion"))
|
||||
}
|
||||
q = q.Equals("cloudregion_id", region.Id)
|
||||
}
|
||||
|
||||
withEip := (query.WithEip != nil && *query.WithEip)
|
||||
withoutEip := (query.WithoutEip != nil && *query.WithoutEip) || (query.EipAssociable != nil && *query.EipAssociable)
|
||||
if withEip || withoutEip {
|
||||
eips := ElasticipManager.Query().SubQuery()
|
||||
sq := eips.Query(eips.Field("associate_id")).Equals("associate_type", api.EIP_ASSOCIATE_TYPE_LOADBALANCER)
|
||||
sq = sq.IsNotNull("associate_id").IsNotEmpty("associate_id")
|
||||
|
||||
if withEip {
|
||||
q = q.In("id", sq)
|
||||
} else if withoutEip {
|
||||
q = q.NotIn("id", sq)
|
||||
}
|
||||
}
|
||||
|
||||
if query.EipAssociable != nil {
|
||||
sq1 := NetworkManager.Query("id")
|
||||
sq2 := WireManager.Query().SubQuery()
|
||||
sq3 := VpcManager.Query().SubQuery()
|
||||
sq1 = sq1.Join(sq2, sqlchemy.Equals(sq1.Field("wire_id"), sq2.Field("id")))
|
||||
sq1 = sq1.Join(sq3, sqlchemy.Equals(sq2.Field("vpc_id"), sq3.Field("id")))
|
||||
cond1 := []string{api.VPC_EXTERNAL_ACCESS_MODE_EIP, api.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW}
|
||||
if *query.EipAssociable {
|
||||
sq1 = sq1.Filter(sqlchemy.In(sq3.Field("external_access_mode"), cond1))
|
||||
} else {
|
||||
sq1 = sq1.Filter(sqlchemy.NotIn(sq3.Field("external_access_mode"), cond1))
|
||||
}
|
||||
sq := LoadbalancernetworkManager.Query("loadbalancer_id").In("network_id", sq1)
|
||||
q = q.In("id", sq)
|
||||
}
|
||||
|
||||
if len(query.AddressType) > 0 {
|
||||
q = q.In("address_type", query.AddressType)
|
||||
}
|
||||
@@ -359,6 +432,9 @@ func (man *SLoadbalancerManager) ValidateCreateData(
|
||||
|
||||
quotaKeys := fetchRegionalQuotaKeys(rbacutils.ScopeProject, ownerId, region, cloudprovider)
|
||||
pendingUsage := SRegionQuota{Loadbalancer: 1}
|
||||
if input.EipBw > 0 && len(input.Eip) == 0 {
|
||||
pendingUsage.Eip = 1
|
||||
}
|
||||
pendingUsage.SetKeys(quotaKeys)
|
||||
if err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("%s", err)
|
||||
@@ -565,11 +641,13 @@ func (lb *SLoadbalancer) StartLoadBalancerDeleteTask(ctx context.Context, userCr
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) StartLoadBalancerCreateTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error {
|
||||
taskData := jsonutils.NewDict()
|
||||
eipId, _ := data.GetString("eip_id")
|
||||
if len(eipId) > 0 {
|
||||
taskData.Set("eip_id", jsonutils.NewString(eipId)) // for huawei internet elb
|
||||
}
|
||||
taskData := data.CopyIncludes(
|
||||
"eip_id", // for huawei internet elb
|
||||
"eip_bw",
|
||||
"eip_bgp_type",
|
||||
"eip_charge_type",
|
||||
"eip_auto_dellocate",
|
||||
)
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "LoadbalancerCreateTask", lb, userCred, taskData, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -743,7 +821,12 @@ func (lb *SLoadbalancer) validatePurgeCondition(ctx context.Context) error {
|
||||
|
||||
func (lb *SLoadbalancer) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
lb.SetStatus(userCred, api.LB_STATUS_DELETING, "")
|
||||
return lb.StartLoadBalancerDeleteTask(ctx, userCred, jsonutils.NewDict(), "")
|
||||
params := jsonutils.NewDict()
|
||||
deleteEip := jsonutils.QueryBoolean(data, "delete_eip", false)
|
||||
if deleteEip {
|
||||
params.Set("delete_eip", jsonutils.JSONTrue)
|
||||
}
|
||||
return lb.StartLoadBalancerDeleteTask(ctx, userCred, params, "")
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetLoadbalancerListeners() ([]SLoadbalancerListener, error) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -797,7 +798,40 @@ func (self *SKVMRegionDriver) RequestCreateLoadbalancer(ctx context.Context, use
|
||||
}
|
||||
// bind eip
|
||||
eipId, _ := task.GetParams().GetString("eip_id")
|
||||
if len(eipId) > 0 {
|
||||
eipBw, _ := task.GetParams().Int("eip_bw")
|
||||
if eipBw > 0 && len(eipId) == 0 {
|
||||
// create eip first
|
||||
bgpType, _ := task.GetParams().GetString("eip_bgp_type")
|
||||
chargeType, _ := task.GetParams().GetString("eip_charge_type")
|
||||
autoDellocate := jsonutils.QueryBoolean(task.GetParams(), "eip_auto_dellocate", false)
|
||||
|
||||
eipPendingUsage := &models.SRegionQuota{Eip: 1}
|
||||
eipPendingUsage.SetKeys(lb.GetQuotaKeys())
|
||||
eip, err := models.ElasticipManager.NewEipForVMOnHost(ctx, userCred, &models.NewEipForVMOnHostArgs{
|
||||
Bandwidth: int(eipBw),
|
||||
BgpType: bgpType,
|
||||
ChargeType: chargeType,
|
||||
AutoDellocate: autoDellocate,
|
||||
|
||||
Loadbalancer: lb,
|
||||
PendingUsage: eipPendingUsage,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("NewEipForVMOnHost fail %s", err)
|
||||
quotas.CancelPendingUsage(ctx, userCred, eipPendingUsage, eipPendingUsage, false)
|
||||
} else {
|
||||
opts := api.ElasticipAssociateInput{
|
||||
InstanceId: lb.Id,
|
||||
InstanceExternalId: lb.ExternalId,
|
||||
InstanceType: api.EIP_ASSOCIATE_TYPE_LOADBALANCER,
|
||||
}
|
||||
|
||||
err = eip.AllocateAndAssociateInstance(ctx, userCred, lb, opts, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "AllocateAndAssociateInstance")
|
||||
}
|
||||
}
|
||||
} else if len(eipId) > 0 {
|
||||
_eip, err := models.ElasticipManager.FetchById(eipId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ElasticipManager.FetchById(%s)", eipId)
|
||||
|
||||
@@ -68,7 +68,8 @@ func (self *LoadbalancerDeleteTask) OnLoadbalancerDeleteComplete(ctx context.Con
|
||||
Obj: lb,
|
||||
Action: notifyclient.ActionDelete,
|
||||
})
|
||||
lb.DeleteEip(ctx, self.UserCred, false)
|
||||
deleteEip := jsonutils.QueryBoolean(self.Params, "delete_eip", false)
|
||||
lb.DeleteEip(ctx, self.UserCred, deleteEip)
|
||||
lb.LBPendingDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ type LoadbalancerCreateOptions struct {
|
||||
Cluster string `json:"cluster_id"`
|
||||
Manager string
|
||||
Tags []string `help:"Tags info,prefix with 'user:', eg: user:project=default" json:"-"`
|
||||
|
||||
Eip string `json:"eip" help:"Id or name of EIP to associate with"`
|
||||
EipBw int `json:"eip_bw"`
|
||||
EipChargeType string `json:"eip_charge_type"`
|
||||
EipBgpType string `json:"eip_bgp_type"`
|
||||
EipAutoDellocate *bool `json:"eip_auto_dellocate"`
|
||||
}
|
||||
|
||||
func (opts *LoadbalancerCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
|
||||
Reference in New Issue
Block a user