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