yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/ucloud/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 ucloud
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	"yunion.io/x/pkg/errors"
    22  	"yunion.io/x/pkg/util/secrules"
    23  
    24  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    25  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    26  	"yunion.io/x/cloudmux/pkg/multicloud"
    27  )
    28  
    29  type SRegion struct {
    30  	multicloud.SRegion
    31  	client *SUcloudClient
    32  
    33  	RegionID string
    34  
    35  	izones []cloudprovider.ICloudZone
    36  	ivpcs  []cloudprovider.ICloudVpc
    37  
    38  	storageCache *SStoragecache
    39  
    40  	latitude      float64
    41  	longitude     float64
    42  	fetchLocation bool
    43  }
    44  
    45  func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
    46  	return nil, cloudprovider.ErrNotImplemented
    47  }
    48  
    49  func (self *SRegion) GetId() string {
    50  	return self.RegionID
    51  }
    52  
    53  func (self *SRegion) GetName() string {
    54  	if name, exist := UCLOUD_REGION_NAMES[self.GetId()]; exist {
    55  		return fmt.Sprintf("%s %s", CLOUD_PROVIDER_UCLOUD_CN, name)
    56  	}
    57  
    58  	return fmt.Sprintf("%s %s", CLOUD_PROVIDER_UCLOUD_CN, self.GetId())
    59  }
    60  
    61  func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
    62  	var en string
    63  	if name, exist := UCLOUD_REGION_NAMES_EN[self.GetId()]; exist {
    64  		en = fmt.Sprintf("%s %s", CLOUD_PROVIDER_UCLOUD, name)
    65  	} else {
    66  		en = fmt.Sprintf("%s %s", CLOUD_PROVIDER_UCLOUD, self.GetId())
    67  	}
    68  
    69  	table := cloudprovider.SModelI18nTable{}
    70  	table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en)
    71  	return table
    72  }
    73  
    74  func (self *SRegion) GetGlobalId() string {
    75  	return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_UCLOUD, self.GetId())
    76  }
    77  
    78  func (self *SRegion) GetStatus() string {
    79  	return api.CLOUD_REGION_STATUS_INSERVER
    80  }
    81  
    82  func (self *SRegion) Refresh() error {
    83  	return nil
    84  }
    85  
    86  func (self *SRegion) IsEmulated() bool {
    87  	return false
    88  }
    89  
    90  func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
    91  	if info, ok := LatitudeAndLongitude[self.GetId()]; ok {
    92  		return info
    93  	}
    94  	return cloudprovider.SGeographicInfo{}
    95  }
    96  
    97  func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
    98  	instance, err := self.GetInstanceByID(id)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	return &instance, nil
   103  }
   104  
   105  func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
   106  	return self.GetDisk(id)
   107  }
   108  
   109  func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
   110  	if self.izones == nil {
   111  		var err error
   112  		err = self.fetchInfrastructure()
   113  		if err != nil {
   114  			return nil, err
   115  		}
   116  	}
   117  	return self.izones, nil
   118  }
   119  
   120  func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
   121  	if self.ivpcs == nil {
   122  		err := self.fetchInfrastructure()
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  	}
   127  	return self.ivpcs, nil
   128  }
   129  
   130  // https://docs.ucloud.cn/api/unet-api/describe_eip
   131  func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
   132  	params := NewUcloudParams()
   133  	eips := make([]SEip, 0)
   134  	err := self.DoListAll("DescribeEIP", params, &eips)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	ieips := []cloudprovider.ICloudEIP{}
   140  	for i := range eips {
   141  		eip := eips[i]
   142  		eip.region = self
   143  		ieips = append(ieips, &eip)
   144  	}
   145  
   146  	return ieips, nil
   147  }
   148  
   149  func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
   150  	ivpcs, err := self.GetIVpcs()
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  	for i := 0; i < len(ivpcs); i += 1 {
   155  		if ivpcs[i].GetGlobalId() == id {
   156  			return ivpcs[i], nil
   157  		}
   158  	}
   159  	return nil, cloudprovider.ErrNotFound
   160  }
   161  
   162  func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
   163  	izones, err := self.GetIZones()
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	for i := 0; i < len(izones); i += 1 {
   168  		if izones[i].GetGlobalId() == id {
   169  			return izones[i], nil
   170  		}
   171  	}
   172  	return nil, cloudprovider.ErrNotFound
   173  }
   174  
   175  func (self *SRegion) GetEipById(eipId string) (SEip, error) {
   176  	params := NewUcloudParams()
   177  	params.Set("EIPIds.0", eipId)
   178  	eips := make([]SEip, 0)
   179  	err := self.DoListAll("DescribeEIP", params, &eips)
   180  	if err != nil {
   181  		return SEip{}, err
   182  	}
   183  
   184  	if len(eips) == 1 {
   185  		eip := eips[0]
   186  		eip.region = self
   187  		return eip, nil
   188  	} else if len(eips) == 0 {
   189  		return SEip{}, cloudprovider.ErrNotFound
   190  	} else {
   191  		return SEip{}, fmt.Errorf("GetEipById %d eip found", len(eips))
   192  	}
   193  }
   194  
   195  func (self *SRegion) GetIEipById(id string) (cloudprovider.ICloudEIP, error) {
   196  	eip, err := self.GetEipById(id)
   197  	return &eip, err
   198  }
   199  
   200  // https://docs.ucloud.cn/api/unet-api/delete_firewall
   201  func (self *SRegion) DeleteSecurityGroup(secgroupId string) error {
   202  	params := NewUcloudParams()
   203  	params.Set("FWId", secgroupId)
   204  	return self.DoAction("DeleteFirewall", params, nil)
   205  }
   206  
   207  func (self *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
   208  	return self.GetSecurityGroupById(secgroupId)
   209  }
   210  
   211  func (self *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) {
   212  	secgroups, err := self.GetSecurityGroups("", "", opts.Name)
   213  	if err != nil {
   214  		return nil, err
   215  	}
   216  	if len(secgroups) == 0 {
   217  		return nil, cloudprovider.ErrNotFound
   218  	}
   219  	if len(secgroups) > 1 {
   220  		return nil, cloudprovider.ErrDuplicateId
   221  	}
   222  	return &secgroups[0], nil
   223  }
   224  
   225  func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
   226  	externalId, err := self.CreateDefaultSecurityGroup(conf.Name, conf.Desc)
   227  	if err != nil {
   228  		return nil, err
   229  	}
   230  	return self.GetISecurityGroupById(externalId)
   231  }
   232  
   233  // https://docs.ucloud.cn/api/unet-api/describe_firewall
   234  // 绑定防火墙组的资源类型,默认为全部资源类型。枚举值为:"unatgw",NAT网关; "uhost",云主机; "upm",物理云主机; "hadoophost",hadoop节点; "fortresshost",堡垒机; "udhost",私有专区主机;"udockhost",容器;"dbaudit",数据库审计.
   235  // todo: 是否需要过滤出仅绑定云主机的安全组?
   236  
   237  func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
   238  	params := NewUcloudParams()
   239  	params.Set("Name", opts.NAME)
   240  	params.Set("Remark", opts.Desc)
   241  	for i, cidr := range strings.Split(opts.CIDR, ",") {
   242  		params.Set(fmt.Sprintf("Network.%d", i), cidr)
   243  	}
   244  
   245  	vpcId := ""
   246  	err := self.DoAction("CreateVPC", params, &vpcId)
   247  	if err != nil {
   248  		return nil, err
   249  	}
   250  
   251  	return self.GetIVpcById(vpcId)
   252  }
   253  
   254  // https://docs.ucloud.cn/api/udisk-api/describe_udisk_snapshot
   255  func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
   256  	params := NewUcloudParams()
   257  	snapshots := make([]SSnapshot, 0)
   258  	err := self.DoListAll("DescribeUDiskSnapshot", params, &snapshots)
   259  	if err != nil {
   260  		return nil, err
   261  	}
   262  
   263  	isnapshots := make([]cloudprovider.ICloudSnapshot, 0)
   264  	for i := range snapshots {
   265  		snapshots[i].region = self
   266  		isnapshots = append(isnapshots, &snapshots[i])
   267  	}
   268  
   269  	return isnapshots, nil
   270  }
   271  
   272  func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
   273  	if len(snapshotId) == 0 {
   274  		return nil, cloudprovider.ErrNotFound
   275  	}
   276  
   277  	params := NewUcloudParams()
   278  	snapshots := make([]SSnapshot, 0)
   279  	err := self.DoListAll("DescribeUDiskSnapshot", params, &snapshots)
   280  	if err != nil {
   281  		return nil, err
   282  	}
   283  
   284  	for i := range snapshots {
   285  		if snapshots[i].SnapshotID == snapshotId {
   286  			snapshot := snapshots[i]
   287  			snapshot.region = self
   288  			return &snapshot, nil
   289  		}
   290  	}
   291  
   292  	return nil, cloudprovider.ErrNotFound
   293  }
   294  
   295  func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
   296  	iHosts := make([]cloudprovider.ICloudHost, 0)
   297  
   298  	izones, err := self.GetIZones()
   299  	if err != nil {
   300  		return nil, err
   301  	}
   302  	for i := 0; i < len(izones); i += 1 {
   303  		iZoneHost, err := izones[i].GetIHosts()
   304  		if err != nil {
   305  			return nil, err
   306  		}
   307  		iHosts = append(iHosts, iZoneHost...)
   308  	}
   309  	return iHosts, nil
   310  }
   311  
   312  func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
   313  	izones, err := self.GetIZones()
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  	for i := 0; i < len(izones); i += 1 {
   318  		ihost, err := izones[i].GetIHostById(id)
   319  		if err == nil {
   320  			return ihost, nil
   321  		} else if errors.Cause(err) != cloudprovider.ErrNotFound {
   322  			return nil, err
   323  		}
   324  	}
   325  	return nil, cloudprovider.ErrNotFound
   326  }
   327  
   328  func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
   329  	iStores := make([]cloudprovider.ICloudStorage, 0)
   330  
   331  	izones, err := self.GetIZones()
   332  	if err != nil {
   333  		return nil, err
   334  	}
   335  	for i := 0; i < len(izones); i += 1 {
   336  		iZoneStores, err := izones[i].GetIStorages()
   337  		if err != nil {
   338  			return nil, err
   339  		}
   340  		iStores = append(iStores, iZoneStores...)
   341  	}
   342  	return iStores, nil
   343  }
   344  
   345  func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
   346  	izones, err := self.GetIZones()
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  	for i := 0; i < len(izones); i += 1 {
   351  		istore, err := izones[i].GetIStorageById(id)
   352  		if err == nil {
   353  			return istore, nil
   354  		} else if errors.Cause(err) != cloudprovider.ErrNotFound {
   355  			return nil, err
   356  		}
   357  	}
   358  	return nil, cloudprovider.ErrNotFound
   359  }
   360  
   361  func (self *SRegion) getStoragecache() *SStoragecache {
   362  	if self.storageCache == nil {
   363  		self.storageCache = &SStoragecache{region: self}
   364  	}
   365  	return self.storageCache
   366  }
   367  
   368  func (self *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) {
   369  	storageCache := self.getStoragecache()
   370  	return []cloudprovider.ICloudStoragecache{storageCache}, nil
   371  }
   372  
   373  func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
   374  	storageCache := self.getStoragecache()
   375  	if storageCache.GetGlobalId() == id {
   376  		return storageCache, nil
   377  	}
   378  	return nil, cloudprovider.ErrNotFound
   379  }
   380  
   381  func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
   382  	return nil, cloudprovider.ErrNotImplemented
   383  }
   384  
   385  func (self *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) {
   386  	return nil, cloudprovider.ErrNotImplemented
   387  }
   388  
   389  func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) {
   390  	return nil, cloudprovider.ErrNotImplemented
   391  }
   392  
   393  func (self *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) {
   394  	return nil, cloudprovider.ErrNotImplemented
   395  }
   396  
   397  func (self *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) {
   398  	return nil, cloudprovider.ErrNotImplemented
   399  }
   400  
   401  func (self *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) {
   402  	return nil, cloudprovider.ErrNotImplemented
   403  }
   404  
   405  func (self *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) {
   406  	return nil, cloudprovider.ErrNotImplemented
   407  }
   408  
   409  func (self *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
   410  	return nil, cloudprovider.ErrNotImplemented
   411  }
   412  
   413  func (self *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) {
   414  	return nil, cloudprovider.ErrNotImplemented
   415  }
   416  
   417  func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) {
   418  	return nil, cloudprovider.ErrNotSupported
   419  }
   420  
   421  func (self *SRegion) GetProvider() string {
   422  	return CLOUD_PROVIDER_UCLOUD
   423  }
   424  
   425  func (self *SRegion) GetCloudEnv() string {
   426  	return ""
   427  }
   428  
   429  func (self *SRegion) DoListAll(action string, params SParams, result interface{}) error {
   430  	params.Set("Region", self.GetId())
   431  	return self.client.DoListAll(action, params, result)
   432  }
   433  
   434  // return total,lenght,error
   435  func (self *SRegion) DoListPart(action string, limit int, offset int, params SParams, result interface{}) (int, int, error) {
   436  	params.Set("Region", self.GetId())
   437  	return self.client.DoListPart(action, limit, offset, params, result)
   438  }
   439  
   440  func (self *SRegion) DoAction(action string, params SParams, result interface{}) error {
   441  	params.Set("Region", self.GetId())
   442  	return self.client.DoAction(action, params, result)
   443  }
   444  
   445  func (self *SRegion) fetchInfrastructure() error {
   446  	if err := self.fetchZones(); err != nil {
   447  		return err
   448  	}
   449  
   450  	if err := self.fetchIVpcs(); err != nil {
   451  		return err
   452  	}
   453  
   454  	for i := 0; i < len(self.ivpcs); i += 1 {
   455  		vpc := self.ivpcs[i].(*SVPC)
   456  		wire := SWire{region: self, vpc: vpc}
   457  		vpc.addWire(&wire)
   458  
   459  		for j := 0; j < len(self.izones); j += 1 {
   460  			zone := self.izones[j].(*SZone)
   461  			zone.addWire(&wire)
   462  		}
   463  	}
   464  	return nil
   465  }
   466  
   467  func (self *SRegion) fetchZones() error {
   468  	type Region struct {
   469  		RegionID   int64  `json:"RegionId"`
   470  		RegionName string `json:"RegionName"`
   471  		IsDefault  bool   `json:"IsDefault"`
   472  		BitMaps    string `json:"BitMaps"`
   473  		Region     string `json:"Region"`
   474  		Zone       string `json:"Zone"`
   475  	}
   476  
   477  	params := NewUcloudParams()
   478  	regions := make([]Region, 0)
   479  	err := self.client.DoListAll("GetRegion", params, &regions)
   480  	if err != nil {
   481  		return err
   482  	}
   483  
   484  	for _, r := range regions {
   485  		if r.Region != self.GetId() {
   486  			continue
   487  		}
   488  
   489  		szone := SZone{}
   490  		szone.ZoneId = r.Zone
   491  		szone.RegionId = r.Region
   492  		szone.region = self
   493  		self.izones = append(self.izones, &szone)
   494  	}
   495  
   496  	return nil
   497  }
   498  
   499  func (self *SRegion) fetchIVpcs() error {
   500  	vpcs := make([]SVPC, 0)
   501  	params := NewUcloudParams()
   502  	err := self.DoListAll("DescribeVPC", params, &vpcs)
   503  	if err != nil {
   504  		return err
   505  	}
   506  
   507  	for i := range vpcs {
   508  		vpc := vpcs[i]
   509  		vpc.region = self
   510  		self.ivpcs = append(self.ivpcs, &vpc)
   511  	}
   512  
   513  	return nil
   514  }
   515  
   516  // https://docs.ucloud.cn/api/uhost-api/describe_uhost_instance
   517  func (self *SRegion) GetInstanceByID(instanceId string) (SInstance, error) {
   518  	params := NewUcloudParams()
   519  	params.Set("UHostIds.0", instanceId)
   520  	instances := make([]SInstance, 0)
   521  	err := self.DoAction("DescribeUHostInstance", params, &instances)
   522  	if err != nil {
   523  		return SInstance{}, err
   524  	}
   525  
   526  	if len(instances) == 1 {
   527  		return instances[0], nil
   528  	} else if len(instances) == 0 {
   529  		return SInstance{}, cloudprovider.ErrNotFound
   530  	} else {
   531  		return SInstance{}, fmt.Errorf("GetInstanceByID %s %d found.", instanceId, len(instances))
   532  	}
   533  }
   534  
   535  // GRE协议被忽略了
   536  func toUcloudSecRule(rule cloudprovider.SecurityRule) []string {
   537  	net := rule.IPNet.String()
   538  	action := "DROP"
   539  	if rule.Action == secrules.SecurityRuleAllow {
   540  		action = "ACCEPT"
   541  	}
   542  
   543  	rules := make([]string, 0)
   544  	if len(rule.Ports) > 0 {
   545  		for _, port := range rule.Ports {
   546  			_rules := generatorRule(rule.Protocol, net, action, port, port, rule.Priority)
   547  			rules = append(rules, _rules...)
   548  		}
   549  	} else {
   550  		_rules := generatorRule(rule.Protocol, net, action, rule.PortStart, rule.PortEnd, rule.Priority)
   551  		rules = append(rules, _rules...)
   552  	}
   553  
   554  	return rules
   555  }
   556  
   557  func generatorRule(protocol, net, action string, startPort, endPort, priority int) []string {
   558  	rules := make([]string, 0)
   559  
   560  	var ports string
   561  	if startPort <= 0 || endPort <= 0 {
   562  		ports = "1-65535"
   563  	} else if startPort == endPort {
   564  		ports = fmt.Sprintf("%d", startPort)
   565  	} else {
   566  		ports = fmt.Sprintf("%d-%d", startPort, endPort)
   567  	}
   568  	prio := "LOW"
   569  	switch priority {
   570  	case 1:
   571  		prio = "LOW"
   572  	case 2:
   573  		prio = "MEDIUM"
   574  	case 3:
   575  		prio = "HIGH"
   576  	}
   577  
   578  	template := fmt.Sprintf("%s|%s|%s|%s|%s|", "%s", "%s", net, action, prio)
   579  	switch protocol {
   580  	case secrules.PROTO_ANY:
   581  		rules = append(rules, fmt.Sprintf(template, "TCP", ports))
   582  		rules = append(rules, fmt.Sprintf(template, "UDP", ports))
   583  		rules = append(rules, fmt.Sprintf(template, "ICMP", ""))
   584  	case secrules.PROTO_TCP:
   585  		rules = append(rules, fmt.Sprintf(template, "TCP", ports))
   586  	case secrules.PROTO_UDP:
   587  		rules = append(rules, fmt.Sprintf(template, "UDP", ports))
   588  	case secrules.PROTO_ICMP:
   589  		rules = append(rules, fmt.Sprintf(template, "ICMP", ""))
   590  	}
   591  
   592  	return rules
   593  }
   594  
   595  // https://docs.ucloud.cn/api/unet-api/update_firewall
   596  func (self *SRegion) syncSecgroupRules(secgroupId string, rules []cloudprovider.SecurityRule) error {
   597  	_rules := []string{}
   598  	for _, r := range rules {
   599  		_rules = append(_rules, toUcloudSecRule(r)...)
   600  	}
   601  
   602  	params := NewUcloudParams()
   603  	params.Set("FWId", secgroupId)
   604  	for i, r := range _rules {
   605  		N := i + 1
   606  		params.Set(fmt.Sprintf("Rule.%d", N), r)
   607  	}
   608  
   609  	return self.DoAction("UpdateFirewall", params, nil)
   610  }
   611  
   612  func (self *SRegion) GetClient() *SUcloudClient {
   613  	return self.client
   614  }
   615  
   616  // https://docs.ucloud.cn/api/ufile-api/describe_bucket
   617  func (client *SUcloudClient) listBuckets(name string, offset int, limit int) ([]SBucket, error) {
   618  	params := NewUcloudParams()
   619  	if len(name) > 0 {
   620  		params.Set("BucketName", name)
   621  	} else {
   622  		params.Set("Limit", limit)
   623  		params.Set("Offset", offset)
   624  	}
   625  	buckets := make([]SBucket, 0)
   626  	// request without RegionId
   627  	err := client.DoAction("DescribeBucket", params, &buckets)
   628  	if err != nil {
   629  		return nil, errors.Wrap(err, "DoAction DescribeBucket")
   630  	}
   631  	return buckets, nil
   632  }
   633  
   634  // https://docs.ucloud.cn/api/ufile-api/update_bucket
   635  func (region *SRegion) updateBucket(name string, aclType string) error {
   636  	params := NewUcloudParams()
   637  	params.Set("BucketName", name)
   638  	params.Set("ProjectId", region.client.projectId)
   639  	params.Set("Type", aclType)
   640  	return region.client.DoAction("UpdateBucket", params, nil)
   641  }
   642  
   643  func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
   644  	iBuckets, err := region.client.getIBuckets()
   645  	if err != nil {
   646  		return nil, errors.Wrap(err, "getIBuckets")
   647  	}
   648  	ret := make([]cloudprovider.ICloudBucket, 0)
   649  	for i := range iBuckets {
   650  		if iBuckets[i].GetLocation() != region.GetId() {
   651  			continue
   652  		}
   653  		ret = append(ret, iBuckets[i])
   654  	}
   655  	return ret, nil
   656  }
   657  
   658  func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
   659  	if aclStr != "private" && aclStr != "public" {
   660  		return errors.Error("invalid acl")
   661  	}
   662  	return region.CreateBucket(name, aclStr)
   663  }
   664  
   665  func (region *SRegion) DeleteIBucket(name string) error {
   666  	err := region.DeleteBucket(name)
   667  	if err != nil {
   668  		if strings.Index(err.Error(), "bucket not found") >= 0 {
   669  			return nil
   670  		}
   671  		return errors.Wrap(err, "region.DeleteBucket")
   672  	}
   673  	return nil
   674  }
   675  
   676  func (region *SRegion) IBucketExist(name string) (bool, error) {
   677  	parts, err := region.client.listBuckets(name, 0, 1)
   678  	if err != nil {
   679  		return false, errors.Wrap(err, "region.listBuckets")
   680  	}
   681  	if len(parts) == 0 {
   682  		return false, cloudprovider.ErrNotFound
   683  	}
   684  	return true, nil
   685  }
   686  
   687  func (region *SRegion) GetIBucketById(bucketId string) (cloudprovider.ICloudBucket, error) {
   688  	return cloudprovider.GetIBucketById(region, bucketId)
   689  }
   690  
   691  func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
   692  	return region.GetIBucketByName(name)
   693  }
   694  
   695  func (region *SRegion) GetCapabilities() []string {
   696  	return region.client.GetCapabilities()
   697  }