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 }