fix(region): sync lb eip (#23126)

This commit is contained in:
屈轩
2025-08-20 14:14:07 +08:00
committed by GitHub
parent 3b34ac8dba
commit d9e8c89711
19 changed files with 128 additions and 111 deletions
+3 -3
View File
@@ -87,14 +87,14 @@ require (
k8s.io/client-go v0.19.3
k8s.io/cluster-bootstrap v0.19.3
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806071154-376c8716aafd
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9
yunion.io/x/pkg v1.10.4-0.20250814065738-8df5d9d07297
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
)
+6 -6
View File
@@ -1270,8 +1270,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806071154-376c8716aafd h1:nIOCPteVEdSJ6Agx3az+hJlfy4QryZQsSZ8Rjb7d5Eg=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806071154-376c8716aafd/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c h1:OfxElEPjNCFhPIq4RHwDCGl/FOppGey9lMnO3HsUUgA=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
@@ -1285,11 +1285,11 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9 h1:8NuoKUPb3sHigChE6Mz6Nf9aZvM/TvORueIZAMYfPK0=
yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/pkg v1.10.4-0.20250814065738-8df5d9d07297 h1:rnU78gHJ+2nEgjpwWN+FclED/nFeuMkrrBWgnTz0ykc=
yunion.io/x/pkg v1.10.4-0.20250814065738-8df5d9d07297/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833 h1:XTFC1naKYkciCQDLm9izpzHXfTenmmtYsTpVKrsN5hE=
yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0 h1:Eha/ywh4foMJm7VJ8ibFOi+WPHacuTWtosAGpOld5vo=
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
+6
View File
@@ -1100,6 +1100,12 @@ func syncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, syncRes
return
}
// 快速同步可能会导致guest被删除,所以需要重新获取
guest := GuestManager.FetchGuestById(syncVMPairs[i].Local.Id)
if guest == nil || guest.Deleted || guest.PendingDeleted {
return
}
SyncVMPeripherals(ctx, userCred, syncVMPairs[i].Local, syncVMPairs[i].Remote, localHost, provider, driver)
}()
}
+3 -2
View File
@@ -903,8 +903,9 @@ func (self *SElasticip) AssociateLoadbalancer(ctx context.Context, userCred mccl
if len(self.AssociateType) > 0 && len(self.AssociateId) > 0 {
if self.AssociateType == api.EIP_ASSOCIATE_TYPE_LOADBALANCER && self.AssociateId == lb.Id {
return nil
} else {
return fmt.Errorf("EIP has been associated!!")
}
if self.GetAssociateResource() != nil {
return fmt.Errorf("eip has been associated!!")
}
}
_, err := db.Update(self, func() error {
+3 -3
View File
@@ -1576,7 +1576,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806071154-376c8716aafd
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024124-b54c4686c57c
## explicit; go 1.21
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
@@ -1671,7 +1671,7 @@ yunion.io/x/log/hooks
yunion.io/x/ovsdb/cli_util
yunion.io/x/ovsdb/schema/ovn_nb
yunion.io/x/ovsdb/types
# yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9
# yunion.io/x/pkg v1.10.4-0.20250814065738-8df5d9d07297
## explicit; go 1.18
yunion.io/x/pkg/appctx
yunion.io/x/pkg/errors
@@ -1725,7 +1725,7 @@ yunion.io/x/pkg/utils
# yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
## explicit; go 1.12
yunion.io/x/s3cli
# yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833
# yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0
## explicit; go 1.17
yunion.io/x/sqlchemy
yunion.io/x/sqlchemy/backends
+31 -24
View File
@@ -163,6 +163,9 @@ func (self *SEipAddress) GetMode() string {
func (self *SEipAddress) GetAssociationType() string {
switch self.InstanceType {
case EIP_INSTANCE_TYPE_ECS, "NetworkInterface":
if strings.HasPrefix(self.Name, "CREATE_BY_ALB") || strings.HasPrefix(self.Name, "CREATE_BY_NLB") {
return api.EIP_ASSOCIATE_TYPE_LOADBALANCER
}
return api.EIP_ASSOCIATE_TYPE_SERVER
case EIP_INSTANCE_TYPE_NAT:
return api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY
@@ -240,15 +243,10 @@ func (self *SEipAddress) ChangeBandwidth(bw int) error {
return self.region.UpdateEipBandwidth(self.AllocationId, bw)
}
func (region *SRegion) GetEips(eipId string, associatedId, addr string, offset int, limit int) ([]SEipAddress, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
}
func (region *SRegion) GetEips(eipId string, associatedId, addr string) ([]SEipAddress, error) {
params := make(map[string]string)
params["RegionId"] = region.RegionId
params["PageSize"] = fmt.Sprintf("%d", limit)
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
params["PageSize"] = "100"
if len(addr) > 0 {
params["EipAddress"] = addr
}
@@ -266,27 +264,36 @@ func (region *SRegion) GetEips(eipId string, associatedId, addr string, offset i
}
}
body, err := region.vpcRequest("DescribeEipAddresses", params)
if err != nil {
log.Errorf("DescribeEipAddresses fail %s", err)
return nil, 0, err
pageNumber := 1
ret := []SEipAddress{}
for {
params["PageNumber"] = fmt.Sprintf("%d", pageNumber)
body, err := region.vpcRequest("DescribeEipAddresses", params)
if err != nil {
log.Errorf("DescribeEipAddresses fail %s", err)
return nil, err
}
part := struct {
EipAddresses struct {
EipAddress []SEipAddress
} `json:"EipAddresses"`
TotalCount int `json:"TotalCount"`
}{}
err = body.Unmarshal(&part)
if err != nil {
return nil, errors.Wrapf(err, "Unmarshal EipAddress details")
}
ret = append(ret, part.EipAddresses.EipAddress...)
if len(ret) >= part.TotalCount {
break
}
pageNumber++
}
eips := make([]SEipAddress, 0)
err = body.Unmarshal(&eips, "EipAddresses", "EipAddress")
if err != nil {
log.Errorf("Unmarshal EipAddress details fail %s", err)
return nil, 0, err
}
total, _ := body.Int("TotalCount")
for i := 0; i < len(eips); i += 1 {
eips[i].region = region
}
return eips, int(total), nil
return ret, nil
}
func (region *SRegion) GetEip(eipId string) (*SEipAddress, error) {
eips, _, err := region.GetEips(eipId, "", "", 0, 1)
eips, err := region.GetEips(eipId, "", "")
if err != nil {
return nil, err
}
+5 -5
View File
@@ -317,15 +317,15 @@ func (lb *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
}
return &eip, nil
}
eips, total, err := lb.region.GetEips("", lb.LoadBalancerId, "", 0, 1)
eips, err := lb.region.GetEips("", lb.LoadBalancerId, "")
if err != nil {
return nil, errors.Wrapf(err, "lb.region.GetEips(%s)", lb.LoadBalancerId)
}
if total != 1 {
return nil, cloudprovider.ErrNotFound
for i := range eips {
eips[i].region = lb.region
return &eips[i], nil
}
eips[0].region = lb.region
return &eips[0], nil
return nil, cloudprovider.ErrNotFound
}
func (region *SRegion) loadbalancerOperation(loadbalancerId, status string) error {
+7 -14
View File
@@ -155,23 +155,16 @@ func (nat *SNatGateway) GetExpiredAt() time.Time {
}
func (nat *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips := []SEipAddress{}
for {
parts, total, err := nat.vpc.region.GetEips("", nat.NatGatewayId, "", len(eips), 50)
if err != nil {
return nil, err
}
eips = append(eips, parts...)
if len(eips) >= total {
break
}
eips, err := nat.vpc.region.GetEips("", nat.NatGatewayId, "")
if err != nil {
return nil, err
}
ieips := []cloudprovider.ICloudEIP{}
for i := 0; i < len(eips); i++ {
ret := []cloudprovider.ICloudEIP{}
for i := range eips {
eips[i].region = nat.vpc.region
ieips = append(ieips, &eips[i])
ret = append(ret, &eips[i])
}
return ieips, nil
return ret, nil
}
func (nat *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) {
+5 -18
View File
@@ -851,37 +851,24 @@ func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error
}
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips, total, err := self.GetEips("", "", "", 0, 50)
eips, err := self.GetEips("", "", "")
if err != nil {
return nil, err
}
for len(eips) < total {
var parts []SEipAddress
parts, total, err = self.GetEips("", "", "", len(eips), 50)
if err != nil {
return nil, err
}
eips = append(eips, parts...)
}
ret := make([]cloudprovider.ICloudEIP, len(eips))
for i := 0; i < len(eips); i += 1 {
for i := range eips {
eips[i].region = self
ret[i] = &eips[i]
}
return ret, nil
}
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
eips, total, err := self.GetEips(eipId, "", "", 0, 1)
eip, err := self.GetEip(eipId)
if err != nil {
return nil, err
}
if total == 0 {
return nil, cloudprovider.ErrNotFound
}
if total > 1 {
return nil, cloudprovider.ErrDuplicateId
}
return &eips[0], nil
return eip, nil
}
func (region *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
+4 -1
View File
@@ -59,7 +59,10 @@ func (self *SSnapshot) GetId() string {
}
func (self *SSnapshot) GetName() string {
return self.SnapshotName
if len(self.SnapshotName) > 0 {
return self.SnapshotName
}
return self.SnapshotId
}
func (self *SSnapshot) GetStatus() string {
+8 -7
View File
@@ -113,14 +113,15 @@ func (self *SNatGateway) Refresh() error {
}
func (self *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips, err := self.region.GetEips("", "", self.NatGatewayId)
if err != nil {
return nil, errors.Wrapf(err, "GetEIPs")
}
ret := []cloudprovider.ICloudEIP{}
for i := range eips {
eips[i].region = self.region
ret = append(ret, &eips[i])
for _, addr := range self.NatGatewayAddresses {
if len(addr.PublicIp) > 0 {
eip, err := self.region.GetEipByIpAddress(addr.PublicIp)
if err != nil {
return nil, errors.Wrapf(err, "GetEipByIpAddress")
}
ret = append(ret, eip)
}
}
return ret, nil
}
+2 -3
View File
@@ -682,12 +682,11 @@ func (svm *SVirtualMachine) doUnregister(ctx context.Context) error {
}
func (svm *SVirtualMachine) DeleteVM(ctx context.Context) error {
err := svm.CheckFileInfo(ctx)
err := svm.doDestroy(ctx)
if err != nil {
log.Errorf("CheckFileInfo %s error: %v", svm.GetName(), err)
return svm.doUnregister(ctx)
}
return svm.doDestroy(ctx)
return nil
}
func (svm *SVirtualMachine) doDetachAndDeleteDisk(ctx context.Context, vdisk *SVirtualDisk) error {
+11
View File
@@ -128,6 +128,17 @@ func (addr *SAddress) GetAssociationType() string {
if len(addr.GetAssociationExternalId()) > 0 {
return api.EIP_ASSOCIATE_TYPE_SERVER
}
for _, user := range addr.Users {
if strings.Contains(user, "/instances/") {
return api.EIP_ASSOCIATE_TYPE_SERVER
}
if strings.Contains(user, "/forwardingRules/") {
return api.EIP_ASSOCIATE_TYPE_LOADBALANCER
}
if strings.Contains(user, "/routers/") {
return api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY
}
}
return ""
}
+7 -9
View File
@@ -322,15 +322,13 @@ func (self *SLoadbalancer) GetILoadBalancerBackendGroups() ([]cloudprovider.IClo
}
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
eips, _, err := self.region.GetEips("", self.LoadBalancerId, 0, 50)
if err != nil {
return nil, errors.Wrapf(err, "GetEips")
}
for i := range eips {
eips[i].region = self.region
return &eips[i], nil
}
return nil, nil
}
+11 -14
View File
@@ -281,27 +281,24 @@ func ErrorMsg(err error) string {
func GetAddrPort(urlStr string) (string, int, error) {
parts, err := url.Parse(urlStr)
if err != nil {
return "", 0, err
return "", 0, errors.Wrapf(err, "url.Parse %s", urlStr)
}
host := parts.Host
hostAddr, hostPortStr, err := net.SplitHostPort(host)
if err == nil {
hostPort, err := strconv.ParseInt(hostPortStr, 10, 32)
if err != nil {
return "", 0, errors.Wrapf(err, "strconv.ParseInt port string %s", hostPortStr)
} else {
return hostAddr, int(hostPort), nil
}
} else {
portStr := parts.Port()
if len(portStr) == 0 {
switch parts.Scheme {
case "http":
return parts.Host, 80, nil
return parts.Hostname(), 80, nil
case "https":
return parts.Host, 443, nil
return parts.Hostname(), 443, nil
default:
return "", 0, errors.Wrapf(errors.ErrInvalidFormat, "Unknown schema %s", parts.Scheme)
return "", 0, errors.Errorf("Unknown schema %s", parts.Scheme)
}
}
port, err := strconv.Atoi(portStr)
if err != nil {
return "", 0, errors.Wrapf(err, "strconv.Atoi port string %s", portStr)
}
return parts.Hostname(), port, nil
}
func GetTransport(insecure bool) *http.Transport {
+9
View File
@@ -363,6 +363,15 @@ func (addr IPV6Addr) Ge(addr2 IPV6Addr) bool {
return !addr.Lt(addr2)
}
func (addr IPV6Addr) IsZero() bool {
for _, v := range addr {
if v != 0 {
return false
}
}
return true
}
type IPV6AddrRange struct {
start IPV6Addr
end IPV6Addr
+4
View File
@@ -139,6 +139,10 @@ func (addr IPV4Addr) ToMac(prefix string) string {
return fmt.Sprintf("%s%02x:%02x:%02x:%02x", prefix, bytes[0], bytes[1], bytes[2], bytes[3])
}
func (addr IPV4Addr) IsZero() bool {
return addr == 0
}
type IPV4AddrRange struct {
start IPV4Addr
end IPV4Addr
+1 -2
View File
@@ -15,7 +15,6 @@
package dameng
import (
"yunion.io/x/log"
"yunion.io/x/sqlchemy"
)
@@ -32,7 +31,7 @@ func (t *SDamengEqualsCondition) WhereClause() string {
// Equals filter conditions
func (dameng *SDamengBackend) Equals(f sqlchemy.IQueryField, v interface{}) sqlchemy.ICondition {
log.Debugf("field %s isFieldText: %v %#v", f.Name(), sqlchemy.IsFieldText(f), f)
// log.Debugf("field %s isFieldText: %v %#v", f.Name(), sqlchemy.IsFieldText(f), f)
if sqlchemy.IsFieldText(f) {
c := SDamengEqualsCondition{sqlchemy.NewTupleCondition(f, v)}
return &c
+2
View File
@@ -21,6 +21,7 @@ import (
"reflect"
"strconv"
"strings"
"runtime/debug"
_ "gitee.com/chunanyong/dm"
@@ -95,6 +96,7 @@ func (dameng *SDamengBackend) PrepareInsertOrUpdateSQL(ts sqlchemy.ITableSpec, i
for _, primary := range onPrimaryCols {
colName := strings.Trim(primary, "'\"")
if _, ok := colNameMap[colName]; !ok {
debug.PrintStack()
log.Fatalf("primary colume %s missing from insert columes for table %s", colName, ts.Name())
}
onConditions = append(onConditions, fmt.Sprintf("T1.%s=T2.%s", primary, primary))