yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/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 azure
    16  
    17  import (
    18  	"context"
    19  	"strconv"
    20  	"strings"
    21  
    22  	"github.com/pkg/errors"
    23  
    24  	"yunion.io/x/jsonutils"
    25  	"yunion.io/x/log"
    26  	"yunion.io/x/pkg/utils"
    27  
    28  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    29  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    30  	"yunion.io/x/cloudmux/pkg/multicloud"
    31  )
    32  
    33  type SLoadbalancer struct {
    34  	multicloud.SResourceBase
    35  	region    *SRegion
    36  	eips      []cloudprovider.ICloudEIP
    37  	lbbgs     []cloudprovider.ICloudLoadbalancerBackendGroup
    38  	listeners []cloudprovider.ICloudLoadbalancerListener
    39  
    40  	Name       string                  `json:"name"`
    41  	ID         string                  `json:"id"`
    42  	Etag       string                  `json:"etag"`
    43  	Type       string                  `json:"type"`
    44  	Tags       map[string]string       `json:"tags"`
    45  	Location   string                  `json:"location"`
    46  	Properties SLoadbalancerProperties `json:"properties"`
    47  	Sku        Sku                     `json:"sku"`
    48  }
    49  
    50  func (self *SLoadbalancer) GetId() string {
    51  	return self.ID
    52  }
    53  
    54  func (self *SLoadbalancer) GetName() string {
    55  	return self.Name
    56  }
    57  
    58  func (self *SLoadbalancer) GetGlobalId() string {
    59  	return strings.ToLower(self.GetId())
    60  }
    61  
    62  func (self *SLoadbalancer) GetStatus() string {
    63  	switch self.Properties.ProvisioningState {
    64  	case "Deleting":
    65  		return api.LB_STATUS_DELETING
    66  	case "Failed":
    67  		return api.LB_STATUS_START_FAILED
    68  	case "Updating":
    69  		return api.LB_SYNC_CONF
    70  	}
    71  
    72  	switch self.Properties.OperationalState {
    73  	case "Running":
    74  		return api.LB_STATUS_ENABLED
    75  	case "Stopped":
    76  		return api.LB_STATUS_DISABLED
    77  	case "Starting", "Stopping":
    78  		return api.LB_SYNC_CONF
    79  	default:
    80  		if self.Properties.ProvisioningState == "Succeeded" {
    81  			return api.LB_STATUS_ENABLED
    82  		}
    83  
    84  		return api.LB_STATUS_UNKNOWN
    85  	}
    86  }
    87  
    88  func (self *SLoadbalancer) Refresh() error {
    89  	lb, err := self.region.GetILoadBalancerById(self.GetId())
    90  	if err != nil {
    91  		return errors.Wrap(err, "GetILoadBalancerById.Refresh")
    92  	}
    93  
    94  	err = jsonutils.Update(self, lb)
    95  	if err != nil {
    96  		return errors.Wrap(err, "jsonutils.Update")
    97  	}
    98  
    99  	self.eips = nil
   100  	self.lbbgs = nil
   101  	self.listeners = nil
   102  	return nil
   103  }
   104  
   105  func (self *SLoadbalancer) IsEmulated() bool {
   106  	return false
   107  }
   108  
   109  func (self *SLoadbalancer) GetSysTags() map[string]string {
   110  	data := map[string]string{}
   111  	data["loadbalance_type"] = self.Type
   112  	data["capacity"] = self.Properties.Sku.Capacity
   113  	data["max_capacity"] = strconv.Itoa(self.Properties.AutoscaleConfiguration.MaxCapacity)
   114  	data["min_capacity"] = strconv.Itoa(self.Properties.AutoscaleConfiguration.MinCapacity)
   115  	data["properties"] = jsonutils.Marshal(self.Properties).String()
   116  	return data
   117  }
   118  
   119  func (self *SLoadbalancer) GetTags() (map[string]string, error) {
   120  	return self.Tags, nil
   121  }
   122  
   123  func (self *SLoadbalancer) SetTags(tags map[string]string, replace bool) error {
   124  	return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags")
   125  }
   126  
   127  func (self *SLoadbalancer) GetProjectId() string {
   128  	return getResourceGroup(self.ID)
   129  }
   130  
   131  func (self *SLoadbalancer) getAddresses() [][]string {
   132  	ret := [][]string{[]string{}, []string{}}
   133  	for _, fip := range self.Properties.FrontendIPConfigurations {
   134  		eip := fip.Properties.PublicIPAddress
   135  		if eip != nil && len(eip.Properties.IPAddress) > 0 {
   136  			ret[0] = append(ret[0], fip.Properties.PublicIPAddress.Properties.IPAddress)
   137  			continue
   138  		}
   139  
   140  		if len(fip.Properties.PrivateIPAddress) > 0 {
   141  			ret[1] = append(ret[1], fip.Properties.PrivateIPAddress)
   142  			continue
   143  		}
   144  	}
   145  
   146  	return ret
   147  }
   148  
   149  func (self *SLoadbalancer) GetAddress() string {
   150  	ips := self.getAddresses()
   151  	if len(ips[0]) > 0 {
   152  		return ips[0][0]
   153  	} else if len(ips[1]) > 0 {
   154  		return ips[1][0]
   155  	} else {
   156  		return ""
   157  	}
   158  }
   159  
   160  func (self *SLoadbalancer) GetAddressType() string {
   161  	ips := self.getAddresses()
   162  	if len(ips[0]) > 0 {
   163  		return api.LB_ADDR_TYPE_INTERNET
   164  	} else if len(ips[1]) > 0 {
   165  		return api.LB_ADDR_TYPE_INTRANET
   166  	} else {
   167  		return api.LB_ADDR_TYPE_INTRANET
   168  	}
   169  }
   170  
   171  func (self *SLoadbalancer) GetNetworkType() string {
   172  	return api.LB_NETWORK_TYPE_VPC
   173  }
   174  
   175  func (self *SLoadbalancer) getNetworkIds() []string {
   176  	ret := []string{}
   177  	for _, fip := range self.Properties.FrontendIPConfigurations {
   178  		subnet := fip.Properties.Subnet
   179  		if len(subnet.ID) > 0 {
   180  			ret = append(ret, subnet.ID)
   181  		}
   182  	}
   183  
   184  	return ret
   185  }
   186  
   187  func (self *SLoadbalancer) getLbbgNetworkIds() []string {
   188  	ret := []string{}
   189  	for _, b := range self.Properties.BackendAddressPools {
   190  		bips := b.Properties.BackendIPConfigurations
   191  		if len(bips) > 0 {
   192  			for _, ip := range bips {
   193  				if strings.Contains(ip.ID, "Microsoft.Network/networkInterfaces") {
   194  					nic, _ := self.region.GetNetworkInterface(strings.Split(ip.ID, "/ipConfigurations")[0])
   195  					if nic != nil && len(nic.Properties.IPConfigurations) > 0 {
   196  						ipc := nic.Properties.IPConfigurations[0]
   197  						if len(ipc.Properties.Subnet.ID) > 0 {
   198  							return []string{ipc.Properties.Subnet.ID}
   199  						}
   200  					}
   201  				}
   202  			}
   203  		}
   204  	}
   205  
   206  	return ret
   207  }
   208  
   209  func (self *SLoadbalancer) GetNetworkIds() []string {
   210  	return self.getNetworkIds()
   211  }
   212  
   213  func (self *SLoadbalancer) GetVpcId() string {
   214  	if self.Type == "Microsoft.Network/loadBalancers" {
   215  		subnets := self.GetNetworkIds()
   216  		if len(subnets) == 0 {
   217  			subnets = self.getLbbgNetworkIds()
   218  		}
   219  
   220  		if len(subnets) > 0 {
   221  			network, err := self.region.GetNetwork(subnets[0])
   222  			if network != nil {
   223  				return strings.Split(network.GetId(), "/subnets")[0]
   224  			}
   225  
   226  			log.Errorf("GetNetwork %s: %s", subnets[0], err)
   227  		}
   228  	} else {
   229  		gips := self.Properties.GatewayIPConfigurations
   230  		for i := range gips {
   231  			netId := gips[i].Properties.Subnet.ID
   232  			if len(netId) > 0 {
   233  				network, err := self.region.GetNetwork(netId)
   234  				if network != nil {
   235  					return strings.Split(network.GetId(), "/subnets")[0]
   236  				}
   237  				log.Errorf("GetNetwork %s: %s", netId, err)
   238  			}
   239  		}
   240  	}
   241  
   242  	return ""
   243  }
   244  
   245  func (self *SLoadbalancer) GetZoneId() string {
   246  	ips := self.Properties.FrontendIPConfigurations
   247  	if len(ips) > 0 && len(ips[0].Zones) > 0 {
   248  		return ips[0].Zones[0]
   249  	}
   250  
   251  	return ""
   252  }
   253  
   254  func (self *SLoadbalancer) GetZone1Id() string {
   255  	ips := self.Properties.FrontendIPConfigurations
   256  	if len(ips) > 0 && len(ips[0].Zones) > 1 {
   257  		return ips[0].Zones[1]
   258  	}
   259  
   260  	return ""
   261  }
   262  
   263  func (self *SLoadbalancer) GetLoadbalancerSpec() string {
   264  	if len(self.Properties.Sku.Name) > 0 {
   265  		return self.Properties.Sku.Name
   266  	}
   267  
   268  	if len(self.Sku.Name) > 0 {
   269  		return self.Sku.Name
   270  	}
   271  	return ""
   272  }
   273  
   274  func (self *SLoadbalancer) GetChargeType() string {
   275  	return api.LB_CHARGE_TYPE_BY_TRAFFIC
   276  }
   277  
   278  func (self *SLoadbalancer) GetEgressMbps() int {
   279  	return 0
   280  }
   281  
   282  func (self *SLoadbalancer) getEipIds() []string {
   283  	ret := []string{}
   284  	for _, fip := range self.Properties.FrontendIPConfigurations {
   285  		eip := fip.Properties.PublicIPAddress
   286  		if eip != nil && len(eip.ID) > 0 {
   287  			ret = append(ret, eip.ID)
   288  			continue
   289  		}
   290  	}
   291  
   292  	return ret
   293  }
   294  
   295  func (self *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
   296  	ieips, err := self.GetIEIPS()
   297  	if err != nil {
   298  		return nil, errors.Wrap(err, "GetIEIPS")
   299  	}
   300  
   301  	if len(ieips) > 0 {
   302  		return self.eips[0], nil
   303  	}
   304  
   305  	return nil, nil
   306  }
   307  
   308  func (self *SLoadbalancer) GetIEIPById(eipId string) (cloudprovider.ICloudEIP, error) {
   309  	ieips, err := self.GetIEIPS()
   310  	if err != nil {
   311  		return nil, errors.Wrap(err, "GetIEIPS")
   312  	}
   313  
   314  	for i := range ieips {
   315  		if ieips[i].GetId() == eipId {
   316  			return ieips[i], nil
   317  		}
   318  	}
   319  
   320  	return nil, errors.Wrap(cloudprovider.ErrNotFound, eipId)
   321  }
   322  
   323  func (self *SLoadbalancer) GetIEIPS() ([]cloudprovider.ICloudEIP, error) {
   324  	if self.eips != nil {
   325  		return self.eips, nil
   326  	}
   327  
   328  	eips := self.getEipIds()
   329  	ieips := make([]cloudprovider.ICloudEIP, 0)
   330  	for i := range eips {
   331  		ieip, err := self.region.GetIEipById(eips[i])
   332  		if err != nil {
   333  			return nil, errors.Wrap(err, "GetIEIP")
   334  		}
   335  		ieips = append(ieips, ieip)
   336  	}
   337  
   338  	if len(ieips) > 0 {
   339  		self.eips = ieips
   340  	}
   341  
   342  	return self.eips, nil
   343  }
   344  
   345  func (self *SLoadbalancer) Delete(ctx context.Context) error {
   346  	return errors.Wrap(cloudprovider.ErrNotImplemented, "Delete")
   347  }
   348  
   349  func (self *SLoadbalancer) Start() error {
   350  	return errors.Wrap(cloudprovider.ErrNotImplemented, "Start")
   351  }
   352  
   353  func (self *SLoadbalancer) Stop() error {
   354  	return errors.Wrap(cloudprovider.ErrNotImplemented, "Stop")
   355  }
   356  
   357  /*
   358  应用型LB: urlPathMaps(defaultBackendAddressPool+defaultBackendHttpSettings+requestRoutingRules+httpListeners)= Onecloud监听器
   359  4层LB: loadBalancingRules(前端) = Onecloud监听器
   360  */
   361  func (self *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
   362  	if self.listeners != nil {
   363  		return self.listeners, nil
   364  	}
   365  
   366  	var err error
   367  	if self.Type == "Microsoft.Network/applicationGateways" {
   368  		self.listeners, err = self.getAppLBListeners()
   369  	} else {
   370  		self.listeners, err = self.getNetworkLBListeners()
   371  	}
   372  
   373  	return self.listeners, err
   374  }
   375  
   376  func (self *SLoadbalancer) getFrontendIPConfiguration(id string) *FrontendIPConfiguration {
   377  	fips := self.Properties.FrontendIPConfigurations
   378  	for i := range fips {
   379  		if fips[i].ID == id {
   380  			return &fips[i]
   381  		}
   382  	}
   383  	log.Debugf("getFrontendIPConfiguration %s not found", id)
   384  	return nil
   385  }
   386  
   387  func (self *SLoadbalancer) getHttpListener(id string) *HTTPListener {
   388  	ss := self.Properties.HTTPListeners
   389  	for i := range ss {
   390  		if ss[i].ID == id {
   391  			return &ss[i]
   392  		}
   393  
   394  		for j := range ss[i].Properties.RequestRoutingRules {
   395  			if ss[i].Properties.RequestRoutingRules[j].ID == id {
   396  				return &ss[i]
   397  			}
   398  		}
   399  	}
   400  	log.Debugf("getHttpListener %s not found", id)
   401  	return nil
   402  }
   403  
   404  func (self *SLoadbalancer) getBackendAddressPool(id string) *BackendAddressPool {
   405  	ss := self.Properties.BackendAddressPools
   406  	for i := range ss {
   407  		if ss[i].ID == id {
   408  			return &ss[i]
   409  		}
   410  	}
   411  	log.Debugf("getBackendAddressPool %s not found", id)
   412  	return nil
   413  }
   414  
   415  func (self *SLoadbalancer) getBackendHTTPSettingsCollection(id string) *BackendHTTPSettingsCollection {
   416  	ss := self.Properties.BackendHTTPSettingsCollection
   417  	for i := range ss {
   418  		if ss[i].ID == id {
   419  			return &ss[i]
   420  		}
   421  	}
   422  	log.Debugf("getBackendHTTPSettingsCollection %s not found", id)
   423  	return nil
   424  }
   425  
   426  func (self *SLoadbalancer) getRedirectConfiguration(id string) *RedirectConfiguration {
   427  	ss := self.Properties.RedirectConfigurations
   428  	for i := range ss {
   429  		if ss[i].ID == id {
   430  			return &ss[i]
   431  		}
   432  	}
   433  	log.Debugf("getRedirectConfiguration %s not found", id)
   434  	return nil
   435  }
   436  
   437  func (self *SLoadbalancer) getProbe(id string) *Probe {
   438  	ss := self.Properties.Probes
   439  	for i := range ss {
   440  		if ss[i].ID == id {
   441  			return &ss[i]
   442  		}
   443  	}
   444  	log.Debugf("getProbe %s not found", id)
   445  	return nil
   446  }
   447  
   448  func (self *SLoadbalancer) getFrontendPort(id string) *FrontendPort {
   449  	ss := self.Properties.FrontendPorts
   450  	for i := range ss {
   451  		if ss[i].ID == id {
   452  			return &ss[i]
   453  		}
   454  	}
   455  	log.Debugf("getFrontendPort %s not found", id)
   456  	return nil
   457  }
   458  
   459  func (self *SLoadbalancer) getRequestRoutingRule(id string) *RequestRoutingRule {
   460  	ss := self.Properties.RequestRoutingRules
   461  	for i := range ss {
   462  		if ss[i].ID == id {
   463  			return &ss[i]
   464  		}
   465  	}
   466  	log.Debugf("getRequestRoutingRule %s not found", id)
   467  	return nil
   468  }
   469  
   470  func (self *SLoadbalancer) getURLPathMap(id string) *URLPathMap {
   471  	ss := self.Properties.URLPathMaps
   472  	for i := range ss {
   473  		if ss[i].ID == id {
   474  			return &ss[i]
   475  		}
   476  	}
   477  	log.Debugf("getURLPathMap %s not found", id)
   478  	return nil
   479  }
   480  
   481  /*
   482  应用型LB: urlPathMaps(defaultBackendAddressPool+defaultBackendHttpSettings+requestRoutingRules+httpListeners)= Onecloud监听器
   483  */
   484  func (self *SLoadbalancer) getAppLBListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
   485  	lbls := []cloudprovider.ICloudLoadbalancerListener{}
   486  	for i := range self.Properties.RequestRoutingRules {
   487  		r := self.Properties.RequestRoutingRules[i]
   488  		uid := strings.Replace(r.ID, "requestRoutingRules", "urlPathMaps", 1)
   489  		u := self.getURLPathMap(uid)
   490  		lbl := self.getAppLBListener(&r, u)
   491  		if lbl != nil {
   492  			lbls = append(lbls, lbl)
   493  		}
   494  	}
   495  
   496  	return lbls, nil
   497  }
   498  
   499  func (self *SLoadbalancer) getAppLBListener(r *RequestRoutingRule, u *URLPathMap) *SLoadBalancerListener {
   500  	var redirect *RedirectConfiguration
   501  	var listener *HTTPListener
   502  	var fp *FrontendIPConfiguration
   503  	var fpp *FrontendPort
   504  	// frontendPort, frontendIPConfiguration, sslCertificate, requestRoutingRules
   505  	listener = self.getHttpListener(r.Properties.HTTPListener.ID)
   506  	// frontendPorts
   507  	fp = self.getFrontendIPConfiguration(listener.Properties.FrontendIPConfiguration.ID)
   508  	fpp = self.getFrontendPort(listener.Properties.FrontendPort.ID)
   509  	// 配置有异常??
   510  	if fpp == nil || listener == nil {
   511  		return nil
   512  	}
   513  
   514  	lbbgId := r.Properties.BackendAddressPool.ID
   515  	lbbgSettingId := r.Properties.BackendHTTPSettings.ID
   516  	provisioningState := "Succeeded"
   517  	rules := make([]PathRule, 0)
   518  	var backendGroup *BackendAddressPool
   519  	var backendSetting *BackendHTTPSettingsCollection
   520  	var backendPort int
   521  	var healthcheck *Probe
   522  	if u != nil {
   523  		provisioningState = u.Properties.ProvisioningState
   524  		rules = u.Properties.PathRules
   525  		if u.Properties.DefaultRedirectConfiguration != nil {
   526  			redirect = self.getRedirectConfiguration(u.Properties.DefaultRedirectConfiguration.ID)
   527  		}
   528  
   529  		if len(lbbgId) == 0 && u.Properties.DefaultBackendAddressPool != nil {
   530  			lbbgId = u.Properties.DefaultBackendAddressPool.ID
   531  		}
   532  
   533  		if len(lbbgSettingId) == 0 && u.Properties.DefaultBackendHTTPSettings != nil {
   534  			lbbgSettingId = u.Properties.DefaultBackendHTTPSettings.ID
   535  		}
   536  	}
   537  
   538  	if len(lbbgId) > 0 {
   539  		backendGroup = self.getBackendAddressPool(lbbgId)
   540  	}
   541  
   542  	if len(lbbgSettingId) > 0 {
   543  		backendSetting = self.getBackendHTTPSettingsCollection(lbbgSettingId)
   544  		backendPort = backendSetting.Properties.Port
   545  	}
   546  
   547  	if backendSetting != nil && backendSetting.Properties.Probe != nil {
   548  		healthcheck = self.getProbe(backendSetting.Properties.Probe.ID)
   549  	}
   550  
   551  	return &SLoadBalancerListener{
   552  		lb:                self,
   553  		fp:                fp,
   554  		listener:          listener,
   555  		backendSetting:    backendSetting,
   556  		backendGroup:      backendGroup,
   557  		redirect:          redirect,
   558  		healthcheck:       healthcheck,
   559  		Name:              r.Name,
   560  		ID:                r.ID,
   561  		ProvisioningState: provisioningState,
   562  		IPVersion:         "",
   563  		Protocol:          listener.Properties.Protocol,
   564  		LoadDistribution:  "",
   565  		FrontendPort:      fpp.Properties.Port,
   566  		BackendPort:       backendPort,
   567  		ClientIdleTimeout: 0,
   568  		EnableFloatingIP:  false,
   569  		EnableTcpReset:    false,
   570  		rules:             rules,
   571  	}
   572  }
   573  
   574  func (self *SLoadbalancer) getNetworkLBListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
   575  	lbls := []cloudprovider.ICloudLoadbalancerListener{}
   576  	for i := range self.Properties.LoadBalancingRules {
   577  		u := self.Properties.LoadBalancingRules[i]
   578  		lbl := self.getNetworkLBListener(&u)
   579  		lbls = append(lbls, &lbl)
   580  	}
   581  
   582  	return lbls, nil
   583  }
   584  
   585  func (self *SLoadbalancer) getNetworkLBListener(u *LoadBalancingRule) SLoadBalancerListener {
   586  	fp := self.getFrontendIPConfiguration(u.Properties.FrontendIPConfiguration.ID)
   587  	backendGroup := self.getBackendAddressPool(u.Properties.BackendAddressPool.ID)
   588  	healthcheck := self.getProbe(u.Properties.Probe.ID)
   589  
   590  	return SLoadBalancerListener{
   591  		lb:                self,
   592  		fp:                fp,
   593  		backendGroup:      backendGroup,
   594  		healthcheck:       healthcheck,
   595  		Name:              u.Name,
   596  		ID:                u.ID,
   597  		ProvisioningState: u.Properties.ProvisioningState,
   598  		IPVersion:         "",
   599  		Protocol:          u.Properties.Protocol,
   600  		LoadDistribution:  u.Properties.LoadDistribution,
   601  		FrontendPort:      u.Properties.FrontendPort,
   602  		BackendPort:       u.Properties.BackendPort,
   603  		ClientIdleTimeout: u.Properties.IdleTimeoutInMinutes * 60,
   604  		EnableFloatingIP:  u.Properties.EnableFloatingIP,
   605  		EnableTcpReset:    u.Properties.EnableTCPReset,
   606  	}
   607  }
   608  
   609  // 应用型LB:  HTTP 设置 + 后端池 = onecloud 后端服务器组
   610  // 4层LB: loadBalancingRules(backendPort)+ 后端池 = onecloud 后端服务器组
   611  func (self *SLoadbalancer) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   612  	if self.lbbgs != nil {
   613  		return self.lbbgs, nil
   614  	}
   615  
   616  	lbls, err := self.GetILoadBalancerListeners()
   617  	if err != nil {
   618  		return nil, errors.Wrap(err, "GetILoadBalancerListeners")
   619  	}
   620  
   621  	bgIds := []string{}
   622  	ilbbgs := []cloudprovider.ICloudLoadbalancerBackendGroup{}
   623  	for i := range lbls {
   624  		lbl := lbls[i].(*SLoadBalancerListener)
   625  		if lbl.backendGroup == nil {
   626  			continue
   627  		}
   628  
   629  		bg := SLoadbalancerBackendGroup{
   630  			lb:           self,
   631  			Pool:         *lbl.backendGroup,
   632  			DefaultPort:  lbl.BackendPort,
   633  			HttpSettings: lbl.backendSetting,
   634  			BackendIps:   lbl.backendGroup.Properties.BackendIPConfigurations,
   635  		}
   636  
   637  		if !utils.IsInStringArray(bg.GetId(), bgIds) {
   638  			bgIds = append(bgIds, bg.GetId())
   639  			ilbbgs = append(ilbbgs, &bg)
   640  		}
   641  
   642  		// sync rules lbbg
   643  		if utils.IsInStringArray(lbl.GetListenerType(), []string{api.LB_LISTENER_TYPE_HTTP, api.LB_LISTENER_TYPE_HTTPS}) {
   644  			rules, err := lbl.GetILoadbalancerListenerRules()
   645  			if err != nil {
   646  				return nil, errors.Wrap(err, "GetILoadbalancerListenerRules")
   647  			}
   648  
   649  			for j := range rules {
   650  				rule := rules[j].(*SLoadbalancerListenerRule)
   651  				if rule.lbbg != nil && !utils.IsInStringArray(rule.lbbg.GetId(), bgIds) {
   652  					bgIds = append(bgIds, bg.GetId())
   653  					ilbbgs = append(ilbbgs, &bg)
   654  				}
   655  			}
   656  		}
   657  	}
   658  
   659  	self.lbbgs = ilbbgs
   660  	return ilbbgs, nil
   661  }
   662  
   663  func (self *SLoadbalancer) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   664  	lbbgs, err := self.GetILoadBalancerBackendGroups()
   665  	if err != nil {
   666  		return nil, errors.Wrap(err, "GetILoadBalancerBackendGroups")
   667  	}
   668  
   669  	for i := range lbbgs {
   670  		if lbbgs[i].GetId() == groupId {
   671  			return lbbgs[i], nil
   672  		}
   673  	}
   674  
   675  	return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerBackendGroupById")
   676  }
   677  
   678  func (self *SLoadbalancer) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   679  	return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerBackendGroup")
   680  }
   681  
   682  func (self *SLoadbalancer) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) (cloudprovider.ICloudLoadbalancerListener, error) {
   683  	return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerListener")
   684  }
   685  
   686  func (self *SLoadbalancer) getNetworkLBListenerById(id string) (cloudprovider.ICloudLoadbalancerListener, error) {
   687  	for i := range self.Properties.LoadBalancingRules {
   688  		u := self.Properties.LoadBalancingRules[i]
   689  		if u.ID == id {
   690  			lbl := self.getNetworkLBListener(&u)
   691  			return &lbl, nil
   692  		}
   693  	}
   694  
   695  	return nil, errors.Wrap(cloudprovider.ErrNotFound, "getNetworkLBListenerById")
   696  }
   697  
   698  func (self *SLoadbalancer) getAppLBListenerById(id string) (cloudprovider.ICloudLoadbalancerListener, error) {
   699  	for i := range self.Properties.RequestRoutingRules {
   700  		r := self.Properties.RequestRoutingRules[i]
   701  		if r.ID == id {
   702  			u := self.getURLPathMap(strings.Replace(r.ID, "requestRoutingRules", "urlPathMaps", 1))
   703  			return self.getAppLBListener(&r, u), nil
   704  		}
   705  	}
   706  
   707  	return nil, errors.Wrap(cloudprovider.ErrNotFound, "getAppLBListenerById")
   708  }
   709  
   710  func (self *SLoadbalancer) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) {
   711  	if self.Type == "Microsoft.Network/applicationGateways" {
   712  		return self.getAppLBListenerById(listenerId)
   713  	} else {
   714  		return self.getNetworkLBListenerById(listenerId)
   715  	}
   716  }
   717  
   718  func (self *SLoadbalancer) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
   719  	icerts := []cloudprovider.ICloudLoadbalancerCertificate{}
   720  	ssl := self.Properties.SSLCertificates
   721  	for i := range ssl {
   722  		s := ssl[i]
   723  		cert := SLoadbalancerCert{
   724  			lb:        self,
   725  			Name:      s.Name,
   726  			ID:        s.ID,
   727  			PublicKey: s.Properties.PublicCertData,
   728  		}
   729  
   730  		icerts = append(icerts, &cert)
   731  	}
   732  
   733  	return icerts, nil
   734  }
   735  
   736  func (self *SLoadbalancer) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
   737  	ssl := self.Properties.SSLCertificates
   738  	for i := range ssl {
   739  		s := ssl[i]
   740  		if s.ID == certId {
   741  			return &SLoadbalancerCert{
   742  				lb:        self,
   743  				Name:      s.Name,
   744  				ID:        s.ID,
   745  				PublicKey: s.Properties.PublicCertData,
   746  			}, nil
   747  		}
   748  	}
   749  
   750  	return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerCertificateById")
   751  }