yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/hcs/loadbalancer.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  	"yunion.io/x/pkg/errors"
    26  
    27  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    28  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    29  	"yunion.io/x/cloudmux/pkg/multicloud"
    30  	"yunion.io/x/cloudmux/pkg/multicloud/huawei"
    31  )
    32  
    33  var LB_ALGORITHM_MAP = map[string]string{
    34  	api.LB_SCHEDULER_WRR: "ROUND_ROBIN",
    35  	api.LB_SCHEDULER_WLC: "LEAST_CONNECTIONS",
    36  	api.LB_SCHEDULER_SCH: "SOURCE_IP",
    37  }
    38  
    39  var LB_PROTOCOL_MAP = map[string]string{
    40  	api.LB_LISTENER_TYPE_HTTP:  "HTTP",
    41  	api.LB_LISTENER_TYPE_HTTPS: "TERMINATED_HTTPS",
    42  	api.LB_LISTENER_TYPE_UDP:   "UDP",
    43  	api.LB_LISTENER_TYPE_TCP:   "TCP",
    44  }
    45  
    46  var LBBG_PROTOCOL_MAP = map[string]string{
    47  	api.LB_LISTENER_TYPE_HTTP:  "HTTP",
    48  	api.LB_LISTENER_TYPE_HTTPS: "HTTP",
    49  	api.LB_LISTENER_TYPE_UDP:   "UDP",
    50  	api.LB_LISTENER_TYPE_TCP:   "TCP",
    51  }
    52  
    53  var LB_STICKY_SESSION_MAP = map[string]string{
    54  	api.LB_STICKY_SESSION_TYPE_INSERT: "HTTP_COOKIE",
    55  	api.LB_STICKY_SESSION_TYPE_SERVER: "APP_COOKIE",
    56  }
    57  
    58  var LB_HEALTHCHECK_TYPE_MAP = map[string]string{
    59  	api.LB_HEALTH_CHECK_HTTP: "HTTP",
    60  	api.LB_HEALTH_CHECK_TCP:  "TCP",
    61  	api.LB_HEALTH_CHECK_UDP:  "UDP_CONNECT",
    62  }
    63  
    64  type SLoadbalancer struct {
    65  	multicloud.SResourceBase
    66  	huawei.HuaweiTags
    67  	region *SRegion
    68  	subnet *SNetwork
    69  	eip    *SEip
    70  
    71  	Description        string     `json:"description"`
    72  	ProvisioningStatus string     `json:"provisioning_status"`
    73  	TenantId           string     `json:"tenant_id"`
    74  	ProjectId          string     `json:"project_id"`
    75  	AdminStateUp       bool       `json:"admin_state_up"`
    76  	Provider           string     `json:"provider"`
    77  	Pools              []Pool     `json:"pools"`
    78  	Listeners          []Listener `json:"listeners"`
    79  	VipPortId          string     `json:"vip_port_id"`
    80  	OperatingStatus    string     `json:"operating_status"`
    81  	VipAddress         string     `json:"vip_address"`
    82  	VipSubnetId        string     `json:"vip_subnet_id"`
    83  	Id                 string     `json:"id"`
    84  	Name               string     `json:"name"`
    85  	CreatedAt          time.Time  `json:"created_at"`
    86  	UpdatedAt          time.Time  `json:"updated_at"`
    87  }
    88  
    89  type Listener struct {
    90  	Id string `json:"id"`
    91  }
    92  
    93  type Pool struct {
    94  	Id string `json:"id"`
    95  }
    96  
    97  func (self *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
    98  	if self.GetEip() == nil {
    99  		return nil, nil
   100  	}
   101  
   102  	return self.eip, nil
   103  }
   104  
   105  func (self *SLoadbalancer) GetId() string {
   106  	return self.Id
   107  }
   108  
   109  func (self *SLoadbalancer) GetName() string {
   110  	return self.Name
   111  }
   112  
   113  func (self *SLoadbalancer) GetGlobalId() string {
   114  	return self.Id
   115  }
   116  
   117  func (self *SLoadbalancer) GetStatus() string {
   118  	return api.LB_STATUS_ENABLED
   119  }
   120  
   121  func (self *SLoadbalancer) Refresh() error {
   122  	lb, err := self.region.GetLoadbalancer(self.GetId())
   123  	if err != nil {
   124  		return err
   125  	}
   126  
   127  	return jsonutils.Update(self, lb)
   128  }
   129  
   130  func (self *SLoadbalancer) IsEmulated() bool {
   131  	return false
   132  }
   133  
   134  func (self *SLoadbalancer) GetProjectId() string {
   135  	return self.ProjectId
   136  }
   137  
   138  func (self *SLoadbalancer) GetAddress() string {
   139  	return self.VipAddress
   140  }
   141  
   142  // todo: api.LB_ADDR_TYPE_INTERNET?
   143  func (self *SLoadbalancer) GetAddressType() string {
   144  	return api.LB_ADDR_TYPE_INTRANET
   145  }
   146  
   147  func (self *SLoadbalancer) GetNetworkType() string {
   148  	return api.LB_NETWORK_TYPE_VPC
   149  }
   150  
   151  func (self *SLoadbalancer) GetNetworkIds() []string {
   152  	net := self.GetNetwork()
   153  	if net != nil {
   154  		return []string{net.GetId()}
   155  	}
   156  
   157  	return []string{}
   158  }
   159  
   160  func (self *SLoadbalancer) GetNetwork() *SNetwork {
   161  	if self.subnet == nil {
   162  		port, err := self.region.GetPort(self.VipPortId)
   163  		if err == nil {
   164  			net, err := self.region.GetNetwork(port.NetworkId)
   165  			if err == nil {
   166  				self.subnet = net
   167  			} else {
   168  				log.Debugf("huawei.SLoadbalancer.getNetwork %s", err)
   169  			}
   170  		} else {
   171  			log.Debugf("huawei.SLoadbalancer.GetPort %s", err)
   172  		}
   173  	}
   174  
   175  	return self.subnet
   176  }
   177  
   178  func (self *SLoadbalancer) GetEip() *SEip {
   179  	if self.eip == nil {
   180  		eips, _ := self.region.GetEips(self.VipPortId, nil)
   181  		for i := range eips {
   182  			self.eip = &eips[i]
   183  		}
   184  	}
   185  	return self.eip
   186  }
   187  
   188  func (self *SLoadbalancer) GetVpcId() string {
   189  	net := self.GetNetwork()
   190  	if net != nil {
   191  		return net.VpcId
   192  	}
   193  
   194  	return ""
   195  }
   196  
   197  func (self *SLoadbalancer) GetZoneId() string {
   198  	net := self.GetNetwork()
   199  	if net != nil {
   200  		z, err := self.region.GetZoneById(net.AvailabilityZone)
   201  		if err != nil {
   202  			log.Infof("getZoneById %s %s", net.AvailabilityZone, err)
   203  			return ""
   204  		}
   205  
   206  		return z.GetGlobalId()
   207  	}
   208  
   209  	return ""
   210  }
   211  
   212  func (self *SLoadbalancer) GetZone1Id() string {
   213  	return ""
   214  }
   215  
   216  func (self *SLoadbalancer) GetLoadbalancerSpec() string {
   217  	return ""
   218  }
   219  
   220  func (self *SLoadbalancer) GetChargeType() string {
   221  	eip := self.GetEip()
   222  	if eip != nil {
   223  		return eip.GetInternetChargeType()
   224  	}
   225  
   226  	return api.EIP_CHARGE_TYPE_BY_TRAFFIC
   227  }
   228  
   229  func (self *SLoadbalancer) GetEgressMbps() int {
   230  	eip := self.GetEip()
   231  	if eip != nil {
   232  		return eip.GetBandwidth()
   233  	}
   234  
   235  	return 0
   236  }
   237  
   238  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0141008275.html
   239  func (self *SLoadbalancer) Delete(ctx context.Context) error {
   240  	return self.region.DeleteLoadBalancer(self.GetId())
   241  }
   242  
   243  func (self *SLoadbalancer) Start() error {
   244  	return nil
   245  }
   246  
   247  func (self *SLoadbalancer) Stop() error {
   248  	return cloudprovider.ErrNotSupported
   249  }
   250  
   251  func (self *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
   252  	ret, err := self.region.GetLoadBalancerListeners(self.GetId())
   253  	if err != nil {
   254  		return nil, err
   255  	}
   256  
   257  	iret := make([]cloudprovider.ICloudLoadbalancerListener, 0)
   258  	for i := range ret {
   259  		listener := ret[i]
   260  		listener.lb = self
   261  		iret = append(iret, &listener)
   262  	}
   263  
   264  	return iret, nil
   265  }
   266  
   267  func (self *SLoadbalancer) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   268  	ret, err := self.region.GetLoadBalancerBackendGroups(self.GetId())
   269  	if err != nil {
   270  		return nil, err
   271  	}
   272  
   273  	iret := make([]cloudprovider.ICloudLoadbalancerBackendGroup, 0)
   274  	for i := range ret {
   275  		bg := ret[i]
   276  		bg.lb = self
   277  		bg.region = self.region
   278  		iret = append(iret, &bg)
   279  	}
   280  
   281  	return iret, nil
   282  }
   283  
   284  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561549.html
   285  func (self *SLoadbalancer) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   286  	ret, err := self.region.CreateLoadBalancerBackendGroup(group)
   287  	ret.lb = self
   288  	return &ret, err
   289  }
   290  
   291  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561563.html
   292  func (self *SLoadbalancer) CreateHealthCheck(backendGroupId string, healthcheck *cloudprovider.SLoadbalancerHealthCheck) error {
   293  	_, err := self.region.CreateLoadBalancerHealthCheck(backendGroupId, healthcheck)
   294  	return err
   295  }
   296  
   297  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561548.html
   298  func (self *SLoadbalancer) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   299  	ret := &SElbBackendGroup{lb: self, region: self.region}
   300  	return ret, self.region.lbGet("lbaas/pools/"+groupId, ret)
   301  }
   302  
   303  func (self *SLoadbalancer) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) (cloudprovider.ICloudLoadbalancerListener, error) {
   304  	ret, err := self.region.CreateLoadBalancerListener(listener)
   305  	if err != nil {
   306  		return nil, err
   307  	}
   308  
   309  	ret.lb = self
   310  	return &ret, nil
   311  }
   312  
   313  func (self *SLoadbalancer) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) {
   314  	ret := &SElbListener{lb: self}
   315  	return ret, self.region.lbGet("lbaas/listeners/"+listenerId, ret)
   316  }
   317  
   318  func (self *SRegion) GetLoadbalancer(id string) (*SLoadbalancer, error) {
   319  	ret := &SLoadbalancer{region: self}
   320  	return ret, self.lbGet("lbaas/loadbalancers/"+id, ret)
   321  }
   322  
   323  func (self *SRegion) DeleteLoadBalancer(elbId string) error {
   324  	resource := fmt.Sprintf("lbaas/loadbalancers/%s", elbId)
   325  	return self.lbDelete(resource)
   326  }
   327  
   328  func (self *SRegion) GetLoadBalancerListeners(lbId string) ([]SElbListener, error) {
   329  	ret := []SElbListener{}
   330  	params := url.Values{}
   331  	if len(lbId) > 0 {
   332  		params.Set("loadbalancer_id", lbId)
   333  	}
   334  	return ret, self.lbList("lbaas/listeners", params, &ret)
   335  }
   336  
   337  func (self *SRegion) CreateLoadBalancerListener(listener *cloudprovider.SLoadbalancerListener) (SElbListener, error) {
   338  	params := map[string]interface{}{
   339  		"name":            listener.Name,
   340  		"description":     listener.Description,
   341  		"protocol":        LB_PROTOCOL_MAP[listener.ListenerType],
   342  		"protocol_port":   listener.ListenerPort,
   343  		"loadbalancer_id": listener.LoadbalancerID,
   344  		"http2_enable":    listener.EnableHTTP2,
   345  	}
   346  	if len(listener.BackendGroupID) > 0 {
   347  		params["default_pool_id"] = listener.BackendGroupID
   348  	}
   349  
   350  	if listener.ListenerType == api.LB_LISTENER_TYPE_HTTPS {
   351  		params["default_tls_container_ref"] = listener.CertificateID
   352  	}
   353  
   354  	if listener.XForwardedFor {
   355  		params["insert_headers"] = map[string]interface{}{
   356  			"X-Forwarded-ELB-IP": listener.XForwardedFor,
   357  		}
   358  	}
   359  
   360  	ret := SElbListener{}
   361  	err := self.lbCreate("lbaas/listeners", map[string]interface{}{"listener": params}, &ret)
   362  	if err != nil {
   363  		return ret, err
   364  	}
   365  	return ret, nil
   366  }
   367  
   368  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561547.html
   369  func (self *SRegion) GetLoadBalancerBackendGroups(elbId string) ([]SElbBackendGroup, error) {
   370  	query := url.Values{}
   371  	if len(elbId) > 0 {
   372  		query.Set("loadbalancer_id", elbId)
   373  	}
   374  
   375  	ret := []SElbBackendGroup{}
   376  	return ret, self.lbList("lbaas/pools", query, &ret)
   377  }
   378  
   379  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561547.html
   380  func (self *SRegion) CreateLoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (SElbBackendGroup, error) {
   381  	ret := SElbBackendGroup{region: self}
   382  	var protocol, scheduler string
   383  	if s, ok := LB_ALGORITHM_MAP[group.Scheduler]; !ok {
   384  		return ret, fmt.Errorf("CreateILoadBalancerBackendGroup unsupported scheduler %s", group.Scheduler)
   385  	} else {
   386  		scheduler = s
   387  	}
   388  
   389  	if t, ok := LBBG_PROTOCOL_MAP[group.ListenType]; !ok {
   390  		return ret, fmt.Errorf("CreateILoadBalancerBackendGroup unsupported listener type %s", group.ListenType)
   391  	} else {
   392  		protocol = t
   393  	}
   394  
   395  	params := map[string]interface{}{
   396  		"project_id":   self.client.projectId,
   397  		"name":         group.Name,
   398  		"protocol":     protocol,
   399  		"lb_algorithm": scheduler,
   400  	}
   401  
   402  	if len(group.ListenerID) > 0 {
   403  		params["listener_id"] = group.ListenerID
   404  	} else if len(group.LoadbalancerID) > 0 {
   405  		params["loadbalancer_id"] = group.LoadbalancerID
   406  	} else {
   407  		return ret, fmt.Errorf("CreateLoadBalancerBackendGroup one of listener id / loadbalancer id must be specified")
   408  	}
   409  
   410  	if group.StickySession != nil {
   411  		s := map[string]interface{}{}
   412  		timeout := int64(group.StickySession.StickySessionCookieTimeout / 60)
   413  		if group.ListenType == api.LB_LISTENER_TYPE_UDP || group.ListenType == api.LB_LISTENER_TYPE_TCP {
   414  			s["type"] = "SOURCE_IP"
   415  			if timeout > 0 {
   416  				s["persistence_timeout"] = timeout
   417  			}
   418  		} else {
   419  			s["type"] = LB_STICKY_SESSION_MAP[group.StickySession.StickySessionType]
   420  			if len(group.StickySession.StickySessionCookie) > 0 {
   421  				s["cookie_name"] = group.StickySession.StickySessionCookie
   422  			} else {
   423  				if timeout > 0 {
   424  					s["persistence_timeout"] = timeout
   425  				}
   426  			}
   427  		}
   428  		params["session_persistence"] = s
   429  	}
   430  	err := self.lbCreate("lbaas/pools", map[string]interface{}{"pool": params}, &ret)
   431  	if err != nil {
   432  		return ret, err
   433  	}
   434  
   435  	if group.HealthCheck != nil {
   436  		_, err := self.CreateLoadBalancerHealthCheck(ret.GetId(), group.HealthCheck)
   437  		if err != nil {
   438  			return ret, err
   439  		}
   440  	}
   441  
   442  	return ret, nil
   443  }
   444  
   445  func (self *SRegion) CreateLoadBalancerHealthCheck(backendGroupId string, healthCheck *cloudprovider.SLoadbalancerHealthCheck) (SElbHealthCheck, error) {
   446  	params := map[string]interface{}{
   447  		"delay":       healthCheck.HealthCheckInterval,
   448  		"max_retries": healthCheck.HealthCheckRise,
   449  		"pool_id":     backendGroupId,
   450  		"timeout":     healthCheck.HealthCheckTimeout,
   451  		"type":        LB_HEALTHCHECK_TYPE_MAP[healthCheck.HealthCheckType],
   452  	}
   453  	if healthCheck.HealthCheckType == api.LB_HEALTH_CHECK_HTTP {
   454  		if len(healthCheck.HealthCheckDomain) > 0 {
   455  			params["domain_name"] = healthCheck.HealthCheckDomain
   456  		}
   457  
   458  		if len(healthCheck.HealthCheckURI) > 0 {
   459  			params["url_path"] = healthCheck.HealthCheckURI
   460  		}
   461  
   462  		if len(healthCheck.HealthCheckHttpCode) > 0 {
   463  			params["expected_codes"] = ToHuaweiHealthCheckHttpCode(healthCheck.HealthCheckHttpCode)
   464  		}
   465  	}
   466  
   467  	ret := SElbHealthCheck{region: self}
   468  	err := self.lbCreate("lbaas/healthmonitors", map[string]interface{}{"healthmonitor": params}, &ret)
   469  	if err != nil {
   470  		return ret, err
   471  	}
   472  
   473  	return ret, nil
   474  }
   475  
   476  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561564.html
   477  func (self *SRegion) UpdateLoadBalancerHealthCheck(healthCheckId string, healthCheck *cloudprovider.SLoadbalancerHealthCheck) (SElbHealthCheck, error) {
   478  	params := map[string]interface{}{
   479  		"delay":       healthCheck.HealthCheckInterval,
   480  		"max_retries": healthCheck.HealthCheckRise,
   481  		"timeout":     healthCheck.HealthCheckTimeout,
   482  	}
   483  	if healthCheck.HealthCheckType == api.LB_HEALTH_CHECK_HTTP {
   484  		if len(healthCheck.HealthCheckDomain) > 0 {
   485  			params["domain_name"] = healthCheck.HealthCheckDomain
   486  		}
   487  
   488  		if len(healthCheck.HealthCheckURI) > 0 {
   489  			params["url_path"] = healthCheck.HealthCheckURI
   490  		}
   491  
   492  		if len(healthCheck.HealthCheckHttpCode) > 0 {
   493  			params["expected_codes"] = ToHuaweiHealthCheckHttpCode(healthCheck.HealthCheckHttpCode)
   494  		}
   495  	}
   496  
   497  	ret := SElbHealthCheck{region: self}
   498  	res := "lbaas/healthmonitors/" + healthCheckId
   499  	err := self.lbUpdate(res, map[string]interface{}{"healthmonitor": params})
   500  	if err != nil {
   501  		return ret, err
   502  	}
   503  	return ret, self.lbGet(res, &ret)
   504  }
   505  
   506  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561565.html
   507  func (self *SRegion) DeleteLoadbalancerHealthCheck(healthCheckId string) error {
   508  	return self.lbDelete("lbaas/healthmonitors/" + healthCheckId)
   509  }
   510  
   511  func (self *SLoadbalancer) SetTags(tags map[string]string, replace bool) error {
   512  	return cloudprovider.ErrNotSupported
   513  }
   514  
   515  func (self *SRegion) lbGet(resource string, retVal interface{}) error {
   516  	return self.client.get("vpc", "v2.0", self.Id, resource, retVal)
   517  }
   518  
   519  func (self *SRegion) lbList(resource string, params url.Values, retVal interface{}) error {
   520  	return self.list("vpc", "v2.0", resource, params, retVal)
   521  }
   522  
   523  func (self *SRegion) lbDelete(resource string) error {
   524  	return self.delete("vpc", "v2.0", resource)
   525  }
   526  
   527  func (self *SRegion) lbCreate(resource string, params map[string]interface{}, retVal interface{}) error {
   528  	return self.create("vpc", "v2.0", resource, params, retVal)
   529  }
   530  
   531  func (self *SRegion) lbUpdate(resource string, params map[string]interface{}) error {
   532  	return self.update("vpc", "v2.0", resource, params)
   533  }
   534  
   535  // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561535.html
   536  func (self *SRegion) CreateLoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (*SLoadbalancer, error) {
   537  	subnet, err := self.GetNetwork(loadbalancer.NetworkIDs[0])
   538  	if err != nil {
   539  		return nil, errors.Wrap(err, "SRegion.CreateLoadBalancer.getNetwork")
   540  	}
   541  
   542  	params := map[string]interface{}{
   543  		"name":          loadbalancer.Name,
   544  		"vip_subnet_id": subnet.NeutronSubnetId,
   545  		"tenant_id":     self.client.projectId,
   546  	}
   547  	if len(loadbalancer.Address) > 0 {
   548  		params["vip_address"] = loadbalancer.Address
   549  	}
   550  	ret := &SLoadbalancer{region: self}
   551  	err = self.lbCreate("lbaas/loadbalancers", map[string]interface{}{"loadbalancer": params}, ret)
   552  	if err != nil {
   553  		return nil, err
   554  	}
   555  
   556  	// 创建公网类型ELB
   557  	if len(loadbalancer.EipID) > 0 {
   558  		err := self.AssociateEipWithPortId(loadbalancer.EipID, ret.VipPortId)
   559  		if err != nil {
   560  			return ret, errors.Wrap(err, "SRegion.CreateLoadBalancer.AssociateEipWithPortId")
   561  		}
   562  	}
   563  	return ret, nil
   564  }
   565  
   566  func (self *SRegion) GetLoadBalancers() ([]SLoadbalancer, error) {
   567  	lbs := []SLoadbalancer{}
   568  	params := url.Values{}
   569  	return lbs, self.lbList("lbaas/loadbalancers", params, &lbs)
   570  }
   571  
   572  func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
   573  	elbs, err := self.GetLoadBalancers()
   574  	if err != nil {
   575  		return nil, err
   576  	}
   577  
   578  	ret := []cloudprovider.ICloudLoadbalancer{}
   579  	for i := range elbs {
   580  		elbs[i].region = self
   581  		ret = append(ret, &elbs[i])
   582  	}
   583  
   584  	return ret, nil
   585  }
   586  
   587  func (self *SRegion) GetILoadBalancerById(id string) (cloudprovider.ICloudLoadbalancer, error) {
   588  	elb, err := self.GetLoadbalancer(id)
   589  	if err != nil {
   590  		return nil, err
   591  	}
   592  	return elb, nil
   593  }
   594  
   595  func (self *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) {
   596  	ret, err := self.CreateLoadBalancer(loadbalancer)
   597  	if err != nil {
   598  		return nil, err
   599  	}
   600  
   601  	return ret, nil
   602  }