diff --git a/pkg/compute/models/loadbalancer_const.go b/pkg/compute/models/loadbalancer_const.go index 5f75879e0d..e436637da5 100644 --- a/pkg/compute/models/loadbalancer_const.go +++ b/pkg/compute/models/loadbalancer_const.go @@ -195,6 +195,7 @@ const ( ) var LB_HEALTH_CHECK_HTTP_CODES = validators.NewChoices( + LB_HEALTH_CHECK_HTTP_CODE_1xx, LB_HEALTH_CHECK_HTTP_CODE_2xx, LB_HEALTH_CHECK_HTTP_CODE_3xx, LB_HEALTH_CHECK_HTTP_CODE_4xx, diff --git a/pkg/compute/models/loadbalancers.go b/pkg/compute/models/loadbalancers.go index da6ec63157..51adf578d8 100644 --- a/pkg/compute/models/loadbalancers.go +++ b/pkg/compute/models/loadbalancers.go @@ -39,6 +39,7 @@ func init() { const ( LB_CHARGE_TYPE_BY_TRAFFIC = "traffic" LB_CHARGE_TYPE_BY_BANDWIDTH = "bandwidth" + LB_CHARGE_TYPE_BY_HOUR = "hour" ) // TODO build errors on pkg/httperrors/errors.go diff --git a/pkg/util/aliyun/loadbalancer.go b/pkg/util/aliyun/loadbalancer.go index b1a0b974bd..e65fac4134 100644 --- a/pkg/util/aliyun/loadbalancer.go +++ b/pkg/util/aliyun/loadbalancer.go @@ -237,9 +237,9 @@ func (lb *SLoadbalancer) GetLoadbalancerSpec() string { func (lb *SLoadbalancer) GetChargeType() string { switch lb.InternetChargeType { case "paybybandwidth": - return "bandwidth" + return models.LB_CHARGE_TYPE_BY_BANDWIDTH case "paybytraffic": - return "traffic" + return models.LB_CHARGE_TYPE_BY_TRAFFIC } return "unknown" } diff --git a/pkg/util/qcloud/loadbalancer.go b/pkg/util/qcloud/loadbalancer.go index 66056cd69b..c4cf26b506 100755 --- a/pkg/util/qcloud/loadbalancer.go +++ b/pkg/util/qcloud/loadbalancer.go @@ -57,9 +57,8 @@ func (self *SLoadbalancer) GetLoadbalancerSpec() string { return "" } -// todo: 实际是按小时计费 func (self *SLoadbalancer) GetChargeType() string { - return "traffic" + return models.LB_CHARGE_TYPE_BY_HOUR } // https://cloud.tencent.com/document/product/214/30689 @@ -135,45 +134,24 @@ CertCaId String 否 客户端证书的 ID,如果 SSLMode=mutual,监听器如 */ func (self *SLoadbalancer) CreateILoadBalancerListener(listener *cloudprovider.SLoadbalancerListener) (cloudprovider.ICloudLoadbalancerListener, error) { sniSwitch := 0 - var hc healthCheck - if listener.HealthCheck == models.LB_HEALTH_CHECK_ENABLE { - hc := healthCheck{ - HTTPCheckDomain: listener.HealthCheckDomain, - HealthSwitch: 1, - HTTPCheckPath: listener.HealthCheckURI, - HTTPCheckMethod: listener.HealthCheck, - UnHealthNum: listener.HealthCheckFail, - IntervalTime: listener.HealthCheckInterval, - HealthNum: listener.HealthCheckRise, - TimeOut: listener.HealthCheckTimeout, - } - - httpCode := onecloudHealthCodeToQcloud(listener.HealthCheckHttpCode) - if httpCode > 0 { - hc.HTTPCode = httpCode - } - } - - cert := certificate{ - SSLMode: "UNIDIRECTIONAL", - CERTCAID: listener.CertificateID, - CERTID: "", - } + hc := getHealthCheck(listener) + cert := getCertificate(listener) listenId, err := self.region.CreateLoadbalancerListener(self.GetId(), listener.Name, - listener.ListenerType, + getProtocol(listener), listener.ListenerPort, - &listener.Scheduler, + getScheduler(listener), &listener.StickySessionCookieTimeout, &sniSwitch, - &hc, - &cert) + hc, + cert) if err != nil { return nil, err } + time.Sleep(3*time.Second) return self.GetILoadBalancerListenerById(listenId) } @@ -273,7 +251,7 @@ func (self *SLoadbalancer) GetZoneId() string { } func (self *SLoadbalancer) GetLoadbalancerListeners(protocal string) ([]SLBListener, error) { - listeners, err := self.region.GetLoadbalancerListeners(self.GetId(), self.Forward, "") + listeners, err := self.region.GetLoadbalancerListeners(self.GetId(), self.Forward, protocal) if err != nil { return nil, err } @@ -446,25 +424,8 @@ func (self *SRegion) CreateLoadbalancerListener(lbid, name, protocol string, por params["Scheduler"] = *scheduler } - if healthCheck != nil { - params["HealthCheck.HealthSwitch"] = strconv.Itoa(healthCheck.HealthSwitch) - params["HealthCheck.TimeOut"] = strconv.Itoa(healthCheck.TimeOut) - params["HealthCheck.IntervalTime"] = strconv.Itoa(healthCheck.IntervalTime) - params["HealthCheck.HealthNum"] = strconv.Itoa(healthCheck.HealthNum) - params["HealthCheck.UnHealthNum"] = strconv.Itoa(healthCheck.UnHealthNum) - params["HealthCheck.HttpCode"] = strconv.Itoa(healthCheck.HTTPCode) - params["HealthCheck.HttpCheckPath"] = healthCheck.HTTPCheckPath - params["HealthCheck.HttpCheckDomain"] = healthCheck.HTTPCheckDomain - params["HealthCheck.HttpCheckMethod"] = healthCheck.HTTPCheckMethod - } - - if cert != nil { - params["Certificate.SSLMode"] = cert.SSLMode - params["Certificate.CertId"] = cert.CERTID - if len(cert.CERTCAID) > 0 { - params["Certificate.CertCaId"] = cert.CERTCAID - } - } + params = healthCheckParams(params, healthCheck) + params = certificateParams(params, cert) resp, err := self.clbRequest("CreateListener", params) if err != nil { @@ -479,7 +440,7 @@ func (self *SRegion) CreateLoadbalancerListener(lbid, name, protocol string, por if len(listeners) == 0 { return "", fmt.Errorf("CreateLoadbalancerListener no listener id returned: %s", resp.String()) } else if len(listeners) == 1 { - return listeners[0].String(), nil + return listeners[0].GetString() } else { return "", fmt.Errorf("CreateLoadbalancerListener mutliple listener id returned: %s", resp.String()) } @@ -504,7 +465,8 @@ func (self *SRegion) GetLBTaskStatus(requestId string) (string, error) { return "", err } - return status.String(), err + _status, err := status.Float() + return fmt.Sprintf("%1.f", _status), err } func (self *SRegion) WaitLBTaskSuccess(requestId string, interval time.Duration, timeout time.Duration) error { diff --git a/pkg/util/qcloud/loadbalancer_acl.go b/pkg/util/qcloud/loadbalancer_acl.go index aaa936ea53..71a874b25d 100755 --- a/pkg/util/qcloud/loadbalancer_acl.go +++ b/pkg/util/qcloud/loadbalancer_acl.go @@ -2,6 +2,7 @@ package qcloud import ( "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/compute/models" ) // todo: 腾讯云没有LB ACL @@ -20,7 +21,7 @@ func (self *SLBACL) GetGlobalId() string { } func (self *SLBACL) GetStatus() string { - return "" + return models.LB_BOOL_OFF } func (self *SLBACL) Refresh() error { diff --git a/pkg/util/qcloud/loadbalancer_backend.go b/pkg/util/qcloud/loadbalancer_backend.go index c14c8ed4f8..db42298705 100755 --- a/pkg/util/qcloud/loadbalancer_backend.go +++ b/pkg/util/qcloud/loadbalancer_backend.go @@ -51,7 +51,6 @@ func (self *SLBBackend) GetGlobalId() string { return self.GetId() } -// todo: status ?? func (self *SLBBackend) GetStatus() string { return "" } @@ -90,7 +89,6 @@ func (self *SLBBackend) GetPort() int { return self.Port } -// todo: self.Type ?? func (self *SLBBackend) GetBackendType() string { return models.LB_BACKEND_GUEST } diff --git a/pkg/util/qcloud/loadbalancer_backendgroup.go b/pkg/util/qcloud/loadbalancer_backendgroup.go index 6888af82df..cb3b518bf3 100755 --- a/pkg/util/qcloud/loadbalancer_backendgroup.go +++ b/pkg/util/qcloud/loadbalancer_backendgroup.go @@ -112,13 +112,14 @@ func (self *SLBBackendGroup) RemoveBackendServer(serverId string, weight int, po return self.lb.region.WaitLBTaskSuccess(requestId, 5*time.Second, 60*time.Second) } -// 腾讯云无后端服务器组 +// 腾讯云无后端服务器组。不支持该操作 func (self *SLBBackendGroup) Delete() error { return cloudprovider.ErrNotSupported } +// 腾讯云无后端服务器组 func (self *SLBBackendGroup) Sync(name string) error { - panic("implement me") + return nil } func backendGroupIdGen(lbid string, secondId string) string { @@ -171,7 +172,6 @@ func (self *SLBBackendGroup) IsDefault() bool { return false } -// todo: ?? func (self *SLBBackendGroup) GetType() string { return models.LB_BACKENDGROUP_TYPE_NORMAL } diff --git a/pkg/util/qcloud/loadbalancer_certificate.go b/pkg/util/qcloud/loadbalancer_certificate.go index d103b7e60a..06caebc9a8 100755 --- a/pkg/util/qcloud/loadbalancer_certificate.go +++ b/pkg/util/qcloud/loadbalancer_certificate.go @@ -16,8 +16,9 @@ type SLBCertificate struct { SCertificate } +// 证书不能修改 func (self *SLBCertificate) Sync(name, privateKey, publickKey string) error { - panic("implement me") + return nil } func (self *SLBCertificate) Delete() error { @@ -28,7 +29,6 @@ func (self *SLBCertificate) GetId() string { return self.ID } -// todo: ?? func (self *SLBCertificate) GetName() string { return self.Alias } @@ -64,7 +64,6 @@ func (self *SLBCertificate) GetMetadata() *jsonutils.JSONDict { return nil } -// todo: ?? func (self *SLBCertificate) GetCommonName() string { return self.Domain } @@ -73,7 +72,6 @@ func (self *SLBCertificate) GetSubjectAlternativeNames() string { return strings.Join(self.SubjectAltName, ",") } -// todo: ?? func (self *SLBCertificate) GetFingerprint() string { _fp := sha1.Sum([]byte(self.Cert)) fp := fmt.Sprintf("sha1:% x", _fp) diff --git a/pkg/util/qcloud/loadbalancer_listener.go b/pkg/util/qcloud/loadbalancer_listener.go index 7302243a03..c57f213aaf 100755 --- a/pkg/util/qcloud/loadbalancer_listener.go +++ b/pkg/util/qcloud/loadbalancer_listener.go @@ -111,7 +111,7 @@ func (self *SLBListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudp } func (self *SLBListener) Start() error { - return cloudprovider.ErrNotSupported + return nil } func (self *SLBListener) Stop() error { @@ -120,7 +120,21 @@ func (self *SLBListener) Stop() error { // https://cloud.tencent.com/document/product/214/30677 func (self *SLBListener) Sync(listener *cloudprovider.SLoadbalancerListener) error { - panic("implement me") + hc := getHealthCheck(listener) + cert := getCertificate(listener) + requestId, err := self.lb.region.UpdateLoadbalancerListener( + self.lb.GetId(), + self.GetId(), + &listener.Name, + getScheduler(listener), + &listener.StickySessionCookieTimeout, + hc, + cert) + if err != nil { + return err + } + + return self.lb.region.WaitLBTaskSuccess(requestId, 5*time.Second, 60*time.Second) } func (self *SLBListener) Delete() error { @@ -263,7 +277,7 @@ func (self *SLBListener) GetScheduler() string { } func (self *SLBListener) GetAclStatus() string { - return "" + return models.LB_BOOL_OFF } func (self *SLBListener) GetAclType() string { @@ -365,7 +379,6 @@ func (self *SLBListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloud return iRules, nil } -// todo: ?? func (self *SLBListener) GetStickySession() string { if self.SessionExpireTime == 0 { return models.LB_BOOL_OFF @@ -423,7 +436,6 @@ func (self *SLBListener) GetTLSCipherPolicy() string { return "" } -// todo: ? // 负载均衡能力说明 https://cloud.tencent.com/document/product/214/6534 func (self *SLBListener) HTTP2Enabled() bool { return true @@ -515,3 +527,138 @@ func (self *SRegion) DeleteLoadbalancerListener(lbid string, listenerId string) return resp.GetString("RequestId") } + +// https://cloud.tencent.com/document/product/214/30681 +func (self *SRegion) UpdateLoadbalancerListener(lbid string, listenerId string,listenerName *string, scheduler *string, sessionExpireTime *int, healthCheck *healthCheck,cert *certificate) (string, error) { + if len(lbid) == 0 { + return "", fmt.Errorf("loadbalancer id should not be empty") + } + + if len(listenerId) == 0 { + return "", fmt.Errorf("loadbalancer listener id should not be empty") + } + + params := map[string]string{ + "LoadBalancerId": lbid, + "ListenerId": listenerId, + } + + if listenerName != nil && len(*listenerName) > 0 { + params["ListenerName"] = *listenerName + } + + if scheduler != nil && len(*scheduler) > 0 { + params["Scheduler"] = *scheduler + } + + if sessionExpireTime != nil { + params["SessionExpireTime"] = strconv.Itoa(*sessionExpireTime) + } + + params = healthCheckParams(params, healthCheck) + params = certificateParams(params, cert) + + resp, err := self.clbRequest("ModifyListener", params) + if err != nil { + return "", err + } + + return resp.GetString("RequestId") +} + +func getHealthCheck(listener *cloudprovider.SLoadbalancerListener) *healthCheck { + var hc *healthCheck + if listener.HealthCheck == models.LB_HEALTH_CHECK_ENABLE { + hc = &healthCheck{ + HealthSwitch: 1, + UnHealthNum: listener.HealthCheckFail, + IntervalTime: listener.HealthCheckInterval, + HealthNum: listener.HealthCheckRise, + TimeOut: listener.HealthCheckTimeout, + } + + httpCode := onecloudHealthCodeToQcloud(listener.HealthCheckHttpCode) + if httpCode > 0 { + hc.HTTPCode = httpCode + hc.HTTPCheckMethod = "HEAD" // todo: add column HttpCheckMethod in model + hc.HTTPCheckDomain = listener.HealthCheckDomain + hc.HTTPCheckPath = listener.HealthCheckURI + } + } + + return hc +} + +func getCertificate(listener *cloudprovider.SLoadbalancerListener) *certificate { + var cert *certificate + if len(listener.CertificateID) > 0 { + cert = &certificate{ + SSLMode: "UNIDIRECTIONAL", + CERTCAID: listener.CertificateID, + CERTID: "", + } + } + + return cert +} + +func getProtocol(listener *cloudprovider.SLoadbalancerListener) string { + switch listener.ListenerType { + case models.LB_LISTENER_TYPE_HTTPS: + return "HTTPS" + case models.LB_LISTENER_TYPE_HTTP: + return "HTTP" + case models.LB_LISTENER_TYPE_TCP: + return "TCP" + case models.LB_LISTENER_TYPE_UDP: + return "UDP" + case "tcp_ssl": + return "TCP_SSL" + default: + return "" + } +} + +func getScheduler(listener *cloudprovider.SLoadbalancerListener) *string { + var sch string + switch listener.Scheduler { + case models.LB_SCHEDULER_WRR: + sch = "WRR" + case models.LB_SCHEDULER_WLC: + sch = "LEAST_CONN" + default: + return nil + } + + return &sch +} + +func healthCheckParams(params map[string]string,hc *healthCheck) map[string]string { + if hc != nil { + params["HealthCheck.HealthSwitch"] = strconv.Itoa(hc.HealthSwitch) + params["HealthCheck.TimeOut"] = strconv.Itoa(hc.TimeOut) + params["HealthCheck.IntervalTime"] = strconv.Itoa(hc.IntervalTime) + params["HealthCheck.HealthNum"] = strconv.Itoa(hc.HealthNum) + params["HealthCheck.UnHealthNum"] = strconv.Itoa(hc.UnHealthNum) + if hc.HTTPCode > 0 { + params["HealthCheck.HttpCode"] = strconv.Itoa(hc.HTTPCode) + params["HealthCheck.HttpCheckPath"] = hc.HTTPCheckPath + params["HealthCheck.HttpCheckDomain"] = hc.HTTPCheckDomain + params["HealthCheck.HttpCheckMethod"] = hc.HTTPCheckMethod + } + } + + return params +} + +func certificateParams(params map[string]string,cert *certificate) map[string]string { + if cert != nil { + params["Certificate.SSLMode"] = cert.SSLMode + params["Certificate.CertId"] = cert.CERTID + if len(cert.CERTCAID) > 0 { + params["Certificate.CertCaId"] = cert.CERTCAID + } + } + + return params +} \ No newline at end of file