aliyun&huawei redis sync support

This commit is contained in:
TangBin
2019-07-22 09:41:31 +08:00
parent 52ed4b7d0c
commit a0a9ddd01b
34 changed files with 2658 additions and 7 deletions

View File

@@ -0,0 +1,26 @@
package compute
const (
ELASTIC_CACHE_STATUS_RUNNING = "running" //(正常)
ELASTIC_CACHE_STATUS_DEPLOYING = "deploying" //(创建中)
ELASTIC_CACHE_STATUS_CHANGING = "changing" //(修改中)
ELASTIC_CACHE_STATUS_INACTIVE = "inactive" //(被禁用)
ELASTIC_CACHE_STATUS_FLUSHING = "flushing" //(清除中)
ELASTIC_CACHE_STATUS_RELEASED = "released" //(已释放)
ELASTIC_CACHE_STATUS_TRANSFORMING = "transforming" //(转换中)
ELASTIC_CACHE_STATUS_UNAVAILABLE = "unavailable" //(服务停止)
ELASTIC_CACHE_STATUS_ERROR = "error" //(创建失败)
ELASTIC_CACHE_STATUS_MIGRATING = "migrating" //(迁移中)
ELASTIC_CACHE_STATUS_BACKUPRECOVERING = "backuprecovering" //(备份恢复中)
ELASTIC_CACHE_STATUS_MINORVERSIONUPGRADING = "minorversionupgrading" //(小版本升级中)
ELASTIC_CACHE_STATUS_NETWORKMODIFYING = "networkmodifying" //(网络变更中)
ELASTIC_CACHE_STATUS_SSLMODIFYING = "sslmodifying" //SSL变更中
ELASTIC_CACHE_STATUS_MAJORVERSIONUPGRADING = "majorversionupgrading" //(大版本升级中,可正常访问)
)
const (
ELASTIC_CACHE_ARCH_TYPE_STAND_ALONE = "standalone" //
ELASTIC_CACHE_ARCH_TYPE_MASTER_SLAVE = "master_slave" //
ELASTIC_CACHE_ARCH_TYPE_CLUSTER = "cluster" // 集群
ELASTIC_CACHE_ARCH_TYPE_PROXY = "proxy" // 代理集群
)

View File

@@ -175,10 +175,11 @@ const (
ACT_UNCACHE_IMAGE_FAIL = "uncache_image_fail"
ACT_UNCACHED_IMAGE = "uncached_image"
ACT_SYNC_CLOUD_DISK = "sync_cloud_disk"
ACT_SYNC_CLOUD_SERVER = "sync_cloud_server"
ACT_SYNC_CLOUD_EIP = "sync_cloud_eip"
ACT_SYNC_CLOUD_PROJECT = "sync_cloud_project"
ACT_SYNC_CLOUD_DISK = "sync_cloud_disk"
ACT_SYNC_CLOUD_SERVER = "sync_cloud_server"
ACT_SYNC_CLOUD_EIP = "sync_cloud_eip"
ACT_SYNC_CLOUD_PROJECT = "sync_cloud_project"
ACT_SYNC_CLOUD_ELASTIC_CACHE = "sync_cloud_elastic_cache"
ACT_PENDING_DELETE = "pending_delete"
ACT_CANCEL_DELETE = "cancel_delete"

View File

@@ -122,6 +122,8 @@ type ICloudRegion interface {
GetIDBInstances() ([]ICloudDBInstance, error)
GetIDBInstanceBackups() ([]ICloudDBInstanceBackup, error)
GetIElasticcaches() ([]ICloudElasticcache, error)
GetProvider() string
}
@@ -767,3 +769,71 @@ type ICloudDBInstanceAccountPrivilege interface {
GetPrivilege() string
GetDBName() string
}
type ICloudElasticcache interface {
IVirtualResource
IBillingResource
GetInstanceType() string
GetCapacityMB() int
GetArchType() string
GetNodeType() string
GetEngine() string
GetEngineVersion() string
GetVpcId() string
GetZoneId() string
GetNetworkType() string
GetNetworkId() string
GetPrivateDNS() string
GetPrivateIpAddr() string
GetPrivateConnectPort() int
GetPublicDNS() string
GetPublicIpAddr() string
GetPublicConnectPort() int
GetMaintainStartTime() string
GetMaintainEndTime() string
GetICloudElasticcacheAccounts() ([]ICloudElasticcacheAccount, error)
GetICloudElasticcacheAcls() ([]ICloudElasticcacheAcl, error)
GetICloudElasticcacheBackups() ([]ICloudElasticcacheBackup, error)
GetICloudElasticcacheParameters() ([]ICloudElasticcacheParameter, error)
}
type ICloudElasticcacheAccount interface {
ICloudResource
GetAccountType() string
GetAccountPrivilege() string
}
type ICloudElasticcacheAcl interface {
ICloudResource
GetIpList() string
}
type ICloudElasticcacheBackup interface {
ICloudResource
GetBackupSizeMb() int
GetBackupType() string
GetBackupMode() string
GetDownloadURL() string
GetStartTime() time.Time
GetEndTime() time.Time
}
type ICloudElasticcacheParameter interface {
ICloudResource
GetParameterKey() string
GetParameterValue() string
GetParameterValueRange() string
GetDescription() string
GetModifiable() bool
GetForceRestart() bool
}

View File

@@ -178,6 +178,21 @@ func (self *SCloudregion) GetDBInstanceBackups(provider *SCloudprovider) ([]SDBI
return backups, nil
}
func (self *SCloudregion) GetElasticcaches(provider *SCloudprovider) ([]SElasticcache, error) {
instances := []SElasticcache{}
// .IsFalse("pending_deleted")
q := ElasticcacheManager.Query().Equals("cloudregion_id", self.Id)
if provider != nil {
q = q.Equals("manager_id", provider.Id)
}
err := db.FetchModelObjects(ElasticcacheManager, q, &instances)
if err != nil {
return nil, errors.Wrapf(err, "GetElasticcaches for region %s", self.Id)
}
return instances, nil
}
func (self *SCloudregion) getGuestCountInternal(increment bool) (int, error) {
zoneTable := ZoneManager.Query("id")
if self.Id == api.DEFAULT_REGION_ID {

View File

@@ -1002,6 +1002,8 @@ func syncPublicCloudProviderInfo(
syncRegionDBInstances(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
syncRegionDBInstanceBackups(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
syncElasticcaches(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
log.Debugf("storageCachePairs count %d", len(storageCachePairs))
for i := range storageCachePairs {
// always sync private cloud cached images

View File

@@ -0,0 +1,116 @@
package models
import (
"context"
"fmt"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
)
func syncElasticcaches(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *SSyncRange) {
extCacheDBs, err := remoteRegion.GetIElasticcaches()
if err != nil {
msg := fmt.Sprintf("GetIElasticcaches for region %s failed %s", remoteRegion.GetName(), err)
log.Errorf(msg)
return
}
localInstances, remoteInstances, result := ElasticcacheManager.SyncElasticcaches(ctx, userCred, provider.GetOwnerId(), provider, localRegion, extCacheDBs)
syncResults.Add(ElasticcacheManager, result)
msg := result.Result()
log.Infof("SyncElasticcaches for region %s result: %s", localRegion.Name, msg)
if result.IsError() {
return
}
db.OpsLog.LogEvent(provider, db.ACT_SYNC_CLOUD_ELASTIC_CACHE, msg, userCred)
for i := 0; i < len(localInstances); i++ {
func() {
lockman.LockObject(ctx, &localInstances[i])
defer lockman.ReleaseObject(ctx, &localInstances[i])
syncElasticcacheParameters(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
syncElasticcacheAccounts(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
syncElasticcacheAcls(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
syncElasticcacheBackups(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
}()
}
}
func syncElasticcacheParameters(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SElasticcache, remoteInstance cloudprovider.ICloudElasticcache) {
parameters, err := remoteInstance.GetICloudElasticcacheParameters()
if err != nil {
msg := fmt.Sprintf("GetIElasticcacheParameters for dbinstance %s failed %s", remoteInstance.GetName(), err)
log.Errorf(msg)
return
}
result := ElasticcacheParameterManager.SyncElasticcacheParameters(ctx, userCred, localInstance, parameters)
syncResults.Add(ElasticcacheParameterManager, result)
msg := result.Result()
log.Infof("SyncElasticcacheParameters for dbinstance %s result: %s", localInstance.Name, msg)
if result.IsError() {
return
}
}
func syncElasticcacheAccounts(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SElasticcache, remoteInstance cloudprovider.ICloudElasticcache) {
accounts, err := remoteInstance.GetICloudElasticcacheAccounts()
if err != nil {
msg := fmt.Sprintf("GetIElasticcacheAccounts for dbinstance %s failed %s", remoteInstance.GetName(), err)
log.Errorf(msg)
return
}
result := ElasticcacheAccountManager.SyncElasticcacheAccounts(ctx, userCred, localInstance, accounts)
syncResults.Add(ElasticcacheAccountManager, result)
msg := result.Result()
log.Infof("SyncElasticcacheAccounts for dbinstance %s result: %s", localInstance.Name, msg)
if result.IsError() {
return
}
}
func syncElasticcacheAcls(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SElasticcache, remoteInstance cloudprovider.ICloudElasticcache) {
acls, err := remoteInstance.GetICloudElasticcacheAcls()
if err != nil {
msg := fmt.Sprintf("GetIElasticcacheAcls for dbinstance %s failed %s", remoteInstance.GetName(), err)
log.Errorf(msg)
return
}
result := ElasticcacheAclManager.SyncElasticcacheAcls(ctx, userCred, localInstance, acls)
syncResults.Add(ElasticcacheAclManager, result)
msg := result.Result()
log.Infof("SyncElasticcacheAcls for dbinstance %s result: %s", localInstance.Name, msg)
if result.IsError() {
return
}
}
func syncElasticcacheBackups(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SElasticcache, remoteInstance cloudprovider.ICloudElasticcache) {
backups, err := remoteInstance.GetICloudElasticcacheBackups()
if err != nil {
msg := fmt.Sprintf("GetIElasticcacheBackups for dbinstance %s failed %s", remoteInstance.GetName(), err)
log.Errorf(msg)
return
}
result := ElasticcacheBackupManager.SyncElasticcacheBackups(ctx, userCred, localInstance, backups)
syncResults.Add(ElasticcacheBackupManager, result)
msg := result.Result()
log.Infof("SyncElasticcacheBackups for dbinstance %s result: %s", localInstance.Name, msg)
if result.IsError() {
return
}
}

View File

@@ -0,0 +1,142 @@
package models
import (
"context"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
)
// SElasticcache.Account
type SElasticcacheAccountManager struct {
db.SVirtualResourceBaseManager
}
var ElasticcacheAccountManager *SElasticcacheAccountManager
func init() {
ElasticcacheAccountManager = &SElasticcacheAccountManager{
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SElasticcacheAccount{},
"elasticcacheaccounts_tbl",
"elasticcacheaccount",
"elasticcacheaccounts",
),
}
ElasticcacheAccountManager.SetVirtualObject(ElasticcacheAccountManager)
}
type SElasticcacheAccount struct {
db.SStatusStandaloneResourceBase
db.SExternalizedResourceBase
ElasticcacheId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"` // elastic cache instance id
AccountType string `width:"16" charset:"ascii" nullable:"false" list:"user" update:"user" create:"optional"` // 账号类型 normal |admin
AccountPrivilege string `width:"16" charset:"ascii" nullable:"false" list:"user" update:"user" create:"optional"` // 账号权限 read | write
}
func (manager *SElasticcacheAccountManager) SyncElasticcacheAccounts(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, cloudElasticcacheAccounts []cloudprovider.ICloudElasticcacheAccount) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
syncResult := compare.SyncResult{}
dbAccounts, err := elasticcache.GetElasticcacheAccounts()
if err != nil {
syncResult.Error(err)
return syncResult
}
removed := make([]SElasticcacheAccount, 0)
commondb := make([]SElasticcacheAccount, 0)
commonext := make([]cloudprovider.ICloudElasticcacheAccount, 0)
added := make([]cloudprovider.ICloudElasticcacheAccount, 0)
if err := compare.CompareSets(dbAccounts, cloudElasticcacheAccounts, &removed, &commondb, &commonext, &added); err != nil {
syncResult.Error(err)
return syncResult
}
for i := 0; i < len(removed); i++ {
err := removed[i].syncRemoveCloudElasticcacheAccount(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i++ {
err := commondb[i].SyncWithCloudElasticcacheAccount(ctx, userCred, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncResult.Update()
}
for i := 0; i < len(added); i++ {
_, err := manager.newFromCloudElasticcacheAccount(ctx, userCred, elasticcache, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncResult.Add()
}
return syncResult
}
func (self *SElasticcacheAccount) syncRemoveCloudElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil {
return errors.Wrapf(err, "newFromCloudElasticcacheAccount.Remove")
}
return self.Delete(ctx, userCred)
}
func (self *SElasticcacheAccount) SyncWithCloudElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, extAccount cloudprovider.ICloudElasticcacheAccount) error {
_, err := db.UpdateWithLock(ctx, self, func() error {
self.Status = extAccount.GetStatus()
self.AccountType = extAccount.GetAccountType()
self.AccountPrivilege = extAccount.GetAccountPrivilege()
return nil
})
if err != nil {
return errors.Wrapf(err, "SyncWithCloudElasticcacheAccount.UpdateWithLock")
}
return nil
}
func (manager *SElasticcacheAccountManager) newFromCloudElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, extAccount cloudprovider.ICloudElasticcacheAccount) (*SElasticcacheAccount, error) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
account := SElasticcacheAccount{}
account.SetModelManager(manager, &account)
account.ElasticcacheId = elasticcache.GetId()
account.Name = extAccount.GetName()
account.ExternalId = extAccount.GetGlobalId()
account.Status = extAccount.GetStatus()
account.AccountType = extAccount.GetAccountType()
account.AccountPrivilege = extAccount.GetAccountPrivilege()
err := manager.TableSpec().Insert(&account)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcacheAccount.Insert")
}
return &account, nil
}

View File

@@ -0,0 +1,137 @@
package models
import (
"context"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
)
// SElasticcache.Acl
type SElasticcacheAclManager struct {
db.SVirtualResourceBaseManager
}
var ElasticcacheAclManager *SElasticcacheAclManager
func init() {
ElasticcacheAclManager = &SElasticcacheAclManager{
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SElasticcacheAcl{},
"elasticcacheacls_tbl",
"elasticcacheacl",
"elasticcacheacls",
),
}
ElasticcacheAclManager.SetVirtualObject(ElasticcacheAclManager)
}
type SElasticcacheAcl struct {
db.SStandaloneResourceBase
db.SExternalizedResourceBase
ElasticcacheId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"` // elastic cache instance id
IpList string `width:"256" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
}
func (manager *SElasticcacheAclManager) SyncElasticcacheAcls(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, cloudElasticcacheAcls []cloudprovider.ICloudElasticcacheAcl) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
syncResult := compare.SyncResult{}
dbAcls, err := elasticcache.GetElasticcacheAcls()
if err != nil {
syncResult.Error(err)
return syncResult
}
removed := make([]SElasticcacheAcl, 0)
commondb := make([]SElasticcacheAcl, 0)
commonext := make([]cloudprovider.ICloudElasticcacheAcl, 0)
added := make([]cloudprovider.ICloudElasticcacheAcl, 0)
if err := compare.CompareSets(dbAcls, cloudElasticcacheAcls, &removed, &commondb, &commonext, &added); err != nil {
syncResult.Error(err)
return syncResult
}
for i := 0; i < len(removed); i++ {
err := removed[i].syncRemoveCloudElasticcacheAcl(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i++ {
err := commondb[i].SyncWithCloudElasticcacheAcl(ctx, userCred, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncResult.Update()
}
for i := 0; i < len(added); i++ {
_, err := manager.newFromCloudElasticcacheAcl(ctx, userCred, elasticcache, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncResult.Add()
}
return syncResult
}
func (self *SElasticcacheAcl) syncRemoveCloudElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil {
return errors.Wrapf(err, "newFromCloudElasticcacheAcl.Remove")
}
return self.Delete(ctx, userCred)
}
func (self *SElasticcacheAcl) SyncWithCloudElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, extAcl cloudprovider.ICloudElasticcacheAcl) error {
_, err := db.UpdateWithLock(ctx, self, func() error {
self.IpList = extAcl.GetIpList()
return nil
})
if err != nil {
return errors.Wrapf(err, "SyncWithCloudElasticcacheAcl.UpdateWithLock")
}
return nil
}
func (manager *SElasticcacheAclManager) newFromCloudElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, extAcl cloudprovider.ICloudElasticcacheAcl) (*SElasticcacheAcl, error) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
acl := SElasticcacheAcl{}
acl.SetModelManager(manager, &acl)
acl.ElasticcacheId = elasticcache.GetId()
acl.Name = extAcl.GetName()
acl.ExternalId = extAcl.GetGlobalId()
acl.IpList = extAcl.GetIpList()
err := manager.TableSpec().Insert(&acl)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcacheAcl.Insert")
}
return &acl, nil
}

View File

@@ -0,0 +1,154 @@
package models
import (
"context"
"time"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
)
// SElasticcache.Backup
type SElasticcacheBackupManager struct {
db.SVirtualResourceBaseManager
}
var ElasticcacheBackupManager *SElasticcacheBackupManager
func init() {
ElasticcacheBackupManager = &SElasticcacheBackupManager{
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SElasticcacheBackup{},
"elasticcachebackups_tbl",
"elasticcachebackup",
"elasticcachebackups",
),
}
ElasticcacheBackupManager.SetVirtualObject(ElasticcacheBackupManager)
}
type SElasticcacheBackup struct {
db.SStatusStandaloneResourceBase
db.SExternalizedResourceBase
ElasticcacheId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"` // elastic cache instance id
BackupSizeMb int `nullable:"false" list:"user"`
BackupType string `width:"32" charset:"ascii" nullable:"true" list:"user"` // 全量|增量额
BackupMode string `width:"32" charset:"ascii" nullable:"true" list:"user"` // 自动|手动
DownloadURL string `width:"512" charset:"ascii" nullable:"true" list:"user"`
StartTime time.Time `list:"user"`
EndTime time.Time `list:"user"`
}
func (manager *SElasticcacheBackupManager) SyncElasticcacheBackups(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, cloudElasticcacheBackups []cloudprovider.ICloudElasticcacheBackup) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
syncResult := compare.SyncResult{}
dbBackups, err := elasticcache.GetElasticcacheBackups()
if err != nil {
syncResult.Error(err)
return syncResult
}
removed := make([]SElasticcacheBackup, 0)
commondb := make([]SElasticcacheBackup, 0)
commonext := make([]cloudprovider.ICloudElasticcacheBackup, 0)
added := make([]cloudprovider.ICloudElasticcacheBackup, 0)
if err := compare.CompareSets(dbBackups, cloudElasticcacheBackups, &removed, &commondb, &commonext, &added); err != nil {
syncResult.Error(err)
return syncResult
}
for i := 0; i < len(removed); i++ {
err := removed[i].syncRemoveCloudElasticcacheBackup(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i++ {
err := commondb[i].SyncWithCloudElasticcacheBackup(ctx, userCred, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncResult.Update()
}
for i := 0; i < len(added); i++ {
_, err := manager.newFromCloudElasticcacheBackup(ctx, userCred, elasticcache, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncResult.Add()
}
return syncResult
}
func (self *SElasticcacheBackup) syncRemoveCloudElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil {
return errors.Wrapf(err, "newFromCloudElasticcacheBackup.Remove")
}
return self.Delete(ctx, userCred)
}
func (self *SElasticcacheBackup) SyncWithCloudElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, extBackup cloudprovider.ICloudElasticcacheBackup) error {
_, err := db.UpdateWithLock(ctx, self, func() error {
self.Status = extBackup.GetStatus()
self.BackupSizeMb = extBackup.GetBackupSizeMb()
self.DownloadURL = extBackup.GetDownloadURL()
return nil
})
if err != nil {
return errors.Wrapf(err, "SyncWithCloudElasticcacheBackup.UpdateWithLock")
}
return nil
}
func (manager *SElasticcacheBackupManager) newFromCloudElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, extBackup cloudprovider.ICloudElasticcacheBackup) (*SElasticcacheBackup, error) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
backup := SElasticcacheBackup{}
backup.SetModelManager(manager, &backup)
backup.ElasticcacheId = elasticcache.GetId()
backup.Name = extBackup.GetName()
backup.ExternalId = extBackup.GetGlobalId()
backup.Status = extBackup.GetStatus()
backup.BackupSizeMb = extBackup.GetBackupSizeMb()
backup.BackupType = extBackup.GetBackupType()
backup.BackupMode = extBackup.GetBackupMode()
backup.DownloadURL = extBackup.GetDownloadURL()
backup.StartTime = extBackup.GetStartTime()
backup.EndTime = extBackup.GetEndTime()
err := manager.TableSpec().Insert(&backup)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcacheBackup.Insert")
}
return &backup, nil
}

View File

@@ -0,0 +1,295 @@
package models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SElasticcacheManager struct {
db.SVirtualResourceBaseManager
}
var ElasticcacheManager *SElasticcacheManager
func init() {
ElasticcacheManager = &SElasticcacheManager{
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SElasticcache{},
"elasticcacheinstances_tbl",
"elasticcache",
"elasticcaches",
),
}
ElasticcacheManager.SetVirtualObject(ElasticcacheManager)
}
type SElasticcache struct {
db.SVirtualResourceBase
db.SExternalizedResourceBase
SBillingResourceBase
SManagedResourceBase
SCloudregionResourceBase
SZoneResourceBase
InstanceType string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"optional"` // redis.master.micro.default
CapacityMB int `nullable:"false" list:"user" create:"optional"` // 1024
ArchType string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"optional"` // 集群版 | 标准版 | 读写分离版 | 单机
NodeType string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"optional"` // STAND_ALONE单节点 MASTER_SLAVE多节点)
Engine string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"required"` // Redis | Memcache
EngineVersion string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"required"` // 4.0 5.0
VpcId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"optional"`
NetworkType string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"optional"` // CLASSIC经典网络 VPC专有网络
NetworkId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"optional"`
PrivateDNS string `width:"256" charset:"ascii" nullable:"false" list:"user" create:"optional"` // 内网DNS
PrivateIpAddr string `width:"17" charset:"ascii" list:"user" create:"optional"` // 内网IP地址
PrivateConnectPort int `nullable:"false" list:"user" create:"optional"` // 内网访问端口
PublicDNS string `width:"256" charset:"ascii" nullable:"false" list:"user" create:"optional"`
PublicIpAddr string `width:"17" charset:"ascii" list:"user" create:"optional"` //
PublicConnectPort int `nullable:"false" list:"user" create:"optional"` // 外网访问端口
MaintainStartTime string `width:"8" charset:"ascii" nullable:"false" list:"user" create:"optional"` // HH:mmZ eg. 02:00Z
MaintainEndTime string `width:"8" charset:"ascii" nullable:"false" list:"user" create:"optional"`
// AutoRenew // 自动续费
// AutoRenewPeriod // 自动续费周期
}
func (self *SElasticcache) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SStatusStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
return extra
}
func (self *SElasticcache) GetElasticcacheParameters() ([]SElasticcacheParameter, error) {
ret := []SElasticcacheParameter{}
q := ElasticcacheParameterManager.Query().Equals("elasticcache_id", self.Id)
err := db.FetchModelObjects(ElasticcacheParameterManager, q, &ret)
if err != nil {
return nil, errors.Wrapf(err, "GetElasticcacheParameters.FetchModelObjects for elastic cache %s", self.Id)
}
return ret, nil
}
func (self *SElasticcache) GetElasticcacheAccounts() ([]SElasticcacheAccount, error) {
ret := []SElasticcacheAccount{}
q := ElasticcacheAccountManager.Query().Equals("elasticcache_id", self.Id)
err := db.FetchModelObjects(ElasticcacheAccountManager, q, &ret)
if err != nil {
return nil, errors.Wrapf(err, "GetElasticcacheAccounts.FetchModelObjects for elastic cache %s", self.Id)
}
return ret, nil
}
func (self *SElasticcache) GetElasticcacheAcls() ([]SElasticcacheAcl, error) {
ret := []SElasticcacheAcl{}
q := ElasticcacheAclManager.Query().Equals("elasticcache_id", self.Id)
err := db.FetchModelObjects(ElasticcacheAclManager, q, &ret)
if err != nil {
return nil, errors.Wrapf(err, "GetElasticcacheAcls.FetchModelObjects for elastic cache %s", self.Id)
}
return ret, nil
}
func (self *SElasticcache) GetElasticcacheBackups() ([]SElasticcacheBackup, error) {
ret := []SElasticcacheBackup{}
q := ElasticcacheBackupManager.Query().Equals("elasticcache_id", self.Id)
err := db.FetchModelObjects(ElasticcacheBackupManager, q, &ret)
if err != nil {
return nil, errors.Wrapf(err, "GetElasticcacheBackups.FetchModelObjects for elastic cache %s", self.Id)
}
return ret, nil
}
func (manager *SElasticcacheManager) SyncElasticcaches(ctx context.Context, userCred mcclient.TokenCredential, syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider, region *SCloudregion, cloudElasticcaches []cloudprovider.ICloudElasticcache) ([]SElasticcache, []cloudprovider.ICloudElasticcache, compare.SyncResult) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
localElasticcaches := []SElasticcache{}
remoteElasticcaches := []cloudprovider.ICloudElasticcache{}
syncResult := compare.SyncResult{}
dbInstances, err := region.GetElasticcaches(provider)
if err != nil {
syncResult.Error(err)
return nil, nil, syncResult
}
removed := make([]SElasticcache, 0)
commondb := make([]SElasticcache, 0)
commonext := make([]cloudprovider.ICloudElasticcache, 0)
added := make([]cloudprovider.ICloudElasticcache, 0)
if err := compare.CompareSets(dbInstances, cloudElasticcaches, &removed, &commondb, &commonext, &added); err != nil {
syncResult.Error(err)
return nil, nil, syncResult
}
for i := 0; i < len(removed); i++ {
err := removed[i].syncRemoveCloudElasticcache(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i++ {
err := commondb[i].SyncWithCloudElasticcache(ctx, userCred, provider, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
localElasticcaches = append(localElasticcaches, commondb[i])
remoteElasticcaches = append(remoteElasticcaches, commonext[i])
syncResult.Update()
}
for i := 0; i < len(added); i++ {
instance, err := manager.newFromCloudElasticcache(ctx, userCred, syncOwnerId, provider, region, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncMetadata(ctx, userCred, instance, added[i])
localElasticcaches = append(localElasticcaches, *instance)
remoteElasticcaches = append(remoteElasticcaches, added[i])
syncResult.Add()
}
return localElasticcaches, remoteElasticcaches, syncResult
}
func (self *SElasticcache) syncRemoveCloudElasticcache(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil {
return self.SetStatus(userCred, api.ELASTIC_CACHE_STATUS_ERROR, "sync to delete")
}
return self.Delete(ctx, userCred)
}
func (self *SElasticcache) SyncWithCloudElasticcache(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extInstance cloudprovider.ICloudElasticcache) error {
diff, err := db.UpdateWithLock(ctx, self, func() error {
self.Status = extInstance.GetStatus()
self.InstanceType = extInstance.GetInstanceType()
self.CapacityMB = extInstance.GetCapacityMB()
self.ArchType = extInstance.GetArchType()
self.NodeType = extInstance.GetNodeType()
self.Engine = extInstance.GetEngine()
self.EngineVersion = extInstance.GetEngineVersion()
self.NetworkType = extInstance.GetNetworkType()
self.PrivateDNS = extInstance.GetPrivateDNS()
self.PrivateIpAddr = extInstance.GetPrivateIpAddr()
self.PrivateConnectPort = extInstance.GetPrivateConnectPort()
self.PublicDNS = extInstance.GetPublicDNS()
self.PublicIpAddr = extInstance.GetPublicIpAddr()
self.PublicConnectPort = extInstance.GetPublicConnectPort()
self.MaintainStartTime = extInstance.GetMaintainStartTime()
self.MaintainEndTime = extInstance.GetMaintainEndTime()
return nil
})
if err != nil {
return errors.Wrapf(err, "syncWithCloudElasticcache.Update")
}
db.OpsLog.LogSyncUpdate(self, diff, userCred)
return nil
}
func (manager *SElasticcacheManager) newFromCloudElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, provider *SCloudprovider, region *SCloudregion, extInstance cloudprovider.ICloudElasticcache) (*SElasticcache, error) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
instance := SElasticcache{}
instance.SetModelManager(manager, &instance)
newName, err := db.GenerateName(manager, ownerId, extInstance.GetName())
if err != nil {
return nil, err
}
instance.Name = newName
instance.ExternalId = extInstance.GetGlobalId()
instance.CloudregionId = region.Id
instance.ManagerId = provider.Id
instance.IsEmulated = extInstance.IsEmulated()
instance.Status = extInstance.GetStatus()
instance.InstanceType = extInstance.GetInstanceType()
instance.CapacityMB = extInstance.GetCapacityMB()
instance.ArchType = extInstance.GetArchType()
instance.NodeType = extInstance.GetNodeType()
instance.Engine = extInstance.GetEngine()
instance.EngineVersion = extInstance.GetEngineVersion()
instance.NetworkType = extInstance.GetNetworkType()
instance.PrivateDNS = extInstance.GetPrivateDNS()
instance.PrivateIpAddr = extInstance.GetPrivateIpAddr()
instance.PrivateConnectPort = extInstance.GetPrivateConnectPort()
instance.PublicDNS = extInstance.GetPublicDNS()
instance.PublicIpAddr = extInstance.GetPublicIpAddr()
instance.PublicConnectPort = extInstance.GetPublicConnectPort()
instance.MaintainStartTime = extInstance.GetMaintainStartTime()
instance.MaintainEndTime = extInstance.GetMaintainEndTime()
if zoneId := extInstance.GetZoneId(); len(zoneId) > 0 {
zone, err := db.FetchByExternalId(ZoneManager, zoneId)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcache.FetchZoneId")
}
instance.ZoneId = zone.GetId()
}
if vpcId := extInstance.GetVpcId(); len(vpcId) > 0 {
vpc, err := db.FetchByExternalId(VpcManager, vpcId)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcache.FetchVpcId")
}
instance.VpcId = vpc.GetId()
}
if networkId := extInstance.GetNetworkId(); len(networkId) > 0 {
network, err := db.FetchByExternalId(NetworkManager, networkId)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcache.FetchNetworkId")
}
instance.NetworkId = network.GetId()
}
if createdAt := extInstance.GetCreatedAt(); !createdAt.IsZero() {
instance.CreatedAt = createdAt
}
factory, err := provider.GetProviderFactory()
if err != nil {
return nil, errors.Wrap(err, "newFromCloudElasticcache.GetProviderFactory")
}
if factory.IsSupportPrepaidResources() {
instance.BillingType = extInstance.GetBillingType()
instance.ExpiredAt = extInstance.GetExpiredAt()
}
err = manager.TableSpec().Insert(&instance)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcache.Insert")
}
SyncCloudProject(userCred, &instance, ownerId, extInstance, instance.ManagerId)
db.OpsLog.LogEvent(&instance, db.ACT_CREATE, instance.GetShortDesc(ctx), userCred)
return &instance, nil
}

View File

@@ -0,0 +1,148 @@
package models
import (
"context"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
)
// SElasticcache.Parameter
type SElasticcacheParameterManager struct {
db.SVirtualResourceBaseManager
}
var ElasticcacheParameterManager *SElasticcacheParameterManager
func init() {
ElasticcacheParameterManager = &SElasticcacheParameterManager{
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SElasticcacheParameter{},
"elasticcacheparameters_tbl",
"elasticcacheparameter",
"elasticcacheparameters",
),
}
ElasticcacheParameterManager.SetVirtualObject(ElasticcacheParameterManager)
}
type SElasticcacheParameter struct {
db.SStandaloneResourceBase
db.SExternalizedResourceBase
ElasticcacheId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"` // elastic cache instance id
Key string `width:"64" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
Value string `width:"256" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
ValueRange string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"optional"` // 校验代码,参数的可选范围。
Modifiable bool `nullable:"true" list:"user" create:"optional"` // True可修改 False不可修改
ForceRestart bool `nullable:"true" list:"user" create:"optional"` // True重启生效 False无需重启提交后即生效
}
func (manager *SElasticcacheParameterManager) SyncElasticcacheParameters(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, cloudElasticcacheParameters []cloudprovider.ICloudElasticcacheParameter) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, elasticcache.GetOwnerId()))
syncResult := compare.SyncResult{}
dbParameters, err := elasticcache.GetElasticcacheParameters()
if err != nil {
syncResult.Error(err)
return syncResult
}
removed := make([]SElasticcacheParameter, 0)
commondb := make([]SElasticcacheParameter, 0)
commonext := make([]cloudprovider.ICloudElasticcacheParameter, 0)
added := make([]cloudprovider.ICloudElasticcacheParameter, 0)
if err := compare.CompareSets(dbParameters, cloudElasticcacheParameters, &removed, &commondb, &commonext, &added); err != nil {
syncResult.Error(err)
return syncResult
}
for i := 0; i < len(removed); i++ {
err := removed[i].syncRemoveCloudElasticcacheParameter(ctx, userCred)
if err != nil {
syncResult.DeleteError(err)
} else {
syncResult.Delete()
}
}
for i := 0; i < len(commondb); i++ {
err := commondb[i].SyncWithCloudElasticcacheParameter(ctx, userCred, commonext[i])
if err != nil {
syncResult.UpdateError(err)
continue
}
syncResult.Update()
}
for i := 0; i < len(added); i++ {
_, err := manager.newFromCloudElasticcacheParameter(ctx, userCred, elasticcache, added[i])
if err != nil {
syncResult.AddError(err)
continue
}
syncResult.Add()
}
return syncResult
}
func (self *SElasticcacheParameter) syncRemoveCloudElasticcacheParameter(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
err := self.ValidateDeleteCondition(ctx)
if err != nil {
return errors.Wrapf(err, "newFromCloudElasticcacheParameter.Remove")
}
return self.Delete(ctx, userCred)
}
func (self *SElasticcacheParameter) SyncWithCloudElasticcacheParameter(ctx context.Context, userCred mcclient.TokenCredential, extParameter cloudprovider.ICloudElasticcacheParameter) error {
_, err := db.UpdateWithLock(ctx, self, func() error {
self.Key = extParameter.GetParameterKey()
self.Value = extParameter.GetParameterValue()
self.Modifiable = extParameter.GetModifiable()
self.ForceRestart = extParameter.GetForceRestart()
return nil
})
if err != nil {
return errors.Wrapf(err, "SyncWithCloudElasticcacheParameter.UpdateWithLock")
}
return nil
}
func (manager *SElasticcacheParameterManager) newFromCloudElasticcacheParameter(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, extParameter cloudprovider.ICloudElasticcacheParameter) (*SElasticcacheParameter, error) {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
parameter := SElasticcacheParameter{}
parameter.SetModelManager(manager, &parameter)
parameter.ElasticcacheId = elasticcache.Id
parameter.Name = extParameter.GetName()
parameter.ExternalId = extParameter.GetGlobalId()
parameter.Key = extParameter.GetParameterKey()
parameter.Value = extParameter.GetParameterValue()
parameter.ValueRange = extParameter.GetParameterValueRange()
parameter.Modifiable = extParameter.GetModifiable()
parameter.ForceRestart = extParameter.GetForceRestart()
parameter.Description = extParameter.GetDescription()
err := manager.TableSpec().Insert(&parameter)
if err != nil {
return nil, errors.Wrapf(err, "newFromCloudElasticcacheParameter.Insert")
}
return &parameter, nil
}

View File

@@ -274,13 +274,12 @@ func (self *SServerSku) GetCustomizeColumns(ctx context.Context, userCred mcclie
countKey := self.GetId() + ".total_guest_count"
v := Cache.Get(countKey)
if v == nil {
count, _ = skuRelatedGuestCount(self)
Cache.Set(countKey, count)
} else {
count = v.(int)
}
count, _ = skuRelatedGuestCount(self)
extra.Add(jsonutils.NewInt(int64(count)), "total_guest_count")
zoneInfo := self.SZoneResourceBase.GetCustomizeColumns(ctx, userCred, query)

View File

@@ -124,6 +124,12 @@ func InitHandlers(app *appsrv.Application) {
models.DBInstanceDatabaseManager,
models.DBInstanceAccountManager,
models.DBInstancePrivilegeManager,
models.ElasticcacheManager,
models.ElasticcacheAclManager,
models.ElasticcacheAccountManager,
models.ElasticcacheParameterManager,
models.ElasticcacheBackupManager,
} {
db.RegisterModelManager(manager)
handler := db.NewModelHandler(manager)

View File

@@ -39,6 +39,7 @@ const (
ALIYUN_API_VERSION = "2014-05-26"
ALIYUN_API_VERSION_VPC = "2016-04-28"
ALIYUN_API_VERSION_LB = "2014-05-15"
ALIYUN_API_VERSION_KVS = "2015-01-01"
ALIYUN_BSS_API_VERSION = "2017-12-14"

View File

@@ -0,0 +1,57 @@
package aliyun
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud"
)
// https://help.aliyun.com/document_detail/95802.html?spm=a2c4g.11186623.6.746.1d4b302ayCuzXB
type SElasticcacheAccount struct {
multicloud.SElasticcacheAccountBase
cacheDB *SElasticcache
AccountStatus string `json:"AccountStatus"`
DatabasePrivileges DatabasePrivileges `json:"DatabasePrivileges"`
InstanceID string `json:"InstanceId"`
AccountName string `json:"AccountName"`
PrivExceeded string `json:"PrivExceeded"`
AccountType string `json:"AccountType"`
}
type DatabasePrivileges struct {
DatabasePrivilege []DatabasePrivilege `json:"DatabasePrivilege"`
}
type DatabasePrivilege struct {
AccountPrivilege string `json:"AccountPrivilege"`
}
func (self *SElasticcacheAccount) GetId() string {
return fmt.Sprintf("%s/%s", self.InstanceID, self.AccountName)
}
func (self *SElasticcacheAccount) GetName() string {
return self.AccountName
}
func (self *SElasticcacheAccount) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcacheAccount) GetStatus() string {
return self.AccountStatus
}
func (self *SElasticcacheAccount) GetAccountType() string {
return self.AccountType
}
func (self *SElasticcacheAccount) GetAccountPrivilege() string {
if len(self.DatabasePrivileges.DatabasePrivilege) == 0 {
return ""
}
return self.DatabasePrivileges.DatabasePrivilege[0].AccountPrivilege
}

View File

@@ -0,0 +1,37 @@
package aliyun
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SElasticcacheAcl struct {
multicloud.SElasticcacheAclBase
cacheDB *SElasticcache
SecurityIPList string `json:"SecurityIpList"`
SecurityIPGroupAttribute string `json:"SecurityIpGroupAttribute"`
SecurityIPGroupName string `json:"SecurityIpGroupName"`
}
func (self *SElasticcacheAcl) GetId() string {
return fmt.Sprintf("%s/%s", self.cacheDB.GetId(), self.SecurityIPGroupName)
}
func (self *SElasticcacheAcl) GetName() string {
return self.SecurityIPGroupName
}
func (self *SElasticcacheAcl) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcacheAcl) GetStatus() string {
return ""
}
func (self *SElasticcacheAcl) GetIpList() string {
return self.SecurityIPList
}

View File

@@ -0,0 +1,68 @@
package aliyun
import (
"fmt"
"time"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SElasticcacheBackup struct {
multicloud.SElasticcacheBackupBase
cacheDB *SElasticcache
BackupIntranetDownloadURL string `json:"BackupIntranetDownloadURL"`
BackupType string `json:"BackupType"`
BackupEndTime time.Time `json:"BackupEndTime"`
BackupMethod string `json:"BackupMethod"`
BackupID int64 `json:"BackupId"`
BackupStartTime time.Time `json:"BackupStartTime"`
BackupDownloadURL string `json:"BackupDownloadURL"`
BackupDBNames string `json:"BackupDBNames"`
NodeInstanceID string `json:"NodeInstanceId"`
BackupMode string `json:"BackupMode"`
BackupStatus string `json:"BackupStatus"`
BackupSizeByte int64 `json:"BackupSize"`
EngineVersion string `json:"EngineVersion"`
}
func (self *SElasticcacheBackup) GetId() string {
return fmt.Sprintf("%d", self.BackupID)
}
func (self *SElasticcacheBackup) GetName() string {
return self.GetId()
}
func (self *SElasticcacheBackup) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcacheBackup) GetStatus() string {
return ""
}
func (self *SElasticcacheBackup) GetBackupSizeMb() int {
return int(self.BackupSizeByte / 1024 / 1024)
}
func (self *SElasticcacheBackup) GetBackupType() string {
return self.BackupType
}
func (self *SElasticcacheBackup) GetBackupMode() string {
return self.BackupMode
}
func (self *SElasticcacheBackup) GetDownloadURL() string {
return self.BackupDownloadURL
}
func (self *SElasticcacheBackup) GetStartTime() time.Time {
return self.BackupStartTime
}
func (self *SElasticcacheBackup) GetEndTime() time.Time {
return self.BackupEndTime
}

View File

@@ -0,0 +1,484 @@
package aliyun
import (
"strconv"
"time"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
// https://help.aliyun.com/document_detail/60933.html?spm=a2c4g.11186623.6.726.38f82ca9U1Gtxw
type SElasticcache struct {
multicloud.SElasticcacheBase
region *SRegion
attribute *SElasticcacheAttribute
netinfo []SNetInfo
Config string `json:"Config"`
HasRenewChangeOrder bool `json:"HasRenewChangeOrder"`
InstanceID string `json:"InstanceId"`
UserName string `json:"UserName"`
ArchitectureType string `json:"ArchitectureType"`
ZoneID string `json:"ZoneId"`
PrivateIP string `json:"PrivateIp"`
VSwitchID string `json:"VSwitchId"`
VpcID string `json:"VpcId"`
NetworkType string `json:"NetworkType"`
Qps int64 `json:"QPS"`
PackageType string `json:"PackageType"`
IsRDS bool `json:"IsRds"`
EngineVersion string `json:"EngineVersion"`
ConnectionDomain string `json:"ConnectionDomain"`
InstanceName string `json:"InstanceName"`
ReplacateID string `json:"ReplacateId"`
Bandwidth int64 `json:"Bandwidth"`
ChargeType TChargeType `json:"ChargeType"`
InstanceType string `json:"InstanceType"`
Tags Tags `json:"Tags"`
InstanceStatus string `json:"InstanceStatus"`
Port int `json:"Port"`
InstanceClass string `json:"InstanceClass"`
CreateTime time.Time `json:"CreateTime"`
EndTime time.Time `json:"EndTime"`
RegionID string `json:"RegionId"`
NodeType string `json:"NodeType"`
CapacityMB int `json:"Capacity"`
Connections int64 `json:"Connections"`
}
type SElasticcacheAttribute struct {
Config string `json:"Config"`
HasRenewChangeOrder string `json:"HasRenewChangeOrder"`
InstanceID string `json:"InstanceId"`
ZoneID string `json:"ZoneId"`
ArchitectureType string `json:"ArchitectureType"`
PrivateIP string `json:"PrivateIp"`
VSwitchID string `json:"VSwitchId"`
Engine string `json:"Engine"`
VpcID string `json:"VpcId"`
NetworkType string `json:"NetworkType"`
Qps int64 `json:"QPS"`
PackageType string `json:"PackageType"`
ReplicaID string `json:"ReplicaId"`
IsRDS bool `json:"IsRds"`
MaintainStartTime string `json:"MaintainStartTime"`
VpcAuthMode string `json:"VpcAuthMode"`
ConnectionDomain string `json:"ConnectionDomain"`
EngineVersion string `json:"EngineVersion"`
InstanceName string `json:"InstanceName"`
Bandwidth int64 `json:"Bandwidth"`
ChargeType TChargeType `json:"ChargeType"`
AuditLogRetention string `json:"AuditLogRetention"`
MaintainEndTime string `json:"MaintainEndTime"`
ReplicationMode string `json:"ReplicationMode"`
InstanceType string `json:"InstanceType"`
InstanceStatus string `json:"InstanceStatus"`
Tags Tags `json:"Tags"`
Port int64 `json:"Port"`
InstanceClass string `json:"InstanceClass"`
CreateTime time.Time `json:"CreateTime"`
NodeType string `json:"NodeType"`
RegionID string `json:"RegionId"`
AvailabilityValue string `json:"AvailabilityValue"`
CapacityMB int `json:"Capacity"`
Connections int64 `json:"Connections"`
SecurityIPList string `json:"SecurityIPList"`
}
type SNetInfo struct {
ConnectionString string `json:"ConnectionString"`
Port string `json:"Port"`
DBInstanceNetType string `json:"DBInstanceNetType"`
VPCID string `json:"VPCId"`
VPCInstanceID string `json:"VPCInstanceId"`
IPAddress string `json:"IPAddress"`
IPType string `json:"IPType"`
Upgradeable string `json:"Upgradeable"`
ExpiredTime *string `json:"ExpiredTime,omitempty"`
}
func (self *SElasticcache) GetId() string {
return self.InstanceID
}
func (self *SElasticcache) GetName() string {
return self.InstanceName
}
func (self *SElasticcache) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcache) GetStatus() string {
// todo: fix
return self.InstanceStatus
}
func (self *SElasticcache) GetBillingType() string {
return convertChargeType(self.ChargeType)
}
func (self *SElasticcache) GetCreatedAt() time.Time {
return self.CreateTime
}
func (self *SElasticcache) GetExpiredAt() time.Time {
return convertExpiredAt(self.EndTime)
}
func (self *SElasticcache) GetInstanceType() string {
return self.InstanceClass
}
func (self *SElasticcache) GetCapacityMB() int {
return self.CapacityMB
}
func (self *SElasticcache) GetArchType() string {
return self.ArchitectureType
}
func (self *SElasticcache) GetNodeType() string {
return self.NodeType
}
func (self *SElasticcache) GetEngine() string {
return self.InstanceType
}
func (self *SElasticcache) GetEngineVersion() string {
return self.EngineVersion
}
func (self *SElasticcache) GetVpcId() string {
return self.VpcID
}
func (self *SElasticcache) GetZoneId() string {
zone, err := self.region.getZoneById(self.ZoneID)
if err != nil {
log.Errorf("failed to find zone for elasticcache %s error: %v", self.GetId(), err)
return ""
}
return zone.GetGlobalId()
}
func (self *SElasticcache) GetNetworkType() string {
switch self.NetworkType {
case "VPC":
return api.LB_NETWORK_TYPE_VPC
case "CLASSIC":
return api.LB_NETWORK_TYPE_CLASSIC
default:
return api.LB_NETWORK_TYPE_VPC
}
}
func (self *SElasticcache) GetNetworkId() string {
return self.VSwitchID
}
func (self *SElasticcache) GetPrivateDNS() string {
return self.ConnectionDomain
}
func (self *SElasticcache) GetPrivateIpAddr() string {
return self.PrivateIP
}
func (self *SElasticcache) GetPrivateConnectPort() int {
return self.Port
}
func (self *SElasticcache) GetPublicDNS() string {
pub, err := self.GetPublicNetInfo()
if err != nil {
log.Errorf("SElasticcache.GetPublicDNS %s", err)
return ""
}
if pub != nil {
return pub.ConnectionString
}
return ""
}
func (self *SElasticcache) GetPublicIpAddr() string {
pub, err := self.GetPublicNetInfo()
if err != nil {
log.Errorf("SElasticcache.GetPublicIpAddr %s", err)
}
if pub != nil {
return pub.IPAddress
}
return ""
}
func (self *SElasticcache) GetPublicConnectPort() int {
pub, err := self.GetPublicNetInfo()
if err != nil {
log.Errorf("SElasticcache.GetPublicConnectPort %s", err)
}
if pub != nil {
port, _ := strconv.Atoi(pub.Port)
return port
}
return 0
}
func (self *SElasticcache) GetMaintainStartTime() string {
attr, err := self.GetAttribute()
if err != nil {
log.Errorf("SElasticcache.GetMaintainStartTime %s", err)
}
if attr != nil {
return attr.MaintainStartTime
}
return ""
}
func (self *SElasticcache) GetMaintainEndTime() string {
attr, err := self.GetAttribute()
if err != nil {
log.Errorf("SElasticcache.GetMaintainEndTime %s", err)
}
if attr != nil {
return attr.MaintainEndTime
}
return ""
}
func (self *SElasticcache) GetICloudElasticcacheAccounts() ([]cloudprovider.ICloudElasticcacheAccount, error) {
accounts, err := self.region.GetElasticCacheAccounts(self.GetId())
if err != nil {
return nil, err
}
iaccounts := make([]cloudprovider.ICloudElasticcacheAccount, len(accounts))
for i := range accounts {
accounts[i].cacheDB = self
iaccounts[i] = &accounts[i]
}
return iaccounts, nil
}
func (self *SElasticcache) GetICloudElasticcacheAcls() ([]cloudprovider.ICloudElasticcacheAcl, error) {
acls, err := self.region.GetElasticCacheAcls(self.GetId())
if err != nil {
return nil, err
}
iacls := make([]cloudprovider.ICloudElasticcacheAcl, len(acls))
for i := range acls {
acls[i].cacheDB = self
iacls[i] = &acls[i]
}
return iacls, nil
}
func (self *SElasticcache) GetICloudElasticcacheBackups() ([]cloudprovider.ICloudElasticcacheBackup, error) {
start := self.CreateTime.Format("2006-01-02T15:04Z")
end := time.Now().Format("2006-01-02T15:04Z")
backups, err := self.region.GetElasticCacheBackups(self.GetId(), start, end)
if err != nil {
return nil, err
}
ibackups := make([]cloudprovider.ICloudElasticcacheBackup, len(backups))
for i := range backups {
backups[i].cacheDB = self
ibackups[i] = &backups[i]
}
return ibackups, nil
}
func (self *SElasticcache) GetICloudElasticcacheParameters() ([]cloudprovider.ICloudElasticcacheParameter, error) {
parameters, err := self.region.GetElasticCacheParameters(self.GetId())
if err != nil {
return nil, err
}
iparameters := make([]cloudprovider.ICloudElasticcacheParameter, len(parameters))
for i := range parameters {
parameters[i].cacheDB = self
iparameters[i] = &parameters[i]
}
return iparameters, nil
}
func (self *SElasticcache) GetAttribute() (*SElasticcacheAttribute, error) {
if self.attribute != nil {
return self.attribute, nil
}
params := make(map[string]string)
params["RegionId"] = self.region.RegionId
params["InstanceId"] = self.GetId()
rets := []SElasticcacheAttribute{}
err := DoListAll(self.region.kvsRequest, "DescribeInstanceAttribute", params, []string{"Instances", "DBInstanceAttribute"}, &rets)
if err != nil {
return nil, errors.Wrap(err, "elasticcache.GetAttribute")
}
count := len(rets)
if count == 1 {
self.attribute = &rets[0]
return self.attribute, nil
} else if count == 0 {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "elasticcache.GetAttribute %s", self.GetId())
} else {
return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "elasticcache.GetAttribute %s.expect 1 found %d ", self.GetId(), count)
}
}
func (self *SElasticcache) GetNetInfo() ([]SNetInfo, error) {
if self.netinfo != nil && len(self.netinfo) > 0 {
return self.netinfo, nil
}
params := make(map[string]string)
params["RegionId"] = self.region.RegionId
params["InstanceId"] = self.GetId()
rets := []SNetInfo{}
err := DoListAll(self.region.kvsRequest, "DescribeDBInstanceNetInfo", params, []string{"NetInfoItems", "InstanceNetInfo"}, &rets)
if err != nil {
return nil, errors.Wrap(err, "elasticcache.GetNetInfo")
}
self.netinfo = rets
return self.netinfo, nil
}
func (self *SElasticcache) GetPublicNetInfo() (*SNetInfo, error) {
nets, err := self.GetNetInfo()
if err != nil {
return nil, err
}
for i := range nets {
if nets[i].DBInstanceNetType == "2" || nets[i].IPType == "Public" {
return &nets[i], nil
}
}
return nil, nil
}
func (self *SRegion) GetElasticCaches(instanceIds []string) ([]SElasticcache, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
if instanceIds != nil && len(instanceIds) > 0 {
params["InstanceIds"] = jsonutils.Marshal(instanceIds).String()
}
ret := []SElasticcache{}
err := DoListAll(self.kvsRequest, "DescribeInstances", params, []string{"Instances", "KVStoreInstance"}, &ret)
if err != nil {
return nil, errors.Wrap(err, "region.GetElasticCaches")
}
for i := range ret {
ret[i].region = self
}
return ret, nil
}
func (self *SRegion) GetElasticCacheById(instanceId string) (*SElasticcache, error) {
caches, err := self.GetElasticCaches([]string{instanceId})
if err != nil {
return nil, errors.Wrapf(err, "region.GetElasticCacheById %s", instanceId)
}
if len(caches) == 1 {
return &caches[0], nil
} else if len(caches) == 0 {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "region.GetElasticCacheById %s", instanceId)
} else {
return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "region.GetElasticCacheById %s.expect 1 found %d ", instanceId, len(caches))
}
}
// https://help.aliyun.com/document_detail/95802.html?spm=a2c4g.11186623.6.746.143e782f3Pfkfg
func (self *SRegion) GetElasticCacheAccounts(instanceId string) ([]SElasticcacheAccount, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["InstanceId"] = instanceId
ret := []SElasticcacheAccount{}
err := DoListAll(self.kvsRequest, "DescribeAccounts", params, []string{"Accounts", "Account"}, &ret)
if err != nil {
return nil, errors.Wrap(err, "region.GetElasticCacheAccounts")
}
return ret, nil
}
// https://help.aliyun.com/document_detail/63889.html?spm=a2c4g.11186623.6.764.3cb43852R7lnoS
func (self *SRegion) GetElasticCacheAcls(instanceId string) ([]SElasticcacheAcl, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["InstanceId"] = instanceId
ret := []SElasticcacheAcl{}
err := DoListAll(self.kvsRequest, "DescribeSecurityIps", params, []string{"SecurityIpGroups", "SecurityIpGroup"}, &ret)
if err != nil {
return nil, errors.Wrap(err, "region.GetElasticCacheAcls")
}
return ret, nil
}
// https://help.aliyun.com/document_detail/61081.html?spm=a2c4g.11186623.6.754.10613852qAbEQV
func (self *SRegion) GetElasticCacheBackups(instanceId, startTime, endTime string) ([]SElasticcacheBackup, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["InstanceId"] = instanceId
params["StartTime"] = startTime
params["EndTime"] = endTime
ret := []SElasticcacheBackup{}
err := DoListAll(self.kvsRequest, "DescribeBackups", params, []string{"Backups", "Backup"}, &ret)
if err != nil {
return nil, errors.Wrap(err, "region.GetElasticCacheBackups")
}
return ret, nil
}
// https://help.aliyun.com/document_detail/93078.html?spm=a2c4g.11186623.6.769.58011975YYL5Gl
func (self *SRegion) GetElasticCacheParameters(instanceId string) ([]SElasticcacheParameter, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["DBInstanceId"] = instanceId
ret := []SElasticcacheParameter{}
err := DoListAll(self.kvsRequest, "DescribeParameters", params, []string{"RunningParameters", "Parameter"}, &ret)
if err != nil {
return nil, errors.Wrap(err, "region.GetElasticCacheParameters")
}
return ret, nil
}

View File

@@ -0,0 +1,70 @@
package aliyun
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SElasticcacheParameter struct {
multicloud.SElasticcacheParameterBase
cacheDB *SElasticcache
ParameterDescription string `json:"ParameterDescription"`
ParameterValue string `json:"ParameterValue"`
ForceRestart string `json:"ForceRestart"`
CheckingCode string `json:"CheckingCode"`
ModifiableStatus string `json:"ModifiableStatus"`
ParameterName string `json:"ParameterName"`
}
func (self *SElasticcacheParameter) GetId() string {
return fmt.Sprintf("%s/%s", self.cacheDB.InstanceID, self.ParameterName)
}
func (self *SElasticcacheParameter) GetName() string {
return self.ParameterName
}
func (self *SElasticcacheParameter) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcacheParameter) GetStatus() string {
return ""
}
func (self *SElasticcacheParameter) GetParameterKey() string {
return self.ParameterName
}
func (self *SElasticcacheParameter) GetParameterValue() string {
return self.ParameterValue
}
func (self *SElasticcacheParameter) GetParameterValueRange() string {
return self.CheckingCode
}
func (self *SElasticcacheParameter) GetDescription() string {
return self.ParameterDescription
}
func (self *SElasticcacheParameter) GetModifiable() bool {
switch self.ModifiableStatus {
case "true":
return true
default:
return false
}
}
func (self *SElasticcacheParameter) GetForceRestart() bool {
switch self.ForceRestart {
case "true":
return true
default:
return false
}
}

View File

@@ -131,6 +131,14 @@ func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonut
return jsonRequest(client, "vpc.aliyuncs.com", ALIYUN_API_VERSION_VPC, action, params, self.client.Debug)
}
func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
client, err := self.getSdkClient()
if err != nil {
return nil, err
}
return jsonRequest(client, "r-kvstore.aliyuncs.com", ALIYUN_API_VERSION_KVS, action, params, self.client.Debug)
}
type LBRegion struct {
RegionEndpoint string
RegionId string
@@ -1077,3 +1085,18 @@ func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket,
}
return &b, nil
}
func (self *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) {
caches, err := self.GetElasticCaches(nil)
if err != nil {
return nil, err
}
icaches := make([]cloudprovider.ICloudElasticcache, len(caches))
for i := range caches {
caches[i].region = self
icaches[i] = &caches[i]
}
return icaches, nil
}

View File

@@ -0,0 +1,73 @@
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type ElasticcacheListOptions struct {
}
shellutils.R(&ElasticcacheListOptions{}, "elasticcache-list", "List elasticcaches", func(cli *aliyun.SRegion, args *ElasticcacheListOptions) error {
instances, e := cli.GetElasticCaches(nil)
if e != nil {
return e
}
printList(instances, len(instances), 0, 0, []string{})
return nil
})
type ElasticcacheIdOptions struct {
ID string `help:"ID of instances to show"`
}
shellutils.R(&ElasticcacheIdOptions{}, "elasticcache-show", "Show elasticcache", func(cli *aliyun.SRegion, args *ElasticcacheIdOptions) error {
instance, err := cli.GetElasticCacheById(args.ID)
if err != nil {
return err
}
printObject(instance)
return nil
})
type ElasticcacheBackupsListOptions struct {
ID string `help:"ID of instances to show"`
StartTime string `help:"backup start time. format: 2019-03-11T10:00Z"`
EndTime string `help:"backup end time. format: 2019-03-11T10:00Z"`
}
shellutils.R(&ElasticcacheBackupsListOptions{}, "elasticcache-backup-list", "List elasticcache backups", func(cli *aliyun.SRegion, args *ElasticcacheBackupsListOptions) error {
backups, err := cli.GetElasticCacheBackups(args.ID, args.StartTime, args.EndTime)
if err != nil {
return err
}
printList(backups, 0, 0, 0, []string{})
return nil
})
shellutils.R(&ElasticcacheIdOptions{}, "elasticcache-parameter-list", "List elasticcache parameters", func(cli *aliyun.SRegion, args *ElasticcacheIdOptions) error {
parameters, err := cli.GetElasticCacheParameters(args.ID)
if err != nil {
return err
}
printList(parameters, 0, 0, 0, []string{})
return nil
})
shellutils.R(&ElasticcacheIdOptions{}, "elasticcache-account-list", "List elasticcache accounts", func(cli *aliyun.SRegion, args *ElasticcacheIdOptions) error {
accounts, err := cli.GetElasticCacheAccounts(args.ID)
if err != nil {
return err
}
printList(accounts, 0, 0, 0, []string{})
return nil
})
shellutils.R(&ElasticcacheIdOptions{}, "elasticcache-acl-list", "List elasticcache security ip rules", func(cli *aliyun.SRegion, args *ElasticcacheIdOptions) error {
acls, err := cli.GetElasticCacheAcls(args.ID)
if err != nil {
return err
}
printList(acls, 0, 0, 0, []string{})
return nil
})
}

View File

@@ -0,0 +1,92 @@
package aliyun
import (
"fmt"
"reflect"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
)
type jsonRequestFunc func(action string, params map[string]string) (jsonutils.JSONObject, error)
func unmarshalResult(resp jsonutils.JSONObject, respErr error, resultKey []string, result interface{}) error {
if respErr != nil {
return respErr
}
if result == nil {
return nil
}
if resultKey != nil && len(resultKey) > 0 {
respErr = resp.Unmarshal(result, resultKey...)
} else {
respErr = resp.Unmarshal(result)
}
if respErr != nil {
log.Errorf("unmarshal json error %s", respErr)
}
return nil
}
func doListPart(client jsonRequestFunc, action string, limit int, offset int, params map[string]string, resultKey []string, result interface{}) (int, int, error) {
params["PageSize"] = fmt.Sprintf("%d", limit)
params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
ret, err := client(action, params)
if err != nil {
return 0, 0, err
}
total, _ := ret.Int("TotalCount")
var lst []jsonutils.JSONObject
lst, err = ret.GetArray(resultKey...)
if err != nil {
return 0, 0, nil
}
resultValue := reflect.Indirect(reflect.ValueOf(result))
elemType := resultValue.Type().Elem()
for i := range lst {
elemPtr := reflect.New(elemType)
err = lst[i].Unmarshal(elemPtr.Interface())
if err != nil {
return 0, 0, err
}
resultValue.Set(reflect.Append(resultValue, elemPtr.Elem()))
}
return int(total), len(lst), nil
}
// 执行操作
func DoAction(client jsonRequestFunc, action string, params map[string]string, resultKey []string, result interface{}) error {
resp, err := client(action, params)
return unmarshalResult(resp, err, resultKey, result)
}
// 遍历所有结果
func DoListAll(client jsonRequestFunc, action string, params map[string]string, resultKey []string, result interface{}) error {
pageLimit := 50
offset := 0
resultValue := reflect.Indirect(reflect.ValueOf(result))
for {
total, part, err := doListPart(client, action, pageLimit, offset, params, resultKey, result)
if err != nil {
return err
}
// total 大于零的情况下通过total字段判断列表是否遍历完成。total不存在或者为0的情况下通过返回列表的长度判断是否遍历完成
if (total > 0 && resultValue.Len() >= total) || (total == 0 && pageLimit > part) {
break
}
offset = resultValue.Len()
}
return nil
}

View File

@@ -0,0 +1,21 @@
package multicloud
type SElasticcacheBase struct {
SVirtualResourceBase
}
type SElasticcacheBackupBase struct {
SResourceBase
}
type SElasticcacheAccountBase struct {
SResourceBase
}
type SElasticcacheAclBase struct {
SResourceBase
}
type SElasticcacheParameterBase struct {
SResourceBase
}

View File

@@ -36,6 +36,7 @@ type Client struct {
Disks *modules.SDiskManager
Domains *modules.SDomainManager
Eips *modules.SEipManager
Elasticcache *modules.SElasticcacheManager
Flavors *modules.SFlavorManager
Images *modules.SImageManager
OpenStackImages *modules.SImageManager
@@ -118,6 +119,7 @@ func (self *Client) initManagers() {
self.Zones = modules.NewZoneManager(self.regionId, self.projectId, self.signer, self.debug)
self.Vpcs = modules.NewVpcManager(self.regionId, self.projectId, self.signer, self.debug)
self.Eips = modules.NewEipManager(self.regionId, self.projectId, self.signer, self.debug)
self.Elasticcache = modules.NewElasticcacheManager(self.regionId, self.projectId, self.signer, self.debug)
self.Disks = modules.NewDiskManager(self.regionId, self.projectId, self.signer, self.debug)
self.Domains = modules.NewDomainManager(self.signer, self.debug)
self.Keypairs = modules.NewKeypairManager(self.regionId, self.projectId, self.signer, self.debug)

View File

@@ -46,7 +46,7 @@ const (
ServiceNameELB ServiceNameType = "elb" // 弹性负载均衡 ELB
ServiceNameBSS ServiceNameType = "bss" // 合作伙伴运营能力
ServiceNameNAT ServiceNameType = "nat" // Nat网关 NAT
ServiceNameDCS ServiceNameType = "dcs" // 分布式缓存服务
)
type SManagerContext struct {

View File

@@ -0,0 +1,52 @@
package modules
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/auth"
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/responses"
)
type SElasticcacheManager struct {
SResourceManager
}
func NewElasticcacheManager(regionId string, projectId string, signer auth.Signer, debug bool) *SElasticcacheManager {
return &SElasticcacheManager{SResourceManager: SResourceManager{
SBaseManager: NewBaseManager(signer, debug),
ServiceName: ServiceNameDCS,
Region: regionId,
ProjectId: projectId,
version: "v1.0",
Keyword: "instance",
KeywordPlural: "instances",
ResourceKeyword: "instances",
}}
}
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423035.html
func (self *SElasticcacheManager) ListBackups(queries map[string]string) (*responses.ListResult, error) {
var spec string
if id, _ := queries["instance_id"]; len(id) == 0 {
return nil, fmt.Errorf("SElasticcacheManager.ListBackups missing parameter instance_id")
} else {
spec = fmt.Sprintf("%s/backups", id)
}
delete(queries, "instance_id")
return self.ListInContextWithSpec(nil, spec, queries, "backup_record_response")
}
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423027.html
func (self *SElasticcacheManager) ListParameters(queries map[string]string) (*responses.ListResult, error) {
var spec string
if id, _ := queries["instance_id"]; len(id) == 0 {
return nil, fmt.Errorf("SElasticcacheManager.ListParameters missing parameter instance_id")
} else {
spec = fmt.Sprintf("%s/configs", id)
}
delete(queries, "instance_id")
return self.ListInContextWithSpec(nil, spec, queries, "redis_config")
}

View File

@@ -0,0 +1,37 @@
package huawei
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SElasticcacheAccount struct {
multicloud.SElasticcacheAccountBase
cacheDB *SElasticcache
}
func (self *SElasticcacheAccount) GetId() string {
return fmt.Sprintf("%s/%s", self.cacheDB.InstanceID, self.cacheDB.AccessUser)
}
func (self *SElasticcacheAccount) GetName() string {
return self.cacheDB.AccessUser
}
func (self *SElasticcacheAccount) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcacheAccount) GetStatus() string {
return ""
}
func (self *SElasticcacheAccount) GetAccountType() string {
return "admin"
}
func (self *SElasticcacheAccount) GetAccountPrivilege() string {
return "write"
}

View File

@@ -0,0 +1,69 @@
package huawei
import (
"time"
"yunion.io/x/onecloud/pkg/multicloud"
)
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423035.html
type SElasticcacheBackup struct {
multicloud.SElasticcacheBackupBase
cacheDB *SElasticcache
Status string `json:"status"`
Remark string `json:"remark"`
Period string `json:"period"`
Progress string `json:"progress"`
SizeByte int64 `json:"size"`
InstanceID string `json:"instance_id"`
BackupID string `json:"backup_id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ExecutionAt time.Time `json:"execution_at"`
BackupType string `json:"backup_type"`
BackupName string `json:"backup_name"`
ErrorCode string `json:"error_code"`
IsSupportRestore string `json:"is_support_restore"`
}
func (self *SElasticcacheBackup) GetId() string {
return self.BackupID
}
func (self *SElasticcacheBackup) GetName() string {
return self.BackupName
}
func (self *SElasticcacheBackup) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcacheBackup) GetStatus() string {
return self.Status
}
func (self *SElasticcacheBackup) GetBackupSizeMb() int {
return int(self.SizeByte / 1024 / 1024)
}
func (self *SElasticcacheBackup) GetBackupType() string {
return self.BackupType
}
func (self *SElasticcacheBackup) GetBackupMode() string {
return ""
}
func (self *SElasticcacheBackup) GetDownloadURL() string {
return ""
}
func (self *SElasticcacheBackup) GetStartTime() time.Time {
return self.CreatedAt
}
func (self *SElasticcacheBackup) GetEndTime() time.Time {
return self.UpdatedAt
}

View File

@@ -0,0 +1,314 @@
package huawei
import (
"time"
"github.com/pkg/errors"
"yunion.io/x/log"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423020.html
type SElasticcache struct {
multicloud.SElasticcacheBase
region *SRegion
Name string `json:"name"`
Engine string `json:"engine"`
CapacityGB int `json:"capacity"`
IP string `json:"ip"`
DomainName string `json:"domainName"`
Port int `json:"port"`
Status string `json:"status"`
Libos bool `json:"libos"`
Description string `json:"description"`
Task string `json:"task"`
MaxMemoryMB int `json:"max_memory"`
UsedMemoryMB int `json:"used_memory"`
InstanceID string `json:"instance_id"`
ResourceSpecCode string `json:"resource_spec_code"`
EngineVersion string `json:"engine_version"`
InternalVersion string `json:"internal_version"`
ChargingMode int `json:"charging_mode"`
CapacityMinor string `json:"capacity_minor"`
VpcID string `json:"vpc_id"`
VpcName string `json:"vpc_name"`
TaskStatus string `json:"task_status"`
CreatedAt string `json:"created_at"`
ErrorCode string `json:"error_code"`
UserID string `json:"user_id"`
UserName string `json:"user_name"`
MaintainBegin string `json:"maintain_begin"`
MaintainEnd string `json:"maintain_end"`
NoPasswordAccess string `json:"no_password_access"`
AccessUser string `json:"access_user"`
EnablePublicip bool `json:"enable_publicip"`
PublicipID string `json:"publicip_id"`
PublicipAddress string `json:"publicip_address"`
EnableSSL bool `json:"enable_ssl"`
ServiceUpgrade bool `json:"service_upgrade"`
ServiceTaskID string `json:"service_task_id"`
IsFree string `json:"is_free"`
EnterpriseProjectID string `json:"enterprise_project_id"`
AvailableZones []string `json:"available_zones"`
SubnetID string `json:"subnet_id"`
SecurityGroupID string `json:"security_group_id"`
BackendAddrs []string `json:"backend_addrs"`
ProductID string `json:"product_id"`
SecurityGroupName string `json:"security_group_name"`
SubnetName string `json:"subnet_name"`
OrderID string `json:"order_id"`
SubnetCIDR string `json:"subnet_cidr"`
InstanceBackupPolicy string `json:"instance_backup_policy"`
EnterpriseProjectName string `json:"enterprise_project_name"`
}
func (self *SElasticcache) GetId() string {
return self.InstanceID
}
func (self *SElasticcache) GetName() string {
return self.Name
}
func (self *SElasticcache) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcache) GetStatus() string {
return self.Status
}
func (self *SElasticcache) GetBillingType() string {
// charging_mode “0”按需计费 “1”按包年包月计费
if self.ChargingMode == 1 {
return billing_api.BILLING_TYPE_PREPAID
} else {
return billing_api.BILLING_TYPE_POSTPAID
}
}
func (self *SElasticcache) GetCreatedAt() time.Time {
var createtime time.Time
if len(self.CreatedAt) > 0 {
createtime, _ = time.Parse("2006-01-02T15:04:05.000Z", self.CreatedAt)
}
return createtime
}
func (self *SElasticcache) GetExpiredAt() time.Time {
var expiredTime time.Time
if self.ChargingMode == 1 {
res, err := self.region.GetOrderResourceDetail(self.GetId())
if err != nil {
log.Debugln(err)
}
expiredTime = res.ExpireTime
}
return expiredTime
}
func (self *SElasticcache) GetInstanceType() string {
// todo: ??
return self.ResourceSpecCode
}
func (self *SElasticcache) GetCapacityMB() int {
return self.CapacityGB * 1024
}
func (self *SElasticcache) GetArchType() string {
/*
资源规格标识。
dcs.single_node表示实例类型为单机
dcs.master_standby表示实例类型为主备
dcs.cluster表示实例类型为集群
*/
return ""
}
func (self *SElasticcache) GetNodeType() string {
return ""
}
func (self *SElasticcache) GetEngine() string {
return self.Engine
}
func (self *SElasticcache) GetEngineVersion() string {
return self.EngineVersion
}
func (self *SElasticcache) GetVpcId() string {
return self.VpcID
}
func (self *SElasticcache) GetZoneId() string {
if len(self.AvailableZones) > 0 {
return self.AvailableZones[0]
}
return ""
}
func (self *SElasticcache) GetNetworkType() string {
return api.LB_NETWORK_TYPE_VPC
}
func (self *SElasticcache) GetNetworkId() string {
return self.SubnetID
}
func (self *SElasticcache) GetPrivateDNS() string {
return self.DomainName
}
func (self *SElasticcache) GetPrivateIpAddr() string {
return self.IP
}
func (self *SElasticcache) GetPrivateConnectPort() int {
return self.Port
}
func (self *SElasticcache) GetPublicDNS() string {
return self.PublicipAddress
}
func (self *SElasticcache) GetPublicIpAddr() string {
return self.PublicipAddress
}
func (self *SElasticcache) GetPublicConnectPort() int {
return self.Port
}
func (self *SElasticcache) GetMaintainStartTime() string {
return self.MaintainBegin
}
func (self *SElasticcache) GetMaintainEndTime() string {
return self.MaintainEnd
}
func (self *SElasticcache) GetICloudElasticcacheAccounts() ([]cloudprovider.ICloudElasticcacheAccount, error) {
iaccounts := []cloudprovider.ICloudElasticcacheAccount{}
if len(self.AccessUser) > 0 {
iaccount := &SElasticcacheAccount{cacheDB: self}
iaccounts = append(iaccounts, iaccount)
}
return iaccounts, nil
}
func (self *SElasticcache) GetICloudElasticcacheAcls() ([]cloudprovider.ICloudElasticcacheAcl, error) {
// 华为云使用安全组做访问控制。目前未支持
return []cloudprovider.ICloudElasticcacheAcl{}, nil
}
func (self *SElasticcache) GetICloudElasticcacheBackups() ([]cloudprovider.ICloudElasticcacheBackup, error) {
start := self.GetCreatedAt().Format("20060102150405")
end := time.Now().Format("20060102150405")
backups, err := self.region.GetElasticCacheBackups(self.GetId(), start, end)
if err != nil {
return nil, err
}
ibackups := make([]cloudprovider.ICloudElasticcacheBackup, len(backups))
for i := range backups {
backups[i].cacheDB = self
ibackups[i] = &backups[i]
}
return ibackups, nil
}
func (self *SElasticcache) GetICloudElasticcacheParameters() ([]cloudprovider.ICloudElasticcacheParameter, error) {
parameters, err := self.region.GetElasticCacheParameters(self.GetId())
if err != nil {
return nil, err
}
iparameters := make([]cloudprovider.ICloudElasticcacheParameter, len(parameters))
for i := range parameters {
parameters[i].cacheDB = self
iparameters[i] = &parameters[i]
}
return iparameters, nil
}
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423035.html
func (self *SRegion) GetElasticCacheBackups(instanceId, startTime, endTime string) ([]SElasticcacheBackup, error) {
params := make(map[string]string)
params["instance_id"] = instanceId
params["beginTime"] = startTime
params["endTime"] = endTime
backups := make([]SElasticcacheBackup, 0)
err := doListAll(self.ecsClient.Elasticcache.ListBackups, params, &backups)
if err != nil {
return nil, err
}
return backups, nil
}
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423027.html
func (self *SRegion) GetElasticCacheParameters(instanceId string) ([]SElasticcacheParameter, error) {
params := make(map[string]string)
params["instance_id"] = instanceId
parameters := make([]SElasticcacheParameter, 0)
err := doListAll(self.ecsClient.Elasticcache.ListParameters, params, &parameters)
if err != nil {
return nil, err
}
return parameters, nil
}
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423044.html
func (self *SRegion) GetElasticCaches() ([]SElasticcache, error) {
params := make(map[string]string)
caches := make([]SElasticcache, 0)
err := doListAll(self.ecsClient.Elasticcache.List, params, &caches)
if err != nil {
return nil, errors.Wrap(err, "region.GetElasticCaches")
}
for i := range caches {
cache, err := self.GetElasticCache(caches[i].GetId())
if err != nil {
return nil, err
} else {
caches[i] = *cache
}
caches[i].region = self
}
return caches, nil
}
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423020.html
func (self *SRegion) GetElasticCache(instanceId string) (*SElasticcache, error) {
cache := SElasticcache{}
err := DoGet(self.ecsClient.Elasticcache.Get, instanceId, nil, &cache)
if err != nil {
return nil, errors.Wrapf(err, "region.GetElasticCache %s", instanceId)
}
cache.region = self
return &cache, nil
}

View File

@@ -0,0 +1,62 @@
package huawei
import (
"fmt"
"yunion.io/x/onecloud/pkg/multicloud"
)
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423027.html
type SElasticcacheParameter struct {
multicloud.SElasticcacheParameterBase
cacheDB *SElasticcache
Description string `json:"description"`
ParamID int64 `json:"param_id"`
ParamName string `json:"param_name"`
ParamValue string `json:"param_value"`
DefaultValue string `json:"default_value"`
ValueType string `json:"value_type"`
ValueRange string `json:"value_range"`
}
func (self *SElasticcacheParameter) GetId() string {
return fmt.Sprintf("%d", self.ParamID)
}
func (self *SElasticcacheParameter) GetName() string {
return self.ParamName
}
func (self *SElasticcacheParameter) GetGlobalId() string {
return fmt.Sprintf("%s/%s", self.cacheDB.InstanceID, self.GetId())
}
func (self *SElasticcacheParameter) GetStatus() string {
return ""
}
func (self *SElasticcacheParameter) GetParameterKey() string {
return self.ParamName
}
func (self *SElasticcacheParameter) GetParameterValue() string {
return self.ParamValue
}
func (self *SElasticcacheParameter) GetParameterValueRange() string {
return self.Description
}
func (self *SElasticcacheParameter) GetDescription() string {
return self.ValueRange
}
func (self *SElasticcacheParameter) GetModifiable() bool {
return true
}
func (self *SElasticcacheParameter) GetForceRestart() bool {
return false
}

View File

@@ -79,6 +79,10 @@ type Pool struct {
}
func (self *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
if self.GetEip() == nil {
return nil, nil
}
return self.eip, nil
}

View File

@@ -1026,3 +1026,18 @@ func (region *SRegion) GetIBucketById(name string) (cloudprovider.ICloudBucket,
func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) {
caches, err := self.GetElasticCaches()
if err != nil {
return nil, err
}
icaches := make([]cloudprovider.ICloudElasticcache, len(caches))
for i := range caches {
caches[i].region = self
icaches[i] = &caches[i]
}
return icaches, nil
}

View File

@@ -0,0 +1,55 @@
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/huawei"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type ElasticcacheListOptions struct {
}
shellutils.R(&ElasticcacheListOptions{}, "dcs-list", "List elasticcaches", func(cli *huawei.SRegion, args *ElasticcacheListOptions) error {
instances, e := cli.GetElasticCaches()
if e != nil {
return e
}
printList(instances, len(instances), 0, 0, []string{})
return nil
})
type ElasticcacheIdOptions struct {
ID string `help:"ID of instances to show"`
}
shellutils.R(&ElasticcacheIdOptions{}, "dcs-show", "Show elasticcache", func(cli *huawei.SRegion, args *ElasticcacheIdOptions) error {
instance, err := cli.GetElasticCache(args.ID)
if err != nil {
return err
}
printObject(instance)
return nil
})
type ElasticcacheBackupsListOptions struct {
ID string `help:"ID of instances to show"`
StartTime string `help:"backup start time. format: 20060102150405"`
EndTime string `help:"backup end time. format: 20060102150405 "`
}
shellutils.R(&ElasticcacheBackupsListOptions{}, "dcs-backup-list", "List elasticcache backups", func(cli *huawei.SRegion, args *ElasticcacheBackupsListOptions) error {
backups, err := cli.GetElasticCacheBackups(args.ID, args.StartTime, args.EndTime)
if err != nil {
return err
}
printList(backups, 0, 0, 0, []string{})
return nil
})
shellutils.R(&ElasticcacheIdOptions{}, "dcs-parameter-list", "List elasticcache parameters", func(cli *huawei.SRegion, args *ElasticcacheIdOptions) error {
parameters, err := cli.GetElasticCacheParameters(args.ID)
if err != nil {
return err
}
printList(parameters, 0, 0, 0, []string{})
return nil
})
}

View File

@@ -69,3 +69,7 @@ func (self *SRegion) GetIDBInstances() ([]cloudprovider.ICloudDBInstance, error)
func (self *SRegion) GetIDBInstanceBackups() ([]cloudprovider.ICloudDBInstanceBackup, error) {
return nil, fmt.Errorf("Not Implemented GetIDBInstanceBackups")
}
func (self *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) {
return nil, fmt.Errorf("Not Implemented GetIElasticcaches")
}