| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289 |
- // 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 aliyun
- import (
- "fmt"
- "strings"
- "time"
- "github.com/aliyun/alibaba-cloud-sdk-go/sdk"
- alierr "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
- "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
- "github.com/aliyun/aliyun-oss-go-sdk/oss"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/regutils"
- "yunion.io/x/pkg/utils"
- api "yunion.io/x/cloudmux/pkg/apis/compute"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/cloudmux/pkg/multicloud"
- )
- type SRegion struct {
- multicloud.SRegion
- client *SAliyunClient
- sdkClient *sdk.Client
- ossClient *oss.Client
- mongoSkus map[string]struct {
- CpuCount int
- MemSizeGb int
- }
- RegionId string
- LocalName string
- RegionEndpoint string
- izones []cloudprovider.ICloudZone
- ivpcs []cloudprovider.ICloudVpc
- lbEndpints map[string]string
- storageCache *SStoragecache
- instanceTypes []SInstanceType
- latitude float64
- longitude float64
- fetchLocation bool
- }
- func (self *SRegion) GetClient() *SAliyunClient {
- return self.client
- }
- func (self *SRegion) getSdkClient() (*sdk.Client, error) {
- if self.sdkClient == nil {
- cli, err := self.client.getSdkClient(self.RegionId)
- if err != nil {
- return nil, err
- }
- self.sdkClient = cli
- }
- return self.sdkClient, nil
- }
- func (self *SRegion) getEcsClient() (*ecs.Client, error) {
- sdkClient, err := self.getSdkClient()
- if err != nil {
- return nil, errors.Wrap(err, "getSdkClient")
- }
- ecsClient := &ecs.Client{
- Client: *sdkClient,
- }
- return ecsClient, nil
- }
- func (self *SRegion) getOSSExternalDomain() string {
- return getOSSExternalDomain(self.RegionId)
- }
- func (self *SRegion) getOSSInternalDomain() string {
- return getOSSInternalDomain(self.RegionId)
- }
- func (self *SRegion) getRegionId() string {
- if self.client.cloudEnv == ALIYUN_FINANCE_CLOUDENV {
- switch self.RegionId {
- case "cn-hangzhou":
- return "cn-hzfinance"
- case "cn-shanghai-finance-1":
- return "cn-shanghai-finance-1-pub"
- case "cn-shenzhen-finance-1":
- return "cn-szfinance"
- }
- }
- return self.RegionId
- }
- func (self *SRegion) GetOssClient() (*oss.Client, error) {
- if self.ossClient == nil {
- cli, err := self.client.getOssClient(self.getRegionId())
- if err != nil {
- return nil, errors.Wrap(err, "self.client.getOssClient")
- }
- self.ossClient = cli
- }
- return self.ossClient, nil
- }
- func (self *SRegion) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- endpoint := self.RegionEndpoint
- if len(endpoint) == 0 {
- endpoint = "ecs.aliyuncs.com"
- }
- params = self.client.SetResourceGropuId(params)
- return jsonRequest(client, endpoint, ALIYUN_API_VERSION, apiName, params, self.client.debug)
- }
- func (self *SRegion) wafRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- if self.RegionId != "cn-hangzhou" && self.RegionId != "ap-southeast-1" {
- return nil, cloudprovider.ErrNotSupported
- }
- params = self.client.SetResourceGropuId(params)
- endpoint := fmt.Sprintf("wafopenapi.%s.aliyuncs.com", self.RegionId)
- return jsonRequest(client, endpoint, ALIYUN_WAF_API_VERSION, apiName, params, self.client.debug)
- }
- func (self *SRegion) wafv2Request(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- if self.RegionId != "cn-hangzhou" && self.RegionId != "ap-southeast-1" {
- return nil, cloudprovider.ErrNotSupported
- }
- params = self.client.SetResourceGropuId(params)
- endpoint := fmt.Sprintf("wafopenapi.%s.aliyuncs.com", self.RegionId)
- return jsonRequest(client, endpoint, ALIYUN_WAF_V2_API_VERSION, apiName, params, self.client.debug)
- }
- func (self *SRegion) esRequest(apiName string, params map[string]string, body interface{}) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- domain := fmt.Sprintf("elasticsearch.%s.aliyuncs.com", self.RegionId)
- return doRequest(client, domain, ALIYUN_ES_API_VERSION, apiName, params, body, self.client.debug)
- }
- func (self *SRegion) kafkaRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- domain := fmt.Sprintf("alikafka.%s.aliyuncs.com", self.RegionId)
- return jsonRequest(client, domain, ALIYUN_KAFKA_API_VERSION, apiName, params, self.client.debug)
- }
- func (self *SRegion) rdsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- return jsonRequest(client, "rds.aliyuncs.com", ALIYUN_RDS_API_VERSION, apiName, params, self.client.debug)
- }
- func (self *SRegion) k8sRequest(apiName string, params map[string]string, body interface{}) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- return doRequest(client, fmt.Sprintf("cs.%s.aliyuncs.com", self.RegionId), ALIYUN_K8S_API_VERSION, apiName, params, body, self.client.debug)
- }
- func (self *SRegion) mongodbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- return jsonRequest(client, "mongodb.aliyuncs.com", ALIYUN_MONGO_DB_API_VERSION, apiName, params, self.client.debug)
- }
- func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- endpoint := self.GetClient().getVpcEndpoint(self.RegionId)
- return jsonRequest(client, endpoint, ALIYUN_API_VERSION_VPC, action, params, self.client.debug)
- }
- func (self *SRegion) nasRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- switch self.GetCloudEnv() {
- case ALIYUN_FINANCE_CLOUDENV:
- if strings.Contains(action, "FileSystem") {
- if self.RegionId == "cn-hangzhou" {
- params["RegionId"] = "cn-hangzhou-dg-a01"
- }
- }
- if strings.Contains(action, "Access") || strings.Contains(action, "MountTarget") {
- if self.RegionId == "cn-hangzhou" {
- params["RegionId"] = "cn-hangzhou-finance"
- }
- }
- }
- params = self.client.SetResourceGropuId(params)
- endpint := self.GetClient().getNasEndpoint(self.RegionId)
- return jsonRequest(client, endpint, ALIYUN_NAS_API_VERSION, action, params, self.client.debug)
- }
- func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- if _, ok := params["RegionId"]; ok {
- params["RegionId"] = transRegionIdFromEcsRegionId(self, "redis")
- }
- params = self.client.SetResourceGropuId(params)
- return jsonRequest(client, "r-kvstore.aliyuncs.com", ALIYUN_API_VERSION_KVS, action, params, self.client.debug)
- }
- func (self *SRegion) scRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- domain := "cas.aliyuncs.com"
- return jsonRequest(client, domain, ALIYUN_CAS_API_VERSION, apiName, params, self.client.debug)
- }
- type LBRegion struct {
- RegionEndpoint string
- RegionId string
- }
- func (self *SRegion) fetchLBRegions(client *sdk.Client) error {
- if len(self.lbEndpints) > 0 {
- return nil
- }
- params := map[string]string{}
- result, err := self._lbRequest(client, "DescribeRegions", "slb.aliyuncs.com", params)
- if err != nil {
- return err
- }
- self.lbEndpints = map[string]string{}
- regions := []LBRegion{}
- if err := result.Unmarshal(®ions, "Regions", "Region"); err != nil {
- return err
- }
- for _, region := range regions {
- self.lbEndpints[region.RegionId] = region.RegionEndpoint
- }
- return nil
- }
- func (self *SRegion) lbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- domain := "slb.aliyuncs.com"
- if !utils.IsInStringArray(apiName, []string{"DescribeRegions", "DescribeZones"}) {
- if regionId, ok := params["RegionId"]; ok {
- if err := self.fetchLBRegions(client); err != nil {
- return nil, err
- }
- endpoint, ok := self.lbEndpints[regionId]
- if !ok {
- return nil, fmt.Errorf("failed to find endpoint for lb region %s", regionId)
- }
- domain = endpoint
- }
- }
- params = self.client.SetResourceGropuId(params)
- return self._lbRequest(client, apiName, domain, params)
- }
- func (self *SRegion) _lbRequest(client *sdk.Client, apiName string, domain string, params map[string]string) (jsonutils.JSONObject, error) {
- return jsonRequest(client, domain, ALIYUN_API_VERSION_LB, apiName, params, self.client.debug)
- }
- func (self *SRegion) albRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- domain := fmt.Sprintf("alb.%s.aliyuncs.com", self.RegionId)
- return jsonRequest(client, domain, ALIYUN_API_VERSION_ALB, apiName, params, self.client.debug)
- }
- func (self *SRegion) nlbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- params = self.client.SetResourceGropuId(params)
- domain := fmt.Sprintf("nlb.%s.aliyuncs.com", self.RegionId)
- return jsonRequest(client, domain, ALIYUN_API_VERSION_NLB, apiName, params, self.client.debug)
- }
- // ///////////////////////////////////////////////////////////////////////////
- func (self *SRegion) GetId() string {
- return self.RegionId
- }
- func (self *SRegion) GetName() string {
- if self.GetCloudEnv() == ALIYUN_FINANCE_CLOUDENV && !strings.Contains(self.LocalName, "金融") {
- return fmt.Sprintf("%s %s %s", CLOUD_PROVIDER_ALIYUN_CN, self.LocalName, "金融云")
- } else {
- return fmt.Sprintf("%s %s", CLOUD_PROVIDER_ALIYUN_CN, self.LocalName)
- }
- }
- func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
- en := fmt.Sprintf("%s %s", CLOUD_PROVIDER_ALIYUN_EN, self.LocalName)
- table := cloudprovider.SModelI18nTable{}
- table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en)
- return table
- }
- func (self *SRegion) GetGlobalId() string {
- return fmt.Sprintf("%s/%s", self.client.GetAccessEnv(), self.RegionId)
- }
- func (self *SRegion) IsEmulated() bool {
- return false
- }
- func (self *SRegion) GetProvider() string {
- return CLOUD_PROVIDER_ALIYUN
- }
- func (self *SRegion) GetCloudEnv() string {
- return self.client.cloudEnv
- }
- func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
- if info, ok := LatitudeAndLongitude[self.RegionId]; ok {
- return info
- }
- return cloudprovider.SGeographicInfo{}
- }
- func (self *SRegion) GetStatus() string {
- return api.CLOUD_REGION_STATUS_INSERVER
- }
- func (self *SRegion) Refresh() error {
- // do nothing
- return nil
- }
- func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
- if self.izones == nil {
- var err error
- err = self.fetchInfrastructure()
- if err != nil {
- return nil, err
- }
- }
- return self.izones, nil
- }
- func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
- izones, err := self.GetIZones()
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(izones); i += 1 {
- if izones[i].GetGlobalId() == id {
- return izones[i], nil
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (self *SRegion) getStoragecache() *SStoragecache {
- if self.storageCache == nil {
- self.storageCache = &SStoragecache{region: self}
- }
- return self.storageCache
- }
- func (self *SRegion) _fetchZones(chargeType TChargeType, spotStrategy SpotStrategyType) error {
- params := make(map[string]string)
- params["RegionId"] = self.RegionId
- if len(chargeType) > 0 {
- params["InstanceChargeType"] = string(chargeType)
- }
- if len(spotStrategy) > 0 {
- params["SpotStrategy"] = string(spotStrategy)
- }
- body, err := self.ecsRequest("DescribeZones", params)
- if err != nil {
- return err
- }
- zones := make([]SZone, 0)
- err = body.Unmarshal(&zones, "Zones", "Zone")
- if err != nil {
- return err
- }
- self.izones = make([]cloudprovider.ICloudZone, len(zones))
- for i := 0; i < len(zones); i += 1 {
- zones[i].region = self
- self.izones[i] = &zones[i]
- }
- return nil
- }
- func (self *SRegion) getZoneById(id string) (*SZone, error) {
- izones, err := self.GetIZones()
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(izones); i += 1 {
- zone := izones[i].(*SZone)
- if zone.ZoneId == id {
- return zone, nil
- }
- }
- return nil, fmt.Errorf("no such zone %s", id)
- }
- 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) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
- if self.ivpcs == nil {
- err := self.fetchInfrastructure()
- if err != nil {
- return nil, err
- }
- }
- return self.ivpcs, nil
- }
- func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
- ivpcs, err := self.GetIVpcs()
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(ivpcs); i += 1 {
- if ivpcs[i].GetGlobalId() == id {
- return ivpcs[i], nil
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (self *SRegion) fetchIVpcs() error {
- vpcs := make([]SVpc, 0)
- for {
- part, total, err := self.GetVpcs(nil, len(vpcs), 50)
- if err != nil {
- return err
- }
- vpcs = append(vpcs, part...)
- if len(vpcs) >= total {
- break
- }
- }
- self.ivpcs = make([]cloudprovider.ICloudVpc, len(vpcs))
- for i := 0; i < len(vpcs); i += 1 {
- vpcs[i].region = self
- self.ivpcs[i] = &vpcs[i]
- }
- return nil
- }
- func (self *SRegion) fetchInfrastructure() error {
- err := self._fetchZones(PostPaidInstanceChargeType, NoSpotStrategy)
- if err != nil {
- return err
- }
- err = self.fetchIVpcs()
- if 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) GetVpcs(vpcId []string, offset int, limit int) ([]SVpc, int, error) {
- if limit > 50 || limit <= 0 {
- limit = 50
- }
- params := make(map[string]string)
- params["RegionId"] = self.RegionId
- params["PageSize"] = fmt.Sprintf("%d", limit)
- params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
- if vpcId != nil && len(vpcId) > 0 {
- params["VpcId"] = strings.Join(vpcId, ",")
- }
- body, err := self.vpcRequest("DescribeVpcs", params)
- if err != nil {
- log.Errorf("GetVpcs fail %s", err)
- return nil, 0, err
- }
- vpcs := make([]SVpc, 0)
- err = body.Unmarshal(&vpcs, "Vpcs", "Vpc")
- if err != nil {
- log.Errorf("Unmarshal vpc fail %s", err)
- return nil, 0, err
- }
- total, _ := body.Int("TotalCount")
- return vpcs, int(total), nil
- }
- func (self *SRegion) getVpc(vpcId string) (*SVpc, error) {
- vpcs, total, err := self.GetVpcs([]string{vpcId}, 0, 1)
- if err != nil {
- return nil, err
- }
- if total != 1 {
- return nil, cloudprovider.ErrNotFound
- }
- vpcs[0].region = self
- return &vpcs[0], nil
- }
- func (self *SRegion) GetVRouters(offset int, limit int) ([]SVRouter, int, error) {
- if limit > 50 || limit <= 0 {
- limit = 50
- }
- params := make(map[string]string)
- params["RegionId"] = self.RegionId
- params["PageSize"] = fmt.Sprintf("%d", limit)
- params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
- body, err := self.ecsRequest("DescribeVRouters", params)
- if err != nil {
- log.Errorf("GetVRouters fail %s", err)
- return nil, 0, err
- }
- vrouters := make([]SVRouter, 0)
- err = body.Unmarshal(&vrouters, "VRouters", "VRouter")
- if err != nil {
- log.Errorf("Unmarshal vrouter fail %s", err)
- return nil, 0, err
- }
- total, _ := body.Int("TotalCount")
- return vrouters, int(total), nil
- }
- func (self *SRegion) GetRouteTables(ids []string, offset int, limit int) ([]SRouteTable, int, error) {
- if limit > 50 || limit <= 0 {
- limit = 50
- }
- params := make(map[string]string)
- params["RegionId"] = self.RegionId
- params["PageSize"] = fmt.Sprintf("%d", limit)
- params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
- if ids != nil && len(ids) > 0 {
- params["RouteTableId"] = strings.Join(ids, ",")
- }
- body, err := self.ecsRequest("DescribeRouteTables", params)
- if err != nil {
- log.Errorf("GetRouteTables fail %s", err)
- return nil, 0, err
- }
- routetables := make([]SRouteTable, 0)
- err = body.Unmarshal(&routetables, "RouteTables", "RouteTable")
- if err != nil {
- log.Errorf("Unmarshal routetables fail %s", err)
- return nil, 0, err
- }
- total, _ := body.Int("TotalCount")
- return routetables, int(total), nil
- }
- func (self *SRegion) GetMatchInstanceTypes(cpu int, memMB int, gpu int, zoneId string) ([]SInstanceType, error) {
- if self.instanceTypes == nil {
- types, err := self.GetInstanceTypes()
- if err != nil {
- log.Errorf("GetInstanceTypes %s", err)
- return nil, err
- }
- self.instanceTypes = types
- }
- var available []string
- if len(zoneId) > 0 {
- zone, err := self.getZoneById(zoneId)
- if err != nil {
- return nil, err
- }
- available = zone.AvailableInstanceTypes.InstanceTypes
- }
- ret := make([]SInstanceType, 0)
- for _, t := range self.instanceTypes {
- if t.CpuCoreCount == cpu && memMB == t.memoryMB() && gpu == t.GPUAmount {
- if available == nil || utils.IsInStringArray(t.InstanceTypeId, available) {
- ret = append(ret, t)
- }
- }
- }
- return ret, nil
- }
- func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, memGB int, storageType string, dataDiskSizesGB []int, vswitchId string, passwd 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(vswitchId)
- if net != nil {
- desc := &cloudprovider.SManagedVMCreateConfig{
- Name: name,
- ExternalImageId: imgId,
- SysDisk: cloudprovider.SDiskInfo{SizeGB: 0, StorageType: storageType},
- Cpu: cpu,
- MemoryMB: memGB * 1024,
- ExternalNetworkId: vswitchId,
- Password: passwd,
- 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", vswitchId)
- }
- func (self *SRegion) instanceOperation(instanceId string, opname string, extra map[string]string) error {
- params := make(map[string]string)
- params["RegionId"] = self.RegionId
- params["InstanceId"] = instanceId
- if extra != nil && len(extra) > 0 {
- for k, v := range extra {
- params[k] = v
- }
- }
- _, err := self.ecsRequest(opname, params)
- return err
- }
- func (self *SRegion) GetInstanceStatus(instanceId string) (string, error) {
- instance, err := self.GetInstance(instanceId)
- if err != nil {
- return "", err
- }
- return instance.Status, nil
- }
- func (self *SRegion) GetInstanceVNCUrl(instanceId string) (string, error) {
- params := make(map[string]string)
- params["RegionId"] = self.RegionId
- params["InstanceId"] = instanceId
- body, err := self.ecsRequest("DescribeInstanceVncUrl", params)
- if err != nil {
- return "", err
- }
- return body.GetString("VncUrl")
- }
- func (self *SRegion) ModifyInstanceVNCUrlPassword(instanceId string, passwd string) error {
- params := make(map[string]string)
- params["RegionId"] = self.RegionId
- params["InstanceId"] = instanceId
- params["VncPassword"] = passwd // must be 6 digital + alphabet
- _, err := self.ecsRequest("ModifyInstanceVncPasswd", params)
- return err
- }
- func (self *SRegion) CreateVpc(opts *cloudprovider.VpcCreateOptions) (*SVpc, error) {
- params := make(map[string]string)
- if len(opts.CIDR) > 0 {
- params["CidrBlock"] = opts.CIDR
- }
- if len(opts.NAME) > 0 {
- params["VpcName"] = opts.NAME
- }
- if len(opts.Desc) > 0 {
- params["Description"] = opts.Desc
- }
- params["ClientToken"] = utils.GenRequestId(20)
- body, err := self.ecsRequest("CreateVpc", params)
- if err != nil {
- return nil, err
- }
- vpcId, err := body.GetString("VpcId")
- if err != nil {
- return nil, err
- }
- err = self.fetchInfrastructure()
- if err != nil {
- return nil, err
- }
- return self.getVpc(vpcId)
- }
- func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
- vpc, err := self.CreateVpc(opts)
- if err != nil {
- return nil, err
- }
- return vpc, nil
- }
- func (self *SRegion) DeleteVpc(vpcId string) error {
- params := make(map[string]string)
- params["VpcId"] = vpcId
- _, err := self.ecsRequest("DeleteVpc", params)
- return err
- }
- 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 errors.Cause(err) != cloudprovider.ErrNotFound {
- return nil, err
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- 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 errors.Cause(err) != cloudprovider.ErrNotFound {
- return nil, err
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- 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) updateInstance(instId string, name, desc, passwd, hostname, userData string) error {
- params := make(map[string]string)
- params["InstanceId"] = instId
- if len(name) > 0 {
- params["InstanceName"] = name
- }
- if len(desc) > 0 {
- params["Description"] = desc
- }
- if len(passwd) > 0 {
- params["Password"] = passwd
- }
- if len(hostname) > 0 {
- params["HostName"] = hostname
- }
- if len(userData) > 0 {
- params["UserData"] = userData
- }
- _, err := self.ecsRequest("ModifyInstanceAttribute", params)
- return err
- }
- func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error {
- return self.updateInstance(instId, "", "", passwd, "", "")
- }
- func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
- eips, err := self.GetEips("", "", "")
- if err != nil {
- return nil, err
- }
- ret := make([]cloudprovider.ICloudEIP, len(eips))
- for i := range eips {
- eips[i].region = self
- ret[i] = &eips[i]
- }
- return ret, nil
- }
- func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
- eip, err := self.GetEip(eipId)
- if err != nil {
- return nil, err
- }
- return eip, nil
- }
- func (region *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
- secgroup, err := region.GetSecurityGroup(secgroupId)
- if err != nil {
- return nil, err
- }
- return secgroup, nil
- }
- func (region *SRegion) CreateISecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
- externalId, err := region.CreateSecurityGroup(opts)
- if err != nil {
- return nil, err
- }
- return region.GetISecurityGroupById(externalId)
- }
- func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
- lbs, err := region.GetLoadbalancers(nil)
- if err != nil {
- return nil, err
- }
- ilbs := []cloudprovider.ICloudLoadbalancer{}
- for i := 0; i < len(lbs); i++ {
- lbs[i].region = region
- ilbs = append(ilbs, &lbs[i])
- }
- // 获取ALB实例
- albs, err := region.GetAlbs()
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(albs); i++ {
- albs[i].region = region
- ilbs = append(ilbs, &albs[i])
- }
- // 获取NLB实例
- nlbs, err := region.GetNlbs()
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(nlbs); i++ {
- nlbs[i].region = region
- ilbs = append(ilbs, &nlbs[i])
- }
- return ilbs, nil
- }
- func (region *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) {
- if strings.HasPrefix(loadbalancerId, "alb-") {
- return region.GetAlbDetail(loadbalancerId)
- } else if strings.HasPrefix(loadbalancerId, "nlb-") {
- return region.GetNlbDetail(loadbalancerId)
- }
- return region.GetLoadbalancerDetail(loadbalancerId)
- }
- func (region *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
- certs, err := region.GetLoadbalancerServerCertificates()
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(certs); i++ {
- if certs[i].GetGlobalId() == certId {
- certs[i].region = region
- return &certs[i], nil
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (region *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
- params := map[string]string{}
- params["RegionId"] = region.RegionId
- params["ServerCertificateName"] = cert.Name
- params["PrivateKey"] = cert.PrivateKey
- params["ServerCertificate"] = cert.Certificate
- body, err := region.lbRequest("UploadServerCertificate", params)
- if err != nil {
- return nil, err
- }
- certID, err := body.GetString("ServerCertificateId")
- if err != nil {
- return nil, err
- }
- return region.GetILoadBalancerCertificateById(certID)
- }
- func (region *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) {
- return region.GetLoadbalancerAclDetail(aclId)
- }
- func (region *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) {
- acls, err := region.GetLoadBalancerAcls()
- if err != nil {
- return nil, err
- }
- iAcls := []cloudprovider.ICloudLoadbalancerAcl{}
- for i := 0; i < len(acls); i++ {
- acls[i].region = region
- iAcls = append(iAcls, &acls[i])
- }
- return iAcls, nil
- }
- func (region *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
- certificates, err := region.GetLoadbalancerServerCertificates()
- if err != nil {
- return nil, err
- }
- iCertificates := []cloudprovider.ICloudLoadbalancerCertificate{}
- for i := 0; i < len(certificates); i++ {
- certificates[i].region = region
- iCertificates = append(iCertificates, &certificates[i])
- }
- return iCertificates, nil
- }
- func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancerCreateOptions) (cloudprovider.ICloudLoadbalancer, error) {
- params := map[string]string{}
- params["RegionId"] = region.RegionId
- params["LoadBalancerName"] = loadbalancer.Name
- if len(loadbalancer.ZoneId) > 0 {
- params["MasterZoneId"] = transZoneIdFromEcsZoneId(region, "elb", loadbalancer.ZoneId)
- }
- if len(loadbalancer.VpcId) > 0 {
- params["VpcId"] = loadbalancer.VpcId
- }
- if len(loadbalancer.NetworkIds) > 0 {
- params["VSwitchId"] = loadbalancer.NetworkIds[0]
- }
- if len(loadbalancer.Address) > 0 {
- params["Address"] = loadbalancer.Address
- }
- if len(loadbalancer.AddressType) > 0 {
- params["AddressType"] = loadbalancer.AddressType
- }
- if len(loadbalancer.LoadbalancerSpec) > 0 {
- params["LoadBalancerSpec"] = loadbalancer.LoadbalancerSpec
- }
- if len(loadbalancer.ChargeType) > 0 {
- params["InternetChargeType"] = "payby" + loadbalancer.ChargeType
- }
- if len(loadbalancer.ProjectId) > 0 {
- params["ResourceGroupId"] = loadbalancer.ProjectId
- }
- if loadbalancer.ChargeType == api.LB_CHARGE_TYPE_BY_BANDWIDTH && loadbalancer.EgressMbps > 0 {
- params["Bandwidth"] = fmt.Sprintf("%d", loadbalancer.EgressMbps)
- }
- body, err := region.lbRequest("CreateLoadBalancer", params)
- if err != nil {
- return nil, err
- }
- loadBalancerID, err := body.GetString("LoadBalancerId")
- if err != nil {
- return nil, err
- }
- region.SetResourceTags(ALIYUN_SERVICE_SLB, "instance", loadBalancerID, loadbalancer.Tags, false)
- iLoadbalancer, err := region.GetLoadbalancerDetail(loadBalancerID)
- if err != nil {
- return nil, err
- }
- return iLoadbalancer, cloudprovider.WaitStatus(iLoadbalancer, api.LB_STATUS_ENABLED, time.Second*5, time.Minute*5)
- }
- func (region *SRegion) AddAccessControlListEntry(aclId string, entrys []cloudprovider.SLoadbalancerAccessControlListEntry) error {
- params := map[string]string{}
- params["RegionId"] = region.RegionId
- params["AclId"] = aclId
- aclArray := jsonutils.NewArray()
- for i := 0; i < len(entrys); i++ {
- //阿里云AclEntrys参数必须是CIDR格式的。
- if regutils.MatchIPAddr(entrys[i].CIDR) {
- entrys[i].CIDR += "/32"
- }
- aclArray.Add(jsonutils.Marshal(map[string]string{"entry": entrys[i].CIDR, "comment": entrys[i].Comment}))
- }
- if aclArray.Length() == 0 {
- return nil
- }
- params["AclEntrys"] = aclArray.String()
- _, err := region.lbRequest("AddAccessControlListEntry", params)
- return err
- }
- func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
- params := map[string]string{}
- params["RegionId"] = region.RegionId
- params["AclName"] = acl.Name
- var body jsonutils.JSONObject
- var err error
- for i := 0; i < 20; i++ {
- body, err = region.lbRequest("CreateAccessControlList", params)
- if err == nil {
- break
- }
- if e, ok := errors.Cause(err).(*alierr.ServerError); ok && e.ErrorCode() == "AclNameExist" {
- params["AclName"] = fmt.Sprintf("%s-%d", acl.Name, i)
- continue
- }
- return nil, err
- }
- aclId, err := body.GetString("AclId")
- if err != nil {
- return nil, err
- }
- iAcl, err := region.GetLoadbalancerAclDetail(aclId)
- if err != nil {
- return nil, err
- }
- return iAcl, region.AddAccessControlListEntry(aclId, acl.Entrys)
- }
- 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].GetIRegion().GetId() != region.GetId() {
- continue
- }
- ret = append(ret, iBuckets[i])
- }
- return ret, nil
- }
- func str2StorageClass(storageClassStr string) (oss.StorageClassType, error) {
- storageClass := oss.StorageStandard
- if strings.EqualFold(storageClassStr, string(oss.StorageStandard)) {
- //
- } else if strings.EqualFold(storageClassStr, string(oss.StorageIA)) {
- storageClass = oss.StorageIA
- } else if strings.EqualFold(storageClassStr, string(oss.StorageArchive)) {
- storageClass = oss.StorageArchive
- } else {
- return storageClass, errors.Error("not supported storageClass")
- }
- return storageClass, nil
- }
- func str2Acl(aclStr string) (oss.ACLType, error) {
- acl := oss.ACLPrivate
- if strings.EqualFold(aclStr, string(oss.ACLPrivate)) {
- // private, default
- } else if strings.EqualFold(aclStr, string(oss.ACLPublicRead)) {
- acl = oss.ACLPublicRead
- } else if strings.EqualFold(aclStr, string(oss.ACLPublicReadWrite)) {
- acl = oss.ACLPublicReadWrite
- } else {
- return acl, errors.Error("not supported acl")
- }
- return acl, nil
- }
- func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
- osscli, err := region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "region.GetOssClient")
- }
- opts := make([]oss.Option, 0)
- if len(storageClassStr) > 0 {
- storageClass, err := str2StorageClass(storageClassStr)
- if err != nil {
- return err
- }
- opts = append(opts, oss.StorageClass(storageClass))
- }
- if len(aclStr) > 0 {
- acl, err := str2Acl(aclStr)
- if err != nil {
- return err
- }
- opts = append(opts, oss.ACL(acl))
- }
- err = osscli.CreateBucket(name, opts...)
- if err != nil {
- return errors.Wrap(err, "oss.CreateBucket")
- }
- region.client.invalidateIBuckets()
- return nil
- }
- func ossErrorCode(err error) int {
- if srvErr, ok := err.(oss.ServiceError); ok {
- return srvErr.StatusCode
- }
- if srvErr, ok := err.(*oss.ServiceError); ok {
- return srvErr.StatusCode
- }
- return -1
- }
- func (region *SRegion) DeleteIBucket(name string) error {
- osscli, err := region.GetOssClient()
- if err != nil {
- return errors.Wrap(err, "region.GetOssClient")
- }
- err = osscli.DeleteBucket(name)
- if err != nil {
- if ossErrorCode(err) == 404 {
- return nil
- }
- return errors.Wrap(err, "DeleteBucket")
- }
- region.client.invalidateIBuckets()
- return nil
- }
- func (region *SRegion) IBucketExist(name string) (bool, error) {
- osscli, err := region.GetOssClient()
- if err != nil {
- return false, errors.Wrap(err, "region.GetOssClient")
- }
- exist, err := osscli.IsBucketExist(name)
- if err != nil {
- return false, errors.Wrap(err, "IsBucketExist")
- }
- return exist, nil
- }
- func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) {
- osscli, err := region.GetOssClient()
- if err != nil {
- return nil, errors.Wrap(err, "region.GetOssClient")
- }
- bi, err := osscli.GetBucketInfo(name)
- if err != nil {
- return nil, errors.Wrap(err, "Bucket")
- }
- bInfo := bi.BucketInfo
- b := SBucket{
- region: region,
- Name: bInfo.Name,
- Location: bInfo.Location,
- CreationDate: bInfo.CreationDate,
- StorageClass: bInfo.StorageClass,
- }
- return &b, nil
- }
- func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
- return region.GetIBucketById(name)
- }
- func (self *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) {
- caches, err := self.GetElasticCaches(nil)
- if err != nil {
- return nil, err
- }
- icaches := make([]cloudprovider.ICloudElasticcache, len(caches))
- for i := range caches {
- caches[i].region = self
- icaches[i] = &caches[i]
- }
- return icaches, nil
- }
- func (region *SRegion) GetCapabilities() []string {
- return region.client.GetCapabilities()
- }
- func (self *SRegion) trialRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
- client, err := self.getSdkClient()
- if err != nil {
- return nil, err
- }
- domain := fmt.Sprintf("actiontrail.%s.aliyuncs.com", self.RegionId)
- return jsonRequest(client, domain, ALIYUN_API_VERSION_TRIAL, apiName, params, self.client.debug)
- }
- func (self *SRegion) GetIVMs() ([]cloudprovider.ICloudVM, error) {
- instances, err := self.GetInstances("", nil)
- if err != nil {
- return nil, err
- }
- ret := []cloudprovider.ICloudVM{}
- for i := range instances {
- ret = append(ret, &instances[i])
- }
- return ret, nil
- }
|