qcloud redis support

This commit is contained in:
TangBin
2020-10-16 11:58:12 +08:00
parent 81df94b277
commit d7894776f3
60 changed files with 3445 additions and 59 deletions
+4
View File
@@ -46,6 +46,10 @@ func init() {
return err
}
if len(opts.SecgroupIds) > 0 {
params.Set("secgroup_ids", jsonutils.NewStringArray(opts.SecgroupIds))
}
result, err := modules.ElasticCache.Create(s, params)
if err != nil {
return err
+1 -1
View File
@@ -141,7 +141,7 @@ require (
k8s.io/cluster-bootstrap v0.17.3
k8s.io/kubernetes v1.16.0
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74
yunion.io/x/jsonutils v0.0.0-20201014025429-7ce189228db6
yunion.io/x/jsonutils v0.0.0-20201022101715-4e3add1ac4aa
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6
+2 -3
View File
@@ -1124,10 +1124,9 @@ vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74 h1:A15C6VdVRWvmQ9pAJHrUs9yan5qKlYH7uaRxHg1kRbk=
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
yunion.io/x/jsonutils v0.0.0-20201014025429-7ce189228db6 h1:RPpnTSCZwa9VQuWAf7S2dRjnZlYTIM0NH/j5vvUpk9g=
yunion.io/x/jsonutils v0.0.0-20201014025429-7ce189228db6/go.mod h1:p0nyMqGA/apTxxyLIU/o1k4V7Vujl2O6ey30L594sYE=
yunion.io/x/jsonutils v0.0.0-20201022101715-4e3add1ac4aa h1:IbxIwaRpdLJhxAzLc8TzNvCWec79o9wCA8jXDcRszlA=
yunion.io/x/jsonutils v0.0.0-20201022101715-4e3add1ac4aa/go.mod h1:p0nyMqGA/apTxxyLIU/o1k4V7Vujl2O6ey30L594sYE=
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d h1:59zrDL7Ft+hDukguJRmLr/Gdu/9V75x+yX99ovZwfaA=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3 h1:5Wc5hkB8PtMudmHuzCyok960RuOa9I55imIGrigSdjs=
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
+117 -1
View File
@@ -14,7 +14,11 @@
package compute
import "yunion.io/x/onecloud/pkg/apis"
import (
"time"
"yunion.io/x/onecloud/pkg/apis"
)
type ElasticcacheDetails struct {
apis.VirtualResourceDetails
@@ -25,6 +29,9 @@ type ElasticcacheDetails struct {
// IP子网名称
Network string `json:"network"`
// 关联安全组列表
Secgroups []apis.StandaloneShortDesc `json:"secgroups"`
}
type ElasticcacheResourceInfo struct {
@@ -99,3 +106,112 @@ type ElasticcacheRemoteUpdateInput struct {
// 是否覆盖替换所有标签
ReplaceTags *bool `json:"replace_tags" help:"replace all remote tags"`
}
//type SElasticcacheJointsBase struct {
// apis.SVirtualJointResourceBase
// // 弹性缓存实例(ID or Name)
// ElasticcacheId string `json:"elasticcache_id"`
//}
type ElasticcacheJointResourceDetails struct {
apis.VirtualJointResourceBaseDetails
// 弹性缓存实例名称
Elasticcache string `json:"elasticcache"`
// 弹性缓存实例ID
ElasticcacheId string `json:"elasticcache_id"`
}
type ElasticcacheJointsListInput struct {
apis.VirtualJointResourceBaseListInput
ElasticcacheFilterListInput
}
type ElasticcacheJointBaseUpdateInput struct {
apis.VirtualJointResourceBaseUpdateInput
}
type ElasticcacheSecgroupsInput struct {
// 安全组Id列表
// 实例必须处于运行状态
//
//
// | 平台 | 最多绑定安全组数量 |
// |-------------|------------------- |
// | 腾讯云 | 10 |
// | 华为云 | 不支持安全组 |
// | 阿里云 | 不支持安全组 |
SecgroupIds []string `json:"secgroup_ids"`
}
type ElasticcacheCreateInput struct {
apis.VirtualResourceCreateInput
// 安全组列表
// 腾讯云需要传此参数
// required: false
ElasticcacheSecgroupsInput
// 主可用区名称或Id
Zone string `json:"zone"`
// Ip子网名称或Id,建议使用Id
// required: true
Network string `json:"network"`
// 网络类型
// enum: vpc, cLassic
// required: true
NetworkType string `json:"network_type"`
// 弹性缓存Engine
// enum: redis, memcache
// required: true
Engine string `json:"engine"`
// 弹性缓存Engine版本
// required: false
EngineVersion string `json:"engine_version"`
// 实例规格
// required: false
InstanceType string `json:"instance_type"`
// 初始密码
// required: false
Password string `json:"password"`
// 安全组名称或Id
// default: default
Secgroup string `json:"secgroup"`
// 内网IP
// 阿里云、华为云此参数可选,其它公有云该参数无效
// required: false
PrivateIp string `json:"private_ip"`
// swagger:ignore
VpcId string
// swagger:ignore
ManagerId string
// 包年包月时间周期
Duration string `json:"duration"`
// swagger:ignore
ExpiredAt time.Time `json:"expired_at"`
// 计费方式
// enum: postpaid, prepaid
BillingType string
// swagger:ignore
BillingCycle string
// 弹性缓存维护时间段
// 华为云此参数可选,其它云该参数无效
// enum: 22:00:00, 02:00:00, 06:00:00, 10:00:00, 14:00:00, 18:00:00
// required: false
MaintainStartTime string `json:"maintain_start_time"`
}
+2
View File
@@ -29,6 +29,7 @@ const (
ELASTIC_CACHE_STATUS_INACTIVE = "inactive" //(被禁用)
ELASTIC_CACHE_STATUS_FLUSHING = "flushing" //(清除中)
ELASTIC_CACHE_STATUS_FLUSHING_FAILED = "flushing_failed" //(清除失败)
ELASTIC_CACHE_STATUS_RELEASING = "releasing" //(释放中)
ELASTIC_CACHE_STATUS_RELEASED = "released" //(已释放)
ELASTIC_CACHE_STATUS_RELEASE_FAILED = "release_failed" //(释放失败)
ELASTIC_CACHE_STATUS_TRANSFORMING = "transforming" //(转换中)
@@ -52,6 +53,7 @@ const (
ELASTIC_CACHE_ACCOUNT_STATUS_CREATE_FAILED = "create_failed" //(创建失败)
ELASTIC_CACHE_ACCOUNT_STATUS_DELETING = "deleting" // 删除中
ELASTIC_CACHE_ACCOUNT_STATUS_DELETE_FAILED = "delete_failed" // 删除失败
ELASTIC_CACHE_ACCOUNT_STATUS_DELETED = "deleted" // 已删除
)
const (
+20
View File
@@ -135,6 +135,7 @@ type SecgroupListInput struct {
ServerFilterListInput
DBInstanceResourceInput
ELasticcacheResourceInput
// equals
Equals string
@@ -242,6 +243,11 @@ type GuestsecgroupListInput struct {
SecgroupFilterListInput
}
type ElasticcachesecgroupListInput struct {
ElasticcacheJointsListInput
SecgroupFilterListInput
}
type GuestsecgroupDetails struct {
GuestJointResourceDetails
@@ -251,6 +257,20 @@ type GuestsecgroupDetails struct {
Secgroup string `json:"secgroup"`
}
//type SElasticcachesecgroup struct {
// SElasticcacheJointsBase
// SSecurityGroupResourceBase
//}
type ElasticcachesecgroupDetails struct {
ElasticcacheJointResourceDetails
SElasticcachesecgroup
// 安全组名称
Secgroup string `json:"secgroup"`
}
type SecgroupMergeInput struct {
// 安全组id列表
SecgroupIds []string `json:"secgroup_ids"`
+12
View File
@@ -681,6 +681,12 @@ type SElasticcacheBackup struct {
EndTime time.Time `json:"end_time"`
}
// SElasticcacheJointsBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SElasticcacheJointsBase.
type SElasticcacheJointsBase struct {
apis.SVirtualJointResourceBase
SElasticcacheResourceBase
}
// SElasticcacheParameter is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SElasticcacheParameter.
type SElasticcacheParameter struct {
apis.SStatusStandaloneResourceBase
@@ -755,6 +761,12 @@ type SElasticcacheSku struct {
Provider string `json:"provider"`
}
// SElasticcachesecgroup is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SElasticcachesecgroup.
type SElasticcachesecgroup struct {
SElasticcacheJointsBase
SSecurityGroupResourceBase
}
// SElasticip is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SElasticip.
type SElasticip struct {
apis.SVirtualResourceBase
+5 -1
View File
@@ -34,7 +34,7 @@ type SCloudElasticCacheInput struct {
Engine string // Redis|Memcache
EngineVersion string // 版本类型
PrivateIpAddress string // 指定新实例的内网IP地址。
SecurityGroupId string // 安全组ID
SecurityGroupIds []string // 安全组ID
EipId string // 绑定弹性IP
MaintainBegin string // 维护时间窗开始时间,格式为HH:mm:ss
MaintainEnd string // 维护时间窗结束时间,格式为HH:mm:ss
@@ -70,3 +70,7 @@ type SCloudElasticCacheBackupPolicyUpdateInput struct {
PreferredBackupPeriod string // Monday(周一) / Tuesday(周二) / Wednesday(周三) / Thursday(周四) / Friday(周五) / Saturday(周六) / Sunday(周日)
PreferredBackupTime string // 备份时间,格式:HH:mmZ-HH:mmZ
}
type SCloudElasticCacheFlushInstanceInput struct {
Password string // root账号密码. requied by qcloud
}
+4 -2
View File
@@ -887,6 +887,7 @@ type ICloudElasticcache interface {
GetMaintainEndTime() string
GetAuthMode() string
GetSecurityGroupIds() ([]string, error)
GetICloudElasticcacheAccounts() ([]ICloudElasticcacheAccount, error)
GetICloudElasticcacheAcls() ([]ICloudElasticcacheAcl, error)
@@ -906,13 +907,14 @@ type ICloudElasticcache interface {
CreateAccount(account SCloudElasticCacheAccountInput) (ICloudElasticcacheAccount, error)
CreateAcl(aclName, securityIps string) (ICloudElasticcacheAcl, error)
CreateBackup() (ICloudElasticcacheBackup, error)
FlushInstance() error
CreateBackup(desc string) (ICloudElasticcacheBackup, error)
FlushInstance(input SCloudElasticCacheFlushInstanceInput) error
UpdateAuthMode(noPasswordAccess bool) error
UpdateInstanceParameters(config jsonutils.JSONObject) error
UpdateBackupPolicy(config SCloudElasticCacheBackupPolicyUpdateInput) error
SetMetadata(tags map[string]string, replace bool) error
UpdateSecurityGroups(secgroupIds []string) error
}
type ICloudElasticcacheAccount interface {
+30 -1
View File
@@ -18,6 +18,8 @@ import (
"context"
"fmt"
"github.com/pkg/errors"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -53,6 +55,7 @@ func syncElasticcaches(ctx context.Context, userCred mcclient.TokenCredential, s
syncElasticcacheAccounts(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
syncElasticcacheAcls(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
syncElasticcacheBackups(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
syncElasticcacheSecgroups(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
}()
}
}
@@ -97,7 +100,11 @@ func syncElasticcacheAcls(ctx context.Context, userCred mcclient.TokenCredential
acls, err := remoteInstance.GetICloudElasticcacheAcls()
if err != nil {
msg := fmt.Sprintf("GetIElasticcacheAcls for dbinstance %s failed %s", remoteInstance.GetName(), err)
log.Errorf(msg)
if errors.Cause(err) == cloudprovider.ErrNotSupported {
log.Warningf(msg)
} else {
log.Errorf(msg)
}
return
}
@@ -128,3 +135,25 @@ func syncElasticcacheBackups(ctx context.Context, userCred mcclient.TokenCredent
return
}
}
func syncElasticcacheSecgroups(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SElasticcache, remoteInstance cloudprovider.ICloudElasticcache) {
secgroupIds, err := remoteInstance.GetSecurityGroupIds()
if err != nil {
msg := fmt.Sprintf("Elasticcache.GetSecurityGroupIds for dbinstance %s failed %s", remoteInstance.GetName(), err)
if errors.Cause(err) == cloudprovider.ErrNotSupported {
log.Warningf(msg)
} else {
log.Errorf(msg)
}
return
}
result := localInstance.SyncElasticcacheSecgroups(ctx, userCred, secgroupIds)
syncResults.Add(ElasticcacheAclManager, result)
msg := result.Result()
log.Infof("SyncElasticcacheSecgroups for dbinstance %s result: %s", localInstance.Name, msg)
if result.IsError() {
return
}
}
@@ -297,6 +297,29 @@ func (self *SElasticcacheAccount) GetCreateAliyunElasticcacheAccountParams() (cl
return ret, nil
}
func (self *SElasticcacheAccount) GetCreateQcloudElasticcacheAccountParams() (cloudprovider.SCloudElasticCacheAccountInput, error) {
ret := cloudprovider.SCloudElasticCacheAccountInput{}
ret.AccountName = self.Name
ret.Description = self.Description
passwd, err := self.GetDecodedPassword()
if err != nil {
return ret, err
}
ret.AccountPassword = passwd
switch self.AccountPrivilege {
case "read":
ret.AccountPrivilege = "r"
case "write":
ret.AccountPrivilege = "rw"
default:
return ret, fmt.Errorf("ElasticcacheAccount.GetUpdateQcloudElasticcacheAccountParams invalid account_privilege %s", self.AccountPrivilege)
}
return ret, nil
}
func (self *SElasticcacheAccount) GetUpdateAliyunElasticcacheAccountParams(data jsonutils.JSONDict) (cloudprovider.SCloudElasticCacheAccountUpdateInput, error) {
ret := cloudprovider.SCloudElasticCacheAccountUpdateInput{}
@@ -363,6 +386,45 @@ func (self *SElasticcacheAccount) GetUpdateHuaweiElasticcacheAccountParams(data
return ret, nil
}
func (self *SElasticcacheAccount) GetUpdateQcloudElasticcacheAccountParams(data jsonutils.JSONDict) (cloudprovider.SCloudElasticCacheAccountUpdateInput, error) {
ret := cloudprovider.SCloudElasticCacheAccountUpdateInput{}
if desc, _ := data.GetString("description"); len(desc) > 0 {
ret.Description = &desc
}
if password, _ := data.GetString("password"); len(password) > 0 {
ret.Password = &password
}
if ok := data.Contains("no_password_access"); ok {
passwordAccess, _ := data.Bool("no_password_access")
if self.AccountType == api.ELASTIC_CACHE_ACCOUNT_TYPE_ADMIN {
ret.NoPasswordAccess = &passwordAccess
} else {
if passwordAccess == false {
return ret, fmt.Errorf("ElasticcacheAccount.GetUpdateQcloudElasticcacheAccountParams normal account not support no auth access")
}
}
}
if privilege, _ := data.GetString("account_privilege"); len(privilege) > 0 {
var p string
switch privilege {
case "read":
p = "r"
case "write":
p = "rw"
default:
return ret, fmt.Errorf("ElasticcacheAccount.GetUpdateQcloudElasticcacheAccountParams invalid account_privilege %s", privilege)
}
ret.AccountPrivilege = &p
}
return ret, nil
}
func (self *SElasticcacheAccount) SavePassword(passwd string) error {
passwd, err := utils.EncryptAESBase64(self.Id, passwd)
if err != nil {
+395 -5
View File
@@ -16,6 +16,7 @@ package models
import (
"context"
"database/sql"
"fmt"
"regexp"
"strings"
@@ -217,6 +218,7 @@ func (manager *SElasticcacheManager) FetchCustomizeColumns(
zoneRows := manager.SZoneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
netIds := make([]string, len(objs))
cacheIds := make([]string, len(objs))
for i := range rows {
rows[i] = api.ElasticcacheDetails{
VirtualResourceDetails: virtRows[i],
@@ -224,6 +226,7 @@ func (manager *SElasticcacheManager) FetchCustomizeColumns(
ZoneResourceInfoBase: zoneRows[i].ZoneResourceInfoBase,
}
netIds[i] = objs[i].(*SElasticcache).NetworkId
cacheIds[i] = objs[i].(*SElasticcache).Id
}
networks := make(map[string]SNetwork)
@@ -239,6 +242,19 @@ func (manager *SElasticcacheManager) FetchCustomizeColumns(
}
}
if len(fields) == 0 || fields.Contains("secgroups") || fields.Contains("secgroup") {
gsgs := fetchElasticcacheSecgroups(cacheIds)
if gsgs != nil {
for i := range rows {
if gsg, ok := gsgs[cacheIds[i]]; ok {
if len(fields) == 0 || fields.Contains("secgroups") {
rows[i].Secgroups = gsg
}
}
}
}
}
return rows
}
@@ -680,7 +696,7 @@ func (manager *SElasticcacheManager) AllowCreateItem(ctx context.Context, userCr
}
func (manager *SElasticcacheManager) BatchCreateValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
input, err := manager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input, err := manager.validateCreateData(ctx, userCred, ownerId, query, data)
if err != nil {
return nil, err
}
@@ -688,7 +704,12 @@ func (manager *SElasticcacheManager) BatchCreateValidateCreateData(ctx context.C
return input, nil
}
func (manager *SElasticcacheManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
func (manager *SElasticcacheManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.ElasticcacheCreateInput) (*jsonutils.JSONDict, error) {
data := input.JSON(&input)
return manager.validateCreateData(ctx, userCred, ownerId, query, data)
}
func (manager *SElasticcacheManager) validateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
var region *SCloudregion
if id, _ := data.GetString("network"); len(id) > 0 {
network, err := db.FetchByIdOrName(NetworkManager, userCred, strings.Split(id, ",")[0])
@@ -743,6 +764,10 @@ func (self *SElasticcache) PostCreate(ctx context.Context, userCred mcclient.Tok
params := jsonutils.NewDict()
params.Set("password", jsonutils.NewString(password))
secgroupIds, err := data.Get("secgroup_ids")
if err == nil {
params.Set("secgroup_ids", secgroupIds)
}
self.SetStatus(userCred, api.ELASTIC_CACHE_STATUS_DEPLOYING, "")
if err := self.StartElasticcacheCreateTask(ctx, userCred, params, ""); err != nil {
log.Errorf("Failed to create elastic cache error: %v", err)
@@ -942,7 +967,7 @@ func (self *SElasticcache) GetCreateHuaweiElasticcacheParams(data *jsonutils.JSO
return nil, errors.Wrap(fmt.Errorf("cached security group not found"), "elasticcache.GetCreateHuaweiElasticcacheParams.SecurityGroup")
}
input.SecurityGroupId = sgCache.GetExternalId()
input.SecurityGroupIds = []string{sgCache.GetExternalId()}
}
if len(self.MaintainEndTime) > 0 {
@@ -952,6 +977,71 @@ func (self *SElasticcache) GetCreateHuaweiElasticcacheParams(data *jsonutils.JSO
return input, nil
}
func (self *SElasticcache) GetCreateQCloudElasticcacheParams(data *jsonutils.JSONDict) (*cloudprovider.SCloudElasticCacheInput, error) {
input := &cloudprovider.SCloudElasticCacheInput{}
iregion, err := self.GetIRegion()
if err != nil {
return nil, fmt.Errorf("elastic cache %s(%s) region not found", self.Name, self.Id)
} else {
input.RegionId = iregion.GetId()
}
input.InstanceType = self.InstanceType
input.InstanceName = self.GetName()
if password, _ := data.GetString("password"); len(password) > 0 {
input.Password = password
}
zone := self.GetZone()
if zone != nil {
izone, err := iregion.GetIZoneById(zone.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "elasticcache.GetCreateHuaweiElasticcacheParams.Zone")
}
input.ZoneIds = []string{izone.GetId()}
}
switch self.BillingType {
case billing.BILLING_TYPE_PREPAID:
input.ChargeType = "PrePaid"
billingCycle, err := bc.ParseBillingCycle(self.BillingCycle)
if err != nil {
return nil, errors.Wrap(err, "elasticcache.GetCreateHuaweiElasticcacheParams.BillingCycle")
}
input.BC = &billingCycle
default:
input.ChargeType = "PostPaid"
}
switch self.NetworkType {
case api.LB_NETWORK_TYPE_CLASSIC:
input.NetworkType = "CLASSIC"
default:
input.NetworkType = "VPC"
}
if ivpc, err := db.FetchById(VpcManager, self.VpcId); err != nil {
return nil, errors.Wrap(err, "elasticcache.GetCreateHuaweiElasticcacheParams.Vpc")
} else {
if ivpc != nil {
vpc := ivpc.(*SVpc)
input.VpcId = vpc.ExternalId
}
}
if inetwork, err := db.FetchById(NetworkManager, self.NetworkId); err != nil {
return nil, errors.Wrap(err, "elasticcache.GetCreateHuaweiElasticcacheParams.Network")
} else {
if inetwork != nil {
network := inetwork.(*SNetwork)
input.NetworkId = network.ExternalId
}
}
return input, nil
}
func (self *SElasticcache) AllowPerformRestart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "restart")
}
@@ -1313,7 +1403,7 @@ func (self *SElasticcache) AllowPerformFlushInstance(ctx context.Context, userCr
func (self *SElasticcache) PerformFlushInstance(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
self.SetStatus(userCred, api.ELASTIC_CACHE_STATUS_FLUSHING, "")
return nil, self.StartFlushInstanceTask(ctx, userCred, jsonutils.NewDict(), "")
return nil, self.StartFlushInstanceTask(ctx, userCred, data.(*jsonutils.JSONDict), "")
}
func (self *SElasticcache) StartFlushInstanceTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
@@ -1437,11 +1527,11 @@ func (self *SElasticcache) AllowPerformSync(ctx context.Context, userCred mcclie
}
func (self *SElasticcache) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
self.SetStatus(userCred, api.ELASTIC_CACHE_STATUS_SYNCING, "")
return nil, self.StartSyncTask(ctx, userCred, data.(*jsonutils.JSONDict), "")
}
func (self *SElasticcache) StartSyncTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
self.SetStatus(userCred, api.ELASTIC_CACHE_STATUS_SYNCING, "")
task, err := taskman.TaskManager.NewTask(ctx, "ElasticcacheSyncTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
return err
@@ -1750,3 +1840,303 @@ func (self *SElasticcache) OnMetadataUpdated(ctx context.Context, userCred mccli
log.Errorf("StartRemoteUpdateTask fail: %s", err)
}
}
func (self *SElasticcache) getSecgroupsBySecgroupExternalIds(externalIds []string) ([]SSecurityGroup, error) {
vpc := self.GetVpc()
if vpc == nil {
return nil, errors.Wrap(errors.ErrNotFound, "GetVpc")
}
return getSecgroupsBySecgroupExternalIds(vpc.ManagerId, externalIds)
}
func (self *SElasticcache) GetElasticcacheSecgroups() ([]SElasticcachesecgroup, error) {
ess := []SElasticcachesecgroup{}
q := ElasticcachesecgroupManager.Query().Equals("elasticcache_id", self.Id)
err := db.FetchModelObjects(ElasticcachesecgroupManager, q, &ess)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
return ess, nil
}
func (self *SElasticcache) validateSecgroupInput(secgroups []string) error {
if !utils.IsInStringArray(self.Status, []string{api.ELASTIC_CACHE_STATUS_RUNNING, api.ELASTIC_CACHE_STATUS_DEPLOYING}) {
return httperrors.NewInputParameterError("Cannot add security groups in status %s", self.Status)
}
region := self.GetRegion()
if region == nil {
return httperrors.NewNotFoundError("region")
}
driver := region.GetDriver()
if driver == nil {
return httperrors.NewNotFoundError("regiondriver")
}
maxCount := driver.GetMaxElasticcacheSecurityGroupCount()
if !driver.IsSupportedElasticcacheSecgroup() || maxCount == 0 {
return httperrors.NewNotSupportedError("not supported bind security group")
}
if len(secgroups) > maxCount {
return httperrors.NewOutOfLimitError("beyond security group quantity limit, max items %d.", maxCount)
}
return nil
}
func CheckingSecgroupIds(ctx context.Context, userCred mcclient.TokenCredential, secgroupIds []string) ([]string, error) {
secgroupNames := []string{}
for _, secgroupId := range secgroupIds {
secgrp, err := SecurityGroupManager.FetchByIdOrName(userCred, secgroupId)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2("secgroup", secgroupId)
}
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "FetchByIdOrName(%s)", secgroupId))
}
err = SecurityGroupManager.ValidateName(secgrp.GetName())
if err != nil {
return nil, httperrors.NewInputParameterError("The secgroup name %s does not meet the requirements, please change the name", secgrp.GetName())
}
secgroupNames = append(secgroupNames, secgrp.GetName())
}
return secgroupNames, nil
}
func (self *SElasticcache) checkingSecgroupIds(ctx context.Context, userCred mcclient.TokenCredential, secgroupIds []string) ([]string, error) {
return CheckingSecgroupIds(ctx, userCred, secgroupIds)
}
// 返回 本次更新后secgroup id的全集、本次更增的secgroup id, 本次删除的secgroup id, error
func (self *SElasticcache) cleanSecgroupIds(action string, secgroupIds []string) ([]string, []string, []string, error) {
ess, err := self.GetElasticcacheSecgroups()
if err != nil {
return nil, nil, nil, errors.Wrap(err, "GetElasticcacheSecgroups")
}
currentIds := make([]string, len(ess))
for i := range ess {
currentIds[i] = ess[i].SecgroupId
}
all := []string{}
adds := []string{}
removes := []string{}
switch action {
case "add":
all = currentIds
for i := range secgroupIds {
if !utils.IsInStringArray(secgroupIds[i], currentIds) && !utils.IsInStringArray(secgroupIds[i], adds) {
adds = append(adds, secgroupIds[i])
all = append(all, secgroupIds[i])
}
}
case "revoke":
for i := range secgroupIds {
if utils.IsInStringArray(secgroupIds[i], currentIds) && !utils.IsInStringArray(secgroupIds[i], adds) {
removes = append(removes, secgroupIds[i])
}
}
for i := range currentIds {
if !utils.IsInStringArray(currentIds[i], removes) {
all = append(all, currentIds[i])
}
}
case "set":
for i := range secgroupIds {
if !utils.IsInStringArray(secgroupIds[i], all) {
all = append(all, secgroupIds[i])
}
}
for i := range currentIds {
if !utils.IsInStringArray(currentIds[i], all) {
removes = append(removes, currentIds[i])
}
}
for i := range all {
if !utils.IsInStringArray(all[i], currentIds) {
adds = append(adds, all[i])
}
}
default:
return nil, nil, nil, fmt.Errorf("not supported cleanSecgroupIds action %s", action)
}
return all, adds, removes, nil
}
func (self *SElasticcache) addSecgroup(ctx context.Context, userCred mcclient.TokenCredential, secgroupId string) error {
es := &SElasticcachesecgroup{}
es.SetModelManager(GuestsecgroupManager, es)
es.ElasticcacheId = self.Id
es.SecgroupId = secgroupId
err := ElasticcachesecgroupManager.TableSpec().Insert(ctx, es)
if err != nil {
return errors.Wrap(err, "ElasticcachesecgroupManager.Insert")
}
return nil
}
func (self *SElasticcache) removeSecgroup(ctx context.Context, userCred mcclient.TokenCredential, secgroupId string) error {
q := ElasticcachesecgroupManager.Query().Equals("secgroup_id", secgroupId).Equals("elasticcache_id", self.GetId())
ret := []SElasticcachesecgroup{}
err := db.FetchModelObjects(ElasticcachesecgroupManager, q, &ret)
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
return errors.Wrap(err, "FetchModelObjects")
} else {
return nil
}
}
for i := range ret {
err = ret[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrapf(err, "Delete elasticcache %s secgroup %s", self.Name, secgroupId)
}
}
return nil
}
func (self *SElasticcache) saveSecgroups(ctx context.Context, userCred mcclient.TokenCredential, adds []string, removes []string) compare.SyncResult {
saveResult := compare.SyncResult{}
for i := range adds {
err := self.addSecgroup(ctx, userCred, adds[i])
if err != nil {
saveResult.Error(errors.Wrap(err, "addSecgroup"))
return saveResult
} else {
saveResult.Add()
}
}
for i := range removes {
err := self.removeSecgroup(ctx, userCred, removes[i])
if err != nil {
saveResult.Error(errors.Wrap(err, "removeSecgroup"))
return saveResult
} else {
saveResult.Delete()
}
}
return saveResult
}
func (self *SElasticcache) ProcessElasticcacheSecgroupsInput(ctx context.Context, userCred mcclient.TokenCredential, action string, input *api.ElasticcacheSecgroupsInput) ([]string, error) {
all, adds, removes, err := self.cleanSecgroupIds(action, input.SecgroupIds)
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
if len(all) == 0 {
return nil, httperrors.NewInputParameterError("secgroups will be empty after update.")
}
switch action {
case "add":
input.SecgroupIds = adds
case "revoke":
input.SecgroupIds = removes
case "set":
input.SecgroupIds = all
}
err = self.validateSecgroupInput(all)
if err != nil {
return nil, err
}
names, err := self.checkingSecgroupIds(ctx, userCred, input.SecgroupIds)
if err != nil {
return nil, err
}
result := self.saveSecgroups(ctx, userCred, adds, removes)
if result.IsError() {
return nil, result.AllError()
}
return names, nil
}
func (self *SElasticcache) SyncSecgroup(ctx context.Context, userCred mcclient.TokenCredential, action string, input api.ElasticcacheSecgroupsInput) (jsonutils.JSONObject, error) {
names, err := self.ProcessElasticcacheSecgroupsInput(ctx, userCred, action, &input)
if err != nil {
return nil, err
}
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_SYNC_CONF, names, userCred, true)
return nil, self.StartSyncSecgroupsTask(ctx, userCred, nil, "")
}
func (self *SElasticcache) AllowPerformAddSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "add-secgroup")
}
func (self *SElasticcache) PerformAddSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticcacheSecgroupsInput) (jsonutils.JSONObject, error) {
return self.SyncSecgroup(ctx, userCred, "add", input)
}
func (self *SElasticcache) AllowPerformRevokeSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "revoke-secgroup")
}
func (self *SElasticcache) PerformRevokeSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticcacheSecgroupsInput) (jsonutils.JSONObject, error) {
return self.SyncSecgroup(ctx, userCred, "revoke", input)
}
func (self *SElasticcache) AllowPerformSetSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "set-secgroup")
}
func (self *SElasticcache) PerformSetSecgroup(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticcacheSecgroupsInput) (jsonutils.JSONObject, error) {
return self.SyncSecgroup(ctx, userCred, "set", input)
}
func (self *SElasticcache) SyncElasticcacheSecgroups(ctx context.Context, userCred mcclient.TokenCredential, externalIds []string) compare.SyncResult {
syncResult := compare.SyncResult{}
secgroups, err := self.getSecgroupsBySecgroupExternalIds(externalIds)
if err != nil {
syncResult.Error(err)
return syncResult
}
secgroupIds := []string{}
for _, secgroup := range secgroups {
secgroupIds = append(secgroupIds, secgroup.Id)
}
_, adds, removes, err := self.cleanSecgroupIds("set", secgroupIds)
if err != nil {
syncResult.Error(err)
return syncResult
}
return self.saveSecgroups(ctx, userCred, adds, removes)
}
func (self *SElasticcache) StartSyncSecgroupsTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
self.SetStatus(userCred, api.ELASTIC_CACHE_STATUS_SYNCING, "")
task, err := taskman.TaskManager.NewTask(ctx, "ElasticcacheSyncsecgroupsTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
+186
View File
@@ -0,0 +1,186 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type SElasticcacheJointsManager struct {
db.SVirtualJointResourceBaseManager
SElasticcacheResourceBaseManager
}
func NewElasticcacheJointsManager(dt interface{}, tableName string, keyword string, keywordPlural string, slave db.IVirtualModelManager) SElasticcacheJointsManager {
return SElasticcacheJointsManager{
SVirtualJointResourceBaseManager: db.NewVirtualJointResourceBaseManager(
dt,
tableName,
keyword,
keywordPlural,
ElasticcacheManager,
slave,
),
}
}
type SElasticcacheJointsBase struct {
db.SVirtualJointResourceBase
SElasticcacheResourceBase
}
func (self *SElasticcacheJointsBase) getElasticcache() *SElasticcache {
ec, _ := ElasticcacheManager.FetchById(self.ElasticcacheId)
return ec.(*SElasticcache)
}
func (manager *SElasticcacheJointsManager) GetMasterFieldName() string {
return "elasticcache_id"
}
func (self *SElasticcacheJointsBase) GetExtraDetails(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
isList bool,
) (api.ElasticcacheJointResourceDetails, error) {
return api.ElasticcacheJointResourceDetails{}, nil
}
func (manager *SElasticcacheJointsManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.ElasticcacheJointResourceDetails {
rows := make([]api.ElasticcacheJointResourceDetails, len(objs))
jointRows := manager.SVirtualJointResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
ecIds := make([]string, len(rows))
for i := range rows {
rows[i] = api.ElasticcacheJointResourceDetails{
VirtualJointResourceBaseDetails: jointRows[i],
}
var base *SElasticcacheJointsBase
reflectutils.FindAnonymouStructPointer(objs[i], &base)
if base != nil && len(base.ElasticcacheId) > 0 {
ecIds[i] = base.ElasticcacheId
}
}
ecIdMaps, err := db.FetchIdNameMap2(ElasticcacheManager, ecIds)
if err != nil {
log.Errorf("db.FetchIdNameMap2 fail %s", err)
return rows
}
for i := range rows {
if name, ok := ecIdMaps[ecIds[i]]; ok {
rows[i].Elasticcache = name
rows[i].ElasticcacheId = ecIds[i]
}
}
return rows
}
func (manager *SElasticcacheJointsManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.ElasticcacheJointsListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SVirtualJointResourceBaseManager.ListItemFilter(ctx, q, userCred, query.VirtualJointResourceBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SVirtualJointResourceBaseManager.ListItemFilter")
}
q, err = manager.SElasticcacheResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ElasticcacheFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SElasticcacheResourceBaseManager.ListItemFilter")
}
return q, nil
}
func (manager *SElasticcacheJointsManager) OrderByExtraFields(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.ElasticcacheJointsListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SVirtualJointResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.VirtualJointResourceBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SVirtualJointResourceBaseManager.OrderByExtraFields")
}
q, err = manager.SElasticcacheResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ElasticcacheFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SElasticcacheResourceBaseManager.OrderByExtraFields")
}
return q, nil
}
func (self *SElasticcacheJointsBase) ValidateUpdateData(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
input api.ElasticcacheJointBaseUpdateInput,
) (api.ElasticcacheJointBaseUpdateInput, error) {
var err error
input.VirtualJointResourceBaseUpdateInput, err = self.SVirtualJointResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualJointResourceBaseUpdateInput)
if err != nil {
return input, errors.Wrap(err, "SVirtualJointResourceBase.ValidateUpdateData")
}
return input, nil
}
func (manager *SElasticcacheJointsManager) ListItemExportKeys(ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
keys stringutils2.SSortedStrings,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SVirtualJointResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SVirtualJointResourceBaseManager.ListItemExportKeys")
}
if keys.ContainsAny(manager.SElasticcacheResourceBaseManager.GetExportKeys()...) {
q, err = manager.SElasticcacheResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SElasticcacheResourceBaseManager.ListItemExportKeys")
}
}
return q, nil
}
@@ -0,0 +1,218 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type SElasticcachesecgroupManager struct {
SElasticcacheJointsManager
SSecurityGroupResourceBaseManager
}
var ElasticcachesecgroupManager *SElasticcachesecgroupManager
func init() {
db.InitManager(func() {
ElasticcachesecgroupManager = &SElasticcachesecgroupManager{
SElasticcacheJointsManager: NewElasticcacheJointsManager(
SElasticcachesecgroup{},
"elasticcachesecgroups_tbl",
"elasticcachesecgroup",
"elasticcachesecgroups",
SecurityGroupManager,
),
}
ElasticcachesecgroupManager.SetVirtualObject(ElasticcachesecgroupManager)
})
}
type SElasticcachesecgroup struct {
SElasticcacheJointsBase
SSecurityGroupResourceBase `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
}
func (manager *SElasticcachesecgroupManager) GetSlaveFieldName() string {
return "secgroup_id"
}
func (self *SElasticcachesecgroup) getSecgroup() *SSecurityGroup {
secgrp, err := SecurityGroupManager.FetchById(self.SecgroupId)
if err != nil {
log.Errorf("failed to find secgroup %s", self.SecgroupId)
return nil
}
secgroup := secgrp.(*SSecurityGroup)
secgroup.SetModelManager(SecurityGroupManager, secgroup)
return secgroup
}
func (self *SElasticcachesecgroup) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return db.DeleteModel(ctx, userCred, self)
}
func (manager *SElasticcachesecgroupManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.ElasticcachesecgroupListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SElasticcacheJointsManager.ListItemFilter(ctx, q, userCred, query.ElasticcacheJointsListInput)
if err != nil {
return nil, errors.Wrap(err, "SElasticcacheJointsManager.ListItemFilter")
}
q, err = manager.SSecurityGroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.SecgroupFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SSecurityGroupResourceBaseManager.ListItemFilter")
}
return q, nil
}
func (manager *SElasticcachesecgroupManager) OrderByExtraFields(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.ElasticcachesecgroupListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SElasticcacheJointsManager.OrderByExtraFields(ctx, q, userCred, query.ElasticcacheJointsListInput)
if err != nil {
return nil, errors.Wrap(err, "SElasticcacheJointsManager.OrderByExtraFields")
}
q, err = manager.SSecurityGroupResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.SecgroupFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SSecurityGroupResourceBaseManager.OrderByExtraFields")
}
return q, nil
}
func (manager *SElasticcachesecgroupManager) ListItemExportKeys(ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
keys stringutils2.SSortedStrings,
) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SElasticcacheJointsManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SElasticcacheJointsManager.ListItemExportKeys")
}
if keys.ContainsAny(manager.SSecurityGroupResourceBaseManager.GetExportKeys()...) {
q, err = manager.SSecurityGroupResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SSecurityGroupResourceBaseManager.ListItemExportKeys")
}
}
return q, nil
}
func (self *SElasticcachesecgroup) GetExtraDetails(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
isList bool,
) (api.ElasticcachesecgroupDetails, error) {
return api.ElasticcachesecgroupDetails{}, nil
}
func (manager *SElasticcachesecgroupManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.ElasticcachesecgroupDetails {
rows := make([]api.ElasticcachesecgroupDetails, len(objs))
ecRows := manager.SElasticcacheJointsManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
secgroupIds := make([]string, len(rows))
for i := range rows {
rows[i].ElasticcacheJointResourceDetails = ecRows[i]
secgroupIds[i] = objs[i].(*SElasticcachesecgroup).SecgroupId
}
secgroupIdMaps, err := db.FetchIdNameMap2(SecurityGroupManager, secgroupIds)
if err != nil {
log.Errorf("FetchIdNameMap2 fail %s", err)
return rows
}
for i := range rows {
if name, ok := secgroupIdMaps[secgroupIds[i]]; ok {
rows[i].Secgroup = name
}
}
return rows
}
func fetchElasticcacheSecgroups(cacheIds []string) map[string][]apis.StandaloneShortDesc {
secgroups := SecurityGroupManager.Query().SubQuery()
cachesecgroups := ElasticcachesecgroupManager.Query().SubQuery()
q := cachesecgroups.Query(
cachesecgroups.Field("elasticcache_id", "elasticcache_id"),
cachesecgroups.Field("secgroup_id", "secgroup_id"),
secgroups.Field("name", "secgroup_name"))
q = q.Filter(sqlchemy.In(cachesecgroups.Field("elasticcache_id"), cacheIds))
q = q.Join(secgroups, sqlchemy.Equals(q.Field("secgroup_id"), secgroups.Field("id")))
type secgroupInfo struct {
SecgroupId string
SecgroupName string
ElasticcacheId string
}
gsgs := make([]secgroupInfo, 0)
err := q.All(&gsgs)
if err != nil {
log.Debugf("fetchElasticcacheSecgroups %s", err)
return nil
}
ret := make(map[string][]apis.StandaloneShortDesc)
for i := range gsgs {
gsg, ok := ret[gsgs[i].ElasticcacheId]
if !ok {
gsg = make([]apis.StandaloneShortDesc, 0)
}
gsg = append(gsg, apis.StandaloneShortDesc{
Id: gsgs[i].SecgroupId,
Name: gsgs[i].SecgroupName,
})
ret[gsgs[i].ElasticcacheId] = gsg
}
return ret
}
+6 -1
View File
@@ -4801,7 +4801,12 @@ func (self *SGuest) getSecgroupsBySecgroupExternalIds(externalIds []string) ([]S
if host == nil {
return nil, errors.Error("not found host for guest")
}
sq := SecurityGroupCacheManager.Query("secgroup_id").In("external_id", externalIds).Equals("manager_id", host.ManagerId)
return getSecgroupsBySecgroupExternalIds(host.ManagerId, externalIds)
}
func getSecgroupsBySecgroupExternalIds(managerId string, externalIds []string) ([]SSecurityGroup, error) {
sq := SecurityGroupCacheManager.Query("secgroup_id").In("external_id", externalIds).Equals("manager_id", managerId)
q := SecurityGroupManager.Query().In("id", sq.SubQuery())
secgroups := []SSecurityGroup{}
err := db.FetchModelObjects(SecurityGroupManager, q, &secgroups)
+7 -1
View File
@@ -174,18 +174,23 @@ type IDBInstanceDriver interface {
type IElasticcacheDriver interface {
IsSupportedElasticcache() bool
// capability
IsSupportedElasticcacheSecgroup() bool
GetMaxElasticcacheSecurityGroupCount() int
AllowCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *SElasticcache) error
AllowUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *SElasticcache) error
ValidateCreateElasticcacheData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
ValidateCreateElasticcacheAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
ValidateCreateElasticcacheAclData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
ValidateCreateElasticcacheBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error
RequestCreateElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheAccount *SElasticcacheAccount, task taskman.ITask) error
RequestCreateElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheAcl *SElasticcacheAcl, task taskman.ITask) error
RequestCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheBackup *SElasticcacheBackup, task taskman.ITask) error
RequestRestartElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestSyncElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestSyncSecgroupsForElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *SElasticcache, task taskman.ITask) error
RequestDeleteElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestDeleteElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, ea *SElasticcacheAccount, task taskman.ITask) error
RequestDeleteElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, ea *SElasticcacheAcl, task taskman.ITask) error
@@ -193,6 +198,7 @@ type IElasticcacheDriver interface {
RequestSetElasticcacheMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestElasticcacheChangeSpec(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestUpdateElasticcacheSecgroups(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestElasticcacheSetMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestElasticcacheAllocatePublicConnection(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
RequestElasticcacheReleasePublicConnection(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
+27
View File
@@ -154,6 +154,12 @@ func (manager *SSecurityGroupManager) ListItemFilter(
q = q.In("id", sq.SubQuery())
}
// elastic cache
q, err = manager.ListItemElasticcacheFilter(ctx, q, userCred, input)
if err != nil {
return nil, errors.Wrap(err, "ListItemElasticcacheFilter")
}
if len(input.Ip) > 0 || len(input.Ports) > 0 {
sq := SecurityGroupRuleManager.Query("secgroup_id")
if len(input.Ip) > 0 {
@@ -171,6 +177,27 @@ func (manager *SSecurityGroupManager) ListItemFilter(
return q, nil
}
func (manager *SSecurityGroupManager) ListItemElasticcacheFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
input api.SecgroupListInput,
) (*sqlchemy.SQuery, error) {
cacheId := input.ElasticcacheId
if len(cacheId) > 0 {
cache, _, err := ValidateElasticcacheResourceInput(userCred, input.ELasticcacheResourceInput)
if err != nil {
return nil, errors.Wrap(err, "ValidateElasticcacheResourceInput")
}
cacheId := cache.GetId()
filters := []sqlchemy.ICondition{}
filters = append(filters, sqlchemy.In(q.Field("id"), ElasticcachesecgroupManager.Query("secgroup_id").Equals("elasticcache_id", cacheId).SubQuery()))
q = q.Filter(sqlchemy.OR(filters...))
}
return q, nil
}
func (manager *SSecurityGroupManager) OrderByExtraFields(
ctx context.Context,
q *sqlchemy.SQuery,
+10 -2
View File
@@ -1279,7 +1279,7 @@ func (self *SAliyunRegionDriver) ValidateCreateElasticcacheData(ctx context.Cont
return data, nil
}
func (self *SAliyunRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
func (self *SAliyunRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iRegion, err := ec.GetIRegion()
if err != nil {
@@ -1479,7 +1479,7 @@ func (self *SAliyunRegionDriver) RequestCreateElasticcacheBackup(ctx context.Con
backupIds = append(backupIds, oBackups[i].GetGlobalId())
}
_, err = iec.CreateBackup()
_, err = iec.CreateBackup("")
if err != nil {
return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.CreateBackup")
}
@@ -1576,3 +1576,11 @@ func (self *SAliyunRegionDriver) IsSupportedDBInstance() bool {
func (self *SAliyunRegionDriver) IsSupportedElasticcache() bool {
return true
}
func (self *SAliyunRegionDriver) IsSupportedElasticcacheSecgroup() bool {
return false
}
func (self *SAliyunRegionDriver) GetMaxElasticcacheSecurityGroupCount() int {
return 0
}
+4
View File
@@ -393,6 +393,10 @@ func (self *SBaseRegionDriver) RequestRemoteUpdateElasticcache(ctx context.Conte
return nil
}
func (self *SBaseRegionDriver) RequestSyncSecgroupsForElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
return fmt.Errorf("Not Implement RequestSyncSecgroupsForElasticcache")
}
func (self *SBaseRegionDriver) IsDBInstanceNeedSecgroup() bool {
return false
}
+9 -1
View File
@@ -2472,7 +2472,7 @@ func (self *SHuaWeiRegionDriver) ValidateCreateElasticcacheData(ctx context.Cont
return data, nil
}
func (self *SHuaWeiRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
func (self *SHuaWeiRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iRegion, err := ec.GetIRegion()
if err != nil {
@@ -2637,6 +2637,14 @@ func (self *SHuaWeiRegionDriver) IsSupportedElasticcache() bool {
return true
}
func (self *SHuaWeiRegionDriver) IsSupportedElasticcacheSecgroup() bool {
return false
}
func (self *SHuaWeiRegionDriver) GetMaxElasticcacheSecurityGroupCount() int {
return 0
}
func (self *SHuaWeiRegionDriver) GetBackendStatusForAdd() []string {
return []string{api.VM_RUNNING, api.VM_READY}
}
+13 -1
View File
@@ -1146,7 +1146,7 @@ func (self *SKVMRegionDriver) ValidateCacheSecgroup(ctx context.Context, userCre
return fmt.Errorf("No need to cache secgroup for onecloud region")
}
func (self *SKVMRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
func (self *SKVMRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error {
return nil
}
@@ -1182,6 +1182,10 @@ func (self *SKVMRegionDriver) RequestUpdateElasticcacheAuthMode(ctx context.Cont
return nil
}
func (self *SKVMRegionDriver) RequestUpdateElasticcacheSecgroups(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
return nil
}
func (self *SKVMRegionDriver) RequestElasticcacheSetMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
return nil
}
@@ -1273,3 +1277,11 @@ func (self *SKVMRegionDriver) RequestSyncBucketStatus(ctx context.Context, userC
})
return nil
}
func (self *SKVMRegionDriver) IsSupportedElasticcacheSecgroup() bool {
return false
}
func (self *SKVMRegionDriver) GetMaxElasticcacheSecurityGroupCount() int {
return 0
}
+32 -4
View File
@@ -47,6 +47,14 @@ type SManagedVirtualizationRegionDriver struct {
SVirtualizationRegionDriver
}
func (self *SManagedVirtualizationRegionDriver) IsSupportedElasticcacheSecgroup() bool {
return false
}
func (self *SManagedVirtualizationRegionDriver) GetMaxElasticcacheSecurityGroupCount() int {
return 0
}
func (self *SManagedVirtualizationRegionDriver) ValidateCreateLoadbalancerData(ctx context.Context, userCred mcclient.TokenCredential, owerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
return self.ValidateManagerId(ctx, userCred, data)
}
@@ -1770,7 +1778,7 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstance(ctx cont
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error {
task.ScheduleRun(nil)
return nil
}
@@ -1993,7 +2001,12 @@ func (self *SManagedVirtualizationRegionDriver) RequestUpdateElasticcacheAuthMod
return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestUpdateElasticcacheAuthMode.UpdatedbAuthMode")
}
return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second)
return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 600*time.Second)
}
func (self *SManagedVirtualizationRegionDriver) RequestUpdateElasticcacheSecgroups(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
// todo: finish me
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheSetMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
@@ -2096,7 +2109,18 @@ func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheFlushInstance
return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheFlushInstance.GetIElasticcacheById")
}
err = iec.FlushInstance()
password, _ := task.GetParams().GetString("password")
input := cloudprovider.SCloudElasticCacheFlushInstanceInput{}
if len(password) > 0 {
input.Password = password
} else {
if info, err := ec.GetDetailsLoginInfo(ctx, userCred, jsonutils.NewDict()); err == nil && info != nil {
pwd, _ := info.GetString("password")
input.Password = pwd
}
}
err = iec.FlushInstance(input)
if err != nil {
return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheFlushInstance.FlushInstance")
}
@@ -2453,7 +2477,7 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcacheBackup(
return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.GetIElasticcacheById")
}
ieb, err := iec.CreateBackup()
ieb, err := iec.CreateBackup(eb.Name)
if err != nil {
return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.CreateBackup")
}
@@ -2832,3 +2856,7 @@ func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateElasticcache(
// nil ops
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestSyncSecgroupsForElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
return fmt.Errorf("Not Implement RequestSyncSecgroupsForElasticcache")
}
+333
View File
@@ -18,6 +18,7 @@ import (
"context"
"fmt"
"regexp"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -26,6 +27,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
@@ -35,7 +37,9 @@ import (
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/choices"
"yunion.io/x/onecloud/pkg/util/rand"
"yunion.io/x/onecloud/pkg/util/seclib2"
)
type SQcloudRegionDriver struct {
@@ -1437,3 +1441,332 @@ func (self *SQcloudRegionDriver) ValidateDBInstanceAccountPrivilege(ctx context.
}
return nil
}
func (self *SQcloudRegionDriver) IsSupportedElasticcacheSecgroup() bool {
return true
}
func (self *SQcloudRegionDriver) GetMaxElasticcacheSecurityGroupCount() int {
return 10
}
func (self *SQcloudRegionDriver) ValidateCreateElasticcacheData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
zoneV := validators.NewModelIdOrNameValidator("zone", "zone", ownerId)
networkV := validators.NewModelIdOrNameValidator("network", "network", ownerId)
instanceTypeV := validators.NewModelIdOrNameValidator("instance_type", "elasticcachesku", ownerId)
chargeTypeV := validators.NewStringChoicesValidator("billing_type", choices.NewChoices(billing_api.BILLING_TYPE_PREPAID, billing_api.BILLING_TYPE_POSTPAID))
networkTypeV := validators.NewStringChoicesValidator("network_type", choices.NewChoices(api.LB_NETWORK_TYPE_VPC)).Default(api.LB_NETWORK_TYPE_VPC).Optional(true)
engineVersionV := validators.NewStringChoicesValidator("engine_version", choices.NewChoices("2.8", "3.0", "3.2", "4.0", "5.0"))
keyV := map[string]validators.IValidator{
"zone": zoneV,
"billing_type": chargeTypeV,
"network_type": networkTypeV,
"network": networkV,
"instance_type": instanceTypeV,
"engine_version": engineVersionV,
}
if err := RunValidators(keyV, data, false); err != nil {
return nil, err
}
// validate password
if password, _ := data.GetString("password"); len(password) > 0 {
if !seclib2.MeetComplxity(password) {
return nil, httperrors.NewWeakPasswordError()
}
}
zoneId, _ := data.GetString("zone_id")
billingType, _ := data.GetString("billing_type")
// validate sku
sku := instanceTypeV.Model.(*models.SElasticcacheSku)
if err := ValidateElasticcacheSku(zoneId, billingType, sku); err != nil {
return nil, err
} else {
data.Set("instance_type", jsonutils.NewString(sku.InstanceSpec))
data.Set("node_type", jsonutils.NewString(sku.NodeType))
data.Set("local_category", jsonutils.NewString(sku.LocalCategory))
data.Set("capacity_mb", jsonutils.NewInt(int64(sku.MemorySizeMB)))
}
// validate secgroups
secgroups := []string{}
err := data.Unmarshal(&secgroups, "secgroup_ids")
if err != nil {
log.Debugf("Unmarshal.security_groups %s", err)
secgroups = []string{api.SECGROUP_DEFAULT_ID}
}
if len(secgroups) == 0 || len(secgroups) > 10 {
return nil, errors.Wrap(err, "secgroups id quantity should between 1 and 10.")
}
_, err = models.CheckingSecgroupIds(ctx, userCred, secgroups)
if err != nil {
return nil, errors.Wrap(err, "CheckingSecgroupIds")
}
// billing cycle
if billingType == billing_api.BILLING_TYPE_PREPAID {
billingCycle, err := data.GetString("billing_cycle")
if err != nil {
return nil, httperrors.NewMissingParameterError("billing_cycle")
}
cycle, err := billing.ParseBillingCycle(billingCycle)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid billing_cycle %s", billingCycle)
}
data.Set("billing_cycle", jsonutils.NewString(cycle.String()))
}
network := networkV.Model.(*models.SNetwork)
vpc := network.GetVpc()
if vpc == nil {
return nil, httperrors.NewNotFoundError("network %s related vpc not found", network.GetId())
}
data.Set("engine", jsonutils.NewString("redis"))
data.Set("vpc_id", jsonutils.NewString(vpc.Id))
data.Set("manager_id", jsonutils.NewString(vpc.ManagerId))
data.Set("cloudregion_id", jsonutils.NewString(vpc.CloudregionId))
return data, nil
}
func (self *SQcloudRegionDriver) IsSupportedElasticcache() bool {
return true
}
func (self *SQcloudRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iRegion, err := ec.GetIRegion()
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.GetIRegion")
}
provider := ec.GetCloudprovider()
if provider == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "qcloudRegionDriver.CreateElasticcache.GetProvider")
}
secgroups := []string{}
err = data.Unmarshal(&secgroups, "ext_secgroup_ids")
if err != nil {
return nil, errors.Wrap(err, "Unmarshal.ext_secgroup_ids")
}
params, err := ec.GetCreateQCloudElasticcacheParams(task.GetParams())
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.GetCreateHuaweiElasticcacheParams")
}
params.SecurityGroupIds = secgroups
iec, err := iRegion.CreateIElasticcaches(params)
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.CreateIElasticcaches")
}
err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 30*time.Second, 15*time.Second, 600*time.Second)
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.WaitStatusWithDelay")
}
ec.SetModelManager(models.ElasticcacheManager, ec)
if err := db.SetExternalId(ec, userCred, iec.GetGlobalId()); err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.SetExternalId")
}
if err := ec.SyncWithCloudElasticcache(ctx, userCred, provider, iec); err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.SyncWithCloudElasticcache")
}
// sync accounts
{
iaccounts, err := iec.GetICloudElasticcacheAccounts()
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.GetICloudElasticcacheAccounts")
}
result := models.ElasticcacheAccountManager.SyncElasticcacheAccounts(ctx, userCred, ec, iaccounts)
log.Debugf("qcloudRegionDriver.CreateElasticcache.SyncElasticcacheAccounts %s", result.Result())
account, err := ec.GetAdminAccount()
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.GetAdminAccount")
}
err = account.SavePassword(params.Password)
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.SavePassword")
}
}
// sync parameters
{
iparams, err := iec.GetICloudElasticcacheParameters()
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcache.GetICloudElasticcacheParameters")
}
result := models.ElasticcacheParameterManager.SyncElasticcacheParameters(ctx, userCred, ec, iparams)
log.Debugf("qcloudRegionDriver.CreateElasticcache.SyncElasticcacheParameters %s", result.Result())
}
return nil, nil
})
return nil
}
func (self *SQcloudRegionDriver) RequestSyncSecgroupsForElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
// sync secgroups to cloud
secgroupExternalIds := []string{}
{
ess, err := ec.GetElasticcacheSecgroups()
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.GetElasticcacheSecgroups")
}
vpc := ec.GetVpc()
for i := range ess {
externalId, err := self.RequestSyncSecurityGroup(ctx, task.GetUserCred(), vpc.GetId(), vpc, ess[i].GetSecGroup(), "")
if err != nil {
return nil, errors.Wrap(err, "RequestSyncSecurityGroup")
}
secgroupExternalIds = append(secgroupExternalIds, externalId)
}
}
ret := jsonutils.NewDict()
ret.Set("ext_secgroup_ids", jsonutils.NewStringArray(secgroupExternalIds))
return ret, nil
})
return nil
}
func (self *SQcloudRegionDriver) ValidateCreateElasticcacheAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
elasticCacheV := validators.NewModelIdOrNameValidator("elasticcache", "elasticcache", ownerId)
accountTypeV := validators.NewStringChoicesValidator("account_type", choices.NewChoices("normal")).Default("normal")
accountPrivilegeV := validators.NewStringChoicesValidator("account_privilege", choices.NewChoices("read", "write"))
keyV := map[string]validators.IValidator{
"elasticcache": elasticCacheV,
"account_type": accountTypeV,
"account_privilege": accountPrivilegeV.Default("read"),
}
for _, v := range keyV {
if err := v.Validate(data); err != nil {
return nil, err
}
}
passwd, _ := data.GetString("password")
if !seclib2.MeetComplxity(passwd) {
return nil, httperrors.NewWeakPasswordError()
}
return data, nil
}
func (self *SQcloudRegionDriver) RequestCreateElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAccount, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
_ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId)
if err != nil {
return nil, errors.Wrap(nil, "qcloudRegionDriver.CreateElasticcacheAccount.GetElasticcache")
}
ec := _ec.(*models.SElasticcache)
iregion, err := ec.GetIRegion()
if err != nil {
return nil, errors.Wrap(nil, "qcloudRegionDriver.CreateElasticcacheAccount.GetIRegion")
}
params, err := ea.GetCreateQcloudElasticcacheAccountParams()
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcacheAccount.GetCreateQcloudElasticcacheAccountParams")
}
iec, err := iregion.GetIElasticcacheById(ec.GetExternalId())
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcacheAccount.GetIElasticcacheById")
}
iea, err := iec.CreateAccount(params)
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcacheAccount.CreateAccount")
}
ea.SetModelManager(models.ElasticcacheAccountManager, ea)
if err := db.SetExternalId(ea, userCred, iea.GetGlobalId()); err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcacheAccount.SetExternalId")
}
err = cloudprovider.WaitStatusWithDelay(iea, api.ELASTIC_CACHE_ACCOUNT_STATUS_AVAILABLE, 3*time.Second, 3*time.Second, 180*time.Second)
if err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcacheAccount.WaitStatusWithDelay")
}
if err = ea.SyncWithCloudElasticcacheAccount(ctx, userCred, iea); err != nil {
return nil, errors.Wrap(err, "qcloudRegionDriver.CreateElasticcacheAccount.SyncWithCloudElasticcache")
}
return nil, nil
})
return nil
}
func (self *SQcloudRegionDriver) RequestElasticcacheAccountResetPassword(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAccount, task taskman.ITask) error {
iregion, err := ea.GetIRegion()
if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.GetIRegion")
}
_ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId)
if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.FetchById")
}
ec := _ec.(*models.SElasticcache)
iec, err := iregion.GetIElasticcacheById(ec.GetExternalId())
if errors.Cause(err) == cloudprovider.ErrNotFound {
return nil
} else if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.GetIElasticcacheById")
}
iea, err := iec.GetICloudElasticcacheAccount(ea.GetExternalId())
if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.GetICloudElasticcacheBackup")
}
data := task.GetParams()
if data == nil {
return errors.Wrap(fmt.Errorf("data is nil"), "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.GetParams")
}
input, err := ea.GetUpdateQcloudElasticcacheAccountParams(*data)
if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.GetUpdateQcloudElasticcacheAccountParams")
}
err = iea.UpdateAccount(input)
if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.UpdateAccount")
}
if input.Password != nil {
err = ea.SavePassword(*input.Password)
if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.SavePassword")
}
}
err = cloudprovider.WaitStatusWithDelay(iea, api.ELASTIC_CACHE_ACCOUNT_STATUS_AVAILABLE, 10*time.Second, 5*time.Second, 60*time.Second)
if err != nil {
return errors.Wrap(err, "qcloudRegionDriver.RequestElasticcacheAccountResetPassword.WaitStatusWithDelay")
}
return ea.SyncWithCloudElasticcacheAccount(ctx, userCred, iea)
}
+1
View File
@@ -222,6 +222,7 @@ func InitHandlers(app *appsrv.Application) {
models.InstanceSnapshotJointManager,
models.DnsZoneVpcManager,
models.DBInstanceSecgroupManager,
models.ElasticcachesecgroupManager,
} {
db.RegisterModelManager(manager)
handler := db.NewJointModelHandler(manager)
@@ -54,7 +54,7 @@ func (self *ElasticcacheAccountCreateTask) OnInit(ctx context.Context, obj db.IS
self.SetStage("OnElasticcacheAccountCreateComplete", nil)
if err := region.GetDriver().RequestCreateElasticcacheAccount(ctx, self.GetUserCred(), ea, self); err != nil {
self.taskFail(ctx, ea, jsonutils.Marshal(err))
self.taskFail(ctx, ea, jsonutils.NewString(err.Error()))
return
}
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheAccountDeleteTask) OnInit(ctx context.Context, obj db.IS
self.SetStage("OnElasticcacheAccountDeleteComplete", nil)
if err := region.GetDriver().RequestDeleteElasticcacheAccount(ctx, self.GetUserCred(), ea, self); err != nil {
self.taskFail(ctx, ea, jsonutils.Marshal(err))
self.taskFail(ctx, ea, jsonutils.NewString(err.Error()))
return
} else {
err = db.DeleteModel(ctx, self.GetUserCred(), ea)
@@ -59,7 +59,7 @@ func (self *ElasticcacheAccountResetPasswordTask) OnInit(ctx context.Context, ob
self.SetStage("OnElasticcacheAccountResetPasswordComplete", nil)
if err := region.GetDriver().RequestElasticcacheAccountResetPassword(ctx, self.GetUserCred(), ea, self); err != nil {
self.taskFail(ctx, ea, jsonutils.Marshal(err))
self.taskFail(ctx, ea, jsonutils.NewString(err.Error()))
return
} else {
logclient.AddActionLogWithStartable(self, ea, logclient.ACT_RESET_PASSWORD, nil, self.UserCred, true)
@@ -54,7 +54,7 @@ func (self *ElasticcacheAclCreateTask) OnInit(ctx context.Context, obj db.IStand
self.SetStage("OnElasticcacheAclCreateComplete", nil)
if err := region.GetDriver().RequestCreateElasticcacheAcl(ctx, self.GetUserCred(), ea, self); err != nil {
self.taskFail(ctx, ea, jsonutils.Marshal(err))
self.taskFail(ctx, ea, jsonutils.NewString(err.Error()))
return
}
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheAclDeleteTask) OnInit(ctx context.Context, obj db.IStand
self.SetStage("OnElasticcacheAclDeleteComplete", nil)
if err := region.GetDriver().RequestDeleteElasticcacheAcl(ctx, self.GetUserCred(), ea, self); err != nil {
self.taskFail(ctx, ea, jsonutils.Marshal(err))
self.taskFail(ctx, ea, jsonutils.NewString(err.Error()))
return
} else {
err = db.DeleteModel(ctx, self.GetUserCred(), ea)
@@ -54,7 +54,7 @@ func (self *ElasticcacheAclUpdateTask) OnInit(ctx context.Context, obj db.IStand
self.SetStage("OnElasticcacheAclUpdateComplete", nil)
if err := region.GetDriver().RequestElasticcacheAclUpdate(ctx, self.GetUserCred(), ea, self); err != nil {
self.taskFail(ctx, ea, jsonutils.Marshal(err))
self.taskFail(ctx, ea, jsonutils.NewString(err.Error()))
return
}
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheAllocatePublicConnectionTask) OnInit(ctx context.Context
self.SetStage("OnElasticcacheAllocatePublicConnectionComplete", nil)
if err := region.GetDriver().RequestElasticcacheAllocatePublicConnection(ctx, self.GetUserCred(), elasticcache, self); err != nil {
self.OnElasticcacheAllocatePublicConnectionCompleteFailed(ctx, elasticcache, jsonutils.Marshal(err))
self.OnElasticcacheAllocatePublicConnectionCompleteFailed(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheBackupCreateTask) OnInit(ctx context.Context, obj db.ISt
self.SetStage("OnElasticcacheBackupCreateComplete", nil)
if err := region.GetDriver().RequestCreateElasticcacheBackup(ctx, self.GetUserCred(), eb, self); err != nil {
self.taskFail(ctx, eb, jsonutils.Marshal(err))
self.taskFail(ctx, eb, jsonutils.NewString(err.Error()))
return
}
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheBackupRestoreInstanceTask) OnInit(ctx context.Context, o
self.SetStage("OnElasticcacheBackupRestoreInstanceComplete", nil)
if err := region.GetDriver().RequestElasticcacheBackupRestoreInstance(ctx, self.GetUserCred(), eb, self); err != nil {
self.OnElasticcacheBackupRestoreInstanceCompleteFailed(ctx, eb, jsonutils.Marshal(err))
self.OnElasticcacheBackupRestoreInstanceCompleteFailed(ctx, eb, jsonutils.NewString(err.Error()))
return
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheChangeSpecTask) OnInit(ctx context.Context, obj db.IStan
self.SetStage("OnElasticcacheChangeSpecComplete", nil)
if err := region.GetDriver().RequestElasticcacheChangeSpec(ctx, self.GetUserCred(), elasticcache, self); err != nil {
self.OnElasticcacheChangeSpecCompleteFailed(ctx, elasticcache, jsonutils.Marshal(err))
self.OnElasticcacheChangeSpecCompleteFailed(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
+24 -3
View File
@@ -19,6 +19,7 @@ import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -54,14 +55,34 @@ func (self *ElasticcacheCreateTask) OnInit(ctx context.Context, obj db.IStandalo
// sync security group here
self.SetStage("OnSyncSecurityGroupComplete", data.(*jsonutils.JSONDict))
self.OnSyncSecurityGroupComplete(ctx, elasticcache, data)
if region.GetDriver().IsSupportedElasticcacheSecgroup() {
secgroups := []string{}
err := self.GetParams().Unmarshal(&secgroups, "secgroup_ids")
if err != nil {
self.taskFail(ctx, elasticcache, jsonutils.Marshal(errors.Wrap(err, "Unmarshal.secgroup_ids")))
return
}
secgroupInput := api.ElasticcacheSecgroupsInput{SecgroupIds: secgroups}
_, err = elasticcache.ProcessElasticcacheSecgroupsInput(ctx, self.UserCred, "set", &secgroupInput)
if err != nil {
self.taskFail(ctx, elasticcache, jsonutils.Marshal(errors.Wrap(err, "ProcessElasticcacheSecgroupsInput")))
return
}
if err := region.GetDriver().RequestSyncSecgroupsForElasticcache(ctx, self.UserCred, elasticcache, self); err != nil {
self.taskFail(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
} else {
self.OnSyncSecurityGroupComplete(ctx, elasticcache, data)
}
}
func (self *ElasticcacheCreateTask) OnSyncSecurityGroupComplete(ctx context.Context, elasticcache *models.SElasticcache, data jsonutils.JSONObject) {
region := elasticcache.GetRegion()
self.SetStage("OnElasticcacheCreateComplete", nil)
if err := region.GetDriver().RequestCreateElasticcache(ctx, self.GetUserCred(), elasticcache, self); err != nil {
self.taskFail(ctx, elasticcache, jsonutils.Marshal(err))
if err := region.GetDriver().RequestCreateElasticcache(ctx, self.GetUserCred(), elasticcache, self, data.(*jsonutils.JSONDict)); err != nil {
self.taskFail(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheFlushInstanceTask) OnInit(ctx context.Context, obj db.IS
self.SetStage("OnElasticcacheFlushInstanceComplete", nil)
if err := region.GetDriver().RequestElasticcacheFlushInstance(ctx, self.GetUserCred(), elasticcache, self); err != nil {
self.OnElasticcacheFlushInstanceCompleteFailed(ctx, elasticcache, jsonutils.Marshal(err))
self.OnElasticcacheFlushInstanceCompleteFailed(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
@@ -60,7 +60,7 @@ func (self *ElasticcacheParameterUpdateTask) OnInit(ctx context.Context, obj db.
self.SetStage("OnElasticcacheParameterUpdateComplete", nil)
if err := region.GetDriver().RequestElasticcacheUpdateInstanceParameters(ctx, self.GetUserCred(), iec.(*models.SElasticcache), self); err != nil {
self.OnElasticcacheParameterUpdateCompleteFailed(ctx, ep, jsonutils.Marshal(err))
self.OnElasticcacheParameterUpdateCompleteFailed(ctx, ep, jsonutils.NewString(err.Error()))
return
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheReleasePublicConnectionTask) OnInit(ctx context.Context,
self.SetStage("OnElasticcacheReleasePublicConnectionComplete", nil)
if err := region.GetDriver().RequestElasticcacheReleasePublicConnection(ctx, self.GetUserCred(), elasticcache, self); err != nil {
self.OnElasticcacheReleasePublicConnectionCompleteFailed(ctx, elasticcache, jsonutils.Marshal(err))
self.OnElasticcacheReleasePublicConnectionCompleteFailed(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheRestartTask) OnInit(ctx context.Context, obj db.IStandal
self.SetStage("OnElasticcacheRestartComplete", nil)
if err := region.GetDriver().RequestRestartElasticcache(ctx, self.GetUserCred(), ec, self); err != nil {
self.taskFail(ctx, ec, jsonutils.Marshal(err))
self.taskFail(ctx, ec, jsonutils.NewString(err.Error()))
return
} else {
logclient.AddActionLogWithStartable(self, ec, logclient.ACT_VM_RESTART, nil, self.UserCred, true)
@@ -54,7 +54,7 @@ func (self *ElasticcacheSetMaintainTimeTask) OnInit(ctx context.Context, obj db.
self.SetStage("OnElasticcacheSetMaintainTimeComplete", nil)
if err := region.GetDriver().RequestElasticcacheSetMaintainTime(ctx, self.GetUserCred(), elasticcache, self); err != nil {
self.OnElasticcacheSetMaintainTimeCompleteFailed(ctx, elasticcache, jsonutils.Marshal(err))
self.OnElasticcacheSetMaintainTimeCompleteFailed(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
+1 -1
View File
@@ -54,7 +54,7 @@ func (self *ElasticcacheSyncTask) OnInit(ctx context.Context, obj db.IStandalone
self.SetStage("OnElasticcacheSyncComplete", nil)
if err := region.GetDriver().RequestSyncElasticcache(ctx, self.GetUserCred(), ec, self); err != nil {
self.taskFail(ctx, ec, jsonutils.Marshal(err))
self.taskFail(ctx, ec, jsonutils.NewString(err.Error()))
return
} else {
logclient.AddActionLogWithStartable(self, ec, logclient.ACT_SYNC_CONF, "", self.UserCred, true)
@@ -0,0 +1,95 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tasks
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
type ElasticcacheSyncsecgroupsTask struct {
taskman.STask
}
func init() {
taskman.RegisterTask(ElasticcacheSyncsecgroupsTask{})
}
func (self *ElasticcacheSyncsecgroupsTask) taskFailed(ctx context.Context, cache *models.SElasticcache, err jsonutils.JSONObject) {
cache.SetStatus(self.GetUserCred(), api.ELASTIC_CACHE_STATUS_SYNC_FAILED, err.String())
self.SetStageFailed(ctx, err)
db.OpsLog.LogEvent(cache, db.ACT_SYNC_CONF, cache.GetShortDesc(ctx), self.GetUserCred())
logclient.AddActionLogWithContext(ctx, cache, logclient.ACT_SYNC_CONF, err, self.UserCred, false)
}
func (self *ElasticcacheSyncsecgroupsTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
cache := obj.(*models.SElasticcache)
region := cache.GetRegion()
if region == nil {
self.taskFailed(ctx, cache, jsonutils.NewString(fmt.Sprintf("failed to found cloudregion for elasticcache %s(%s)", cache.Name, cache.Id)))
return
}
self.SetStage("OnElasticcacheSyncSecgroupsComplete", nil)
err := region.GetDriver().RequestSyncSecgroupsForElasticcache(ctx, self.GetUserCred(), cache, self)
if err != nil {
self.taskFailed(ctx, cache, jsonutils.Marshal(err))
return
}
}
// https://cloud.tencent.com/document/api/239/41256
func (self *ElasticcacheSyncsecgroupsTask) OnElasticcacheSyncSecgroupsComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
cache := obj.(*models.SElasticcache)
secgroups := []string{}
err := data.Unmarshal(&secgroups, "ext_secgroup_ids")
if err != nil {
self.taskFailed(ctx, cache, jsonutils.Marshal(err))
return
}
iregion, err := cache.GetIRegion()
if err != nil {
self.taskFailed(ctx, cache, jsonutils.Marshal(err))
return
}
iec, err := iregion.GetIElasticcacheById(cache.GetExternalId())
if err != nil {
self.taskFailed(ctx, cache, jsonutils.Marshal(err))
return
}
err = iec.UpdateSecurityGroups(secgroups)
if err != nil {
self.taskFailed(ctx, cache, jsonutils.Marshal(err))
return
}
self.SetStageComplete(ctx, nil)
}
func (self *ElasticcacheSyncsecgroupsTask) OnElasticcacheSyncSecgroupsCompleteFailed(ctx context.Context, cache *models.SElasticcache, data jsonutils.JSONObject) {
self.taskFailed(ctx, cache, data)
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheSyncstatusTask) OnInit(ctx context.Context, obj db.IStan
self.SetStage("OnElasticcacheSyncStatusComplete", nil)
err := region.GetDriver().RequestSyncElasticcacheStatus(ctx, self.GetUserCred(), cache, self)
if err != nil {
self.taskFailed(ctx, cache, jsonutils.Marshal(err))
self.taskFailed(ctx, cache, jsonutils.NewString(err.Error()))
return
}
}
@@ -54,7 +54,7 @@ func (self *ElasticcacheUpdateAuthModeTask) OnInit(ctx context.Context, obj db.I
self.SetStage("OnElasticcacheUpdateAuthModeComplete", nil)
if err := region.GetDriver().RequestUpdateElasticcacheAuthMode(ctx, self.GetUserCred(), elasticcache, self); err != nil {
self.OnElasticcacheUpdateAuthModeCompleteFailed(ctx, elasticcache, jsonutils.Marshal(err))
self.OnElasticcacheUpdateAuthModeCompleteFailed(ctx, elasticcache, jsonutils.NewString(err.Error()))
return
}
+7 -6
View File
@@ -29,12 +29,13 @@ type ElasticCacheCreateOptions struct {
Cloudregion string
Zone string
VpcId string
Network string `help:"network id"`
SecurityGroup string `help:"elastic cache security group. required by huawei."`
Engine string `choices:"redis"`
EngineVersion string `choices:"2.8|3.0|4.0|5.0"`
PrivateIP string `help:"private ip address in specificated network"`
Password string `help:"set auth password"`
Network string `help:"network id"`
SecurityGroup string `help:"elastic cache security group. required by huawei."`
SecgroupIds []string `help:"elastic cache security group. required by qcloud."`
Engine string `choices:"redis"`
EngineVersion string `choices:"2.8|3.0|3.2|4.0|5.0"`
PrivateIP string `help:"private ip address in specificated network"`
Password string `help:"set auth password"`
InstanceType string
CapacityMB string `help:"elastic cache capacity. required by huawei."`
BillingType string `choices:"postpaid|prepaid" default:"postpaid"`
+10 -2
View File
@@ -797,7 +797,7 @@ func (self *SElasticcache) UpdateInstanceParameters(config jsonutils.JSONObject)
}
// https://help.aliyun.com/document_detail/61075.html?spm=a2c4g.11186623.6.749.4cba126a2U9xNa
func (self *SElasticcache) CreateBackup() (cloudprovider.ICloudElasticcacheBackup, error) {
func (self *SElasticcache) CreateBackup(desc string) (cloudprovider.ICloudElasticcacheBackup, error) {
params := make(map[string]string)
params["InstanceId"] = self.GetId()
@@ -826,7 +826,7 @@ func (self *SElasticcache) UpdateBackupPolicy(config cloudprovider.SCloudElastic
}
// https://help.aliyun.com/document_detail/60931.html?spm=a2c4g.11186623.6.728.5c57292920UKx3
func (self *SElasticcache) FlushInstance() error {
func (self *SElasticcache) FlushInstance(input cloudprovider.SCloudElasticCacheFlushInstanceInput) error {
params := make(map[string]string)
params["InstanceId"] = self.GetId()
@@ -873,6 +873,10 @@ func (self *SElasticcache) GetAuthMode() string {
}
}
func (self *SElasticcache) GetSecurityGroupIds() ([]string, error) {
return nil, cloudprovider.ErrNotSupported
}
func (self *SElasticcache) GetICloudElasticcacheAccount(accountId string) (cloudprovider.ICloudElasticcacheAccount, error) {
segs := strings.Split(accountId, "/")
if len(segs) < 2 {
@@ -929,3 +933,7 @@ func (instance *SElasticcache) GetMetadata() *jsonutils.JSONDict {
func (instance *SElasticcache) SetMetadata(tags map[string]string, replace bool) error {
return instance.region.SetResourceTags("kvs", "INSTANCE", []string{instance.GetId()}, tags, replace)
}
func (self *SElasticcache) UpdateSecurityGroups(secgroupIds []string) error {
return errors.Wrap(cloudprovider.ErrNotSupported, "UpdateSecurityGroups")
}
+13 -3
View File
@@ -439,7 +439,9 @@ func (self *SRegion) CreateIElasticcaches(ec *cloudprovider.SCloudElasticCacheIn
params.Set("engine_version", jsonutils.NewString(ec.EngineVersion))
params.Set("capacity", jsonutils.NewInt(ec.CapacityGB))
params.Set("vpc_id", jsonutils.NewString(ec.VpcId))
params.Set("security_group_id", jsonutils.NewString(ec.SecurityGroupId))
if len(ec.SecurityGroupIds) > 0 {
params.Set("security_group_id", jsonutils.NewString(ec.SecurityGroupIds[0]))
}
params.Set("subnet_id", jsonutils.NewString(ec.NetworkId))
params.Set("product_id", jsonutils.NewString(ec.InstanceType))
zones, err := self.zoneNameToDcsZoneIds(ec.ZoneIds)
@@ -613,7 +615,7 @@ func (self *SElasticcache) UpdateInstanceParameters(config jsonutils.JSONObject)
}
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423033.html
func (self *SElasticcache) CreateBackup() (cloudprovider.ICloudElasticcacheBackup, error) {
func (self *SElasticcache) CreateBackup(desc string) (cloudprovider.ICloudElasticcacheBackup, error) {
return nil, cloudprovider.ErrNotSupported
}
@@ -666,7 +668,7 @@ func (self *SElasticcache) UpdateBackupPolicy(config cloudprovider.SCloudElastic
// https://support.huaweicloud.com/api-dcs/dcs-zh-api-180423030.html
// 当前版本,只有DCS2.0实例支持清空数据功能,即flush操作。
func (self *SElasticcache) FlushInstance() error {
func (self *SElasticcache) FlushInstance(input cloudprovider.SCloudElasticCacheFlushInstanceInput) error {
resp, err := self.region.ecsClient.Elasticcache.Flush(self.GetId())
if err != nil {
return errors.Wrap(err, "elasticcache.FlushInstance")
@@ -700,6 +702,10 @@ func (self *SElasticcache) GetAuthMode() string {
}
}
func (self *SElasticcache) GetSecurityGroupIds() ([]string, error) {
return nil, cloudprovider.ErrNotSupported
}
func (self *SElasticcache) GetICloudElasticcacheAccount(accountId string) (cloudprovider.ICloudElasticcacheAccount, error) {
accounts, err := self.GetICloudElasticcacheAccounts()
if err != nil {
@@ -738,3 +744,7 @@ func (self *SElasticcache) GetICloudElasticcacheBackup(backupId string) (cloudpr
func (instance *SElasticcache) SetMetadata(tags map[string]string, replace bool) error {
return cloudprovider.ErrNotImplemented
}
func (self *SElasticcache) UpdateSecurityGroups(secgroupIds []string) error {
return errors.Wrap(cloudprovider.ErrNotSupported, "UpdateSecurityGroups")
}
+55
View File
@@ -0,0 +1,55 @@
package qcloud
import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SElasticcacheDeal struct {
region *SRegion
DealID string `json:"DealId"`
DealName string `json:"DealName"`
ZoneID int64 `json:"ZoneId"`
GoodsNum int64 `json:"GoodsNum"`
Creater string `json:"Creater"`
CreatTime string `json:"CreatTime"`
OverdueTime string `json:"OverdueTime"`
EndTime string `json:"EndTime"`
Status int64 `json:"Status"`
Description string `json:"Description"`
Price int64 `json:"Price"`
InstanceIDS []string `json:"InstanceIds"`
}
// https://cloud.tencent.com/document/product/239/30602
func (self *SRegion) GetElasticcacheIdByDeal(dealId string) (string, error) {
params := map[string]string{}
params["DealIds.0"] = dealId
resp, err := self.redisRequest("DescribeInstanceDealDetail", params)
if err != nil {
return "", errors.Wrap(err, "DescribeInstanceDealDetail")
}
ret := []SElasticcacheDeal{}
err = resp.Unmarshal(&ret, "DealDetails")
if err != nil {
return "", errors.Wrap(err, "DealDetails")
}
if len(ret) == 0 {
return "", cloudprovider.ErrNotFound
} else if len(ret) > 1 {
log.Infof("%#v", ret)
return "", cloudprovider.ErrDuplicateId
} else {
if ret[0].InstanceIDS != nil && len(ret[0].InstanceIDS) == 1 {
return ret[0].InstanceIDS[0], nil
} else {
log.Infof("%#v", ret)
return "", cloudprovider.ErrNotFound
}
}
}
@@ -0,0 +1,152 @@
package qcloud
import (
"fmt"
"strings"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SElasticcacheAccount struct {
multicloud.SElasticcacheAccountBase
cacheDB *SElasticcache
InstanceID string `json:"InstanceId"`
AccountName string `json:"AccountName"`
Remark string `json:"Remark"`
Privilege string `json:"Privilege"`
ReadonlyPolicy []string `json:"ReadonlyPolicy"`
Status int `json:"Status"`
}
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 {
switch self.Status {
case 1:
return api.ELASTIC_CACHE_ACCOUNT_STATUS_CREATING
case 2:
return api.ELASTIC_CACHE_ACCOUNT_STATUS_AVAILABLE
case 4:
return api.ELASTIC_CACHE_ACCOUNT_STATUS_DELETED
default:
return api.ELASTIC_CACHE_ACCOUNT_STATUS_UNAVAILABLE
}
}
func (self *SElasticcacheAccount) GetAccountType() string {
if strings.ToLower(self.AccountName) == "root" {
return api.ELASTIC_CACHE_ACCOUNT_TYPE_ADMIN
} else {
return api.ELASTIC_CACHE_ACCOUNT_TYPE_NORMAL
}
}
func (self *SElasticcacheAccount) GetAccountPrivilege() string {
switch self.Privilege {
case "r":
return api.ELASTIC_CACHE_ACCOUNT_PRIVILEGE_READ
case "w":
return api.ELASTIC_CACHE_ACCOUNT_PRIVILEGE_WRITE
case "rw":
return api.ELASTIC_CACHE_ACCOUNT_PRIVILEGE_WRITE
default:
return self.Privilege
}
}
func (self *SElasticcacheAccount) Refresh() error {
account, err := self.cacheDB.GetICloudElasticcacheAccount(self.GetGlobalId())
if err != nil {
return errors.Wrap(err, "GetICloudElasticcacheAccount")
}
err = jsonutils.Update(self, account)
if err != nil {
return errors.Wrap(err, "Update")
}
return nil
}
// https://cloud.tencent.com/document/product/239/38925
func (self *SElasticcacheAccount) Delete() error {
params := map[string]string{}
params["InstanceId"] = self.cacheDB.GetId()
params["AccountName"] = self.AccountName
_, err := self.cacheDB.region.redisRequest("DeleteInstanceAccount", params)
if err != nil {
return errors.Wrap(err, "DeleteInstanceAccount")
}
return nil
}
// https://cloud.tencent.com/document/product/239/20014
func (self *SElasticcacheAccount) ResetPassword(input cloudprovider.SCloudElasticCacheAccountResetPasswordInput) error {
params := map[string]string{}
params["InstanceId"] = self.cacheDB.GetId()
if input.NoPasswordAccess != nil && *input.NoPasswordAccess {
params["NoAuth"] = "true"
} else {
if len(input.NewPassword) > 0 {
params["Password"] = input.NewPassword
} else {
return nil
}
}
_, err := self.cacheDB.region.redisRequest("ResetPassword", params)
if err != nil {
return errors.Wrap(err, "ResetPassword")
}
return nil
}
// https://cloud.tencent.com/document/product/239/38923
func (self *SElasticcacheAccount) UpdateAccount(input cloudprovider.SCloudElasticCacheAccountUpdateInput) error {
params := map[string]string{}
params["InstanceId"] = self.cacheDB.GetId()
params["AccountName"] = self.AccountName
if input.NoPasswordAccess != nil && *input.NoPasswordAccess {
params["NoAuth"] = "true"
} else {
if input.Password != nil && len(*input.Password) > 0 {
params["AccountPassword"] = *input.Password
}
}
if input.Description != nil && len(*input.Description) > 0 {
params["Remark"] = *input.Description
}
if input.AccountPrivilege != nil && len(*input.AccountPrivilege) > 0 {
params["Privilege"] = *input.AccountPrivilege
params["ReadonlyPolicy.0"] = "master"
}
_, err := self.cacheDB.region.redisRequest("ModifyInstanceAccount", params)
if err != nil {
return errors.Wrap(err, "ModifyInstanceAccount")
}
return nil
}
@@ -0,0 +1,170 @@
package qcloud
import (
"strconv"
"strings"
"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"
)
type SElasticcacheBackup struct {
multicloud.SElasticcacheBackupBase
cacheDB *SElasticcache
StartTime time.Time `json:"StartTime"`
BackupID string `json:"BackupId"`
BackupType string `json:"BackupType"`
Status int `json:"Status"`
Remark string `json:"Remark"`
Locked int64 `json:"Locked"`
}
func (self *SElasticcacheBackup) GetId() string {
return self.BackupID
}
func (self *SElasticcacheBackup) GetName() string {
if len(self.Remark) > 0 {
segs := strings.Split(self.Remark, "@")
return segs[0]
}
return self.GetId()
}
func (self *SElasticcacheBackup) GetGlobalId() string {
return self.GetId()
}
/*
ELASTIC_CACHE_BACKUP_STATUS_CREATING = "creating" // 备份中
ELASTIC_CACHE_BACKUP_STATUS_CREATE_EXPIRED = "expired" //(备份文件已过期)
ELASTIC_CACHE_BACKUP_STATUS_CREATE_DELETED = "deleted" //(备份文件已删除)
ELASTIC_CACHE_BACKUP_STATUS_DELETING = "deleting" // 删除中
ELASTIC_CACHE_BACKUP_STATUS_SUCCESS = "success" // 备份成功
ELASTIC_CACHE_BACKUP_STATUS_FAILED = "failed" // 备份失败
*/
func (self *SElasticcacheBackup) GetStatus() string {
switch self.Status {
case 1:
return api.ELASTIC_CACHE_BACKUP_STATUS_CREATING
case 2:
return api.ELASTIC_CACHE_BACKUP_STATUS_SUCCESS
case -1:
return api.ELASTIC_CACHE_BACKUP_STATUS_CREATE_EXPIRED
case -2:
return api.ELASTIC_CACHE_BACKUP_STATUS_CREATE_DELETED
case 3:
return api.ELASTIC_CACHE_BACKUP_STATUS_CREATING
case 4:
return api.ELASTIC_CACHE_BACKUP_STATUS_SUCCESS
default:
return strconv.Itoa(self.Status)
}
}
func (self *SElasticcacheBackup) Refresh() error {
backup, err := self.cacheDB.GetICloudElasticcacheBackup(self.GetGlobalId())
if err != nil {
return errors.Wrap(err, "GetICloudElasticcacheBackup")
}
err = jsonutils.Update(self, backup)
if err != nil {
return errors.Wrap(err, "Update")
}
return nil
}
func (self *SElasticcacheBackup) GetBackupSizeMb() int {
return 0
}
func (self *SElasticcacheBackup) GetBackupType() string {
return api.ELASTIC_CACHE_BACKUP_TYPE_INCREMENTAL
}
func (self *SElasticcacheBackup) GetBackupMode() string {
switch self.BackupType {
case "systemBackupInstance":
return api.ELASTIC_CACHE_BACKUP_MODE_AUTOMATED
case "manualBackupInstance":
return api.ELASTIC_CACHE_BACKUP_MODE_MANUAL
default:
return self.BackupType
}
}
// https://cloud.tencent.com/document/api/239/34443
func (self *SElasticcacheBackup) GetDownloadURL() string {
url, err := self.GetBackupDownloadURL()
if err != nil {
log.Debugf("GetBackupDownloadURL %s", err)
return ""
}
return url
}
func (self *SElasticcacheBackup) GetStartTime() time.Time {
return self.StartTime
}
func (self *SElasticcacheBackup) GetEndTime() time.Time {
return time.Time{}
}
func (self *SElasticcacheBackup) Delete() error {
return errors.Wrap(cloudprovider.ErrNotSupported, "Delete")
}
// https://cloud.tencent.com/document/product/239/34435
// todo: password
func (self *SElasticcacheBackup) RestoreInstance(instanceId string) error {
params := map[string]string{}
params["InstanceId"] = instanceId
params["BackupId"] = self.GetId()
//if len(Password) > 0 {
// params["Password"] = Password
//}
_, err := self.cacheDB.region.redisRequest("RestoreInstance", params)
if err != nil {
return errors.Wrap(err, "RestoreInstance")
}
return nil
}
func (self *SElasticcacheBackup) GetBackupDownloadURL() (string, error) {
params := map[string]string{}
params["InstanceId"] = self.cacheDB.GetId()
params["BackupId"] = self.GetId()
client := self.cacheDB.region.client
resp, err := client.redisRequest("DescribeBackupUrl", params)
if err != nil {
return "", errors.Wrap(err, "DescribeBackupUrl")
}
urls := []string{}
err = resp.Unmarshal(&urls, "DownloadUrl")
if err != nil {
return "", errors.Wrap(err, "Unmarshal.DownloadUrl")
}
if len(urls) > 0 {
return urls[0], nil
}
return "", nil
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,77 @@
package qcloud
import (
"fmt"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SElasticcacheParameters struct {
multicloud.SElasticcacheParameterBase
cacheDB *SElasticcache
InstanceEnumParam []SElasticcacheParameter `json:"InstanceEnumParam"`
InstanceIntegerParam []SElasticcacheParameter `json:"InstanceIntegerParam"`
InstanceTextParam []SElasticcacheParameter `json:"InstanceTextParam"`
RequestID string `json:"RequestId"`
TotalCount int64 `json:"TotalCount"`
}
type SElasticcacheParameter struct {
multicloud.SElasticcacheParameterBase
cacheDB *SElasticcache
CurrentValue string `json:"CurrentValue"`
DefaultValue string `json:"DefaultValue"`
EnumValue []string `json:"EnumValue,omitempty"`
NeedRestart string `json:"NeedRestart"`
ParamName string `json:"ParamName"`
Tips string `json:"Tips"`
ValueType string `json:"ValueType"`
Max *string `json:"Max,omitempty"`
Min *string `json:"Min,omitempty"`
TextValue []string `json:"TextValue,omitempty"`
}
func (self *SElasticcacheParameter) GetId() string {
return fmt.Sprintf("%s/%s", self.cacheDB.InstanceID, self.ParamName)
}
func (self *SElasticcacheParameter) GetName() string {
return self.ParamName
}
func (self *SElasticcacheParameter) GetGlobalId() string {
return self.GetId()
}
func (self *SElasticcacheParameter) GetStatus() string {
return api.ELASTIC_CACHE_PARAMETER_STATUS_AVAILABLE
}
func (self *SElasticcacheParameter) GetParameterKey() string {
return self.ParamName
}
func (self *SElasticcacheParameter) GetParameterValue() string {
return self.CurrentValue
}
func (self *SElasticcacheParameter) GetParameterValueRange() string {
return fmt.Sprintf("%s", self.EnumValue)
}
func (self *SElasticcacheParameter) GetDescription() string {
return self.Tips
}
func (self *SElasticcacheParameter) GetModifiable() bool {
return true
}
func (self *SElasticcacheParameter) GetForceRestart() bool {
return self.NeedRestart == "true"
}
@@ -0,0 +1,24 @@
package qcloud
import "yunion.io/x/onecloud/pkg/multicloud"
type SElasticcacheSecgroup struct {
multicloud.SElasticcacheBackupBase
cacheDB *SElasticcache
CreateTime string `json:"CreateTime"`
InboundRule []BoundRule `json:"InboundRule"`
OutboundRule []BoundRule `json:"OutboundRule"`
ProjectID int64 `json:"ProjectId"`
SecurityGroupID string `json:"SecurityGroupId"`
SecurityGroupName string `json:"SecurityGroupName"`
SecurityGroupRemark string `json:"SecurityGroupRemark"`
}
type BoundRule struct {
Action string `json:"Action"`
IP string `json:"Ip"`
Port string `json:"Port"`
Proto string `json:"Proto"`
}
@@ -0,0 +1,30 @@
package qcloud
import "yunion.io/x/pkg/errors"
type SElasticcacheTask struct {
Status string `json:"Status"`
StartTime string `json:"StartTime"`
TaskType string `json:"TaskType"`
InstanceID string `json:"InstanceId"`
TaskMessage string `json:"TaskMessage"`
RequestID string `json:"RequestId"`
}
// https://cloud.tencent.com/document/product/239/30601
func (self *SRegion) DescribeTaskInfo(taskId string) (*SElasticcacheTask, error) {
params := map[string]string{}
params["TaskId"] = taskId
resp, err := self.redisRequest("DescribeTaskInfo", params)
if err != nil {
return nil, errors.Wrap(err, "DescribeTaskInfo")
}
ret := &SElasticcacheTask{}
err = resp.Unmarshal(ret)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
return ret, nil
}
+18
View File
@@ -55,6 +55,7 @@ const (
QCLOUD_MARIADB_API_VERSION = "2017-03-12"
QCLOUD_POSTGRES_API_VERSION = "2017-03-12"
QCLOUD_SQLSERVER_API_VERSION = "2018-03-28"
QCLOUD_REDIS_API_VERSION = "2018-04-12"
)
type QcloudClientConfig struct {
@@ -159,6 +160,12 @@ func accountRequest(client *common.Client, apiName string, params map[string]str
return _phpJsonRequest(client, &wssJsonResponse{}, domain, "/v2/index.php", "", apiName, params, debug)
}
// redis
func redisRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
domain := apiDomain("redis", params)
return _jsonRequest(client, domain, QCLOUD_REDIS_API_VERSION, apiName, params, debug, true)
}
// loadbalancer服务 api 3.0
func clbRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
domain := apiDomain("clb", params)
@@ -550,6 +557,15 @@ func (client *SQcloudClient) cdbRequest(apiName string, params map[string]string
return cdbRequest(cli, apiName, params, client.debug)
}
func (client *SQcloudClient) redisRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := client.getDefaultClient()
if err != nil {
return nil, err
}
return redisRequest(cli, apiName, params, client.debug)
}
func (client *SQcloudClient) mariadbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
cli, err := client.getDefaultClient()
if err != nil {
@@ -892,6 +908,8 @@ func (self *SQcloudClient) GetCapabilities() []string {
cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE,
cloudprovider.CLOUD_CAPABILITY_RDS,
// cloudprovider.CLOUD_CAPABILITY_CACHE,
// cloudprovider.CLOUD_CAPABILITY_RDS,
cloudprovider.CLOUD_CAPABILITY_CACHE,
cloudprovider.CLOUD_CAPABILITY_EVENT,
cloudprovider.CLOUD_CAPABILITY_CLOUDID,
cloudprovider.CLOUD_CAPABILITY_DNSZONE,
+116
View File
@@ -17,6 +17,8 @@ package qcloud
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/tencentyun/cos-go-sdk-v5"
@@ -712,6 +714,11 @@ func (self *SRegion) wssRequest(apiName string, params map[string]string) (jsonu
return self.client.wssRequest(apiName, params)
}
func (self *SRegion) redisRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
params["Region"] = self.Region
return self.client.redisRequest(apiName, params)
}
func (self *SRegion) GetNetworks(ids []string, vpcId string, offset int, limit int) ([]SNetwork, int, error) {
if limit > 50 || limit <= 0 {
limit = 50
@@ -1001,3 +1008,112 @@ func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreat
func (region *SRegion) GetCapabilities() []string {
return region.client.GetCapabilities()
}
func (region *SRegion) GetIElasticcaches() ([]cloudprovider.ICloudElasticcache, error) {
caches, err := region.GetCloudElasticcaches()
if err != nil {
return nil, errors.Wrap(err, "GetCloudElasticcaches")
}
ret := []cloudprovider.ICloudElasticcache{}
for i := range caches {
cache := caches[i]
cache.region = region
ret = append(ret, &cache)
}
return ret, nil
}
func (region *SRegion) GetIElasticcacheById(id string) (cloudprovider.ICloudElasticcache, error) {
caches, err := region.GetCloudElasticcaches()
if err != nil {
return nil, errors.Wrap(err, "GetCloudElasticcaches")
}
for i := range caches {
if caches[i].GetGlobalId() == id {
caches[i].region = region
return &caches[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
// https://cloud.tencent.com/document/product/239/20026
func (r *SRegion) CreateIElasticcaches(ec *cloudprovider.SCloudElasticCacheInput) (cloudprovider.ICloudElasticcache, error) {
params := map[string]string{}
if len(ec.ZoneIds) == 0 {
return nil, fmt.Errorf("CreateIElasticcaches zone id should not be empty.")
}
zoneId, ok := zoneIdMaps[ec.ZoneIds[0]]
if !ok {
return nil, fmt.Errorf("can't convert zone %s to integer id", ec.ZoneIds[0])
}
spec, err := parseLocalInstanceSpec(ec.InstanceType)
if err != nil {
return nil, errors.Wrap(err, "parseLocalInstanceSpec")
}
params["InstanceName"] = ec.InstanceName
params["ProjectId"] = ec.ProjectId
params["ZoneId"] = fmt.Sprintf("%d", zoneId)
params["TypeId"] = spec.TypeId
params["MemSize"] = strconv.Itoa(spec.MemSizeMB)
params["RedisShardNum"] = spec.RedisShardNum
params["RedisReplicasNum"] = spec.RedisReplicasNum
params["GoodsNum"] = "1"
if strings.ToLower(ec.NetworkType) == api.LB_NETWORK_TYPE_VPC {
params["VpcId"] = ec.VpcId
params["SubnetId"] = ec.NetworkId
for i := range ec.SecurityGroupIds {
params[fmt.Sprintf("SecurityGroupIdList.%d", i)] = ec.SecurityGroupIds[i]
}
}
params["Period"] = "1"
params["BillingMode"] = "0"
if ec.BC != nil && ec.BC.GetMonths() >= 1 {
params["Period"] = strconv.Itoa(ec.BC.GetMonths())
params["BillingMode"] = "1"
// 自动续费
if ec.BC.AutoRenew {
params["AutoRenew"] = "1"
}
}
if len(ec.Password) > 0 {
params["NoAuth"] = "false"
params["Password"] = ec.Password
} else {
params["NoAuth"] = "true"
}
resp, err := r.redisRequest("CreateInstances", params)
if err != nil {
return nil, errors.Wrap(err, "CreateInstances")
}
instanceId, err := resp.GetString("DealId")
if err != nil {
return nil, errors.Wrap(err, "dealId")
}
//instanceId := ""
//err = cloudprovider.Wait(5*time.Second, 900*time.Second, func() (bool, error) {
// instanceId, err = r.GetElasticcacheIdByDeal(dealId)
// if err != nil {
// return false, nil
// }
//
// return true, nil
//})
//if err != nil {
// return nil, errors.Wrap(err, "Wait.GetElasticcacheIdByDeal")
//}
return r.GetIElasticcacheById(instanceId)
}
@@ -0,0 +1,71 @@
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type RedisListOptions struct {
}
shellutils.R(&RedisListOptions{}, "redis-list", "List redis", func(cli *qcloud.SRegion, args *RedisListOptions) error {
redis, err := cli.GetCloudElasticcaches()
if err != nil {
return err
}
printList(redis, 0, 0, 0, []string{})
return nil
})
type RedisParameterListOptions struct {
INSTANCEID string `json:"instanceid"`
}
shellutils.R(&RedisParameterListOptions{}, "redis-parameter-list", "List redis parameters", func(cli *qcloud.SRegion, args *RedisParameterListOptions) error {
parameters, err := cli.GetCloudElasticcacheParameters(args.INSTANCEID)
if err != nil {
return err
}
printList(parameters, 0, 0, 0, []string{})
return nil
})
type RedisBackupListOptions struct {
INSTANCEID string `json:"instanceid"`
}
shellutils.R(&RedisBackupListOptions{}, "redis-backup-list", "List redis backups", func(cli *qcloud.SRegion, args *RedisBackupListOptions) error {
backups, err := cli.GetCloudElasticcacheBackups(args.INSTANCEID)
if err != nil {
return err
}
printList(backups, 0, 0, 0, []string{})
return nil
})
type RedisSecGroupListOptions struct {
INSTANCEID string `json:"instanceid"`
}
shellutils.R(&RedisSecGroupListOptions{}, "redis-secgroup-list", "List redis secgroups", func(cli *qcloud.SRegion, args *RedisSecGroupListOptions) error {
secgroups, err := cli.GetCloudElasticcacheSecurityGroups(args.INSTANCEID)
if err != nil {
return err
}
printList(secgroups, 0, 0, 0, []string{})
return nil
})
type RedisAccountListOptions struct {
INSTANCEID string `json:"instanceid"`
}
shellutils.R(&RedisAccountListOptions{}, "redis-account-list", "List redis accounts", func(cli *qcloud.SRegion, args *RedisAccountListOptions) error {
accounts, err := cli.GetCloudElasticcacheAccounts(args.INSTANCEID)
if err != nil {
return err
}
printList(accounts, 0, 0, 0, []string{})
return nil
})
}
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
//"log"
"net/http"
+1 -1
View File
@@ -1068,7 +1068,7 @@ sigs.k8s.io/yaml
yunion.io/x/executor/apis
yunion.io/x/executor/client
yunion.io/x/executor/server
# yunion.io/x/jsonutils v0.0.0-20201014025429-7ce189228db6
# yunion.io/x/jsonutils v0.0.0-20201022101715-4e3add1ac4aa
yunion.io/x/jsonutils
# yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3
yunion.io/x/log
+2 -1
View File
@@ -28,6 +28,7 @@ import (
"strings"
"time"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/sortedmap"
@@ -293,7 +294,7 @@ func (this *JSONString) unmarshalValue(val reflect.Value) error {
if len(this.data) > 0 {
tm, err = timeutils.ParseTimeStr(this.data)
if err != nil {
return errors.Wrap(err, "timeutils.ParseTimeStr")
log.Warningf("timeutils.ParseTimeStr %s %s", this.data, err)
}
} else {
tm = time.Time{}