yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/hcs/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 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 26 api "yunion.io/x/cloudmux/pkg/apis/compute" 27 "yunion.io/x/cloudmux/pkg/cloudprovider" 28 "yunion.io/x/cloudmux/pkg/multicloud" 29 "yunion.io/x/cloudmux/pkg/multicloud/huawei" 30 ) 31 32 type InsertHeaders struct { 33 XForwardedELBIP bool `json:"X-Forwarded-ELB-IP"` 34 } 35 36 type Loadbalancer struct { 37 Id string `json:"id"` 38 } 39 40 type SElbListener struct { 41 multicloud.SResourceBase 42 multicloud.SLoadbalancerRedirectBase 43 huawei.HuaweiTags 44 lb *SLoadbalancer 45 acl *SElbACL 46 backendgroup *SElbBackendGroup 47 48 ProtocolPort int `json:"protocol_port"` 49 Protocol string `json:"protocol"` 50 Description string `json:"description"` 51 AdminStateUp bool `json:"admin_state_up"` 52 Http2Enable bool `json:"http2_enable"` 53 Loadbalancers []Loadbalancer `json:"loadbalancers"` 54 TenantId string `json:"tenant_id"` 55 ProjectId string `json:"project_id"` 56 ConnectionLimit int `json:"connection_limit"` 57 DefaultPoolId string `json:"default_pool_id"` 58 Id string `json:"id"` 59 Name string `json:"name"` 60 CreatedAt time.Time `json:"created_at"` 61 UpdatedAt time.Time `json:"updated_at"` 62 InsertHeaders InsertHeaders `json:"insert_headers"` 63 DefaultTlsContainerRef string `json:"default_tls_container_ref"` 64 } 65 66 func (self *SElbListener) GetId() string { 67 return self.Id 68 } 69 70 func (self *SElbListener) GetName() string { 71 return self.Name 72 } 73 74 func (self *SElbListener) GetGlobalId() string { 75 return self.GetId() 76 } 77 78 func (self *SElbListener) GetStatus() string { 79 return api.LB_STATUS_ENABLED 80 } 81 82 func (self *SElbListener) Refresh() error { 83 ilistener, err := self.lb.GetILoadBalancerListenerById(self.GetId()) 84 if err != nil { 85 return err 86 } 87 88 listener := ilistener.(*SElbListener) 89 listener.lb = self.lb 90 err = jsonutils.Update(self, listener) 91 if err != nil { 92 return err 93 } 94 95 return nil 96 } 97 98 func (self *SElbListener) IsEmulated() bool { 99 return false 100 } 101 102 func (self *SElbListener) GetProjectId() string { 103 return self.ProjectId 104 } 105 106 func (self *SElbListener) GetListenerType() string { 107 switch self.Protocol { 108 case "TCP": 109 return api.LB_LISTENER_TYPE_TCP 110 case "UDP": 111 return api.LB_LISTENER_TYPE_UDP 112 case "HTTP": 113 return api.LB_LISTENER_TYPE_HTTP 114 case "TERMINATED_HTTPS": 115 return api.LB_LISTENER_TYPE_HTTPS 116 case "HTTPS": 117 return api.LB_LISTENER_TYPE_HTTPS 118 default: 119 return "" 120 } 121 } 122 123 func (self *SElbListener) GetListenerPort() int { 124 return self.ProtocolPort 125 } 126 127 func (self *SElbListener) GetBackendGroup() (*SElbBackendGroup, error) { 128 if self.backendgroup == nil { 129 lbbgId := self.GetBackendGroupId() 130 if len(lbbgId) > 0 { 131 lbbg, err := self.lb.GetILoadBalancerBackendGroupById(lbbgId) 132 if err != nil { 133 return nil, err 134 } 135 136 self.backendgroup = lbbg.(*SElbBackendGroup) 137 } 138 } 139 140 return self.backendgroup, nil 141 } 142 143 func (self *SElbListener) GetScheduler() string { 144 lbbg, err := self.GetBackendGroup() 145 if err != nil { 146 log.Errorf("ElbListener GetScheduler %s", err.Error()) 147 } 148 149 if lbbg == nil { 150 return "" 151 } 152 153 return lbbg.GetScheduler() 154 } 155 156 func (self *SElbListener) GetAcl() (*SElbACL, error) { 157 if self.acl != nil { 158 return self.acl, nil 159 } 160 161 acls, err := self.lb.region.GetLoadBalancerAcls(self.GetId()) 162 if err != nil { 163 return nil, err 164 } 165 166 if len(acls) == 0 { 167 return nil, nil 168 } else { 169 self.acl = &acls[0] 170 return &acls[0], nil 171 } 172 } 173 174 func (self *SElbListener) GetAclStatus() string { 175 acl, err := self.GetAcl() 176 if err != nil { 177 log.Debugf("GetAclStatus %s", err) 178 return "" 179 } 180 181 if acl != nil && acl.EnableWhitelist { 182 return api.LB_BOOL_ON 183 } 184 185 return api.LB_BOOL_OFF 186 } 187 188 func (self *SElbListener) GetAclType() string { 189 return api.LB_ACL_TYPE_WHITE 190 } 191 192 func (self *SElbListener) GetAclId() string { 193 acl, err := self.GetAcl() 194 if err != nil { 195 log.Debugf("GetAclStatus %s", err) 196 return "" 197 } 198 199 if acl == nil { 200 return "" 201 } 202 203 return acl.GetId() 204 } 205 206 func (self *SElbListener) GetEgressMbps() int { 207 return 0 208 } 209 210 func (self *SElbListener) GetHealthCheck() string { 211 lbbg, err := self.GetBackendGroup() 212 if err != nil { 213 log.Errorf("ElbListener GetHealthCheck %s", err.Error()) 214 } 215 216 if lbbg == nil { 217 return "" 218 } 219 220 health, err := lbbg.GetHealthCheck() 221 if err != nil { 222 log.Errorf("ElbListener GetHealthCheck %s", err.Error()) 223 } 224 225 if health != nil { 226 return api.LB_BOOL_ON 227 } else { 228 return api.LB_BOOL_OFF 229 } 230 } 231 232 func (self *SElbListener) GetHealthCheckType() string { 233 lbbg, err := self.GetBackendGroup() 234 if err != nil { 235 log.Errorf("ElbListener GetHealthCheckType %s", err.Error()) 236 } 237 238 if lbbg == nil { 239 return "" 240 } 241 242 health, err := lbbg.GetHealthCheck() 243 if err != nil { 244 log.Errorf("ElbListener GetHealthCheckType %s", err.Error()) 245 } 246 247 if health != nil { 248 return health.HealthCheckType 249 } 250 251 return "" 252 } 253 254 func (self *SElbListener) GetHealthCheckTimeout() int { 255 lbbg, err := self.GetBackendGroup() 256 if err != nil { 257 log.Errorf("ElbListener GetHealthCheckTimeout %s", err.Error()) 258 } 259 260 if lbbg == nil { 261 return 0 262 } 263 264 health, err := lbbg.GetHealthCheck() 265 if err != nil { 266 log.Errorf("ElbListener GetHealthCheckTimeout %s", err.Error()) 267 } 268 269 if health != nil { 270 return health.HealthCheckTimeout 271 } 272 273 return 0 274 } 275 276 func (self *SElbListener) GetHealthCheckInterval() int { 277 lbbg, err := self.GetBackendGroup() 278 if err != nil { 279 log.Errorf("ElbListener GetHealthCheckInterval %s", err.Error()) 280 } 281 282 if lbbg == nil { 283 return 0 284 } 285 286 health, err := lbbg.GetHealthCheck() 287 if err != nil { 288 log.Errorf("ElbListener GetHealthCheckInterval %s", err.Error()) 289 } 290 291 if health != nil { 292 return health.HealthCheckInterval 293 } 294 295 return 0 296 } 297 298 func (self *SElbListener) GetHealthCheckRise() int { 299 lbbg, err := self.GetBackendGroup() 300 if err != nil { 301 log.Errorf("ElbListener GetHealthCheckRise %s", err.Error()) 302 } 303 304 if lbbg == nil { 305 return 0 306 } 307 308 health, err := lbbg.GetHealthCheck() 309 if err != nil { 310 log.Errorf("ElbListener GetHealthCheckRise %s", err.Error()) 311 } 312 313 if health != nil { 314 return health.HealthCheckRise 315 } else { 316 return 0 317 } 318 } 319 320 func (self *SElbListener) GetHealthCheckFail() int { 321 return 0 322 } 323 324 func (self *SElbListener) GetHealthCheckReq() string { 325 return "" 326 } 327 328 func (self *SElbListener) GetHealthCheckExp() string { 329 return "" 330 } 331 332 func (self *SElbListener) GetBackendGroupId() string { 333 return self.DefaultPoolId 334 } 335 336 func (self *SElbListener) GetBackendServerPort() int { 337 return 0 338 } 339 340 func (self *SElbListener) GetHealthCheckDomain() string { 341 lbbg, err := self.GetBackendGroup() 342 if err != nil { 343 log.Errorf("ElbListener GetHealthCheckDomain %s", err.Error()) 344 } 345 346 if lbbg == nil { 347 return "" 348 } 349 350 health, err := lbbg.GetHealthCheck() 351 if err != nil { 352 log.Errorf("ElbListener GetHealthCheckDomain %s", err.Error()) 353 } 354 355 if health != nil { 356 return health.HealthCheckDomain 357 } 358 359 return "" 360 } 361 362 func (self *SElbListener) GetHealthCheckURI() string { 363 lbbg, err := self.GetBackendGroup() 364 if err != nil { 365 log.Errorf("ElbListener GetHealthCheckURI %s", err.Error()) 366 } 367 368 if lbbg == nil { 369 return "" 370 } 371 372 health, err := lbbg.GetHealthCheck() 373 if err != nil { 374 log.Errorf("ElbListener GetHealthCheckURI %s", err.Error()) 375 } 376 377 if health != nil { 378 return health.HealthCheckURI 379 } 380 381 return "" 382 } 383 384 func (self *SElbListener) GetHealthCheckCode() string { 385 return "" 386 } 387 388 // https://support.huaweicloud.com/api-elb/zh-cn_topic_0136295317.html 389 func (self *SElbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) { 390 l7policy, err := self.lb.region.CreateLoadBalancerPolicy(self.GetId(), rule) 391 if err != nil { 392 return nil, err 393 } 394 395 l7policy.region = self.lb.region 396 l7policy.lb = self.lb 397 l7policy.listener = self 398 return l7policy, nil 399 } 400 401 func (self *SElbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) { 402 ret := &SElbListenerPolicy{region: self.lb.region, lb: self.lb, listener: self} 403 return ret, self.lb.region.lbGet("lbaas/l7policies/"+ruleId, ret) 404 } 405 406 func (self *SElbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) { 407 ret, err := self.lb.region.GetLoadBalancerPolicies(self.GetId()) 408 if err != nil { 409 return nil, err 410 } 411 412 iret := []cloudprovider.ICloudLoadbalancerListenerRule{} 413 for i := range ret { 414 rule := ret[i] 415 rule.listener = self 416 rule.lb = self.lb 417 rule.region = self.lb.region 418 iret = append(iret, &rule) 419 } 420 421 return iret, nil 422 } 423 424 func (self *SElbListener) GetStickySession() string { 425 lbbg, err := self.GetBackendGroup() 426 if err != nil { 427 log.Errorf("ElbListener GetStickySession %s", err.Error()) 428 } 429 430 if lbbg == nil { 431 return "" 432 } 433 434 stickySession, err := lbbg.GetStickySession() 435 if err != nil { 436 log.Errorf("ElbListener GetStickySession %s", err.Error()) 437 } 438 439 if stickySession != nil { 440 return stickySession.StickySession 441 } 442 443 return "" 444 } 445 446 func (self *SElbListener) GetStickySessionType() string { 447 lbbg, err := self.GetBackendGroup() 448 if err != nil { 449 log.Errorf("ElbListener GetStickySessionType %s", err.Error()) 450 } 451 452 if lbbg == nil { 453 return "" 454 } 455 456 stickySession, err := lbbg.GetStickySession() 457 if err != nil { 458 log.Errorf("ElbListener GetStickySessionType %s", err.Error()) 459 } 460 461 if stickySession != nil { 462 return stickySession.StickySessionType 463 } 464 465 return "" 466 } 467 468 func (self *SElbListener) GetStickySessionCookie() string { 469 lbbg, err := self.GetBackendGroup() 470 if err != nil { 471 log.Errorf("ElbListener GetStickySessionCookie %s", err.Error()) 472 } 473 474 if lbbg == nil { 475 return "" 476 } 477 478 stickySession, err := lbbg.GetStickySession() 479 if err != nil { 480 log.Errorf("ElbListener GetStickySessionCookie %s", err.Error()) 481 } 482 483 if stickySession != nil { 484 return stickySession.StickySessionCookie 485 } 486 487 return "" 488 } 489 490 func (self *SElbListener) GetStickySessionCookieTimeout() int { 491 lbbg, err := self.GetBackendGroup() 492 if err != nil { 493 log.Errorf("ElbListener GetStickySessionCookieTimeout %s", err.Error()) 494 } 495 496 if lbbg == nil { 497 return 0 498 } 499 500 stickySession, err := lbbg.GetStickySession() 501 if err != nil { 502 log.Errorf("ElbListener GetStickySessionCookieTimeout %s", err.Error()) 503 } 504 505 if stickySession != nil { 506 return stickySession.StickySessionCookieTimeout 507 } 508 509 return 0 510 } 511 512 func (self *SElbListener) XForwardedForEnabled() bool { 513 return self.InsertHeaders.XForwardedELBIP 514 } 515 516 func (self *SElbListener) GzipEnabled() bool { 517 return false 518 } 519 520 func (self *SElbListener) GetCertificateId() string { 521 return self.DefaultTlsContainerRef 522 } 523 524 func (self *SElbListener) GetTLSCipherPolicy() string { 525 return "" 526 } 527 528 func (self *SElbListener) HTTP2Enabled() bool { 529 return self.Http2Enable 530 } 531 532 func (self *SElbListener) Start() error { 533 return nil 534 } 535 536 func (self *SElbListener) Stop() error { 537 return cloudprovider.ErrNotSupported 538 } 539 540 // https://support.huaweicloud.com/api-elb/zh-cn_topic_0096561544.html 541 /* 542 default_pool_id有如下限制: 543 不能更新为其他监听器的default_pool。 544 不能更新为其他监听器的关联的转发策略所使用的pool。 545 default_pool_id对应的后端云服务器组的protocol和监听器的protocol有如下关系: 546 监听器的protocol为TCP时,后端云服务器组的protocol必须为TCP。 547 监听器的protocol为UDP时,后端云服务器组的protocol必须为UDP。 548 监听器的protocol为HTTP或TERMINATED_HTTPS时,后端云服务器组的protocol必须为HTTP。 549 */ 550 func (self *SElbListener) Sync(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) error { 551 return self.lb.region.UpdateLoadBalancerListener(self.GetId(), listener) 552 } 553 554 func (self *SElbListener) Delete(ctx context.Context) error { 555 return self.lb.region.lbDelete("lbaas/listeners/" + self.GetId()) 556 } 557 558 func (self *SRegion) UpdateLoadBalancerListener(listenerId string, listener *cloudprovider.SLoadbalancerListener) error { 559 params := map[string]interface{}{ 560 "name": listener.Name, 561 "description": listener.Description, 562 "http2_enable": listener.EnableHTTP2, 563 "default_pool_id": jsonutils.JSONNull, 564 } 565 if len(listener.BackendGroupID) > 0 { 566 params["default_pool_id"] = listener.BackendGroupID 567 } 568 569 if listener.ListenerType == api.LB_LISTENER_TYPE_HTTPS { 570 params["default_tls_container_ref"] = listener.CertificateID 571 } 572 573 if listener.XForwardedFor { 574 params["insert_headers"] = map[string]interface{}{ 575 "X-Forwarded-ELB-IP": listener.XForwardedFor, 576 } 577 } 578 return self.lbUpdate("elb/listeners/"+listenerId, map[string]interface{}{"listener": params}) 579 } 580 581 // https://support.huaweicloud.com/api-elb/zh-cn_topic_0136295315.html 582 func (self *SRegion) GetLoadBalancerPolicies(listenerId string) ([]SElbListenerPolicy, error) { 583 query := url.Values{} 584 if len(listenerId) > 0 { 585 query.Set("listener_id", listenerId) 586 } 587 588 ret := []SElbListenerPolicy{} 589 return ret, self.lbList("lbaas/l7policies", query, &ret) 590 } 591 592 // https://support.huaweicloud.com/api-elb/zh-cn_topic_0116649234.html 593 func (self *SRegion) GetLoadBalancerPolicyRules(policyId string) ([]SElbListenerPolicyRule, error) { 594 ret := []SElbListenerPolicyRule{} 595 return ret, self.lbList(fmt.Sprintf("lbaas/l7policies/%s/rules", policyId), url.Values{}, &ret) 596 } 597 598 // https://support.huaweicloud.com/api-elb/zh-cn_topic_0136295317.html 599 func (self *SRegion) CreateLoadBalancerPolicy(listenerId string, rule *cloudprovider.SLoadbalancerListenerRule) (*SElbListenerPolicy, error) { 600 ret := &SElbListenerPolicy{} 601 params := map[string]interface{}{ 602 "name": rule.Name, 603 "listener_id": listenerId, 604 "action": "REDIRECT_TO_POOL", 605 "redirect_pool_id": rule.BackendGroupID, 606 } 607 err := self.lbCreate("lbaas/l7policies", map[string]interface{}{"l7policy": params}, ret) 608 if err != nil { 609 return nil, err 610 } 611 if len(rule.Domain) > 0 { 612 params := map[string]interface{}{ 613 "type": "HOST_NAME", 614 "value": rule.Domain, 615 "compare_type": "EQUAL_TO", 616 } 617 err := self.lbCreate(fmt.Sprintf("lbaas/l7policies/%s/rules", ret.GetId()), map[string]interface{}{"rule": params}, nil) 618 if err != nil { 619 return ret, err 620 } 621 } 622 623 if len(rule.Path) > 0 { 624 params := map[string]interface{}{ 625 "type": "PATH", 626 "value": rule.Path, 627 "compare_type": "EQUAL_TO", 628 } 629 err := self.lbCreate(fmt.Sprintf("lbaas/l7policies/%s/rules", ret.GetId()), map[string]interface{}{"rule": params}, nil) 630 if err != nil { 631 return ret, err 632 } 633 } 634 635 return ret, nil 636 } 637 638 func (self *SElbListener) GetClientIdleTimeout() int { 639 return 0 640 } 641 642 func (self *SElbListener) GetBackendConnectTimeout() int { 643 return 0 644 }