yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/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 apsara
    16  
    17  import (
    18  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  	"time"
    22  
    23  	"github.com/aokoli/goutils"
    24  	"github.com/pkg/errors"
    25  
    26  	"yunion.io/x/jsonutils"
    27  	"yunion.io/x/log"
    28  
    29  	billingapi "yunion.io/x/cloudmux/pkg/apis/billing"
    30  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    31  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    32  	"yunion.io/x/cloudmux/pkg/multicloud"
    33  	"yunion.io/x/onecloud/pkg/util/billing"
    34  )
    35  
    36  // https://help.apsara.com/document_detail/60933.html?spm=a2c4g.11186623.6.726.38f82ca9U1Gtxw
    37  type SElasticcache struct {
    38  	multicloud.SElasticcacheBase
    39  	multicloud.SBillingBase
    40  	ApsaraTags
    41  
    42  	region    *SRegion
    43  	attribute *SElasticcacheAttribute
    44  	netinfo   []SNetInfo
    45  
    46  	Config              string      `json:"Config"`
    47  	HasRenewChangeOrder bool        `json:"HasRenewChangeOrder"`
    48  	InstanceID          string      `json:"InstanceId"`
    49  	UserName            string      `json:"UserName"`
    50  	ArchitectureType    string      `json:"ArchitectureType"`
    51  	ZoneID              string      `json:"ZoneId"`
    52  	PrivateIP           string      `json:"PrivateIp"`
    53  	VSwitchID           string      `json:"VSwitchId"`
    54  	VpcID               string      `json:"VpcId"`
    55  	NetworkType         string      `json:"NetworkType"`
    56  	Qps                 int64       `json:"QPS"`
    57  	PackageType         string      `json:"PackageType"`
    58  	IsRDS               bool        `json:"IsRds"`
    59  	EngineVersion       string      `json:"EngineVersion"`
    60  	ConnectionDomain    string      `json:"ConnectionDomain"`
    61  	InstanceName        string      `json:"InstanceName"`
    62  	ReplacateID         string      `json:"ReplacateId"`
    63  	Bandwidth           int64       `json:"Bandwidth"`
    64  	ChargeType          TChargeType `json:"ChargeType"`
    65  	InstanceType        string      `json:"InstanceType"`
    66  	Tags                Tags        `json:"Tags"`
    67  	InstanceStatus      string      `json:"InstanceStatus"`
    68  	Port                int         `json:"Port"`
    69  	InstanceClass       string      `json:"InstanceClass"`
    70  	CreateTime          time.Time   `json:"CreateTime"`
    71  	EndTime             time.Time   `json:"EndTime"`
    72  	RegionID            string      `json:"RegionId"`
    73  	NodeType            string      `json:"NodeType"`
    74  	CapacityMB          int         `json:"Capacity"`
    75  	Connections         int64       `json:"Connections"`
    76  
    77  	DepartmentInfo
    78  }
    79  
    80  type SElasticcacheAttribute struct {
    81  	Config              string      `json:"Config"`
    82  	HasRenewChangeOrder string      `json:"HasRenewChangeOrder"`
    83  	InstanceID          string      `json:"InstanceId"`
    84  	ZoneID              string      `json:"ZoneId"`
    85  	ArchitectureType    string      `json:"ArchitectureType"`
    86  	PrivateIP           string      `json:"PrivateIp"`
    87  	VSwitchID           string      `json:"VSwitchId"`
    88  	Engine              string      `json:"Engine"`
    89  	VpcID               string      `json:"VpcId"`
    90  	NetworkType         string      `json:"NetworkType"`
    91  	Qps                 int64       `json:"QPS"`
    92  	PackageType         string      `json:"PackageType"`
    93  	ReplicaID           string      `json:"ReplicaId"`
    94  	IsRDS               bool        `json:"IsRds"`
    95  	MaintainStartTime   string      `json:"MaintainStartTime"`
    96  	VpcAuthMode         string      `json:"VpcAuthMode"`
    97  	ConnectionDomain    string      `json:"ConnectionDomain"`
    98  	EngineVersion       string      `json:"EngineVersion"`
    99  	InstanceName        string      `json:"InstanceName"`
   100  	Bandwidth           int64       `json:"Bandwidth"`
   101  	ChargeType          TChargeType `json:"ChargeType"`
   102  	AuditLogRetention   string      `json:"AuditLogRetention"`
   103  	MaintainEndTime     string      `json:"MaintainEndTime"`
   104  	ReplicationMode     string      `json:"ReplicationMode"`
   105  	InstanceType        string      `json:"InstanceType"`
   106  	InstanceStatus      string      `json:"InstanceStatus"`
   107  	Tags                Tags        `json:"Tags"`
   108  	Port                int64       `json:"Port"`
   109  	InstanceClass       string      `json:"InstanceClass"`
   110  	CreateTime          time.Time   `json:"CreateTime"`
   111  	NodeType            string      `json:"NodeType"`
   112  	RegionID            string      `json:"RegionId"`
   113  	AvailabilityValue   string      `json:"AvailabilityValue"`
   114  	CapacityMB          int         `json:"Capacity"`
   115  	Connections         int64       `json:"Connections"`
   116  	SecurityIPList      string      `json:"SecurityIPList"`
   117  }
   118  
   119  type SNetInfo struct {
   120  	ConnectionString  string  `json:"ConnectionString"`
   121  	Port              string  `json:"Port"`
   122  	DBInstanceNetType string  `json:"DBInstanceNetType"`
   123  	VPCID             string  `json:"VPCId"`
   124  	VPCInstanceID     string  `json:"VPCInstanceId"`
   125  	IPAddress         string  `json:"IPAddress"`
   126  	IPType            string  `json:"IPType"`
   127  	Upgradeable       string  `json:"Upgradeable"`
   128  	ExpiredTime       *string `json:"ExpiredTime,omitempty"`
   129  }
   130  
   131  func (self *SElasticcache) GetId() string {
   132  	return self.InstanceID
   133  }
   134  
   135  func (self *SElasticcache) GetName() string {
   136  	return self.InstanceName
   137  }
   138  
   139  func (self *SElasticcache) GetGlobalId() string {
   140  	return self.GetId()
   141  }
   142  
   143  func (self *SElasticcache) GetStatus() string {
   144  	switch self.InstanceStatus {
   145  	case "Normal":
   146  		return api.ELASTIC_CACHE_STATUS_RUNNING
   147  	case "Creating":
   148  		return api.ELASTIC_CACHE_STATUS_DEPLOYING
   149  	case "Changing":
   150  		return api.ELASTIC_CACHE_STATUS_CHANGING
   151  	case "Inactive":
   152  		return api.ELASTIC_CACHE_STATUS_INACTIVE
   153  	case "Flushing":
   154  		return api.ELASTIC_CACHE_STATUS_FLUSHING
   155  	case "Released":
   156  		return api.ELASTIC_CACHE_STATUS_RELEASED
   157  	case "Transforming":
   158  		return api.ELASTIC_CACHE_STATUS_TRANSFORMING
   159  	case "Unavailable":
   160  		return api.ELASTIC_CACHE_STATUS_UNAVAILABLE
   161  	case "Error":
   162  		return api.ELASTIC_CACHE_STATUS_ERROR
   163  	case "Migrating":
   164  		return api.ELASTIC_CACHE_STATUS_MIGRATING
   165  	case "BackupRecovering":
   166  		return api.ELASTIC_CACHE_STATUS_BACKUPRECOVERING
   167  	case "MinorVersionUpgrading":
   168  		return api.ELASTIC_CACHE_STATUS_MINORVERSIONUPGRADING
   169  	case "NetworkModifying":
   170  		return api.ELASTIC_CACHE_STATUS_NETWORKMODIFYING
   171  	case "SSLModifying":
   172  		return api.ELASTIC_CACHE_STATUS_SSLMODIFYING
   173  	case "MajorVersionUpgrading":
   174  		return api.ELASTIC_CACHE_STATUS_MAJORVERSIONUPGRADING
   175  	default:
   176  		return api.ELASTIC_CACHE_STATUS_MAJORVERSIONUPGRADING
   177  	}
   178  }
   179  
   180  func (self *SElasticcache) Refresh() error {
   181  	cache, err := self.region.GetElasticCacheById(self.GetId())
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	err = jsonutils.Update(self, cache)
   187  	if err != nil {
   188  		return err
   189  	}
   190  
   191  	return nil
   192  }
   193  
   194  func (self *SElasticcache) GetBillingType() string {
   195  	return convertChargeType(self.ChargeType)
   196  }
   197  
   198  func (self *SElasticcache) GetCreatedAt() time.Time {
   199  	return self.CreateTime
   200  }
   201  
   202  func (self *SElasticcache) GetExpiredAt() time.Time {
   203  	return convertExpiredAt(self.EndTime)
   204  }
   205  
   206  func (self *SElasticcache) GetInstanceType() string {
   207  	return self.InstanceClass
   208  }
   209  
   210  func (self *SElasticcache) GetCapacityMB() int {
   211  	return self.CapacityMB
   212  }
   213  
   214  func (self *SElasticcache) GetArchType() string {
   215  	switch self.ArchitectureType {
   216  	case "rwsplit":
   217  		return api.ELASTIC_CACHE_ARCH_TYPE_RWSPLIT
   218  	case "cluster":
   219  		return api.ELASTIC_CACHE_ARCH_TYPE_CLUSTER
   220  	case "standard":
   221  		if self.NodeType == "single" {
   222  			return api.ELASTIC_CACHE_ARCH_TYPE_SINGLE
   223  		} else if self.NodeType == "double" {
   224  			return api.ELASTIC_CACHE_ARCH_TYPE_MASTER
   225  		}
   226  	}
   227  
   228  	return ""
   229  }
   230  
   231  func (self *SElasticcache) GetNodeType() string {
   232  	return self.NodeType
   233  }
   234  
   235  func (self *SElasticcache) GetEngine() string {
   236  	return self.InstanceType
   237  }
   238  
   239  func (self *SElasticcache) GetEngineVersion() string {
   240  	return self.EngineVersion
   241  }
   242  
   243  func (self *SElasticcache) GetVpcId() string {
   244  	return self.VpcID
   245  }
   246  
   247  func (self *SElasticcache) GetZoneId() string {
   248  	zone, err := self.region.getZoneById(self.ZoneID)
   249  	if err != nil {
   250  		log.Errorf("failed to find zone for elasticcache %s error: %v", self.GetId(), err)
   251  		return ""
   252  	}
   253  	return zone.GetGlobalId()
   254  }
   255  
   256  func (self *SElasticcache) GetNetworkType() string {
   257  	switch self.NetworkType {
   258  	case "VPC":
   259  		return api.LB_NETWORK_TYPE_VPC
   260  	case "CLASSIC":
   261  		return api.LB_NETWORK_TYPE_CLASSIC
   262  	default:
   263  		return api.LB_NETWORK_TYPE_VPC
   264  	}
   265  }
   266  
   267  func (self *SElasticcache) GetNetworkId() string {
   268  	return self.VSwitchID
   269  }
   270  
   271  func (self *SElasticcache) GetPrivateDNS() string {
   272  	return self.ConnectionDomain
   273  }
   274  
   275  func (self *SElasticcache) GetPrivateIpAddr() string {
   276  	return self.PrivateIP
   277  }
   278  
   279  func (self *SElasticcache) GetPrivateConnectPort() int {
   280  	return self.Port
   281  }
   282  
   283  func (self *SElasticcache) Renew(bc billing.SBillingCycle) error {
   284  	return cloudprovider.ErrNotSupported
   285  }
   286  
   287  func (self *SElasticcache) GetPublicDNS() string {
   288  	pub, err := self.GetPublicNetInfo()
   289  	if err != nil {
   290  		log.Errorf("SElasticcache.GetPublicDNS %s", err)
   291  		return ""
   292  	}
   293  
   294  	if pub != nil {
   295  		return pub.ConnectionString
   296  	}
   297  
   298  	return ""
   299  }
   300  
   301  func (self *SElasticcache) GetPublicIpAddr() string {
   302  	pub, err := self.GetPublicNetInfo()
   303  	if err != nil {
   304  		log.Errorf("SElasticcache.GetPublicIpAddr %s", err)
   305  	}
   306  
   307  	if pub != nil {
   308  		return pub.IPAddress
   309  	}
   310  
   311  	return ""
   312  }
   313  
   314  func (self *SElasticcache) GetPublicConnectPort() int {
   315  	pub, err := self.GetPublicNetInfo()
   316  	if err != nil {
   317  		log.Errorf("SElasticcache.GetPublicConnectPort %s", err)
   318  	}
   319  
   320  	if pub != nil {
   321  		port, _ := strconv.Atoi(pub.Port)
   322  		return port
   323  	}
   324  
   325  	return 0
   326  }
   327  
   328  func (self *SElasticcache) GetMaintainStartTime() string {
   329  	attr, err := self.GetAttribute()
   330  	if err != nil {
   331  		log.Errorf("SElasticcache.GetMaintainStartTime %s", err)
   332  	}
   333  
   334  	if attr != nil {
   335  		return attr.MaintainStartTime
   336  	}
   337  
   338  	return ""
   339  }
   340  
   341  func (self *SElasticcache) GetMaintainEndTime() string {
   342  	attr, err := self.GetAttribute()
   343  	if err != nil {
   344  		log.Errorf("SElasticcache.GetMaintainEndTime %s", err)
   345  	}
   346  
   347  	if attr != nil {
   348  		return attr.MaintainEndTime
   349  	}
   350  
   351  	return ""
   352  }
   353  
   354  func (self *SElasticcache) GetICloudElasticcacheAccounts() ([]cloudprovider.ICloudElasticcacheAccount, error) {
   355  	accounts, err := self.region.GetElasticCacheAccounts(self.GetId())
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  
   360  	iaccounts := make([]cloudprovider.ICloudElasticcacheAccount, len(accounts))
   361  	for i := range accounts {
   362  		accounts[i].cacheDB = self
   363  		iaccounts[i] = &accounts[i]
   364  	}
   365  
   366  	return iaccounts, nil
   367  }
   368  
   369  func (self *SElasticcache) GetICloudElasticcacheAccountByName(accountName string) (cloudprovider.ICloudElasticcacheAccount, error) {
   370  	account, err := self.region.GetElasticCacheAccountByName(self.GetId(), accountName)
   371  	if err != nil {
   372  		return nil, err
   373  	}
   374  
   375  	account.cacheDB = self
   376  	return account, nil
   377  }
   378  
   379  func (self *SElasticcache) GetICloudElasticcacheAcls() ([]cloudprovider.ICloudElasticcacheAcl, error) {
   380  	acls, err := self.region.GetElasticCacheAcls(self.GetId())
   381  	if err != nil {
   382  		return nil, err
   383  	}
   384  
   385  	iacls := make([]cloudprovider.ICloudElasticcacheAcl, len(acls))
   386  	for i := range acls {
   387  		acls[i].cacheDB = self
   388  		iacls[i] = &acls[i]
   389  	}
   390  
   391  	return iacls, nil
   392  }
   393  
   394  func (self *SElasticcache) GetICloudElasticcacheBackups() ([]cloudprovider.ICloudElasticcacheBackup, error) {
   395  	start := self.CreateTime.Format("2006-01-02T15:04Z")
   396  	end := time.Now().Format("2006-01-02T15:04Z")
   397  	backups, err := self.region.GetElasticCacheBackups(self.GetId(), start, end)
   398  	if err != nil {
   399  		return nil, err
   400  	}
   401  
   402  	ibackups := make([]cloudprovider.ICloudElasticcacheBackup, len(backups))
   403  	for i := range backups {
   404  		backups[i].cacheDB = self
   405  		ibackups[i] = &backups[i]
   406  	}
   407  
   408  	return ibackups, nil
   409  }
   410  
   411  func (self *SElasticcache) GetICloudElasticcacheParameters() ([]cloudprovider.ICloudElasticcacheParameter, error) {
   412  	parameters, err := self.region.GetElasticCacheParameters(self.GetId())
   413  	if err != nil {
   414  		return nil, err
   415  	}
   416  
   417  	iparameters := make([]cloudprovider.ICloudElasticcacheParameter, len(parameters))
   418  	for i := range parameters {
   419  		parameters[i].cacheDB = self
   420  		iparameters[i] = &parameters[i]
   421  	}
   422  
   423  	return iparameters, nil
   424  }
   425  
   426  func (self *SElasticcache) GetAttribute() (*SElasticcacheAttribute, error) {
   427  	if self.attribute != nil {
   428  		return self.attribute, nil
   429  	}
   430  
   431  	params := make(map[string]string)
   432  	params["RegionId"] = self.region.RegionId
   433  	params["InstanceId"] = self.GetId()
   434  
   435  	rets := []SElasticcacheAttribute{}
   436  	err := DoListAll(self.region.kvsRequest, "DescribeInstanceAttribute", params, []string{"Instances", "DBInstanceAttribute"}, &rets)
   437  	if err != nil {
   438  		return nil, errors.Wrap(err, "elasticcache.GetAttribute")
   439  	}
   440  
   441  	count := len(rets)
   442  	if count >= 1 {
   443  		self.attribute = &rets[0]
   444  		return self.attribute, nil
   445  	} else {
   446  		return nil, errors.Wrapf(cloudprovider.ErrNotFound, "elasticcache.GetAttribute %s", self.GetId())
   447  	}
   448  }
   449  
   450  func (self *SElasticcache) GetNetInfo() ([]SNetInfo, error) {
   451  	params := make(map[string]string)
   452  	params["RegionId"] = self.region.RegionId
   453  	params["InstanceId"] = self.GetId()
   454  
   455  	rets := []SNetInfo{}
   456  	err := DoListAll(self.region.kvsRequest, "DescribeDBInstanceNetInfo", params, []string{"NetInfoItems", "InstanceNetInfo"}, &rets)
   457  	if err != nil {
   458  		return nil, errors.Wrap(err, "elasticcache.GetNetInfo")
   459  	}
   460  
   461  	self.netinfo = rets
   462  	return self.netinfo, nil
   463  }
   464  
   465  // https://help.apsara.com/document_detail/66742.html?spm=a2c4g.11186623.6.731.54c123d2P02qhk
   466  func (self *SElasticcache) GetPublicNetInfo() (*SNetInfo, error) {
   467  	nets, err := self.GetNetInfo()
   468  	if err != nil {
   469  		return nil, err
   470  	}
   471  
   472  	for i := range nets {
   473  		if nets[i].IPType == "Public" {
   474  			return &nets[i], nil
   475  		}
   476  	}
   477  
   478  	return nil, nil
   479  }
   480  
   481  func (self *SRegion) GetElasticCaches(instanceIds []string) ([]SElasticcache, error) {
   482  	params := make(map[string]string)
   483  	params["RegionId"] = self.RegionId
   484  	if instanceIds != nil && len(instanceIds) > 0 {
   485  		params["InstanceIds"] = strings.Join(instanceIds, ",")
   486  	}
   487  
   488  	ret := []SElasticcache{}
   489  	err := DoListAll(self.kvsRequest, "DescribeInstances", params, []string{"Instances", "KVStoreInstance"}, &ret)
   490  	if err != nil {
   491  		return nil, errors.Wrap(err, "region.GetElasticCaches")
   492  	}
   493  
   494  	for i := range ret {
   495  		ret[i].region = self
   496  	}
   497  
   498  	return ret, nil
   499  }
   500  
   501  func (self *SRegion) GetElasticCacheById(instanceId string) (*SElasticcache, error) {
   502  	caches, err := self.GetElasticCaches([]string{instanceId})
   503  	if err != nil {
   504  		return nil, errors.Wrapf(err, "region.GetElasticCacheById %s", instanceId)
   505  	}
   506  
   507  	if len(caches) == 1 {
   508  		return &caches[0], nil
   509  	} else if len(caches) == 0 {
   510  		return nil, cloudprovider.ErrNotFound
   511  	} else {
   512  		return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "region.GetElasticCacheById %s.expect 1 found %d ", instanceId, len(caches))
   513  	}
   514  }
   515  
   516  func (self *SRegion) GetIElasticcacheById(id string) (cloudprovider.ICloudElasticcache, error) {
   517  	ec, err := self.GetElasticCacheById(id)
   518  	if err != nil {
   519  		return nil, err
   520  	}
   521  
   522  	return ec, nil
   523  }
   524  
   525  // https://help.apsara.com/document_detail/95802.html?spm=a2c4g.11186623.6.746.143e782f3Pfkfg
   526  func (self *SRegion) GetElasticCacheAccounts(instanceId string) ([]SElasticcacheAccount, error) {
   527  	params := make(map[string]string)
   528  	params["RegionId"] = self.RegionId
   529  	params["InstanceId"] = instanceId
   530  
   531  	ret := []SElasticcacheAccount{}
   532  	err := DoListAll(self.kvsRequest, "DescribeAccounts", params, []string{"Accounts", "Account"}, &ret)
   533  	if err != nil {
   534  		return nil, errors.Wrap(err, "region.GetElasticCacheAccounts")
   535  	}
   536  
   537  	return ret, nil
   538  }
   539  
   540  func (self *SRegion) GetElasticCacheAccountByName(instanceId string, accountName string) (*SElasticcacheAccount, error) {
   541  	params := make(map[string]string)
   542  	params["RegionId"] = self.RegionId
   543  	params["InstanceId"] = instanceId
   544  	params["AccountName"] = accountName
   545  
   546  	ret := []SElasticcacheAccount{}
   547  	err := DoListAll(self.kvsRequest, "DescribeAccounts", params, []string{"Accounts", "Account"}, &ret)
   548  	if err != nil {
   549  		return nil, errors.Wrap(err, "region.GetElasticCacheAccounts")
   550  	}
   551  
   552  	if len(ret) == 1 {
   553  		return &ret[0], nil
   554  	} else if len(ret) == 0 {
   555  		return nil, cloudprovider.ErrNotFound
   556  	} else {
   557  		return nil, errors.Wrap(fmt.Errorf("%d account with name %s found", len(ret), accountName), "region.GetElasticCacheAccountByName")
   558  	}
   559  }
   560  
   561  // https://help.apsara.com/document_detail/63889.html?spm=a2c4g.11186623.6.764.3cb43852R7lnoS
   562  func (self *SRegion) GetElasticCacheAcls(instanceId string) ([]SElasticcacheAcl, error) {
   563  	params := make(map[string]string)
   564  	params["RegionId"] = self.RegionId
   565  	params["InstanceId"] = instanceId
   566  
   567  	ret := []SElasticcacheAcl{}
   568  	err := DoListAll(self.kvsRequest, "DescribeSecurityIps", params, []string{"SecurityIpGroups", "SecurityIpGroup"}, &ret)
   569  	if err != nil {
   570  		return nil, errors.Wrap(err, "region.GetElasticCacheAcls")
   571  	}
   572  
   573  	return ret, nil
   574  }
   575  
   576  // https://help.apsara.com/document_detail/61081.html?spm=a2c4g.11186623.6.754.10613852qAbEQV
   577  func (self *SRegion) GetElasticCacheBackups(instanceId, startTime, endTime string) ([]SElasticcacheBackup, error) {
   578  	params := make(map[string]string)
   579  	params["RegionId"] = self.RegionId
   580  	params["InstanceId"] = instanceId
   581  	params["StartTime"] = startTime
   582  	params["EndTime"] = endTime
   583  
   584  	ret := []SElasticcacheBackup{}
   585  	err := DoListAll(self.kvsRequest, "DescribeBackups", params, []string{"Backups", "Backup"}, &ret)
   586  	if err != nil {
   587  		return nil, errors.Wrap(err, "region.GetElasticCacheBackups")
   588  	}
   589  
   590  	return ret, nil
   591  }
   592  
   593  // https://help.apsara.com/document_detail/93078.html?spm=a2c4g.11186623.6.769.58011975YYL5Gl
   594  func (self *SRegion) GetElasticCacheParameters(instanceId string) ([]SElasticcacheParameter, error) {
   595  	params := make(map[string]string)
   596  	params["RegionId"] = self.RegionId
   597  	params["DBInstanceId"] = instanceId
   598  
   599  	ret := []SElasticcacheParameter{}
   600  	err := DoListAll(self.kvsRequest, "DescribeParameters", params, []string{"RunningParameters", "Parameter"}, &ret)
   601  	if err != nil {
   602  		return nil, errors.Wrap(err, "region.GetElasticCacheParameters")
   603  	}
   604  
   605  	return ret, nil
   606  }
   607  
   608  // https://help.apsara.com/document_detail/60873.html?spm=a2c4g.11174283.6.715.7412dce0qSYemb
   609  func (self *SRegion) CreateIElasticcaches(ec *cloudprovider.SCloudElasticCacheInput) (cloudprovider.ICloudElasticcache, error) {
   610  	params := make(map[string]string)
   611  	params["RegionId"] = self.RegionId
   612  	params["InstanceClass"] = ec.InstanceType
   613  	params["InstanceName"] = ec.InstanceName
   614  	params["InstanceType"] = ec.Engine
   615  	params["EngineVersion"] = ec.EngineVersion
   616  
   617  	if len(ec.Password) > 0 {
   618  		params["UserName"] = ec.UserName
   619  		params["Password"] = ec.Password
   620  	}
   621  
   622  	if len(ec.ZoneIds) > 0 {
   623  		params["ZoneId"] = ec.ZoneIds[0]
   624  	}
   625  
   626  	if len(ec.PrivateIpAddress) > 0 {
   627  		params["PrivateIpAddress"] = ec.PrivateIpAddress
   628  	}
   629  
   630  	if len(ec.NodeType) > 0 {
   631  		params["NodeType"] = ec.NodeType
   632  	}
   633  
   634  	if len(ec.ProjectId) > 0 {
   635  		params["ResourceGroupId"] = ec.ProjectId
   636  	}
   637  
   638  	params["NetworkType"] = ec.NetworkType
   639  	params["VpcId"] = ec.VpcId
   640  	params["VSwitchId"] = ec.NetworkId
   641  	params["ChargeType"] = ec.ChargeType
   642  	if strings.ToLower(ec.ChargeType) == billingapi.BILLING_TYPE_PREPAID && ec.BillingCycle != nil {
   643  		if ec.BillingCycle.GetMonths() >= 1 && ec.BillingCycle.GetMonths() <= 9 {
   644  			params["Period"] = strconv.Itoa(ec.BillingCycle.GetMonths())
   645  		} else if ec.BillingCycle.GetMonths() == 12 || ec.BillingCycle.GetMonths() == 24 || ec.BillingCycle.GetMonths() == 36 {
   646  			params["Period"] = strconv.Itoa(ec.BillingCycle.GetMonths())
   647  		} else {
   648  			return nil, fmt.Errorf("region.CreateIElasticcaches invalid billing cycle.reqired month (1~9) or  year(1~3)")
   649  		}
   650  	}
   651  
   652  	ret := &SElasticcache{}
   653  	err := DoAction(self.kvsRequest, "CreateInstance", params, []string{}, ret)
   654  	if err != nil {
   655  		return nil, errors.Wrap(err, "region.CreateIElasticcaches")
   656  	}
   657  	self.SetResourceTags("kvs", "INSTANCE", []string{ret.InstanceID}, ec.Tags, false)
   658  
   659  	ret.region = self
   660  	return ret, nil
   661  }
   662  
   663  // https://help.apsara.com/document_detail/116215.html?spm=a2c4g.11174283.6.736.6b9ddce0c5nsw6
   664  func (self *SElasticcache) Restart() error {
   665  	params := make(map[string]string)
   666  	params["InstanceId"] = self.GetId()
   667  	params["EffectiveTime"] = "0" // 立即重启
   668  
   669  	err := DoAction(self.region.kvsRequest, "RestartInstance", params, nil, nil)
   670  	if err != nil {
   671  		return errors.Wrap(err, "elasticcache.Restart")
   672  	}
   673  
   674  	return nil
   675  }
   676  
   677  // https://help.apsara.com/document_detail/60898.html?spm=a2c4g.11186623.6.713.56ec1603KS0xA0
   678  func (self *SElasticcache) Delete() error {
   679  	params := make(map[string]string)
   680  	params["InstanceId"] = self.GetId()
   681  
   682  	err := DoAction(self.region.kvsRequest, "DeleteInstance", params, nil, nil)
   683  	if err != nil {
   684  		return errors.Wrap(err, "elasticcache.Delete")
   685  	}
   686  
   687  	return nil
   688  }
   689  
   690  // https://help.apsara.com/document_detail/60903.html?spm=a2c4g.11186623.6.711.3f062c92aRJNfw
   691  func (self *SElasticcache) ChangeInstanceSpec(spec string) error {
   692  	params := make(map[string]string)
   693  	params["InstanceId"] = self.GetId()
   694  	params["InstanceClass"] = strings.Split(spec, ":")[0]
   695  	params["AutoPay"] = "true" // 自动付款
   696  
   697  	err := DoAction(self.region.kvsRequest, "ModifyInstanceSpec", params, nil, nil)
   698  	if err != nil {
   699  		return errors.Wrap(err, "elasticcache.ChangeInstanceSpec")
   700  	}
   701  
   702  	return nil
   703  }
   704  
   705  // https://help.apsara.com/document_detail/61000.html?spm=a2c4g.11186623.6.730.57d66cb0QlQS86
   706  func (self *SElasticcache) SetMaintainTime(maintainStartTime, maintainEndTime string) error {
   707  	params := make(map[string]string)
   708  	params["InstanceId"] = self.GetId()
   709  	params["MaintainStartTime"] = maintainStartTime
   710  	params["MaintainEndTime"] = maintainEndTime
   711  
   712  	err := DoAction(self.region.kvsRequest, "ModifyInstanceMaintainTime", params, nil, nil)
   713  	if err != nil {
   714  		return errors.Wrap(err, "elasticcache.SetMaintainTime")
   715  	}
   716  
   717  	return nil
   718  }
   719  
   720  // https://help.apsara.com/document_detail/125795.html?spm=a2c4g.11186623.6.719.51542b3593cDKO
   721  func (self *SElasticcache) AllocatePublicConnection(port int) (string, error) {
   722  	if port < 1024 {
   723  		port = 6379
   724  	}
   725  
   726  	suffix, _ := goutils.RandomAlphabetic(4)
   727  	conn := self.GetId() + strings.ToLower(suffix)
   728  
   729  	params := make(map[string]string)
   730  	params["InstanceId"] = self.GetId()
   731  	params["Port"] = strconv.Itoa(port)
   732  	params["ConnectionStringPrefix"] = conn
   733  
   734  	err := DoAction(self.region.kvsRequest, "AllocateInstancePublicConnection", params, nil, nil)
   735  	if err != nil {
   736  		return "", errors.Wrap(err, "elasticcache.AllocatePublicConnection")
   737  	}
   738  
   739  	return conn, nil
   740  }
   741  
   742  // https://help.apsara.com/document_detail/125796.html?spm=a2c4g.11186623.6.720.702a3b23Qayopy
   743  func (self *SElasticcache) ReleasePublicConnection() error {
   744  	publicConn := self.GetPublicDNS()
   745  	if len(publicConn) == 0 {
   746  		log.Debugf("elasticcache.ReleasePublicConnection public connect is empty")
   747  		return nil
   748  	}
   749  
   750  	params := make(map[string]string)
   751  	params["InstanceId"] = self.GetId()
   752  	params["CurrentConnectionString"] = publicConn
   753  
   754  	err := DoAction(self.region.kvsRequest, "ReleaseInstancePublicConnection", params, nil, nil)
   755  	if err != nil {
   756  		return errors.Wrap(err, "elasticcache.ReleasePublicConnection")
   757  	}
   758  
   759  	return nil
   760  }
   761  
   762  // https://help.apsara.com/document_detail/93603.html?spm=a2c4g.11186623.6.732.10666cf9UVgNPb 修改链接地址
   763  
   764  // https://help.apsara.com/document_detail/95973.html?spm=a2c4g.11186623.6.742.4698126aH0s4Q5
   765  func (self *SElasticcache) CreateAccount(input cloudprovider.SCloudElasticCacheAccountInput) (cloudprovider.ICloudElasticcacheAccount, error) {
   766  	params := make(map[string]string)
   767  	params["InstanceId"] = self.GetId()
   768  	params["AccountName"] = input.AccountName
   769  	params["AccountPassword"] = input.AccountPassword
   770  	if len(input.AccountPrivilege) > 0 {
   771  		params["AccountPrivilege"] = input.AccountPrivilege
   772  	}
   773  
   774  	if len(input.Description) > 0 {
   775  		params["AccountDescription"] = input.Description
   776  	}
   777  
   778  	err := DoAction(self.region.kvsRequest, "CreateAccount", params, nil, nil)
   779  	if err != nil {
   780  		return nil, errors.Wrap(err, "elasticcache.CreateAccount")
   781  	}
   782  
   783  	return self.GetICloudElasticcacheAccountByName(input.AccountName)
   784  }
   785  
   786  func (self *SElasticcache) CreateAcl(aclName, securityIps string) (cloudprovider.ICloudElasticcacheAcl, error) {
   787  	acl := &SElasticcacheAcl{}
   788  	acl.cacheDB = self
   789  	acl.SecurityIPGroupName = aclName
   790  	acl.SecurityIPList = securityIps
   791  	return acl, self.region.createAcl(self.GetId(), aclName, securityIps)
   792  }
   793  
   794  // https://help.apsara.com/document_detail/61113.html?spm=a2c4g.11186623.6.770.16a61e7admr0xy
   795  func (self *SElasticcache) UpdateInstanceParameters(config jsonutils.JSONObject) error {
   796  	params := make(map[string]string)
   797  	params["InstanceId"] = self.GetId()
   798  	params["Config"] = config.String()
   799  
   800  	err := DoAction(self.region.kvsRequest, "ModifyInstanceConfig", params, nil, nil)
   801  	if err != nil {
   802  		return errors.Wrap(err, "elasticcache.UpdateInstanceParameters")
   803  	}
   804  
   805  	return nil
   806  }
   807  
   808  // https://help.apsara.com/document_detail/61075.html?spm=a2c4g.11186623.6.749.4cba126a2U9xNa
   809  func (self *SElasticcache) CreateBackup(desc string) (cloudprovider.ICloudElasticcacheBackup, error) {
   810  	params := make(map[string]string)
   811  	params["InstanceId"] = self.GetId()
   812  
   813  	// 目前没有查询备份ID的接口,因此,备份ID没什么用
   814  	err := DoAction(self.region.kvsRequest, "CreateBackup", params, []string{"BackupJobID"}, nil)
   815  	if err != nil {
   816  		return nil, errors.Wrap(err, "elasticcache.CreateBackup")
   817  	}
   818  
   819  	return nil, nil
   820  }
   821  
   822  // https://help.apsara.com/document_detail/61077.html?spm=a2c4g.11186623.6.750.3d7630be7ziUfg
   823  func (self *SElasticcache) UpdateBackupPolicy(config cloudprovider.SCloudElasticCacheBackupPolicyUpdateInput) error {
   824  	params := make(map[string]string)
   825  	params["InstanceId"] = self.GetId()
   826  	params["PreferredBackupPeriod"] = config.PreferredBackupPeriod
   827  	params["PreferredBackupTime"] = config.PreferredBackupTime
   828  
   829  	err := DoAction(self.region.kvsRequest, "ModifyBackupPolicy", params, nil, nil)
   830  	if err != nil {
   831  		return errors.Wrap(err, "elasticcache.UpdateBackupPolicy")
   832  	}
   833  
   834  	return nil
   835  }
   836  
   837  // https://help.apsara.com/document_detail/60931.html?spm=a2c4g.11186623.6.728.5c57292920UKx3
   838  func (self *SElasticcache) FlushInstance(input cloudprovider.SCloudElasticCacheFlushInstanceInput) error {
   839  	params := make(map[string]string)
   840  	params["InstanceId"] = self.GetId()
   841  
   842  	err := DoAction(self.region.kvsRequest, "FlushInstance", params, nil, nil)
   843  	if err != nil {
   844  		return errors.Wrap(err, "elasticcache.FlushInstance")
   845  	}
   846  
   847  	return nil
   848  }
   849  
   850  // https://help.apsara.com/document_detail/98531.html?spm=5176.11065259.1996646101.searchclickresult.4df474c38Sc2SO
   851  func (self *SElasticcache) UpdateAuthMode(noPwdAccess bool, password string) error {
   852  	params := make(map[string]string)
   853  	params["InstanceId"] = self.GetId()
   854  	if noPwdAccess {
   855  		params["VpcAuthMode"] = "Close"
   856  	} else {
   857  		params["VpcAuthMode"] = "Open"
   858  	}
   859  
   860  	err := DoAction(self.region.kvsRequest, "ModifyInstanceVpcAuthMode", params, nil, nil)
   861  	if err != nil {
   862  		return errors.Wrap(err, "elasticcacheAccount.UpdateAuthMode")
   863  	}
   864  
   865  	return nil
   866  }
   867  
   868  func (self *SElasticcache) GetAuthMode() string {
   869  	attribute, err := self.GetAttribute()
   870  	if err != nil {
   871  		log.Errorf("elasticcache.GetAuthMode %s", err)
   872  	}
   873  	switch attribute.VpcAuthMode {
   874  	case "Open":
   875  		return "on"
   876  	default:
   877  		return "off"
   878  	}
   879  }
   880  
   881  func (self *SElasticcache) GetSecurityGroupIds() ([]string, error) {
   882  	return nil, cloudprovider.ErrNotSupported
   883  }
   884  
   885  func (self *SElasticcache) GetICloudElasticcacheAccount(accountId string) (cloudprovider.ICloudElasticcacheAccount, error) {
   886  	segs := strings.Split(accountId, "/")
   887  	if len(segs) < 2 {
   888  		return nil, errors.Wrap(fmt.Errorf("%s", accountId), "elasticcache.GetICloudElasticcacheAccount invalid account id ")
   889  	}
   890  
   891  	return self.GetICloudElasticcacheAccountByName(segs[1])
   892  }
   893  
   894  func (self *SElasticcache) GetICloudElasticcacheAcl(aclId string) (cloudprovider.ICloudElasticcacheAcl, error) {
   895  	acls, err := self.GetICloudElasticcacheAcls()
   896  	if err != nil {
   897  		return nil, err
   898  	}
   899  
   900  	for _, acl := range acls {
   901  		if acl.GetId() == aclId {
   902  			return acl, nil
   903  		}
   904  	}
   905  
   906  	return nil, cloudprovider.ErrNotFound
   907  }
   908  
   909  func (self *SElasticcache) GetICloudElasticcacheBackup(backupId string) (cloudprovider.ICloudElasticcacheBackup, error) {
   910  	backups, err := self.GetICloudElasticcacheBackups()
   911  	if err != nil {
   912  		return nil, err
   913  	}
   914  
   915  	for _, backup := range backups {
   916  		if backup.GetId() == backupId {
   917  			return backup, nil
   918  		}
   919  	}
   920  
   921  	return nil, cloudprovider.ErrNotFound
   922  }
   923  
   924  func (instance *SElasticcache) GetTags() (map[string]string, error) {
   925  	tags, err := instance.region.ListResourceTags("kvs", "INSTANCE", []string{instance.GetId()})
   926  	if err != nil {
   927  		return nil, errors.Wrap(err, "instance.region.ListResourceTags")
   928  	}
   929  	if _, ok := tags[instance.GetId()]; !ok {
   930  		return map[string]string{}, nil
   931  	}
   932  	return *tags[instance.GetId()], nil
   933  }
   934  
   935  func (instance *SElasticcache) SetTags(tags map[string]string, replace bool) error {
   936  	return instance.region.SetResourceTags(APSARA_PRODUCT_KVSTORE, "INSTANCE", []string{instance.GetId()}, tags, replace)
   937  }
   938  
   939  func (self *SElasticcache) UpdateSecurityGroups(secgroupIds []string) error {
   940  	return errors.Wrap(cloudprovider.ErrNotSupported, "UpdateSecurityGroups")
   941  }