yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/region.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package apsara
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  	"time"
    21  
    22  	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
    23  	"github.com/aliyun/aliyun-oss-go-sdk/oss"
    24  
    25  	"yunion.io/x/jsonutils"
    26  	"yunion.io/x/log"
    27  	"yunion.io/x/pkg/errors"
    28  	"yunion.io/x/pkg/util/regutils"
    29  	"yunion.io/x/pkg/utils"
    30  
    31  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    32  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    33  	"yunion.io/x/cloudmux/pkg/multicloud"
    34  )
    35  
    36  type SRegion struct {
    37  	multicloud.SRegion
    38  
    39  	client    *SApsaraClient
    40  	sdkClient *sdk.Client
    41  
    42  	RegionId  string
    43  	LocalName string
    44  
    45  	izones []cloudprovider.ICloudZone
    46  
    47  	ivpcs []cloudprovider.ICloudVpc
    48  
    49  	lbEndpints map[string]string
    50  
    51  	storageCache *SStoragecache
    52  
    53  	instanceTypes []SInstanceType
    54  
    55  	latitude      float64
    56  	longitude     float64
    57  	fetchLocation bool
    58  
    59  	ossEndpoint string
    60  }
    61  
    62  func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
    63  	return nil, cloudprovider.ErrNotImplemented
    64  }
    65  
    66  func (self *SRegion) GetClient() *SApsaraClient {
    67  	return self.client
    68  }
    69  
    70  func (self *SRegion) getSdkClient() (*sdk.Client, error) {
    71  	if self.sdkClient == nil {
    72  		var err error
    73  		self.sdkClient, err = self.GetClient().getDefaultClient(self.RegionId)
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  	}
    78  	return self.sdkClient, nil
    79  }
    80  
    81  func (self *SRegion) GetOssClient() (*oss.Client, error) {
    82  	if len(self.ossEndpoint) == 0 {
    83  		_, err := self.GetBuckets()
    84  		if err != nil {
    85  			return nil, err
    86  		}
    87  		if len(self.ossEndpoint) == 0 {
    88  			return nil, fmt.Errorf("no available buckets")
    89  		}
    90  	}
    91  	return self.client.getOssClient(self.ossEndpoint)
    92  }
    93  
    94  func (self *SRegion) productRequest(client *sdk.Client, product, domain, apiVersion, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
    95  	params["Product"] = product
    96  	return jsonRequest(client, domain, apiVersion, apiName, params, debug)
    97  }
    98  
    99  func (self *SRegion) ossRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
   100  	params["RegionId"] = self.RegionId
   101  	return self.client.ossRequest(apiName, params)
   102  }
   103  
   104  func (self *SRegion) ecsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
   105  	client, err := self.getSdkClient()
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	domain := self.client.getDomain(APSARA_PRODUCT_ECS)
   110  	params["Product"] = APSARA_PRODUCT_ECS
   111  	return jsonRequest(client, domain, APSARA_API_VERSION, apiName, params, self.client.debug)
   112  }
   113  
   114  func (self *SRegion) rdsRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
   115  	client, err := self.getSdkClient()
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	domain := self.client.getDomain(APSARA_PRODUCT_RDS)
   120  	return self.productRequest(client, APSARA_PRODUCT_RDS, domain, APSARA_API_VERION_RDS, apiName, params, self.client.debug)
   121  }
   122  
   123  func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
   124  	client, err := self.getSdkClient()
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	domain := self.client.getDomain(APSARA_PRODUCT_VPC)
   129  	return self.productRequest(client, APSARA_PRODUCT_VPC, domain, APSARA_API_VERSION_VPC, action, params, self.client.debug)
   130  }
   131  
   132  func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
   133  	client, err := self.getSdkClient()
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	domain := self.client.getDomain(APSARA_PRODUCT_KVSTORE)
   138  	return self.productRequest(client, APSARA_PRODUCT_KVSTORE, domain, APSARA_API_VERSION_KVS, action, params, self.client.debug)
   139  }
   140  
   141  func (self *SRegion) tagRequest(serviceType string, action string, params map[string]string) (jsonutils.JSONObject, error) {
   142  	switch serviceType {
   143  	case APSARA_PRODUCT_ECS:
   144  		return self.ecsRequest(action, params)
   145  	case APSARA_PRODUCT_RDS:
   146  		return self.rdsRequest(action, params)
   147  	case APSARA_PRODUCT_SLB:
   148  		return self.lbRequest(action, params)
   149  	case APSARA_PRODUCT_KVSTORE:
   150  		return self.kvsRequest(action, params)
   151  	default:
   152  		return nil, errors.Wrapf(errors.ErrNotSupported, "not support %s service tag", serviceType)
   153  	}
   154  }
   155  
   156  func (self *SRegion) lbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
   157  	client, err := self.getSdkClient()
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	domain := self.client.getDomain(APSARA_PRODUCT_SLB)
   162  	return self.productRequest(client, APSARA_PRODUCT_SLB, domain, APSARA_API_VERSION_LB, apiName, params, self.client.debug)
   163  }
   164  
   165  /////////////////////////////////////////////////////////////////////////////
   166  func (self *SRegion) GetId() string {
   167  	return self.RegionId
   168  }
   169  
   170  func (self *SRegion) GetName() string {
   171  	switch self.client.cpcfg.Vendor {
   172  	case api.CLOUD_PROVIDER_APSARA:
   173  		return fmt.Sprintf("%s %s", CLOUD_PROVIDER_APSARA_CN, self.LocalName)
   174  	default:
   175  		return fmt.Sprintf("%s %s", CLOUD_PROVIDER_APSARA_CN, self.LocalName)
   176  	}
   177  }
   178  
   179  func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
   180  	en := fmt.Sprintf("%s %s", CLOUD_PROVIDER_APSARA_EN, self.LocalName)
   181  	table := cloudprovider.SModelI18nTable{}
   182  	table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en)
   183  	return table
   184  }
   185  
   186  func (self *SRegion) GetGlobalId() string {
   187  	return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_APSARA, self.RegionId)
   188  }
   189  
   190  func (self *SRegion) IsEmulated() bool {
   191  	return false
   192  }
   193  
   194  func (self *SRegion) GetProvider() string {
   195  	return self.client.cpcfg.Vendor
   196  }
   197  
   198  func (self *SRegion) GetCloudEnv() string {
   199  	return ""
   200  }
   201  
   202  func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
   203  	return cloudprovider.SGeographicInfo{}
   204  }
   205  
   206  func (self *SRegion) GetStatus() string {
   207  	return api.CLOUD_REGION_STATUS_INSERVER
   208  }
   209  
   210  func (self *SRegion) Refresh() error {
   211  	// do nothing
   212  	return nil
   213  }
   214  
   215  func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
   216  	if self.izones == nil {
   217  		var err error
   218  		err = self.fetchInfrastructure()
   219  		if err != nil {
   220  			return nil, err
   221  		}
   222  	}
   223  	return self.izones, nil
   224  }
   225  
   226  func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
   227  	izones, err := self.GetIZones()
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  	for i := 0; i < len(izones); i += 1 {
   232  		if izones[i].GetGlobalId() == id {
   233  			return izones[i], nil
   234  		}
   235  	}
   236  	return nil, cloudprovider.ErrNotFound
   237  }
   238  
   239  func (self *SRegion) getStoragecache() *SStoragecache {
   240  	if self.storageCache == nil {
   241  		self.storageCache = &SStoragecache{region: self}
   242  	}
   243  	return self.storageCache
   244  }
   245  
   246  func (self *SRegion) _fetchZones(chargeType TChargeType, spotStrategy SpotStrategyType) error {
   247  	params := make(map[string]string)
   248  	params["RegionId"] = self.RegionId
   249  	if len(chargeType) > 0 {
   250  		params["InstanceChargeType"] = string(chargeType)
   251  	}
   252  	if len(spotStrategy) > 0 {
   253  		params["SpotStrategy"] = string(spotStrategy)
   254  	}
   255  	body, err := self.ecsRequest("DescribeZones", params)
   256  	if err != nil {
   257  		return err
   258  	}
   259  
   260  	zones := make([]SZone, 0)
   261  	err = body.Unmarshal(&zones, "Zones", "Zone")
   262  	if err != nil {
   263  		return err
   264  	}
   265  
   266  	self.izones = make([]cloudprovider.ICloudZone, len(zones))
   267  
   268  	for i := 0; i < len(zones); i += 1 {
   269  		zones[i].region = self
   270  		self.izones[i] = &zones[i]
   271  	}
   272  
   273  	return nil
   274  }
   275  
   276  func (self *SRegion) getZoneById(id string) (*SZone, error) {
   277  	izones, err := self.GetIZones()
   278  	if err != nil {
   279  		return nil, err
   280  	}
   281  	for i := 0; i < len(izones); i += 1 {
   282  		zone := izones[i].(*SZone)
   283  		if zone.ZoneId == id {
   284  			return zone, nil
   285  		}
   286  	}
   287  	return nil, fmt.Errorf("no such zone %s", id)
   288  }
   289  
   290  func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
   291  	return self.GetInstance(id)
   292  }
   293  
   294  func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
   295  	return self.getDisk(id)
   296  }
   297  
   298  func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
   299  	if self.ivpcs == nil {
   300  		err := self.fetchInfrastructure()
   301  		if err != nil {
   302  			return nil, err
   303  		}
   304  	}
   305  	return self.ivpcs, nil
   306  }
   307  
   308  func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
   309  	ivpcs, err := self.GetIVpcs()
   310  	if err != nil {
   311  		return nil, err
   312  	}
   313  	for i := 0; i < len(ivpcs); i += 1 {
   314  		if ivpcs[i].GetGlobalId() == id {
   315  			return ivpcs[i], nil
   316  		}
   317  	}
   318  	return nil, cloudprovider.ErrNotFound
   319  }
   320  
   321  func (self *SRegion) fetchIVpcs() error {
   322  	vpcs := make([]SVpc, 0)
   323  	for {
   324  		part, total, err := self.GetVpcs(nil, len(vpcs), 50)
   325  		if err != nil {
   326  			return err
   327  		}
   328  		vpcs = append(vpcs, part...)
   329  		if len(vpcs) >= total {
   330  			break
   331  		}
   332  	}
   333  	self.ivpcs = make([]cloudprovider.ICloudVpc, len(vpcs))
   334  	for i := 0; i < len(vpcs); i += 1 {
   335  		vpcs[i].region = self
   336  		self.ivpcs[i] = &vpcs[i]
   337  	}
   338  	return nil
   339  }
   340  
   341  func (self *SRegion) fetchInfrastructure() error {
   342  	err := self._fetchZones(PostPaidInstanceChargeType, NoSpotStrategy)
   343  	if err != nil {
   344  		return err
   345  	}
   346  	err = self.fetchIVpcs()
   347  	if err != nil {
   348  		return err
   349  	}
   350  	for i := 0; i < len(self.ivpcs); i += 1 {
   351  		for j := 0; j < len(self.izones); j += 1 {
   352  			zone := self.izones[j].(*SZone)
   353  			vpc := self.ivpcs[i].(*SVpc)
   354  			wire := SWire{zone: zone, vpc: vpc}
   355  			zone.addWire(&wire)
   356  			vpc.addWire(&wire)
   357  		}
   358  	}
   359  	return nil
   360  }
   361  
   362  func (self *SRegion) GetVpcs(vpcId []string, offset int, limit int) ([]SVpc, int, error) {
   363  	if limit > 50 || limit <= 0 {
   364  		limit = 50
   365  	}
   366  	params := make(map[string]string)
   367  	params["RegionId"] = self.RegionId
   368  	params["PageSize"] = fmt.Sprintf("%d", limit)
   369  	params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
   370  
   371  	if vpcId != nil && len(vpcId) > 0 {
   372  		params["VpcId"] = strings.Join(vpcId, ",")
   373  	}
   374  
   375  	body, err := self.ecsRequest("DescribeVpcs", params)
   376  	if err != nil {
   377  		log.Errorf("GetVpcs fail %s", err)
   378  		return nil, 0, err
   379  	}
   380  
   381  	vpcs := make([]SVpc, 0)
   382  	err = body.Unmarshal(&vpcs, "Vpcs", "Vpc")
   383  	if err != nil {
   384  		log.Errorf("Unmarshal vpc fail %s", err)
   385  		return nil, 0, err
   386  	}
   387  	total, _ := body.Int("TotalCount")
   388  	return vpcs, int(total), nil
   389  }
   390  
   391  func (self *SRegion) getVpc(vpcId string) (*SVpc, error) {
   392  	vpcs, total, err := self.GetVpcs([]string{vpcId}, 0, 1)
   393  	if err != nil {
   394  		return nil, err
   395  	}
   396  	if total != 1 {
   397  		return nil, cloudprovider.ErrNotFound
   398  	}
   399  	vpcs[0].region = self
   400  	return &vpcs[0], nil
   401  }
   402  
   403  func (self *SRegion) GetVRouters(offset int, limit int) ([]SVRouter, int, error) {
   404  	if limit > 50 || limit <= 0 {
   405  		limit = 50
   406  	}
   407  	params := make(map[string]string)
   408  	params["RegionId"] = self.RegionId
   409  	params["PageSize"] = fmt.Sprintf("%d", limit)
   410  	params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
   411  
   412  	body, err := self.ecsRequest("DescribeVRouters", params)
   413  	if err != nil {
   414  		log.Errorf("GetVRouters fail %s", err)
   415  		return nil, 0, err
   416  	}
   417  
   418  	vrouters := make([]SVRouter, 0)
   419  	err = body.Unmarshal(&vrouters, "VRouters", "VRouter")
   420  	if err != nil {
   421  		log.Errorf("Unmarshal vrouter fail %s", err)
   422  		return nil, 0, err
   423  	}
   424  	total, _ := body.Int("TotalCount")
   425  	return vrouters, int(total), nil
   426  }
   427  
   428  func (self *SRegion) GetRouteTables(ids []string, offset int, limit int) ([]SRouteTable, int, error) {
   429  	if limit > 50 || limit <= 0 {
   430  		limit = 50
   431  	}
   432  	params := make(map[string]string)
   433  	params["RegionId"] = self.RegionId
   434  	params["PageSize"] = fmt.Sprintf("%d", limit)
   435  	params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
   436  	if ids != nil && len(ids) > 0 {
   437  		params["RouteTableId"] = strings.Join(ids, ",")
   438  	}
   439  
   440  	body, err := self.ecsRequest("DescribeRouteTables", params)
   441  	if err != nil {
   442  		log.Errorf("GetRouteTables fail %s", err)
   443  		return nil, 0, err
   444  	}
   445  
   446  	routetables := make([]SRouteTable, 0)
   447  	err = body.Unmarshal(&routetables, "RouteTables", "RouteTable")
   448  	if err != nil {
   449  		log.Errorf("Unmarshal routetables fail %s", err)
   450  		return nil, 0, err
   451  	}
   452  	total, _ := body.Int("TotalCount")
   453  	return routetables, int(total), nil
   454  }
   455  
   456  func (self *SRegion) GetMatchInstanceTypes(cpu int, memMB int, gpu int, zoneId string) ([]SInstanceType, error) {
   457  	if self.instanceTypes == nil {
   458  		types, err := self.GetInstanceTypes()
   459  		if err != nil {
   460  			log.Errorf("GetInstanceTypes %s", err)
   461  			return nil, err
   462  		}
   463  		self.instanceTypes = types
   464  	}
   465  	var available []string
   466  	if len(zoneId) > 0 {
   467  		zone, err := self.getZoneById(zoneId)
   468  		if err != nil {
   469  			return nil, err
   470  		}
   471  		available = zone.AvailableInstanceTypes.InstanceTypes
   472  	}
   473  	ret := make([]SInstanceType, 0)
   474  	for _, t := range self.instanceTypes {
   475  		if t.CpuCoreCount == cpu && memMB == t.memoryMB() && gpu == t.GPUAmount {
   476  			if available == nil || utils.IsInStringArray(t.InstanceTypeId, available) {
   477  				ret = append(ret, t)
   478  			}
   479  		}
   480  	}
   481  	return ret, nil
   482  }
   483  
   484  func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, memGB int, storageType string, dataDiskSizesGB []int, vswitchId string, passwd string, publicKey string) (*SInstance, error) {
   485  	izones, err := self.GetIZones()
   486  	if err != nil {
   487  		return nil, err
   488  	}
   489  	for i := 0; i < len(izones); i += 1 {
   490  		z := izones[i].(*SZone)
   491  		log.Debugf("Search in zone %s", z.LocalName)
   492  		net := z.getNetworkById(vswitchId)
   493  		if net != nil {
   494  			desc := &cloudprovider.SManagedVMCreateConfig{
   495  				Name:              name,
   496  				ExternalImageId:   imgId,
   497  				SysDisk:           cloudprovider.SDiskInfo{SizeGB: 0, StorageType: storageType},
   498  				Cpu:               cpu,
   499  				MemoryMB:          memGB * 1024,
   500  				ExternalNetworkId: vswitchId,
   501  				Password:          passwd,
   502  				DataDisks:         []cloudprovider.SDiskInfo{},
   503  				PublicKey:         publicKey,
   504  			}
   505  			for _, sizeGB := range dataDiskSizesGB {
   506  				desc.DataDisks = append(desc.DataDisks, cloudprovider.SDiskInfo{SizeGB: sizeGB, StorageType: storageType})
   507  			}
   508  			inst, err := z.getHost().CreateVM(desc)
   509  			if err != nil {
   510  				return nil, err
   511  			}
   512  			return inst.(*SInstance), nil
   513  		}
   514  	}
   515  	return nil, fmt.Errorf("cannot find vswitch %s", vswitchId)
   516  }
   517  
   518  func (self *SRegion) instanceOperation(instanceId string, opname string, extra map[string]string) error {
   519  	params := make(map[string]string)
   520  	params["RegionId"] = self.RegionId
   521  	params["InstanceId"] = instanceId
   522  	if extra != nil && len(extra) > 0 {
   523  		for k, v := range extra {
   524  			params[k] = v
   525  		}
   526  	}
   527  	_, err := self.ecsRequest(opname, params)
   528  	return err
   529  }
   530  
   531  func (self *SRegion) GetInstanceStatus(instanceId string) (string, error) {
   532  	instance, err := self.GetInstance(instanceId)
   533  	if err != nil {
   534  		return "", err
   535  	}
   536  	return instance.Status, nil
   537  }
   538  
   539  func (self *SRegion) GetInstanceVNCUrl(instanceId string) (string, error) {
   540  	params := make(map[string]string)
   541  	params["RegionId"] = self.RegionId
   542  	params["InstanceId"] = instanceId
   543  	body, err := self.ecsRequest("DescribeInstanceVncUrl", params)
   544  	if err != nil {
   545  		return "", err
   546  	}
   547  	return body.GetString("VncUrl")
   548  }
   549  
   550  func (self *SRegion) ModifyInstanceVNCUrlPassword(instanceId string, passwd string) error {
   551  	params := make(map[string]string)
   552  	params["RegionId"] = self.RegionId
   553  	params["InstanceId"] = instanceId
   554  	params["VncPassword"] = passwd // must be 6 digital + alphabet
   555  	_, err := self.ecsRequest("ModifyInstanceVncPasswd", params)
   556  	return err
   557  }
   558  
   559  func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
   560  	params := make(map[string]string)
   561  	if len(opts.CIDR) > 0 {
   562  		params["CidrBlock"] = opts.CIDR
   563  	}
   564  	if len(opts.NAME) > 0 {
   565  		params["VpcName"] = opts.NAME
   566  	}
   567  	if len(opts.Desc) > 0 {
   568  		params["Description"] = opts.Desc
   569  	}
   570  	params["ClientToken"] = utils.GenRequestId(20)
   571  	body, err := self.ecsRequest("CreateVpc", params)
   572  	if err != nil {
   573  		return nil, err
   574  	}
   575  	vpcId, err := body.GetString("VpcId")
   576  	if err != nil {
   577  		return nil, err
   578  	}
   579  	err = self.fetchInfrastructure()
   580  	if err != nil {
   581  		return nil, err
   582  	}
   583  	return self.GetIVpcById(vpcId)
   584  }
   585  
   586  func (self *SRegion) DeleteVpc(vpcId string) error {
   587  	params := make(map[string]string)
   588  	params["VpcId"] = vpcId
   589  
   590  	_, err := self.ecsRequest("DeleteVpc", params)
   591  	return err
   592  }
   593  
   594  func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
   595  	izones, err := self.GetIZones()
   596  	if err != nil {
   597  		return nil, err
   598  	}
   599  	for i := 0; i < len(izones); i += 1 {
   600  		ihost, err := izones[i].GetIHostById(id)
   601  		if err == nil {
   602  			return ihost, nil
   603  		} else if err != cloudprovider.ErrNotFound {
   604  			return nil, err
   605  		}
   606  	}
   607  	return nil, cloudprovider.ErrNotFound
   608  }
   609  
   610  func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
   611  	izones, err := self.GetIZones()
   612  	if err != nil {
   613  		return nil, err
   614  	}
   615  	for i := 0; i < len(izones); i += 1 {
   616  		istore, err := izones[i].GetIStorageById(id)
   617  		if err == nil {
   618  			return istore, nil
   619  		} else if err != cloudprovider.ErrNotFound {
   620  			return nil, err
   621  		}
   622  	}
   623  	return nil, cloudprovider.ErrNotFound
   624  }
   625  
   626  func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
   627  	iHosts := make([]cloudprovider.ICloudHost, 0)
   628  
   629  	izones, err := self.GetIZones()
   630  	if err != nil {
   631  		return nil, err
   632  	}
   633  	for i := 0; i < len(izones); i += 1 {
   634  		iZoneHost, err := izones[i].GetIHosts()
   635  		if err != nil {
   636  			return nil, err
   637  		}
   638  		iHosts = append(iHosts, iZoneHost...)
   639  	}
   640  	return iHosts, nil
   641  }
   642  
   643  func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
   644  	iStores := make([]cloudprovider.ICloudStorage, 0)
   645  
   646  	izones, err := self.GetIZones()
   647  	if err != nil {
   648  		return nil, err
   649  	}
   650  	for i := 0; i < len(izones); i += 1 {
   651  		iZoneStores, err := izones[i].GetIStorages()
   652  		if err != nil {
   653  			return nil, err
   654  		}
   655  		iStores = append(iStores, iZoneStores...)
   656  	}
   657  	return iStores, nil
   658  }
   659  
   660  func (self *SRegion) updateInstance(instId string, name, desc, passwd, hostname, userData string) error {
   661  	params := make(map[string]string)
   662  	params["InstanceId"] = instId
   663  	if len(name) > 0 {
   664  		params["InstanceName"] = name
   665  	}
   666  	if len(desc) > 0 {
   667  		params["Description"] = desc
   668  	}
   669  	if len(passwd) > 0 {
   670  		params["Password"] = passwd
   671  	}
   672  	if len(hostname) > 0 {
   673  		params["HostName"] = hostname
   674  	}
   675  	if len(userData) > 0 {
   676  		params["UserData"] = userData
   677  	}
   678  	_, err := self.ecsRequest("ModifyInstanceAttribute", params)
   679  	return err
   680  }
   681  
   682  func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error {
   683  	return self.updateInstance(instId, "", "", passwd, "", "")
   684  }
   685  
   686  // func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
   687  // 	eips, total, err := self.GetSnapshots("", 0, 50)
   688  // 	if err != nil {
   689  // 		return nil, err
   690  // 	}
   691  // 	for len(eips) < total {
   692  // 		var parts []SEipAddress
   693  // 		parts, total, err = self.GetEips("", len(eips), 50)
   694  // 		if err != nil {
   695  // 			return nil, err
   696  // 		}
   697  // 		eips = append(eips, parts...)
   698  // 	}
   699  // 	ret := make([]cloudprovider.ICloudEIP, len(eips))
   700  // 	for i := 0; i < len(eips); i += 1 {
   701  // 		ret[i] = &eips[i]
   702  // 	}
   703  // 	return ret, nil
   704  // }
   705  
   706  func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
   707  	eips, total, err := self.GetEips("", "", 0, 50)
   708  	if err != nil {
   709  		return nil, err
   710  	}
   711  	for len(eips) < total {
   712  		var parts []SEipAddress
   713  		parts, total, err = self.GetEips("", "", len(eips), 50)
   714  		if err != nil {
   715  			return nil, err
   716  		}
   717  		eips = append(eips, parts...)
   718  	}
   719  	ret := make([]cloudprovider.ICloudEIP, len(eips))
   720  	for i := 0; i < len(eips); i += 1 {
   721  		ret[i] = &eips[i]
   722  	}
   723  	return ret, nil
   724  }
   725  
   726  func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
   727  	eips, total, err := self.GetEips(eipId, "", 0, 1)
   728  	if err != nil {
   729  		return nil, err
   730  	}
   731  	if total == 0 {
   732  		return nil, cloudprovider.ErrNotFound
   733  	}
   734  	if total > 1 {
   735  		return nil, cloudprovider.ErrDuplicateId
   736  	}
   737  	return &eips[0], nil
   738  }
   739  
   740  func (region *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
   741  	secgroup, err := region.GetSecurityGroupDetails(secgroupId)
   742  	if err != nil {
   743  		return nil, err
   744  	}
   745  	vpc, err := region.getVpc(secgroup.VpcId)
   746  	if err != nil {
   747  		return nil, errors.Wrapf(err, "region.getVpc(%s)", secgroup.VpcId)
   748  	}
   749  	secgroup.vpc = vpc
   750  	return secgroup, nil
   751  }
   752  
   753  func (region *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) {
   754  	secgroups, total, err := region.GetSecurityGroups(opts.VpcId, opts.Name, []string{}, 0, 0)
   755  	if err != nil {
   756  		return nil, err
   757  	}
   758  	if total == 0 {
   759  		return nil, cloudprovider.ErrNotFound
   760  	}
   761  	if total > 1 {
   762  		return nil, cloudprovider.ErrDuplicateId
   763  	}
   764  	return &secgroups[0], nil
   765  }
   766  
   767  func (region *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
   768  	externalId, err := region.CreateSecurityGroup(conf.VpcId, conf.Name, conf.Desc)
   769  	if err != nil {
   770  		return nil, err
   771  	}
   772  	return region.GetISecurityGroupById(externalId)
   773  }
   774  
   775  func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
   776  	lbs, err := region.GetLoadbalancers(nil)
   777  	if err != nil {
   778  		return nil, err
   779  	}
   780  	ilbs := []cloudprovider.ICloudLoadbalancer{}
   781  	for i := 0; i < len(lbs); i++ {
   782  		lbs[i].region = region
   783  		ilbs = append(ilbs, &lbs[i])
   784  	}
   785  	return ilbs, nil
   786  }
   787  
   788  func (region *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) {
   789  	return region.GetLoadbalancerDetail(loadbalancerId)
   790  }
   791  
   792  func (region *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
   793  	certs, err := region.GetLoadbalancerServerCertificates()
   794  	if err != nil {
   795  		return nil, err
   796  	}
   797  	for i := 0; i < len(certs); i++ {
   798  		if certs[i].GetGlobalId() == certId {
   799  			certs[i].region = region
   800  			return &certs[i], nil
   801  		}
   802  	}
   803  	return nil, cloudprovider.ErrNotFound
   804  }
   805  
   806  func (region *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
   807  	params := map[string]string{}
   808  	params["RegionId"] = region.RegionId
   809  	params["ServerCertificateName"] = cert.Name
   810  	params["PrivateKey"] = cert.PrivateKey
   811  	params["ServerCertificate"] = cert.Certificate
   812  	body, err := region.lbRequest("UploadServerCertificate", params)
   813  	if err != nil {
   814  		return nil, err
   815  	}
   816  	certID, err := body.GetString("ServerCertificateId")
   817  	if err != nil {
   818  		return nil, err
   819  	}
   820  	return region.GetILoadBalancerCertificateById(certID)
   821  }
   822  
   823  func (region *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) {
   824  	return nil, cloudprovider.ErrNotFound
   825  }
   826  
   827  func (region *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) {
   828  	return nil, cloudprovider.ErrNotSupported
   829  }
   830  
   831  func (region *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
   832  	certificates, err := region.GetLoadbalancerServerCertificates()
   833  	if err != nil {
   834  		return nil, err
   835  	}
   836  	iCertificates := []cloudprovider.ICloudLoadbalancerCertificate{}
   837  	for i := 0; i < len(certificates); i++ {
   838  		certificates[i].region = region
   839  		iCertificates = append(iCertificates, &certificates[i])
   840  	}
   841  	return iCertificates, nil
   842  }
   843  
   844  func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) {
   845  	params := map[string]string{}
   846  	params["RegionId"] = region.RegionId
   847  	params["LoadBalancerName"] = loadbalancer.Name
   848  	if len(loadbalancer.ZoneID) > 0 {
   849  		params["MasterZoneId"] = loadbalancer.ZoneID
   850  	}
   851  
   852  	if len(loadbalancer.VpcID) > 0 {
   853  		params["VpcId"] = loadbalancer.VpcID
   854  	}
   855  
   856  	if len(loadbalancer.NetworkIDs) > 0 {
   857  		params["VSwitchId"] = loadbalancer.NetworkIDs[0]
   858  	}
   859  
   860  	if len(loadbalancer.Address) > 0 {
   861  		params["Address"] = loadbalancer.Address
   862  	}
   863  
   864  	if len(loadbalancer.AddressType) > 0 {
   865  		params["AddressType"] = loadbalancer.AddressType
   866  	}
   867  
   868  	if len(loadbalancer.LoadbalancerSpec) > 0 {
   869  		params["LoadBalancerSpec"] = loadbalancer.LoadbalancerSpec
   870  	}
   871  
   872  	if len(loadbalancer.ChargeType) > 0 {
   873  		params["InternetChargeType"] = "payby" + loadbalancer.ChargeType
   874  	}
   875  
   876  	if len(loadbalancer.ProjectId) > 0 {
   877  		params["ResourceGroupId"] = loadbalancer.ProjectId
   878  	}
   879  
   880  	if loadbalancer.ChargeType == api.LB_CHARGE_TYPE_BY_BANDWIDTH && loadbalancer.EgressMbps > 0 {
   881  		params["Bandwidth"] = fmt.Sprintf("%d", loadbalancer.EgressMbps)
   882  	}
   883  
   884  	body, err := region.lbRequest("CreateLoadBalancer", params)
   885  	if err != nil {
   886  		return nil, err
   887  	}
   888  	loadBalancerID, err := body.GetString("LoadBalancerId")
   889  	if err != nil {
   890  		return nil, err
   891  	}
   892  	region.SetResourceTags("slb", "instance", []string{loadBalancerID}, loadbalancer.Tags, false)
   893  	iLoadbalancer, err := region.GetLoadbalancerDetail(loadBalancerID)
   894  	if err != nil {
   895  		return nil, err
   896  	}
   897  	return iLoadbalancer, cloudprovider.WaitStatus(iLoadbalancer, api.LB_STATUS_ENABLED, time.Second*5, time.Minute*5)
   898  }
   899  
   900  func (region *SRegion) AddAccessControlListEntry(aclId string, entrys []cloudprovider.SLoadbalancerAccessControlListEntry) error {
   901  	params := map[string]string{}
   902  	params["RegionId"] = region.RegionId
   903  	params["AclId"] = aclId
   904  	aclArray := jsonutils.NewArray()
   905  	for i := 0; i < len(entrys); i++ {
   906  		//阿里云AclEntrys参数必须是CIDR格式的。
   907  		if regutils.MatchIPAddr(entrys[i].CIDR) {
   908  			entrys[i].CIDR += "/32"
   909  		}
   910  		aclArray.Add(jsonutils.Marshal(map[string]string{"entry": entrys[i].CIDR, "comment": entrys[i].Comment}))
   911  	}
   912  	if aclArray.Length() == 0 {
   913  		return nil
   914  	}
   915  	params["AclEntrys"] = aclArray.String()
   916  	_, err := region.lbRequest("AddAccessControlListEntry", params)
   917  	return err
   918  }
   919  
   920  func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
   921  	params := map[string]string{}
   922  	params["RegionId"] = region.RegionId
   923  	params["AclName"] = acl.Name
   924  	body, err := region.lbRequest("CreateAccessControlList", params)
   925  	if err != nil {
   926  		return nil, err
   927  	}
   928  	aclId, err := body.GetString("AclId")
   929  	if err != nil {
   930  		return nil, err
   931  	}
   932  	iAcl, err := region.GetLoadbalancerAclDetail(aclId)
   933  	if err != nil {
   934  		return nil, err
   935  	}
   936  	return iAcl, region.AddAccessControlListEntry(aclId, acl.Entrys)
   937  }
   938  
   939  func (self *SRegion) GetBuckets() ([]SBucket, error) {
   940  	resp, err := self.ossRequest("GetService", map[string]string{})
   941  	if err != nil {
   942  		return nil, err
   943  	}
   944  	if !resp.Contains("Data") {
   945  		if self.client.cpcfg.UpdatePermission != nil {
   946  			self.client.cpcfg.UpdatePermission("oss", "ListBuckets")
   947  		}
   948  		return []SBucket{}, nil
   949  	}
   950  	ret := []SBucket{}
   951  	err = resp.Unmarshal(&ret, "Data", "ListAllMyBucketsResult", "Buckets", "Bucket")
   952  	if err != nil {
   953  		return nil, errors.Wrapf(err, "resp.Unmarshal")
   954  	}
   955  	if len(ret) > 0 {
   956  		self.ossEndpoint = ret[0].IntranetEndpoint
   957  	}
   958  	return ret, nil
   959  }
   960  
   961  func (self *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
   962  	buckets, err := self.GetBuckets()
   963  	if err != nil {
   964  		return nil, err
   965  	}
   966  	ret := []cloudprovider.ICloudBucket{}
   967  	for i := range buckets {
   968  		buckets[i].region = self
   969  		ret = append(ret, &buckets[i])
   970  	}
   971  	return ret, nil
   972  }
   973  
   974  func str2StorageClass(storageClassStr string) (oss.StorageClassType, error) {
   975  	storageClass := oss.StorageStandard
   976  	if strings.EqualFold(storageClassStr, string(oss.StorageStandard)) {
   977  		//
   978  	} else if strings.EqualFold(storageClassStr, string(oss.StorageIA)) {
   979  		storageClass = oss.StorageIA
   980  	} else if strings.EqualFold(storageClassStr, string(oss.StorageArchive)) {
   981  		storageClass = oss.StorageArchive
   982  	} else {
   983  		return storageClass, errors.Error("not supported storageClass")
   984  	}
   985  	return storageClass, nil
   986  }
   987  
   988  func str2Acl(aclStr string) (oss.ACLType, error) {
   989  	acl := oss.ACLPrivate
   990  	if strings.EqualFold(aclStr, string(oss.ACLPrivate)) {
   991  		// private, default
   992  	} else if strings.EqualFold(aclStr, string(oss.ACLPublicRead)) {
   993  		acl = oss.ACLPublicRead
   994  	} else if strings.EqualFold(aclStr, string(oss.ACLPublicReadWrite)) {
   995  		acl = oss.ACLPublicReadWrite
   996  	} else {
   997  		return acl, errors.Error("not supported acl")
   998  	}
   999  	return acl, nil
  1000  }
  1001  
  1002  func (self *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
  1003  	osscli, err := self.GetOssClient()
  1004  	if err != nil {
  1005  		return errors.Wrap(err, "region.GetOssClient")
  1006  	}
  1007  	opts := make([]oss.Option, 0)
  1008  	if len(storageClassStr) > 0 {
  1009  		storageClass, err := str2StorageClass(storageClassStr)
  1010  		if err != nil {
  1011  			return err
  1012  		}
  1013  		opts = append(opts, oss.StorageClass(storageClass))
  1014  	}
  1015  	if len(aclStr) > 0 {
  1016  		acl, err := str2Acl(aclStr)
  1017  		if err != nil {
  1018  			return err
  1019  		}
  1020  		opts = append(opts, oss.ACL(acl))
  1021  	}
  1022  	return osscli.CreateBucket(name, opts...)
  1023  }
  1024  
  1025  func ossErrorCode(err error) int {
  1026  	if srvErr, ok := err.(oss.ServiceError); ok {
  1027  		return srvErr.StatusCode
  1028  	}
  1029  	if srvErr, ok := err.(*oss.ServiceError); ok {
  1030  		return srvErr.StatusCode
  1031  	}
  1032  	return -1
  1033  }
  1034  
  1035  func (self *SRegion) DeleteIBucket(name string) error {
  1036  	cli, err := self.GetOssClient()
  1037  	if err != nil {
  1038  		return err
  1039  	}
  1040  	return cli.DeleteBucket(name)
  1041  }
  1042  
  1043  func (self *SRegion) GetBucket(name string) (*SBucket, error) {
  1044  	params := map[string]string{
  1045  		"AccountInfo":      "aaa",
  1046  		"x-acs-instanceid": name,
  1047  		"Params":           jsonutils.Marshal(map[string]string{"BucketName": name}).String(),
  1048  	}
  1049  	resp, err := self.ossRequest("GetBucketInfo", params)
  1050  	if err != nil {
  1051  		return nil, errors.Wrapf(err, "GetBucketInfo")
  1052  	}
  1053  	bucket := &SBucket{region: self}
  1054  	return bucket, resp.Unmarshal(bucket, "Data", "BucketInfo", "Bucket")
  1055  }
  1056  
  1057  func (self *SRegion) IBucketExist(name string) (bool, error) {
  1058  	_, err := self.GetBucket(name)
  1059  	if err != nil {
  1060  		return false, err
  1061  	}
  1062  	return true, nil
  1063  }
  1064  
  1065  func (self *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) {
  1066  	buckets, err := self.GetBuckets()
  1067  	if err != nil {
  1068  		return nil, err
  1069  	}
  1070  	for i := range buckets {
  1071  		if buckets[i].GetName() == name {
  1072  			buckets[i].region = self
  1073  			return &buckets[i], nil
  1074  		}
  1075  	}
  1076  	return nil, errors.Wrapf(cloudprovider.ErrNotFound, name)
  1077  }
  1078  
  1079  func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
  1080  	return region.GetIBucketById(name)
  1081  }
  1082  
  1083  func (self *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) {
  1084  	caches, err := self.GetElasticCaches(nil)
  1085  	if err != nil {
  1086  		return nil, err
  1087  	}
  1088  
  1089  	icaches := make([]cloudprovider.ICloudElasticcache, len(caches))
  1090  	for i := range caches {
  1091  		caches[i].region = self
  1092  		icaches[i] = &caches[i]
  1093  	}
  1094  
  1095  	return icaches, nil
  1096  }
  1097  
  1098  func (region *SRegion) GetCapabilities() []string {
  1099  	return region.client.GetCapabilities()
  1100  }