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