yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/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 azure
    16  
    17  import (
    18  	"fmt"
    19  	"net/url"
    20  	"strconv"
    21  	"strings"
    22  
    23  	"yunion.io/x/jsonutils"
    24  	"yunion.io/x/log"
    25  	"yunion.io/x/pkg/errors"
    26  	"yunion.io/x/pkg/util/netutils"
    27  
    28  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    29  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    30  	"yunion.io/x/cloudmux/pkg/multicloud"
    31  )
    32  
    33  type SVMSize struct {
    34  	//MaxDataDiskCount     int32 `json:"maxDataDiskCount,omitempty"` //Unmarshal会出错
    35  	MemoryInMB           int32 `json:"memoryInMB,omitempty"`
    36  	NumberOfCores        int   `json:"numberOfCores,omitempty"`
    37  	Name                 string
    38  	OsDiskSizeInMB       int32 `json:"osDiskSizeInMB,omitempty"`
    39  	ResourceDiskSizeInMB int32 `json:"resourceDiskSizeInMB,omitempty"`
    40  }
    41  
    42  type SRegion struct {
    43  	multicloud.SRegion
    44  	client *SAzureClient
    45  
    46  	storageCache    *SStoragecache
    47  	appServicePlans map[string]*SAppServicePlan
    48  
    49  	ID          string
    50  	Name        string
    51  	DisplayName string
    52  	Latitude    string
    53  	Longitude   string
    54  }
    55  
    56  func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
    57  	return nil, cloudprovider.ErrNotImplemented
    58  }
    59  
    60  /////////////////////////////////////////////////////////////////////////////
    61  func (self *SRegion) Refresh() error {
    62  	// do nothing
    63  	return nil
    64  }
    65  
    66  func (self *SRegion) GetClient() *SAzureClient {
    67  	return self.client
    68  }
    69  
    70  func (self *SRegion) ListVmSizes() ([]SVMSize, error) {
    71  	result := []SVMSize{}
    72  	resource := fmt.Sprintf("Microsoft.Compute/locations/%s/vmSizes", self.Name)
    73  	return result, self.client.list(resource, url.Values{}, &result)
    74  }
    75  
    76  func (self *SRegion) getHardwareProfile(cpu, memMB int) []string {
    77  	vmSizes, err := self.ListVmSizes()
    78  	if err != nil {
    79  		return []string{}
    80  	}
    81  	result := []string{}
    82  	for i := range vmSizes {
    83  		if vmSizes[i].MemoryInMB == int32(memMB) && vmSizes[i].NumberOfCores == cpu {
    84  			result = append(result, vmSizes[i].Name)
    85  		}
    86  	}
    87  	return result
    88  }
    89  
    90  func (self *SRegion) getVMSize(name string) (*SVMSize, error) {
    91  	vmSizes, err := self.ListVmSizes()
    92  	if err != nil {
    93  		return nil, errors.Wrapf(err, "ListVmSizes")
    94  	}
    95  	for i := range vmSizes {
    96  		if vmSizes[i].Name == name {
    97  			return &vmSizes[i], nil
    98  		}
    99  	}
   100  	return nil, errors.Wrapf(cloudprovider.ErrNotFound, name)
   101  }
   102  
   103  func (self *SRegion) GetId() string {
   104  	return self.Name
   105  }
   106  
   107  func (self *SRegion) GetName() string {
   108  	return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AZURE_CN, self.DisplayName)
   109  }
   110  
   111  func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
   112  	en := fmt.Sprintf("%s %s", CLOUD_PROVIDER_AZURE_EN, self.DisplayName)
   113  	table := cloudprovider.SModelI18nTable{}
   114  	table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en)
   115  	return table
   116  }
   117  
   118  func (self *SRegion) GetGlobalId() string {
   119  	return fmt.Sprintf("%s/%s", self.client.GetAccessEnv(), self.Name)
   120  }
   121  
   122  func (self *SRegion) IsEmulated() bool {
   123  	return false
   124  }
   125  
   126  func (self *SRegion) GetProvider() string {
   127  	return CLOUD_PROVIDER_AZURE
   128  }
   129  
   130  func (self *SRegion) GetCloudEnv() string {
   131  	return self.client.envName
   132  }
   133  
   134  func (self *SRegion) trimGeographicString(geographic string) string {
   135  	return strings.TrimFunc(geographic, func(r rune) bool {
   136  		return !((r >= '0' && r <= '9') || r == '.' || r == '-')
   137  	})
   138  }
   139  
   140  func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
   141  	info := cloudprovider.SGeographicInfo{}
   142  	if geographicInfo, ok := AzureGeographicInfo[self.Name]; ok {
   143  		info = geographicInfo
   144  	}
   145  
   146  	self.Latitude = self.trimGeographicString(self.Latitude)
   147  	self.Longitude = self.trimGeographicString(self.Longitude)
   148  
   149  	latitude, err := strconv.ParseFloat(self.Latitude, 32)
   150  	if err != nil {
   151  		log.Errorf("Parse azure region %s latitude %s error: %v", self.Name, self.Latitude, err)
   152  	} else {
   153  		info.Latitude = float32(latitude)
   154  	}
   155  
   156  	longitude, err := strconv.ParseFloat(self.Longitude, 32)
   157  	if err != nil {
   158  		log.Errorf("Parse azure region %s longitude %s error: %v", self.Name, self.Longitude, err)
   159  	} else {
   160  		info.Longitude = float32(longitude)
   161  	}
   162  	return info
   163  }
   164  
   165  func (self *SRegion) GetStatus() string {
   166  	return api.CLOUD_REGION_STATUS_INSERVER
   167  }
   168  
   169  func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
   170  	vpc := SVpc{
   171  		region:   self,
   172  		Name:     opts.NAME,
   173  		Location: self.Name,
   174  		Properties: VirtualNetworkPropertiesFormat{
   175  			AddressSpace: AddressSpace{
   176  				AddressPrefixes: []string{opts.CIDR},
   177  			},
   178  		},
   179  		Type: "Microsoft.Network/virtualNetworks",
   180  	}
   181  	return &vpc, self.create("", jsonutils.Marshal(vpc), &vpc)
   182  }
   183  
   184  func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
   185  	izones, err := self.GetIZones()
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  	for i := 0; i < len(izones); i += 1 {
   190  		ihost, err := izones[i].GetIHostById(id)
   191  		if err == nil {
   192  			return ihost, nil
   193  		} else if err != cloudprovider.ErrNotFound {
   194  			return nil, err
   195  		}
   196  	}
   197  	return nil, cloudprovider.ErrNotFound
   198  }
   199  
   200  func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
   201  	izones, err := self.GetIZones()
   202  	if err != nil {
   203  		return nil, err
   204  	}
   205  	for i := 0; i < len(izones); i += 1 {
   206  		istore, err := izones[i].GetIStorageById(id)
   207  		if err == nil {
   208  			return istore, nil
   209  		} else if err != cloudprovider.ErrNotFound {
   210  			return nil, err
   211  		}
   212  	}
   213  	return nil, cloudprovider.ErrNotFound
   214  }
   215  
   216  func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
   217  	return self.GetInstance(id)
   218  }
   219  
   220  func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
   221  	return self.GetDisk(id)
   222  }
   223  
   224  func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
   225  	iHosts := make([]cloudprovider.ICloudHost, 0)
   226  
   227  	izones, err := self.GetIZones()
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  	for i := 0; i < len(izones); i += 1 {
   232  		iZoneHost, err := izones[i].GetIHosts()
   233  		if err != nil {
   234  			return nil, err
   235  		}
   236  		iHosts = append(iHosts, iZoneHost...)
   237  	}
   238  	return iHosts, nil
   239  }
   240  
   241  func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
   242  	iStores := make([]cloudprovider.ICloudStorage, 0)
   243  
   244  	izones, err := self.GetIZones()
   245  	if err != nil {
   246  		return nil, err
   247  	}
   248  	for i := 0; i < len(izones); i += 1 {
   249  		iZoneStores, err := izones[i].GetIStorages()
   250  		if err != nil {
   251  			return nil, err
   252  		}
   253  		iStores = append(iStores, iZoneStores...)
   254  	}
   255  	return iStores, nil
   256  }
   257  
   258  func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
   259  	storageCache := self.getStoragecache()
   260  	if storageCache.GetGlobalId() == id {
   261  		return self.storageCache, nil
   262  	}
   263  	return nil, cloudprovider.ErrNotFound
   264  }
   265  
   266  func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
   267  	ivpcs, err := self.GetIVpcs()
   268  	if err != nil {
   269  		return nil, err
   270  	}
   271  	for i := 0; i < len(ivpcs); i++ {
   272  		if ivpcs[i].GetGlobalId() == id {
   273  			return ivpcs[i], nil
   274  		}
   275  	}
   276  	return nil, cloudprovider.ErrNotFound
   277  }
   278  
   279  func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
   280  	if izones, err := self.GetIZones(); err != nil {
   281  		return nil, err
   282  	} else {
   283  		for i := 0; i < len(izones); i += 1 {
   284  			if izones[i].GetGlobalId() == id {
   285  				return izones[i], nil
   286  			}
   287  		}
   288  	}
   289  	return nil, cloudprovider.ErrNotFound
   290  }
   291  
   292  func (self *SRegion) getZone() *SZone {
   293  	return &SZone{region: self, Name: self.Name}
   294  }
   295  
   296  func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
   297  	return []cloudprovider.ICloudZone{self.getZone()}, nil
   298  }
   299  
   300  func (self *SRegion) getStoragecache() *SStoragecache {
   301  	if self.storageCache == nil {
   302  		self.storageCache = &SStoragecache{region: self}
   303  	}
   304  	return self.storageCache
   305  }
   306  
   307  func (self *SRegion) ListVpcs() ([]SVpc, error) {
   308  	result := []SVpc{}
   309  	err := self.list("Microsoft.Network/virtualNetworks", url.Values{}, &result)
   310  	if err != nil {
   311  		return nil, errors.Wrapf(err, "list")
   312  	}
   313  	return result, nil
   314  }
   315  
   316  func (self *SRegion) ListClassicVpcs() ([]SClassicVpc, error) {
   317  	result := []SClassicVpc{}
   318  	err := self.list("Microsoft.ClassicNetwork/virtualNetworks", url.Values{}, &result)
   319  	if err != nil {
   320  		return nil, errors.Wrapf(err, "ListClassicVpcs")
   321  	}
   322  	return result, nil
   323  }
   324  
   325  func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
   326  	vpcs, err := self.ListVpcs()
   327  	if err != nil {
   328  		return nil, errors.Wrapf(err, "ListVpcs")
   329  	}
   330  	classicVpcs, err := self.ListClassicVpcs()
   331  	if err != nil {
   332  		return nil, errors.Wrapf(err, "ListClassicVpcs")
   333  	}
   334  	ret := []cloudprovider.ICloudVpc{}
   335  	for i := range vpcs {
   336  		vpcs[i].region = self
   337  		ret = append(ret, &vpcs[i])
   338  	}
   339  	for i := range classicVpcs {
   340  		classicVpcs[i].region = self
   341  		ret = append(ret, &classicVpcs[i])
   342  	}
   343  	return ret, nil
   344  }
   345  
   346  func (self *SRegion) CreateInstanceSimple(name string, imgId, osType string, cpu int, memMb int, sysDiskSizeGB int, storageType string, dataDiskSizesGB []int, nicId string, passwd string, publicKey string) (*SInstance, error) {
   347  	desc := &cloudprovider.SManagedVMCreateConfig{
   348  		Name:            name,
   349  		ExternalImageId: imgId,
   350  		SysDisk:         cloudprovider.SDiskInfo{SizeGB: sysDiskSizeGB, StorageType: storageType},
   351  		Cpu:             cpu,
   352  		MemoryMB:        memMb,
   353  		Password:        passwd,
   354  		DataDisks:       []cloudprovider.SDiskInfo{},
   355  		PublicKey:       publicKey,
   356  		OsType:          osType,
   357  	}
   358  	if len(passwd) > 0 {
   359  		desc.Password = passwd
   360  	}
   361  	for _, sizeGB := range dataDiskSizesGB {
   362  		desc.DataDisks = append(desc.DataDisks, cloudprovider.SDiskInfo{SizeGB: sizeGB, StorageType: storageType})
   363  	}
   364  	return self._createVM(desc, nicId)
   365  }
   366  
   367  func (region *SRegion) GetEips() ([]SEipAddress, error) {
   368  	eips := []SEipAddress{}
   369  	err := region.client.list("Microsoft.Network/publicIPAddresses", url.Values{}, &eips)
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  	result := []SEipAddress{}
   374  	for i := 0; i < len(eips); i++ {
   375  		if eips[i].Location == region.Name {
   376  			eips[i].region = region
   377  			result = append(result, eips[i])
   378  		}
   379  	}
   380  	return result, nil
   381  }
   382  
   383  func (region *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
   384  	eips, err := region.GetEips()
   385  	if err != nil {
   386  		return nil, errors.Wrapf(err, "GetEips")
   387  	}
   388  	classicEips, err := region.GetClassicEips()
   389  	if err != nil {
   390  		return nil, errors.Wrapf(err, "GetClassicEips")
   391  	}
   392  	ieips := []cloudprovider.ICloudEIP{}
   393  	for i := 0; i < len(eips); i++ {
   394  		if len(eips[i].GetIpAddr()) == 0 {
   395  			continue
   396  		}
   397  		_, err := netutils.NewIPV4Addr(eips[i].GetIpAddr())
   398  		if err != nil {
   399  			continue
   400  		}
   401  		eips[i].region = region
   402  		ieips = append(ieips, &eips[i])
   403  	}
   404  	for i := 0; i < len(classicEips); i++ {
   405  		if len(classicEips[i].GetIpAddr()) == 0 {
   406  			continue
   407  		}
   408  		_, err := netutils.NewIPV4Addr(eips[i].GetIpAddr())
   409  		if err != nil {
   410  			continue
   411  		}
   412  		classicEips[i].region = region
   413  		ieips = append(ieips, &classicEips[i])
   414  	}
   415  	return ieips, nil
   416  }
   417  
   418  func (region *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
   419  	if strings.Contains(strings.ToLower(secgroupId), "microsoft.classicnetwork") {
   420  		return region.GetClassicSecurityGroupDetails(secgroupId)
   421  	}
   422  	return region.GetSecurityGroupDetails(secgroupId)
   423  }
   424  
   425  func (region *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) {
   426  	if strings.Contains(strings.ToLower(opts.VpcId), "microsoft.classicnetwork") {
   427  		return nil, errors.Wrapf(cloudprovider.ErrNotSupported, "not support classic secgroup")
   428  	}
   429  	resource := fmt.Sprintf("subscriptions/%s/resourcegroups/%s/providers/microsoft.network/networksecuritygroups/%s", region.client.subscriptionId, opts.ProjectId, opts.Name)
   430  	secgroup := &SSecurityGroup{region: region}
   431  	err := region.get(resource, url.Values{}, secgroup)
   432  	if err != nil {
   433  		return nil, errors.Wrapf(err, "get(%s)", resource)
   434  	}
   435  	return secgroup, nil
   436  }
   437  
   438  func (region *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
   439  	if conf.VpcId == "classic" {
   440  		return region.CreateClassicSecurityGroup(conf.Name)
   441  	}
   442  	return region.CreateSecurityGroup(conf.Name)
   443  }
   444  
   445  func (region *SRegion) getIAppLBs() ([]cloudprovider.ICloudLoadbalancer, error) {
   446  	lbs := []SLoadbalancer{}
   447  	params := url.Values{}
   448  	params.Set("api-version", "2021-02-01")
   449  	err := region.list("Microsoft.Network/applicationGateways", params, &lbs)
   450  	if err != nil {
   451  		return nil, errors.Wrapf(err, "list")
   452  	}
   453  
   454  	ilbs := make([]cloudprovider.ICloudLoadbalancer, len(lbs))
   455  	for i := range lbs {
   456  		lbs[i].region = region
   457  		ilbs[i] = &lbs[i]
   458  	}
   459  
   460  	return ilbs, nil
   461  }
   462  
   463  func (region *SRegion) getINetworkLBs() ([]cloudprovider.ICloudLoadbalancer, error) {
   464  	lbs := []SLoadbalancer{}
   465  	params := url.Values{}
   466  	params.Set("api-version", "2021-02-01")
   467  	err := region.list("Microsoft.Network/loadBalancers", params, &lbs)
   468  	if err != nil {
   469  		return nil, errors.Wrapf(err, "list")
   470  	}
   471  
   472  	ilbs := make([]cloudprovider.ICloudLoadbalancer, len(lbs))
   473  	for i := range lbs {
   474  		lbs[i].region = region
   475  		ilbs[i] = &lbs[i]
   476  	}
   477  
   478  	return ilbs, nil
   479  }
   480  
   481  func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
   482  	appLbs, err := region.getIAppLBs()
   483  	if err != nil {
   484  		return nil, errors.Wrap(err, "GetIAppLBs")
   485  	}
   486  
   487  	netLbs, err := region.getINetworkLBs()
   488  	if err != nil {
   489  		return nil, errors.Wrap(err, "GetINetworkLBs")
   490  	}
   491  
   492  	lbs := []cloudprovider.ICloudLoadbalancer{}
   493  	lbs = append(lbs, appLbs...)
   494  	lbs = append(lbs, netLbs...)
   495  	return lbs, nil
   496  }
   497  
   498  func (region *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) {
   499  	lb := SLoadbalancer{}
   500  	params := url.Values{}
   501  	params.Set("api-version", "2021-02-01")
   502  	err := region.get(loadbalancerId, params, &lb)
   503  	if err != nil {
   504  		return nil, errors.Wrapf(err, "get")
   505  	}
   506  
   507  	lb.region = region
   508  	return &lb, nil
   509  }
   510  
   511  func (region *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) {
   512  	return nil, errors.Wrap(cloudprovider.ErrNotSupported, "GetILoadBalancerAclById")
   513  }
   514  
   515  func (region *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
   516  	segs := strings.Split(certId, "/sslCertificates")
   517  	if len(segs[0]) > 0 {
   518  		lb, err := region.GetILoadBalancerById(segs[0])
   519  		if err != nil {
   520  			return nil, errors.Wrap(err, "GetILoadBalancerById")
   521  		}
   522  
   523  		return lb.(*SLoadbalancer).GetILoadBalancerCertificateById(certId)
   524  	}
   525  
   526  	return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerCertificateById")
   527  }
   528  
   529  func (region *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
   530  	lbs, err := region.GetILoadBalancers()
   531  	if err != nil {
   532  		return nil, errors.Wrap(err, "GetILoadBalancers")
   533  	}
   534  
   535  	certs := []cloudprovider.ICloudLoadbalancerCertificate{}
   536  	for i := range lbs {
   537  		_certs, err := lbs[i].(*SLoadbalancer).GetILoadBalancerCertificates()
   538  		if err != nil {
   539  			return nil, errors.Wrap(err, "GetILoadBalancerCertificates")
   540  		}
   541  		certs = append(certs, _certs...)
   542  	}
   543  
   544  	return certs, nil
   545  }
   546  
   547  func (region *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
   548  	return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerCertificate")
   549  }
   550  
   551  func (region *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) {
   552  	return nil, errors.Wrap(cloudprovider.ErrNotSupported, "GetILoadBalancerAcls")
   553  }
   554  
   555  func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) {
   556  	return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "GetILoadBalancerCertificates")
   557  }
   558  
   559  func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
   560  	return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerAcl")
   561  }
   562  
   563  func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
   564  	accounts, err := region.ListStorageAccounts()
   565  	if err != nil {
   566  		return nil, errors.Wrapf(err, "ListStorageAccounts")
   567  	}
   568  	ret := make([]cloudprovider.ICloudBucket, 0)
   569  	for i := range accounts {
   570  		ret = append(ret, &accounts[i])
   571  	}
   572  	return ret, nil
   573  }
   574  
   575  func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error {
   576  	_, err := region.createStorageAccount(name, storageClassStr)
   577  	if err != nil {
   578  		return errors.Wrapf(err, "region.createStorageAccount name=%s storageClass=%s acl=%s", name, storageClassStr, acl)
   579  	}
   580  	return nil
   581  }
   582  
   583  func (region *SRegion) DeleteIBucket(name string) error {
   584  	accounts, err := region.listStorageAccounts()
   585  	if err != nil {
   586  		return errors.Wrap(err, "ListStorageAccounts")
   587  	}
   588  	for i := range accounts {
   589  		if accounts[i].Name == name {
   590  			err = region.del(accounts[i].ID)
   591  			if err != nil {
   592  				return errors.Wrapf(err, "region.del")
   593  			}
   594  			return nil
   595  		}
   596  	}
   597  	return nil
   598  }
   599  
   600  func (region *SRegion) IBucketExist(name string) (bool, error) {
   601  	return region.checkStorageAccountNameExist(name)
   602  }
   603  
   604  func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket, error) {
   605  	return cloudprovider.GetIBucketById(region, name)
   606  }
   607  
   608  func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
   609  	return region.GetIBucketById(name)
   610  }
   611  
   612  func (region *SRegion) GetCapabilities() []string {
   613  	return region.client.GetCapabilities()
   614  }
   615  
   616  func (self *SRegion) get(resource string, params url.Values, retVal interface{}) error {
   617  	return self.client.get(resource, params, retVal)
   618  }
   619  
   620  func (self *SRegion) Show(resource string) (jsonutils.JSONObject, error) {
   621  	ret := jsonutils.NewDict()
   622  	err := self.get(resource, url.Values{}, ret)
   623  	if err != nil {
   624  		return nil, err
   625  	}
   626  	return ret, nil
   627  }
   628  
   629  func (self *SRegion) del(resource string) error {
   630  	return self.client.del(resource)
   631  }
   632  
   633  func (self *SRegion) Delete(resource string) error {
   634  	return self.del(resource)
   635  }
   636  
   637  func (self *SRegion) checkResourceGroup(resourceGroup string) (string, error) {
   638  	if len(resourceGroup) == 0 {
   639  		resourceGroup = "Default"
   640  	}
   641  	resourceGroups, err := self.client.ListResourceGroups()
   642  	if err != nil {
   643  		return "", errors.Wrapf(err, "ListResourceGroups")
   644  	}
   645  
   646  	for i := range resourceGroups {
   647  		proj := resourceGroups[i]
   648  		if strings.ToLower(proj.GetName()) == strings.ToLower(resourceGroup) ||
   649  			proj.GetGlobalId() == resourceGroup ||
   650  			(strings.Contains(resourceGroup, "/") && strings.HasSuffix(proj.GetGlobalId(), resourceGroup)) {
   651  			return resourceGroup, nil
   652  		}
   653  	}
   654  	_, err = self.CreateResourceGroup(resourceGroup)
   655  	return resourceGroup, err
   656  }
   657  
   658  type sInfo struct {
   659  	Location string `json:"Location"`
   660  	Name     string `json:"Name"`
   661  	Type     string `json:"Type"`
   662  }
   663  
   664  func (self *SRegion) createInfo(body jsonutils.JSONObject) (sInfo, error) {
   665  	info := sInfo{}
   666  	err := body.Unmarshal(&info)
   667  	if err != nil {
   668  		return info, errors.Wrapf(err, "body.Unmarshal")
   669  	}
   670  	if len(info.Name) == 0 {
   671  		return info, fmt.Errorf("Missing name params")
   672  	}
   673  	if len(info.Type) == 0 {
   674  		return info, fmt.Errorf("Missing type params")
   675  	}
   676  	return info, nil
   677  }
   678  
   679  func (self *SRegion) create(resourceGroup string, _body jsonutils.JSONObject, retVal interface{}) error {
   680  	body := _body.(*jsonutils.JSONDict)
   681  	info, err := self.createInfo(_body)
   682  	if err != nil {
   683  		return errors.Wrapf(err, "createInfo")
   684  	}
   685  	resourceGroup, err = self.checkResourceGroup(resourceGroup)
   686  	if err != nil {
   687  		return errors.Wrapf(err, "checkResourceGroup(%s)", resourceGroup)
   688  	}
   689  	info.Name, err = self.client.getUniqName(resourceGroup, info.Type, info.Name)
   690  	if err != nil {
   691  		return errors.Wrapf(err, "getUniqName")
   692  	}
   693  	info.Location = self.Name
   694  	body.Update(jsonutils.Marshal(info))
   695  	body.Remove("location")
   696  	body.Remove("name")
   697  	body.Remove("type")
   698  	return self.client.create(resourceGroup, info.Type, info.Name, body, retVal)
   699  }
   700  
   701  func (self *SRegion) update(body jsonutils.JSONObject, retVal interface{}) error {
   702  	return self.client.update(body, retVal)
   703  }
   704  
   705  func (self *SRegion) perform(id, action string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
   706  	return self.client.perform(id, action, body)
   707  }
   708  
   709  func (self *SRegion) put(resource string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
   710  	return self.client.put(resource, body)
   711  }
   712  
   713  func (self *SRegion) patch(resource string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
   714  	return self.client.patch(resource, body)
   715  }
   716  
   717  func (self *SRegion) list(resource string, params url.Values, retVal interface{}) error {
   718  	result := []jsonutils.JSONObject{}
   719  	err := self.client.list(resource, params, &result)
   720  	if err != nil {
   721  		return errors.Wrapf(err, "client.list")
   722  	}
   723  	ret := []jsonutils.JSONObject{}
   724  	for i := range result {
   725  		location, _ := result[i].GetString("location")
   726  		if len(location) == 0 || strings.ToLower(self.Name) == strings.ToLower(strings.Replace(location, " ", "", -1)) {
   727  			ret = append(ret, result[i])
   728  		}
   729  	}
   730  	return jsonutils.Update(retVal, ret)
   731  }