Files
cloudpods/pkg/multicloud/aws/region.go

1098 lines
28 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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(vpcId string, name string) (cloudprovider.ICloudSecurityGroup, error) {
secgroups, total, err := self.GetSecurityGroups(vpcId, 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()
}