yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/hcso/elasticcache_instance.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 hcso
    16  
    17  import (
    18  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  	"time"
    22  
    23  	"yunion.io/x/jsonutils"
    24  	"yunion.io/x/log"
    25  	"yunion.io/x/pkg/errors"
    26  
    27  	billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
    28  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    29  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    30  	"yunion.io/x/cloudmux/pkg/multicloud"
    31  	"yunion.io/x/cloudmux/pkg/multicloud/huawei"
    32  	"yunion.io/x/onecloud/pkg/util/billing"
    33  )
    34  
    35  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423020.html
    36  type SElasticcache struct {
    37  	multicloud.SElasticcacheBase
    38  	huawei.HuaweiTags
    39  
    40  	region *SRegion
    41  
    42  	Name                  string   `json:"name"`
    43  	Engine                string   `json:"engine"`
    44  	CapacityGB            int      `json:"capacity"`
    45  	IP                    string   `json:"ip"`
    46  	DomainName            string   `json:"domainName"`
    47  	Port                  int      `json:"port"`
    48  	Status                string   `json:"status"`
    49  	Libos                 bool     `json:"libos"`
    50  	Description           string   `json:"description"`
    51  	Task                  string   `json:"task"`
    52  	MaxMemoryMB           int      `json:"max_memory"`
    53  	UsedMemoryMB          int      `json:"used_memory"`
    54  	InstanceID            string   `json:"instance_id"`
    55  	ResourceSpecCode      string   `json:"resource_spec_code"`
    56  	EngineVersion         string   `json:"engine_version"`
    57  	InternalVersion       string   `json:"internal_version"`
    58  	ChargingMode          int      `json:"charging_mode"`
    59  	CapacityMinor         string   `json:"capacity_minor"`
    60  	VpcID                 string   `json:"vpc_id"`
    61  	VpcName               string   `json:"vpc_name"`
    62  	TaskStatus            string   `json:"task_status"`
    63  	CreatedAt             string   `json:"created_at"`
    64  	ErrorCode             string   `json:"error_code"`
    65  	UserID                string   `json:"user_id"`
    66  	UserName              string   `json:"user_name"`
    67  	MaintainBegin         string   `json:"maintain_begin"`
    68  	MaintainEnd           string   `json:"maintain_end"`
    69  	NoPasswordAccess      string   `json:"no_password_access"`
    70  	AccessUser            string   `json:"access_user"`
    71  	EnablePublicip        bool     `json:"enable_publicip"`
    72  	PublicipID            string   `json:"publicip_id"`
    73  	PublicipAddress       string   `json:"publicip_address"`
    74  	EnableSSL             bool     `json:"enable_ssl"`
    75  	ServiceUpgrade        bool     `json:"service_upgrade"`
    76  	ServiceTaskID         string   `json:"service_task_id"`
    77  	IsFree                string   `json:"is_free"`
    78  	EnterpriseProjectID   string   `json:"enterprise_project_id"`
    79  	AvailableZones        []string `json:"available_zones"`
    80  	SubnetID              string   `json:"subnet_id"`
    81  	SecurityGroupID       string   `json:"security_group_id"`
    82  	BackendAddrs          []string `json:"backend_addrs"`
    83  	ProductID             string   `json:"product_id"`
    84  	SecurityGroupName     string   `json:"security_group_name"`
    85  	SubnetName            string   `json:"subnet_name"`
    86  	OrderID               string   `json:"order_id"`
    87  	SubnetCIDR            string   `json:"subnet_cidr"`
    88  	InstanceBackupPolicy  string   `json:"instance_backup_policy"`
    89  	EnterpriseProjectName string   `json:"enterprise_project_name"`
    90  }
    91  
    92  func (self *SElasticcache) GetId() string {
    93  	return self.InstanceID
    94  }
    95  
    96  func (self *SElasticcache) GetName() string {
    97  	return self.Name
    98  }
    99  
   100  func (self *SElasticcache) GetGlobalId() string {
   101  	return self.GetId()
   102  }
   103  
   104  func (self *SElasticcache) GetProjectId() string {
   105  	return self.EnterpriseProjectID
   106  }
   107  
   108  func (self *SElasticcache) Refresh() error {
   109  	cache, err := self.region.GetElasticCache(self.GetId())
   110  	if err != nil {
   111  		return errors.Wrap(err, "Elasticcache.Refresh.GetElasticCache")
   112  	}
   113  
   114  	err = jsonutils.Update(self, cache)
   115  	if err != nil {
   116  		return errors.Wrap(err, "Elasticcache.Refresh.Update")
   117  	}
   118  
   119  	return nil
   120  }
   121  
   122  func (self *SElasticcache) GetStatus() string {
   123  	switch self.Status {
   124  	case "RUNNING":
   125  		return api.ELASTIC_CACHE_STATUS_RUNNING
   126  	case "CREATING":
   127  		return api.ELASTIC_CACHE_STATUS_DEPLOYING
   128  	case "CREATEFAILED":
   129  		return api.ELASTIC_CACHE_STATUS_CREATE_FAILED
   130  	case "ERROR":
   131  		return api.ELASTIC_CACHE_STATUS_ERROR
   132  	case "RESTARTING":
   133  		return api.ELASTIC_CACHE_STATUS_RESTARTING
   134  	case "FROZEN":
   135  		return api.ELASTIC_CACHE_STATUS_UNAVAILABLE
   136  	case "EXTENDING":
   137  		return api.ELASTIC_CACHE_STATUS_CHANGING
   138  	case "RESTORING":
   139  		return api.ELASTIC_CACHE_STATUS_TRANSFORMING // ?
   140  	case "FLUSHING":
   141  		return api.ELASTIC_CACHE_STATUS_FLUSHING
   142  	}
   143  
   144  	return ""
   145  }
   146  
   147  func (self *SElasticcache) GetBillingType() string {
   148  	// charging_mode “0”:按需计费    “1”:按包年包月计费
   149  	if self.ChargingMode == 1 {
   150  		return billing_api.BILLING_TYPE_PREPAID
   151  	} else {
   152  		return billing_api.BILLING_TYPE_POSTPAID
   153  	}
   154  }
   155  
   156  func (self *SElasticcache) GetCreatedAt() time.Time {
   157  	var createtime time.Time
   158  	if len(self.CreatedAt) > 0 {
   159  		createtime, _ = time.Parse("2006-01-02T15:04:05.000Z", self.CreatedAt)
   160  	}
   161  
   162  	return createtime
   163  }
   164  
   165  func (self *SElasticcache) GetExpiredAt() time.Time {
   166  	var expiredTime time.Time
   167  	return expiredTime
   168  }
   169  
   170  func (self *SElasticcache) GetInstanceType() string {
   171  	// todo: ??
   172  	return self.ResourceSpecCode
   173  }
   174  
   175  func (self *SElasticcache) GetCapacityMB() int {
   176  	return self.CapacityGB * 1024
   177  }
   178  
   179  func (self *SElasticcache) GetArchType() string {
   180  	/*
   181  	   资源规格标识。
   182  
   183  	   dcs.single_node:表示实例类型为单机
   184  	   dcs.master_standby:表示实例类型为主备
   185  	   dcs.cluster:表示实例类型为集群
   186  	*/
   187  	if strings.Contains(self.ResourceSpecCode, "single") {
   188  		return api.ELASTIC_CACHE_ARCH_TYPE_SINGLE
   189  	} else if strings.Contains(self.ResourceSpecCode, "ha") {
   190  		return api.ELASTIC_CACHE_ARCH_TYPE_MASTER
   191  	} else if strings.Contains(self.ResourceSpecCode, "cluster") {
   192  		return api.ELASTIC_CACHE_ARCH_TYPE_CLUSTER
   193  	} else if strings.Contains(self.ResourceSpecCode, "proxy") {
   194  		return api.ELASTIC_CACHE_ARCH_TYPE_CLUSTER
   195  	}
   196  
   197  	return ""
   198  }
   199  
   200  func (self *SElasticcache) GetNodeType() string {
   201  	// single(单副本) | double(双副本)
   202  	if strings.Contains(self.ResourceSpecCode, "single") {
   203  		return "single"
   204  	} else {
   205  		return "double"
   206  	}
   207  }
   208  
   209  func (self *SElasticcache) GetEngine() string {
   210  	return self.Engine
   211  }
   212  
   213  func (self *SElasticcache) GetEngineVersion() string {
   214  	return self.EngineVersion
   215  }
   216  
   217  func (self *SElasticcache) GetVpcId() string {
   218  	return self.VpcID
   219  }
   220  
   221  func (self *SElasticcache) GetZoneId() string {
   222  	if len(self.AvailableZones) > 0 {
   223  		zone, err := self.region.getZoneById(self.AvailableZones[0])
   224  		if err != nil {
   225  			log.Errorf("elasticcache.GetZoneId %s", err)
   226  			return ""
   227  		}
   228  
   229  		return zone.GetGlobalId()
   230  	}
   231  
   232  	return ""
   233  }
   234  
   235  func (self *SElasticcache) GetNetworkType() string {
   236  	return api.LB_NETWORK_TYPE_VPC
   237  }
   238  
   239  func (self *SElasticcache) GetNetworkId() string {
   240  	return self.SubnetID
   241  }
   242  
   243  func (self *SElasticcache) GetPrivateDNS() string {
   244  	return self.DomainName
   245  }
   246  
   247  func (self *SElasticcache) GetPrivateIpAddr() string {
   248  	return self.IP
   249  }
   250  
   251  func (self *SElasticcache) GetPrivateConnectPort() int {
   252  	return self.Port
   253  }
   254  
   255  func (self *SElasticcache) GetPublicDNS() string {
   256  	return self.PublicipAddress
   257  }
   258  
   259  func (self *SElasticcache) GetPublicIpAddr() string {
   260  	return self.PublicipAddress
   261  }
   262  
   263  func (self *SElasticcache) GetPublicConnectPort() int {
   264  	return self.Port
   265  }
   266  
   267  func (self *SElasticcache) GetMaintainStartTime() string {
   268  	return self.MaintainBegin
   269  }
   270  
   271  func (self *SElasticcache) GetMaintainEndTime() string {
   272  	return self.MaintainEnd
   273  }
   274  
   275  func (self *SElasticcache) GetICloudElasticcacheAccounts() ([]cloudprovider.ICloudElasticcacheAccount, error) {
   276  	iaccounts := []cloudprovider.ICloudElasticcacheAccount{}
   277  	iaccount := &SElasticcacheAccount{cacheDB: self}
   278  	iaccounts = append(iaccounts, iaccount)
   279  	return iaccounts, nil
   280  }
   281  
   282  func (self *SElasticcache) GetICloudElasticcacheAcls() ([]cloudprovider.ICloudElasticcacheAcl, error) {
   283  	// 华为云使用安全组做访问控制。目前未支持
   284  	return []cloudprovider.ICloudElasticcacheAcl{}, nil
   285  }
   286  
   287  func (self *SElasticcache) GetICloudElasticcacheBackups() ([]cloudprovider.ICloudElasticcacheBackup, error) {
   288  	start := self.GetCreatedAt().Format("20060102150405")
   289  	end := time.Now().Format("20060102150405")
   290  	backups, err := self.region.GetElasticCacheBackups(self.GetId(), start, end)
   291  	if err != nil {
   292  		return nil, err
   293  	}
   294  
   295  	ibackups := make([]cloudprovider.ICloudElasticcacheBackup, len(backups))
   296  	for i := range backups {
   297  		backups[i].cacheDB = self
   298  		ibackups[i] = &backups[i]
   299  	}
   300  
   301  	return ibackups, nil
   302  }
   303  
   304  func (self *SElasticcache) GetICloudElasticcacheParameters() ([]cloudprovider.ICloudElasticcacheParameter, error) {
   305  	parameters, err := self.region.GetElasticCacheParameters(self.GetId())
   306  	if err != nil {
   307  		return nil, err
   308  	}
   309  
   310  	iparameters := make([]cloudprovider.ICloudElasticcacheParameter, len(parameters))
   311  	for i := range parameters {
   312  		parameters[i].cacheDB = self
   313  		iparameters[i] = &parameters[i]
   314  	}
   315  
   316  	return iparameters, nil
   317  }
   318  
   319  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423035.html
   320  func (self *SRegion) GetElasticCacheBackups(instanceId, startTime, endTime string) ([]SElasticcacheBackup, error) {
   321  	params := make(map[string]string)
   322  	params["instance_id"] = instanceId
   323  	params["beginTime"] = startTime
   324  	params["endTime"] = endTime
   325  
   326  	backups := make([]SElasticcacheBackup, 0)
   327  	err := doListAll(self.ecsClient.Elasticcache.ListBackups, params, &backups)
   328  	if err != nil {
   329  		return nil, err
   330  	}
   331  
   332  	return backups, nil
   333  }
   334  
   335  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423027.html
   336  func (self *SRegion) GetElasticCacheParameters(instanceId string) ([]SElasticcacheParameter, error) {
   337  	params := make(map[string]string)
   338  	params["instance_id"] = instanceId
   339  
   340  	parameters := make([]SElasticcacheParameter, 0)
   341  	err := doListAll(self.ecsClient.Elasticcache.ListParameters, params, &parameters)
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  
   346  	return parameters, nil
   347  }
   348  
   349  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423044.html
   350  func (self *SRegion) GetElasticCaches() ([]SElasticcache, error) {
   351  	params := make(map[string]string)
   352  	caches := make([]SElasticcache, 0)
   353  	err := doListAll(self.ecsClient.Elasticcache.List, params, &caches)
   354  	if err != nil {
   355  		return nil, errors.Wrap(err, "region.GetElasticCaches")
   356  	}
   357  
   358  	for i := range caches {
   359  		cache, err := self.GetElasticCache(caches[i].GetId())
   360  		if err != nil {
   361  			return nil, err
   362  		} else {
   363  			caches[i] = *cache
   364  		}
   365  
   366  		caches[i].region = self
   367  	}
   368  
   369  	return caches, nil
   370  }
   371  
   372  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423020.html
   373  func (self *SRegion) GetElasticCache(instanceId string) (*SElasticcache, error) {
   374  	cache := SElasticcache{}
   375  	err := DoGet(self.ecsClient.Elasticcache.Get, instanceId, nil, &cache)
   376  	if err != nil {
   377  		return nil, errors.Wrapf(err, "region.GetElasticCache %s", instanceId)
   378  	}
   379  
   380  	cache.region = self
   381  	return &cache, nil
   382  }
   383  
   384  func (self *SRegion) GetIElasticcacheById(id string) (cloudprovider.ICloudElasticcache, error) {
   385  	ec, err := self.GetElasticCache(id)
   386  	if err != nil {
   387  		return nil, errors.Wrap(err, "region.GetIElasticCacheById.GetElasticCache")
   388  	}
   389  
   390  	return ec, nil
   391  }
   392  
   393  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423047.html
   394  func (self *SRegion) zoneNameToDcsZoneIds(zoneIds []string) ([]string, error) {
   395  	type Z struct {
   396  		ID                   string `json:"id"`
   397  		Code                 string `json:"code"`
   398  		Name                 string `json:"name"`
   399  		Port                 string `json:"port"`
   400  		ResourceAvailability string `json:"resource_availability"`
   401  	}
   402  
   403  	rs := []Z{}
   404  	err := doListAll(self.ecsClient.DcsAvailableZone.List, nil, &rs)
   405  	if err != nil {
   406  		return nil, errors.Wrap(err, "region.zoneNameToDcsZoneIds")
   407  	}
   408  
   409  	zoneMap := map[string]string{}
   410  	for i := range rs {
   411  		if rs[i].ResourceAvailability == "true" {
   412  			zoneMap[rs[i].Code] = rs[i].ID
   413  		}
   414  	}
   415  
   416  	ret := []string{}
   417  	for _, zone := range zoneIds {
   418  		if id, ok := zoneMap[zone]; ok {
   419  			ret = append(ret, id)
   420  		} else {
   421  			return nil, errors.Wrap(fmt.Errorf("zone %s not found or not available", zone), "region.zoneNameToDcsZoneIds")
   422  		}
   423  	}
   424  
   425  	return ret, nil
   426  }
   427  
   428  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423019.html
   429  func (self *SRegion) CreateIElasticcaches(ec *cloudprovider.SCloudElasticCacheInput) (cloudprovider.ICloudElasticcache, error) {
   430  	params := jsonutils.NewDict()
   431  	params.Set("name", jsonutils.NewString(ec.InstanceName))
   432  	params.Set("engine", jsonutils.NewString(ec.Engine))
   433  	params.Set("engine_version", jsonutils.NewString(ec.EngineVersion))
   434  	params.Set("capacity", jsonutils.NewInt(ec.CapacityGB))
   435  	params.Set("vpc_id", jsonutils.NewString(ec.VpcId))
   436  	if len(ec.SecurityGroupIds) > 0 {
   437  		params.Set("security_group_id", jsonutils.NewString(ec.SecurityGroupIds[0]))
   438  	}
   439  	params.Set("subnet_id", jsonutils.NewString(ec.NetworkId))
   440  	params.Set("product_id", jsonutils.NewString(ec.InstanceType))
   441  	zones, err := self.zoneNameToDcsZoneIds(ec.ZoneIds)
   442  	if err != nil {
   443  		return nil, err
   444  	}
   445  	params.Set("available_zones", jsonutils.NewStringArray(zones))
   446  
   447  	if len(ec.ProjectId) > 0 {
   448  		params.Set("enterprise_project_id", jsonutils.NewString(ec.ProjectId))
   449  	}
   450  
   451  	if len(ec.Password) > 0 {
   452  		params.Set("no_password_access", jsonutils.NewString("false"))
   453  		params.Set("password", jsonutils.NewString(ec.Password))
   454  
   455  		// todo: 这里换成常量
   456  		if ec.Engine == "Memcache" {
   457  			params.Set("access_user", jsonutils.NewString(ec.UserName))
   458  		}
   459  	} else {
   460  		params.Set("no_password_access", jsonutils.NewString("true"))
   461  	}
   462  
   463  	if len(ec.EipId) > 0 {
   464  		params.Set("enable_publicip", jsonutils.NewString("true"))
   465  		params.Set("publicip_id", jsonutils.NewString(ec.EipId))
   466  		// enable_ssl
   467  	} else {
   468  		params.Set("enable_publicip", jsonutils.NewString("false"))
   469  	}
   470  
   471  	if len(ec.PrivateIpAddress) > 0 {
   472  		params.Set("private_ip", jsonutils.NewString(ec.PrivateIpAddress))
   473  	}
   474  
   475  	if len(ec.MaintainBegin) > 0 {
   476  		params.Set("maintain_begin", jsonutils.NewString(ec.MaintainBegin))
   477  		params.Set("maintain_end", jsonutils.NewString(ec.MaintainEnd))
   478  	}
   479  
   480  	if strings.ToLower(ec.ChargeType) == billing_api.BILLING_TYPE_PREPAID && ec.BillingCycle != nil {
   481  		bssParam := jsonutils.NewDict()
   482  		bssParam.Set("charging_mode", jsonutils.NewString("prePaid"))
   483  		bssParam.Set("is_auto_pay", jsonutils.NewString("true"))
   484  		bssParam.Set("is_auto_renew", jsonutils.NewString(fmt.Sprintf("%v", ec.BillingCycle.AutoRenew)))
   485  		if ec.BillingCycle.GetMonths() >= 1 && ec.BillingCycle.GetMonths() >= 9 {
   486  			bssParam.Set("period_type", jsonutils.NewString("month"))
   487  			bssParam.Set("period_num", jsonutils.NewInt(int64(ec.BillingCycle.GetMonths())))
   488  		} else if ec.BillingCycle.GetYears() >= 1 && ec.BillingCycle.GetYears() <= 3 {
   489  			bssParam.Set("period_type", jsonutils.NewString("year"))
   490  			bssParam.Set("period_num", jsonutils.NewInt(int64(ec.BillingCycle.GetYears())))
   491  		} else {
   492  			return nil, fmt.Errorf("region.CreateIElasticcaches invalid billing cycle.reqired month (1~9) or  year(1~3)")
   493  		}
   494  
   495  		params.Set("bss_param", bssParam)
   496  	}
   497  
   498  	ret := &SElasticcache{}
   499  	err = DoCreate(self.ecsClient.Elasticcache.Create, params, ret)
   500  	if err != nil {
   501  		return nil, errors.Wrap(err, "region.CreateIElasticcaches")
   502  	}
   503  
   504  	ret.region = self
   505  	return ret, nil
   506  }
   507  
   508  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423030.html
   509  func (self *SElasticcache) Restart() error {
   510  	resp, err := self.region.ecsClient.Elasticcache.Restart(self.GetId())
   511  	if err != nil {
   512  		return errors.Wrap(err, "elasticcache.Restart")
   513  	}
   514  
   515  	rets, err := resp.GetArray("results")
   516  	if err != nil {
   517  		return errors.Wrap(err, "elasticcache.results")
   518  	}
   519  
   520  	for _, r := range rets {
   521  		if ret, _ := r.GetString("result"); ret != "success" {
   522  			return fmt.Errorf("elasticcache.Restart failed")
   523  		}
   524  	}
   525  
   526  	return nil
   527  }
   528  
   529  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423022.html
   530  func (self *SElasticcache) Delete() error {
   531  	err := DoDelete(self.region.ecsClient.Elasticcache.Delete, self.GetId(), nil, nil)
   532  	if err != nil {
   533  		return errors.Wrap(err, "elasticcache.Delete")
   534  	}
   535  
   536  	return nil
   537  }
   538  
   539  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423024.html
   540  func (self *SElasticcache) ChangeInstanceSpec(spec string) error {
   541  	segs := strings.Split(spec, ":")
   542  	if len(segs) < 2 {
   543  		return fmt.Errorf("elasticcache.ChangeInstanceSpec invalid sku %s", spec)
   544  	}
   545  
   546  	if !strings.HasPrefix(segs[1], "m") || !strings.HasSuffix(segs[1], "g") {
   547  		return fmt.Errorf("elasticcache.ChangeInstanceSpec sku %s memeory size is invalid.", spec)
   548  	}
   549  
   550  	newCapacity := segs[1][1 : len(segs[1])-1]
   551  	capacity, err := strconv.Atoi(newCapacity)
   552  	if err != nil {
   553  		return errors.Wrap(fmt.Errorf("invalid sku capacity %s", spec), "Elasticcache.ChangeInstanceSpec")
   554  	}
   555  
   556  	_, err = self.region.ecsClient.Elasticcache.ChangeInstanceSpec(self.GetId(), segs[0], int64(capacity))
   557  	if err != nil {
   558  		return errors.Wrap(err, "elasticcache.ChangeInstanceSpec")
   559  	}
   560  
   561  	return nil
   562  }
   563  
   564  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423021.html
   565  func (self *SElasticcache) SetMaintainTime(maintainStartTime, maintainEndTime string) error {
   566  	params := jsonutils.NewDict()
   567  	params.Set("maintain_begin", jsonutils.NewString(maintainStartTime))
   568  	params.Set("maintain_end", jsonutils.NewString(maintainEndTime))
   569  	err := DoUpdate(self.region.ecsClient.Elasticcache.Update, self.GetId(), params, nil)
   570  	if err != nil {
   571  		return errors.Wrap(err, "elasticcache.SetMaintainTime")
   572  	}
   573  
   574  	return nil
   575  }
   576  
   577  // https://support.huaweicloud.com/usermanual-dcs/dcs-zh-ug-180314001.html
   578  // 目前只有Redis3.0版本密码模式的实例支持通过公网访问Redis实例,其他版本暂不支持公网访问。
   579  // todo: 目前没找到api
   580  func (self *SElasticcache) AllocatePublicConnection(port int) (string, error) {
   581  	return "", cloudprovider.ErrNotSupported
   582  }
   583  
   584  // todo: 目前没找到api
   585  func (self *SElasticcache) ReleasePublicConnection() error {
   586  	return cloudprovider.ErrNotSupported
   587  }
   588  
   589  func (self *SElasticcache) CreateAccount(account cloudprovider.SCloudElasticCacheAccountInput) (cloudprovider.ICloudElasticcacheAccount, error) {
   590  	return nil, cloudprovider.ErrNotSupported
   591  }
   592  
   593  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423031.html
   594  
   595  func (self *SElasticcache) CreateAcl(aclName, securityIps string) (cloudprovider.ICloudElasticcacheAcl, error) {
   596  	return nil, cloudprovider.ErrNotSupported
   597  }
   598  
   599  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423029.html
   600  func (self *SElasticcache) UpdateInstanceParameters(config jsonutils.JSONObject) error {
   601  	params := jsonutils.NewDict()
   602  	params.Set("redis_config", config)
   603  	err := DoUpdateWithSpec(self.region.ecsClient.Elasticcache.UpdateInContextWithSpec, self.GetId(), "configs", params)
   604  	if err != nil {
   605  		return errors.Wrap(err, "elasticcache.UpdateInstanceParameters")
   606  	}
   607  
   608  	return nil
   609  }
   610  
   611  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423033.html
   612  func (self *SElasticcache) CreateBackup(desc string) (cloudprovider.ICloudElasticcacheBackup, error) {
   613  	return nil, cloudprovider.ErrNotSupported
   614  }
   615  
   616  func backupPeriodTrans(config cloudprovider.SCloudElasticCacheBackupPolicyUpdateInput) *jsonutils.JSONArray {
   617  	segs := strings.Split(config.PreferredBackupPeriod, ",")
   618  	ret := jsonutils.NewArray()
   619  	for _, seg := range segs {
   620  		switch seg {
   621  		case "Monday":
   622  			ret.Add(jsonutils.NewString("1"))
   623  		case "Tuesday":
   624  			ret.Add(jsonutils.NewString("2"))
   625  		case "Wednesday":
   626  			ret.Add(jsonutils.NewString("3"))
   627  		case "Thursday":
   628  			ret.Add(jsonutils.NewString("4"))
   629  		case "Friday":
   630  			ret.Add(jsonutils.NewString("5"))
   631  		case "Saturday":
   632  			ret.Add(jsonutils.NewString("6"))
   633  		case "Sunday":
   634  			ret.Add(jsonutils.NewString("7"))
   635  		}
   636  	}
   637  
   638  	return ret
   639  }
   640  
   641  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423021.html
   642  func (self *SElasticcache) UpdateBackupPolicy(config cloudprovider.SCloudElasticCacheBackupPolicyUpdateInput) error {
   643  	params := jsonutils.NewDict()
   644  	policy := jsonutils.NewDict()
   645  	policy.Set("save_days", jsonutils.NewInt(int64(config.BackupReservedDays)))
   646  	policy.Set("backup_type", jsonutils.NewString(config.BackupType))
   647  	plan := jsonutils.NewDict()
   648  	backTime := strings.ReplaceAll(config.PreferredBackupTime, "Z", "")
   649  	backupPeriod := backupPeriodTrans(config)
   650  	plan.Set("begin_at", jsonutils.NewString(backTime))
   651  	plan.Set("period_type", jsonutils.NewString("weekly"))
   652  	plan.Set("backup_at", backupPeriod)
   653  	policy.Set("periodical_backup_plan", plan)
   654  	params.Set("instance_backup_policy", policy)
   655  	err := DoUpdateWithSpec(self.region.ecsClient.Elasticcache.UpdateInContextWithSpec, self.GetId(), "configs", params)
   656  	if err != nil {
   657  		return errors.Wrap(err, "elasticcache.UpdateInstanceParameters")
   658  	}
   659  
   660  	return nil
   661  }
   662  
   663  // https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423030.html
   664  // 当前版本,只有DCS2.0实例支持清空数据功能,即flush操作。
   665  func (self *SElasticcache) FlushInstance(input cloudprovider.SCloudElasticCacheFlushInstanceInput) error {
   666  	resp, err := self.region.ecsClient.Elasticcache.Flush(self.GetId())
   667  	if err != nil {
   668  		return errors.Wrap(err, "elasticcache.FlushInstance")
   669  	}
   670  
   671  	rets, err := resp.GetArray("results")
   672  	if err != nil {
   673  		return errors.Wrap(err, "elasticcache.FlushInstance")
   674  	}
   675  
   676  	for _, r := range rets {
   677  		if ret, _ := r.GetString("result"); ret != "success" {
   678  			return fmt.Errorf("elasticcache.FlushInstance failed")
   679  		}
   680  	}
   681  
   682  	return nil
   683  }
   684  
   685  // SElasticcacheAccount => ResetPassword
   686  func (self *SElasticcache) UpdateAuthMode(noPwdAccess bool, password string) error {
   687  	return cloudprovider.ErrNotSupported
   688  }
   689  
   690  func (self *SElasticcache) GetAuthMode() string {
   691  	switch self.NoPasswordAccess {
   692  	case "true":
   693  		return "off"
   694  	default:
   695  		return "on"
   696  	}
   697  }
   698  
   699  func (self *SElasticcache) GetSecurityGroupIds() ([]string, error) {
   700  	return nil, cloudprovider.ErrNotSupported
   701  }
   702  
   703  func (self *SElasticcache) GetICloudElasticcacheAccount(accountId string) (cloudprovider.ICloudElasticcacheAccount, error) {
   704  	accounts, err := self.GetICloudElasticcacheAccounts()
   705  	if err != nil {
   706  		return nil, errors.Wrap(err, "Elasticcache.GetICloudElasticcacheAccount.Accounts")
   707  	}
   708  
   709  	for i := range accounts {
   710  		account := accounts[i]
   711  		if account.GetGlobalId() == accountId {
   712  			return account, nil
   713  		}
   714  	}
   715  
   716  	return nil, cloudprovider.ErrNotFound
   717  }
   718  
   719  func (self *SElasticcache) GetICloudElasticcacheAcl(aclId string) (cloudprovider.ICloudElasticcacheAcl, error) {
   720  	return nil, cloudprovider.ErrNotSupported
   721  }
   722  
   723  func (self *SElasticcache) GetICloudElasticcacheBackup(backupId string) (cloudprovider.ICloudElasticcacheBackup, error) {
   724  	backups, err := self.GetICloudElasticcacheBackups()
   725  	if err != nil {
   726  		return nil, err
   727  	}
   728  
   729  	for _, backup := range backups {
   730  		if backup.GetId() == backupId {
   731  			return backup, nil
   732  		}
   733  	}
   734  
   735  	return nil, cloudprovider.ErrNotFound
   736  }
   737  
   738  func (instance *SElasticcache) SetTags(tags map[string]string, replace bool) error {
   739  	return cloudprovider.ErrNotImplemented
   740  }
   741  
   742  func (self *SElasticcache) UpdateSecurityGroups(secgroupIds []string) error {
   743  	return errors.Wrap(cloudprovider.ErrNotSupported, "UpdateSecurityGroups")
   744  }
   745  
   746  func (self *SElasticcache) Renew(bc billing.SBillingCycle) error {
   747  	return cloudprovider.ErrNotSupported
   748  }
   749  
   750  func (self *SElasticcache) SetAutoRenew(bc billing.SBillingCycle) error {
   751  	return cloudprovider.ErrNotSupported
   752  }