yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/hcso/loadbalancer_listener.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package hcso
    16  
    17  import (
    18  	"context"
    19  	"time"
    20  
    21  	"yunion.io/x/jsonutils"
    22  	"yunion.io/x/log"
    23  
    24  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    25  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    26  	"yunion.io/x/cloudmux/pkg/multicloud"
    27  	"yunion.io/x/cloudmux/pkg/multicloud/huawei"
    28  )
    29  
    30  type InsertHeaders struct {
    31  	XForwardedELBIP bool `json:"X-Forwarded-ELB-IP"`
    32  }
    33  
    34  type Loadbalancer struct {
    35  	ID string `json:"id"`
    36  }
    37  
    38  type SElbListener struct {
    39  	multicloud.SResourceBase
    40  	multicloud.SLoadbalancerRedirectBase
    41  	huawei.HuaweiTags
    42  	lb           *SLoadbalancer
    43  	acl          *SElbACL
    44  	backendgroup *SElbBackendGroup
    45  
    46  	ProtocolPort           int            `json:"protocol_port"`
    47  	Protocol               string         `json:"protocol"`
    48  	Description            string         `json:"description"`
    49  	AdminStateUp           bool           `json:"admin_state_up"`
    50  	Http2Enable            bool           `json:"http2_enable"`
    51  	Loadbalancers          []Loadbalancer `json:"loadbalancers"`
    52  	TenantID               string         `json:"tenant_id"`
    53  	ProjectID              string         `json:"project_id"`
    54  	ConnectionLimit        int            `json:"connection_limit"`
    55  	DefaultPoolID          string         `json:"default_pool_id"`
    56  	ID                     string         `json:"id"`
    57  	Name                   string         `json:"name"`
    58  	CreatedAt              time.Time      `json:"created_at"`
    59  	UpdatedAt              time.Time      `json:"updated_at"`
    60  	InsertHeaders          InsertHeaders  `json:"insert_headers"`
    61  	DefaultTlsContainerRef string         `json:"default_tls_container_ref"`
    62  }
    63  
    64  func (self *SElbListener) GetId() string {
    65  	return self.ID
    66  }
    67  
    68  func (self *SElbListener) GetName() string {
    69  	return self.Name
    70  }
    71  
    72  func (self *SElbListener) GetGlobalId() string {
    73  	return self.GetId()
    74  }
    75  
    76  func (self *SElbListener) GetStatus() string {
    77  	return api.LB_STATUS_ENABLED
    78  }
    79  
    80  func (self *SElbListener) Refresh() error {
    81  	ilistener, err := self.lb.GetILoadBalancerListenerById(self.GetId())
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	listener := ilistener.(*SElbListener)
    87  	listener.lb = self.lb
    88  	err = jsonutils.Update(self, listener)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	return nil
    94  }
    95  
    96  func (self *SElbListener) IsEmulated() bool {
    97  	return false
    98  }
    99  
   100  func (self *SElbListener) GetProjectId() string {
   101  	return self.ProjectID
   102  }
   103  
   104  func (self *SElbListener) GetListenerType() string {
   105  	switch self.Protocol {
   106  	case "TCP":
   107  		return api.LB_LISTENER_TYPE_TCP
   108  	case "UDP":
   109  		return api.LB_LISTENER_TYPE_UDP
   110  	case "HTTP":
   111  		return api.LB_LISTENER_TYPE_HTTP
   112  	case "TERMINATED_HTTPS":
   113  		return api.LB_LISTENER_TYPE_HTTPS
   114  	case "HTTPS":
   115  		return api.LB_LISTENER_TYPE_HTTPS
   116  	default:
   117  		return ""
   118  	}
   119  }
   120  
   121  func (self *SElbListener) GetListenerPort() int {
   122  	return self.ProtocolPort
   123  }
   124  
   125  func (self *SElbListener) GetBackendGroup() (*SElbBackendGroup, error) {
   126  	if self.backendgroup == nil {
   127  		lbbgId := self.GetBackendGroupId()
   128  		if len(lbbgId) > 0 {
   129  			lbbg, err := self.lb.GetILoadBalancerBackendGroupById(lbbgId)
   130  			if err != nil {
   131  				return nil, err
   132  			}
   133  
   134  			self.backendgroup = lbbg.(*SElbBackendGroup)
   135  		}
   136  	}
   137  
   138  	return self.backendgroup, nil
   139  }
   140  
   141  func (self *SElbListener) GetScheduler() string {
   142  	lbbg, err := self.GetBackendGroup()
   143  	if err != nil {
   144  		log.Errorf("ElbListener GetScheduler %s", err.Error())
   145  	}
   146  
   147  	if lbbg == nil {
   148  		return ""
   149  	}
   150  
   151  	return lbbg.GetScheduler()
   152  }
   153  
   154  func (self *SElbListener) GetAcl() (*SElbACL, error) {
   155  	if self.acl != nil {
   156  		return self.acl, nil
   157  	}
   158  
   159  	acls, err := self.lb.region.GetLoadBalancerAcls(self.GetId())
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  
   164  	if len(acls) == 0 {
   165  		return nil, nil
   166  	} else {
   167  		self.acl = &acls[0]
   168  		return &acls[0], nil
   169  	}
   170  }
   171  
   172  func (self *SElbListener) GetAclStatus() string {
   173  	acl, err := self.GetAcl()
   174  	if err != nil {
   175  		log.Debugf("GetAclStatus %s", err)
   176  		return ""
   177  	}
   178  
   179  	if acl != nil && acl.EnableWhitelist {
   180  		return api.LB_BOOL_ON
   181  	}
   182  
   183  	return api.LB_BOOL_OFF
   184  }
   185  
   186  func (self *SElbListener) GetAclType() string {
   187  	return api.LB_ACL_TYPE_WHITE
   188  }
   189  
   190  func (self *SElbListener) GetAclId() string {
   191  	acl, err := self.GetAcl()
   192  	if err != nil {
   193  		log.Debugf("GetAclStatus %s", err)
   194  		return ""
   195  	}
   196  
   197  	if acl == nil {
   198  		return ""
   199  	}
   200  
   201  	return acl.GetId()
   202  }
   203  
   204  func (self *SElbListener) GetEgressMbps() int {
   205  	return 0
   206  }
   207  
   208  func (self *SElbListener) GetHealthCheck() string {
   209  	lbbg, err := self.GetBackendGroup()
   210  	if err != nil {
   211  		log.Errorf("ElbListener GetHealthCheck %s", err.Error())
   212  	}
   213  
   214  	if lbbg == nil {
   215  		return ""
   216  	}
   217  
   218  	health, err := lbbg.GetHealthCheck()
   219  	if err != nil {
   220  		log.Errorf("ElbListener GetHealthCheck %s", err.Error())
   221  	}
   222  
   223  	if health != nil {
   224  		return api.LB_BOOL_ON
   225  	} else {
   226  		return api.LB_BOOL_OFF
   227  	}
   228  }
   229  
   230  func (self *SElbListener) GetHealthCheckType() string {
   231  	lbbg, err := self.GetBackendGroup()
   232  	if err != nil {
   233  		log.Errorf("ElbListener GetHealthCheckType %s", err.Error())
   234  	}
   235  
   236  	if lbbg == nil {
   237  		return ""
   238  	}
   239  
   240  	health, err := lbbg.GetHealthCheck()
   241  	if err != nil {
   242  		log.Errorf("ElbListener GetHealthCheckType %s", err.Error())
   243  	}
   244  
   245  	if health != nil {
   246  		return health.HealthCheckType
   247  	}
   248  
   249  	return ""
   250  }
   251  
   252  func (self *SElbListener) GetHealthCheckTimeout() int {
   253  	lbbg, err := self.GetBackendGroup()
   254  	if err != nil {
   255  		log.Errorf("ElbListener GetHealthCheckTimeout %s", err.Error())
   256  	}
   257  
   258  	if lbbg == nil {
   259  		return 0
   260  	}
   261  
   262  	health, err := lbbg.GetHealthCheck()
   263  	if err != nil {
   264  		log.Errorf("ElbListener GetHealthCheckTimeout %s", err.Error())
   265  	}
   266  
   267  	if health != nil {
   268  		return health.HealthCheckTimeout
   269  	}
   270  
   271  	return 0
   272  }
   273  
   274  func (self *SElbListener) GetHealthCheckInterval() int {
   275  	lbbg, err := self.GetBackendGroup()
   276  	if err != nil {
   277  		log.Errorf("ElbListener GetHealthCheckInterval %s", err.Error())
   278  	}
   279  
   280  	if lbbg == nil {
   281  		return 0
   282  	}
   283  
   284  	health, err := lbbg.GetHealthCheck()
   285  	if err != nil {
   286  		log.Errorf("ElbListener GetHealthCheckInterval %s", err.Error())
   287  	}
   288  
   289  	if health != nil {
   290  		return health.HealthCheckInterval
   291  	}
   292  
   293  	return 0
   294  }
   295  
   296  func (self *SElbListener) GetHealthCheckRise() int {
   297  	lbbg, err := self.GetBackendGroup()
   298  	if err != nil {
   299  		log.Errorf("ElbListener GetHealthCheckRise %s", err.Error())
   300  	}
   301  
   302  	if lbbg == nil {
   303  		return 0
   304  	}
   305  
   306  	health, err := lbbg.GetHealthCheck()
   307  	if err != nil {
   308  		log.Errorf("ElbListener GetHealthCheckRise %s", err.Error())
   309  	}
   310  
   311  	if health != nil {
   312  		return health.HealthCheckRise
   313  	} else {
   314  		return 0
   315  	}
   316  }
   317  
   318  func (self *SElbListener) GetHealthCheckFail() int {
   319  	return 0
   320  }
   321  
   322  func (self *SElbListener) GetHealthCheckReq() string {
   323  	return ""
   324  }
   325  
   326  func (self *SElbListener) GetHealthCheckExp() string {
   327  	return ""
   328  }
   329  
   330  func (self *SElbListener) GetBackendGroupId() string {
   331  	return self.DefaultPoolID
   332  }
   333  
   334  func (self *SElbListener) GetBackendServerPort() int {
   335  	return 0
   336  }
   337  
   338  func (self *SElbListener) GetHealthCheckDomain() string {
   339  	lbbg, err := self.GetBackendGroup()
   340  	if err != nil {
   341  		log.Errorf("ElbListener GetHealthCheckDomain %s", err.Error())
   342  	}
   343  
   344  	if lbbg == nil {
   345  		return ""
   346  	}
   347  
   348  	health, err := lbbg.GetHealthCheck()
   349  	if err != nil {
   350  		log.Errorf("ElbListener GetHealthCheckDomain %s", err.Error())
   351  	}
   352  
   353  	if health != nil {
   354  		return health.HealthCheckDomain
   355  	}
   356  
   357  	return ""
   358  }
   359  
   360  func (self *SElbListener) GetHealthCheckURI() string {
   361  	lbbg, err := self.GetBackendGroup()
   362  	if err != nil {
   363  		log.Errorf("ElbListener GetHealthCheckURI %s", err.Error())
   364  	}
   365  
   366  	if lbbg == nil {
   367  		return ""
   368  	}
   369  
   370  	health, err := lbbg.GetHealthCheck()
   371  	if err != nil {
   372  		log.Errorf("ElbListener GetHealthCheckURI %s", err.Error())
   373  	}
   374  
   375  	if health != nil {
   376  		return health.HealthCheckURI
   377  	}
   378  
   379  	return ""
   380  }
   381  
   382  func (self *SElbListener) GetHealthCheckCode() string {
   383  	return ""
   384  }
   385  
   386  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0136295317.html
   387  func (self *SElbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) {
   388  	l7policy, err := self.lb.region.CreateLoadBalancerPolicy(self.GetId(), rule)
   389  	if err != nil {
   390  		return nil, err
   391  	}
   392  
   393  	l7policy.region = self.lb.region
   394  	l7policy.lb = self.lb
   395  	l7policy.listener = self
   396  	return &l7policy, nil
   397  }
   398  
   399  func (self *SElbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) {
   400  	ret := &SElbListenerPolicy{}
   401  	err := DoGet(self.lb.region.ecsClient.ElbL7policies.Get, ruleId, nil, ret)
   402  	if err != nil {
   403  		return nil, err
   404  	}
   405  
   406  	ret.region = self.lb.region
   407  	ret.lb = self.lb
   408  	ret.listener = self
   409  	return ret, nil
   410  }
   411  
   412  func (self *SElbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) {
   413  	ret, err := self.lb.region.GetLoadBalancerPolicies(self.GetId())
   414  	if err != nil {
   415  		return nil, err
   416  	}
   417  
   418  	iret := []cloudprovider.ICloudLoadbalancerListenerRule{}
   419  	for i := range ret {
   420  		rule := ret[i]
   421  		rule.listener = self
   422  		rule.lb = self.lb
   423  		iret = append(iret, &rule)
   424  	}
   425  
   426  	return iret, nil
   427  }
   428  
   429  func (self *SElbListener) GetStickySession() string {
   430  	lbbg, err := self.GetBackendGroup()
   431  	if err != nil {
   432  		log.Errorf("ElbListener GetStickySession %s", err.Error())
   433  	}
   434  
   435  	if lbbg == nil {
   436  		return ""
   437  	}
   438  
   439  	stickySession, err := lbbg.GetStickySession()
   440  	if err != nil {
   441  		log.Errorf("ElbListener GetStickySession %s", err.Error())
   442  	}
   443  
   444  	if stickySession != nil {
   445  		return stickySession.StickySession
   446  	}
   447  
   448  	return ""
   449  }
   450  
   451  func (self *SElbListener) GetStickySessionType() string {
   452  	lbbg, err := self.GetBackendGroup()
   453  	if err != nil {
   454  		log.Errorf("ElbListener GetStickySessionType %s", err.Error())
   455  	}
   456  
   457  	if lbbg == nil {
   458  		return ""
   459  	}
   460  
   461  	stickySession, err := lbbg.GetStickySession()
   462  	if err != nil {
   463  		log.Errorf("ElbListener GetStickySessionType %s", err.Error())
   464  	}
   465  
   466  	if stickySession != nil {
   467  		return stickySession.StickySessionType
   468  	}
   469  
   470  	return ""
   471  }
   472  
   473  func (self *SElbListener) GetStickySessionCookie() string {
   474  	lbbg, err := self.GetBackendGroup()
   475  	if err != nil {
   476  		log.Errorf("ElbListener GetStickySessionCookie %s", err.Error())
   477  	}
   478  
   479  	if lbbg == nil {
   480  		return ""
   481  	}
   482  
   483  	stickySession, err := lbbg.GetStickySession()
   484  	if err != nil {
   485  		log.Errorf("ElbListener GetStickySessionCookie %s", err.Error())
   486  	}
   487  
   488  	if stickySession != nil {
   489  		return stickySession.StickySessionCookie
   490  	}
   491  
   492  	return ""
   493  }
   494  
   495  func (self *SElbListener) GetStickySessionCookieTimeout() int {
   496  	lbbg, err := self.GetBackendGroup()
   497  	if err != nil {
   498  		log.Errorf("ElbListener GetStickySessionCookieTimeout %s", err.Error())
   499  	}
   500  
   501  	if lbbg == nil {
   502  		return 0
   503  	}
   504  
   505  	stickySession, err := lbbg.GetStickySession()
   506  	if err != nil {
   507  		log.Errorf("ElbListener GetStickySessionCookieTimeout %s", err.Error())
   508  	}
   509  
   510  	if stickySession != nil {
   511  		return stickySession.StickySessionCookieTimeout
   512  	}
   513  
   514  	return 0
   515  }
   516  
   517  func (self *SElbListener) XForwardedForEnabled() bool {
   518  	return self.InsertHeaders.XForwardedELBIP
   519  }
   520  
   521  func (self *SElbListener) GzipEnabled() bool {
   522  	return false
   523  }
   524  
   525  func (self *SElbListener) GetCertificateId() string {
   526  	return self.DefaultTlsContainerRef
   527  }
   528  
   529  func (self *SElbListener) GetTLSCipherPolicy() string {
   530  	return ""
   531  }
   532  
   533  func (self *SElbListener) HTTP2Enabled() bool {
   534  	return self.Http2Enable
   535  }
   536  
   537  func (self *SElbListener) Start() error {
   538  	return nil
   539  }
   540  
   541  func (self *SElbListener) Stop() error {
   542  	return cloudprovider.ErrNotSupported
   543  }
   544  
   545  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561544.html
   546  /*
   547  default_pool_id有如下限制:
   548  不能更新为其他监听器的default_pool。
   549  不能更新为其他监听器的关联的转发策略所使用的pool。
   550  default_pool_id对应的后端云服务器组的protocol和监听器的protocol有如下关系:
   551  监听器的protocol为TCP时,后端云服务器组的protocol必须为TCP。
   552  监听器的protocol为UDP时,后端云服务器组的protocol必须为UDP。
   553  监听器的protocol为HTTP或TERMINATED_HTTPS时,后端云服务器组的protocol必须为HTTP。
   554  */
   555  func (self *SElbListener) Sync(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) error {
   556  	return self.lb.region.UpdateLoadBalancerListener(self.GetId(), listener)
   557  }
   558  
   559  func (self *SElbListener) Delete(ctx context.Context) error {
   560  	err := DoDelete(self.lb.region.ecsClient.ElbListeners.Delete, self.GetId(), nil, nil)
   561  	if err != nil {
   562  		return err
   563  	}
   564  
   565  	return nil
   566  }
   567  
   568  func (self *SRegion) UpdateLoadBalancerListener(listenerId string, listener *cloudprovider.SLoadbalancerListener) error {
   569  	params := jsonutils.NewDict()
   570  	listenerObj := jsonutils.NewDict()
   571  	listenerObj.Set("name", jsonutils.NewString(listener.Name))
   572  	listenerObj.Set("description", jsonutils.NewString(listener.Description))
   573  	listenerObj.Set("http2_enable", jsonutils.NewBool(listener.EnableHTTP2))
   574  	if len(listener.BackendGroupID) > 0 {
   575  		listenerObj.Set("default_pool_id", jsonutils.NewString(listener.BackendGroupID))
   576  	} else {
   577  		listenerObj.Set("default_pool_id", jsonutils.JSONNull)
   578  	}
   579  
   580  	if listener.ListenerType == api.LB_LISTENER_TYPE_HTTPS {
   581  		listenerObj.Set("default_tls_container_ref", jsonutils.NewString(listener.CertificateID))
   582  	}
   583  
   584  	if listener.XForwardedFor {
   585  		insertObj := jsonutils.NewDict()
   586  		insertObj.Set("X-Forwarded-ELB-IP", jsonutils.NewBool(listener.XForwardedFor))
   587  		listenerObj.Set("insert_headers", insertObj)
   588  	}
   589  
   590  	params.Set("listener", listenerObj)
   591  	err := DoUpdate(self.ecsClient.ElbListeners.Update, listenerId, params, nil)
   592  	if err != nil {
   593  		return err
   594  	}
   595  	return nil
   596  }
   597  
   598  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0136295315.html
   599  func (self *SRegion) GetLoadBalancerPolicies(listenerId string) ([]SElbListenerPolicy, error) {
   600  	params := map[string]string{}
   601  	if len(listenerId) > 0 {
   602  		params["listener_id"] = listenerId
   603  	}
   604  
   605  	ret := []SElbListenerPolicy{}
   606  	err := doListAll(self.ecsClient.ElbL7policies.List, params, &ret)
   607  	if err != nil {
   608  		return nil, err
   609  	}
   610  
   611  	for i := range ret {
   612  		ret[i].region = self
   613  	}
   614  
   615  	return ret, nil
   616  }
   617  
   618  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0116649234.html
   619  func (self *SRegion) GetLoadBalancerPolicyRules(policyId string) ([]SElbListenerPolicyRule, error) {
   620  	m := self.ecsClient.ElbPolicies
   621  	err := m.SetL7policyId(policyId)
   622  	if err != nil {
   623  		return nil, err
   624  	}
   625  
   626  	ret := []SElbListenerPolicyRule{}
   627  	err = doListAll(m.List, nil, &ret)
   628  	if err != nil {
   629  		return nil, err
   630  	}
   631  
   632  	for i := range ret {
   633  		ret[i].region = self
   634  	}
   635  
   636  	return ret, nil
   637  }
   638  
   639  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0136295317.html
   640  func (self *SRegion) CreateLoadBalancerPolicy(listenerID string, rule *cloudprovider.SLoadbalancerListenerRule) (
   641  	SElbListenerPolicy, error) {
   642  	l7policy := SElbListenerPolicy{}
   643  	params := jsonutils.NewDict()
   644  	policyObj := jsonutils.NewDict()
   645  	policyObj.Set("name", jsonutils.NewString(rule.Name))
   646  	policyObj.Set("listener_id", jsonutils.NewString(listenerID))
   647  	// todo: REDIRECT_TO_LISTENER?
   648  	policyObj.Set("action", jsonutils.NewString("REDIRECT_TO_POOL"))
   649  	policyObj.Set("redirect_pool_id", jsonutils.NewString(rule.BackendGroupID))
   650  	params.Set("l7policy", policyObj)
   651  
   652  	err := DoCreate(self.ecsClient.ElbL7policies.Create, params, &l7policy)
   653  	if err != nil {
   654  		return l7policy, err
   655  	}
   656  
   657  	m := self.ecsClient.ElbPolicies
   658  	m.SetL7policyId(l7policy.GetId())
   659  	if len(rule.Domain) > 0 {
   660  		p := jsonutils.NewDict()
   661  		p.Set("type", jsonutils.NewString("HOST_NAME"))
   662  		p.Set("value", jsonutils.NewString(rule.Domain))
   663  		// todo: support more compare_type
   664  		p.Set("compare_type", jsonutils.NewString("EQUAL_TO"))
   665  		rule := jsonutils.NewDict()
   666  		rule.Set("rule", p)
   667  		err := DoCreate(m.Create, rule, nil)
   668  		if err != nil {
   669  			return l7policy, err
   670  		}
   671  	}
   672  
   673  	if len(rule.Path) > 0 {
   674  		p := jsonutils.NewDict()
   675  		p.Set("type", jsonutils.NewString("PATH"))
   676  		p.Set("value", jsonutils.NewString(rule.Path))
   677  		p.Set("compare_type", jsonutils.NewString("EQUAL_TO"))
   678  		rule := jsonutils.NewDict()
   679  		rule.Set("rule", p)
   680  		err := DoCreate(m.Create, rule, nil)
   681  		if err != nil {
   682  			return l7policy, err
   683  		}
   684  	}
   685  
   686  	return l7policy, nil
   687  }
   688  
   689  func (self *SElbListener) GetClientIdleTimeout() int {
   690  	return 0
   691  }
   692  
   693  func (self *SElbListener) GetBackendConnectTimeout() int {
   694  	return 0
   695  }