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  }