yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/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 aws 16 17 import ( 18 "fmt" 19 "strings" 20 "sync" 21 "time" 22 23 "github.com/aws/aws-sdk-go/aws" 24 "github.com/aws/aws-sdk-go/aws/session" 25 "github.com/aws/aws-sdk-go/service/acm" 26 "github.com/aws/aws-sdk-go/service/ec2" 27 "github.com/aws/aws-sdk-go/service/elbv2" 28 "github.com/aws/aws-sdk-go/service/iam" 29 "github.com/aws/aws-sdk-go/service/organizations" 30 "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" 31 "github.com/aws/aws-sdk-go/service/s3" 32 "github.com/aws/aws-sdk-go/service/wafv2" 33 34 "yunion.io/x/jsonutils" 35 "yunion.io/x/log" 36 "yunion.io/x/pkg/errors" 37 38 api "yunion.io/x/cloudmux/pkg/apis/compute" 39 "yunion.io/x/cloudmux/pkg/cloudprovider" 40 "yunion.io/x/cloudmux/pkg/multicloud" 41 ) 42 43 var ( 44 lock sync.RWMutex 45 ) 46 47 var RegionLocations = map[string]string{ 48 "us-east-2": "美国东部(俄亥俄州)", 49 "us-east-1": "美国东部(弗吉尼亚北部)", 50 "us-west-1": "美国西部(加利福尼亚北部)", 51 "us-west-2": "美国西部(俄勒冈)", 52 "ap-east-1": "亚太区域(香港)", 53 "ap-south-1": "亚太区域(孟买)", 54 "ap-northeast-3": "亚太区域(大阪-本地)", 55 "ap-northeast-2": "亚太区域(首尔)", 56 "ap-southeast-1": "亚太区域(新加坡)", 57 "ap-southeast-2": "亚太区域(悉尼)", 58 "ap-northeast-1": "亚太区域(东京)", 59 "ca-central-1": "加拿大(中部)", 60 "cn-north-1": "中国(北京)", 61 "cn-northwest-1": "中国(宁夏)", 62 "eu-central-1": "欧洲(法兰克福)", 63 "eu-west-1": "欧洲(爱尔兰)", 64 "eu-west-2": "欧洲(伦敦)", 65 "eu-south-1": "欧洲(米兰)", 66 "eu-west-3": "欧洲(巴黎)", 67 "eu-north-1": "欧洲(斯德哥尔摩)", 68 "me-south-1": "中东(巴林)", 69 "sa-east-1": "南美洲(圣保罗)", 70 "us-gov-west-1": "AWS GovCloud(美国西部)", 71 "us-gov-east-1": "AWS GovCloud(美国东部)", 72 73 "af-south-1": "非洲(开普敦)", 74 } 75 76 var RegionLocationsEN = map[string]string{ 77 "us-east-1": "US East (N. Virginia)", 78 "us-east-2": "US East (Ohio)", 79 "us-west-1": "US West (N. California)", 80 "us-west-2": "US West (Oregon)", 81 "af-south-1": "Africa (Cape Town)", 82 "ap-east-1": "Asia Pacific (Hong Kong)", 83 "ap-south-1": "Asia Pacific (Mumbai)", 84 "ap-northeast-3": "Asia Pacific (Osaka)", 85 "ap-northeast-2": "Asia Pacific (Seoul)", 86 "ap-southeast-1": "Asia Pacific (Singapore)", 87 "ap-southeast-2": "Asia Pacific (Sydney)", 88 "ap-northeast-1": "Asia Pacific (Tokyo)", 89 "ca-central-1": "Canada (Central)", 90 "eu-central-1": "Europe (Frankfurt)", 91 "eu-west-1": "Europe (Ireland)", 92 "eu-west-2": "Europe (London)", 93 "eu-south-1": "Europe (Milan)", 94 "eu-west-3": "Europe (Paris)", 95 "eu-north-1": "Europe (Stockholm)", 96 "me-south-1": "Middle East (Bahrain)", 97 "sa-east-1": "South America (São Paulo)", 98 "cn-north-1": "China (Beijing)", 99 "cn-northwest-1": "China (Ninxia)", 100 "us-gov-west-1": "AWS GovCloud(US West)", 101 "us-gov-east-1": "AWS GovCloud(US East)", 102 } 103 104 const ( 105 RDS_SERVICE_NAME = "rds" 106 RDS_SERVICE_ID = "RDS" 107 108 EC2_SERVICE_NAME = "ec2" 109 EC2_SERVICE_ID = "EC2" 110 111 IAM_SERVICE_NAME = "iam" 112 IAM_SERVICE_ID = "IAM" 113 114 STS_SERVICE_NAME = "sts" 115 STS_SERVICE_ID = "STS" 116 117 CLOUDWATCH_SERVICE_NAME = "monitoring" 118 CLOUDWATCH_SERVICE_ID = "CloudWatch" 119 120 CLOUD_TRAIL_SERVICE_NAME = "CloudTrail" 121 CLOUD_TRAIL_SERVICE_ID = "cloudtrail" 122 123 ROUTE53_SERVICE_NAME = "route53" 124 125 ELASTICACHE_SERVICE_NAME = "elasticache" 126 ) 127 128 type SRegion struct { 129 multicloud.SRegion 130 131 client *SAwsClient 132 ec2Client *ec2.EC2 133 iamClient *iam.IAM 134 s3Client *s3.S3 135 elbv2Client *elbv2.ELBV2 136 acmClient *acm.ACM 137 wafClient *wafv2.WAFV2 138 organizationClient *organizations.Organizations 139 resourceGroupTagClient *resourcegroupstaggingapi.ResourceGroupsTaggingAPI 140 141 izones []cloudprovider.ICloudZone 142 ivpcs []cloudprovider.ICloudVpc 143 144 storageCache *SStoragecache 145 146 RegionEndpoint string 147 RegionId string // 这里为保持一致沿用阿里云RegionId的叫法, 与AWS RegionName字段对应 148 } 149 150 ///////////////////////////////////////////////////////////////////////////// 151 /* 请不要使用这个client(AWS_DEFAULT_REGION)跨region查信息.有可能导致查询返回的信息为空。比如DescribeAvailabilityZones*/ 152 func (self *SRegion) GetClient() *SAwsClient { 153 return self.client 154 } 155 156 func (self *SRegion) getAwsSession() (*session.Session, error) { 157 return self.client.getAwsSession(self.RegionId, true) 158 } 159 160 func (self *SRegion) getEc2Client() (*ec2.EC2, error) { 161 if self.ec2Client == nil { 162 s, err := self.getAwsSession() 163 164 if err != nil { 165 return nil, errors.Wrap(err, "getAwsSession") 166 } 167 168 self.ec2Client = ec2.New(s) 169 } 170 171 return self.ec2Client, nil 172 } 173 174 func (self *SRegion) getIamClient() (*iam.IAM, error) { 175 if self.iamClient == nil { 176 s, err := self.getAwsSession() 177 178 if err != nil { 179 return nil, errors.Wrap(err, "getAwsSession") 180 } 181 182 self.iamClient = iam.New(s) 183 } 184 185 return self.iamClient, nil 186 } 187 188 func (self *SRegion) getWafClient() (*wafv2.WAFV2, error) { 189 if self.wafClient == nil { 190 s, err := self.getAwsSession() 191 if err != nil { 192 return nil, errors.Wrapf(err, "getAwsSession") 193 } 194 self.wafClient = wafv2.New(s) 195 } 196 return self.wafClient, nil 197 } 198 199 func (self *SRegion) GetS3Client() (*s3.S3, error) { 200 if self.s3Client == nil { 201 s, err := self.getAwsSession() 202 if err != nil { 203 return nil, errors.Wrap(err, "getAwsSession") 204 } 205 self.s3Client = s3.New(s, 206 &aws.Config{ 207 DisableRestProtocolURICleaning: aws.Bool(true), 208 }) 209 } 210 return self.s3Client, nil 211 } 212 213 func (r *SRegion) getOrganizationClient() (*organizations.Organizations, error) { 214 if r.organizationClient == nil { 215 s, err := r.getAwsSession() 216 if err != nil { 217 return nil, errors.Wrap(err, "getAwsSession") 218 } 219 r.organizationClient = organizations.New(s) 220 } 221 return r.organizationClient, nil 222 } 223 224 func (self *SRegion) getResourceGroupTagClient() (*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, error) { 225 if self.resourceGroupTagClient == nil { 226 s, err := self.getAwsSession() 227 if err != nil { 228 return nil, errors.Wrap(err, "getAwsSession") 229 } 230 self.resourceGroupTagClient = resourcegroupstaggingapi.New(s) 231 } 232 return self.resourceGroupTagClient, nil 233 } 234 235 func (self *SRegion) rdsRequest(apiName string, params map[string]string, retval interface{}) error { 236 return self.client.request(self.RegionId, RDS_SERVICE_NAME, RDS_SERVICE_ID, "2014-10-31", apiName, params, retval, true) 237 } 238 239 func (self *SRegion) ec2Request(apiName string, params map[string]string, retval interface{}) error { 240 return self.client.request(self.RegionId, EC2_SERVICE_NAME, EC2_SERVICE_ID, "2016-11-15", apiName, params, retval, true) 241 } 242 243 func (self *SAwsClient) monitorRequest(regionId, apiName string, params map[string]string, retval interface{}) error { 244 return self.request(regionId, CLOUDWATCH_SERVICE_NAME, CLOUDWATCH_SERVICE_ID, "2010-08-01", apiName, params, retval, true) 245 } 246 247 func (self *SRegion) GetElbV2Client() (*elbv2.ELBV2, error) { 248 if self.elbv2Client == nil { 249 s, err := self.getAwsSession() 250 251 if err != nil { 252 return nil, errors.Wrap(err, "getAwsSession") 253 } 254 255 self.elbv2Client = elbv2.New(s) 256 } 257 258 return self.elbv2Client, nil 259 } 260 261 ///////////////////////////////////////////////////////////////////////////// 262 func (self *SRegion) fetchZones() error { 263 ec2Client, err := self.getEc2Client() 264 if err != nil { 265 return errors.Wrap(err, "getEc2Client") 266 } 267 // todo: 这里将过滤出指定region下全部的zones。是否只过滤出可用的zone即可? The state of the Availability Zone (available | information | impaired | unavailable) 268 zones, err := ec2Client.DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{}) 269 if err != nil { 270 return errors.Wrap(err, "DescribeAvailabilityZones") 271 } 272 err = FillZero(zones) 273 if err != nil { 274 return err 275 } 276 277 self.izones = make([]cloudprovider.ICloudZone, 0) 278 for _, zone := range zones.AvailabilityZones { 279 self.izones = append(self.izones, &SZone{ZoneId: *zone.ZoneName, State: *zone.State, LocalName: *zone.ZoneName, region: self}) 280 } 281 282 return nil 283 } 284 285 func (self *SRegion) fetchIVpcs() error { 286 ec2Client, err := self.getEc2Client() 287 if err != nil { 288 return errors.Wrap(err, "getEc2Client") 289 } 290 291 vpcs, err := ec2Client.DescribeVpcs(&ec2.DescribeVpcsInput{}) 292 if err != nil { 293 return err 294 } 295 296 self.ivpcs = make([]cloudprovider.ICloudVpc, 0) 297 for _, vpc := range vpcs.Vpcs { 298 cidrBlockAssociationSet := []string{} 299 for i := range vpc.CidrBlockAssociationSet { 300 cidr := vpc.CidrBlockAssociationSet[i] 301 if cidr.CidrBlockState.State != nil && *cidr.CidrBlockState.State == "associated" { 302 cidrBlockAssociationSet = append(cidrBlockAssociationSet, *cidr.CidrBlock) 303 } 304 } 305 306 tagspec := TagSpec{ResourceType: "vpc"} 307 tagspec.LoadingEc2Tags(vpc.Tags) 308 ivpc := &SVpc{region: self, 309 CidrBlock: *vpc.CidrBlock, 310 CidrBlockAssociationSet: cidrBlockAssociationSet, 311 IsDefault: *vpc.IsDefault, 312 RegionId: self.RegionId, 313 Status: *vpc.State, 314 VpcId: *vpc.VpcId, 315 VpcName: tagspec.GetNameTag(), 316 InstanceTenancy: *vpc.InstanceTenancy, 317 } 318 jsonutils.Update(&ivpc.AwsTags.TagSet, vpc.Tags) 319 self.ivpcs = append(self.ivpcs, ivpc) 320 } 321 322 return nil 323 } 324 325 func (self *SRegion) fetchInfrastructure() error { 326 if _, err := self.getEc2Client(); err != nil { 327 return err 328 } 329 330 if err := self.fetchZones(); err != nil { 331 return err 332 } 333 334 if err := self.fetchIVpcs(); err != nil { 335 return err 336 } 337 338 for i := 0; i < len(self.ivpcs); i += 1 { 339 for j := 0; j < len(self.izones); j += 1 { 340 zone := self.izones[j].(*SZone) 341 vpc := self.ivpcs[i].(*SVpc) 342 wire := SWire{zone: zone, vpc: vpc} 343 zone.addWire(&wire) 344 vpc.addWire(&wire) 345 } 346 } 347 return nil 348 } 349 350 func (self *SRegion) GetId() string { 351 return self.RegionId 352 } 353 354 func (self *SRegion) GetName() string { 355 if localName, ok := RegionLocations[self.RegionId]; ok { 356 return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, localName) 357 } 358 359 return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, self.RegionId) 360 } 361 362 func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable { 363 var en string 364 if localName, ok := RegionLocationsEN[self.RegionId]; ok { 365 en = fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_EN, localName) 366 } else { 367 en = fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_EN, self.RegionId) 368 } 369 370 table := cloudprovider.SModelI18nTable{} 371 table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en) 372 return table 373 } 374 375 func (self *SRegion) GetGlobalId() string { 376 return fmt.Sprintf("%s/%s", self.client.GetAccessEnv(), self.RegionId) 377 } 378 379 func (self *SRegion) GetStatus() string { 380 return api.CLOUD_REGION_STATUS_INSERVER 381 } 382 383 func (self *SRegion) Refresh() error { 384 return nil 385 } 386 387 func (self *SRegion) IsEmulated() bool { 388 return false 389 } 390 391 func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo { 392 if info, ok := LatitudeAndLongitude[self.RegionId]; ok { 393 return info 394 } 395 return cloudprovider.SGeographicInfo{} 396 } 397 398 func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) { 399 if self.izones == nil { 400 if err := self.fetchInfrastructure(); err != nil { 401 return nil, errors.Wrap(err, "fetchInfrastructure") 402 } 403 } 404 return self.izones, nil 405 } 406 407 func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) { 408 if self.ivpcs == nil { 409 err := self.fetchInfrastructure() 410 if err != nil { 411 return nil, errors.Wrap(err, "fetchInfrastructure") 412 } 413 } 414 return self.ivpcs, nil 415 } 416 417 func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) { 418 return self.GetInstance(id) 419 } 420 421 func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) { 422 return self.GetDisk(id) 423 } 424 425 func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) { 426 eips, err := self.GetEips("", "", "") 427 if err != nil { 428 return nil, errors.Wrap(err, "GetEips") 429 } 430 ret := []cloudprovider.ICloudEIP{} 431 for i := range eips { 432 eips[i].region = self 433 ret = append(ret, &eips[i]) 434 } 435 return ret, nil 436 } 437 438 func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { 439 snapshots, _, err := self.GetSnapshots("", "", "", []string{}, 0, 0) 440 if err != nil { 441 return nil, errors.Wrap(err, "GetSnapshots") 442 } 443 444 ret := make([]cloudprovider.ICloudSnapshot, len(snapshots)) 445 for i := 0; i < len(snapshots); i += 1 { 446 ret[i] = &snapshots[i] 447 } 448 return ret, nil 449 } 450 451 func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) { 452 izones, err := self.GetIZones() 453 if err != nil { 454 return nil, errors.Wrap(err, "GetIZones") 455 } 456 457 for _, zone := range izones { 458 if zone.GetGlobalId() == id { 459 return zone, nil 460 } 461 } 462 463 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIZoneById") 464 } 465 466 func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) { 467 ivpcs, err := self.GetIVpcs() 468 if err != nil { 469 return nil, errors.Wrap(err, "GetIVpcs") 470 } 471 472 for _, vpc := range ivpcs { 473 if vpc.GetGlobalId() == id { 474 return vpc, nil 475 } 476 } 477 478 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIVpcById") 479 } 480 481 func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) { 482 izones, err := self.GetIZones() 483 if err != nil { 484 return nil, errors.Wrap(err, "GetIZones") 485 } 486 for i := 0; i < len(izones); i += 1 { 487 ihost, err := izones[i].GetIHostById(id) 488 if err == nil { 489 return ihost, nil 490 } else if errors.Cause(err) != cloudprovider.ErrNotFound { 491 log.Errorf("GetIHostById %s: %s", id, err) 492 return nil, errors.Wrap(err, "GetIHostById") 493 } 494 } 495 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIHostById") 496 } 497 498 func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { 499 izones, err := self.GetIZones() 500 if err != nil { 501 return nil, errors.Wrap(err, "GetIZones") 502 } 503 for i := 0; i < len(izones); i += 1 { 504 istore, err := izones[i].GetIStorageById(id) 505 if err == nil { 506 return istore, nil 507 } else if errors.Cause(err) != cloudprovider.ErrNotFound { 508 log.Errorf("GetIStorageById %s: %s", id, err) 509 return nil, errors.Wrap(err, "GetIStorageById") 510 } 511 } 512 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIStorageById") 513 } 514 515 func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) { 516 iHosts := make([]cloudprovider.ICloudHost, 0) 517 518 izones, err := self.GetIZones() 519 if err != nil { 520 return nil, errors.Wrap(err, "GetIZones") 521 } 522 for i := 0; i < len(izones); i += 1 { 523 iZoneHost, err := izones[i].GetIHosts() 524 if err != nil { 525 return nil, errors.Wrap(err, "GetIHosts") 526 } 527 iHosts = append(iHosts, iZoneHost...) 528 } 529 return iHosts, nil 530 } 531 532 func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) { 533 iStores := make([]cloudprovider.ICloudStorage, 0) 534 535 izones, err := self.GetIZones() 536 if err != nil { 537 return nil, errors.Wrap(err, "GetIZones") 538 } 539 for i := 0; i < len(izones); i += 1 { 540 iZoneStores, err := izones[i].GetIStorages() 541 if err != nil { 542 return nil, errors.Wrap(err, "GetIStorages") 543 } 544 iStores = append(iStores, iZoneStores...) 545 } 546 return iStores, nil 547 } 548 549 func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) { 550 if self.storageCache == nil { 551 self.storageCache = &SStoragecache{region: self} 552 } 553 554 if self.storageCache.GetGlobalId() == id { 555 return self.storageCache, nil 556 } 557 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIStoragecacheById") 558 559 } 560 561 func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) { 562 tagspec := TagSpec{ResourceType: "vpc"} 563 if len(opts.NAME) > 0 { 564 tagspec.SetNameTag(opts.NAME) 565 } 566 567 if len(opts.Desc) > 0 { 568 tagspec.SetDescTag(opts.Desc) 569 } 570 571 spec, err := tagspec.GetTagSpecifications() 572 if err != nil { 573 return nil, errors.Wrap(err, "GetTagSpecifications") 574 } 575 576 ec2Client, err := self.getEc2Client() 577 if err != nil { 578 return nil, errors.Wrap(err, "getEc2Client") 579 } 580 581 // start create vpc 582 vpc, err := ec2Client.CreateVpc(&ec2.CreateVpcInput{CidrBlock: &opts.CIDR}) 583 if err != nil { 584 return nil, errors.Wrap(err, "CreateVpc") 585 } 586 587 tagsParams := &ec2.CreateTagsInput{Resources: []*string{vpc.Vpc.VpcId}, Tags: spec.Tags} 588 _, err = ec2Client.CreateTags(tagsParams) 589 if err != nil { 590 log.Debugf("CreateIVpc add tag failed %s", err.Error()) 591 } 592 593 err = self.fetchInfrastructure() 594 if err != nil { 595 return nil, errors.Wrap(err, "fetchInfrastructure") 596 } 597 return self.GetIVpcById(*vpc.Vpc.VpcId) 598 } 599 600 func (self *SRegion) GetIEipById(id string) (cloudprovider.ICloudEIP, error) { 601 eip, err := self.GetEip(id) 602 if err != nil { 603 return nil, errors.Wrap(err, "GetEip") 604 } 605 return eip, nil 606 } 607 608 func (self *SRegion) GetProvider() string { 609 return CLOUD_PROVIDER_AWS 610 } 611 612 func (self *SRegion) GetCloudEnv() string { 613 return self.client.accessUrl 614 } 615 616 func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, memGB int, storageType string, dataDiskSizesGB []int, networkId string, publicKey string) (*SInstance, error) { 617 izones, err := self.GetIZones() 618 if err != nil { 619 return nil, errors.Wrap(err, "GetIZones") 620 } 621 for i := 0; i < len(izones); i += 1 { 622 z := izones[i].(*SZone) 623 log.Debugf("Search in zone %s", z.LocalName) 624 net := z.getNetworkById(networkId) 625 if net != nil { 626 desc := &cloudprovider.SManagedVMCreateConfig{ 627 Name: name, 628 ExternalImageId: imgId, 629 SysDisk: cloudprovider.SDiskInfo{SizeGB: 0, StorageType: storageType}, 630 Cpu: cpu, 631 MemoryMB: memGB * 1024, 632 ExternalNetworkId: networkId, 633 DataDisks: []cloudprovider.SDiskInfo{}, 634 PublicKey: publicKey, 635 } 636 for _, sizeGB := range dataDiskSizesGB { 637 desc.DataDisks = append(desc.DataDisks, cloudprovider.SDiskInfo{SizeGB: sizeGB, StorageType: storageType}) 638 } 639 inst, err := z.getHost().CreateVM(desc) 640 if err != nil { 641 return nil, errors.Wrap(err, "CreateVM") 642 } 643 return inst.(*SInstance), nil 644 } 645 } 646 return nil, fmt.Errorf("cannot find vswitch %s", networkId) 647 } 648 649 func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) { 650 client, err := self.GetElbV2Client() 651 if err != nil { 652 return nil, errors.Wrap(err, "GetElbV2Client") 653 } 654 655 params := &elbv2.DescribeLoadBalancersInput{} 656 ret, err := client.DescribeLoadBalancers(params) 657 if err != nil { 658 return nil, errors.Wrap(err, "DescribeLoadBalancers") 659 } 660 661 result := make([]SElb, 0) 662 err = unmarshalAwsOutput(ret, "LoadBalancers", &result) 663 if err != nil { 664 return nil, errors.Wrap(err, "unmarshalAwsOutput.LoadBalancers") 665 } 666 667 ielbs := make([]cloudprovider.ICloudLoadbalancer, len(result)) 668 for i := range result { 669 result[i].region = self 670 ielbs[i] = &result[i] 671 } 672 673 return ielbs, nil 674 } 675 676 func (self *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) { 677 client, err := self.GetElbV2Client() 678 if err != nil { 679 return nil, errors.Wrap(err, "GetElbV2Client") 680 } 681 682 params := &elbv2.DescribeLoadBalancersInput{} 683 params.SetLoadBalancerArns([]*string{&loadbalancerId}) 684 ret, err := client.DescribeLoadBalancers(params) 685 if err != nil { 686 if strings.Contains(err.Error(), "LoadBalancerNotFound") { 687 return nil, cloudprovider.ErrNotFound 688 } 689 690 return nil, errors.Wrap(err, "DescribeLoadBalancers") 691 } 692 693 elbs := []SElb{} 694 err = unmarshalAwsOutput(ret, "LoadBalancers", &elbs) 695 if err != nil { 696 return nil, errors.Wrap(err, "unmarshalAwsOutput.LoadBalancers") 697 } 698 699 if len(elbs) == 1 { 700 elbs[0].region = self 701 return &elbs[0], nil 702 } 703 704 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerById") 705 } 706 707 func (self *SRegion) getElbAttributesById(loadbalancerId string) (map[string]string, error) { 708 client, err := self.GetElbV2Client() 709 if err != nil { 710 return nil, errors.Wrap(err, "GetElbV2Client") 711 } 712 713 params := &elbv2.DescribeLoadBalancerAttributesInput{} 714 params.SetLoadBalancerArn(loadbalancerId) 715 output, err := client.DescribeLoadBalancerAttributes(params) 716 if err != nil { 717 return nil, errors.Wrap(err, "DescribeLoadBalancerAttributes") 718 } 719 720 attrs := []map[string]string{} 721 err = unmarshalAwsOutput(output, "Attributes", &attrs) 722 if err != nil { 723 return nil, errors.Wrap(err, "unmarshalAwsOutput.Attributes") 724 } 725 726 ret := map[string]string{} 727 for i := range attrs { 728 for k, v := range attrs[i] { 729 ret[k] = v 730 } 731 } 732 733 return ret, nil 734 } 735 736 func (self *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) { 737 return nil, cloudprovider.ErrNotSupported 738 } 739 740 func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) { 741 certs, err := self.GetILoadBalancerCertificates() 742 if err != nil { 743 return nil, errors.Wrap(err, "GetILoadBalancerCertificates") 744 } 745 746 for i := range certs { 747 if certs[i].GetId() == certId { 748 return certs[i], nil 749 } 750 } 751 752 return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerCertificateById") 753 } 754 755 func (self *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) { 756 client, err := self.getIamClient() 757 if err != nil { 758 return nil, errors.Wrap(err, "region.CreateILoadBalancerCertificate.getIamClient") 759 } 760 761 params := &iam.UploadServerCertificateInput{} 762 params.SetServerCertificateName(cert.Name) 763 params.SetPrivateKey(cert.PrivateKey) 764 params.SetCertificateBody(cert.Certificate) 765 ret, err := client.UploadServerCertificate(params) 766 if err != nil { 767 return nil, errors.Wrap(err, "region.CreateILoadBalancerCertificate.UploadServerCertificate") 768 } 769 770 // wait upload cert success 771 err = cloudprovider.Wait(5*time.Second, 30*time.Second, func() (bool, error) { 772 _, err := self.GetILoadBalancerCertificateById(*ret.ServerCertificateMetadata.Arn) 773 if err == nil { 774 return true, nil 775 } 776 777 if errors.Cause(err) == cloudprovider.ErrNotFound { 778 return false, nil 779 } else { 780 return false, err 781 } 782 }) 783 if err != nil { 784 return nil, errors.Wrap(err, "region.CreateILoadBalancerCertificate.Wait") 785 } 786 787 return self.GetILoadBalancerCertificateById(*ret.ServerCertificateMetadata.Arn) 788 } 789 790 func (self *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) { 791 return nil, cloudprovider.ErrNotSupported 792 } 793 794 func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) { 795 client, err := self.getIamClient() 796 if err != nil { 797 return nil, errors.Wrap(err, "getIamClient") 798 } 799 800 params := &iam.ListServerCertificatesInput{} 801 ret, err := client.ListServerCertificates(params) 802 if err != nil { 803 return nil, errors.Wrap(err, "ListServerCertificates") 804 } 805 806 certs := []SElbCertificate{} 807 err = unmarshalAwsOutput(ret, "ServerCertificateMetadataList", &certs) 808 if err != nil { 809 return nil, errors.Wrap(err, "unmarshalAwsOutput.ServerCertificateMetadataList") 810 } 811 812 icerts := make([]cloudprovider.ICloudLoadbalancerCertificate, len(certs)) 813 for i := range certs { 814 certs[i].region = self 815 icerts[i] = &certs[i] 816 } 817 818 return icerts, nil 819 } 820 821 func (self *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) { 822 client, err := self.GetElbV2Client() 823 if err != nil { 824 return nil, errors.Wrap(err, "GetElbV2Client") 825 } 826 827 params := &elbv2.CreateLoadBalancerInput{} 828 params.SetName(loadbalancer.Name) 829 params.SetType(loadbalancer.LoadbalancerSpec) 830 params.SetIpAddressType("ipv4") 831 if loadbalancer.AddressType == api.LB_ADDR_TYPE_INTERNET { 832 params.SetScheme("internet-facing") 833 } else { 834 params.SetScheme("internal") 835 } 836 837 // params.SetSecurityGroups() 838 params.SetSubnets(ConvertedList(loadbalancer.NetworkIDs)) 839 840 tagInput := []*elbv2.Tag{} 841 keys := []string{} 842 values := []string{} 843 for k, v := range loadbalancer.Tags { 844 keys = append(keys, k) 845 values = append(values, v) 846 } 847 for i := range keys { 848 tagInput = append(tagInput, &elbv2.Tag{ 849 Key: &keys[i], 850 Value: &values[i], 851 }) 852 } 853 if len(loadbalancer.Tags) > 0 { 854 params.SetTags(tagInput) 855 } 856 857 ret, err := client.CreateLoadBalancer(params) 858 if err != nil { 859 return nil, errors.Wrap(err, "CreateLoadBalancer") 860 } 861 862 elbs := []SElb{} 863 err = unmarshalAwsOutput(ret, "LoadBalancers", &elbs) 864 if err != nil { 865 return nil, errors.Wrap(err, "unmarshalAwsOutput.LoadBalancers") 866 } 867 868 if len(elbs) == 1 { 869 elbs[0].region = self 870 return &elbs[0], nil 871 } 872 873 return nil, fmt.Errorf("CreateILoadBalancer error %#v", elbs) 874 } 875 876 func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) { 877 iBuckets, err := region.client.getIBuckets() 878 if err != nil { 879 return nil, errors.Wrap(err, "getIBuckets") 880 } 881 ret := make([]cloudprovider.ICloudBucket, 0) 882 for i := range iBuckets { 883 if iBuckets[i].GetLocation() != region.GetId() { 884 continue 885 } 886 ret = append(ret, iBuckets[i]) 887 } 888 return ret, nil 889 } 890 891 func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error { 892 s3cli, err := region.GetS3Client() 893 if err != nil { 894 return errors.Wrap(err, "GetS3Client") 895 } 896 input := &s3.CreateBucketInput{} 897 input.SetBucket(name) 898 if region.GetId() != DEFAULT_S3_REGION_ID { 899 location := region.GetId() 900 input.CreateBucketConfiguration = &s3.CreateBucketConfiguration{} 901 input.CreateBucketConfiguration.SetLocationConstraint(location) 902 } 903 _, err = s3cli.CreateBucket(input) 904 if err != nil { 905 return errors.Wrap(err, "CreateBucket") 906 } 907 region.client.invalidateIBuckets() 908 // if *output.Location != region.GetId() { 909 // log.Warningf("Request location %s != got locaiton %s", region.GetId(), *output.Location) 910 // } 911 return nil 912 } 913 914 func (region *SRegion) DeleteIBucket(name string) error { 915 s3cli, err := region.GetS3Client() 916 if err != nil { 917 return errors.Wrap(err, "GetS3Client") 918 } 919 input := &s3.DeleteBucketInput{} 920 input.Bucket = &name 921 _, err = s3cli.DeleteBucket(input) 922 if err != nil { 923 if region.client.debug { 924 log.Debugf("%#v %s", err, err) 925 } 926 if strings.Index(err.Error(), "NoSuchBucket:") >= 0 { 927 return nil 928 } 929 return errors.Wrap(err, "DeleteBucket") 930 } 931 region.client.invalidateIBuckets() 932 return nil 933 } 934 935 func (region *SRegion) IBucketExist(name string) (bool, error) { 936 s3cli, err := region.GetS3Client() 937 if err != nil { 938 return false, errors.Wrap(err, "GetS3Client") 939 } 940 input := &s3.HeadBucketInput{} 941 input.Bucket = &name 942 _, err = s3cli.HeadBucket(input) 943 if err != nil { 944 if region.client.debug { 945 log.Debugf("%#v %s", err, err) 946 } 947 if strings.Index(err.Error(), "NotFound:") >= 0 { 948 return false, nil 949 } 950 return false, errors.Wrap(err, "IsBucketExist") 951 } 952 return true, nil 953 } 954 955 func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) { 956 return cloudprovider.GetIBucketById(region, name) 957 } 958 959 func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) { 960 return region.GetIBucketById(name) 961 } 962 963 func (region *SRegion) getBaseEndpoint() string { 964 if len(region.RegionEndpoint) > 4 { 965 return region.RegionEndpoint[4:] 966 } 967 return "" 968 } 969 970 func (region *SRegion) getS3Endpoint() string { 971 base := region.getBaseEndpoint() 972 if len(base) > 0 { 973 return "s3." + base 974 } 975 return "" 976 } 977 978 func (region *SRegion) getS3WebsiteEndpoint() string { 979 base := region.getBaseEndpoint() 980 if len(base) > 0 { 981 return "s3-website." + base 982 } 983 return "" 984 } 985 986 func (region *SRegion) getEc2Endpoint() string { 987 return region.RegionEndpoint 988 } 989 990 func (self *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) { 991 return nil, cloudprovider.ErrNotSupported 992 } 993 994 func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) { 995 return nil, cloudprovider.ErrNotImplemented 996 } 997 998 func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { 999 backendgroups, err := self.GetElbBackendgroups("", nil) 1000 if err != nil { 1001 return nil, errors.Wrap(err, "GetElbBackendgroups") 1002 } 1003 1004 ret := make([]cloudprovider.ICloudLoadbalancerBackendGroup, len(backendgroups)) 1005 for i := range backendgroups { 1006 ret[i] = &backendgroups[i] 1007 } 1008 1009 return ret, nil 1010 } 1011 1012 func (self *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) { 1013 secgroups, total, err := self.GetSecurityGroups("", "", secgroupId, 0, 1) 1014 if err != nil { 1015 return nil, errors.Wrap(err, "GetSecurityGroups") 1016 } 1017 if total == 0 { 1018 return nil, cloudprovider.ErrNotFound 1019 } 1020 if total > 1 { 1021 return nil, cloudprovider.ErrDuplicateId 1022 } 1023 return &secgroups[0], nil 1024 } 1025 1026 func (self *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) { 1027 secgroups, total, err := self.GetSecurityGroups(opts.VpcId, opts.Name, "", 0, 1) 1028 if err != nil { 1029 return nil, errors.Wrap(err, "GetSecurityGroups") 1030 } 1031 if total == 0 { 1032 return nil, cloudprovider.ErrNotFound 1033 } 1034 if total > 1 { 1035 return nil, cloudprovider.ErrDuplicateId 1036 } 1037 return &secgroups[0], nil 1038 } 1039 1040 func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) { 1041 groupId, err := self.CreateSecurityGroup(conf.VpcId, conf.Name, "", conf.Desc) 1042 if err != nil { 1043 return nil, errors.Wrap(err, "CreateSecurityGroup") 1044 } 1045 return self.GetISecurityGroupById(groupId) 1046 } 1047 1048 func (region *SRegion) GetCapabilities() []string { 1049 return region.client.GetCapabilities() 1050 } 1051 1052 func (region *SRegion) CreateInternetGateway() (cloudprovider.ICloudInternetGateway, error) { 1053 ec2Client, err := region.getEc2Client() 1054 if err != nil { 1055 return nil, errors.Wrap(err, "getEc2Client") 1056 } 1057 input := ec2.CreateInternetGatewayInput{} 1058 output, err := ec2Client.CreateInternetGateway(&input) 1059 if err != nil { 1060 return nil, errors.Wrap(err, "CreateInternetGateway") 1061 } 1062 1063 ret := &SInternetGateway{} 1064 ret.region = region 1065 err = unmarshalAwsOutput(output, "InternetGateway", ret) 1066 if err != nil { 1067 return nil, errors.Wrap(err, "unmarshalAwsOutput") 1068 } 1069 1070 return ret, nil 1071 }