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