yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/huawei/region.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 "fmt" 19 "net/url" 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/util/secrules" 27 28 api "yunion.io/x/cloudmux/pkg/apis/compute" 29 "yunion.io/x/cloudmux/pkg/cloudprovider" 30 "yunion.io/x/cloudmux/pkg/multicloud" 31 "yunion.io/x/cloudmux/pkg/multicloud/huawei/client" 32 "yunion.io/x/cloudmux/pkg/multicloud/huawei/obs" 33 ) 34 35 type Locales struct { 36 EnUs string `json:"en-us"` 37 ZhCN string `json:"zh-cn"` 38 } 39 40 // https://support.huaweicloud.com/api-iam/zh-cn_topic_0067148043.html 41 type SRegion struct { 42 multicloud.SRegion 43 44 client *SHuaweiClient 45 ecsClient *client.Client 46 obsClient *obs.ObsClient // 对象存储client.请勿直接引用。 47 48 Description string `json:"description"` 49 ID string `json:"id"` 50 Locales Locales `json:"locales"` 51 ParentRegionID string `json:"parent_region_id"` 52 Type string `json:"type"` 53 54 izones []cloudprovider.ICloudZone 55 ivpcs []cloudprovider.ICloudVpc 56 57 storageCache *SStoragecache 58 } 59 60 func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { 61 return nil, cloudprovider.ErrNotImplemented 62 } 63 64 func (self *SRegion) GetClient() *SHuaweiClient { 65 return self.client 66 } 67 68 func (self *SRegion) getECSClient() (*client.Client, error) { 69 var err error 70 71 if len(self.client.projectId) > 0 { 72 project, err := self.client.GetProjectById(self.client.projectId) 73 if err != nil { 74 return nil, err 75 } 76 77 if !strings.Contains(project.Name, self.ID) { 78 return nil, errors.Errorf("region %s and project %s mismatch", self.ID, project.Name) 79 } 80 } 81 82 if self.ecsClient == nil { 83 self.ecsClient, err = self.client.newRegionAPIClient(self.ID) 84 if err != nil { 85 return nil, err 86 } 87 } 88 89 return self.ecsClient, err 90 } 91 92 func (self *SRegion) getOBSEndpoint() string { 93 return getOBSEndpoint(self.GetId()) 94 } 95 96 func (self *SRegion) getOBSClient() (*obs.ObsClient, error) { 97 if self.obsClient == nil { 98 obsClient, err := self.client.getOBSClient(self.GetId()) 99 if err != nil { 100 return nil, err 101 } 102 103 self.obsClient = obsClient 104 } 105 106 return self.obsClient, nil 107 } 108 109 func (self *SRegion) fetchZones() error { 110 zones := make([]SZone, 0) 111 err := doListAll(self.ecsClient.Zones.List, nil, &zones) 112 if err != nil { 113 return err 114 } 115 116 self.izones = make([]cloudprovider.ICloudZone, 0) 117 for i := range zones { 118 zone := zones[i] 119 zone.region = self 120 self.izones = append(self.izones, &zone) 121 } 122 return nil 123 } 124 125 func (self *SRegion) fetchIVpcs() error { 126 // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090625.html 127 vpcs := make([]SVpc, 0) 128 querys := map[string]string{ 129 "limit": "2048", 130 } 131 err := doListAllWithMarker(self.ecsClient.Vpcs.List, querys, &vpcs) 132 if err != nil { 133 return err 134 } 135 136 self.ivpcs = make([]cloudprovider.ICloudVpc, 0) 137 for i := range vpcs { 138 vpc := vpcs[i] 139 vpc.region = self 140 self.ivpcs = append(self.ivpcs, &vpc) 141 } 142 return nil 143 } 144 145 func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) { 146 if len(id) == 0 { 147 return nil, errors.Wrap(cloudprovider.ErrNotFound, "SRegion.GetIVMById") 148 } 149 150 instance, err := self.GetInstanceByID(id) 151 if err != nil { 152 return nil, err 153 } 154 return &instance, err 155 } 156 157 func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) { 158 return self.GetDisk(id) 159 } 160 161 func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo { 162 if info, ok := LatitudeAndLongitude[self.ID]; ok { 163 return info 164 } 165 return cloudprovider.SGeographicInfo{} 166 } 167 168 func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) { 169 elbs, err := self.GetLoadBalancers() 170 if err != nil { 171 return nil, err 172 } 173 174 ielbs := make([]cloudprovider.ICloudLoadbalancer, len(elbs)) 175 for i := range elbs { 176 elbs[i].region = self 177 ielbs[i] = &elbs[i] 178 } 179 180 return ielbs, nil 181 } 182 183 func (self *SRegion) GetLoadBalancers() ([]SLoadbalancer, error) { 184 lbs := []SLoadbalancer{} 185 params := url.Values{} 186 return lbs, self.lbListAll("elb/loadbalancers", params, "loadbalancers", &lbs) 187 } 188 189 func (self *SRegion) GetILoadBalancerById(id string) (cloudprovider.ICloudLoadbalancer, error) { 190 elb, err := self.GetLoadbalancer(id) 191 if err != nil { 192 return nil, err 193 } 194 return elb, nil 195 } 196 197 func (self *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) { 198 acl, err := self.GetLoadBalancerAcl(aclId) 199 if err != nil { 200 return nil, err 201 } 202 return acl, nil 203 } 204 205 func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) { 206 cert, err := self.GetLoadBalancerCertificate(certId) 207 if err != nil { 208 return nil, err 209 } 210 return cert, nil 211 } 212 213 func (self *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) { 214 ret, err := self.CreateLoadBalancerCertificate(cert) 215 if err != nil { 216 return nil, err 217 } 218 return ret, nil 219 } 220 221 func (self *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) { 222 ret, err := self.GetLoadBalancerAcls("") 223 if err != nil { 224 return nil, err 225 } 226 227 iret := make([]cloudprovider.ICloudLoadbalancerAcl, len(ret)) 228 for i := range ret { 229 ret[i].region = self 230 iret[i] = &ret[i] 231 } 232 return iret, nil 233 } 234 235 func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) { 236 ret, err := self.GetLoadBalancerCertificates() 237 if err != nil { 238 return nil, err 239 } 240 241 iret := make([]cloudprovider.ICloudLoadbalancerCertificate, len(ret)) 242 for i := range ret { 243 ret[i].region = self 244 iret[i] = &ret[i] 245 } 246 return iret, nil 247 } 248 249 // https://support.huaweicloud.com/api-iam/zh-cn_topic_0057845622.html 250 func (self *SRegion) GetId() string { 251 return self.ID 252 } 253 254 func (self *SRegion) GetName() string { 255 return fmt.Sprintf("%s %s", CLOUD_PROVIDER_HUAWEI_CN, self.Locales.ZhCN) 256 } 257 258 func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable { 259 en := fmt.Sprintf("%s %s", CLOUD_PROVIDER_HUAWEI_EN, self.Locales.EnUs) 260 table := cloudprovider.SModelI18nTable{} 261 table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en) 262 return table 263 } 264 265 func (self *SRegion) GetGlobalId() string { 266 return fmt.Sprintf("%s/%s", self.client.GetAccessEnv(), self.ID) 267 } 268 269 func (self *SRegion) GetStatus() string { 270 return api.CLOUD_REGION_STATUS_INSERVER 271 } 272 273 func (self *SRegion) Refresh() error { 274 return nil 275 } 276 277 func (self *SRegion) IsEmulated() bool { 278 return false 279 } 280 281 func (self *SRegion) GetLatitude() float32 { 282 if locationInfo, ok := LatitudeAndLongitude[self.ID]; ok { 283 return locationInfo.Latitude 284 } 285 return 0.0 286 } 287 288 func (self *SRegion) GetLongitude() float32 { 289 if locationInfo, ok := LatitudeAndLongitude[self.ID]; ok { 290 return locationInfo.Longitude 291 } 292 return 0.0 293 } 294 295 func (self *SRegion) fetchInfrastructure() error { 296 _, err := self.getECSClient() 297 if err != nil { 298 return err 299 } 300 301 if err := self.fetchZones(); err != nil { 302 return err 303 } 304 305 if err := self.fetchIVpcs(); err != nil { 306 return err 307 } 308 309 for i := 0; i < len(self.ivpcs); i += 1 { 310 vpc := self.ivpcs[i].(*SVpc) 311 wire := SWire{region: self, vpc: vpc} 312 vpc.addWire(&wire) 313 314 for j := 0; j < len(self.izones); j += 1 { 315 zone := self.izones[j].(*SZone) 316 zone.addWire(&wire) 317 } 318 } 319 return nil 320 } 321 322 func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) { 323 if self.izones == nil { 324 var err error 325 err = self.fetchInfrastructure() 326 if err != nil { 327 return nil, err 328 } 329 } 330 return self.izones, nil 331 } 332 333 func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) { 334 if self.ivpcs == nil { 335 err := self.fetchInfrastructure() 336 if err != nil { 337 return nil, err 338 } 339 } 340 return self.ivpcs, nil 341 } 342 343 func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) { 344 eips, err := self.GetEips("", nil) 345 if err != nil { 346 return nil, err 347 } 348 349 ret := []cloudprovider.ICloudEIP{} 350 for i := 0; i < len(eips); i += 1 { 351 eips[i].region = self 352 ret = append(ret, &eips[i]) 353 } 354 return ret, nil 355 } 356 357 func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) { 358 ivpcs, err := self.GetIVpcs() 359 if err != nil { 360 return nil, err 361 } 362 for i := 0; i < len(ivpcs); i += 1 { 363 if ivpcs[i].GetGlobalId() == id { 364 return ivpcs[i], nil 365 } 366 } 367 return nil, cloudprovider.ErrNotFound 368 } 369 370 func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) { 371 izones, err := self.GetIZones() 372 if err != nil { 373 return nil, err 374 } 375 for i := 0; i < len(izones); i += 1 { 376 if izones[i].GetGlobalId() == id { 377 return izones[i], nil 378 } 379 } 380 return nil, cloudprovider.ErrNotFound 381 } 382 383 func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) { 384 eip, err := self.GetEip(eipId) 385 if err != nil { 386 return nil, err 387 } 388 return eip, nil 389 } 390 391 // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0060595555.html 392 func (self *SRegion) DeleteSecurityGroup(secgroupId string) error { 393 return DoDelete(self.ecsClient.SecurityGroups.Delete, secgroupId, nil, nil) 394 } 395 396 func (self *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) { 397 return self.GetSecurityGroupDetails(secgroupId) 398 } 399 400 func (self *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) { 401 secgroups, err := self.GetSecurityGroups(opts.VpcId, opts.Name) 402 if err != nil { 403 return nil, err 404 } 405 if len(secgroups) == 0 { 406 return nil, cloudprovider.ErrNotFound 407 } 408 if len(secgroups) > 1 { 409 return nil, cloudprovider.ErrDuplicateId 410 } 411 secgroups[0].region = self 412 return &secgroups[0], nil 413 } 414 415 func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) { 416 return self.CreateSecurityGroup(conf.VpcId, conf.Name, conf.Desc) 417 } 418 419 // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090608.html 420 func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) { 421 return self.CreateVpc(opts.NAME, opts.CIDR, opts.Desc) 422 } 423 424 func (self *SRegion) CreateVpc(name, cidr, desc string) (*SVpc, error) { 425 params := map[string]interface{}{ 426 "vpc": map[string]string{ 427 "name": name, 428 "cidr": cidr, 429 "description": desc, 430 }, 431 } 432 vpc := &SVpc{region: self} 433 return vpc, DoCreate(self.ecsClient.Vpcs.Create, jsonutils.Marshal(params), vpc) 434 } 435 436 // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090596.html 437 // size: 1Mbit/s~2000Mbit/s 438 // bgpType: 5_telcom,5_union,5_bgp,5_sbgp. 439 // 东北-大连:5_telcom、5_union 440 // 华南-广州:5_sbgp 441 // 华东-上海二:5_sbgp 442 // 华北-北京一:5_bgp、5_sbgp 443 // 亚太-香港:5_bgp 444 func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) { 445 var ctype TInternetChargeType 446 switch eip.ChargeType { 447 case api.EIP_CHARGE_TYPE_BY_TRAFFIC: 448 ctype = InternetChargeByTraffic 449 case api.EIP_CHARGE_TYPE_BY_BANDWIDTH: 450 ctype = InternetChargeByBandwidth 451 } 452 453 // todo: 如何避免hardcode。集成到cloudmeta服务中? 454 if len(eip.BGPType) == 0 { 455 switch self.GetId() { 456 case "cn-north-1", "cn-east-2", "cn-south-1": 457 eip.BGPType = "5_sbgp" 458 case "cn-northeast-1": 459 eip.BGPType = "5_telcom" 460 case "cn-north-4", "ap-southeast-1", "ap-southeast-2", "eu-west-0": 461 eip.BGPType = "5_bgp" 462 case "cn-southwest-2": 463 eip.BGPType = "5_sbgp" 464 default: 465 eip.BGPType = "5_bgp" 466 } 467 } 468 469 // 华为云EIP名字最大长度64 470 if len(eip.Name) > 64 { 471 eip.Name = eip.Name[:64] 472 } 473 474 ieip, err := self.AllocateEIP(eip.Name, eip.BandwidthMbps, ctype, eip.BGPType, eip.ProjectId) 475 ieip.region = self 476 if err != nil { 477 return nil, err 478 } 479 480 err = cloudprovider.WaitStatus(ieip, api.EIP_STATUS_READY, 5*time.Second, 60*time.Second) 481 return ieip, err 482 } 483 484 func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { 485 snapshots, err := self.GetSnapshots("", "") 486 if err != nil { 487 log.Errorf("self.GetSnapshots fail %s", err) 488 return nil, err 489 } 490 491 ret := make([]cloudprovider.ICloudSnapshot, len(snapshots)) 492 for i := 0; i < len(snapshots); i += 1 { 493 snapshots[i].region = self 494 ret[i] = &snapshots[i] 495 } 496 return ret, nil 497 } 498 499 func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) { 500 snapshot, err := self.GetSnapshotById(snapshotId) 501 return &snapshot, err 502 } 503 504 func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) { 505 iHosts := make([]cloudprovider.ICloudHost, 0) 506 507 izones, err := self.GetIZones() 508 if err != nil { 509 return nil, err 510 } 511 for i := 0; i < len(izones); i += 1 { 512 iZoneHost, err := izones[i].GetIHosts() 513 if err != nil { 514 return nil, err 515 } 516 iHosts = append(iHosts, iZoneHost...) 517 } 518 return iHosts, nil 519 } 520 521 func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) { 522 izones, err := self.GetIZones() 523 if err != nil { 524 return nil, err 525 } 526 for i := 0; i < len(izones); i += 1 { 527 ihost, err := izones[i].GetIHostById(id) 528 if err == nil { 529 return ihost, nil 530 } else if errors.Cause(err) != cloudprovider.ErrNotFound { 531 return nil, err 532 } 533 } 534 return nil, cloudprovider.ErrNotFound 535 } 536 537 func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) { 538 iStores := make([]cloudprovider.ICloudStorage, 0) 539 540 izones, err := self.GetIZones() 541 if err != nil { 542 return nil, err 543 } 544 for i := 0; i < len(izones); i += 1 { 545 iZoneStores, err := izones[i].GetIStorages() 546 if err != nil { 547 return nil, err 548 } 549 iStores = append(iStores, iZoneStores...) 550 } 551 return iStores, nil 552 } 553 554 func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { 555 izones, err := self.GetIZones() 556 if err != nil { 557 return nil, err 558 } 559 for i := 0; i < len(izones); i += 1 { 560 istore, err := izones[i].GetIStorageById(id) 561 if err == nil { 562 return istore, nil 563 } else if errors.Cause(err) != cloudprovider.ErrNotFound { 564 return nil, err 565 } 566 } 567 return nil, cloudprovider.ErrNotFound 568 } 569 570 func (self *SRegion) GetProvider() string { 571 return CLOUD_PROVIDER_HUAWEI 572 } 573 574 func (self *SRegion) GetCloudEnv() string { 575 return self.client.cloudEnv 576 } 577 578 // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090615.html 579 // 目前desc字段并没有用到 580 func (self *SRegion) CreateSecurityGroup(vpcId string, name string, desc string) (*SSecurityGroup, error) { 581 // 华为不允许创建名称为default的安全组 582 if strings.ToLower(name) == "default" { 583 name = fmt.Sprintf("%s-%s", vpcId, name) 584 } 585 586 params := jsonutils.NewDict() 587 secgroupObj := jsonutils.NewDict() 588 secgroupObj.Add(jsonutils.NewString(name), "name") 589 if len(vpcId) > 0 && vpcId != api.NORMAL_VPC_ID { 590 secgroupObj.Add(jsonutils.NewString(vpcId), "vpc_id") 591 } 592 params.Add(secgroupObj, "security_group") 593 594 secgroup := SSecurityGroup{region: self} 595 err := DoCreate(self.ecsClient.SecurityGroups.Create, params, &secgroup) 596 return &secgroup, err 597 } 598 599 // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0087467071.html 600 func (self *SRegion) delSecurityGroupRule(secGrpRuleId string) error { 601 _, err := self.ecsClient.SecurityGroupRules.DeleteInContextWithSpec(nil, secGrpRuleId, "", nil, nil, "") 602 return err 603 } 604 605 func (self *SRegion) DeleteSecurityGroupRule(ruleId string) error { 606 return self.delSecurityGroupRule(ruleId) 607 } 608 609 func (self *SRegion) CreateSecurityGroupRule(secgroupId string, rule cloudprovider.SecurityRule) error { 610 return self.addSecurityGroupRules(secgroupId, rule) 611 } 612 613 // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0087451723.html 614 // icmp port对应关系:https://support.huaweicloud.com/api-vpc/zh-cn_topic_0024109590.html 615 func (self *SRegion) addSecurityGroupRules(secGrpId string, rule cloudprovider.SecurityRule) error { 616 direction := "" 617 if rule.Direction == secrules.SecurityRuleIngress { 618 direction = "ingress" 619 } else { 620 direction = "egress" 621 } 622 623 protocal := rule.Protocol 624 if rule.Protocol == secrules.PROTO_ANY { 625 protocal = "" 626 } 627 628 // imcp协议默认为any 629 if rule.Protocol == secrules.PROTO_ICMP { 630 return self.addSecurityGroupRule(secGrpId, direction, "-1", "-1", protocal, rule.IPNet.String()) 631 } 632 633 if len(rule.Ports) > 0 { 634 for _, port := range rule.Ports { 635 portStr := fmt.Sprintf("%d", port) 636 err := self.addSecurityGroupRule(secGrpId, direction, portStr, portStr, protocal, rule.IPNet.String()) 637 if err != nil { 638 return err 639 } 640 } 641 } else { 642 portStart := fmt.Sprintf("%d", rule.PortStart) 643 portEnd := fmt.Sprintf("%d", rule.PortEnd) 644 err := self.addSecurityGroupRule(secGrpId, direction, portStart, portEnd, protocal, rule.IPNet.String()) 645 if err != nil { 646 return err 647 } 648 } 649 650 return nil 651 } 652 653 func (self *SRegion) addSecurityGroupRule(secGrpId, direction, portStart, portEnd, protocol, ipNet string) error { 654 params := jsonutils.NewDict() 655 secgroupObj := jsonutils.NewDict() 656 secgroupObj.Add(jsonutils.NewString(secGrpId), "security_group_id") 657 secgroupObj.Add(jsonutils.NewString(direction), "direction") 658 secgroupObj.Add(jsonutils.NewString(ipNet), "remote_ip_prefix") 659 secgroupObj.Add(jsonutils.NewString("IPV4"), "ethertype") 660 // 端口为空或者1-65535 661 if len(portStart) > 0 && portStart != "0" && portStart != "-1" { 662 secgroupObj.Add(jsonutils.NewString(portStart), "port_range_min") 663 } 664 if len(portEnd) > 0 && portEnd != "0" && portEnd != "-1" { 665 secgroupObj.Add(jsonutils.NewString(portEnd), "port_range_max") 666 } 667 if len(protocol) > 0 { 668 secgroupObj.Add(jsonutils.NewString(protocol), "protocol") 669 } 670 params.Add(secgroupObj, "security_group_rule") 671 672 rule := SecurityGroupRule{} 673 return DoCreate(self.ecsClient.SecurityGroupRules.Create, params, &rule) 674 } 675 676 func (self *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) { 677 ret, err := self.CreateLoadBalancer(loadbalancer) 678 if err != nil { 679 return nil, err 680 } 681 682 return ret, nil 683 } 684 685 func (self *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) { 686 ret, err := self.CreateLoadBalancerAcl(acl) 687 if err != nil { 688 return nil, err 689 } 690 691 return ret, nil 692 } 693 694 func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) { 695 iBuckets, err := region.client.getIBuckets() 696 if err != nil { 697 return nil, errors.Wrap(err, "getIBuckets") 698 } 699 ret := make([]cloudprovider.ICloudBucket, 0) 700 for i := range iBuckets { 701 // huawei OBS is shared across projects 702 if iBuckets[i].GetLocation() == region.GetId() { 703 ret = append(ret, iBuckets[i]) 704 } 705 } 706 return ret, nil 707 } 708 709 func str2StorageClass(storageClassStr string) (obs.StorageClassType, error) { 710 if strings.EqualFold(storageClassStr, string(obs.StorageClassStandard)) { 711 return obs.StorageClassStandard, nil 712 } else if strings.EqualFold(storageClassStr, string(obs.StorageClassWarm)) { 713 return obs.StorageClassWarm, nil 714 } else if strings.EqualFold(storageClassStr, string(obs.StorageClassCold)) { 715 return obs.StorageClassCold, nil 716 } else { 717 return obs.StorageClassStandard, errors.Error("unsupported storageClass") 718 } 719 } 720 721 func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error { 722 obsClient, err := region.getOBSClient() 723 if err != nil { 724 return errors.Wrap(err, "region.getOBSClient") 725 } 726 input := &obs.CreateBucketInput{} 727 input.Bucket = name 728 input.Location = region.GetId() 729 if len(aclStr) > 0 { 730 if strings.EqualFold(aclStr, string(obs.AclPrivate)) { 731 input.ACL = obs.AclPrivate 732 } else if strings.EqualFold(aclStr, string(obs.AclPublicRead)) { 733 input.ACL = obs.AclPublicRead 734 } else if strings.EqualFold(aclStr, string(obs.AclPublicReadWrite)) { 735 input.ACL = obs.AclPublicReadWrite 736 } else { 737 return errors.Error("unsupported acl") 738 } 739 } 740 if len(storageClassStr) > 0 { 741 input.StorageClass, err = str2StorageClass(storageClassStr) 742 if err != nil { 743 return err 744 } 745 } 746 _, err = obsClient.CreateBucket(input) 747 if err != nil { 748 return errors.Wrap(err, "obsClient.CreateBucket") 749 } 750 region.client.invalidateIBuckets() 751 return nil 752 } 753 754 func obsHttpCode(err error) int { 755 switch httpErr := err.(type) { 756 case obs.ObsError: 757 return httpErr.StatusCode 758 case *obs.ObsError: 759 return httpErr.StatusCode 760 } 761 return -1 762 } 763 764 func (region *SRegion) DeleteIBucket(name string) error { 765 obsClient, err := region.getOBSClient() 766 if err != nil { 767 return errors.Wrap(err, "region.getOBSClient") 768 } 769 _, err = obsClient.DeleteBucket(name) 770 if err != nil { 771 if obsHttpCode(err) == 404 { 772 return nil 773 } 774 log.Debugf("%#v %s", err, err) 775 return errors.Wrap(err, "DeleteBucket") 776 } 777 region.client.invalidateIBuckets() 778 return nil 779 } 780 781 func (region *SRegion) HeadBucket(name string) (*obs.BaseModel, error) { 782 obsClient, err := region.getOBSClient() 783 if err != nil { 784 return nil, errors.Wrap(err, "region.getOBSClient") 785 } 786 return obsClient.HeadBucket(name) 787 } 788 789 func (region *SRegion) IBucketExist(name string) (bool, error) { 790 _, err := region.HeadBucket(name) 791 if err != nil { 792 if obsHttpCode(err) == 404 { 793 return false, nil 794 } else { 795 return false, errors.Wrap(err, "HeadBucket") 796 } 797 } 798 return true, nil 799 } 800 801 func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) { 802 return cloudprovider.GetIBucketById(region, name) 803 } 804 805 func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) { 806 return region.GetIBucketById(name) 807 } 808 809 func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) { 810 return nil, cloudprovider.ErrNotImplemented 811 } 812 813 func (self *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) { 814 caches, err := self.GetElasticCaches() 815 if err != nil { 816 return nil, err 817 } 818 819 icaches := make([]cloudprovider.ICloudElasticcache, len(caches)) 820 for i := range caches { 821 caches[i].region = self 822 icaches[i] = &caches[i] 823 } 824 825 return icaches, nil 826 } 827 828 func (region *SRegion) GetCapabilities() []string { 829 return region.client.GetCapabilities() 830 } 831 832 func (self *SRegion) GetDiskTypes() ([]SDiskType, error) { 833 ret, err := self.ecsClient.Disks.GetDiskTypes() 834 if err != nil { 835 return nil, errors.Wrap(err, "GetDiskTypes") 836 } 837 838 dts := []SDiskType{} 839 _ret := jsonutils.NewArray(ret.Data...) 840 err = _ret.Unmarshal(&dts) 841 if err != nil { 842 return nil, errors.Wrap(err, "Unmarshal") 843 } 844 845 return dts, nil 846 } 847 848 func (self *SRegion) GetZoneSupportedDiskTypes(zoneId string) ([]string, error) { 849 dts, err := self.GetDiskTypes() 850 if err != nil { 851 return nil, errors.Wrap(err, "GetDiskTypes") 852 } 853 854 ret := []string{} 855 for i := range dts { 856 if dts[i].IsAvaliableInZone(zoneId) { 857 ret = append(ret, dts[i].Name) 858 } 859 } 860 861 return ret, nil 862 }