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