diff --git a/go.mod b/go.mod index 496d450843..27ba111295 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( k8s.io/cri-api v0.22.17 k8s.io/klog/v2 v2.20.0 moul.io/http2curl/v2 v2.3.0 - yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250620092920-5cf87c1f27fd + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5 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 diff --git a/go.sum b/go.sum index 33d01a74f1..2a6643f315 100644 --- a/go.sum +++ b/go.sum @@ -1412,8 +1412,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.20250620092920-5cf87c1f27fd h1:FvsOvo2KpO8eSrz/amhKV6WZBgvOFOWZrtxrqIm+Z4s= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250620092920-5cf87c1f27fd/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5 h1:BIbMRsvXq0WZY7LYjzKOxzhazD7Rusm/JRda0mZ53WM= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5/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= diff --git a/vendor/modules.txt b/vendor/modules.txt index 9a24888ddc..d30c9cbf52 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1852,7 +1852,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.20250620092920-5cf87c1f27fd +# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5 ## explicit; go 1.21 yunion.io/x/cloudmux/pkg/apis yunion.io/x/cloudmux/pkg/apis/billing diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/alb.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/alb.go new file mode 100644 index 0000000000..24b5436574 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/alb.go @@ -0,0 +1,337 @@ +// 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 aliyun + +import ( + "context" + "time" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SAlb struct { + multicloud.SLoadbalancerBase + AliyunTags + region *SRegion + + LoadBalancerId string `json:"LoadBalancerId"` + LoadBalancerName string `json:"LoadBalancerName"` + LoadBalancerStatus string `json:"LoadBalancerStatus"` + LoadBalancerBizStatus string `json:"LoadBalancerBizStatus"` + LoadBalancerEdition string `json:"LoadBalancerEdition"` + LoadBalancerPayType string `json:"LoadBalancerPayType"` + AddressType string `json:"AddressType"` + AddressAllocatedMode string `json:"AddressAllocatedMode"` + Ipv6AddressType string `json:"Ipv6AddressType"` + DNSName string `json:"DNSName"` + VpcId string `json:"VpcId"` + LoadBalancerBussinessStatus string `json:"LoadBalancerBussinessStatus"` + CreateTime time.Time `json:"CreateTime"` + ResourceGroupId string `json:"ResourceGroupId"` + CanBeDeleted bool `json:"CanBeDeleted"` + ModificationProtectionConfig map[string]interface{} `json:"ModificationProtectionConfig"` + DeletionProtectionConfig map[string]interface{} `json:"DeletionProtectionConfig"` + AccessLogConfig map[string]interface{} `json:"AccessLogConfig"` + LoadBalancerOperationLocks []map[string]interface{} `json:"LoadBalancerOperationLocks"` + ZoneMappings []ZoneMapping `json:"ZoneMappings"` + RegionId string `json:"RegionId"` +} + +type ZoneMapping struct { + ZoneId string `json:"ZoneId"` + VSwitchId string `json:"VSwitchId"` + AllocationId string `json:"AllocationId"` + EipType string `json:"EipType"` + LoadBalancerAddresses []LoadBalancerAddress `json:"LoadBalancerAddresses"` +} + +type LoadBalancerAddress struct { + Address string `json:"Address"` + AddressType string `json:"AddressType"` + AllocationId string `json:"AllocationId"` + EipType string `json:"EipType"` + IntranetAddress string `json:"IntranetAddress"` + InternetAddress string `json:"InternetAddress"` + Ipv6Address string `json:"Ipv6Address"` +} + +func (alb *SAlb) GetName() string { + return alb.LoadBalancerName +} + +func (alb *SAlb) GetId() string { + return alb.LoadBalancerId +} + +func (alb *SAlb) GetGlobalId() string { + return alb.LoadBalancerId +} + +func (alb *SAlb) GetStatus() string { + switch alb.LoadBalancerStatus { + case "Active": + return api.LB_STATUS_ENABLED + case "Provisioning", "Configuring": + return api.LB_STATUS_UNKNOWN + case "Stopped": + return api.LB_STATUS_DISABLED + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (alb *SAlb) GetAddress() string { + return alb.DNSName +} + +func (alb *SAlb) GetAddressType() string { + return alb.AddressType +} + +func (alb *SAlb) GetNetworkType() string { + return "vpc" +} + +func (alb *SAlb) GetNetworkIds() []string { + ret := []string{} + for _, zone := range alb.ZoneMappings { + if len(zone.VSwitchId) > 0 { + ret = append(ret, zone.VSwitchId) + } + } + return ret +} + +func (alb *SAlb) GetZoneId() string { + if len(alb.ZoneMappings) > 0 { + zone, err := alb.region.getZoneById(alb.ZoneMappings[0].ZoneId) + if err != nil { + log.Errorf("failed to find zone for alb %s error: %v", alb.LoadBalancerName, err) + return "" + } + return zone.GetGlobalId() + } + return "" +} + +func (alb *SAlb) GetZone1Id() string { + if len(alb.ZoneMappings) > 1 { + zone, err := alb.region.getZoneById(alb.ZoneMappings[1].ZoneId) + if err != nil { + log.Errorf("failed to find zone for alb %s error: %v", alb.LoadBalancerName, err) + return "" + } + return zone.GetGlobalId() + } + return "" +} + +func (alb *SAlb) IsEmulated() bool { + return false +} + +func (alb *SAlb) GetVpcId() string { + return alb.VpcId +} + +func (alb *SAlb) Refresh() error { + loadbalancer, err := alb.region.GetAlbDetail(alb.LoadBalancerId) + if err != nil { + return err + } + return jsonutils.Update(alb, loadbalancer) +} + +func (alb *SAlb) Delete(ctx context.Context) error { + return alb.region.DeleteAlb(alb.LoadBalancerId) +} + +func (alb *SAlb) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { + groups, err := alb.region.GetAlbServerGroups() + if err != nil { + return nil, err + } + igroups := []cloudprovider.ICloudLoadbalancerBackendGroup{} + for i := 0; i < len(groups); i++ { + // 过滤出属于当前负载均衡器的服务器组 + for _, lbId := range groups[i].RelatedLoadBalancerIds { + if lbId == alb.LoadBalancerId { + groups[i].alb = alb + igroups = append(igroups, &groups[i]) + break + } + } + } + return igroups, nil +} + +func (alb *SAlb) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { + serverGroup, err := alb.region.CreateAlbServerGroup(group, alb.VpcId) + if err != nil { + return nil, err + } + serverGroup.alb = alb + return serverGroup, nil +} + +func (alb *SAlb) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { + groups, err := alb.GetILoadBalancerBackendGroups() + if err != nil { + return nil, err + } + for i := 0; i < len(groups); i++ { + if groups[i].GetGlobalId() == groupId { + return groups[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (alb *SAlb) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (cloudprovider.ICloudLoadbalancerListener, error) { + return alb.region.CreateAlbListener(alb, listener) +} + +func (alb *SAlb) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) { + listeners, err := alb.GetILoadBalancerListeners() + if err != nil { + return nil, err + } + for i := 0; i < len(listeners); i++ { + if listeners[i].GetGlobalId() == listenerId { + return listeners[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (alb *SAlb) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) { + listeners, err := alb.region.GetAlbListeners(alb.LoadBalancerId) + if err != nil { + return nil, err + } + ilisteners := []cloudprovider.ICloudLoadbalancerListener{} + for i := 0; i < len(listeners); i++ { + listeners[i].alb = alb + ilisteners = append(ilisteners, &listeners[i]) + } + return ilisteners, nil +} + +func (alb *SAlb) GetChargeType() string { + return api.LB_CHARGE_TYPE_BY_TRAFFIC +} + +func (alb *SAlb) GetCreatedAt() time.Time { + return alb.CreateTime +} + +func (alb *SAlb) GetEgressMbps() int { + return 0 +} + +func (alb *SAlb) GetIEIPs() ([]cloudprovider.ICloudEIP, error) { + return []cloudprovider.ICloudEIP{}, nil +} + +func (alb *SAlb) Start() error { + return cloudprovider.ErrNotSupported +} + +func (alb *SAlb) Stop() error { + return cloudprovider.ErrNotSupported +} + +func (alb *SAlb) GetLoadbalancerSpec() string { + return alb.LoadBalancerEdition +} + +func (alb *SAlb) GetProjectId() string { + return alb.ResourceGroupId +} + +// region methods +func (region *SRegion) GetAlbs() ([]SAlb, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "MaxResults": "100", + } + + albs := []SAlb{} + nextToken := "" + + for { + if nextToken != "" { + params["NextToken"] = nextToken + } + + body, err := region.albRequest("ListLoadBalancers", params) + if err != nil { + return nil, err + } + + pageAlbs := []SAlb{} + err = body.Unmarshal(&pageAlbs, "LoadBalancers") + if err != nil { + return nil, err + } + + for i := 0; i < len(pageAlbs); i++ { + pageAlbs[i].region = region + } + albs = append(albs, pageAlbs...) + + nextToken, _ = body.GetString("NextToken") + if nextToken == "" { + break + } + } + + return albs, nil +} + +func (region *SRegion) GetAlbDetail(albId string) (*SAlb, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "LoadBalancerId": albId, + } + + body, err := region.albRequest("GetLoadBalancerAttribute", params) + if err != nil { + return nil, err + } + + alb := &SAlb{region: region} + err = body.Unmarshal(alb) + if err != nil { + return nil, err + } + + return alb, nil +} + +func (region *SRegion) DeleteAlb(albId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "LoadBalancerId": albId, + } + + _, err := region.albRequest("DeleteLoadBalancer", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/alblistener.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/alblistener.go new file mode 100644 index 0000000000..11e9d6f510 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/alblistener.go @@ -0,0 +1,503 @@ +// 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 aliyun + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SAlbListener struct { + multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase + AliyunTags + alb *SAlb + + ListenerId string `json:"ListenerId"` + ListenerDescription string `json:"ListenerDescription"` + ListenerProtocol string `json:"ListenerProtocol"` + ListenerPort int `json:"ListenerPort"` + ListenerStatus string `json:"ListenerStatus"` + LoadBalancerId string `json:"LoadBalancerId"` + RequestTimeout int `json:"RequestTimeout"` + IdleTimeout int `json:"IdleTimeout"` + SecurityPolicyId string `json:"SecurityPolicyId"` + GzipEnabledField bool `json:"GzipEnabled"` + Http2Enabled bool `json:"Http2Enabled"` + QuicEnabled bool `json:"QuicEnabled"` + ProxyProtocolEnabled bool `json:"ProxyProtocolEnabled"` + Certificates []AlbCertificate `json:"Certificates"` + CaCertificates []AlbCertificate `json:"CaCertificates"` + DefaultActions []AlbAction `json:"DefaultActions"` + XForwardedForConfig map[string]interface{} `json:"XForwardedForConfig"` + AccessLogTracingConfig map[string]interface{} `json:"AccessLogTracingConfig"` + // LogConfig map[string]interface{} `json:"LogConfig"` + CreateTime string `json:"CreateTime"` + RegionId string `json:"RegionId"` +} + +type AlbCertificate struct { + CertificateId string `json:"CertificateId"` + IsDefault bool `json:"IsDefault"` +} + +type AlbAction struct { + Type string `json:"Type"` + Order int `json:"Order"` + ForwardGroupConfig ForwardGroupConfig `json:"ForwardGroupConfig"` + FixedResponseConfig FixedResponseConfig `json:"FixedResponseConfig"` + RedirectConfig RedirectConfig `json:"RedirectConfig"` + RewriteConfig RewriteConfig `json:"RewriteConfig"` + InsertHeaderConfig InsertHeaderConfig `json:"InsertHeaderConfig"` + RemoveHeaderConfig RemoveHeaderConfig `json:"RemoveHeaderConfig"` + TrafficLimitConfig TrafficLimitConfig `json:"TrafficLimitConfig"` + TrafficMirrorConfig TrafficMirrorConfig `json:"TrafficMirrorConfig"` + CorsConfig CorsConfig `json:"CorsConfig"` +} + +type ForwardGroupConfig struct { + ServerGroupTuples []ServerGroupTuple `json:"ServerGroupTuples"` +} + +type ServerGroupTuple struct { + ServerGroupId string `json:"ServerGroupId"` + Weight int `json:"Weight"` +} + +type FixedResponseConfig struct { + Content string `json:"Content"` + ContentType string `json:"ContentType"` + HttpCode string `json:"HttpCode"` +} + +type RedirectConfig struct { + Host string `json:"Host"` + HttpCode string `json:"HttpCode"` + Path string `json:"Path"` + Port string `json:"Port"` + Protocol string `json:"Protocol"` + Query string `json:"Query"` +} + +type RewriteConfig struct { + Host string `json:"Host"` + Path string `json:"Path"` + Query string `json:"Query"` +} + +type InsertHeaderConfig struct { + Key string `json:"Key"` + Value string `json:"Value"` + ValueType string `json:"ValueType"` +} + +type RemoveHeaderConfig struct { + Key string `json:"Key"` +} + +type TrafficLimitConfig struct { + QPS int `json:"QPS"` +} + +type TrafficMirrorConfig struct { + MirrorGroupConfig MirrorGroupConfig `json:"MirrorGroupConfig"` + TargetType string `json:"TargetType"` +} + +type MirrorGroupConfig struct { + ServerGroupTuples []ServerGroupTuple `json:"ServerGroupTuples"` +} + +type CorsConfig struct { + AllowCredentials string `json:"AllowCredentials"` + AllowHeaders []string `json:"AllowHeaders"` + AllowMethods []string `json:"AllowMethods"` + AllowOrigin []string `json:"AllowOrigin"` + ExposeHeaders []string `json:"ExposeHeaders"` + MaxAge int `json:"MaxAge"` +} + +func (listener *SAlbListener) GetName() string { + if len(listener.ListenerDescription) > 0 { + return listener.ListenerDescription + } + return fmt.Sprintf("%s:%d", listener.ListenerProtocol, listener.ListenerPort) +} + +func (listener *SAlbListener) GetId() string { + return listener.ListenerId +} + +func (listener *SAlbListener) GetGlobalId() string { + return listener.ListenerId +} + +func (listener *SAlbListener) GetStatus() string { + switch listener.ListenerStatus { + case "Running": + return api.LB_STATUS_ENABLED + case "Stopped": + return api.LB_STATUS_DISABLED + case "Provisioning", "Configuring": + return api.LB_STATUS_UNKNOWN + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (listener *SAlbListener) IsEmulated() bool { + return false +} + +func (listener *SAlbListener) GetEgressMbps() int { + return 0 +} + +func (listener *SAlbListener) Refresh() error { + lis, err := listener.alb.region.GetAlbListener(listener.ListenerId) + if err != nil { + return err + } + return jsonutils.Update(listener, lis) +} + +func (listener *SAlbListener) GetListenerType() string { + switch listener.ListenerProtocol { + case "HTTP": + return api.LB_LISTENER_TYPE_HTTP + case "HTTPS": + return api.LB_LISTENER_TYPE_HTTPS + case "QUIC": + return "QUIC" + default: + return listener.ListenerProtocol + } +} + +func (listener *SAlbListener) GetListenerPort() int { + return listener.ListenerPort +} + +func (listener *SAlbListener) GetBackendGroupId() string { + if len(listener.DefaultActions) > 0 { + for _, action := range listener.DefaultActions { + if action.Type == "ForwardGroup" && len(action.ForwardGroupConfig.ServerGroupTuples) > 0 { + return action.ForwardGroupConfig.ServerGroupTuples[0].ServerGroupId + } + } + } + return "" +} + +func (listener *SAlbListener) GetBackendServerPort() int { + return 0 +} + +func (listener *SAlbListener) GetScheduler() string { + return "" +} + +func (listener *SAlbListener) GetAclStatus() string { + return "" +} + +func (listener *SAlbListener) GetAclType() string { + return "" +} + +func (listener *SAlbListener) GetAclId() string { + return "" +} + +func (listener *SAlbListener) GetHealthCheck() string { + return "" +} + +func (listener *SAlbListener) GetHealthCheckType() string { + return "" +} + +func (listener *SAlbListener) GetHealthCheckDomain() string { + return "" +} + +func (listener *SAlbListener) GetHealthCheckURI() string { + return "" +} + +func (listener *SAlbListener) GetHealthCheckCode() string { + return "" +} + +func (listener *SAlbListener) GetHealthCheckRise() int { + return 0 +} + +func (listener *SAlbListener) GetHealthCheckFail() int { + return 0 +} + +func (listener *SAlbListener) GetHealthCheckTimeout() int { + return 0 +} + +func (listener *SAlbListener) GetHealthCheckInterval() int { + return 0 +} + +func (listener *SAlbListener) GetHealthCheckReq() string { + return "" +} + +func (listener *SAlbListener) GetHealthCheckExp() string { + return "" +} + +func (listener *SAlbListener) GetStickySession() string { + return "" +} + +func (listener *SAlbListener) GetStickySessionType() string { + return "" +} + +func (listener *SAlbListener) GetStickySessionCookie() string { + return "" +} + +func (listener *SAlbListener) GetStickySessionCookieTimeout() int { + return 0 +} + +func (listener *SAlbListener) XForwardedForEnabled() bool { + return false +} + +func (listener *SAlbListener) GzipEnabled() bool { + return listener.GzipEnabledField +} + +func (listener *SAlbListener) GetCertificateId() string { + for _, cert := range listener.Certificates { + if cert.IsDefault { + return cert.CertificateId + } + } + if len(listener.Certificates) > 0 { + return listener.Certificates[0].CertificateId + } + return "" +} + +func (listener *SAlbListener) GetTLSCipherPolicy() string { + return listener.SecurityPolicyId +} + +func (listener *SAlbListener) HTTP2Enabled() bool { + return listener.Http2Enabled +} + +func (listener *SAlbListener) ChangeCertificate(ctx context.Context, opts *cloudprovider.ListenerCertificateOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SAlbListener) SetAcl(ctx context.Context, opts *cloudprovider.ListenerAclOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SAlbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) { + rules, err := listener.alb.region.GetAlbRules(listener.ListenerId) + if err != nil { + return nil, err + } + iRules := []cloudprovider.ICloudLoadbalancerListenerRule{} + for i := 0; i < len(rules); i++ { + rules[i].albListener = listener + iRules = append(iRules, &rules[i]) + } + return iRules, nil +} + +func (listener *SAlbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) { + listenerRule, err := listener.alb.region.CreateAlbRule(listener.ListenerId, rule) + if err != nil { + return nil, err + } + listenerRule.albListener = listener + return listenerRule, nil +} + +func (listener *SAlbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) { + rule, err := listener.alb.region.GetAlbRule(ruleId) + if err != nil { + return nil, err + } + rule.albListener = listener + return rule, nil +} + +func (listener *SAlbListener) Delete(ctx context.Context) error { + return listener.alb.region.DeleteAlbListener(listener.ListenerId) +} + +func (listener *SAlbListener) Start() error { + return listener.alb.region.StartAlbListener(listener.ListenerId) +} + +func (listener *SAlbListener) Stop() error { + return listener.alb.region.StopAlbListener(listener.ListenerId) +} + +func (listener *SAlbListener) ChangeScheduler(ctx context.Context, opts *cloudprovider.ChangeListenerSchedulerOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SAlbListener) SetHealthCheck(ctx context.Context, opts *cloudprovider.ListenerHealthCheckOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SAlbListener) GetProjectId() string { + return listener.alb.GetProjectId() +} + +func (listener *SAlbListener) GetClientIdleTimeout() int { + return listener.IdleTimeout +} + +func (listener *SAlbListener) GetBackendConnectTimeout() int { + return listener.RequestTimeout +} + +// region methods +func (region *SRegion) GetAlbListeners(loadBalancerId string) ([]SAlbListener, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "MaxResults": "100", + } + + if len(loadBalancerId) > 0 { + params["LoadBalancerIds.1"] = loadBalancerId + } + + listeners := []SAlbListener{} + nextToken := "" + + for { + if nextToken != "" { + params["NextToken"] = nextToken + } + + body, err := region.albRequest("ListListeners", params) + if err != nil { + return nil, err + } + + pageListeners := []SAlbListener{} + err = body.Unmarshal(&pageListeners, "Listeners") + if err != nil { + return nil, err + } + + listeners = append(listeners, pageListeners...) + + nextToken, _ = body.GetString("NextToken") + if nextToken == "" { + break + } + } + + return listeners, nil +} + +func (region *SRegion) GetAlbListener(listenerId string) (*SAlbListener, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + body, err := region.albRequest("GetListenerAttribute", params) + if err != nil { + return nil, err + } + + listener := &SAlbListener{} + err = body.Unmarshal(listener) + if err != nil { + return nil, err + } + + return listener, nil +} + +func (region *SRegion) CreateAlbListener(alb *SAlb, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (*SAlbListener, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "LoadBalancerId": alb.LoadBalancerId, + "ListenerProtocol": listener.ListenerType, + "ListenerPort": fmt.Sprintf("%d", listener.ListenerPort), + } + + if len(listener.Name) > 0 { + params["ListenerDescription"] = listener.Name + } + + body, err := region.albRequest("CreateListener", params) + if err != nil { + return nil, err + } + + listenerId, err := body.GetString("ListenerId") + if err != nil { + return nil, err + } + + return region.GetAlbListener(listenerId) +} + +func (region *SRegion) DeleteAlbListener(listenerId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + _, err := region.albRequest("DeleteListener", params) + return err +} + +func (region *SRegion) StartAlbListener(listenerId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + _, err := region.albRequest("StartListener", params) + return err +} + +func (region *SRegion) StopAlbListener(listenerId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + _, err := region.albRequest("StopListener", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albrule.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albrule.go new file mode 100644 index 0000000000..5f68d7c38e --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albrule.go @@ -0,0 +1,300 @@ +// 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 aliyun + +import ( + "context" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SAlbRule struct { + multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase + AliyunTags + albListener *SAlbListener + + RuleId string `json:"RuleId"` + RuleName string `json:"RuleName"` + RuleStatus string `json:"RuleStatus"` + Priority int `json:"Priority"` + ListenerId string `json:"ListenerId"` + LoadBalancerId string `json:"LoadBalancerId"` + RuleConditions []RuleCondition `json:"RuleConditions"` + RuleActions []AlbRuleAction `json:"RuleActions"` + Direction string `json:"Direction"` + CreateTime string `json:"CreateTime"` + RegionId string `json:"RegionId"` +} + +type RuleCondition struct { + Type string `json:"Type"` + HostConfig HostConfig `json:"HostConfig"` + PathConfig PathConfig `json:"PathConfig"` + MethodConfig MethodConfig `json:"MethodConfig"` + QueryStringConfig QueryStringConfig `json:"QueryStringConfig"` + HeaderConfig HeaderConfig `json:"HeaderConfig"` + CookieConfig CookieConfig `json:"CookieConfig"` + SourceIpConfig SourceIpConfig `json:"SourceIpConfig"` + ResponseHeaderConfig ResponseHeaderConfig `json:"ResponseHeaderConfig"` + ResponseStatusCodeConfig ResponseStatusCodeConfig `json:"ResponseStatusCodeConfig"` +} + +type AlbRuleAction struct { + Type string `json:"Type"` + Order int `json:"Order"` + ForwardGroupConfig ForwardGroupConfig `json:"ForwardGroupConfig"` +} + +type HostConfig struct { + Values []string `json:"Values"` +} + +type PathConfig struct { + Values []string `json:"Values"` +} + +type MethodConfig struct { + Values []string `json:"Values"` +} + +type QueryStringConfig struct { + Values []QueryStringValue `json:"Values"` +} + +type QueryStringValue struct { + Key string `json:"Key"` + Value string `json:"Value"` +} + +type HeaderConfig struct { + Key string `json:"Key"` + Values []string `json:"Values"` +} + +type CookieConfig struct { + Values []CookieValue `json:"Values"` +} + +type CookieValue struct { + Key string `json:"Key"` + Value string `json:"Value"` +} + +type SourceIpConfig struct { + Values []string `json:"Values"` +} + +type ResponseHeaderConfig struct { + Key string `json:"Key"` + Values []string `json:"Values"` +} + +type ResponseStatusCodeConfig struct { + Values []string `json:"Values"` +} + +func (rule *SAlbRule) GetName() string { + return rule.RuleName +} + +func (rule *SAlbRule) GetId() string { + return rule.RuleId +} + +func (rule *SAlbRule) GetGlobalId() string { + return rule.RuleId +} + +func (rule *SAlbRule) GetStatus() string { + switch rule.RuleStatus { + case "Available": + return api.LB_STATUS_ENABLED + case "Configuring": + return api.LB_STATUS_UNKNOWN + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (rule *SAlbRule) IsDefault() bool { + return false +} + +func (rule *SAlbRule) IsEmulated() bool { + return false +} + +func (rule *SAlbRule) Refresh() error { + r, err := rule.albListener.alb.region.GetAlbRule(rule.RuleId) + if err != nil { + return err + } + return jsonutils.Update(rule, r) +} + +func (rule *SAlbRule) GetCondition() string { + return "" +} + +func (rule *SAlbRule) GetDomain() string { + for _, condition := range rule.RuleConditions { + if condition.Type == "Host" && len(condition.HostConfig.Values) > 0 { + return condition.HostConfig.Values[0] + } + } + return "" +} + +func (rule *SAlbRule) GetPath() string { + for _, condition := range rule.RuleConditions { + if condition.Type == "Path" && len(condition.PathConfig.Values) > 0 { + return condition.PathConfig.Values[0] + } + } + return "" +} + +func (rule *SAlbRule) GetProjectId() string { + return rule.albListener.GetProjectId() +} + +func (rule *SAlbRule) GetBackendGroupId() string { + for _, action := range rule.RuleActions { + if action.Type == "ForwardGroup" && len(action.ForwardGroupConfig.ServerGroupTuples) > 0 { + return action.ForwardGroupConfig.ServerGroupTuples[0].ServerGroupId + } + } + return "" +} + +func (rule *SAlbRule) Delete(ctx context.Context) error { + return rule.albListener.alb.region.DeleteAlbRule(rule.RuleId) +} + +// region methods +func (region *SRegion) GetAlbRules(listenerId string) ([]SAlbRule, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerIds.1": listenerId, + } + + body, err := region.albRequest("ListRules", params) + if err != nil { + return nil, err + } + + rules := []SAlbRule{} + err = body.Unmarshal(&rules, "Rules") + if err != nil { + return nil, err + } + + return rules, nil +} + +func (region *SRegion) GetAlbRule(ruleId string) (*SAlbRule, error) { + rules, err := region.GetAlbRules("") + if err != nil { + return nil, err + } + + for _, rule := range rules { + if rule.RuleId == ruleId { + return &rule, nil + } + } + + return nil, cloudprovider.ErrNotFound +} + +func (region *SRegion) CreateAlbRule(listenerId string, rule *cloudprovider.SLoadbalancerListenerRule) (*SAlbRule, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + "RuleName": rule.Name, + "Priority": "100", + } + + // 构建规则条件 + conditions := jsonutils.NewArray() + if len(rule.Domain) > 0 { + condition := jsonutils.Marshal(map[string]interface{}{ + "Type": "Host", + "HostConfig": map[string]interface{}{ + "Values": []string{rule.Domain}, + }, + }) + conditions.Add(condition) + } + + if len(rule.Path) > 0 { + condition := jsonutils.Marshal(map[string]interface{}{ + "Type": "Path", + "PathConfig": map[string]interface{}{ + "Values": []string{rule.Path}, + }, + }) + conditions.Add(condition) + } + + params["RuleConditions"] = conditions.String() + + // 构建规则动作 + actions := jsonutils.NewArray() + if len(rule.BackendGroupId) > 0 { + action := jsonutils.Marshal(map[string]interface{}{ + "Type": "ForwardGroup", + "Order": 1, + "ForwardGroupConfig": map[string]interface{}{ + "ServerGroupTuples": []map[string]interface{}{ + { + "ServerGroupId": rule.BackendGroupId, + "Weight": 100, + }, + }, + }, + }) + actions.Add(action) + } + + params["RuleActions"] = actions.String() + + body, err := region.albRequest("CreateRule", params) + if err != nil { + return nil, err + } + + ruleId, err := body.GetString("RuleId") + if err != nil { + return nil, err + } + + return region.GetAlbRule(ruleId) +} + +func (region *SRegion) DeleteAlbRule(ruleId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "RuleId": ruleId, + } + + _, err := region.albRequest("DeleteRule", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albservergroup.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albservergroup.go new file mode 100644 index 0000000000..723bf112f4 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albservergroup.go @@ -0,0 +1,319 @@ +// 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 aliyun + +import ( + "context" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SAlbServerGroup struct { + multicloud.SResourceBase + AliyunTags + alb *SAlb + + ServerGroupId string `json:"ServerGroupId"` + ServerGroupName string `json:"ServerGroupName"` + ServerGroupType string `json:"ServerGroupType"` + Protocol string `json:"Protocol"` + Scheduler string `json:"Scheduler"` + VpcId string `json:"VpcId"` + ServerGroupStatus string `json:"ServerGroupStatus"` + StickySessionConfig map[string]interface{} `json:"StickySessionConfig"` + HealthCheckConfig map[string]interface{} `json:"HealthCheckConfig"` + UchConfig map[string]interface{} `json:"UchConfig"` + SlowStartConfig map[string]interface{} `json:"SlowStartConfig"` + ConnectionDrainConfig map[string]interface{} `json:"ConnectionDrainConfig"` + RelatedLoadBalancerIds []string `json:"RelatedLoadBalancerIds"` + Servers []AlbServer `json:"Servers"` + CreateTime string `json:"CreateTime"` + RegionId string `json:"RegionId"` + ResourceGroupId string `json:"ResourceGroupId"` +} + +type AlbServer struct { + ServerId string `json:"ServerId"` + ServerType string `json:"ServerType"` + ServerIp string `json:"ServerIp"` + Port int `json:"Port"` + Weight int `json:"Weight"` + Description string `json:"Description"` + Status string `json:"Status"` +} + +func (group *SAlbServerGroup) GetILoadbalancer() cloudprovider.ICloudLoadbalancer { + return group.alb +} + +func (group *SAlbServerGroup) GetLoadbalancerId() string { + return group.alb.GetId() +} + +func (group *SAlbServerGroup) GetProtocolType() string { + return group.Protocol +} + +func (group *SAlbServerGroup) GetScheduler() string { + return group.Scheduler +} + +func (group *SAlbServerGroup) GetHealthCheck() (*cloudprovider.SLoadbalancerHealthCheck, error) { + return nil, nil +} + +func (group *SAlbServerGroup) GetStickySession() (*cloudprovider.SLoadbalancerStickySession, error) { + return nil, nil +} + +func (group *SAlbServerGroup) GetName() string { + return group.ServerGroupName +} + +func (group *SAlbServerGroup) GetId() string { + return group.ServerGroupId +} + +func (group *SAlbServerGroup) GetGlobalId() string { + return group.ServerGroupId +} + +func (group *SAlbServerGroup) GetStatus() string { + switch group.ServerGroupStatus { + case "Available": + return api.LB_STATUS_ENABLED + case "Configuring": + return api.LB_STATUS_UNKNOWN + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (group *SAlbServerGroup) IsDefault() bool { + return false +} + +func (group *SAlbServerGroup) GetType() string { + return api.LB_BACKENDGROUP_TYPE_NORMAL +} + +func (group *SAlbServerGroup) IsEmulated() bool { + return false +} + +func (group *SAlbServerGroup) Refresh() error { + serverGroup, err := group.alb.region.GetAlbServerGroup(group.ServerGroupId) + if err != nil { + return err + } + return jsonutils.Update(group, serverGroup) +} + +func (group *SAlbServerGroup) GetILoadbalancerBackends() ([]cloudprovider.ICloudLoadbalancerBackend, error) { + backends := []cloudprovider.ICloudLoadbalancerBackend{} + for i := 0; i < len(group.Servers); i++ { + server := &SAlbServerGroupServer{ + albServerGroup: group, + AlbServer: group.Servers[i], + } + backends = append(backends, server) + } + return backends, nil +} + +func (group *SAlbServerGroup) GetILoadbalancerBackendById(backendId string) (cloudprovider.ICloudLoadbalancerBackend, error) { + backends, err := group.GetILoadbalancerBackends() + if err != nil { + return nil, err + } + for i := 0; i < len(backends); i++ { + if backends[i].GetGlobalId() == backendId { + return backends[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (group *SAlbServerGroup) Sync(ctx context.Context, group2 *cloudprovider.SLoadbalancerBackendGroup) error { + return nil +} + +func (group *SAlbServerGroup) Delete(ctx context.Context) error { + return group.alb.region.DeleteAlbServerGroup(group.ServerGroupId) +} + +func (group *SAlbServerGroup) AddBackendServer(serverId string, weight, port int) (cloudprovider.ICloudLoadbalancerBackend, error) { + err := group.alb.region.AddServersToAlbServerGroup(group.ServerGroupId, []cloudprovider.SLoadbalancerBackend{ + { + ExternalID: serverId, + Weight: weight, + Port: port, + }, + }) + if err != nil { + return nil, err + } + + return &SAlbServerGroupServer{ + albServerGroup: group, + AlbServer: AlbServer{ + ServerId: serverId, + Weight: weight, + Port: port, + }, + }, nil +} + +func (group *SAlbServerGroup) RemoveBackendServer(serverId string, weight, port int) error { + return group.alb.region.RemoveServersFromAlbServerGroup(group.ServerGroupId, []string{serverId}) +} + +func (group *SAlbServerGroup) GetProjectId() string { + return group.ResourceGroupId +} + +// region methods +func (region *SRegion) GetAlbServerGroups() ([]SAlbServerGroup, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "MaxResults": "100", + } + + groups := []SAlbServerGroup{} + nextToken := "" + + for { + if nextToken != "" { + params["NextToken"] = nextToken + } + + body, err := region.albRequest("ListServerGroups", params) + if err != nil { + return nil, err + } + + pageGroups := []SAlbServerGroup{} + err = body.Unmarshal(&pageGroups, "ServerGroups") + if err != nil { + return nil, err + } + + groups = append(groups, pageGroups...) + + nextToken, _ = body.GetString("NextToken") + if nextToken == "" { + break + } + } + + return groups, nil +} + +func (region *SRegion) GetAlbServerGroup(serverGroupId string) (*SAlbServerGroup, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + body, err := region.albRequest("ListServerGroupServers", params) + if err != nil { + return nil, err + } + + group := &SAlbServerGroup{} + err = body.Unmarshal(group) + if err != nil { + return nil, err + } + + return group, nil +} + +func (region *SRegion) CreateAlbServerGroup(group *cloudprovider.SLoadbalancerBackendGroup, vpcId string) (*SAlbServerGroup, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupName": group.Name, + "ServerGroupType": "Instance", + "VpcId": vpcId, + "Protocol": "HTTP", + "Scheduler": "Wrr", + } + + body, err := region.albRequest("CreateServerGroup", params) + if err != nil { + return nil, err + } + + serverGroupId, err := body.GetString("ServerGroupId") + if err != nil { + return nil, err + } + + return region.GetAlbServerGroup(serverGroupId) +} + +func (region *SRegion) DeleteAlbServerGroup(serverGroupId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + _, err := region.albRequest("DeleteServerGroup", params) + return err +} + +func (region *SRegion) AddServersToAlbServerGroup(serverGroupId string, backends []cloudprovider.SLoadbalancerBackend) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + servers := jsonutils.NewArray() + for _, backend := range backends { + servers.Add(jsonutils.Marshal(map[string]interface{}{ + "ServerId": backend.ExternalID, + "ServerType": "Ecs", + "Port": backend.Port, + "Weight": backend.Weight, + })) + } + params["Servers"] = servers.String() + + _, err := region.albRequest("AddServersToServerGroup", params) + return err +} + +func (region *SRegion) RemoveServersFromAlbServerGroup(serverGroupId string, serverIds []string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + servers := jsonutils.NewArray() + for _, serverId := range serverIds { + servers.Add(jsonutils.Marshal(map[string]interface{}{ + "ServerId": serverId, + "ServerType": "Ecs", + })) + } + params["Servers"] = servers.String() + + _, err := region.albRequest("RemoveServersFromServerGroup", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albservergroupserver.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albservergroupserver.go new file mode 100644 index 0000000000..71ea41814b --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/albservergroupserver.go @@ -0,0 +1,131 @@ +// 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 aliyun + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SAlbServerGroupServer struct { + multicloud.SResourceBase + AliyunTags + albServerGroup *SAlbServerGroup + AlbServer +} + +func (server *SAlbServerGroupServer) GetName() string { + return server.ServerId +} + +func (server *SAlbServerGroupServer) GetId() string { + return fmt.Sprintf("%s/%s/%d", server.albServerGroup.ServerGroupId, server.ServerId, server.Port) +} + +func (server *SAlbServerGroupServer) GetGlobalId() string { + return server.GetId() +} + +func (server *SAlbServerGroupServer) GetStatus() string { + switch server.Status { + case "Available": + return api.LB_STATUS_ENABLED + case "Configuring": + return api.LB_STATUS_UNKNOWN + default: + return api.LB_STATUS_ENABLED + } +} + +func (server *SAlbServerGroupServer) IsEmulated() bool { + return false +} + +func (server *SAlbServerGroupServer) Refresh() error { + serverGroup, err := server.albServerGroup.alb.region.GetAlbServerGroup(server.albServerGroup.ServerGroupId) + if err != nil { + return err + } + + for _, s := range serverGroup.Servers { + if s.ServerId == server.ServerId && s.Port == server.Port { + return jsonutils.Update(server, &s) + } + } + return cloudprovider.ErrNotFound +} + +func (server *SAlbServerGroupServer) GetWeight() int { + return server.Weight +} + +func (server *SAlbServerGroupServer) GetPort() int { + return server.Port +} + +func (server *SAlbServerGroupServer) GetBackendType() string { + return api.LB_BACKEND_GUEST +} + +func (server *SAlbServerGroupServer) GetBackendRole() string { + return api.LB_BACKEND_ROLE_DEFAULT +} + +func (server *SAlbServerGroupServer) GetBackendId() string { + return server.ServerId +} + +func (server *SAlbServerGroupServer) GetIpAddress() string { + return server.ServerIp +} + +func (server *SAlbServerGroupServer) GetProjectId() string { + return server.albServerGroup.GetProjectId() +} + +func (server *SAlbServerGroupServer) SyncConf(ctx context.Context, port, weight int) error { + return server.albServerGroup.alb.region.UpdateAlbServerGroupServerAttribute( + server.albServerGroup.ServerGroupId, + server.ServerId, + port, + weight, + ) +} + +// region methods for ALB server group server operations +func (region *SRegion) UpdateAlbServerGroupServerAttribute(serverGroupId, serverId string, port, weight int) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + servers := jsonutils.NewArray() + servers.Add(jsonutils.Marshal(map[string]interface{}{ + "ServerId": serverId, + "ServerType": "Ecs", + "Port": port, + "Weight": weight, + })) + params["Servers"] = servers.String() + + _, err := region.albRequest("UpdateServerGroupServersAttribute", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/aliyun.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/aliyun.go index 7962cc6f9a..a2a39270a4 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/aliyun.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/aliyun.go @@ -94,6 +94,30 @@ const ( ALIYUN_SERVICE_MONGO_DB = "mongodb" DefaultAssumeRoleName = "ResourceDirectoryAccountAccessRole" + + ALIYUN_API_VERSION_ECS = "2014-05-26" + ALIYUN_API_VERSION_EIP = "2016-04-28" + ALIYUN_API_VERSION_ELB = "2016-04-28" + ALIYUN_API_VERSION_VGW = "2016-04-28" + ALIYUN_API_VERSION_NAS = "2017-06-26" + ALIYUN_API_VERSION_CON = "2018-12-01" + ALIYUN_API_VERSION_VHH = "2019-06-01" + ALIYUN_API_VERSION_BSS = "2017-12-14" + ALIYUN_API_VERSION_FC = "2021-04-06" + ALIYUN_API_VERSION_NLB = "2022-04-30" + ALIYUN_API_VERSION_ALB = "2020-06-16" + + ALIYUN_BSS_BILLING_METHOD_PREPAID = "Subscription" + ALIYUN_BSS_BILLING_METHOD_POSTPAID = "PayAsYouGo" + + ALIYUN_API_INTERVAL = 5 * time.Second + + DEFAULT_SESSION_DURATION_SECONDS = 3600 + + ALIYUN_SERVICE_ALB = "alb" + ALIYUN_SERVICE_NLB = "nlb" + ALIYUN_SERVICE_OSS = "oss" + ALIYUN_SERVICE_EIP = "eip" ) var ( diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlb.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlb.go new file mode 100644 index 0000000000..48a649fab4 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlb.go @@ -0,0 +1,341 @@ +// 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 aliyun + +import ( + "context" + "time" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SNlb struct { + multicloud.SLoadbalancerBase + AliyunTags + region *SRegion + + LoadBalancerId string `json:"LoadBalancerId"` + LoadBalancerName string `json:"LoadBalancerName"` + LoadBalancerStatus string `json:"LoadBalancerStatus"` + LoadBalancerBusinessStatus string `json:"LoadBalancerBusinessStatus"` + LoadBalancerType string `json:"LoadBalancerType"` + AddressType string `json:"AddressType"` + AddressIpVersion string `json:"AddressIpVersion"` + Ipv6AddressType string `json:"Ipv6AddressType"` + VpcId string `json:"VpcId"` + RegionId string `json:"RegionId"` + ZoneId string `json:"ZoneId"` + DNSName string `json:"DNSName"` + NetworkType string `json:"NetworkType"` + InternetChargeType string `json:"InternetChargeType"` + LoadBalancerBillingConfig map[string]interface{} `json:"LoadBalancerBillingConfig"` + ModificationProtectionConfig map[string]interface{} `json:"ModificationProtectionConfig"` + DeletionProtectionConfig map[string]interface{} `json:"DeletionProtectionConfig"` + LoadBalancerOperationLocks []map[string]interface{} `json:"LoadBalancerOperationLocks"` + ZoneMappings []NlbZoneMapping `json:"ZoneMappings"` + CreateTime time.Time `json:"CreateTime"` + ResourceGroupId string `json:"ResourceGroupId"` + CpsEnabled bool `json:"CpsEnabled"` + CrossZoneEnabled bool `json:"CrossZoneEnabled"` + TrafficAffinityEnabled bool `json:"TrafficAffinityEnabled"` + BandwidthPackageId string `json:"BandwidthPackageId"` +} + +type NlbZoneMapping struct { + ZoneId string `json:"ZoneId"` + VSwitchId string `json:"VSwitchId"` + AllocationId string `json:"AllocationId"` + PrivateIPv4Address string `json:"PrivateIPv4Address"` + IPv6Address string `json:"IPv6Address"` + LoadBalancerAddresses []NlbLoadBalancerAddress `json:"LoadBalancerAddresses"` +} + +type NlbLoadBalancerAddress struct { + AllocationId string `json:"AllocationId"` + EipType string `json:"EipType"` + PrivateIPv4Address string `json:"PrivateIPv4Address"` + PrivateIPv6Address string `json:"PrivateIPv6Address"` + PublicIPv4Address string `json:"PublicIPv4Address"` + PublicIPv6Address string `json:"PublicIPv6Address"` +} + +func (nlb *SNlb) GetName() string { + return nlb.LoadBalancerName +} + +func (nlb *SNlb) GetId() string { + return nlb.LoadBalancerId +} + +func (nlb *SNlb) GetGlobalId() string { + return nlb.LoadBalancerId +} + +func (nlb *SNlb) GetStatus() string { + switch nlb.LoadBalancerStatus { + case "Active": + return api.LB_STATUS_ENABLED + case "Provisioning", "Configuring": + return api.LB_STATUS_UNKNOWN + case "Stopped": + return api.LB_STATUS_DISABLED + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (nlb *SNlb) GetAddress() string { + return nlb.DNSName +} + +func (nlb *SNlb) GetAddressType() string { + return nlb.AddressType +} + +func (nlb *SNlb) GetNetworkType() string { + return "vpc" +} + +func (nlb *SNlb) GetNetworkIds() []string { + ret := []string{} + for _, zone := range nlb.ZoneMappings { + if len(zone.VSwitchId) > 0 { + ret = append(ret, zone.VSwitchId) + } + } + return ret +} + +func (nlb *SNlb) GetZoneId() string { + if len(nlb.ZoneMappings) > 0 { + zone, err := nlb.region.getZoneById(nlb.ZoneMappings[0].ZoneId) + if err != nil { + log.Errorf("failed to find zone for nlb %s error: %v", nlb.LoadBalancerName, err) + return "" + } + return zone.GetGlobalId() + } + return "" +} + +func (nlb *SNlb) GetZone1Id() string { + if len(nlb.ZoneMappings) > 1 { + zone, err := nlb.region.getZoneById(nlb.ZoneMappings[1].ZoneId) + if err != nil { + log.Errorf("failed to find zone for nlb %s error: %v", nlb.LoadBalancerName, err) + return "" + } + return zone.GetGlobalId() + } + return "" +} + +func (nlb *SNlb) IsEmulated() bool { + return false +} + +func (nlb *SNlb) GetVpcId() string { + return nlb.VpcId +} + +func (nlb *SNlb) Refresh() error { + loadbalancer, err := nlb.region.GetNlbDetail(nlb.LoadBalancerId) + if err != nil { + return err + } + return jsonutils.Update(nlb, loadbalancer) +} + +func (nlb *SNlb) Delete(ctx context.Context) error { + return nlb.region.DeleteNlb(nlb.LoadBalancerId) +} + +func (nlb *SNlb) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { + groups, err := nlb.region.GetNlbServerGroups() + if err != nil { + return nil, err + } + igroups := []cloudprovider.ICloudLoadbalancerBackendGroup{} + for i := 0; i < len(groups); i++ { + // 过滤出属于当前负载均衡器的服务器组 + for _, lbId := range groups[i].RelatedLoadBalancerIds { + if lbId == nlb.LoadBalancerId { + groups[i].nlb = nlb + igroups = append(igroups, &groups[i]) + break + } + } + } + return igroups, nil +} + +func (nlb *SNlb) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { + serverGroup, err := nlb.region.CreateNlbServerGroup(group, nlb.VpcId) + if err != nil { + return nil, err + } + serverGroup.nlb = nlb + return serverGroup, nil +} + +func (nlb *SNlb) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { + groups, err := nlb.GetILoadBalancerBackendGroups() + if err != nil { + return nil, err + } + for i := 0; i < len(groups); i++ { + if groups[i].GetGlobalId() == groupId { + return groups[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (nlb *SNlb) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (cloudprovider.ICloudLoadbalancerListener, error) { + return nlb.region.CreateNlbListener(nlb, listener) +} + +func (nlb *SNlb) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) { + listeners, err := nlb.GetILoadBalancerListeners() + if err != nil { + return nil, err + } + for i := 0; i < len(listeners); i++ { + if listeners[i].GetGlobalId() == listenerId { + return listeners[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (nlb *SNlb) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) { + listeners, err := nlb.region.GetNlbListeners(nlb.LoadBalancerId) + if err != nil { + return nil, err + } + ilisteners := []cloudprovider.ICloudLoadbalancerListener{} + for i := 0; i < len(listeners); i++ { + listeners[i].nlb = nlb + ilisteners = append(ilisteners, &listeners[i]) + } + return ilisteners, nil +} + +func (nlb *SNlb) GetChargeType() string { + return api.LB_CHARGE_TYPE_BY_TRAFFIC +} + +func (nlb *SNlb) GetCreatedAt() time.Time { + return nlb.CreateTime +} + +func (nlb *SNlb) GetEgressMbps() int { + return 0 +} + +func (nlb *SNlb) GetIEIPs() ([]cloudprovider.ICloudEIP, error) { + return []cloudprovider.ICloudEIP{}, nil +} + +func (nlb *SNlb) Start() error { + return cloudprovider.ErrNotSupported +} + +func (nlb *SNlb) Stop() error { + return cloudprovider.ErrNotSupported +} + +func (nlb *SNlb) GetLoadbalancerSpec() string { + return nlb.LoadBalancerType +} + +func (nlb *SNlb) GetProjectId() string { + return nlb.ResourceGroupId +} + +// region methods +func (region *SRegion) GetNlbs() ([]SNlb, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "MaxResults": "100", + } + + nlbs := []SNlb{} + nextToken := "" + + for { + if nextToken != "" { + params["NextToken"] = nextToken + } + + body, err := region.nlbRequest("ListLoadBalancers", params) + if err != nil { + return nil, err + } + + pageNlbs := []SNlb{} + err = body.Unmarshal(&pageNlbs, "LoadBalancers") + if err != nil { + return nil, err + } + + for i := 0; i < len(pageNlbs); i++ { + pageNlbs[i].region = region + } + nlbs = append(nlbs, pageNlbs...) + + nextToken, _ = body.GetString("NextToken") + if nextToken == "" { + break + } + } + + return nlbs, nil +} + +func (region *SRegion) GetNlbDetail(nlbId string) (*SNlb, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "LoadBalancerId": nlbId, + } + + body, err := region.nlbRequest("GetLoadBalancerAttribute", params) + if err != nil { + return nil, err + } + + nlb := &SNlb{region: region} + err = body.Unmarshal(nlb) + if err != nil { + return nil, err + } + + return nlb, nil +} + +func (region *SRegion) DeleteNlb(nlbId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "LoadBalancerId": nlbId, + } + + _, err := region.nlbRequest("DeleteLoadBalancer", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlblistener.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlblistener.go new file mode 100644 index 0000000000..a059ae550d --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlblistener.go @@ -0,0 +1,392 @@ +// 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 aliyun + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SNlbListener struct { + multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase + AliyunTags + nlb *SNlb + + ListenerId string `json:"ListenerId"` + ListenerDescription string `json:"ListenerDescription"` + ListenerProtocol string `json:"ListenerProtocol"` + ListenerPort int `json:"ListenerPort"` + ListenerStatus string `json:"ListenerStatus"` + LoadBalancerId string `json:"LoadBalancerId"` + ServerGroupId string `json:"ServerGroupId"` + IdleTimeout int `json:"IdleTimeout"` + SecurityPolicyId string `json:"SecurityPolicyId"` + CaEnabled bool `json:"CaEnabled"` + CaCertificateIds []string `json:"CaCertificateIds"` + CertificateIds []string `json:"CertificateIds"` + Cps int `json:"Cps"` + Mss int `json:"Mss"` + ProxyProtocolEnabled bool `json:"ProxyProtocolEnabled"` + SecSensorEnabled bool `json:"SecSensorEnabled"` + ProxyProtocolV2Config map[string]interface{} `json:"ProxyProtocolV2Config"` + AlpnEnabled bool `json:"AlpnEnabled"` + AlpnPolicy string `json:"AlpnPolicy"` + StartPort string `json:"StartPort"` + EndPort string `json:"EndPort"` + RegionId string `json:"RegionId"` +} + +func (listener *SNlbListener) GetName() string { + if len(listener.ListenerDescription) > 0 { + return listener.ListenerDescription + } + return fmt.Sprintf("%s:%d", listener.ListenerProtocol, listener.ListenerPort) +} + +func (listener *SNlbListener) GetId() string { + return listener.ListenerId +} + +func (listener *SNlbListener) GetGlobalId() string { + return listener.ListenerId +} + +func (listener *SNlbListener) GetStatus() string { + switch listener.ListenerStatus { + case "Running": + return api.LB_STATUS_ENABLED + case "Stopped": + return api.LB_STATUS_DISABLED + case "Provisioning", "Configuring": + return api.LB_STATUS_UNKNOWN + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (listener *SNlbListener) IsEmulated() bool { + return false +} + +func (listener *SNlbListener) GetEgressMbps() int { + return 0 +} + +func (listener *SNlbListener) Refresh() error { + lis, err := listener.nlb.region.GetNlbListener(listener.ListenerId) + if err != nil { + return err + } + return jsonutils.Update(listener, lis) +} + +func (listener *SNlbListener) GetListenerType() string { + switch listener.ListenerProtocol { + case "TCP": + return api.LB_LISTENER_TYPE_TCP + case "UDP": + return api.LB_LISTENER_TYPE_UDP + case "TCPSSL": + return "TCPSSL" + default: + return listener.ListenerProtocol + } +} + +func (listener *SNlbListener) GetListenerPort() int { + return listener.ListenerPort +} + +func (listener *SNlbListener) GetBackendGroupId() string { + return listener.ServerGroupId +} + +func (listener *SNlbListener) GetBackendServerPort() int { + return 0 +} + +func (listener *SNlbListener) GetScheduler() string { + return "" +} + +func (listener *SNlbListener) GetAclStatus() string { + return "" +} + +func (listener *SNlbListener) GetAclType() string { + return "" +} + +func (listener *SNlbListener) GetAclId() string { + return "" +} + +func (listener *SNlbListener) GetHealthCheck() string { + return "" +} + +func (listener *SNlbListener) GetHealthCheckType() string { + return "" +} + +func (listener *SNlbListener) GetHealthCheckDomain() string { + return "" +} + +func (listener *SNlbListener) GetHealthCheckURI() string { + return "" +} + +func (listener *SNlbListener) GetHealthCheckCode() string { + return "" +} + +func (listener *SNlbListener) GetHealthCheckRise() int { + return 0 +} + +func (listener *SNlbListener) GetHealthCheckFail() int { + return 0 +} + +func (listener *SNlbListener) GetHealthCheckTimeout() int { + return 0 +} + +func (listener *SNlbListener) GetHealthCheckInterval() int { + return 0 +} + +func (listener *SNlbListener) GetHealthCheckReq() string { + return "" +} + +func (listener *SNlbListener) GetHealthCheckExp() string { + return "" +} + +func (listener *SNlbListener) GetStickySession() string { + return "" +} + +func (listener *SNlbListener) GetStickySessionType() string { + return "" +} + +func (listener *SNlbListener) GetStickySessionCookie() string { + return "" +} + +func (listener *SNlbListener) GetStickySessionCookieTimeout() int { + return 0 +} + +func (listener *SNlbListener) XForwardedForEnabled() bool { + return false +} + +func (listener *SNlbListener) GzipEnabled() bool { + return false +} + +func (listener *SNlbListener) GetCertificateId() string { + if len(listener.CertificateIds) > 0 { + return listener.CertificateIds[0] + } + return "" +} + +func (listener *SNlbListener) GetTLSCipherPolicy() string { + return listener.SecurityPolicyId +} + +func (listener *SNlbListener) HTTP2Enabled() bool { + return false +} + +func (listener *SNlbListener) ChangeCertificate(ctx context.Context, opts *cloudprovider.ListenerCertificateOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SNlbListener) SetAcl(ctx context.Context, opts *cloudprovider.ListenerAclOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SNlbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) { + return []cloudprovider.ICloudLoadbalancerListenerRule{}, nil +} + +func (listener *SNlbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) { + return nil, cloudprovider.ErrNotSupported +} + +func (listener *SNlbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) { + return nil, cloudprovider.ErrNotFound +} + +func (listener *SNlbListener) Delete(ctx context.Context) error { + return listener.nlb.region.DeleteNlbListener(listener.ListenerId) +} + +func (listener *SNlbListener) Start() error { + return listener.nlb.region.StartNlbListener(listener.ListenerId) +} + +func (listener *SNlbListener) Stop() error { + return listener.nlb.region.StopNlbListener(listener.ListenerId) +} + +func (listener *SNlbListener) ChangeScheduler(ctx context.Context, opts *cloudprovider.ChangeListenerSchedulerOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SNlbListener) SetHealthCheck(ctx context.Context, opts *cloudprovider.ListenerHealthCheckOptions) error { + return cloudprovider.ErrNotSupported +} + +func (listener *SNlbListener) GetProjectId() string { + return listener.nlb.GetProjectId() +} + +func (listener *SNlbListener) GetClientIdleTimeout() int { + return listener.IdleTimeout +} + +func (listener *SNlbListener) GetBackendConnectTimeout() int { + return 0 +} + +// region methods +func (region *SRegion) GetNlbListeners(loadBalancerId string) ([]SNlbListener, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "MaxResults": "100", + } + + if len(loadBalancerId) > 0 { + params["LoadBalancerIds.1"] = loadBalancerId + } + + listeners := []SNlbListener{} + nextToken := "" + + for { + if nextToken != "" { + params["NextToken"] = nextToken + } + + body, err := region.nlbRequest("ListListeners", params) + if err != nil { + return nil, err + } + + pageListeners := []SNlbListener{} + err = body.Unmarshal(&pageListeners, "Listeners") + if err != nil { + return nil, err + } + + listeners = append(listeners, pageListeners...) + + nextToken, _ = body.GetString("NextToken") + if nextToken == "" { + break + } + } + + return listeners, nil +} + +func (region *SRegion) GetNlbListener(listenerId string) (*SNlbListener, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + body, err := region.nlbRequest("GetListenerAttribute", params) + if err != nil { + return nil, err + } + + listener := &SNlbListener{} + err = body.Unmarshal(listener) + if err != nil { + return nil, err + } + + return listener, nil +} + +func (region *SRegion) CreateNlbListener(nlb *SNlb, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (*SNlbListener, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "LoadBalancerId": nlb.LoadBalancerId, + "ListenerProtocol": listener.ListenerType, + "ListenerPort": fmt.Sprintf("%d", listener.ListenerPort), + } + + if len(listener.Name) > 0 { + params["ListenerDescription"] = listener.Name + } + + body, err := region.nlbRequest("CreateListener", params) + if err != nil { + return nil, err + } + + listenerId, err := body.GetString("ListenerId") + if err != nil { + return nil, err + } + + return region.GetNlbListener(listenerId) +} + +func (region *SRegion) DeleteNlbListener(listenerId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + _, err := region.nlbRequest("DeleteListener", params) + return err +} + +func (region *SRegion) StartNlbListener(listenerId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + _, err := region.nlbRequest("StartListener", params) + return err +} + +func (region *SRegion) StopNlbListener(listenerId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ListenerId": listenerId, + } + + _, err := region.nlbRequest("StopListener", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlbservergroup.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlbservergroup.go new file mode 100644 index 0000000000..1ea287b5f9 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlbservergroup.go @@ -0,0 +1,323 @@ +// 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 aliyun + +import ( + "context" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SNlbServerGroup struct { + multicloud.SResourceBase + AliyunTags + nlb *SNlb + + ServerGroupId string `json:"ServerGroupId"` + ServerGroupName string `json:"ServerGroupName"` + ServerGroupType string `json:"ServerGroupType"` + Protocol string `json:"Protocol"` + Scheduler string `json:"Scheduler"` + VpcId string `json:"VpcId"` + ServerGroupStatus string `json:"ServerGroupStatus"` + AddressIPVersion string `json:"AddressIPVersion"` + AnyPortEnabled bool `json:"AnyPortEnabled"` + ConnectionDrainEnabled bool `json:"ConnectionDrainEnabled"` + ConnectionDrainTimeout int `json:"ConnectionDrainTimeout"` + PreserveClientIpEnabled bool `json:"PreserveClientIpEnabled"` + PersistenceEnabled bool `json:"PersistenceEnabled"` + PersistenceTimeout int `json:"PersistenceTimeout"` + HealthCheckConfig map[string]interface{} `json:"HealthCheckConfig"` + RelatedLoadBalancerIds []string `json:"RelatedLoadBalancerIds"` + Servers []NlbServer `json:"Servers"` + CreateTime string `json:"CreateTime"` + RegionId string `json:"RegionId"` + ResourceGroupId string `json:"ResourceGroupId"` +} + +type NlbServer struct { + ServerId string `json:"ServerId"` + ServerType string `json:"ServerType"` + ServerIp string `json:"ServerIp"` + Port int `json:"Port"` + Weight int `json:"Weight"` + Description string `json:"Description"` + Status string `json:"Status"` + ZoneId string `json:"ZoneId"` +} + +func (group *SNlbServerGroup) GetILoadbalancer() cloudprovider.ICloudLoadbalancer { + return group.nlb +} + +func (group *SNlbServerGroup) GetLoadbalancerId() string { + return group.nlb.GetId() +} + +func (group *SNlbServerGroup) GetProtocolType() string { + return group.Protocol +} + +func (group *SNlbServerGroup) GetScheduler() string { + return group.Scheduler +} + +func (group *SNlbServerGroup) GetHealthCheck() (*cloudprovider.SLoadbalancerHealthCheck, error) { + return nil, nil +} + +func (group *SNlbServerGroup) GetStickySession() (*cloudprovider.SLoadbalancerStickySession, error) { + return nil, nil +} + +func (group *SNlbServerGroup) GetName() string { + return group.ServerGroupName +} + +func (group *SNlbServerGroup) GetId() string { + return group.ServerGroupId +} + +func (group *SNlbServerGroup) GetGlobalId() string { + return group.ServerGroupId +} + +func (group *SNlbServerGroup) GetStatus() string { + switch group.ServerGroupStatus { + case "Available": + return api.LB_STATUS_ENABLED + case "Configuring": + return api.LB_STATUS_UNKNOWN + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (group *SNlbServerGroup) IsDefault() bool { + return false +} + +func (group *SNlbServerGroup) GetType() string { + return api.LB_BACKENDGROUP_TYPE_NORMAL +} + +func (group *SNlbServerGroup) IsEmulated() bool { + return false +} + +func (group *SNlbServerGroup) Refresh() error { + serverGroup, err := group.nlb.region.GetNlbServerGroup(group.ServerGroupId) + if err != nil { + return err + } + return jsonutils.Update(group, serverGroup) +} + +func (group *SNlbServerGroup) GetILoadbalancerBackends() ([]cloudprovider.ICloudLoadbalancerBackend, error) { + backends := []cloudprovider.ICloudLoadbalancerBackend{} + for i := 0; i < len(group.Servers); i++ { + server := &SNlbServerGroupServer{ + nlbServerGroup: group, + NlbServer: group.Servers[i], + } + backends = append(backends, server) + } + return backends, nil +} + +func (group *SNlbServerGroup) GetILoadbalancerBackendById(backendId string) (cloudprovider.ICloudLoadbalancerBackend, error) { + backends, err := group.GetILoadbalancerBackends() + if err != nil { + return nil, err + } + for i := 0; i < len(backends); i++ { + if backends[i].GetGlobalId() == backendId { + return backends[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (group *SNlbServerGroup) Sync(ctx context.Context, group2 *cloudprovider.SLoadbalancerBackendGroup) error { + return nil +} + +func (group *SNlbServerGroup) Delete(ctx context.Context) error { + return group.nlb.region.DeleteNlbServerGroup(group.ServerGroupId) +} + +func (group *SNlbServerGroup) AddBackendServer(serverId string, weight, port int) (cloudprovider.ICloudLoadbalancerBackend, error) { + err := group.nlb.region.AddServersToNlbServerGroup(group.ServerGroupId, []cloudprovider.SLoadbalancerBackend{ + { + ExternalID: serverId, + Weight: weight, + Port: port, + }, + }) + if err != nil { + return nil, err + } + + return &SNlbServerGroupServer{ + nlbServerGroup: group, + NlbServer: NlbServer{ + ServerId: serverId, + Weight: weight, + Port: port, + }, + }, nil +} + +func (group *SNlbServerGroup) RemoveBackendServer(serverId string, weight, port int) error { + return group.nlb.region.RemoveServersFromNlbServerGroup(group.ServerGroupId, []string{serverId}) +} + +func (group *SNlbServerGroup) GetProjectId() string { + return group.ResourceGroupId +} + +// region methods +func (region *SRegion) GetNlbServerGroups() ([]SNlbServerGroup, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "MaxResults": "100", + } + + groups := []SNlbServerGroup{} + nextToken := "" + + for { + if nextToken != "" { + params["NextToken"] = nextToken + } + + body, err := region.nlbRequest("ListServerGroups", params) + if err != nil { + return nil, err + } + + pageGroups := []SNlbServerGroup{} + err = body.Unmarshal(&pageGroups, "ServerGroups") + if err != nil { + return nil, err + } + + groups = append(groups, pageGroups...) + + nextToken, _ = body.GetString("NextToken") + if nextToken == "" { + break + } + } + + return groups, nil +} + +func (region *SRegion) GetNlbServerGroup(serverGroupId string) (*SNlbServerGroup, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + body, err := region.nlbRequest("ListServerGroupServers", params) + if err != nil { + return nil, err + } + + group := &SNlbServerGroup{} + err = body.Unmarshal(group) + if err != nil { + return nil, err + } + + return group, nil +} + +func (region *SRegion) CreateNlbServerGroup(group *cloudprovider.SLoadbalancerBackendGroup, vpcId string) (*SNlbServerGroup, error) { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupName": group.Name, + "ServerGroupType": "Instance", + "VpcId": vpcId, + "Protocol": "TCP", + "Scheduler": "Wrr", + } + + body, err := region.nlbRequest("CreateServerGroup", params) + if err != nil { + return nil, err + } + + serverGroupId, err := body.GetString("ServerGroupId") + if err != nil { + return nil, err + } + + return region.GetNlbServerGroup(serverGroupId) +} + +func (region *SRegion) DeleteNlbServerGroup(serverGroupId string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + _, err := region.nlbRequest("DeleteServerGroup", params) + return err +} + +func (region *SRegion) AddServersToNlbServerGroup(serverGroupId string, backends []cloudprovider.SLoadbalancerBackend) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + servers := jsonutils.NewArray() + for _, backend := range backends { + servers.Add(jsonutils.Marshal(map[string]interface{}{ + "ServerId": backend.ExternalID, + "ServerType": "Ecs", + "Port": backend.Port, + "Weight": backend.Weight, + })) + } + params["Servers"] = servers.String() + + _, err := region.nlbRequest("AddServersToServerGroup", params) + return err +} + +func (region *SRegion) RemoveServersFromNlbServerGroup(serverGroupId string, serverIds []string) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + servers := jsonutils.NewArray() + for _, serverId := range serverIds { + servers.Add(jsonutils.Marshal(map[string]interface{}{ + "ServerId": serverId, + "ServerType": "Ecs", + })) + } + params["Servers"] = servers.String() + + _, err := region.nlbRequest("RemoveServersFromServerGroup", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlbservergroupserver.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlbservergroupserver.go new file mode 100644 index 0000000000..7d209963d7 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/nlbservergroupserver.go @@ -0,0 +1,131 @@ +// 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 aliyun + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/cloudmux/pkg/apis/compute" + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/cloudmux/pkg/multicloud" +) + +type SNlbServerGroupServer struct { + multicloud.SResourceBase + AliyunTags + nlbServerGroup *SNlbServerGroup + NlbServer +} + +func (server *SNlbServerGroupServer) GetName() string { + return server.ServerId +} + +func (server *SNlbServerGroupServer) GetId() string { + return fmt.Sprintf("%s/%s/%d", server.nlbServerGroup.ServerGroupId, server.ServerId, server.Port) +} + +func (server *SNlbServerGroupServer) GetGlobalId() string { + return server.GetId() +} + +func (server *SNlbServerGroupServer) GetStatus() string { + switch server.Status { + case "Available": + return api.LB_STATUS_ENABLED + case "Configuring": + return api.LB_STATUS_UNKNOWN + default: + return api.LB_STATUS_ENABLED + } +} + +func (server *SNlbServerGroupServer) IsEmulated() bool { + return false +} + +func (server *SNlbServerGroupServer) Refresh() error { + serverGroup, err := server.nlbServerGroup.nlb.region.GetNlbServerGroup(server.nlbServerGroup.ServerGroupId) + if err != nil { + return err + } + + for _, s := range serverGroup.Servers { + if s.ServerId == server.ServerId && s.Port == server.Port { + return jsonutils.Update(server, &s) + } + } + return cloudprovider.ErrNotFound +} + +func (server *SNlbServerGroupServer) GetWeight() int { + return server.Weight +} + +func (server *SNlbServerGroupServer) GetPort() int { + return server.Port +} + +func (server *SNlbServerGroupServer) GetBackendType() string { + return api.LB_BACKEND_GUEST +} + +func (server *SNlbServerGroupServer) GetBackendRole() string { + return api.LB_BACKEND_ROLE_DEFAULT +} + +func (server *SNlbServerGroupServer) GetBackendId() string { + return server.ServerId +} + +func (server *SNlbServerGroupServer) GetIpAddress() string { + return server.ServerIp +} + +func (server *SNlbServerGroupServer) GetProjectId() string { + return server.nlbServerGroup.GetProjectId() +} + +func (server *SNlbServerGroupServer) SyncConf(ctx context.Context, port, weight int) error { + return server.nlbServerGroup.nlb.region.UpdateNlbServerGroupServerAttribute( + server.nlbServerGroup.ServerGroupId, + server.ServerId, + port, + weight, + ) +} + +// region methods for NLB server group server operations +func (region *SRegion) UpdateNlbServerGroupServerAttribute(serverGroupId, serverId string, port, weight int) error { + params := map[string]string{ + "RegionId": region.RegionId, + "ServerGroupId": serverGroupId, + } + + servers := jsonutils.NewArray() + servers.Add(jsonutils.Marshal(map[string]interface{}{ + "ServerId": serverId, + "ServerType": "Ecs", + "Port": port, + "Weight": weight, + })) + params["Servers"] = servers.String() + + _, err := region.nlbRequest("UpdateServerGroupServersAttribute", params) + return err +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/region.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/region.go index aa666f15f8..5e73e5e79b 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/region.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/region.go @@ -319,6 +319,26 @@ func (self *SRegion) _lbRequest(client *sdk.Client, apiName string, domain strin return jsonRequest(client, domain, ALIYUN_API_VERSION_LB, apiName, params, self.client.debug) } +func (self *SRegion) albRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { + client, err := self.getSdkClient() + if err != nil { + return nil, err + } + params = self.client.SetResourceGropuId(params) + domain := fmt.Sprintf("alb.%s.aliyuncs.com", self.RegionId) + return jsonRequest(client, domain, ALIYUN_API_VERSION_ALB, apiName, params, self.client.debug) +} + +func (self *SRegion) nlbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { + client, err := self.getSdkClient() + if err != nil { + return nil, err + } + params = self.client.SetResourceGropuId(params) + domain := fmt.Sprintf("nlb.%s.aliyuncs.com", self.RegionId) + return jsonRequest(client, domain, ALIYUN_API_VERSION_NLB, apiName, params, self.client.debug) +} + // /////////////////////////////////////////////////////////////////////////// func (self *SRegion) GetId() string { return self.RegionId @@ -910,6 +930,27 @@ func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, lbs[i].region = region ilbs = append(ilbs, &lbs[i]) } + + // 获取ALB实例 + albs, err := region.GetAlbs() + if err != nil { + return nil, err + } + for i := 0; i < len(albs); i++ { + albs[i].region = region + ilbs = append(ilbs, &albs[i]) + } + + // 获取NLB实例 + nlbs, err := region.GetNlbs() + if err != nil { + return nil, err + } + for i := 0; i < len(nlbs); i++ { + nlbs[i].region = region + ilbs = append(ilbs, &nlbs[i]) + } + return ilbs, nil } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/tag_base.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/tag_base.go index c265a476c2..46b6c9a959 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/tag_base.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/tag_base.go @@ -15,6 +15,8 @@ package aliyun import ( + "encoding/json" + "yunion.io/x/pkg/errors" "yunion.io/x/cloudmux/pkg/cloudprovider" @@ -22,12 +24,12 @@ import ( ) type AliyunTags struct { - Tags struct { - Tag []multicloud.STag + // 使用RawMessage来延迟解析,兼容两种格式 + TagsRaw json.RawMessage `json:"Tags"` - // Kafka - TagVO []multicloud.STag `json:"TagVO" yunion-deprecated-by:"Tag"` - } + // 缓存解析后的标签 + parsedTags []multicloud.STag + parsed bool } var sysTags = []string{ @@ -41,9 +43,52 @@ var sysTags = []string{ "eas_resource_group_name", "eas_tenant_name", "managedby", } +// 解析标签数据,兼容两种格式 +func (self *AliyunTags) parseTags() error { + if self.parsed || len(self.TagsRaw) == 0 { + return nil + } + + // 先尝试解析为直接数组格式(ALB格式) + var directTags []multicloud.STag + if err := json.Unmarshal(self.TagsRaw, &directTags); err == nil { + self.parsedTags = directTags + self.parsed = true + return nil + } + + // 如果失败,尝试解析为嵌套格式(传统格式) + var nested struct { + Tag []multicloud.STag + TagVO []multicloud.STag `json:"TagVO"` + } + + if err := json.Unmarshal(self.TagsRaw, &nested); err == nil { + // 合并Tag和TagVO + var allTags []multicloud.STag + allTags = append(allTags, nested.Tag...) + allTags = append(allTags, nested.TagVO...) + self.parsedTags = allTags + self.parsed = true + return nil + } + + return errors.Errorf("failed to parse tags") +} + +// 获取所有标签 +func (self *AliyunTags) getAllTags() []multicloud.STag { + self.parseTags() + return self.parsedTags +} + func (self *AliyunTags) GetTags() (map[string]string, error) { ret := map[string]string{} - for _, tag := range self.Tags.Tag { + + // 获取所有标签(兼容两种格式) + allTags := self.getAllTags() + + for _, tag := range allTags { if tag.IsSysTagPrefix(sysTags) { continue } @@ -59,7 +104,11 @@ func (self *AliyunTags) GetTags() (map[string]string, error) { func (self *AliyunTags) GetSysTags() map[string]string { ret := map[string]string{} - for _, tag := range self.Tags.Tag { + + // 获取所有标签(兼容两种格式) + allTags := self.getAllTags() + + for _, tag := range allTags { if tag.IsSysTagPrefix(sysTags) { if len(tag.TagKey) > 0 { ret[tag.TagKey] = tag.TagValue