mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
qcloud redis support
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
Generated
Vendored
-1
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
//"log"
|
||||
"net/http"
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -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
@@ -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{}
|
||||
|
||||
Reference in New Issue
Block a user