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