yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/google/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 google
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  	"time"
    21  
    22  	"yunion.io/x/jsonutils"
    23  	"yunion.io/x/log"
    24  	"yunion.io/x/pkg/errors"
    25  	"yunion.io/x/pkg/utils"
    26  
    27  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    28  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    29  	"yunion.io/x/cloudmux/pkg/multicloud"
    30  )
    31  
    32  type SRegion struct {
    33  	cloudprovider.SFakeOnPremiseRegion
    34  	multicloud.SRegion
    35  	client *SGoogleClient
    36  
    37  	capabilities []string
    38  	Quotas       []SQuota
    39  
    40  	Description       string
    41  	ID                string
    42  	Kind              string
    43  	Name              string
    44  	Status            string
    45  	SelfLink          string
    46  	CreationTimestamp time.Time
    47  }
    48  
    49  func (region *SRegion) GetClient() *SGoogleClient {
    50  	return region.client
    51  }
    52  
    53  func (region *SRegion) GetName() string {
    54  	if name, ok := RegionNames[region.Name]; ok {
    55  		return fmt.Sprintf("%s %s", CLOUD_PROVIDER_GOOGLE_CN, name)
    56  	}
    57  	return fmt.Sprintf("%s %s", CLOUD_PROVIDER_GOOGLE_CN, region.Name)
    58  }
    59  
    60  func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
    61  	en := fmt.Sprintf("%s %s", CLOUD_PROVIDER_GOOGLE, self.Name)
    62  	table := cloudprovider.SModelI18nTable{}
    63  	table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en)
    64  	return table
    65  }
    66  
    67  func (region *SRegion) GetId() string {
    68  	return region.Name
    69  }
    70  
    71  func (region *SRegion) GetGlobalId() string {
    72  	return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_GOOGLE, region.Name)
    73  }
    74  
    75  func (region *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
    76  	if geoInfo, ok := LatitudeAndLongitude[region.Name]; ok {
    77  		return geoInfo
    78  	}
    79  	return cloudprovider.SGeographicInfo{}
    80  }
    81  
    82  func (self *SRegion) GetCreatedAt() time.Time {
    83  	return self.CreationTimestamp
    84  }
    85  
    86  func (region *SRegion) GetProvider() string {
    87  	return CLOUD_PROVIDER_GOOGLE
    88  }
    89  
    90  func (region *SRegion) GetStatus() string {
    91  	if region.Status == "UP" || utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
    92  		return api.CLOUD_REGION_STATUS_INSERVER
    93  	}
    94  	return api.CLOUD_REGION_STATUS_OUTOFSERVICE
    95  }
    96  
    97  func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error {
    98  	_, err := region.CreateBucket(name, storageClassStr, cloudprovider.TBucketACLType(acl))
    99  	return err
   100  }
   101  
   102  func (region *SRegion) DeleteIBucket(name string) error {
   103  	return region.DeleteBucket(name)
   104  }
   105  
   106  func (region *SRegion) IBucketExist(name string) (bool, error) {
   107  	//{"error":{"code":403,"details":"200420163731-compute@developer.gserviceaccount.com does not have storage.buckets.get access to test."}}
   108  	//{"error":{"code":404,"details":"Not Found"}}
   109  	_, err := region.GetBucket(name)
   110  	if err == nil {
   111  		return true, nil
   112  	}
   113  	if errors.Cause(err) == cloudprovider.ErrNotFound || strings.Contains(err.Error(), "storage.buckets.get access") {
   114  		return false, nil
   115  	}
   116  	return false, err
   117  }
   118  
   119  func (region *SRegion) GetIBucketById(id string) (cloudprovider.ICloudBucket, error) {
   120  	return cloudprovider.GetIBucketById(region, id)
   121  }
   122  
   123  func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
   124  	return region.GetIBucketById(name)
   125  }
   126  
   127  func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
   128  	iBuckets, err := region.client.getIBuckets()
   129  	if err != nil {
   130  		return nil, errors.Wrap(err, "getIBuckets")
   131  	}
   132  	ret := []cloudprovider.ICloudBucket{}
   133  	for i := range iBuckets {
   134  		if iBuckets[i].GetLocation() != region.GetId() {
   135  			continue
   136  		}
   137  		ret = append(ret, iBuckets[i])
   138  	}
   139  	return ret, nil
   140  }
   141  
   142  func (region *SRegion) IsEmulated() bool {
   143  	return false
   144  }
   145  
   146  func (region *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
   147  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   148  		return []cloudprovider.ICloudZone{}, nil
   149  	}
   150  	zones, err := region.GetZones(region.Name, 0, "")
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  	izones := []cloudprovider.ICloudZone{}
   155  	for i := 0; i < len(zones); i++ {
   156  		zones[i].region = region
   157  		izones = append(izones, &zones[i])
   158  	}
   159  	return izones, nil
   160  }
   161  
   162  func (region *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
   163  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   164  		return nil, cloudprovider.ErrNotFound
   165  	}
   166  
   167  	zones, err := region.GetIZones()
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  	for i := range zones {
   172  		if zones[i].GetGlobalId() == id {
   173  			return zones[i], nil
   174  		}
   175  	}
   176  	return nil, cloudprovider.ErrNotFound
   177  }
   178  
   179  func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
   180  	if utils.IsInStringArray(self.Name, MultiRegions) || utils.IsInStringArray(self.Name, DualRegions) {
   181  		return []cloudprovider.ICloudVpc{}, nil
   182  	}
   183  	vpcs, err := self.GetVpcs()
   184  	if err != nil {
   185  		return nil, errors.Wrapf(err, "GetVpcs")
   186  	}
   187  	ret := []cloudprovider.ICloudVpc{}
   188  	for i := range vpcs {
   189  		vpcs[i].region = self
   190  		ret = append(ret, &vpcs[i])
   191  	}
   192  	return ret, nil
   193  }
   194  
   195  func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
   196  	vpc, err := self.GetVpc(id)
   197  	if err != nil {
   198  		return nil, errors.Wrapf(err, "GetVpc")
   199  	}
   200  	return vpc, nil
   201  }
   202  
   203  func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
   204  	if utils.IsInStringArray(self.Name, MultiRegions) || utils.IsInStringArray(self.Name, DualRegions) {
   205  		return nil, cloudprovider.ErrNotSupported
   206  	}
   207  	gvpc, err := self.client.GetGlobalNetwork(opts.GlobalVpcExternalId)
   208  	if err != nil {
   209  		return nil, errors.Wrapf(err, "GetGlobalNetwork")
   210  	}
   211  	return self.CreateVpc(opts.NAME, gvpc.SelfLink, opts.CIDR, opts.Desc)
   212  }
   213  
   214  func (region *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
   215  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   216  		return nil, cloudprovider.ErrNotFound
   217  	}
   218  
   219  	storage, err := region.GetStorage(id)
   220  	if err != nil {
   221  		return nil, err
   222  	}
   223  	zone, err := region.GetZone(storage.Zone)
   224  	if err != nil {
   225  		return nil, errors.Wrapf(err, "region.GetZone(%s)", storage.Zone)
   226  	}
   227  	zone.region = region
   228  	storage.zone = zone
   229  	return storage, nil
   230  }
   231  
   232  func (region *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
   233  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   234  		return nil, cloudprovider.ErrNotFound
   235  	}
   236  
   237  	izones, err := region.GetIZones()
   238  	if err != nil {
   239  		return nil, err
   240  	}
   241  	for i := 0; i < len(izones); i += 1 {
   242  		ihost, err := izones[i].GetIHostById(id)
   243  		if err == nil {
   244  			return ihost, nil
   245  		} else if errors.Cause(err) != cloudprovider.ErrNotFound {
   246  			return nil, err
   247  		}
   248  	}
   249  	return nil, cloudprovider.ErrNotFound
   250  }
   251  
   252  func (region *SRegion) GetProjectId() string {
   253  	return region.client.projectId
   254  }
   255  
   256  func (region *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
   257  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   258  		return []cloudprovider.ICloudEIP{}, nil
   259  	}
   260  
   261  	eips, err := region.GetEips("", 0, "")
   262  	if err != nil {
   263  		return nil, err
   264  	}
   265  	ieips := []cloudprovider.ICloudEIP{}
   266  	for i := range eips {
   267  		eips[i].region = region
   268  		ieips = append(ieips, &eips[i])
   269  	}
   270  	return ieips, nil
   271  }
   272  
   273  func (region *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
   274  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   275  		return nil, cloudprovider.ErrNotFound
   276  	}
   277  
   278  	ivm, err := region.GetInstance(id)
   279  	if err != nil {
   280  		return nil, err
   281  	}
   282  	zone, err := region.GetZone(ivm.Zone)
   283  	if err != nil {
   284  		return nil, errors.Wrapf(err, "GetZone(%s)", ivm.Zone)
   285  	}
   286  	ivm.host = &SHost{zone: zone}
   287  	return ivm, nil
   288  }
   289  
   290  func (region *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
   291  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   292  		return nil, cloudprovider.ErrNotFound
   293  	}
   294  
   295  	disk, err := region.GetDisk(id)
   296  	if err != nil {
   297  		return nil, err
   298  	}
   299  	return disk, nil
   300  }
   301  
   302  func (region *SRegion) GetIEipById(id string) (cloudprovider.ICloudEIP, error) {
   303  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   304  		return nil, cloudprovider.ErrNotFound
   305  	}
   306  
   307  	eip, err := region.GetEip(id)
   308  	if err != nil {
   309  		return nil, err
   310  	}
   311  	return eip, nil
   312  }
   313  
   314  func (region *SRegion) fetchSnapshots() error {
   315  	if len(region.client.snapshots) > 0 {
   316  		return nil
   317  	}
   318  	region.client.snapshots = map[string][]SSnapshot{}
   319  	snapshots, err := region.GetSnapshots("", 0, "")
   320  	if err != nil {
   321  		return err
   322  	}
   323  	regionNames := []string{}
   324  	for _, region := range region.client.iregions {
   325  		regionNames = append(regionNames, region.GetId())
   326  	}
   327  	for _, snapshot := range snapshots {
   328  		for _, location := range snapshot.StorageLocations {
   329  			_regionName := ""
   330  			if utils.IsInStringArray(location, regionNames) {
   331  				_regionName = location
   332  			} else {
   333  				for _, regionName := range regionNames {
   334  					if strings.HasPrefix(regionName, location) {
   335  						_regionName = regionName
   336  						break
   337  					}
   338  				}
   339  			}
   340  			if len(_regionName) > 0 {
   341  				if _, ok := region.client.snapshots[_regionName]; !ok {
   342  					region.client.snapshots[_regionName] = []SSnapshot{}
   343  				}
   344  				region.client.snapshots[_regionName] = append(region.client.snapshots[_regionName], snapshot)
   345  				break
   346  			}
   347  
   348  		}
   349  	}
   350  	return nil
   351  }
   352  
   353  func (region *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
   354  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   355  		return []cloudprovider.ICloudSnapshot{}, nil
   356  	}
   357  
   358  	region.fetchSnapshots()
   359  	isnapshots := []cloudprovider.ICloudSnapshot{}
   360  	if snapshots, ok := region.client.snapshots[region.Name]; ok {
   361  		for i := range snapshots {
   362  			snapshots[i].region = region
   363  			isnapshots = append(isnapshots, &snapshots[i])
   364  		}
   365  	}
   366  	return isnapshots, nil
   367  }
   368  
   369  func (region *SRegion) GetISnapshotById(id string) (cloudprovider.ICloudSnapshot, error) {
   370  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   371  		return nil, cloudprovider.ErrNotFound
   372  	}
   373  
   374  	snapshot, err := region.GetSnapshot(id)
   375  	if err != nil {
   376  		return nil, err
   377  	}
   378  	return snapshot, nil
   379  }
   380  
   381  func (region *SRegion) rdsDelete(id string) error {
   382  	operation := &SOperation{}
   383  	err := region.client.rdsDelete(id, operation)
   384  	if err != nil {
   385  		return errors.Wrap(err, "client.rdsDelete")
   386  	}
   387  	_, err = region.WaitRdsOperation(operation.SelfLink, id, "delete")
   388  	if err != nil {
   389  		return errors.Wrapf(err, "region.WaitRdsOperation(%s)", operation.SelfLink)
   390  	}
   391  	return nil
   392  }
   393  
   394  func (region *SRegion) rdsDo(id string, action string, params map[string]string, body jsonutils.JSONObject) error {
   395  	opId, err := region.client.rdsDo(id, action, params, body)
   396  	if err != nil {
   397  		return err
   398  	}
   399  	if strings.Index(opId, "/operations/") > 0 {
   400  		_, err = region.WaitRdsOperation(opId, id, action)
   401  		return err
   402  	}
   403  	return nil
   404  }
   405  
   406  func (region *SRegion) rdsPatch(id string, body jsonutils.JSONObject) error {
   407  	opId, err := region.client.rdsPatch(id, body)
   408  	if err != nil {
   409  		return err
   410  	}
   411  	if strings.Index(opId, "/operations/") > 0 {
   412  		_, err = region.WaitRdsOperation(opId, id, "update")
   413  		return err
   414  	}
   415  	return nil
   416  }
   417  
   418  func (region *SRegion) rdsUpdate(id string, params map[string]string, body jsonutils.JSONObject) error {
   419  	opId, err := region.client.rdsUpdate(id, params, body)
   420  	if err != nil {
   421  		return err
   422  	}
   423  	if strings.Index(opId, "/operations/") > 0 {
   424  		_, err = region.WaitRdsOperation(opId, id, "update")
   425  		return err
   426  	}
   427  	return nil
   428  }
   429  
   430  func (region *SRegion) rdsGet(resource string, retval interface{}) error {
   431  	return region.client.rdsGet(resource, retval)
   432  }
   433  
   434  func (region *SRegion) rdsInsert(resource string, body jsonutils.JSONObject, retval interface{}) error {
   435  	operation := SOperation{}
   436  	err := region.client.rdsInsert(resource, body, &operation)
   437  	if err != nil {
   438  		return errors.Wrap(err, "rdsInsert")
   439  	}
   440  	resourceId, err := region.WaitRdsOperation(operation.SelfLink, resource, "insert")
   441  	if err != nil {
   442  		return errors.Wrapf(err, "region.WaitRdsOperation(%s)", operation.SelfLink)
   443  	}
   444  	return region.rdsGet(resourceId, retval)
   445  }
   446  
   447  func (region *SRegion) RdsListAll(resource string, params map[string]string, retval interface{}) error {
   448  	return region.client.rdsListAll(resource, params, retval)
   449  }
   450  
   451  func (region *SRegion) RdsList(resource string, params map[string]string, maxResults int, pageToken string, retval interface{}) error {
   452  	if maxResults == 0 && len(pageToken) == 0 {
   453  		return region.RdsListAll(resource, params, retval)
   454  	}
   455  	if params == nil {
   456  		params = map[string]string{}
   457  	}
   458  	params["maxResults"] = fmt.Sprintf("%d", maxResults)
   459  	params["pageToken"] = pageToken
   460  	resp, err := region.client.rdsList(resource, params)
   461  	if err != nil {
   462  		return errors.Wrap(err, "billingList")
   463  	}
   464  	if resp.Contains("items") && retval != nil {
   465  		err = resp.Unmarshal(retval, "items")
   466  		if err != nil {
   467  			return errors.Wrap(err, "resp.Unmarshal")
   468  		}
   469  	}
   470  	return nil
   471  }
   472  
   473  func (region *SRegion) BillingList(resource string, params map[string]string, pageSize int, pageToken string, retval interface{}) error {
   474  	if pageSize == 0 && len(pageToken) == 0 {
   475  		return region.BillingListAll(resource, params, retval)
   476  	}
   477  	if params == nil {
   478  		params = map[string]string{}
   479  	}
   480  	params["pageSize"] = fmt.Sprintf("%d", pageSize)
   481  	params["pageToken"] = pageToken
   482  	resp, err := region.client.billingList(resource, params)
   483  	if err != nil {
   484  		return errors.Wrap(err, "billingList")
   485  	}
   486  	if resp.Contains("skus") && retval != nil {
   487  		err = resp.Unmarshal(retval, "skus")
   488  		if err != nil {
   489  			return errors.Wrap(err, "resp.Unmarshal")
   490  		}
   491  	}
   492  	return nil
   493  }
   494  
   495  func (region *SRegion) BillingListAll(resource string, params map[string]string, retval interface{}) error {
   496  	return region.client.billingListAll(resource, params, retval)
   497  }
   498  
   499  func (region *SRegion) ListAll(resource string, params map[string]string, retval interface{}) error {
   500  	return region.listAll("GET", resource, params, retval)
   501  }
   502  
   503  func (region *SRegion) listAll(method string, resource string, params map[string]string, retval interface{}) error {
   504  	return region.client._ecsListAll(method, resource, params, retval)
   505  }
   506  
   507  func (region *SRegion) List(resource string, params map[string]string, maxResults int, pageToken string, retval interface{}) error {
   508  	if maxResults == 0 && len(pageToken) == 0 {
   509  		return region.ListAll(resource, params, retval)
   510  	}
   511  	if params == nil {
   512  		params = map[string]string{}
   513  	}
   514  	params["maxResults"] = fmt.Sprintf("%d", maxResults)
   515  	params["pageToken"] = pageToken
   516  	resp, err := region.client.ecsList(resource, params)
   517  	if err != nil {
   518  		return errors.Wrap(err, "ecsList")
   519  	}
   520  	if resp.Contains("items") && retval != nil {
   521  		err = resp.Unmarshal(retval, "items")
   522  		if err != nil {
   523  			return errors.Wrap(err, "resp.Unmarshal")
   524  		}
   525  	}
   526  	return nil
   527  }
   528  
   529  func (region *SRegion) Get(resourceType, id string, retval interface{}) error {
   530  	return region.client.ecsGet(resourceType, id, retval)
   531  }
   532  
   533  func (self *SGoogleClient) GetBySelfId(id string, retval interface{}) error {
   534  	resp, err := jsonRequest(self.client, "GET", GOOGLE_COMPUTE_DOMAIN, GOOGLE_API_VERSION, id, nil, nil, self.debug)
   535  	if err != nil {
   536  		return err
   537  	}
   538  	if retval != nil {
   539  		return resp.Unmarshal(retval)
   540  	}
   541  	return nil
   542  }
   543  
   544  func (self *SRegion) GetBySelfId(id string, retval interface{}) error {
   545  	return self.client.GetBySelfId(id, retval)
   546  }
   547  
   548  func (region *SRegion) StorageListAll(resource string, params map[string]string, retval interface{}) error {
   549  	return region.client.storageListAll(resource, params, retval)
   550  }
   551  
   552  func (region *SRegion) StorageList(resource string, params map[string]string, maxResults int, pageToken string, retval interface{}) error {
   553  	if maxResults == 0 && len(pageToken) == 0 {
   554  		return region.client.storageListAll(resource, params, retval)
   555  	}
   556  	if params == nil {
   557  		params = map[string]string{}
   558  	}
   559  	params["maxResults"] = fmt.Sprintf("%d", maxResults)
   560  	params["pageToken"] = pageToken
   561  	resp, err := region.client.storageList(resource, params)
   562  	if err != nil {
   563  		return errors.Wrap(err, "storageList")
   564  	}
   565  	if resp.Contains("items") && retval != nil {
   566  		err = resp.Unmarshal(retval, "items")
   567  		if err != nil {
   568  			return errors.Wrap(err, "resp.Unmarshal")
   569  		}
   570  	}
   571  	return nil
   572  }
   573  
   574  func (region *SRegion) StorageGet(id string, retval interface{}) error {
   575  	return region.client.storageGet(id, retval)
   576  }
   577  
   578  func (region *SRegion) StoragePut(id string, body jsonutils.JSONObject, retval interface{}) error {
   579  	return region.client.storagePut(id, body, retval)
   580  }
   581  
   582  func (region *SRegion) StorageDo(id string, action string, params map[string]string, body jsonutils.JSONObject) error {
   583  	opId, err := region.client.storageDo(id, action, params, body)
   584  	if err != nil {
   585  		return err
   586  	}
   587  	if strings.Index(opId, "/operations/") > 0 {
   588  		_, err = region.client.WaitOperation(opId, id, action)
   589  		return err
   590  	}
   591  	return nil
   592  }
   593  
   594  func (region *SRegion) Do(id string, action string, params map[string]string, body jsonutils.JSONObject) error {
   595  	opId, err := region.client.ecsDo(id, action, params, body)
   596  	if err != nil {
   597  		return err
   598  	}
   599  	if strings.Index(opId, "/operations/") > 0 {
   600  		_, err = region.client.WaitOperation(opId, id, action)
   601  		return err
   602  	}
   603  	return nil
   604  }
   605  
   606  func (region *SRegion) Patch(id string, action string, params map[string]string, body jsonutils.JSONObject) error {
   607  	opId, err := region.client.ecsPatch(id, action, params, body)
   608  	if err != nil {
   609  		return err
   610  	}
   611  	if strings.Index(opId, "/operations/") > 0 {
   612  		_, err = region.client.WaitOperation(opId, id, action)
   613  		return err
   614  	}
   615  	return nil
   616  }
   617  
   618  func (region *SRegion) StorageDelete(id string) error {
   619  	return region.client.storageDelete(id, nil)
   620  }
   621  
   622  func (region *SRegion) Delete(id string) error {
   623  	operation := &SOperation{}
   624  	err := region.client.ecsDelete(id, operation)
   625  	if err != nil {
   626  		return errors.Wrap(err, "client.ecsDelete")
   627  	}
   628  	_, err = region.client.WaitOperation(operation.SelfLink, id, "delete")
   629  	if err != nil {
   630  		return errors.Wrapf(err, "region.WaitOperation(%s)", operation.SelfLink)
   631  	}
   632  	return nil
   633  }
   634  
   635  func (region *SRegion) StorageInsert(resource string, body jsonutils.JSONObject, retval interface{}) error {
   636  	return region.client.storageInsert(resource, body, retval)
   637  }
   638  
   639  func (region *SRegion) CloudbuildInsert(body jsonutils.JSONObject) error {
   640  	result := &struct {
   641  		Name string
   642  	}{}
   643  	resource := fmt.Sprintf("projects/%s/builds", region.GetProjectId())
   644  	err := region.client.cloudbuildInsert(resource, body, result)
   645  	if err != nil {
   646  		return errors.Wrap(err, "insert")
   647  	}
   648  	err = cloudprovider.Wait(time.Second*10, time.Minute*40, func() (bool, error) {
   649  		operation, err := region.GetCloudbuildOperation(result.Name)
   650  		if err != nil {
   651  			return false, errors.Wrapf(err, "region.GetCloudbuildOperation(%s)", result.Name)
   652  		}
   653  		status := operation.Metadata.Build.Status
   654  		log.Debugf("cloudbuild %s status: %s", result.Name, status)
   655  		if status == "FAILURE" {
   656  			return false, fmt.Errorf("cloudbuild failed error log: %s", operation.Metadata.Build.LogUrl)
   657  		}
   658  		if status == "SUCCESS" {
   659  			return true, nil
   660  		}
   661  		return false, nil
   662  	})
   663  	if err != nil {
   664  		return errors.Wrap(err, "cloudprovider.Wait")
   665  	}
   666  	return nil
   667  }
   668  
   669  func (region *SRegion) cloudbuildGet(id string, retval interface{}) error {
   670  	return region.client.cloudbuildGet(id, retval)
   671  }
   672  
   673  func (self *SGoogleClient) Insert(resource string, body jsonutils.JSONObject, retval interface{}) error {
   674  	operation := &SOperation{}
   675  	err := self.ecsInsert(resource, body, operation)
   676  	if err != nil {
   677  		return err
   678  	}
   679  	resourceId, err := self.WaitOperation(operation.SelfLink, resource, "insert")
   680  	if err != nil {
   681  		return errors.Wrapf(err, "region.WaitOperation(%s)", operation.SelfLink)
   682  	}
   683  	return self.GetBySelfId(resourceId, retval)
   684  }
   685  
   686  func (self *SRegion) Insert(resource string, body jsonutils.JSONObject, retval interface{}) error {
   687  	return self.client.Insert(resource, body, retval)
   688  }
   689  
   690  func (region *SRegion) fetchResourcePolicies() ([]SResourcePolicy, error) {
   691  	if len(region.client.resourcepolices) > 0 {
   692  		return region.client.resourcepolices, nil
   693  	}
   694  	policies, err := region.GetResourcePolicies(0, "")
   695  	if err != nil {
   696  		return nil, err
   697  	}
   698  	region.client.resourcepolices = policies
   699  	return policies, nil
   700  }
   701  
   702  func (region *SRegion) GetISnapshotPolicies() ([]cloudprovider.ICloudSnapshotPolicy, error) {
   703  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   704  		return []cloudprovider.ICloudSnapshotPolicy{}, nil
   705  	}
   706  
   707  	policies, err := region.fetchResourcePolicies()
   708  	if err != nil {
   709  		return nil, err
   710  	}
   711  	ipolicies := []cloudprovider.ICloudSnapshotPolicy{}
   712  	for i := range policies {
   713  		policies[i].region = region
   714  		if utils.IsInStringArray(region.Name, policies[i].SnapshotSchedulePolicy.SnapshotProperties.StorageLocations) {
   715  			ipolicies = append(ipolicies, &policies[i])
   716  		}
   717  	}
   718  	return ipolicies, nil
   719  }
   720  
   721  func (region *SRegion) GetISnapshotPolicyById(id string) (cloudprovider.ICloudSnapshotPolicy, error) {
   722  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   723  		return nil, cloudprovider.ErrNotFound
   724  	}
   725  
   726  	policy, err := region.GetResourcePolicy(id)
   727  	if err != nil {
   728  		return nil, err
   729  	}
   730  	if !strings.Contains(region.Name, policy.SnapshotSchedulePolicy.SnapshotProperties.StorageLocations[0]) {
   731  		return nil, cloudprovider.ErrNotFound
   732  	}
   733  	return policy, nil
   734  }
   735  
   736  func (region *SRegion) CreateEIP(args *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
   737  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   738  		return nil, cloudprovider.ErrNotSupported
   739  	}
   740  
   741  	eip, err := region.CreateEip(args.Name, "")
   742  	if err != nil {
   743  		return nil, err
   744  	}
   745  	return eip, nil
   746  }
   747  
   748  func (region *SRegion) GetCapabilities() []string {
   749  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   750  		return []string{cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE}
   751  	}
   752  	if region.capabilities == nil {
   753  		return region.client.GetCapabilities()
   754  	}
   755  	return region.capabilities
   756  }
   757  
   758  func (region *SRegion) GetIDBInstances() ([]cloudprovider.ICloudDBInstance, error) {
   759  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   760  		return []cloudprovider.ICloudDBInstance{}, nil
   761  	}
   762  
   763  	instances, err := region.GetDBInstances(0, "")
   764  	if err != nil {
   765  		return nil, errors.Wrap(err, "GetDBInstances")
   766  	}
   767  	ret := []cloudprovider.ICloudDBInstance{}
   768  	for i := range instances {
   769  		instances[i].region = region
   770  		ret = append(ret, &instances[i])
   771  	}
   772  	return ret, nil
   773  }
   774  
   775  func (region *SRegion) GetIDBInstanceById(instanceId string) (cloudprovider.ICloudDBInstance, error) {
   776  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   777  		return nil, cloudprovider.ErrNotFound
   778  	}
   779  
   780  	instance, err := region.GetDBInstance(instanceId)
   781  	if err != nil {
   782  		return nil, errors.Wrapf(err, "GetDBInstance(%s)", instanceId)
   783  	}
   784  	return instance, nil
   785  }
   786  
   787  func (region *SRegion) GetIDBInstanceBackups() ([]cloudprovider.ICloudDBInstanceBackup, error) {
   788  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   789  		return []cloudprovider.ICloudDBInstanceBackup{}, nil
   790  	}
   791  
   792  	instances, err := region.GetDBInstances(0, "")
   793  	if err != nil {
   794  		return nil, errors.Wrap(err, "GetDBInstances")
   795  	}
   796  	ret := []cloudprovider.ICloudDBInstanceBackup{}
   797  	for i := range instances {
   798  		instances[i].region = region
   799  		backups, err := region.GetDBInstanceBackups(instances[i].Name)
   800  		if err != nil {
   801  			return nil, errors.Wrapf(err, "GetDBInstanceBackups(%s)", instances[i].Name)
   802  		}
   803  		for j := range backups {
   804  			backups[j].rds = &instances[i]
   805  			ret = append(ret, &backups[j])
   806  		}
   807  	}
   808  	return ret, nil
   809  }
   810  
   811  func (region *SRegion) GetIDBInstanceBackupById(backupId string) (cloudprovider.ICloudDBInstanceBackup, error) {
   812  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   813  		return nil, cloudprovider.ErrNotFound
   814  	}
   815  
   816  	backup, err := region.GetDBInstanceBackup(backupId)
   817  	if err != nil {
   818  		return nil, errors.Wrapf(err, "GetDBInstanceBackup(%s)", backupId)
   819  	}
   820  	return backup, nil
   821  }
   822  
   823  func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) {
   824  	if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
   825  		return nil, cloudprovider.ErrNotSupported
   826  	}
   827  
   828  	rds, err := region.CreateDBInstance(desc)
   829  	if err != nil {
   830  		return nil, errors.Wrap(err, "CreateDBInstance")
   831  	}
   832  	return rds, nil
   833  }