Files
cloudpods/pkg/multicloud/aws/region.go
T
2020-07-30 14:48:16 +08:00

1098 lines
28 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package aws
import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"net/url"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol/query"
"github.com/aws/aws-sdk-go/service/acm"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/s3"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
var RegionLocations = map[string]string{
"us-east-2": "美国东部(俄亥俄州)",
"us-east-1": "美国东部(弗吉尼亚北部)",
"us-west-1": "美国西部(加利福尼亚北部)",
"us-west-2": "美国西部(俄勒冈)",
"ap-east-1": "亚太区域(香港)",
"ap-south-1": "亚太区域(孟买)",
"ap-northeast-3": "亚太区域(大阪-本地)",
"ap-northeast-2": "亚太区域(首尔)",
"ap-southeast-1": "亚太区域(新加坡)",
"ap-southeast-2": "亚太区域(悉尼)",
"ap-northeast-1": "亚太区域(东京)",
"ca-central-1": "加拿大(中部)",
"cn-north-1": "中国(北京)",
"cn-northwest-1": "中国(宁夏)",
"eu-central-1": "欧洲(法兰克福)",
"eu-west-1": "欧洲(爱尔兰)",
"eu-west-2": "欧洲(伦敦)",
"eu-west-3": "欧洲(巴黎)",
"eu-north-1": "欧洲(斯德哥尔摩)",
"me-south-1": "中东(巴林)",
"sa-east-1": "南美洲(圣保罗)",
"us-gov-west-1": "AWS GovCloud(美国西部)",
"us-gov-east-1": "AWS GovCloud(美国东部)",
}
const (
RDS_SERVICE_NAME = "rds"
RDS_SERVICE_ID = "RDS"
EC2_SERVICE_NAME = "ec2"
EC2_SERVICE_ID = "EC2"
CLOUDWATCH_SERVICE_NAME = "monitoring"
CLOUDWATCH_SERVICE_ID = "CloudWatch"
)
type SRegion struct {
multicloud.SRegion
client *SAwsClient
ec2Client *ec2.EC2
iamClient *iam.IAM
s3Client *s3.S3
elbv2Client *elbv2.ELBV2
acmClient *acm.ACM
izones []cloudprovider.ICloudZone
ivpcs []cloudprovider.ICloudVpc
storageCache *SStoragecache
RegionEndpoint string
RegionId string // 这里为保持一致沿用阿里云RegionId的叫法, 与AWS RegionName字段对应
}
/////////////////////////////////////////////////////////////////////////////
/* 请不要使用这个client(AWS_DEFAULT_REGION)跨region查信息.有可能导致查询返回的信息为空。比如DescribeAvailabilityZones*/
func (self *SRegion) GetClient() *SAwsClient {
return self.client
}
func (self *SRegion) getAwsSession() (*session.Session, error) {
return self.client.getAwsSession(self.RegionId)
}
func (self *SRegion) getEc2Client() (*ec2.EC2, error) {
if self.ec2Client == nil {
s, err := self.getAwsSession()
if err != nil {
return nil, err
}
self.ec2Client = ec2.New(s)
return self.ec2Client, nil
}
return self.ec2Client, nil
}
func (self *SRegion) getIamClient() (*iam.IAM, error) {
if self.iamClient == nil {
s, err := self.getAwsSession()
if err != nil {
return nil, err
}
self.iamClient = iam.New(s)
}
return self.iamClient, nil
}
func (self *SRegion) GetS3Client() (*s3.S3, error) {
if self.s3Client == nil {
s, err := self.getAwsSession()
if err != nil {
return nil, err
}
self.s3Client = s3.New(s)
}
return self.s3Client, nil
}
var UnmarshalHandler = request.NamedHandler{Name: "yunion.query.Unmarshal", Fn: Unmarshal}
func Unmarshal(r *request.Request) {
defer r.HTTPResponse.Body.Close()
if r.DataFilled() {
var decoder *xml.Decoder
if DEBUG {
body, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("ioutil.ReadAll", "read response body", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
log.Debugf("response: \n%s", string(body))
decoder = xml.NewDecoder(strings.NewReader(string(body)))
} else {
decoder = xml.NewDecoder(r.HTTPResponse.Body)
}
if r.ClientInfo.ServiceID == EC2_SERVICE_ID {
err := decoder.Decode(r.Data)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("SerializationError", "failed decoding EC2 Query response", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
}
return
}
for {
tok, err := decoder.Token()
if err != nil {
if err == io.EOF {
break
}
r.Error = awserr.NewRequestFailure(
awserr.New("decoder.Token()", "get token", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
if tok == nil {
break
}
switch typed := tok.(type) {
case xml.CharData:
continue
case xml.StartElement:
if typed.Name.Local == r.Operation.Name+"Result" {
err = decoder.DecodeElement(r.Data, &typed)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("DecodeElement", "failed decoding Query response", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
}
return
}
case xml.EndElement:
break
}
}
}
}
var buildHandler = request.NamedHandler{Name: "yunion.query.Build", Fn: Build}
func Build(r *request.Request) {
body := url.Values{
"Action": {r.Operation.Name},
"Version": {r.ClientInfo.APIVersion},
}
if r.Params != nil {
if params, ok := r.Params.(map[string]string); ok {
for k, v := range params {
body.Add(k, v)
}
}
}
if DEBUG {
log.Debugf("params: %s", body.Encode())
}
if !r.IsPresigned() {
r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode()))
} else { // This is a pre-signed request
r.HTTPRequest.Method = "GET"
r.HTTPRequest.URL.RawQuery = body.Encode()
}
}
func (self *SRegion) rdsRequest(apiName string, params map[string]string, retval interface{}) error {
session, err := self.getAwsSession()
if err != nil {
return err
}
c := session.ClientConfig(RDS_SERVICE_NAME)
metadata := metadata.ClientInfo{
ServiceName: RDS_SERVICE_NAME,
ServiceID: RDS_SERVICE_ID,
SigningName: c.SigningName,
SigningRegion: c.SigningRegion,
Endpoint: c.Endpoint,
APIVersion: "2014-10-31",
}
if self.client.debug {
logLevel := aws.LogLevelType(uint(aws.LogDebugWithRequestErrors) + uint(aws.LogDebugWithHTTPBody))
c.Config.LogLevel = &logLevel
}
client := client.New(*c.Config, metadata, c.Handlers)
client.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
client.Handlers.Build.PushBackNamed(buildHandler)
client.Handlers.Unmarshal.PushBackNamed(UnmarshalHandler)
client.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
client.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
return jsonRequest(client, apiName, params, retval, true)
}
func (self *SRegion) ec2Request(apiName string, params map[string]string, retval interface{}) error {
session, err := self.getAwsSession()
if err != nil {
return err
}
c := session.ClientConfig(EC2_SERVICE_NAME)
metadata := metadata.ClientInfo{
ServiceName: EC2_SERVICE_NAME,
ServiceID: EC2_SERVICE_ID,
SigningName: c.SigningName,
SigningRegion: c.SigningRegion,
Endpoint: c.Endpoint,
APIVersion: "2016-11-15",
}
requestErr := aws.LogDebugWithRequestErrors
c.Config.LogLevel = &requestErr
client := client.New(*c.Config, metadata, c.Handlers)
client.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
client.Handlers.Build.PushBackNamed(buildHandler)
client.Handlers.Unmarshal.PushBackNamed(UnmarshalHandler)
client.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
client.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
return jsonRequest(client, apiName, params, retval, true)
}
func (self *SRegion) cloudWatchRequest(apiName string, params *cloudwatch.GetMetricStatisticsInput,
retval interface{}) error {
session, err := self.getAwsSession()
if err != nil {
return err
}
c := session.ClientConfig(CLOUDWATCH_SERVICE_NAME)
metadata := metadata.ClientInfo{
ServiceName: CLOUDWATCH_SERVICE_NAME,
ServiceID: CLOUDWATCH_SERVICE_ID,
SigningName: c.SigningName,
SigningRegion: c.SigningRegion,
Endpoint: c.Endpoint,
APIVersion: "2010-08-01",
}
requestErr := aws.LogDebugWithRequestErrors
c.Config.LogLevel = &requestErr
client := client.New(*c.Config, metadata, c.Handlers)
client.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
client.Handlers.Build.PushBackNamed(query.BuildHandler)
client.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler)
client.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
client.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
return cloudWatchRequest(client, apiName, params, retval, true)
}
func (self *SRegion) GetElbV2Client() (*elbv2.ELBV2, error) {
if self.elbv2Client == nil {
s, err := self.getAwsSession()
if err != nil {
return nil, err
}
self.elbv2Client = elbv2.New(s)
}
return self.elbv2Client, nil
}
/////////////////////////////////////////////////////////////////////////////
func (self *SRegion) fetchZones() error {
// todo: 这里将过滤出指定region下全部的zones。是否只过滤出可用的zone即可? The state of the Availability Zone (available | information | impaired | unavailable)
zones, err := self.ec2Client.DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{})
if err != nil {
return err
}
err = FillZero(zones)
if err != nil {
return err
}
self.izones = make([]cloudprovider.ICloudZone, 0)
for _, zone := range zones.AvailabilityZones {
self.izones = append(self.izones, &SZone{ZoneId: *zone.ZoneName, State: *zone.State, LocalName: *zone.ZoneName, region: self})
}
return nil
}
func (self *SRegion) fetchIVpcs() error {
vpcs, err := self.ec2Client.DescribeVpcs(&ec2.DescribeVpcsInput{})
if err != nil {
return err
}
self.ivpcs = make([]cloudprovider.ICloudVpc, 0)
for _, vpc := range vpcs.Vpcs {
tags := make(map[string]string, 0)
for _, tag := range vpc.Tags {
tags[*tag.Key] = *tag.Value
}
self.ivpcs = append(self.ivpcs, &SVpc{region: self,
CidrBlock: *vpc.CidrBlock,
Tags: tags,
IsDefault: *vpc.IsDefault,
RegionId: self.RegionId,
Status: *vpc.State,
VpcId: *vpc.VpcId,
VpcName: tags["Name"],
InstanceTenancy: *vpc.InstanceTenancy,
})
}
return nil
}
func (self *SRegion) fetchInfrastructure() error {
if _, err := self.getEc2Client(); err != nil {
return err
}
if err := self.fetchZones(); err != nil {
return err
}
if err := self.fetchIVpcs(); err != nil {
return err
}
for i := 0; i < len(self.ivpcs); i += 1 {
for j := 0; j < len(self.izones); j += 1 {
zone := self.izones[j].(*SZone)
vpc := self.ivpcs[i].(*SVpc)
wire := SWire{zone: zone, vpc: vpc}
zone.addWire(&wire)
vpc.addWire(&wire)
}
}
return nil
}
func (self *SRegion) GetId() string {
return self.RegionId
}
func (self *SRegion) GetName() string {
if localName, ok := RegionLocations[self.RegionId]; ok {
return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, localName)
}
return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, self.RegionId)
}
func (self *SRegion) GetGlobalId() string {
return fmt.Sprintf("%s/%s", self.client.GetAccessEnv(), self.RegionId)
}
func (self *SRegion) GetStatus() string {
return api.CLOUD_REGION_STATUS_INSERVER
}
func (self *SRegion) Refresh() error {
return nil
}
func (self *SRegion) IsEmulated() bool {
return false
}
func (self *SRegion) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
if info, ok := LatitudeAndLongitude[self.RegionId]; ok {
return info
}
return cloudprovider.SGeographicInfo{}
}
func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
if self.izones == nil {
if err := self.fetchInfrastructure(); err != nil {
return nil, err
}
}
return self.izones, nil
}
func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
if self.ivpcs == nil {
err := self.fetchInfrastructure()
if err != nil {
return nil, err
}
}
return self.ivpcs, nil
}
func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
return self.GetInstance(id)
}
func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
return self.GetDisk(id)
}
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
_, err := self.getEc2Client()
if err != nil {
return nil, err
}
eips, total, err := self.GetEips("", "", 0, 0)
if err != nil {
return nil, err
}
ret := make([]cloudprovider.ICloudEIP, total)
for i := 0; i < len(eips); i += 1 {
ret[i] = &eips[i]
}
return ret, nil
}
func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
snapshots, _, err := self.GetSnapshots("", "", "", []string{}, 0, 0)
if err != nil {
return nil, err
}
ret := make([]cloudprovider.ICloudSnapshot, len(snapshots))
for i := 0; i < len(snapshots); i += 1 {
ret[i] = &snapshots[i]
}
return ret, nil
}
func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for _, zone := range izones {
if zone.GetGlobalId() == id {
return zone, nil
}
}
return nil, ErrorNotFound()
}
func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
ivpcs, err := self.GetIVpcs()
if err != nil {
return nil, err
}
for _, vpc := range ivpcs {
if vpc.GetGlobalId() == id {
return vpc, nil
}
}
return nil, ErrorNotFound()
}
func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
ihost, err := izones[i].GetIHostById(id)
if err == nil {
return ihost, nil
} else if err != cloudprovider.ErrNotFound {
return nil, err
}
}
return nil, ErrorNotFound()
}
func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
istore, err := izones[i].GetIStorageById(id)
if err == nil {
return istore, nil
} else if err != cloudprovider.ErrNotFound {
return nil, err
}
}
return nil, ErrorNotFound()
}
func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
iHosts := make([]cloudprovider.ICloudHost, 0)
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
iZoneHost, err := izones[i].GetIHosts()
if err != nil {
return nil, err
}
iHosts = append(iHosts, iZoneHost...)
}
return iHosts, nil
}
func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
iStores := make([]cloudprovider.ICloudStorage, 0)
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
iZoneStores, err := izones[i].GetIStorages()
if err != nil {
return nil, err
}
iStores = append(iStores, iZoneStores...)
}
return iStores, nil
}
func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
if self.storageCache == nil {
self.storageCache = &SStoragecache{region: self}
}
if self.storageCache.GetGlobalId() == id {
return self.storageCache, nil
}
return nil, ErrorNotFound()
}
func (self *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudprovider.ICloudVpc, error) {
tagspec := TagSpec{ResourceType: "vpc"}
if len(name) > 0 {
tagspec.SetNameTag(name)
}
if len(desc) > 0 {
tagspec.SetDescTag(desc)
}
spec, err := tagspec.GetTagSpecifications()
if err != nil {
return nil, err
}
// start create vpc
vpc, err := self.ec2Client.CreateVpc(&ec2.CreateVpcInput{CidrBlock: &cidr})
if err != nil {
return nil, err
}
tagsParams := &ec2.CreateTagsInput{Resources: []*string{vpc.Vpc.VpcId}, Tags: spec.Tags}
_, err = self.ec2Client.CreateTags(tagsParams)
if err != nil {
log.Debugf("CreateIVpc add tag failed %s", err.Error())
}
err = self.fetchInfrastructure()
if err != nil {
return nil, err
}
return self.GetIVpcById(*vpc.Vpc.VpcId)
}
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
eips, total, err := self.GetEips(eipId, "", 0, 0)
if err != nil {
return nil, err
}
if total == 0 {
return nil, ErrorNotFound()
}
if total > 1 {
return nil, cloudprovider.ErrDuplicateId
}
return &eips[0], nil
}
func (self *SRegion) GetProvider() string {
return CLOUD_PROVIDER_AWS
}
func (self *SRegion) GetCloudEnv() string {
return self.client.accessUrl
}
func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, memGB int, storageType string, dataDiskSizesGB []int, networkId string, publicKey string) (*SInstance, error) {
izones, err := self.GetIZones()
if err != nil {
return nil, err
}
for i := 0; i < len(izones); i += 1 {
z := izones[i].(*SZone)
log.Debugf("Search in zone %s", z.LocalName)
net := z.getNetworkById(networkId)
if net != nil {
desc := &cloudprovider.SManagedVMCreateConfig{
Name: name,
ExternalImageId: imgId,
SysDisk: cloudprovider.SDiskInfo{SizeGB: 0, StorageType: storageType},
Cpu: cpu,
MemoryMB: memGB * 1024,
ExternalNetworkId: networkId,
DataDisks: []cloudprovider.SDiskInfo{},
PublicKey: publicKey,
}
for _, sizeGB := range dataDiskSizesGB {
desc.DataDisks = append(desc.DataDisks, cloudprovider.SDiskInfo{SizeGB: sizeGB, StorageType: storageType})
}
inst, err := z.getHost().CreateVM(desc)
if err != nil {
return nil, err
}
return inst.(*SInstance), nil
}
}
return nil, fmt.Errorf("cannot find vswitch %s", networkId)
}
func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
client, err := self.GetElbV2Client()
if err != nil {
return nil, err
}
params := &elbv2.DescribeLoadBalancersInput{}
ret, err := client.DescribeLoadBalancers(params)
if err != nil {
return nil, err
}
result := make([]SElb, 0)
err = unmarshalAwsOutput(ret, "LoadBalancers", &result)
if err != nil {
return nil, err
}
ielbs := make([]cloudprovider.ICloudLoadbalancer, len(result))
for i := range result {
result[i].region = self
ielbs[i] = &result[i]
}
return ielbs, nil
}
func (self *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) {
client, err := self.GetElbV2Client()
if err != nil {
return nil, err
}
params := &elbv2.DescribeLoadBalancersInput{}
params.SetLoadBalancerArns([]*string{&loadbalancerId})
ret, err := client.DescribeLoadBalancers(params)
if err != nil {
if strings.Contains(err.Error(), "LoadBalancerNotFound") {
return nil, cloudprovider.ErrNotFound
}
return nil, err
}
elbs := []SElb{}
err = unmarshalAwsOutput(ret, "LoadBalancers", &elbs)
if err != nil {
return nil, err
}
if len(elbs) == 1 {
elbs[0].region = self
return &elbs[0], nil
}
return nil, ErrorNotFound()
}
func (self *SRegion) getElbAttributesById(loadbalancerId string) (map[string]string, error) {
client, err := self.GetElbV2Client()
if err != nil {
return nil, err
}
params := &elbv2.DescribeLoadBalancerAttributesInput{}
params.SetLoadBalancerArn(loadbalancerId)
output, err := client.DescribeLoadBalancerAttributes(params)
if err != nil {
return nil, err
}
attrs := []map[string]string{}
err = unmarshalAwsOutput(output, "Attributes", &attrs)
if err != nil {
return nil, err
}
ret := map[string]string{}
for i := range attrs {
for k, v := range attrs[i] {
ret[k] = v
}
}
return ret, nil
}
func (self *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) {
return nil, cloudprovider.ErrNotSupported
}
func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
certs, err := self.GetILoadBalancerCertificates()
if err != nil {
return nil, err
}
for i := range certs {
if certs[i].GetId() == certId {
return certs[i], nil
}
}
return nil, ErrorNotFound()
}
func (self *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
client, err := self.getIamClient()
if err != nil {
return nil, errors.Wrap(err, "region.CreateILoadBalancerCertificate.getIamClient")
}
params := &iam.UploadServerCertificateInput{}
params.SetServerCertificateName(cert.Name)
params.SetPrivateKey(cert.PrivateKey)
params.SetCertificateBody(cert.Certificate)
ret, err := client.UploadServerCertificate(params)
if err != nil {
return nil, errors.Wrap(err, "region.CreateILoadBalancerCertificate.UploadServerCertificate")
}
// wait upload cert success
err = cloudprovider.Wait(5*time.Second, 30*time.Second, func() (bool, error) {
_, err := self.GetILoadBalancerCertificateById(*ret.ServerCertificateMetadata.Arn)
if err == nil {
return true, nil
}
if err == cloudprovider.ErrNotFound {
return false, nil
} else {
return false, err
}
})
if err != nil {
return nil, errors.Wrap(err, "region.CreateILoadBalancerCertificate.Wait")
}
return self.GetILoadBalancerCertificateById(*ret.ServerCertificateMetadata.Arn)
}
func (self *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) {
return nil, cloudprovider.ErrNotSupported
}
func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
client, err := self.getIamClient()
if err != nil {
return nil, err
}
params := &iam.ListServerCertificatesInput{}
ret, err := client.ListServerCertificates(params)
if err != nil {
return nil, err
}
certs := []SElbCertificate{}
err = unmarshalAwsOutput(ret, "ServerCertificateMetadataList", &certs)
if err != nil {
return nil, err
}
icerts := make([]cloudprovider.ICloudLoadbalancerCertificate, len(certs))
for i := range certs {
certs[i].region = self
icerts[i] = &certs[i]
}
return icerts, nil
}
func (self *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) {
client, err := self.GetElbV2Client()
if err != nil {
return nil, err
}
params := &elbv2.CreateLoadBalancerInput{}
params.SetName(loadbalancer.Name)
params.SetType(loadbalancer.LoadbalancerSpec)
params.SetIpAddressType("ipv4")
if loadbalancer.AddressType == api.LB_ADDR_TYPE_INTERNET {
params.SetScheme("internet-facing")
} else {
params.SetScheme("internal")
}
// params.SetSecurityGroups()
params.SetSubnets(ConvertedList(loadbalancer.NetworkIDs))
ret, err := client.CreateLoadBalancer(params)
if err != nil {
return nil, err
}
elbs := []SElb{}
err = unmarshalAwsOutput(ret, "LoadBalancers", &elbs)
if err != nil {
return nil, err
}
if len(elbs) == 1 {
elbs[0].region = self
return &elbs[0], nil
}
return nil, fmt.Errorf("CreateILoadBalancer error %#v", elbs)
}
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
iBuckets, err := region.client.getIBuckets()
if err != nil {
return nil, errors.Wrap(err, "getIBuckets")
}
ret := make([]cloudprovider.ICloudBucket, 0)
for i := range iBuckets {
if iBuckets[i].GetLocation() != region.GetId() {
continue
}
ret = append(ret, iBuckets[i])
}
return ret, nil
}
func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error {
s3cli, err := region.GetS3Client()
if err != nil {
return errors.Wrap(err, "GetS3Client")
}
input := &s3.CreateBucketInput{}
input.SetBucket(name)
input.CreateBucketConfiguration = &s3.CreateBucketConfiguration{}
input.CreateBucketConfiguration.SetLocationConstraint(region.GetId())
_, err = s3cli.CreateBucket(input)
if err != nil {
return errors.Wrap(err, "CreateBucket")
}
region.client.invalidateIBuckets()
// if *output.Location != region.GetId() {
// log.Warningf("Request location %s != got locaiton %s", region.GetId(), *output.Location)
// }
return nil
}
func (region *SRegion) DeleteIBucket(name string) error {
s3cli, err := region.GetS3Client()
if err != nil {
return errors.Wrap(err, "GetS3Client")
}
input := &s3.DeleteBucketInput{}
input.Bucket = &name
_, err = s3cli.DeleteBucket(input)
if err != nil {
if region.client.debug {
log.Debugf("%#v %s", err, err)
}
if strings.Index(err.Error(), "NoSuchBucket:") >= 0 {
return nil
}
return errors.Wrap(err, "DeleteBucket")
}
region.client.invalidateIBuckets()
return nil
}
func (region *SRegion) IBucketExist(name string) (bool, error) {
s3cli, err := region.GetS3Client()
if err != nil {
return false, errors.Wrap(err, "GetS3Client")
}
input := &s3.HeadBucketInput{}
input.Bucket = &name
_, err = s3cli.HeadBucket(input)
if err != nil {
if region.client.debug {
log.Debugf("%#v %s", err, err)
}
if strings.Index(err.Error(), "NotFound:") >= 0 {
return false, nil
}
return false, errors.Wrap(err, "IsBucketExist")
}
return true, nil
}
func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) {
return cloudprovider.GetIBucketById(region, name)
}
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
return region.GetIBucketById(name)
}
func (region *SRegion) getBaseEndpoint() string {
if len(region.RegionEndpoint) > 4 {
return region.RegionEndpoint[4:]
}
return ""
}
func (region *SRegion) getS3Endpoint() string {
base := region.getBaseEndpoint()
if len(base) > 0 {
return "s3." + base
}
return ""
}
func (region *SRegion) getEc2Endpoint() string {
return region.RegionEndpoint
}
func (self *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
return nil, cloudprovider.ErrNotSupported
}
func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
backendgroups, err := self.GetElbBackendgroups("", nil)
if err != nil {
return nil, err
}
ret := make([]cloudprovider.ICloudLoadbalancerBackendGroup, len(backendgroups))
for i := range backendgroups {
ret[i] = &backendgroups[i]
}
return ret, nil
}
func (self *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
secgroups, total, err := self.GetSecurityGroups("", "", secgroupId, 0, 1)
if err != nil {
return nil, err
}
if total == 0 {
return nil, cloudprovider.ErrNotFound
}
if total > 1 {
return nil, cloudprovider.ErrDuplicateId
}
return &secgroups[0], nil
}
func (self *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) {
secgroups, total, err := self.GetSecurityGroups(opts.VpcId, opts.Name, "", 0, 1)
if err != nil {
return nil, err
}
if total == 0 {
return nil, cloudprovider.ErrNotFound
}
if total > 1 {
return nil, cloudprovider.ErrDuplicateId
}
return &secgroups[0], nil
}
func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
groupId, err := self.CreateSecurityGroup(conf.VpcId, conf.Name, "", conf.Desc)
if err != nil {
return nil, err
}
return self.GetISecurityGroupById(groupId)
}
func (region *SRegion) GetCapabilities() []string {
return region.client.GetCapabilities()
}