yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/google/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 google
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"strings"
    21  	"time"
    22  
    23  	"yunion.io/x/jsonutils"
    24  	"yunion.io/x/log"
    25  	"yunion.io/x/pkg/errors"
    26  	"yunion.io/x/pkg/utils"
    27  
    28  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    29  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    30  )
    31  
    32  // 全球负载均衡 https://cloud.google.com/compute/docs/reference/rest/v1/globalAddresses/list
    33  // 区域负载均衡 https://cloud.google.com/compute/docs/reference/rest/v1/addresses
    34  // https://cloud.google.com/compute/docs/reference/rest/v1/targetHttpProxies/get
    35  // https://cloud.google.com/compute/docs/reference/rest/v1/targetGrpcProxies/get
    36  // https://cloud.google.com/compute/docs/reference/rest/v1/targetHttpsProxies/get
    37  // https://cloud.google.com/compute/docs/reference/rest/v1/targetSslProxies/get
    38  // https://cloud.google.com/compute/docs/reference/rest/v1/targetTcpProxies/get
    39  
    40  type SLoadbalancer struct {
    41  	SResourceBase
    42  	region          *SRegion
    43  	urlMap          *SUrlMap           // http & https LB
    44  	backendServices []SBackendServices // tcp & udp LB. 或者 http & https 后端
    45  	instanceGroups  []SInstanceGroup
    46  	healthChecks    []HealthChecks
    47  
    48  	forwardRules []SForwardingRule // 服务IP地址
    49  	isHttpLb     bool              // 标记是否为http/https lb
    50  }
    51  
    52  func (self *SLoadbalancer) GetStatus() string {
    53  	return api.LB_STATUS_ENABLED
    54  }
    55  
    56  func (self *SLoadbalancer) Refresh() error {
    57  	lb, err := self.region.GetLoadbalancer(self.GetGlobalId())
    58  	if err != nil {
    59  		return errors.Wrap(err, "GetLoadbalancer")
    60  	}
    61  
    62  	err = jsonutils.Update(self, &lb)
    63  	if err != nil {
    64  		return errors.Wrap(err, "Refresh.Update")
    65  	}
    66  
    67  	self.healthChecks = nil
    68  	self.instanceGroups = nil
    69  	self.forwardRules = nil
    70  	if self.isHttpLb {
    71  		bss, err := self.GetBackendServices()
    72  		if err != nil {
    73  			return errors.Wrap(err, "GetForwardingRules")
    74  		}
    75  		self.backendServices = bss
    76  	}
    77  	return nil
    78  }
    79  
    80  func (self *SLoadbalancer) IsEmulated() bool {
    81  	return true
    82  }
    83  
    84  func (self *SLoadbalancer) GetSysTags() map[string]string {
    85  	frs, err := self.GetForwardingRules()
    86  	if err != nil {
    87  		return nil
    88  	}
    89  
    90  	ips := []string{}
    91  	for i := range frs {
    92  		if len(frs[i].IPAddress) > 0 {
    93  			ips = append(ips, frs[i].IPAddress)
    94  		}
    95  	}
    96  	data := map[string]string{}
    97  	data["FrontendIPs"] = strings.Join(ips, ",")
    98  	return data
    99  }
   100  
   101  func (self *SLoadbalancer) GetTags() (map[string]string, error) {
   102  	return map[string]string{}, nil
   103  }
   104  
   105  func (self *SLoadbalancer) SetTags(tags map[string]string, replace bool) error {
   106  	return cloudprovider.ErrNotSupported
   107  }
   108  
   109  func (self *SLoadbalancer) GetCreatedAt() time.Time {
   110  	return time.Time{}
   111  }
   112  
   113  func (self *SLoadbalancer) GetProjectId() string {
   114  	return self.region.GetProjectId()
   115  }
   116  
   117  /*
   118  对应forwardingRules地址,存在多个前端IP的情况下,只展示按拉丁字母排序最前的一个地址。其他地址需要到详情中查看
   119  External
   120  Internal
   121  InternalManaged
   122  InternalSelfManaged
   123  Invalid
   124  UndefinedLoadBalancingScheme
   125  */
   126  func (self *SLoadbalancer) GetAddress() string {
   127  	frs, err := self.GetForwardingRules()
   128  	if err != nil {
   129  		log.Errorf("GetAddress.GetForwardingRules %s", err)
   130  	}
   131  
   132  	for i := range frs {
   133  		sche := strings.ToLower(frs[i].LoadBalancingScheme)
   134  		if !utils.IsInStringArray(sche, []string{"invalid", "undefinedloadbalancingscheme"}) {
   135  			return frs[i].IPAddress
   136  		}
   137  	}
   138  
   139  	return ""
   140  }
   141  
   142  func (self *SLoadbalancer) GetAddressType() string {
   143  	frs, err := self.GetForwardingRules()
   144  	if err != nil {
   145  		return api.LB_ADDR_TYPE_INTRANET
   146  	}
   147  
   148  	for i := range frs {
   149  		sche := strings.ToLower(frs[i].LoadBalancingScheme)
   150  		if !utils.IsInStringArray(sche, []string{"invalid", "undefinedloadbalancingscheme"}) {
   151  			if sche == "external" {
   152  				return api.LB_ADDR_TYPE_INTERNET
   153  			} else {
   154  				return api.LB_ADDR_TYPE_INTRANET
   155  			}
   156  		}
   157  	}
   158  
   159  	return api.LB_ADDR_TYPE_INTERNET
   160  }
   161  
   162  func (self *SLoadbalancer) GetNetworkType() string {
   163  	return api.LB_NETWORK_TYPE_VPC
   164  }
   165  
   166  func (self *SLoadbalancer) GetNetworkIds() []string {
   167  	igs, err := self.GetInstanceGroups()
   168  	if err != nil {
   169  		log.Errorf("GetInstanceGroups %s", err)
   170  		return nil
   171  	}
   172  
   173  	selfLinks := make([]string, 0)
   174  	networkIds := make([]string, 0)
   175  	for i := range igs {
   176  		if utils.IsInStringArray(igs[i].Subnetwork, selfLinks) {
   177  			selfLinks = append(selfLinks, igs[i].Subnetwork)
   178  			network := SResourceBase{
   179  				Name:     "",
   180  				SelfLink: igs[i].Network,
   181  			}
   182  			networkIds = append(networkIds, network.GetGlobalId())
   183  		}
   184  	}
   185  
   186  	return networkIds
   187  }
   188  
   189  func (self *SLoadbalancer) GetVpcId() string {
   190  	networkIds := self.GetNetworkIds()
   191  	if len(networkIds) == 0 {
   192  		return ""
   193  	}
   194  	if len(networkIds) >= 1 {
   195  		vpc, err := self.region.GetVpc(networkIds[0])
   196  		if err == nil && vpc != nil {
   197  			return vpc.GetGlobalId()
   198  		}
   199  	}
   200  	return ""
   201  }
   202  
   203  func (self *SLoadbalancer) GetZoneId() string {
   204  	igs, err := self.GetInstanceGroups()
   205  	if err != nil {
   206  		log.Errorf("GetInstanceGroups %s", err)
   207  		return ""
   208  	}
   209  
   210  	for i := range igs {
   211  		if len(igs[i].Zone) > 0 {
   212  			zone := SResourceBase{
   213  				Name:     "",
   214  				SelfLink: igs[i].Zone,
   215  			}
   216  
   217  			return zone.GetGlobalId()
   218  		}
   219  	}
   220  
   221  	return ""
   222  }
   223  
   224  func (self *SLoadbalancer) GetZone1Id() string {
   225  	return ""
   226  }
   227  
   228  func (self *SLoadbalancer) GetLoadbalancerSpec() string {
   229  	if self.isHttpLb {
   230  		return "regional_http_lb"
   231  	}
   232  
   233  	return fmt.Sprintf("regional_%s", strings.ToLower(self.backendServices[0].Protocol))
   234  }
   235  
   236  func (self *SLoadbalancer) GetChargeType() string {
   237  	return api.LB_CHARGE_TYPE_BY_TRAFFIC
   238  }
   239  
   240  func (self *SLoadbalancer) GetEgressMbps() int {
   241  	return 0
   242  }
   243  
   244  func (self *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
   245  	frs, err := self.GetForwardingRules()
   246  	if err != nil {
   247  		log.Errorf("GetAddress.GetForwardingRules %s", err)
   248  	}
   249  
   250  	for i := range frs {
   251  		if strings.ToLower(frs[i].LoadBalancingScheme) == "external" {
   252  			eips, err := self.region.GetEips(frs[i].IPAddress, 0, "")
   253  			if err != nil {
   254  				log.Errorf("GetEips %s", err)
   255  			}
   256  
   257  			if len(eips) > 0 {
   258  				return &eips[0], nil
   259  			}
   260  		}
   261  	}
   262  
   263  	return nil, nil
   264  }
   265  
   266  func (self *SLoadbalancer) Delete(ctx context.Context) error {
   267  	return cloudprovider.ErrNotImplemented
   268  }
   269  
   270  func (self *SLoadbalancer) Start() error {
   271  	return cloudprovider.ErrNotSupported
   272  }
   273  
   274  func (self *SLoadbalancer) Stop() error {
   275  	return cloudprovider.ErrNotSupported
   276  }
   277  
   278  func (self *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
   279  	lbls, err := self.GetLoadbalancerListeners()
   280  	if err != nil {
   281  		return nil, errors.Wrap(err, "GetLoadbalancerListeners")
   282  	}
   283  
   284  	ilbls := make([]cloudprovider.ICloudLoadbalancerListener, len(lbls))
   285  	for i := range lbls {
   286  		ilbls[i] = &lbls[i]
   287  	}
   288  
   289  	return ilbls, nil
   290  }
   291  
   292  func (self *SLoadbalancer) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   293  	lbbgs, err := self.GetLoadbalancerBackendGroups()
   294  	if err != nil {
   295  		return nil, errors.Wrap(err, "GetLoadbalancerBackendGroups")
   296  	}
   297  
   298  	ilbbgs := make([]cloudprovider.ICloudLoadbalancerBackendGroup, len(lbbgs))
   299  	for i := range lbbgs {
   300  		ilbbgs[i] = &lbbgs[i]
   301  	}
   302  
   303  	return ilbbgs, nil
   304  }
   305  
   306  func (self *SLoadbalancer) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   307  	return nil, cloudprovider.ErrNotSupported
   308  }
   309  
   310  func (self *SLoadbalancer) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
   311  	lbbgs, err := self.GetLoadbalancerBackendGroups()
   312  	if err != nil {
   313  		return nil, errors.Wrap(err, "GetLoadbalancerBackendGroups")
   314  	}
   315  
   316  	for i := range lbbgs {
   317  		if lbbgs[i].GetGlobalId() == groupId {
   318  			return &lbbgs[i], nil
   319  		}
   320  	}
   321  
   322  	return nil, cloudprovider.ErrNotFound
   323  }
   324  
   325  func (self *SLoadbalancer) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) (cloudprovider.ICloudLoadbalancerListener, error) {
   326  	return nil, cloudprovider.ErrNotSupported
   327  }
   328  
   329  func (self *SLoadbalancer) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) {
   330  	lbls, err := self.GetLoadbalancerListeners()
   331  	if err != nil {
   332  		return nil, errors.Wrap(err, "GetLoadbalancerBackendGroups")
   333  	}
   334  
   335  	for i := range lbls {
   336  		if lbls[i].GetGlobalId() == listenerId {
   337  			return &lbls[i], nil
   338  		}
   339  	}
   340  
   341  	return nil, cloudprovider.ErrNotFound
   342  }
   343  
   344  // GET https://compute.googleapis.com/compute/v1/projects/{project}/aggregated/targetHttpProxies 前端监听
   345  //  tcp lb backend type: backend service
   346  func (self *SRegion) GetRegionalTcpLoadbalancers() ([]SLoadbalancer, error) {
   347  	bss, err := self.GetRegionalBackendServices("protocol eq TCP")
   348  	if err != nil {
   349  		return nil, errors.Wrap(err, "GetRegionalBackendServices")
   350  	}
   351  
   352  	lbs := make([]SLoadbalancer, len(bss))
   353  	for i := range bss {
   354  		lbs[i] = SLoadbalancer{
   355  			region: self,
   356  			SResourceBase: SResourceBase{
   357  				Name:     bss[i].Name,
   358  				SelfLink: bss[i].SelfLink,
   359  			},
   360  			urlMap:          nil,
   361  			backendServices: []SBackendServices{bss[i]},
   362  			forwardRules:    nil,
   363  		}
   364  	}
   365  
   366  	return lbs, nil
   367  }
   368  
   369  //  udp lb backend type: backend service
   370  func (self *SRegion) GetRegionalUdpLoadbalancers() ([]SLoadbalancer, error) {
   371  	bss, err := self.GetRegionalBackendServices("protocol eq UDP")
   372  	if err != nil {
   373  		return nil, errors.Wrap(err, "GetRegionalBackendServices")
   374  	}
   375  
   376  	lbs := make([]SLoadbalancer, len(bss))
   377  	for i := range bss {
   378  		lbs[i] = SLoadbalancer{
   379  			region: self,
   380  			SResourceBase: SResourceBase{
   381  				Name:     bss[i].Name,
   382  				SelfLink: bss[i].SelfLink,
   383  			},
   384  			urlMap:          nil,
   385  			backendServices: []SBackendServices{bss[i]},
   386  			forwardRules:    nil,
   387  		}
   388  	}
   389  
   390  	return lbs, nil
   391  }
   392  
   393  //  http&https lb: urlmaps
   394  func (self *SRegion) GetRegionalHTTPLoadbalancers() ([]SLoadbalancer, error) {
   395  	ums, err := self.GetRegionalUrlMaps("")
   396  	if err != nil {
   397  		return nil, errors.Wrap(err, "GetRegionalUrlMaps")
   398  	}
   399  
   400  	lbs := make([]SLoadbalancer, len(ums))
   401  	for i := range ums {
   402  		lbs[i] = SLoadbalancer{
   403  			region: self,
   404  			SResourceBase: SResourceBase{
   405  				Name:     ums[i].Name,
   406  				SelfLink: ums[i].SelfLink,
   407  			},
   408  			urlMap:          &ums[i],
   409  			backendServices: nil,
   410  			forwardRules:    nil,
   411  			isHttpLb:        true,
   412  		}
   413  	}
   414  
   415  	return lbs, nil
   416  }
   417  
   418  func (self *SRegion) GetRegionalLoadbalancers() ([]SLoadbalancer, error) {
   419  	lbs := make([]SLoadbalancer, 0)
   420  	funcs := []func() ([]SLoadbalancer, error){self.GetRegionalHTTPLoadbalancers, self.GetRegionalTcpLoadbalancers, self.GetRegionalUdpLoadbalancers}
   421  	for i := range funcs {
   422  		_lbs, err := funcs[i]()
   423  		if err != nil {
   424  			return nil, errors.Wrap(err, "GetRegionalLoadbalancers")
   425  		}
   426  		lbs = append(lbs, _lbs...)
   427  	}
   428  
   429  	return lbs, nil
   430  }
   431  
   432  func (self *SRegion) GetLoadbalancer(resourceId string) (SLoadbalancer, error) {
   433  	lb := SLoadbalancer{}
   434  	var err error
   435  	if strings.Contains(resourceId, "/urlMaps/") {
   436  		ret := SUrlMap{}
   437  		err = self.GetBySelfId(resourceId, &ret)
   438  		lb.isHttpLb = true
   439  		lb.urlMap = &ret
   440  		lb.SResourceBase = SResourceBase{
   441  			Name:     ret.Name,
   442  			SelfLink: ret.SelfLink,
   443  		}
   444  	} else {
   445  		ret := SBackendServices{}
   446  		err = self.GetBySelfId(resourceId, &ret)
   447  		lb.backendServices = []SBackendServices{ret}
   448  		lb.SResourceBase = SResourceBase{
   449  			Name:     ret.Name,
   450  			SelfLink: ret.SelfLink,
   451  		}
   452  	}
   453  
   454  	if err != nil {
   455  		return lb, errors.Wrapf(err, "get")
   456  	}
   457  
   458  	lb.region = self
   459  	return lb, nil
   460  }
   461  
   462  func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
   463  	lbs, err := self.GetRegionalLoadbalancers()
   464  	if err != nil {
   465  		return nil, errors.Wrap(err, "GetRegionalLoadbalancers")
   466  	}
   467  	ilbs := []cloudprovider.ICloudLoadbalancer{}
   468  	for i := range lbs {
   469  		ilbs = append(ilbs, &lbs[i])
   470  	}
   471  	return ilbs, nil
   472  }
   473  
   474  func (self *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) {
   475  	lb, err := self.GetLoadbalancer(loadbalancerId)
   476  	if err != nil {
   477  		return nil, errors.Wrap(err, "GetLoadbalancer")
   478  	}
   479  	return &lb, nil
   480  }