yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/google/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 google 16 17 import ( 18 "context" 19 "fmt" 20 "strconv" 21 "strings" 22 "time" 23 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 ) 30 31 type SLoadbalancerListener struct { 32 lb *SLoadbalancer 33 rules []SLoadbalancerListenerRule 34 forwardRule SForwardingRule // 服务IP地址 35 backendService SBackendServices // 36 httpProxy *STargetHttpProxy // http 37 httpsProxy *STargetHttpsProxy // https 38 healthChecks []HealthChecks 39 40 ForwardRuleName string `json:"forward_rule_name"` 41 BackendServiceName string `json:"backend_service_name"` 42 Protocol string `json:"protocol"` 43 Port string `json:"port"` // 监听端口 44 } 45 46 func (self *SLoadbalancerListener) GetId() string { 47 return fmt.Sprintf("%s::%s::%s", self.forwardRule.GetGlobalId(), self.backendService.GetGlobalId(), self.Port) 48 } 49 50 func (self *SLoadbalancerListener) GetName() string { 51 return fmt.Sprintf("%s::%s::%s", self.forwardRule.GetName(), self.backendService.GetName(), self.Port) 52 } 53 54 func (self *SLoadbalancerListener) GetGlobalId() string { 55 return self.GetId() 56 } 57 58 func (self *SLoadbalancerListener) GetStatus() string { 59 return api.LB_STATUS_ENABLED 60 } 61 62 func (self *SLoadbalancerListener) Refresh() error { 63 return nil 64 } 65 66 func (self *SLoadbalancerListener) IsEmulated() bool { 67 return true 68 } 69 70 func (self *SLoadbalancerListener) GetCreatedAt() time.Time { 71 return time.Time{} 72 } 73 74 func (self *SLoadbalancerListener) GetSysTags() map[string]string { 75 return nil 76 } 77 78 func (self *SLoadbalancerListener) GetTags() (map[string]string, error) { 79 if len(self.forwardRule.IPAddress) > 0 { 80 return map[string]string{"FrontendIP": self.forwardRule.IPAddress}, nil 81 } 82 83 return map[string]string{}, nil 84 } 85 86 func (self *SLoadbalancerListener) SetTags(tags map[string]string, replace bool) error { 87 return cloudprovider.ErrNotSupported 88 } 89 90 func (self *SLoadbalancerListener) GetProjectId() string { 91 return self.lb.GetProjectId() 92 } 93 94 func (self *SLoadbalancerListener) GetListenerType() string { 95 return self.Protocol 96 } 97 98 func (self *SLoadbalancerListener) GetListenerPort() int { 99 port, err := strconv.Atoi(self.Port) 100 if err != nil { 101 log.Errorf("GetListenerPort %s", err) 102 return 0 103 } 104 105 return port 106 } 107 108 /* 109 在本地范围内使用的负载均衡算法。可能的值为: 110 111 ROUND_ROBIN:这是一个简单的策略,其中按循环顺序选择每个健康的后端。这是默认设置。 112 LEAST_REQUEST:一种 O(1) 算法,它选择两个随机的健康主机并选择具有较少活动请求的主机。 113 RING_HASH:环/模散列负载均衡器对后端实现一致的散列。该算法的特性是从一组 N 个主机中添加/删除一个主机只会影响 1/N 的请求。 114 RANDOM:负载均衡器随机选择一个健康的主机。 115 ORIGINAL_DESTINATION:根据客户端连接元数据选择后端主机,即在连接被重定向到负载均衡器之前,连接被打开到与传入连接的目标地址相同的地址。 116 MAGLEV:用作环形哈希负载均衡器的替代品。Maglev 不如环哈希稳定,但具有更快的表查找构建时间和主机选择时间。有关磁悬浮的更多信息,请参阅https://ai.google/research/pubs/pub44824 117 此字段适用于: 118 119 service_protocol 设置为 HTTP、HTTPS 或 HTTP2,并且 load_balancing_scheme 设置为 INTERNAL_MANAGED 的区域后端服务。 120 load_balancing_scheme 设置为 INTERNAL_SELF_MANAGED 的全局后端服务。 121 如果 sessionAffinity 不为 NONE,并且该字段未设置为 MAGLEV 或 RING_HASH,则会话亲缘性设置不会生效。 122 123 当后端服务被绑定到目标 gRPC 代理且 validateForProxyless 字段设置为 true 的 URL 映射引用时,仅支持默认的 ROUND_ROBIN 策略。 124 */ 125 // todo: fix me ??? 126 func (self *SLoadbalancerListener) GetScheduler() string { 127 switch self.backendService.LocalityLBPolicy { 128 case "ROUND_ROBIN": 129 return api.LB_SCHEDULER_RR 130 case "LEAST_REQUEST": 131 return api.LB_SCHEDULER_WLC 132 case "RING_HASH": 133 return api.LB_SCHEDULER_QCH 134 case "ORIGINAL_DESTINATION": 135 return api.LB_SCHEDULER_SCH 136 case "MAGLEV": 137 return api.LB_SCHEDULER_MH 138 default: 139 return "" 140 } 141 } 142 143 func (self *SLoadbalancerListener) GetAclStatus() string { 144 return api.LB_BOOL_OFF 145 } 146 147 func (self *SLoadbalancerListener) GetAclType() string { 148 return "" 149 } 150 151 func (self *SLoadbalancerListener) GetAclId() string { 152 return "" 153 } 154 155 func (self *SLoadbalancerListener) GetEgressMbps() int { 156 return 0 157 } 158 159 func (self *SLoadbalancerListener) GetBackendGroupId() string { 160 return self.backendService.GetGlobalId() 161 } 162 163 func (self *SLoadbalancerListener) GetBackendServerPort() int { 164 igs, err := self.GetInstanceGroups() 165 if err != nil { 166 log.Errorf("GetInstanceGroups %s", err) 167 return 0 168 } 169 170 for i := range igs { 171 for j := range igs[i].NamedPorts { 172 if igs[i].NamedPorts[j].Name == self.backendService.PortName { 173 return int(igs[i].NamedPorts[j].Port) 174 } 175 } 176 } 177 178 return 0 179 } 180 181 func (self *SLoadbalancerListener) GetClientIdleTimeout() int { 182 return int(self.backendService.ConnectionDraining.DrainingTimeoutSEC) 183 } 184 185 func (self *SLoadbalancerListener) GetBackendConnectTimeout() int { 186 return int(self.backendService.TimeoutSEC) 187 } 188 189 func (self *SLoadbalancerListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) { 190 return nil, cloudprovider.ErrNotImplemented 191 } 192 193 func (self *SLoadbalancerListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) { 194 rules, err := self.GetLoadbalancerListenerRules() 195 if err != nil { 196 return nil, errors.Wrap(err, "GetLoadbalancerListenerRules") 197 } 198 199 for i := range rules { 200 if rules[i].GetGlobalId() == ruleId { 201 return &rules[i], nil 202 } 203 } 204 205 return nil, cloudprovider.ErrNotFound 206 } 207 208 func (self *SLoadbalancerListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) { 209 rules, err := self.GetLoadbalancerListenerRules() 210 if err != nil { 211 return nil, errors.Wrap(err, "GetLoadbalancerListenerRules") 212 } 213 214 irules := make([]cloudprovider.ICloudLoadbalancerListenerRule, len(rules)) 215 for i := range rules { 216 irules[i] = &rules[i] 217 } 218 219 return irules, nil 220 } 221 222 func (self *SLoadbalancerListener) GetStickySession() string { 223 if self.backendService.SessionAffinity == "NONE" { 224 return api.LB_BOOL_OFF 225 } else { 226 return api.LB_BOOL_ON 227 } 228 } 229 230 /* 231 https://cloud.google.com/load-balancing/docs/backend-service#sessionAffinity 232 区域级外部 HTTP(S) 负载均衡器: 233 无 (NONE) 234 客户端 IP (CLIENT_IP) 235 生成的 Cookie (GENERATED_COOKIE) 236 标头字段 (HEADER_FIELD) 237 HTTP Cookie (HTTP_COOKIE) 238 */ 239 func (self *SLoadbalancerListener) GetStickySessionType() string { 240 switch self.backendService.SessionAffinity { 241 case "HTTP_COOKIE": 242 return api.LB_STICKY_SESSION_TYPE_SERVER 243 case "GENERATED_COOKIE": 244 return api.LB_STICKY_SESSION_TYPE_INSERT 245 } 246 return self.backendService.SessionAffinity 247 } 248 249 func (self *SLoadbalancerListener) GetStickySessionCookie() string { 250 return self.backendService.ConsistentHash.HTTPCookie.Name 251 } 252 253 func (self *SLoadbalancerListener) GetStickySessionCookieTimeout() int { 254 if len(self.backendService.ConsistentHash.HTTPCookie.TTL.Seconds) == 0 { 255 return 0 256 } 257 258 sec, err := strconv.Atoi(self.backendService.ConsistentHash.HTTPCookie.TTL.Seconds) 259 if err != nil { 260 log.Debugf("GetStickySessionCookieTimeout %s", err) 261 return 0 262 } 263 264 return sec 265 } 266 267 // https://cloud.google.com/load-balancing/docs/https 268 func (self *SLoadbalancerListener) XForwardedForEnabled() bool { 269 return true 270 } 271 272 // https://cloud.google.com/load-balancing/docs/https/troubleshooting-ext-https-lbs 273 func (self *SLoadbalancerListener) GzipEnabled() bool { 274 return false 275 } 276 277 func (self *SLoadbalancerListener) GetCertificateId() string { 278 if self.httpsProxy != nil && len(self.httpsProxy.SSLCertificates) > 0 { 279 cert := SResourceBase{ 280 Name: "", 281 SelfLink: self.httpsProxy.SSLCertificates[0], 282 } 283 return cert.GetGlobalId() 284 } 285 286 return "" 287 } 288 289 func (self *SLoadbalancerListener) GetTLSCipherPolicy() string { 290 return "" 291 } 292 293 // https://cloud.google.com/load-balancing/docs/https/troubleshooting-ext-https-lbs 294 func (self *SLoadbalancerListener) HTTP2Enabled() bool { 295 return true 296 } 297 298 // todo: fix me route 299 // 高级配置才有重定向,具体怎么解析? 300 func (self *SLoadbalancerListener) GetRedirect() string { 301 //self.lb.urlMap.PathMatchers[0].RouteRules[0].URLRedirect 302 return "" 303 } 304 305 func (self *SLoadbalancerListener) GetRedirectCode() int64 { 306 return 0 307 } 308 309 func (self *SLoadbalancerListener) GetRedirectScheme() string { 310 return "" 311 } 312 313 func (self *SLoadbalancerListener) GetRedirectHost() string { 314 return "" 315 } 316 317 func (self *SLoadbalancerListener) GetRedirectPath() string { 318 return "" 319 } 320 321 func (self *SLoadbalancerListener) GetHealthCheck() string { 322 if len(self.backendService.HealthChecks) > 0 { 323 return api.LB_BOOL_ON 324 } else { 325 return api.LB_BOOL_OFF 326 } 327 } 328 329 func (self *SLoadbalancerListener) GetHealthChecks() []HealthChecks { 330 if self.healthChecks != nil { 331 return self.healthChecks 332 } 333 334 hcm, err := self.lb.GetHealthCheckMaps() 335 if err != nil { 336 log.Errorf("GetHealthCheckMaps %s", err) 337 return nil 338 } 339 ret := make([]HealthChecks, 0) 340 for i := range self.backendService.HealthChecks { 341 hc := self.backendService.HealthChecks[i] 342 if _, ok := hcm[hc]; ok { 343 ret = append(ret, hcm[hc]) 344 } 345 } 346 347 self.healthChecks = ret 348 return ret 349 } 350 351 func (self *SLoadbalancerListener) GetHealthCheckType() string { 352 hcs := self.GetHealthChecks() 353 if hcs == nil { 354 return "" 355 } 356 357 switch strings.ToLower(hcs[0].Type) { 358 case "tcp": 359 return api.LB_HEALTH_CHECK_TCP 360 case "udp": 361 return api.LB_HEALTH_CHECK_UDP 362 case "http", "http2": 363 return api.LB_HEALTH_CHECK_HTTP 364 case "https", "ssl": 365 return api.LB_HEALTH_CHECK_HTTPS 366 default: 367 return "" 368 } 369 } 370 371 func (self *SLoadbalancerListener) GetHealthCheckTimeout() int { 372 hcs := self.GetHealthChecks() 373 if hcs == nil { 374 return 0 375 } 376 377 return int(hcs[0].TimeoutSEC) 378 } 379 380 func (self *SLoadbalancerListener) GetHealthCheckInterval() int { 381 hcs := self.GetHealthChecks() 382 if hcs == nil { 383 return 0 384 } 385 386 return int(hcs[0].CheckIntervalSEC) 387 } 388 389 func (self *SLoadbalancerListener) GetHealthCheckRise() int { 390 hcs := self.GetHealthChecks() 391 if hcs == nil { 392 return 0 393 } 394 395 return int(hcs[0].HealthyThreshold) 396 } 397 398 func (self *SLoadbalancerListener) GetHealthCheckFail() int { 399 hcs := self.GetHealthChecks() 400 if hcs == nil { 401 return 0 402 } 403 404 return int(hcs[0].UnhealthyThreshold) 405 } 406 407 func (self *SLoadbalancerListener) GetHealthCheckReq() string { 408 return "" 409 } 410 411 func (self *SLoadbalancerListener) GetHealthCheckExp() string { 412 return "" 413 } 414 415 func (self *SLoadbalancerListener) GetHealthCheckDomain() string { 416 hcs := self.GetHealthChecks() 417 if hcs == nil { 418 return "" 419 } 420 switch hcs[0].Type { 421 case "HTTPS": 422 return hcs[0].HTTPSHealthCheck.Host 423 case "HTTP2": 424 return hcs[0].Http2HealthCheck.Host 425 case "HTTP": 426 return hcs[0].HTTPHealthCheck.Host 427 default: 428 return "" 429 } 430 } 431 432 func (self *SLoadbalancerListener) GetHealthCheckURI() string { 433 hcs := self.GetHealthChecks() 434 if hcs == nil { 435 return "" 436 } 437 switch hcs[0].Type { 438 case "HTTPS": 439 return hcs[0].HTTPSHealthCheck.RequestPath 440 case "HTTP2": 441 return hcs[0].Http2HealthCheck.RequestPath 442 case "HTTP": 443 return hcs[0].HTTPHealthCheck.RequestPath 444 default: 445 return "" 446 } 447 } 448 449 func (self *SLoadbalancerListener) GetHealthCheckCode() string { 450 return "" 451 } 452 453 func (self *SLoadbalancerListener) Start() error { 454 return cloudprovider.ErrNotSupported 455 } 456 457 func (self *SLoadbalancerListener) Stop() error { 458 return cloudprovider.ErrNotSupported 459 } 460 461 func (self *SLoadbalancerListener) Sync(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) error { 462 return cloudprovider.ErrNotSupported 463 } 464 465 func (self *SLoadbalancerListener) Delete(ctx context.Context) error { 466 return cloudprovider.ErrNotSupported 467 } 468 469 func (self *SLoadbalancerListener) GetInstanceGroups() ([]SInstanceGroup, error) { 470 igs, err := self.lb.GetInstanceGroupsMap() 471 if err != nil { 472 return nil, errors.Wrap(err, "GetInstanceGroups") 473 } 474 475 ret := make([]SInstanceGroup, 0) 476 for i := range self.backendService.Backends { 477 b := self.backendService.Backends[i] 478 if ig, ok := igs[b.Group]; ok { 479 ret = append(ret, ig) 480 } 481 } 482 483 return ret, nil 484 } 485 486 func (self *SLoadbalancer) GetLoadbalancerListeners() ([]SLoadbalancerListener, error) { 487 if self.urlMap != nil { 488 return self.GetHTTPLoadbalancerListeners() 489 } else { 490 return self.GetNetworkLoadbalancerListeners() 491 } 492 } 493 494 func (self *SLoadbalancer) GetHTTPLoadbalancerListeners() ([]SLoadbalancerListener, error) { 495 frs, err := self.GetForwardingRules() 496 if err != nil { 497 return nil, errors.Wrap(err, "GetForwardingRules") 498 } 499 500 _hps, err := self.GetTargetHttpProxies() 501 if err != nil { 502 return nil, errors.Wrap(err, "GetTargetHttpProxies") 503 } 504 505 hps := make(map[string]STargetHttpProxy, 0) 506 for i := range _hps { 507 hps[_hps[i].SelfLink] = _hps[i] 508 } 509 510 _hsps, err := self.GetTargetHttpsProxies() 511 if err != nil { 512 return nil, errors.Wrap(err, "GetTargetHttpsProxies") 513 } 514 515 hsps := make(map[string]STargetHttpsProxy, 0) 516 for i := range _hsps { 517 hsps[_hsps[i].SelfLink] = _hsps[i] 518 } 519 520 bss, err := self.GetBackendServices() 521 if err != nil { 522 return nil, errors.Wrap(err, "GetBackendServices") 523 } 524 525 lbls := make([]SLoadbalancerListener, 0) 526 for i := range frs { 527 fr := frs[i] 528 for j := range bss { 529 bs := bss[j] 530 port := "80" 531 protocol := "http" 532 var hp STargetHttpProxy 533 var hsp STargetHttpsProxy 534 if fr.PortRange == "443-443" { 535 port = "443" 536 hsp = hsps[fr.Target] 537 protocol = "https" 538 } else if fr.PortRange == "8080-8080" { 539 port = "8080" 540 hp = hps[fr.Target] 541 } else { 542 hp = hps[fr.Target] 543 } 544 545 lbl := SLoadbalancerListener{ 546 lb: self, 547 forwardRule: fr, 548 backendService: bs, 549 httpProxy: &hp, 550 httpsProxy: &hsp, 551 ForwardRuleName: fr.GetName(), 552 BackendServiceName: bs.GetName(), 553 Protocol: protocol, 554 Port: port, 555 } 556 lbls = append(lbls, lbl) 557 } 558 } 559 560 return lbls, nil 561 } 562 563 func (self *SLoadbalancer) GetNetworkLoadbalancerListeners() ([]SLoadbalancerListener, error) { 564 frs, err := self.GetForwardingRules() 565 if err != nil { 566 return nil, errors.Wrap(err, "GetForwardingRules") 567 } 568 569 bss, err := self.GetBackendServices() 570 if err != nil { 571 return nil, errors.Wrap(err, "GetBackendServices") 572 } 573 574 lbls := make([]SLoadbalancerListener, 0) 575 for i := range frs { 576 fr := frs[i] 577 for j := range bss { 578 bs := bss[j] 579 for n := range fr.Ports { 580 lbl := SLoadbalancerListener{ 581 lb: self, 582 forwardRule: fr, 583 backendService: bs, 584 ForwardRuleName: fr.GetName(), 585 BackendServiceName: bs.GetName(), 586 Protocol: strings.ToLower(fr.IPProtocol), 587 Port: fr.Ports[n], 588 } 589 590 lbls = append(lbls, lbl) 591 } 592 } 593 } 594 595 return lbls, nil 596 }