yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/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 apsara 16 17 import ( 18 "fmt" 19 "strings" 20 "time" 21 22 "github.com/aliyun/alibaba-cloud-sdk-go/sdk" 23 "github.com/aliyun/aliyun-oss-go-sdk/oss" 24 25 "yunion.io/x/jsonutils" 26 "yunion.io/x/log" 27 "yunion.io/x/pkg/errors" 28 "yunion.io/x/pkg/util/regutils" 29 "yunion.io/x/pkg/utils" 30 31 api "yunion.io/x/cloudmux/pkg/apis/compute" 32 "yunion.io/x/cloudmux/pkg/cloudprovider" 33 "yunion.io/x/cloudmux/pkg/multicloud" 34 ) 35 36 type SRegion struct { 37 multicloud.SRegion 38 39 client *SApsaraClient 40 sdkClient *sdk.Client 41 42 RegionId string 43 LocalName string 44 45 izones []cloudprovider.ICloudZone 46 47 ivpcs []cloudprovider.ICloudVpc 48 49 lbEndpints map[string]string 50 51 storageCache *SStoragecache 52 53 instanceTypes []SInstanceType 54 55 latitude float64 56 longitude float64 57 fetchLocation bool 58 59 ossEndpoint string 60 } 61 62 func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { 63 return nil, cloudprovider.ErrNotImplemented 64 } 65 66 func (self *SRegion) GetClient() *SApsaraClient { 67 return self.client 68 } 69 70 func (self *SRegion) getSdkClient() (*sdk.Client, error) { 71 if self.sdkClient == nil { 72 var err error 73 self.sdkClient, err = self.GetClient().getDefaultClient(self.RegionId) 74 if err != nil { 75 return nil, err 76 } 77 } 78 return self.sdkClient, nil 79 } 80 81 func (self *SRegion) GetOssClient() (*oss.Client, error) { 82 if len(self.ossEndpoint) == 0 { 83 _, err := self.GetBuckets() 84 if err != nil { 85 return nil, err 86 } 87 if len(self.ossEndpoint) == 0 { 88 return nil, fmt.Errorf("no available buckets") 89 } 90 } 91 return self.client.getOssClient(self.ossEndpoint) 92 } 93 94 func (self *SRegion) productRequest(client *sdk.Client, product, domain, apiVersion, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) { 95 params["Product"] = product 96 return jsonRequest(client, domain, apiVersion, apiName, params, debug) 97 } 98 99 func (self *SRegion) ossRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { 100 params["RegionId"] = self.RegionId 101 return self.client.ossRequest(apiName, params) 102 } 103 104 func (self *SRegion) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { 105 client, err := self.getSdkClient() 106 if err != nil { 107 return nil, err 108 } 109 domain := self.client.getDomain(APSARA_PRODUCT_ECS) 110 params["Product"] = APSARA_PRODUCT_ECS 111 return jsonRequest(client, domain, APSARA_API_VERSION, apiName, params, self.client.debug) 112 } 113 114 func (self *SRegion) rdsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { 115 client, err := self.getSdkClient() 116 if err != nil { 117 return nil, err 118 } 119 domain := self.client.getDomain(APSARA_PRODUCT_RDS) 120 return self.productRequest(client, APSARA_PRODUCT_RDS, domain, APSARA_API_VERION_RDS, apiName, params, self.client.debug) 121 } 122 123 func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { 124 client, err := self.getSdkClient() 125 if err != nil { 126 return nil, err 127 } 128 domain := self.client.getDomain(APSARA_PRODUCT_VPC) 129 return self.productRequest(client, APSARA_PRODUCT_VPC, domain, APSARA_API_VERSION_VPC, action, params, self.client.debug) 130 } 131 132 func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { 133 client, err := self.getSdkClient() 134 if err != nil { 135 return nil, err 136 } 137 domain := self.client.getDomain(APSARA_PRODUCT_KVSTORE) 138 return self.productRequest(client, APSARA_PRODUCT_KVSTORE, domain, APSARA_API_VERSION_KVS, action, params, self.client.debug) 139 } 140 141 func (self *SRegion) tagRequest(serviceType string, action string, params map[string]string) (jsonutils.JSONObject, error) { 142 switch serviceType { 143 case APSARA_PRODUCT_ECS: 144 return self.ecsRequest(action, params) 145 case APSARA_PRODUCT_RDS: 146 return self.rdsRequest(action, params) 147 case APSARA_PRODUCT_SLB: 148 return self.lbRequest(action, params) 149 case APSARA_PRODUCT_KVSTORE: 150 return self.kvsRequest(action, params) 151 default: 152 return nil, errors.Wrapf(errors.ErrNotSupported, "not support %s service tag", serviceType) 153 } 154 } 155 156 func (self *SRegion) lbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { 157 client, err := self.getSdkClient() 158 if err != nil { 159 return nil, err 160 } 161 domain := self.client.getDomain(APSARA_PRODUCT_SLB) 162 return self.productRequest(client, APSARA_PRODUCT_SLB, domain, APSARA_API_VERSION_LB, apiName, params, self.client.debug) 163 } 164 165 ///////////////////////////////////////////////////////////////////////////// 166 func (self *SRegion) GetId() string { 167 return self.RegionId 168 } 169 170 func (self *SRegion) GetName() string { 171 switch self.client.cpcfg.Vendor { 172 case api.CLOUD_PROVIDER_APSARA: 173 return fmt.Sprintf("%s %s", CLOUD_PROVIDER_APSARA_CN, self.LocalName) 174 default: 175 return fmt.Sprintf("%s %s", CLOUD_PROVIDER_APSARA_CN, self.LocalName) 176 } 177 } 178 179 func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable { 180 en := fmt.Sprintf("%s %s", CLOUD_PROVIDER_APSARA_EN, self.LocalName) 181 table := cloudprovider.SModelI18nTable{} 182 table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en) 183 return table 184 } 185 186 func (self *SRegion) GetGlobalId() string { 187 return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_APSARA, self.RegionId) 188 } 189 190 func (self *SRegion) IsEmulated() bool { 191 return false 192 } 193 194 func (self *SRegion) GetProvider() string { 195 return self.client.cpcfg.Vendor 196 } 197 198 func (self *SRegion) GetCloudEnv() string { 199 return "" 200 } 201 202 func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo { 203 return cloudprovider.SGeographicInfo{} 204 } 205 206 func (self *SRegion) GetStatus() string { 207 return api.CLOUD_REGION_STATUS_INSERVER 208 } 209 210 func (self *SRegion) Refresh() error { 211 // do nothing 212 return nil 213 } 214 215 func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) { 216 if self.izones == nil { 217 var err error 218 err = self.fetchInfrastructure() 219 if err != nil { 220 return nil, err 221 } 222 } 223 return self.izones, nil 224 } 225 226 func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) { 227 izones, err := self.GetIZones() 228 if err != nil { 229 return nil, err 230 } 231 for i := 0; i < len(izones); i += 1 { 232 if izones[i].GetGlobalId() == id { 233 return izones[i], nil 234 } 235 } 236 return nil, cloudprovider.ErrNotFound 237 } 238 239 func (self *SRegion) getStoragecache() *SStoragecache { 240 if self.storageCache == nil { 241 self.storageCache = &SStoragecache{region: self} 242 } 243 return self.storageCache 244 } 245 246 func (self *SRegion) _fetchZones(chargeType TChargeType, spotStrategy SpotStrategyType) error { 247 params := make(map[string]string) 248 params["RegionId"] = self.RegionId 249 if len(chargeType) > 0 { 250 params["InstanceChargeType"] = string(chargeType) 251 } 252 if len(spotStrategy) > 0 { 253 params["SpotStrategy"] = string(spotStrategy) 254 } 255 body, err := self.ecsRequest("DescribeZones", params) 256 if err != nil { 257 return err 258 } 259 260 zones := make([]SZone, 0) 261 err = body.Unmarshal(&zones, "Zones", "Zone") 262 if err != nil { 263 return err 264 } 265 266 self.izones = make([]cloudprovider.ICloudZone, len(zones)) 267 268 for i := 0; i < len(zones); i += 1 { 269 zones[i].region = self 270 self.izones[i] = &zones[i] 271 } 272 273 return nil 274 } 275 276 func (self *SRegion) getZoneById(id string) (*SZone, error) { 277 izones, err := self.GetIZones() 278 if err != nil { 279 return nil, err 280 } 281 for i := 0; i < len(izones); i += 1 { 282 zone := izones[i].(*SZone) 283 if zone.ZoneId == id { 284 return zone, nil 285 } 286 } 287 return nil, fmt.Errorf("no such zone %s", id) 288 } 289 290 func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) { 291 return self.GetInstance(id) 292 } 293 294 func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) { 295 return self.getDisk(id) 296 } 297 298 func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) { 299 if self.ivpcs == nil { 300 err := self.fetchInfrastructure() 301 if err != nil { 302 return nil, err 303 } 304 } 305 return self.ivpcs, nil 306 } 307 308 func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) { 309 ivpcs, err := self.GetIVpcs() 310 if err != nil { 311 return nil, err 312 } 313 for i := 0; i < len(ivpcs); i += 1 { 314 if ivpcs[i].GetGlobalId() == id { 315 return ivpcs[i], nil 316 } 317 } 318 return nil, cloudprovider.ErrNotFound 319 } 320 321 func (self *SRegion) fetchIVpcs() error { 322 vpcs := make([]SVpc, 0) 323 for { 324 part, total, err := self.GetVpcs(nil, len(vpcs), 50) 325 if err != nil { 326 return err 327 } 328 vpcs = append(vpcs, part...) 329 if len(vpcs) >= total { 330 break 331 } 332 } 333 self.ivpcs = make([]cloudprovider.ICloudVpc, len(vpcs)) 334 for i := 0; i < len(vpcs); i += 1 { 335 vpcs[i].region = self 336 self.ivpcs[i] = &vpcs[i] 337 } 338 return nil 339 } 340 341 func (self *SRegion) fetchInfrastructure() error { 342 err := self._fetchZones(PostPaidInstanceChargeType, NoSpotStrategy) 343 if err != nil { 344 return err 345 } 346 err = self.fetchIVpcs() 347 if err != nil { 348 return err 349 } 350 for i := 0; i < len(self.ivpcs); i += 1 { 351 for j := 0; j < len(self.izones); j += 1 { 352 zone := self.izones[j].(*SZone) 353 vpc := self.ivpcs[i].(*SVpc) 354 wire := SWire{zone: zone, vpc: vpc} 355 zone.addWire(&wire) 356 vpc.addWire(&wire) 357 } 358 } 359 return nil 360 } 361 362 func (self *SRegion) GetVpcs(vpcId []string, offset int, limit int) ([]SVpc, int, error) { 363 if limit > 50 || limit <= 0 { 364 limit = 50 365 } 366 params := make(map[string]string) 367 params["RegionId"] = self.RegionId 368 params["PageSize"] = fmt.Sprintf("%d", limit) 369 params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) 370 371 if vpcId != nil && len(vpcId) > 0 { 372 params["VpcId"] = strings.Join(vpcId, ",") 373 } 374 375 body, err := self.ecsRequest("DescribeVpcs", params) 376 if err != nil { 377 log.Errorf("GetVpcs fail %s", err) 378 return nil, 0, err 379 } 380 381 vpcs := make([]SVpc, 0) 382 err = body.Unmarshal(&vpcs, "Vpcs", "Vpc") 383 if err != nil { 384 log.Errorf("Unmarshal vpc fail %s", err) 385 return nil, 0, err 386 } 387 total, _ := body.Int("TotalCount") 388 return vpcs, int(total), nil 389 } 390 391 func (self *SRegion) getVpc(vpcId string) (*SVpc, error) { 392 vpcs, total, err := self.GetVpcs([]string{vpcId}, 0, 1) 393 if err != nil { 394 return nil, err 395 } 396 if total != 1 { 397 return nil, cloudprovider.ErrNotFound 398 } 399 vpcs[0].region = self 400 return &vpcs[0], nil 401 } 402 403 func (self *SRegion) GetVRouters(offset int, limit int) ([]SVRouter, int, error) { 404 if limit > 50 || limit <= 0 { 405 limit = 50 406 } 407 params := make(map[string]string) 408 params["RegionId"] = self.RegionId 409 params["PageSize"] = fmt.Sprintf("%d", limit) 410 params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) 411 412 body, err := self.ecsRequest("DescribeVRouters", params) 413 if err != nil { 414 log.Errorf("GetVRouters fail %s", err) 415 return nil, 0, err 416 } 417 418 vrouters := make([]SVRouter, 0) 419 err = body.Unmarshal(&vrouters, "VRouters", "VRouter") 420 if err != nil { 421 log.Errorf("Unmarshal vrouter fail %s", err) 422 return nil, 0, err 423 } 424 total, _ := body.Int("TotalCount") 425 return vrouters, int(total), nil 426 } 427 428 func (self *SRegion) GetRouteTables(ids []string, offset int, limit int) ([]SRouteTable, int, error) { 429 if limit > 50 || limit <= 0 { 430 limit = 50 431 } 432 params := make(map[string]string) 433 params["RegionId"] = self.RegionId 434 params["PageSize"] = fmt.Sprintf("%d", limit) 435 params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) 436 if ids != nil && len(ids) > 0 { 437 params["RouteTableId"] = strings.Join(ids, ",") 438 } 439 440 body, err := self.ecsRequest("DescribeRouteTables", params) 441 if err != nil { 442 log.Errorf("GetRouteTables fail %s", err) 443 return nil, 0, err 444 } 445 446 routetables := make([]SRouteTable, 0) 447 err = body.Unmarshal(&routetables, "RouteTables", "RouteTable") 448 if err != nil { 449 log.Errorf("Unmarshal routetables fail %s", err) 450 return nil, 0, err 451 } 452 total, _ := body.Int("TotalCount") 453 return routetables, int(total), nil 454 } 455 456 func (self *SRegion) GetMatchInstanceTypes(cpu int, memMB int, gpu int, zoneId string) ([]SInstanceType, error) { 457 if self.instanceTypes == nil { 458 types, err := self.GetInstanceTypes() 459 if err != nil { 460 log.Errorf("GetInstanceTypes %s", err) 461 return nil, err 462 } 463 self.instanceTypes = types 464 } 465 var available []string 466 if len(zoneId) > 0 { 467 zone, err := self.getZoneById(zoneId) 468 if err != nil { 469 return nil, err 470 } 471 available = zone.AvailableInstanceTypes.InstanceTypes 472 } 473 ret := make([]SInstanceType, 0) 474 for _, t := range self.instanceTypes { 475 if t.CpuCoreCount == cpu && memMB == t.memoryMB() && gpu == t.GPUAmount { 476 if available == nil || utils.IsInStringArray(t.InstanceTypeId, available) { 477 ret = append(ret, t) 478 } 479 } 480 } 481 return ret, nil 482 } 483 484 func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, memGB int, storageType string, dataDiskSizesGB []int, vswitchId string, passwd string, publicKey string) (*SInstance, error) { 485 izones, err := self.GetIZones() 486 if err != nil { 487 return nil, err 488 } 489 for i := 0; i < len(izones); i += 1 { 490 z := izones[i].(*SZone) 491 log.Debugf("Search in zone %s", z.LocalName) 492 net := z.getNetworkById(vswitchId) 493 if net != nil { 494 desc := &cloudprovider.SManagedVMCreateConfig{ 495 Name: name, 496 ExternalImageId: imgId, 497 SysDisk: cloudprovider.SDiskInfo{SizeGB: 0, StorageType: storageType}, 498 Cpu: cpu, 499 MemoryMB: memGB * 1024, 500 ExternalNetworkId: vswitchId, 501 Password: passwd, 502 DataDisks: []cloudprovider.SDiskInfo{}, 503 PublicKey: publicKey, 504 } 505 for _, sizeGB := range dataDiskSizesGB { 506 desc.DataDisks = append(desc.DataDisks, cloudprovider.SDiskInfo{SizeGB: sizeGB, StorageType: storageType}) 507 } 508 inst, err := z.getHost().CreateVM(desc) 509 if err != nil { 510 return nil, err 511 } 512 return inst.(*SInstance), nil 513 } 514 } 515 return nil, fmt.Errorf("cannot find vswitch %s", vswitchId) 516 } 517 518 func (self *SRegion) instanceOperation(instanceId string, opname string, extra map[string]string) error { 519 params := make(map[string]string) 520 params["RegionId"] = self.RegionId 521 params["InstanceId"] = instanceId 522 if extra != nil && len(extra) > 0 { 523 for k, v := range extra { 524 params[k] = v 525 } 526 } 527 _, err := self.ecsRequest(opname, params) 528 return err 529 } 530 531 func (self *SRegion) GetInstanceStatus(instanceId string) (string, error) { 532 instance, err := self.GetInstance(instanceId) 533 if err != nil { 534 return "", err 535 } 536 return instance.Status, nil 537 } 538 539 func (self *SRegion) GetInstanceVNCUrl(instanceId string) (string, error) { 540 params := make(map[string]string) 541 params["RegionId"] = self.RegionId 542 params["InstanceId"] = instanceId 543 body, err := self.ecsRequest("DescribeInstanceVncUrl", params) 544 if err != nil { 545 return "", err 546 } 547 return body.GetString("VncUrl") 548 } 549 550 func (self *SRegion) ModifyInstanceVNCUrlPassword(instanceId string, passwd string) error { 551 params := make(map[string]string) 552 params["RegionId"] = self.RegionId 553 params["InstanceId"] = instanceId 554 params["VncPassword"] = passwd // must be 6 digital + alphabet 555 _, err := self.ecsRequest("ModifyInstanceVncPasswd", params) 556 return err 557 } 558 559 func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) { 560 params := make(map[string]string) 561 if len(opts.CIDR) > 0 { 562 params["CidrBlock"] = opts.CIDR 563 } 564 if len(opts.NAME) > 0 { 565 params["VpcName"] = opts.NAME 566 } 567 if len(opts.Desc) > 0 { 568 params["Description"] = opts.Desc 569 } 570 params["ClientToken"] = utils.GenRequestId(20) 571 body, err := self.ecsRequest("CreateVpc", params) 572 if err != nil { 573 return nil, err 574 } 575 vpcId, err := body.GetString("VpcId") 576 if err != nil { 577 return nil, err 578 } 579 err = self.fetchInfrastructure() 580 if err != nil { 581 return nil, err 582 } 583 return self.GetIVpcById(vpcId) 584 } 585 586 func (self *SRegion) DeleteVpc(vpcId string) error { 587 params := make(map[string]string) 588 params["VpcId"] = vpcId 589 590 _, err := self.ecsRequest("DeleteVpc", params) 591 return err 592 } 593 594 func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) { 595 izones, err := self.GetIZones() 596 if err != nil { 597 return nil, err 598 } 599 for i := 0; i < len(izones); i += 1 { 600 ihost, err := izones[i].GetIHostById(id) 601 if err == nil { 602 return ihost, nil 603 } else if err != cloudprovider.ErrNotFound { 604 return nil, err 605 } 606 } 607 return nil, cloudprovider.ErrNotFound 608 } 609 610 func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { 611 izones, err := self.GetIZones() 612 if err != nil { 613 return nil, err 614 } 615 for i := 0; i < len(izones); i += 1 { 616 istore, err := izones[i].GetIStorageById(id) 617 if err == nil { 618 return istore, nil 619 } else if err != cloudprovider.ErrNotFound { 620 return nil, err 621 } 622 } 623 return nil, cloudprovider.ErrNotFound 624 } 625 626 func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) { 627 iHosts := make([]cloudprovider.ICloudHost, 0) 628 629 izones, err := self.GetIZones() 630 if err != nil { 631 return nil, err 632 } 633 for i := 0; i < len(izones); i += 1 { 634 iZoneHost, err := izones[i].GetIHosts() 635 if err != nil { 636 return nil, err 637 } 638 iHosts = append(iHosts, iZoneHost...) 639 } 640 return iHosts, nil 641 } 642 643 func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) { 644 iStores := make([]cloudprovider.ICloudStorage, 0) 645 646 izones, err := self.GetIZones() 647 if err != nil { 648 return nil, err 649 } 650 for i := 0; i < len(izones); i += 1 { 651 iZoneStores, err := izones[i].GetIStorages() 652 if err != nil { 653 return nil, err 654 } 655 iStores = append(iStores, iZoneStores...) 656 } 657 return iStores, nil 658 } 659 660 func (self *SRegion) updateInstance(instId string, name, desc, passwd, hostname, userData string) error { 661 params := make(map[string]string) 662 params["InstanceId"] = instId 663 if len(name) > 0 { 664 params["InstanceName"] = name 665 } 666 if len(desc) > 0 { 667 params["Description"] = desc 668 } 669 if len(passwd) > 0 { 670 params["Password"] = passwd 671 } 672 if len(hostname) > 0 { 673 params["HostName"] = hostname 674 } 675 if len(userData) > 0 { 676 params["UserData"] = userData 677 } 678 _, err := self.ecsRequest("ModifyInstanceAttribute", params) 679 return err 680 } 681 682 func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error { 683 return self.updateInstance(instId, "", "", passwd, "", "") 684 } 685 686 // func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { 687 // eips, total, err := self.GetSnapshots("", 0, 50) 688 // if err != nil { 689 // return nil, err 690 // } 691 // for len(eips) < total { 692 // var parts []SEipAddress 693 // parts, total, err = self.GetEips("", len(eips), 50) 694 // if err != nil { 695 // return nil, err 696 // } 697 // eips = append(eips, parts...) 698 // } 699 // ret := make([]cloudprovider.ICloudEIP, len(eips)) 700 // for i := 0; i < len(eips); i += 1 { 701 // ret[i] = &eips[i] 702 // } 703 // return ret, nil 704 // } 705 706 func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) { 707 eips, total, err := self.GetEips("", "", 0, 50) 708 if err != nil { 709 return nil, err 710 } 711 for len(eips) < total { 712 var parts []SEipAddress 713 parts, total, err = self.GetEips("", "", len(eips), 50) 714 if err != nil { 715 return nil, err 716 } 717 eips = append(eips, parts...) 718 } 719 ret := make([]cloudprovider.ICloudEIP, len(eips)) 720 for i := 0; i < len(eips); i += 1 { 721 ret[i] = &eips[i] 722 } 723 return ret, nil 724 } 725 726 func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) { 727 eips, total, err := self.GetEips(eipId, "", 0, 1) 728 if err != nil { 729 return nil, err 730 } 731 if total == 0 { 732 return nil, cloudprovider.ErrNotFound 733 } 734 if total > 1 { 735 return nil, cloudprovider.ErrDuplicateId 736 } 737 return &eips[0], nil 738 } 739 740 func (region *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) { 741 secgroup, err := region.GetSecurityGroupDetails(secgroupId) 742 if err != nil { 743 return nil, err 744 } 745 vpc, err := region.getVpc(secgroup.VpcId) 746 if err != nil { 747 return nil, errors.Wrapf(err, "region.getVpc(%s)", secgroup.VpcId) 748 } 749 secgroup.vpc = vpc 750 return secgroup, nil 751 } 752 753 func (region *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) { 754 secgroups, total, err := region.GetSecurityGroups(opts.VpcId, opts.Name, []string{}, 0, 0) 755 if err != nil { 756 return nil, err 757 } 758 if total == 0 { 759 return nil, cloudprovider.ErrNotFound 760 } 761 if total > 1 { 762 return nil, cloudprovider.ErrDuplicateId 763 } 764 return &secgroups[0], nil 765 } 766 767 func (region *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) { 768 externalId, err := region.CreateSecurityGroup(conf.VpcId, conf.Name, conf.Desc) 769 if err != nil { 770 return nil, err 771 } 772 return region.GetISecurityGroupById(externalId) 773 } 774 775 func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) { 776 lbs, err := region.GetLoadbalancers(nil) 777 if err != nil { 778 return nil, err 779 } 780 ilbs := []cloudprovider.ICloudLoadbalancer{} 781 for i := 0; i < len(lbs); i++ { 782 lbs[i].region = region 783 ilbs = append(ilbs, &lbs[i]) 784 } 785 return ilbs, nil 786 } 787 788 func (region *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) { 789 return region.GetLoadbalancerDetail(loadbalancerId) 790 } 791 792 func (region *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) { 793 certs, err := region.GetLoadbalancerServerCertificates() 794 if err != nil { 795 return nil, err 796 } 797 for i := 0; i < len(certs); i++ { 798 if certs[i].GetGlobalId() == certId { 799 certs[i].region = region 800 return &certs[i], nil 801 } 802 } 803 return nil, cloudprovider.ErrNotFound 804 } 805 806 func (region *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) { 807 params := map[string]string{} 808 params["RegionId"] = region.RegionId 809 params["ServerCertificateName"] = cert.Name 810 params["PrivateKey"] = cert.PrivateKey 811 params["ServerCertificate"] = cert.Certificate 812 body, err := region.lbRequest("UploadServerCertificate", params) 813 if err != nil { 814 return nil, err 815 } 816 certID, err := body.GetString("ServerCertificateId") 817 if err != nil { 818 return nil, err 819 } 820 return region.GetILoadBalancerCertificateById(certID) 821 } 822 823 func (region *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) { 824 return nil, cloudprovider.ErrNotFound 825 } 826 827 func (region *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) { 828 return nil, cloudprovider.ErrNotSupported 829 } 830 831 func (region *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) { 832 certificates, err := region.GetLoadbalancerServerCertificates() 833 if err != nil { 834 return nil, err 835 } 836 iCertificates := []cloudprovider.ICloudLoadbalancerCertificate{} 837 for i := 0; i < len(certificates); i++ { 838 certificates[i].region = region 839 iCertificates = append(iCertificates, &certificates[i]) 840 } 841 return iCertificates, nil 842 } 843 844 func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) { 845 params := map[string]string{} 846 params["RegionId"] = region.RegionId 847 params["LoadBalancerName"] = loadbalancer.Name 848 if len(loadbalancer.ZoneID) > 0 { 849 params["MasterZoneId"] = loadbalancer.ZoneID 850 } 851 852 if len(loadbalancer.VpcID) > 0 { 853 params["VpcId"] = loadbalancer.VpcID 854 } 855 856 if len(loadbalancer.NetworkIDs) > 0 { 857 params["VSwitchId"] = loadbalancer.NetworkIDs[0] 858 } 859 860 if len(loadbalancer.Address) > 0 { 861 params["Address"] = loadbalancer.Address 862 } 863 864 if len(loadbalancer.AddressType) > 0 { 865 params["AddressType"] = loadbalancer.AddressType 866 } 867 868 if len(loadbalancer.LoadbalancerSpec) > 0 { 869 params["LoadBalancerSpec"] = loadbalancer.LoadbalancerSpec 870 } 871 872 if len(loadbalancer.ChargeType) > 0 { 873 params["InternetChargeType"] = "payby" + loadbalancer.ChargeType 874 } 875 876 if len(loadbalancer.ProjectId) > 0 { 877 params["ResourceGroupId"] = loadbalancer.ProjectId 878 } 879 880 if loadbalancer.ChargeType == api.LB_CHARGE_TYPE_BY_BANDWIDTH && loadbalancer.EgressMbps > 0 { 881 params["Bandwidth"] = fmt.Sprintf("%d", loadbalancer.EgressMbps) 882 } 883 884 body, err := region.lbRequest("CreateLoadBalancer", params) 885 if err != nil { 886 return nil, err 887 } 888 loadBalancerID, err := body.GetString("LoadBalancerId") 889 if err != nil { 890 return nil, err 891 } 892 region.SetResourceTags("slb", "instance", []string{loadBalancerID}, loadbalancer.Tags, false) 893 iLoadbalancer, err := region.GetLoadbalancerDetail(loadBalancerID) 894 if err != nil { 895 return nil, err 896 } 897 return iLoadbalancer, cloudprovider.WaitStatus(iLoadbalancer, api.LB_STATUS_ENABLED, time.Second*5, time.Minute*5) 898 } 899 900 func (region *SRegion) AddAccessControlListEntry(aclId string, entrys []cloudprovider.SLoadbalancerAccessControlListEntry) error { 901 params := map[string]string{} 902 params["RegionId"] = region.RegionId 903 params["AclId"] = aclId 904 aclArray := jsonutils.NewArray() 905 for i := 0; i < len(entrys); i++ { 906 //阿里云AclEntrys参数必须是CIDR格式的。 907 if regutils.MatchIPAddr(entrys[i].CIDR) { 908 entrys[i].CIDR += "/32" 909 } 910 aclArray.Add(jsonutils.Marshal(map[string]string{"entry": entrys[i].CIDR, "comment": entrys[i].Comment})) 911 } 912 if aclArray.Length() == 0 { 913 return nil 914 } 915 params["AclEntrys"] = aclArray.String() 916 _, err := region.lbRequest("AddAccessControlListEntry", params) 917 return err 918 } 919 920 func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) { 921 params := map[string]string{} 922 params["RegionId"] = region.RegionId 923 params["AclName"] = acl.Name 924 body, err := region.lbRequest("CreateAccessControlList", params) 925 if err != nil { 926 return nil, err 927 } 928 aclId, err := body.GetString("AclId") 929 if err != nil { 930 return nil, err 931 } 932 iAcl, err := region.GetLoadbalancerAclDetail(aclId) 933 if err != nil { 934 return nil, err 935 } 936 return iAcl, region.AddAccessControlListEntry(aclId, acl.Entrys) 937 } 938 939 func (self *SRegion) GetBuckets() ([]SBucket, error) { 940 resp, err := self.ossRequest("GetService", map[string]string{}) 941 if err != nil { 942 return nil, err 943 } 944 if !resp.Contains("Data") { 945 if self.client.cpcfg.UpdatePermission != nil { 946 self.client.cpcfg.UpdatePermission("oss", "ListBuckets") 947 } 948 return []SBucket{}, nil 949 } 950 ret := []SBucket{} 951 err = resp.Unmarshal(&ret, "Data", "ListAllMyBucketsResult", "Buckets", "Bucket") 952 if err != nil { 953 return nil, errors.Wrapf(err, "resp.Unmarshal") 954 } 955 if len(ret) > 0 { 956 self.ossEndpoint = ret[0].IntranetEndpoint 957 } 958 return ret, nil 959 } 960 961 func (self *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) { 962 buckets, err := self.GetBuckets() 963 if err != nil { 964 return nil, err 965 } 966 ret := []cloudprovider.ICloudBucket{} 967 for i := range buckets { 968 buckets[i].region = self 969 ret = append(ret, &buckets[i]) 970 } 971 return ret, nil 972 } 973 974 func str2StorageClass(storageClassStr string) (oss.StorageClassType, error) { 975 storageClass := oss.StorageStandard 976 if strings.EqualFold(storageClassStr, string(oss.StorageStandard)) { 977 // 978 } else if strings.EqualFold(storageClassStr, string(oss.StorageIA)) { 979 storageClass = oss.StorageIA 980 } else if strings.EqualFold(storageClassStr, string(oss.StorageArchive)) { 981 storageClass = oss.StorageArchive 982 } else { 983 return storageClass, errors.Error("not supported storageClass") 984 } 985 return storageClass, nil 986 } 987 988 func str2Acl(aclStr string) (oss.ACLType, error) { 989 acl := oss.ACLPrivate 990 if strings.EqualFold(aclStr, string(oss.ACLPrivate)) { 991 // private, default 992 } else if strings.EqualFold(aclStr, string(oss.ACLPublicRead)) { 993 acl = oss.ACLPublicRead 994 } else if strings.EqualFold(aclStr, string(oss.ACLPublicReadWrite)) { 995 acl = oss.ACLPublicReadWrite 996 } else { 997 return acl, errors.Error("not supported acl") 998 } 999 return acl, nil 1000 } 1001 1002 func (self *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error { 1003 osscli, err := self.GetOssClient() 1004 if err != nil { 1005 return errors.Wrap(err, "region.GetOssClient") 1006 } 1007 opts := make([]oss.Option, 0) 1008 if len(storageClassStr) > 0 { 1009 storageClass, err := str2StorageClass(storageClassStr) 1010 if err != nil { 1011 return err 1012 } 1013 opts = append(opts, oss.StorageClass(storageClass)) 1014 } 1015 if len(aclStr) > 0 { 1016 acl, err := str2Acl(aclStr) 1017 if err != nil { 1018 return err 1019 } 1020 opts = append(opts, oss.ACL(acl)) 1021 } 1022 return osscli.CreateBucket(name, opts...) 1023 } 1024 1025 func ossErrorCode(err error) int { 1026 if srvErr, ok := err.(oss.ServiceError); ok { 1027 return srvErr.StatusCode 1028 } 1029 if srvErr, ok := err.(*oss.ServiceError); ok { 1030 return srvErr.StatusCode 1031 } 1032 return -1 1033 } 1034 1035 func (self *SRegion) DeleteIBucket(name string) error { 1036 cli, err := self.GetOssClient() 1037 if err != nil { 1038 return err 1039 } 1040 return cli.DeleteBucket(name) 1041 } 1042 1043 func (self *SRegion) GetBucket(name string) (*SBucket, error) { 1044 params := map[string]string{ 1045 "AccountInfo": "aaa", 1046 "x-acs-instanceid": name, 1047 "Params": jsonutils.Marshal(map[string]string{"BucketName": name}).String(), 1048 } 1049 resp, err := self.ossRequest("GetBucketInfo", params) 1050 if err != nil { 1051 return nil, errors.Wrapf(err, "GetBucketInfo") 1052 } 1053 bucket := &SBucket{region: self} 1054 return bucket, resp.Unmarshal(bucket, "Data", "BucketInfo", "Bucket") 1055 } 1056 1057 func (self *SRegion) IBucketExist(name string) (bool, error) { 1058 _, err := self.GetBucket(name) 1059 if err != nil { 1060 return false, err 1061 } 1062 return true, nil 1063 } 1064 1065 func (self *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) { 1066 buckets, err := self.GetBuckets() 1067 if err != nil { 1068 return nil, err 1069 } 1070 for i := range buckets { 1071 if buckets[i].GetName() == name { 1072 buckets[i].region = self 1073 return &buckets[i], nil 1074 } 1075 } 1076 return nil, errors.Wrapf(cloudprovider.ErrNotFound, name) 1077 } 1078 1079 func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) { 1080 return region.GetIBucketById(name) 1081 } 1082 1083 func (self *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) { 1084 caches, err := self.GetElasticCaches(nil) 1085 if err != nil { 1086 return nil, err 1087 } 1088 1089 icaches := make([]cloudprovider.ICloudElasticcache, len(caches)) 1090 for i := range caches { 1091 caches[i].region = self 1092 icaches[i] = &caches[i] 1093 } 1094 1095 return icaches, nil 1096 } 1097 1098 func (region *SRegion) GetCapabilities() []string { 1099 return region.client.GetCapabilities() 1100 }