yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/elasticache_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 aws
    16  
    17  import (
    18  	"strconv"
    19  	"strings"
    20  	"time"
    21  
    22  	"github.com/aws/aws-sdk-go/aws/awserr"
    23  	"github.com/aws/aws-sdk-go/service/elasticache"
    24  
    25  	"yunion.io/x/jsonutils"
    26  	"yunion.io/x/log"
    27  	"yunion.io/x/pkg/errors"
    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  func (region *SRegion) DescribeElasticacheReplicationGroups(Id string) ([]*elasticache.ReplicationGroup, error) {
    37  	ecClient, err := region.getAwsElasticacheClient()
    38  	if err != nil {
    39  		return nil, errors.Wrap(err, "client.getAwsElasticacheClient")
    40  	}
    41  
    42  	input := elasticache.DescribeReplicationGroupsInput{}
    43  
    44  	replicaGroup := []*elasticache.ReplicationGroup{}
    45  
    46  	marker := ""
    47  	maxrecords := (int64)(100)
    48  	input.MaxRecords = &maxrecords
    49  
    50  	if len(Id) > 0 {
    51  		input.ReplicationGroupId = &Id
    52  	}
    53  
    54  	for {
    55  		if len(marker) >= 0 {
    56  			input.Marker = &marker
    57  		}
    58  		out, err := ecClient.DescribeReplicationGroups(&input)
    59  		if err != nil {
    60  			if e, ok := err.(awserr.Error); ok && e.Code() == "ReplicationGroupNotFoundFault" {
    61  				return nil, errors.Wrapf(cloudprovider.ErrNotFound, err.Error())
    62  			}
    63  			return nil, errors.Wrap(err, "ecClient.DescribeReplicationGroups")
    64  		}
    65  		replicaGroup = append(replicaGroup, out.ReplicationGroups...)
    66  
    67  		if out.Marker != nil && len(*out.Marker) > 0 {
    68  			marker = *out.Marker
    69  		} else {
    70  			break
    71  		}
    72  	}
    73  
    74  	return replicaGroup, nil
    75  }
    76  
    77  func (region *SRegion) GetElasticaches() ([]SElasticache, error) {
    78  	replicaGroups, err := region.DescribeElasticacheReplicationGroups("")
    79  	if err != nil {
    80  		return nil, errors.Wrap(err, " region.DescribeElasticacheReplicationGroups")
    81  	}
    82  	result := []SElasticache{}
    83  	for i := range replicaGroups {
    84  		result = append(result, SElasticache{region: region, replicaGroup: replicaGroups[i]})
    85  	}
    86  	return result, nil
    87  }
    88  
    89  func (region *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) {
    90  	sElasticahes, err := region.GetElasticaches()
    91  	if err != nil {
    92  		return nil, errors.Wrap(err, "region.GetSElasticaches()")
    93  	}
    94  	result := []cloudprovider.ICloudElasticcache{}
    95  	for i := range sElasticahes {
    96  		result = append(result, &sElasticahes[i])
    97  	}
    98  	return result, nil
    99  }
   100  
   101  func (region *SRegion) GetSElasticacheById(Id string) (*SElasticache, error) {
   102  	replicaGroups, err := region.DescribeElasticacheReplicationGroups(Id)
   103  	if err != nil {
   104  		return nil, errors.Wrap(err, " region.DescribeElasticacheReplicationGroups")
   105  	}
   106  	if len(replicaGroups) == 0 {
   107  		return nil, cloudprovider.ErrNotFound
   108  	}
   109  	if len(replicaGroups) > 1 {
   110  		return nil, cloudprovider.ErrDuplicateId
   111  	}
   112  	return &SElasticache{region: region, replicaGroup: replicaGroups[0]}, nil
   113  }
   114  
   115  func (region *SRegion) GetIElasticcacheById(id string) (cloudprovider.ICloudElasticcache, error) {
   116  	sElasticache, err := region.GetSElasticacheById(id)
   117  	if err != nil {
   118  		return nil, errors.Wrapf(err, "region.GetSElasticacheById(%s)", id)
   119  	}
   120  	return sElasticache, nil
   121  }
   122  
   123  func (region *SRegion) DescribeElasticacheClusters() ([]*elasticache.CacheCluster, error) {
   124  	ecClient, err := region.getAwsElasticacheClient()
   125  	if err != nil {
   126  		return nil, errors.Wrap(err, "client.getAwsElasticacheClient")
   127  	}
   128  
   129  	input := elasticache.DescribeCacheClustersInput{}
   130  
   131  	clusters := []*elasticache.CacheCluster{}
   132  	marker := ""
   133  	maxrecords := (int64)(100)
   134  	input.MaxRecords = &maxrecords
   135  
   136  	for {
   137  		if len(marker) >= 0 {
   138  			input.Marker = &marker
   139  		}
   140  		out, err := ecClient.DescribeCacheClusters(&input)
   141  		if err != nil {
   142  			return nil, errors.Wrap(err, "ecClient.DescribeCacheClusters")
   143  		}
   144  		clusters = append(clusters, out.CacheClusters...)
   145  
   146  		if out.Marker != nil && len(*out.Marker) > 0 {
   147  			marker = *out.Marker
   148  		} else {
   149  			break
   150  		}
   151  	}
   152  
   153  	return clusters, nil
   154  }
   155  
   156  func (region *SRegion) DescribeCacheSubnetGroups(Id string) ([]*elasticache.CacheSubnetGroup, error) {
   157  	ecClient, err := region.getAwsElasticacheClient()
   158  	if err != nil {
   159  		return nil, errors.Wrap(err, "client.getAwsElasticacheClient")
   160  	}
   161  	input := elasticache.DescribeCacheSubnetGroupsInput{}
   162  	subnetGroups := []*elasticache.CacheSubnetGroup{}
   163  
   164  	marker := ""
   165  	maxrecords := (int64)(100)
   166  	input.MaxRecords = &maxrecords
   167  	if len(Id) > 0 {
   168  		input.CacheSubnetGroupName = &Id
   169  	}
   170  	for {
   171  		if len(marker) >= 0 {
   172  			input.Marker = &marker
   173  		}
   174  		out, err := ecClient.DescribeCacheSubnetGroups(&input)
   175  		if err != nil {
   176  			return nil, errors.Wrap(err, "ecClient.DescribeCacheSubnetGroups")
   177  		}
   178  		subnetGroups = append(subnetGroups, out.CacheSubnetGroups...)
   179  
   180  		if out.Marker != nil && len(*out.Marker) > 0 {
   181  			marker = *out.Marker
   182  		} else {
   183  			break
   184  		}
   185  	}
   186  
   187  	return subnetGroups, nil
   188  }
   189  
   190  type SElasticache struct {
   191  	multicloud.SElasticcacheBase
   192  	AwsTags
   193  
   194  	region        *SRegion
   195  	replicaGroup  *elasticache.ReplicationGroup
   196  	cacheClusters []*elasticache.CacheCluster
   197  	subnetGroup   *elasticache.CacheSubnetGroup
   198  }
   199  
   200  func (self *SElasticache) GetId() string {
   201  	return *self.replicaGroup.ReplicationGroupId
   202  }
   203  
   204  func (self *SElasticache) GetName() string {
   205  	return *self.replicaGroup.ReplicationGroupId
   206  }
   207  
   208  func (self *SElasticache) GetGlobalId() string {
   209  	return self.GetId()
   210  }
   211  
   212  func (self *SElasticache) GetStatus() string {
   213  	if self.replicaGroup.Status == nil {
   214  		return api.ELASTIC_CACHE_STATUS_UNKNOWN
   215  	}
   216  	// creating, available, modifying, deleting, create-failed, snapshotting
   217  	switch *self.replicaGroup.Status {
   218  	case "creating":
   219  		return api.ELASTIC_CACHE_STATUS_DEPLOYING
   220  	case "available":
   221  		return api.ELASTIC_CACHE_STATUS_RUNNING
   222  	case "modifying":
   223  		return api.ELASTIC_CACHE_STATUS_CHANGING
   224  	case "deleting":
   225  		return api.ELASTIC_CACHE_STATUS_DELETING
   226  	case "create-failed":
   227  		return api.ELASTIC_CACHE_STATUS_CREATE_FAILED
   228  	case "snapshotting":
   229  		return api.ELASTIC_CACHE_STATUS_SNAPSHOTTING
   230  	default:
   231  		return api.ELASTIC_CACHE_STATUS_UNKNOWN
   232  	}
   233  }
   234  
   235  func (self *SElasticache) Refresh() error {
   236  	if self.replicaGroup.ReplicationGroupId == nil {
   237  		return errors.Wrap(cloudprovider.ErrNotFound, "replicationGroupId not found")
   238  	}
   239  	replica, err := self.region.DescribeElasticacheReplicationGroups(*self.replicaGroup.ReplicationGroupId)
   240  
   241  	if err != nil {
   242  		return errors.Wrapf(err, "self.region.DescribeElasticacheReplicationGroups(%s)", *self.replicaGroup.ReplicationGroupId)
   243  	}
   244  
   245  	if len(replica) == 0 {
   246  		return cloudprovider.ErrNotFound
   247  	}
   248  	if len(replica) > 1 {
   249  		return cloudprovider.ErrDuplicateId
   250  	}
   251  
   252  	self.replicaGroup = replica[0]
   253  	self.cacheClusters = nil
   254  	self.subnetGroup = nil
   255  
   256  	return nil
   257  }
   258  
   259  func (self *SElasticache) GetBillingType() string {
   260  	return billingapi.BILLING_TYPE_POSTPAID
   261  }
   262  
   263  func (self *SElasticache) GetCreatedAt() time.Time {
   264  	return time.Time{}
   265  }
   266  
   267  func (self *SElasticache) GetExpiredAt() time.Time {
   268  	return time.Time{}
   269  }
   270  
   271  func (self *SElasticache) fetchClusters() error {
   272  	if self.cacheClusters != nil {
   273  		return nil
   274  	}
   275  	clusters, err := self.region.DescribeElasticacheClusters()
   276  	if err != nil {
   277  		return errors.Wrap(err, "self.region.DescribeElasticacheClusters")
   278  	}
   279  	self.cacheClusters = []*elasticache.CacheCluster{}
   280  	for i := range clusters {
   281  		if clusters[i].ReplicationGroupId != nil && *clusters[i].ReplicationGroupId == self.GetId() {
   282  			self.cacheClusters = append(self.cacheClusters, clusters[i])
   283  		}
   284  	}
   285  	return nil
   286  }
   287  
   288  func (self *SElasticache) GetInstanceType() string {
   289  	if self.replicaGroup.CacheNodeType != nil {
   290  		return *self.replicaGroup.CacheNodeType
   291  	}
   292  	return ""
   293  }
   294  
   295  func (self *SElasticache) GetCapacityMB() int {
   296  	return 0
   297  }
   298  
   299  func (self *SElasticache) GetArchType() string {
   300  	if self.replicaGroup.ClusterEnabled != nil && *self.replicaGroup.ClusterEnabled == true {
   301  		return api.ELASTIC_CACHE_ARCH_TYPE_CLUSTER
   302  	}
   303  
   304  	self.fetchClusters()
   305  	if len(self.cacheClusters) > 1 {
   306  		return api.ELASTIC_CACHE_ARCH_TYPE_RWSPLIT
   307  	}
   308  
   309  	return api.ELASTIC_CACHE_ARCH_TYPE_SINGLE
   310  }
   311  
   312  func (self *SElasticache) GetNodeType() string {
   313  	nodeGroupNums := 1
   314  	for _, nodeGroup := range self.replicaGroup.NodeGroups {
   315  		if nodeGroup != nil {
   316  			nodeGroupNums = len(nodeGroup.NodeGroupMembers)
   317  			break
   318  		}
   319  	}
   320  	switch nodeGroupNums {
   321  	case 1:
   322  		return api.ELASTIC_CACHE_NODE_TYPE_SINGLE
   323  	case 2:
   324  		return api.ELASTIC_CACHE_NODE_TYPE_DOUBLE
   325  	case 3:
   326  		return api.ELASTIC_CACHE_NODE_TYPE_THREE
   327  	case 4:
   328  		return api.ELASTIC_CACHE_NODE_TYPE_FOUR
   329  	case 5:
   330  		return api.ELASTIC_CACHE_NODE_TYPE_FIVE
   331  	case 6:
   332  		return api.ELASTIC_CACHE_NODE_TYPE_SIX
   333  	}
   334  
   335  	return strconv.Itoa(nodeGroupNums)
   336  }
   337  
   338  func (self *SElasticache) GetEngine() string {
   339  	self.fetchClusters()
   340  	for _, cluster := range self.cacheClusters {
   341  		if cluster != nil && cluster.Engine != nil {
   342  			return *cluster.Engine
   343  		}
   344  	}
   345  	return ""
   346  }
   347  
   348  func (self *SElasticache) GetEngineVersion() string {
   349  	self.fetchClusters()
   350  	for _, cluster := range self.cacheClusters {
   351  		if cluster != nil && cluster.EngineVersion != nil {
   352  			return *cluster.EngineVersion
   353  		}
   354  	}
   355  	return ""
   356  }
   357  
   358  func (self *SElasticache) fetchSubnetGroup() error {
   359  	if self.subnetGroup != nil {
   360  		return nil
   361  	}
   362  	err := self.fetchClusters()
   363  	if err != nil {
   364  		return errors.Wrap(err, "self.fetchClusters()")
   365  	}
   366  
   367  	subnetGroupName := ""
   368  	for _, cluster := range self.cacheClusters {
   369  		if cluster != nil && cluster.CacheSubnetGroupName != nil {
   370  			subnetGroupName = *cluster.CacheSubnetGroupName
   371  		}
   372  	}
   373  
   374  	if len(subnetGroupName) == 0 {
   375  		return cloudprovider.ErrNotFound
   376  	}
   377  
   378  	subnetGroup, err := self.region.DescribeCacheSubnetGroups(subnetGroupName)
   379  	if err != nil {
   380  		return errors.Wrapf(err, "self.region.DescribeCacheSubnetGroups(%s)", subnetGroupName)
   381  	}
   382  
   383  	if len(subnetGroup) == 0 {
   384  		return errors.Wrapf(cloudprovider.ErrNotFound, "subnetGroup %s not found", subnetGroupName)
   385  	}
   386  	if len(subnetGroup) > 1 {
   387  		return cloudprovider.ErrDuplicateId
   388  	}
   389  
   390  	self.subnetGroup = subnetGroup[0]
   391  	return nil
   392  }
   393  
   394  func (self *SElasticache) GetVpcId() string {
   395  	err := self.fetchSubnetGroup()
   396  	if err != nil {
   397  		log.Errorf("Error:%s,self.fetchSubnetGroup()", err)
   398  		return ""
   399  	}
   400  	if self.subnetGroup != nil && self.subnetGroup.VpcId != nil {
   401  		return *self.subnetGroup.VpcId
   402  	}
   403  	return ""
   404  }
   405  
   406  func (self *SElasticache) GetZoneId() string {
   407  	return ""
   408  }
   409  
   410  func (self *SElasticache) GetNetworkType() string {
   411  	if len(self.GetVpcId()) > 0 {
   412  		return api.LB_NETWORK_TYPE_VPC
   413  	}
   414  	return api.LB_NETWORK_TYPE_CLASSIC
   415  }
   416  
   417  func (self *SElasticache) GetNetworkId() string {
   418  	return ""
   419  }
   420  
   421  // cluster mode(shard) 只有配置endpoint,no cluster mode 有primary/readonly endpoint
   422  func (self *SElasticache) GetPrivateDNS() string {
   423  	for _, nodeGroup := range self.replicaGroup.NodeGroups {
   424  		if nodeGroup != nil && nodeGroup.PrimaryEndpoint != nil && nodeGroup.PrimaryEndpoint.Address != nil {
   425  			return *nodeGroup.PrimaryEndpoint.Address
   426  		}
   427  	}
   428  	return ""
   429  }
   430  
   431  func (self *SElasticache) GetPrivateIpAddr() string {
   432  	return ""
   433  }
   434  
   435  func (self *SElasticache) GetPrivateConnectPort() int {
   436  	for _, nodeGroup := range self.replicaGroup.NodeGroups {
   437  		if nodeGroup != nil && nodeGroup.PrimaryEndpoint != nil && nodeGroup.PrimaryEndpoint.Port != nil {
   438  			return int(*nodeGroup.PrimaryEndpoint.Port)
   439  		}
   440  	}
   441  	return 0
   442  }
   443  
   444  func (self *SElasticache) GetPublicDNS() string {
   445  	return ""
   446  }
   447  
   448  func (self *SElasticache) GetPublicIpAddr() string {
   449  	return ""
   450  }
   451  
   452  func (self *SElasticache) GetPublicConnectPort() int {
   453  	return 0
   454  }
   455  
   456  func (self *SElasticache) GetMaintainStartTime() string {
   457  	self.fetchClusters()
   458  	window := ""
   459  	for _, cluster := range self.cacheClusters {
   460  		if cluster != nil && cluster.PreferredMaintenanceWindow != nil {
   461  			window = *cluster.PreferredMaintenanceWindow
   462  			break
   463  		}
   464  	}
   465  
   466  	splited := strings.Split(window, "-")
   467  	return splited[0]
   468  }
   469  
   470  func (self *SElasticache) GetMaintainEndTime() string {
   471  	self.fetchClusters()
   472  	window := ""
   473  	for _, cluster := range self.cacheClusters {
   474  		if cluster != nil && cluster.PreferredMaintenanceWindow != nil {
   475  			window = *cluster.PreferredMaintenanceWindow
   476  			break
   477  		}
   478  	}
   479  
   480  	splited := strings.Split(window, "-")
   481  	if len(splited) == 2 {
   482  		return splited[1]
   483  	}
   484  	return ""
   485  }
   486  
   487  func (self *SElasticache) GetUsers() ([]SElasticacheUser, error) {
   488  	result := []SElasticacheUser{}
   489  	users, err := self.region.DescribeUsers("")
   490  	if err != nil {
   491  		return nil, errors.Wrap(err, "self.region.DescribeUsers")
   492  	}
   493  	for i := range users {
   494  		result = append(result, SElasticacheUser{region: self.region, user: users[i]})
   495  	}
   496  	return result, nil
   497  }
   498  
   499  func (self *SElasticache) GetICloudElasticcacheAccounts() ([]cloudprovider.ICloudElasticcacheAccount, error) {
   500  	result := []cloudprovider.ICloudElasticcacheAccount{}
   501  	users, err := self.GetUsers()
   502  	if err != nil {
   503  		return nil, errors.Wrap(err, "self.GetUsers()")
   504  	}
   505  	for i := range users {
   506  		result = append(result, &users[i])
   507  	}
   508  	return result, nil
   509  }
   510  
   511  func (self *SElasticache) GetUserById(id string) (*SElasticacheUser, error) {
   512  	users, err := self.region.DescribeUsers("")
   513  	if err != nil {
   514  		return nil, errors.Wrap(err, "self.region.DescribeUsers")
   515  	}
   516  	for i := range users {
   517  		temp := SElasticacheUser{region: self.region, user: users[i]}
   518  		if temp.GetId() == id {
   519  			return &temp, nil
   520  		}
   521  	}
   522  	return nil, cloudprovider.ErrNotFound
   523  }
   524  
   525  func (self *SElasticache) GetICloudElasticcacheAccount(accountId string) (cloudprovider.ICloudElasticcacheAccount, error) {
   526  	user, err := self.GetUserById(accountId)
   527  	if err != nil {
   528  		return nil, errors.Wrapf(err, "self.GetUserById(%s)", accountId)
   529  	}
   530  	return user, nil
   531  }
   532  
   533  func (self *SElasticache) GetICloudElasticcacheAcls() ([]cloudprovider.ICloudElasticcacheAcl, error) {
   534  	return []cloudprovider.ICloudElasticcacheAcl{}, nil
   535  }
   536  
   537  func (self *SElasticache) GetICloudElasticcacheAcl(aclId string) (cloudprovider.ICloudElasticcacheAcl, error) {
   538  	return nil, cloudprovider.ErrNotSupported
   539  }
   540  
   541  func (self *SElasticache) GetSnapshots() ([]SElasticacheSnapshop, error) {
   542  	result := []SElasticacheSnapshop{}
   543  	snapshots, err := self.region.DescribeSnapshots(self.GetName(), "")
   544  	if err != nil {
   545  		return nil, errors.Wrapf(err, " self.region.DescribeSnapshots(%s)", self.GetName())
   546  	}
   547  
   548  	for i := range snapshots {
   549  		result = append(result, SElasticacheSnapshop{region: self.region, snapshot: snapshots[i]})
   550  	}
   551  	return result, nil
   552  }
   553  
   554  func (self *SElasticache) GetICloudElasticcacheBackups() ([]cloudprovider.ICloudElasticcacheBackup, error) {
   555  	snapshots, err := self.GetSnapshots()
   556  	if err != nil {
   557  		return nil, errors.Wrap(err, "self.GetSnapshots()")
   558  	}
   559  	result := []cloudprovider.ICloudElasticcacheBackup{}
   560  	for i := range snapshots {
   561  		result = append(result, &snapshots[i])
   562  	}
   563  	return result, nil
   564  }
   565  
   566  func (self *SElasticache) GetICloudElasticcacheBackup(backupId string) (cloudprovider.ICloudElasticcacheBackup, error) {
   567  	snapshots, err := self.GetSnapshots()
   568  	if err != nil {
   569  		return nil, errors.Wrap(err, "self.GetSnapshots()")
   570  	}
   571  	for i := range snapshots {
   572  		if snapshots[i].GetId() == backupId {
   573  			return &snapshots[i], nil
   574  		}
   575  	}
   576  	return nil, cloudprovider.ErrNotFound
   577  }
   578  
   579  func (self *SElasticache) GetParameterGroupName() (string, error) {
   580  	err := self.fetchClusters()
   581  	if err != nil {
   582  		return "", errors.Wrap(err, "self.fetchClusters()")
   583  	}
   584  	for _, cluster := range self.cacheClusters {
   585  		if cluster != nil && cluster.CacheParameterGroup != nil && cluster.CacheParameterGroup.CacheParameterGroupName != nil {
   586  			return *cluster.CacheParameterGroup.CacheParameterGroupName, nil
   587  		}
   588  	}
   589  
   590  	return "", cloudprovider.ErrNotFound
   591  }
   592  
   593  func (self *SElasticache) GetParameters() ([]SElasticacheParameter, error) {
   594  	groupName, err := self.GetParameterGroupName()
   595  	if err != nil {
   596  		return nil, errors.Wrap(err, "self.GetParameterGroupName()")
   597  	}
   598  	parameters, err := self.region.DescribeCacheParameters(groupName)
   599  	if err != nil {
   600  		return nil, errors.Wrapf(err, "self.region.DescribeCacheParameters(%s)", groupName)
   601  	}
   602  
   603  	result := []SElasticacheParameter{}
   604  
   605  	for i := range parameters {
   606  		result = append(result, SElasticacheParameter{parameterGroup: groupName, parameter: parameters[i]})
   607  	}
   608  	return result, nil
   609  }
   610  
   611  func (self *SElasticache) GetICloudElasticcacheParameters() ([]cloudprovider.ICloudElasticcacheParameter, error) {
   612  	parameters, err := self.GetParameters()
   613  	if err != nil {
   614  		return nil, errors.Wrap(err, "self.GetParameters()")
   615  	}
   616  	result := []cloudprovider.ICloudElasticcacheParameter{}
   617  	for i := range parameters {
   618  		result = append(result, &parameters[i])
   619  	}
   620  	return result, nil
   621  }
   622  
   623  func (self *SElasticache) GetSecurityGroupIds() ([]string, error) {
   624  	err := self.fetchClusters()
   625  	if err != nil {
   626  		return nil, errors.Wrap(err, "self.fetchClusters()")
   627  	}
   628  	result := []string{}
   629  	for _, cluster := range self.cacheClusters {
   630  		if cluster != nil {
   631  			for _, securityGroup := range cluster.SecurityGroups {
   632  				if securityGroup != nil && securityGroup.Status != nil && *securityGroup.Status == "active" {
   633  					if securityGroup.SecurityGroupId != nil {
   634  						result = append(result, *securityGroup.SecurityGroupId)
   635  					}
   636  				}
   637  			}
   638  		}
   639  	}
   640  
   641  	return result, nil
   642  }
   643  
   644  func (self *SElasticache) AllocatePublicConnection(port int) (string, error) {
   645  	return "", cloudprovider.ErrNotSupported
   646  }
   647  
   648  func (self *SElasticache) ChangeInstanceSpec(spec string) error {
   649  	return cloudprovider.ErrNotSupported
   650  }
   651  
   652  func (self *SElasticache) CreateAccount(input cloudprovider.SCloudElasticCacheAccountInput) (cloudprovider.ICloudElasticcacheAccount, error) {
   653  	return nil, cloudprovider.ErrNotImplemented
   654  }
   655  
   656  func (self *SElasticache) CreateAcl(aclName, securityIps string) (cloudprovider.ICloudElasticcacheAcl, error) {
   657  	return nil, cloudprovider.ErrNotSupported
   658  }
   659  
   660  func (self *SElasticache) CreateBackup(desc string) (cloudprovider.ICloudElasticcacheBackup, error) {
   661  	return nil, cloudprovider.ErrNotImplemented
   662  }
   663  
   664  func (self *SElasticache) Delete() error {
   665  	return cloudprovider.ErrNotImplemented
   666  }
   667  
   668  func (self *SElasticache) FlushInstance(input cloudprovider.SCloudElasticCacheFlushInstanceInput) error {
   669  	return cloudprovider.ErrNotSupported
   670  }
   671  
   672  func (self *SElasticache) GetAuthMode() string {
   673  	return ""
   674  }
   675  
   676  func (self *SElasticache) ReleasePublicConnection() error {
   677  	return cloudprovider.ErrNotSupported
   678  }
   679  
   680  func (self *SElasticache) Renew(bc billing.SBillingCycle) error {
   681  	return cloudprovider.ErrNotSupported
   682  }
   683  
   684  func (self *SElasticache) Restart() error {
   685  	return cloudprovider.ErrNotSupported
   686  }
   687  
   688  func (self *SElasticache) SetMaintainTime(maintainStartTime, maintainEndTime string) error {
   689  	return cloudprovider.ErrNotImplemented
   690  }
   691  
   692  func (self *SElasticache) UpdateAuthMode(noPwdAccess bool, password string) error {
   693  	return cloudprovider.ErrNotImplemented
   694  }
   695  
   696  func (self *SElasticache) UpdateBackupPolicy(config cloudprovider.SCloudElasticCacheBackupPolicyUpdateInput) error {
   697  	return cloudprovider.ErrNotImplemented
   698  }
   699  
   700  func (self *SElasticache) UpdateInstanceParameters(config jsonutils.JSONObject) error {
   701  	return cloudprovider.ErrNotImplemented
   702  }
   703  
   704  func (self *SElasticache) UpdateSecurityGroups(secgroupIds []string) error {
   705  	return cloudprovider.ErrNotImplemented
   706  }