fix(region): 修复本地到期释放功能和资源同步冲突 (#22860)

This commit is contained in:
屈轩
2025-07-10 19:37:58 +08:00
committed by GitHub
parent 992c5f498e
commit ebd7298d0d
32 changed files with 298 additions and 524 deletions
+4
View File
@@ -15,6 +15,8 @@
package compute
import (
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/apis"
@@ -648,6 +650,8 @@ type ServerCreateInput struct {
BillingType string `json:"billing_type"`
// swagger:ignore
BillingCycle string `json:"billing_cycle"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// swagger:ignore
// Deprecated
+2 -2
View File
@@ -82,8 +82,8 @@ type DBInstanceCreateInput struct {
// default: false
AutoRenew bool `json:"auto_renew"`
// swagger:ignore
ExpiredAt time.Time `json:"expired_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]
+3 -3
View File
@@ -246,13 +246,13 @@ type ElasticcacheCreateInput struct {
// 包年包月时间周期
Duration string `json:"duration"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 是否自动续费(仅包年包月时生效)
// default: false
AutoRenew bool `json:"auto_renew"`
// swagger:ignore
ExpiredAt time.Time `json:"expired_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]
BillingType string
+2 -2
View File
@@ -87,8 +87,8 @@ type FileSystemCreateInput struct {
// default: false
AutoRenew bool `json:"auto_renew"`
// 到期释放时间,仅后付费支持
ExpiredAt time.Time `json:"expired_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]
+2 -2
View File
@@ -117,8 +117,8 @@ type NatgatewayCreateInput struct {
// default: false
AutoRenew bool `json:"auto_renew"`
// 到期释放时间,仅后付费支持
ExpiredAt time.Time `json:"expired_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]
+26 -3
View File
@@ -14,7 +14,13 @@
package apis
import "time"
import (
"time"
"yunion.io/x/pkg/util/billing"
"yunion.io/x/onecloud/pkg/httperrors"
)
type DomainizedResourceInput struct {
// 指定项目归属域名称或ID
@@ -390,8 +396,25 @@ type DistinctFieldsInput struct {
}
type PostpaidExpireInput struct {
Duration string `json:"duration"`
ExpireTime time.Time `json:"expire_time"`
Duration string `json:"duration"`
// swagger:ignore
ExpireTime time.Time `json:"expire_time" yunion-deprecated-by:"release_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
}
func (input *PostpaidExpireInput) GetReleaseAt() (time.Time, error) {
if !input.ReleaseAt.IsZero() {
return input.ReleaseAt, nil
}
if len(input.Duration) == 0 {
return time.Time{}, httperrors.NewInputParameterError("missing duration/expire_time")
}
bc, err := billing.ParseBillingCycle(input.Duration)
if err != nil {
return time.Time{}, httperrors.NewInputParameterError("invalid duration: %s", input.Duration)
}
return bc.EndAt(time.Now()), nil
}
type AutoRenewInput struct {
+2
View File
@@ -51,6 +51,8 @@ const (
ACT_BACKUP_START = "backup_start"
ACT_BACKUP_START_FAILED = "backup_start_fail"
ACT_SET_RELEASE_TIME = "set_release_time"
ACT_FREEZE = "freeze"
ACT_FREEZE_FAIL = "freeze_fail"
ACT_UNFREEZE = "unfreeze"
+1 -6
View File
@@ -78,7 +78,7 @@ func (drv *SBaseGuestDriver) OnGuestCreateTaskComplete(ctx context.Context, gues
if len(duration) > 0 {
bc, err := billing.ParseBillingCycle(duration)
if err == nil && guest.ExpiredAt.IsZero() {
guest.SaveRenewInfo(ctx, task.GetUserCred(), &bc, nil, "")
models.SaveRenewInfo(ctx, task.GetUserCred(), guest, &bc, nil, "")
}
if jsonutils.QueryBoolean(task.GetParams(), "auto_prepaid_recycle", false) {
err := guest.CanPerformPrepaidRecycle()
@@ -395,11 +395,6 @@ func (drv *SBaseGuestDriver) RequestSyncSecgroupsOnHost(ctx context.Context, gue
return nil // do nothing
}
func (drv *SBaseGuestDriver) CancelExpireTime(
ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest) error {
return guest.CancelExpireTime(ctx, userCred)
}
func (drv *SBaseGuestDriver) IsSupportPublicipToEip() bool {
return false
}
+2 -1
View File
@@ -1040,6 +1040,7 @@ func (drv *SManagedVirtualizedGuestDriver) RequestChangeBillingType(ctx context.
guest.BillingType = ivm.GetBillingType()
guest.Status = ivm.GetStatus()
guest.ExpiredAt = time.Time{}
guest.AutoRenew = false
if guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
guest.AutoRenew = ivm.IsAutoRenew()
guest.ExpiredAt = ivm.GetExpiredAt()
@@ -1293,7 +1294,7 @@ func (drv *SManagedVirtualizedGuestDriver) OnGuestDeployTaskDataReceived(ctx con
exp, err := data.GetTime("expired_at")
if err == nil && !guest.IsPrepaidRecycle() {
guest.SaveRenewInfo(ctx, task.GetUserCred(), nil, &exp, "")
models.SaveRenewInfo(ctx, task.GetUserCred(), guest, nil, &exp, "")
}
driver, _ := guest.GetDriver()
+83 -36
View File
@@ -26,17 +26,16 @@ import (
"yunion.io/x/pkg/util/billing"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/billing"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
notifyapi "yunion.io/x/onecloud/pkg/apis/notify"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules/notify"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
@@ -44,8 +43,10 @@ type SBillingResourceBase struct {
// 计费类型, 按量、包年包月
// example: postpaid
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"optional" json:"billing_type"`
// 过期时间
ExpiredAt time.Time `nullable:"true" list:"user" create:"optional" json:"expired_at"`
// 包年包月到期时间
ExpiredAt time.Time `nullable:"true" list:"user" json:"expired_at"`
// 到期释放时间
ReleaseAt time.Time `nullable:"true" list:"user" create:"optional" json:"release_at"`
// 计费周期
BillingCycle string `width:"10" charset:"ascii" nullable:"true" list:"user" create:"optional" json:"billing_cycle"`
// 是否自动续费
@@ -62,10 +63,35 @@ func (self *SBillingResourceBase) GetChargeType() string {
}
}
func (self *SBillingResourceBase) SetReleaseAt(releaseAt time.Time) {
self.ReleaseAt = releaseAt
}
func (self *SBillingResourceBase) GetExpiredAt() time.Time {
return self.ExpiredAt
}
func (self *SBillingResourceBase) SetExpiredAt(expireAt time.Time) {
self.ExpiredAt = expireAt
}
func (self *SBillingResourceBase) SetBillingCycle(billingCycle string) {
self.BillingCycle = billingCycle
}
func (self *SBillingResourceBase) SetBillingType(billingType string) {
self.BillingType = billingType
}
func (self *SBillingResourceBase) GetBillingType() string {
return self.BillingType
}
func (self *SBillingResourceBase) getBillingBaseInfo() SBillingBaseInfo {
info := SBillingBaseInfo{}
info.ChargeType = self.GetChargeType()
info.ExpiredAt = self.ExpiredAt
info.ReleaseAt = self.ReleaseAt
if self.GetChargeType() == api.BILLING_TYPE_PREPAID {
info.BillingCycle = self.BillingCycle
}
@@ -93,7 +119,7 @@ func (self *SBillingResourceBase) IsValidPrePaid() bool {
func (self *SBillingResourceBase) IsValidPostPaid() bool {
if self.BillingType == api.BILLING_TYPE_POSTPAID {
now := time.Now().UTC()
if self.ExpiredAt.After(now) {
if self.ReleaseAt.After(now) {
return true
}
}
@@ -103,6 +129,7 @@ func (self *SBillingResourceBase) IsValidPostPaid() bool {
type SBillingBaseInfo struct {
ChargeType string `json:",omitempty"`
ExpiredAt time.Time `json:",omitempty"`
ReleaseAt time.Time `json:",omitempty"`
BillingCycle string `json:",omitempty"`
}
@@ -170,43 +197,14 @@ func (manager *SBillingResourceBaseManager) OrderByExtraFields(
func ListExpiredPostpaidResources(
q *sqlchemy.SQuery, limit int) *sqlchemy.SQuery {
q = q.Equals("billing_type", api.BILLING_TYPE_POSTPAID)
q = q.IsNotNull("expired_at")
q = q.LT("expired_at", time.Now())
q = q.IsNotNull("release_at")
q = q.LT("release_at", time.Now())
if limit > 0 {
q = q.Limit(limit)
}
return q
}
func ParseBillingCycleInput(billingBase *SBillingResourceBase, input apis.PostpaidExpireInput) (*billing.SBillingCycle, error) {
var (
bc billing.SBillingCycle
err error
durationStr string
)
if len(input.Duration) == 0 {
if input.ExpireTime.IsZero() {
return nil, httperrors.NewInputParameterError("missing duration/expire_time")
}
timeC := billingBase.ExpiredAt
if timeC.IsZero() {
timeC = time.Now()
}
dur := input.ExpireTime.Sub(timeC)
if dur <= 0 {
return nil, httperrors.NewInputParameterError("expire time is before current expire at")
}
bc = billing.DurationToBillingCycle(dur)
} else {
bc, err = billing.ParseBillingCycle(durationStr)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid duration %s: %s", durationStr, err)
}
}
return &bc, nil
}
type SBillingResourceCheckManager struct {
db.SResourceBaseManager
}
@@ -242,6 +240,55 @@ type IBillingModelManager interface {
type IBillingModel interface {
db.IModel
GetExpiredAt() time.Time
SetReleaseAt(releaseAt time.Time)
SetExpiredAt(expireAt time.Time)
SetBillingCycle(billingCycle string)
SetBillingType(billingType string)
GetBillingType() string
}
func SaveReleaseAt(ctx context.Context, model IBillingModel, userCred mcclient.TokenCredential, releaseAt time.Time) error {
diff, err := db.Update(model, func() error {
model.SetReleaseAt(releaseAt)
return nil
})
if err != nil {
return errors.Wrap(err, "Update")
}
if len(diff) > 0 {
db.OpsLog.LogEvent(model, db.ACT_SET_RELEASE_TIME, fmt.Sprintf("release at: %s", releaseAt), userCred)
}
if len(diff) > 0 && userCred != nil {
logclient.AddActionLogWithContext(ctx, model, logclient.ACT_SET_RELEASE_TIME, diff, userCred, true)
}
return nil
}
func SaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
model IBillingModel, bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
) error {
_, err := db.Update(model, func() error {
if billingType == "" {
billingType = billing_api.BILLING_TYPE_PREPAID
}
if model.GetBillingType() == "" {
model.SetBillingType(billingType)
}
if expireAt != nil && !expireAt.IsZero() {
model.SetExpiredAt(*expireAt)
} else if bc != nil {
model.SetBillingCycle(bc.String())
model.SetExpiredAt(bc.EndAt(model.GetExpiredAt()))
}
return nil
})
if err != nil {
log.Errorf("UpdateItem error %s", err)
return err
}
db.OpsLog.LogEvent(model, db.ACT_RENEW, model.GetShortDesc(ctx), userCred)
return nil
}
func fetchExpiredModels(manager db.IModelManager, advanceDay int) ([]IBillingModel, error) {
+23 -77
View File
@@ -405,9 +405,10 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred
}
}
tm := time.Time{}
input.BillingCycle = billingCycle.String()
input.ExpiredAt = billingCycle.EndAt(tm)
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
input.ReleaseAt = billingCycle.EndAt(time.Now())
}
}
for k, v := range map[string]string{
@@ -1133,33 +1134,6 @@ func (self *SDBInstance) StartDBInstanceRenewTask(ctx context.Context, userCred
return nil
}
func (self *SDBInstance) SaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
) error {
_, err := db.Update(self, func() error {
if billingType == "" {
billingType = billing_api.BILLING_TYPE_PREPAID
}
if self.BillingType == "" {
self.BillingType = billingType
}
if expireAt != nil && !expireAt.IsZero() {
self.ExpiredAt = *expireAt
} else {
self.BillingCycle = bc.String()
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
}
return nil
})
if err != nil {
log.Errorf("Update error %s", err)
return err
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
return nil
}
func (self *SDBInstance) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
desc := self.SVirtualResourceBase.GetShortDesc(ctx)
region, _ := self.GetRegion()
@@ -1722,10 +1696,6 @@ func (self *SDBInstance) SyncWithCloudDBInstance(ctx context.Context, userCred m
self.CreatedAt = createdAt
}
if expiredAt := ext.GetExpiredAt(); !expiredAt.IsZero() {
self.ExpiredAt = expiredAt
}
if len(self.VpcId) == 0 {
if vpcId := ext.GetIVpcId(); len(vpcId) > 0 {
vpc, err := db.FetchByExternalIdAndManagerId(VpcManager, vpcId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
@@ -1751,19 +1721,13 @@ func (self *SDBInstance) SyncWithCloudDBInstance(ctx context.Context, userCred m
}
}
factory, err := provider.GetProviderFactory()
if err != nil {
return errors.Wrap(err, "SyncWithCloudDBInstance.GetProviderFactory")
}
if factory.IsSupportPrepaidResources() && !ext.GetExpiredAt().IsZero() {
self.BillingType = ext.GetBillingType()
if expired := ext.GetExpiredAt(); !expired.IsZero() {
self.ExpiredAt = expired
}
self.BillingType = ext.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
self.AutoRenew = ext.IsAutoRenew()
self.ExpiredAt = ext.GetExpiredAt()
}
return nil
})
if err != nil {
@@ -1841,23 +1805,19 @@ func (manager *SDBInstanceManager) newFromCloudDBInstance(ctx context.Context, u
instance.CreatedAt = createdAt
}
factory, err := provider.GetProviderFactory()
if err != nil {
return nil, errors.Wrap(err, "newFromCloudDBInstance.GetProviderFactory")
}
if factory.IsSupportPrepaidResources() {
instance.BillingType = extInstance.GetBillingType()
if expired := extInstance.GetExpiredAt(); !expired.IsZero() {
instance.ExpiredAt = expired
}
instance.BillingType = extInstance.GetBillingType()
instance.AutoRenew = false
instance.ExpiredAt = time.Time{}
if instance.BillingType == billing_api.BILLING_TYPE_PREPAID {
instance.AutoRenew = extInstance.IsAutoRenew()
instance.ExpiredAt = extInstance.GetExpiredAt()
}
err = func() error {
err := func() error {
lockman.LockRawObject(ctx, manager.Keyword(), "name")
defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "name")
var err error
instance.Name, err = db.GenerateName(ctx, manager, ownerId, extInstance.GetName())
if err != nil {
return errors.Wrapf(err, "db.GenerateName")
@@ -2063,41 +2023,27 @@ func (self *SDBInstance) PerformPostpaidExpire(ctx context.Context, userCred mcc
return nil, httperrors.NewBadRequestError("dbinstance billing type is %s", self.BillingType)
}
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
releaseAt, err := input.GetReleaseAt()
if err != nil {
return nil, err
}
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
if err != nil {
return nil, err
}
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
return nil, err
}
func (self *SDBInstance) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if err := self.CancelExpireTime(ctx, userCred); err != nil {
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
if err != nil {
return nil, err
}
return nil, nil
}
func (self *SDBInstance) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
return httperrors.NewBadRequestError("dbinstance billing type %s not support cancel expire", self.BillingType)
}
_, err := sqlchemy.GetDB().Exec(
fmt.Sprintf(
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
DBInstanceManager.TableSpec().Name(),
), self.Id,
)
if err != nil {
return errors.Wrap(err, "dbinstance cancel expire time")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, "dbinstance cancel expire time", userCred)
return nil
}
func (self *SDBInstance) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DBInstanceRemoteUpdateInput) (jsonutils.JSONObject, error) {
err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "")
if err != nil {
+3 -47
View File
@@ -28,7 +28,6 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/billing"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/fileutils"
"yunion.io/x/pkg/util/pinyinutils"
@@ -1852,13 +1851,13 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
if provider.GetFactory().IsSupportPrepaidResources() && !recycle {
if billintType := extDisk.GetBillingType(); len(billintType) > 0 {
self.BillingType = extDisk.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
self.ExpiredAt = extDisk.GetExpiredAt()
self.AutoRenew = extDisk.IsAutoRenew()
}
}
if expiredAt := extDisk.GetExpiredAt(); !expiredAt.IsZero() {
self.ExpiredAt = extDisk.GetExpiredAt()
}
}
if createdAt := extDisk.GetCreatedAt(); !createdAt.IsZero() {
@@ -3021,49 +3020,6 @@ func (self *SDisk) DeleteSnapshots(ctx context.Context, userCred mcclient.TokenC
return nil
}
func (self *SDisk) SaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
) error {
_, err := db.Update(self, func() error {
if billingType == "" {
billingType = billing_api.BILLING_TYPE_PREPAID
}
if self.BillingType == "" {
self.BillingType = billingType
}
if expireAt != nil && !expireAt.IsZero() {
self.ExpiredAt = *expireAt
} else if bc != nil {
self.BillingCycle = bc.String()
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
}
return nil
})
if err != nil {
return errors.Wrapf(err, "SaveRenewInfo.Update")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
return nil
}
func (self *SDisk) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
return fmt.Errorf("billing type %s not support cancel expire", self.BillingType)
}
_, err := sqlchemy.GetDB().Exec(
fmt.Sprintf(
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
DiskManager.TableSpec().Name(),
), self.Id,
)
if err != nil {
return errors.Wrap(err, "disk cancel expire time")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, "disk cancel expire time", userCred)
return nil
}
func (self *SDisk) IsDetachable() bool {
storage, _ := self.GetStorage()
if storage == nil {
+6 -6
View File
@@ -440,10 +440,10 @@ func (self *SElasticSearch) SyncWithCloudElasticSearch(ctx context.Context, user
self.IsMultiAz = ext.IsMultiAz()
self.BillingType = ext.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
if expiredAt := ext.GetExpiredAt(); !expiredAt.IsZero() {
self.ExpiredAt = expiredAt
}
self.ExpiredAt = ext.GetExpiredAt()
self.AutoRenew = ext.IsAutoRenew()
}
@@ -586,10 +586,10 @@ func (self *SCloudregion) newFromCloudElasticSearch(ctx context.Context, userCre
}
es.BillingType = ext.GetBillingType()
es.ExpiredAt = time.Time{}
es.AutoRenew = false
if es.BillingType == billing_api.BILLING_TYPE_PREPAID {
if expired := ext.GetExpiredAt(); !expired.IsZero() {
es.ExpiredAt = expired
}
es.ExpiredAt = ext.GetExpiredAt()
es.AutoRenew = ext.IsAutoRenew()
}
+22 -87
View File
@@ -27,7 +27,6 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/billing"
bc "yunion.io/x/pkg/util/billing"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/netutils"
@@ -641,16 +640,11 @@ func (self *SElasticcache) SyncWithCloudElasticcache(ctx context.Context, userCr
self.Connections = cnns
}
factory, err := provider.GetProviderFactory()
if err != nil {
return errors.Wrap(err, "SyncWithCloudElasticcache.GetProviderFactory")
}
if factory.IsSupportPrepaidResources() {
self.BillingType = extInstance.GetBillingType()
if expired := extInstance.GetExpiredAt(); !expired.IsZero() {
self.ExpiredAt = expired
}
self.BillingType = extInstance.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
self.ExpiredAt = extInstance.GetExpiredAt()
self.AutoRenew = extInstance.IsAutoRenew()
}
@@ -760,23 +754,19 @@ func (self *SCloudregion) newFromCloudElasticcache(ctx context.Context, userCred
instance.CreatedAt = createdAt
}
factory, err := provider.GetProviderFactory()
if err != nil {
return nil, errors.Wrap(err, "newFromCloudElasticcache.GetProviderFactory")
}
if factory.IsSupportPrepaidResources() {
instance.BillingType = extInstance.GetBillingType()
if expired := extInstance.GetExpiredAt(); !expired.IsZero() {
instance.ExpiredAt = expired
}
instance.BillingType = extInstance.GetBillingType()
instance.ExpiredAt = time.Time{}
instance.AutoRenew = false
if instance.BillingType == billing_api.BILLING_TYPE_PREPAID {
instance.ExpiredAt = extInstance.GetExpiredAt()
instance.AutoRenew = extInstance.IsAutoRenew()
}
err = func() error {
err := func() error {
lockman.LockRawObject(ctx, ElasticcacheManager.Keyword(), "name")
defer lockman.ReleaseRawObject(ctx, ElasticcacheManager.Keyword(), "name")
var err error
instance.Name, err = db.GenerateName(ctx, ElasticcacheManager, ownerId, extInstance.GetName())
if err != nil {
return err
@@ -883,25 +873,15 @@ func (manager *SElasticcacheManager) validateCreateData(ctx context.Context, use
}
}
// postpiad billing cycle
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
if len(input.Duration) > 0 {
cycle, err := bc.ParseBillingCycle(input.Duration)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid duration %s", input.Duration)
}
tm := time.Time{}
input.BillingCycle = cycle.String()
// .Format("2006-01-02 15:04:05")
input.ExpiredAt = cycle.EndAt(tm)
}
} else if input.BillingType == billing_api.BILLING_TYPE_PREPAID {
cycle, err := billing.ParseBillingCycle(input.BillingCycle)
if len(input.Duration) > 0 {
cycle, err := bc.ParseBillingCycle(input.Duration)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid billing_cycle %s", input.BillingCycle)
return nil, httperrors.NewInputParameterError("invalid duration %s", input.Duration)
}
input.BillingCycle = cycle.String()
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
input.ReleaseAt = cycle.EndAt(time.Now())
}
}
// validate password
@@ -1569,33 +1549,6 @@ func (manager *SElasticcacheManager) getExpiredPostpaids() []SElasticcache {
return ecs
}
func (cache *SElasticcache) SaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
bcycle *bc.SBillingCycle, expireAt *time.Time, billingType string,
) error {
_, err := db.Update(cache, func() error {
if billingType == "" {
billingType = billing_api.BILLING_TYPE_PREPAID
}
if cache.BillingType == "" {
cache.BillingType = billingType
}
if expireAt != nil && !expireAt.IsZero() {
cache.ExpiredAt = *expireAt
} else if bcycle != nil {
cache.BillingCycle = bcycle.String()
cache.ExpiredAt = bcycle.EndAt(cache.ExpiredAt)
}
return nil
})
if err != nil {
log.Errorf("Update error %s", err)
return err
}
db.OpsLog.LogEvent(cache, db.ACT_RENEW, cache.GetShortDesc(ctx), userCred)
return nil
}
func (cache *SElasticcache) SetDisableDelete(userCred mcclient.TokenCredential, val bool) error {
diff, err := db.Update(cache, func() error {
if val {
@@ -1677,41 +1630,23 @@ func (self *SElasticcache) PerformPostpaidExpire(ctx context.Context, userCred m
return nil, httperrors.NewBadRequestError("elasticcache billing type is %s", self.BillingType)
}
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
releaseAt, err := input.GetReleaseAt()
if err != nil {
return nil, err
}
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
return nil, err
}
func (self *SElasticcache) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if err := self.CancelExpireTime(ctx, userCred); err != nil {
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
if err != nil {
return nil, err
}
return nil, nil
}
func (self *SElasticcache) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
return httperrors.NewBadRequestError("elasticcache billing type %s not support cancel expire", self.BillingType)
}
_, err := sqlchemy.GetDB().Exec(
fmt.Sprintf(
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
ElasticcacheManager.TableSpec().Name(),
), self.Id,
)
if err != nil {
return errors.Wrap(err, "elasticcache cancel expire time")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, "elasticcache cancel expire time", userCred)
return nil
}
func (self *SElasticcache) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticcacheRemoteUpdateInput) (jsonutils.JSONObject, error) {
err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "")
if err != nil {
+14 -6
View File
@@ -19,6 +19,7 @@ import (
"database/sql"
"fmt"
"sort"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
@@ -33,6 +34,7 @@ import (
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -599,12 +601,11 @@ func (self *SElasticip) SyncWithCloudEip(ctx context.Context, userCred mcclient.
self.ChargeType = chargeType
}
factory, _ := provider.GetProviderFactory()
if factory != nil && factory.IsSupportPrepaidResources() {
self.BillingType = ext.GetBillingType()
if expired := ext.GetExpiredAt(); !expired.IsZero() {
self.ExpiredAt = expired
}
self.BillingType = ext.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
self.ExpiredAt = ext.GetExpiredAt()
self.AutoRenew = ext.IsAutoRenew()
}
@@ -660,6 +661,13 @@ func (manager *SElasticipManager) newFromCloudEip(ctx context.Context, userCred
if !extEip.GetCreatedAt().IsZero() {
eip.CreatedAt = extEip.GetCreatedAt()
}
eip.BillingType = extEip.GetBillingType()
eip.ExpiredAt = time.Time{}
eip.AutoRenew = false
if eip.BillingType == billing_api.BILLING_TYPE_PREPAID {
eip.ExpiredAt = extEip.GetExpiredAt()
eip.AutoRenew = extEip.IsAutoRenew()
}
if len(eip.ChargeType) == 0 {
eip.ChargeType = api.EIP_CHARGE_TYPE_BY_TRAFFIC
}
+3 -2
View File
@@ -187,9 +187,10 @@ func (man *SFileSystemManager) ValidateCreateData(ctx context.Context, userCred
return input, httperrors.NewInputParameterError("unsupported duration %s", input.Duration)
}
}
tm := time.Time{}
input.BillingCycle = billingCycle.String()
input.ExpiredAt = billingCycle.EndAt(tm)
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
input.ReleaseAt = billingCycle.EndAt(time.Now())
}
}
input.SharableVirtualResourceCreateInput, err = man.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.SharableVirtualResourceCreateInput)
+14 -56
View File
@@ -3349,7 +3349,8 @@ func (self *SGuest) DoCancelPendingDelete(ctx context.Context, userCred mcclient
}
if self.BillingType == billing_api.BILLING_TYPE_POSTPAID && !self.ExpiredAt.IsZero() {
if err := self.CancelExpireTime(ctx, userCred); err != nil {
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
if err != nil {
return err
}
}
@@ -4482,20 +4483,22 @@ func (self *SGuest) PerformCancelExpire(ctx context.Context, userCred mcclient.T
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
return nil, httperrors.NewBadRequestError("guest billing type %s not support cancel expire", self.BillingType)
}
driver, err := self.GetDriver()
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
if err != nil {
return nil, err
}
if err := driver.CancelExpireTime(ctx, userCred, self); err != nil {
return nil, err
}
disks, err := self.GetDisks()
if err != nil {
return nil, err
}
for i := 0; i < len(disks); i += 1 {
if err := disks[i].CancelExpireTime(ctx, userCred); err != nil {
return nil, err
if disks[i].BillingType == billing_api.BILLING_TYPE_POSTPAID {
err := SaveReleaseAt(ctx, &disks[i], userCred, time.Time{})
if err != nil {
return nil, err
}
}
}
return nil, nil
@@ -4516,16 +4519,15 @@ func (self *SGuest) PerformPostpaidExpire(ctx context.Context, userCred mcclient
return nil, httperrors.NewBadRequestError("guest %s unsupport postpaid expire", self.Hypervisor)
}
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
releaseAt, err := input.GetReleaseAt()
if err != nil {
return nil, err
}
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
if err != nil {
return nil, err
}
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_SET_EXPIRED_TIME, input, userCred, true)
return nil, nil
}
@@ -4589,7 +4591,7 @@ func (self *SGuest) SaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
) error {
err := self.doSaveRenewInfo(ctx, userCred, bc, expireAt, billingType)
err := SaveRenewInfo(ctx, userCred, self, bc, expireAt, billingType)
if err != nil {
return err
}
@@ -4599,7 +4601,7 @@ func (self *SGuest) SaveRenewInfo(
}
for i := 0; i < len(disks); i += 1 {
if disks[i].AutoDelete {
err = disks[i].SaveRenewInfo(ctx, userCred, bc, expireAt, billingType)
err = SaveRenewInfo(ctx, userCred, &disks[i], bc, expireAt, billingType)
if err != nil {
return err
}
@@ -4608,50 +4610,6 @@ func (self *SGuest) SaveRenewInfo(
return nil
}
func (self *SGuest) doSaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
) error {
_, err := db.Update(self, func() error {
if billingType == "" {
billingType = billing_api.BILLING_TYPE_PREPAID
}
if self.BillingType == "" {
self.BillingType = billingType
}
if expireAt != nil && !expireAt.IsZero() {
self.ExpiredAt = *expireAt
} else if bc != nil {
self.BillingCycle = bc.String()
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
}
return nil
})
if err != nil {
log.Errorf("UpdateItem error %s", err)
return err
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
return nil
}
func (self *SGuest) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
return fmt.Errorf("billing type %s not support cancel expire", self.BillingType)
}
_, err := sqlchemy.GetDB().Exec(
fmt.Sprintf(
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
GuestManager.TableSpec().Name(),
), self.Id,
)
if err != nil {
return errors.Wrap(err, "guest cancel expire time")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, "guest cancel expire time", userCred)
return nil
}
func (self *SGuest) PerformStreamDisksComplete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
disks, err := self.GetDisks()
if err != nil {
-1
View File
@@ -202,7 +202,6 @@ type IGuestDriver interface {
GetUserDataType() string
GetWindowsUserDataType() string
IsWindowsUserDataTypeNeedEncode() bool
CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error
IsSupportCdrom(guest *SGuest) (bool, error)
IsSupportFloppy(guest *SGuest) (bool, error)
+15 -35
View File
@@ -1983,10 +1983,6 @@ func (manager *SGuestManager) validateCreateData(
}
if len(input.Duration) > 0 {
/*if !userCred.IsAllow(rbacutils.ScopeSystem, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionPerform, "renew") {
return nil, httperrors.NewForbiddenError("only admin can create prepaid resource")
}*/
if input.ResourceType == api.HostResourceTypePrepaidRecycle {
return nil, httperrors.NewConflictError("cannot create prepaid server on prepaid resource type")
}
@@ -2010,10 +2006,10 @@ func (manager *SGuestManager) validateCreateData(
input.BillingType = billing_api.BILLING_TYPE_PREPAID
}
input.BillingCycle = billingCycle.String()
// expired_at will be set later by callback
// data.Add(jsonutils.NewTimeString(billingCycle.EndAt(time.Time{})), "expired_at")
input.Duration = billingCycle.String()
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
input.ReleaseAt = billingCycle.EndAt(time.Now())
}
}
}
@@ -3263,16 +3259,15 @@ func (g *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.TokenCre
if len(extVM.GetDescription()) > 0 {
g.Description = extVM.GetDescription()
}
g.IsEmulated = extVM.IsEmulated()
if provider.GetFactory().IsSupportPrepaidResources() && !recycle {
g.BillingType = extVM.GetBillingType()
g.BillingType = extVM.GetBillingType()
g.ExpiredAt = time.Time{}
g.AutoRenew = false
if g.BillingType == billing_api.BILLING_TYPE_PREPAID {
g.ExpiredAt = extVM.GetExpiredAt()
drv, _ := g.GetDriver()
if drv != nil && drv.IsSupportSetAutoRenew() {
g.AutoRenew = extVM.IsAutoRenew()
}
g.AutoRenew = extVM.IsAutoRenew()
}
return nil
})
if err != nil {
@@ -3339,15 +3334,12 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
guest.IsEmulated = extVM.IsEmulated()
if provider.GetFactory().IsSupportPrepaidResources() {
guest.BillingType = extVM.GetBillingType()
if expired := extVM.GetExpiredAt(); !expired.IsZero() {
guest.ExpiredAt = expired
}
drv, _ := guest.GetDriver()
if drv != nil && drv.IsSupportSetAutoRenew() {
guest.AutoRenew = extVM.IsAutoRenew()
}
guest.BillingType = extVM.GetBillingType()
guest.ExpiredAt = time.Time{}
guest.AutoRenew = false
if guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
guest.ExpiredAt = extVM.GetExpiredAt()
guest.AutoRenew = extVM.IsAutoRenew()
}
if createdAt := extVM.GetCreatedAt(); !createdAt.IsZero() {
@@ -3358,18 +3350,6 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
instanceType := extVM.GetInstanceType()
/*zoneExtId, err := metaData.GetString("zone_ext_id")
if err != nil {
log.Errorf("get zone external id fail %s", err)
}
isku, err := ServerSkuManager.FetchByZoneExtId(zoneExtId, instanceType)
if err != nil {
log.Errorf("get sku zone %s instance type %s fail %s", zoneExtId, instanceType, err)
} else {
guest.SkuId = isku.GetId()
}*/
if len(instanceType) > 0 {
guest.InstanceType = instanceType
}
+6 -6
View File
@@ -437,10 +437,10 @@ func (self *SKafka) SyncWithCloudKafka(ctx context.Context, userCred mcclient.To
self.IsMultiAz = ext.IsMultiAz()
self.BillingType = ext.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
if expiredAt := ext.GetExpiredAt(); !expiredAt.IsZero() {
self.ExpiredAt = expiredAt
}
self.ExpiredAt = ext.GetExpiredAt()
self.AutoRenew = ext.IsAutoRenew()
}
@@ -538,10 +538,10 @@ func (self *SCloudregion) newFromCloudKafka(ctx context.Context, userCred mcclie
}
kafka.BillingType = ext.GetBillingType()
kafka.ExpiredAt = time.Time{}
kafka.AutoRenew = false
if kafka.BillingType == billing_api.BILLING_TYPE_PREPAID {
if expired := ext.GetExpiredAt(); !expired.IsZero() {
kafka.ExpiredAt = expired
}
kafka.ExpiredAt = ext.GetExpiredAt()
kafka.AutoRenew = ext.IsAutoRenew()
}
+3 -3
View File
@@ -491,10 +491,10 @@ func (self *SCloudregion) newFromCloudModelartsPool(ctx context.Context, userCre
pool.CpuArch = sku.CpuArch
pool.BillingType = ext.GetBillingType()
pool.ExpiredAt = time.Time{}
pool.AutoRenew = false
if pool.BillingType == billing_api.BILLING_TYPE_PREPAID {
if expired := ext.GetExpiredAt(); !expired.IsZero() {
pool.ExpiredAt = expired
}
pool.ExpiredAt = ext.GetExpiredAt()
pool.AutoRenew = ext.IsAutoRenew()
}
+15 -53
View File
@@ -23,7 +23,6 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/billing"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/rbacscope"
"yunion.io/x/sqlchemy"
@@ -340,32 +339,6 @@ func (self *SMongoDB) SetAutoRenew(autoRenew bool) error {
return err
}
func (self *SMongoDB) SaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
) error {
_, err := db.Update(self, func() error {
if billingType == "" {
billingType = billing_api.BILLING_TYPE_PREPAID
}
if self.BillingType == "" {
self.BillingType = billingType
}
if expireAt != nil && !expireAt.IsZero() {
self.ExpiredAt = *expireAt
} else {
self.BillingCycle = bc.String()
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
}
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
return nil
}
func (self *SMongoDB) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
log.Infof("mongodb delete do nothing")
return nil
@@ -526,6 +499,14 @@ func (self *SMongoDB) SyncWithCloudMongoDB(ctx context.Context, userCred mcclien
self.MaxConnections = ext.GetMaxConnections()
self.NetworkAddress = ext.GetNetworkAddress()
self.BillingType = ext.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
self.ExpiredAt = ext.GetExpiredAt()
self.AutoRenew = ext.IsAutoRenew()
}
if vpcId := ext.GetVpcId(); len(vpcId) > 0 {
vpc, err := db.FetchByExternalIdAndManagerId(VpcManager, vpcId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
return q.Equals("manager_id", self.ManagerId)
@@ -616,11 +597,10 @@ func (self *SCloudregion) newFromCloudMongoDB(ctx context.Context, userCred mccl
}
ins.BillingType = ext.GetBillingType()
ins.ExpiredAt = time.Time{}
ins.AutoRenew = false
if ins.BillingType == billing_api.BILLING_TYPE_PREPAID {
expiredAt := ext.GetExpiredAt()
if !expiredAt.IsZero() {
ins.ExpiredAt = expiredAt
}
ins.ExpiredAt = ext.GetExpiredAt()
ins.AutoRenew = ext.IsAutoRenew()
}
@@ -782,41 +762,23 @@ func (self *SMongoDB) PerformPostpaidExpire(ctx context.Context, userCred mcclie
return nil, httperrors.NewBadRequestError("self billing type is %s", self.BillingType)
}
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
releaseAt, err := input.GetReleaseAt()
if err != nil {
return nil, err
}
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
return nil, err
}
func (self *SMongoDB) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if err := self.CancelExpireTime(ctx, userCred); err != nil {
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
if err != nil {
return nil, err
}
return nil, nil
}
func (self *SMongoDB) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
return httperrors.NewBadRequestError("self billing type %s not support cancel expire", self.BillingType)
}
_, err := sqlchemy.GetDB().Exec(
fmt.Sprintf(
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
MongoDBManager.TableSpec().Name(),
), self.Id,
)
if err != nil {
return errors.Wrap(err, "self cancel expire time")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, "self cancel expire time", userCred)
return nil
}
func (self *SMongoDB) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.MongoDBRemoteUpdateInput) (jsonutils.JSONObject, error) {
err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "")
if err != nil {
+17 -61
View File
@@ -186,9 +186,10 @@ func (man *SNatGatewayManager) ValidateCreateData(
return input, httperrors.NewInputParameterError("unsupported duration %s", input.Duration)
}
}
tm := time.Time{}
input.BillingCycle = billingCycle.String()
input.ExpiredAt = billingCycle.EndAt(tm)
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
input.ReleaseAt = billingCycle.EndAt(time.Now())
}
}
if len(input.Eip) > 0 || input.EipBw > 0 {
if len(input.Eip) > 0 {
@@ -521,12 +522,11 @@ func (self *SNatGateway) SyncWithCloudNatGateway(ctx context.Context, userCred m
}
}
factory, _ := provider.GetProviderFactory()
if factory.IsSupportPrepaidResources() {
self.BillingType = extNat.GetBillingType()
if expired := extNat.GetExpiredAt(); !expired.IsZero() {
self.ExpiredAt = expired
}
self.BillingType = extNat.GetBillingType()
self.ExpiredAt = time.Time{}
self.AutoRenew = false
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
self.ExpiredAt = extNat.GetExpiredAt()
self.AutoRenew = extNat.IsAutoRenew()
}
@@ -566,14 +566,14 @@ func (manager *SNatGatewayManager) newFromCloudNatGateway(ctx context.Context, u
nat.ExternalId = extNat.GetGlobalId()
nat.IsEmulated = extNat.IsEmulated()
factory, _ := provider.GetProviderFactory()
if factory.IsSupportPrepaidResources() {
nat.BillingType = extNat.GetBillingType()
if expired := extNat.GetExpiredAt(); !expired.IsZero() {
nat.ExpiredAt = expired
}
nat.BillingType = extNat.GetBillingType()
nat.ExpiredAt = time.Time{}
nat.AutoRenew = false
if nat.BillingType == billing_api.BILLING_TYPE_PREPAID {
nat.ExpiredAt = extNat.GetExpiredAt()
nat.AutoRenew = extNat.IsAutoRenew()
}
if networId := extNat.GetINetworkId(); len(networId) > 0 {
_network, err := db.FetchByExternalIdAndManagerId(NetworkManager, networId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
sq := WireManager.Query("id").Equals("vpc_id", vpc.Id).SubQuery()
@@ -892,25 +892,7 @@ func (manager *SNatEntryManager) FetchCustomizeColumns(
}
func (self *SNatGateway) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return nil, self.CancelExpireTime(ctx, userCred)
}
func (self *SNatGateway) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
return httperrors.NewBadRequestError("nat billing type %s not support cancel expire", self.BillingType)
}
_, err := sqlchemy.GetDB().Exec(
fmt.Sprintf(
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
NatGatewayManager.TableSpec().Name(),
), self.Id,
)
if err != nil {
return errors.Wrap(err, "nat cancel expire time")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, "nat cancel expire time", userCred)
return nil
return nil, SaveReleaseAt(ctx, self, userCred, time.Time{})
}
func (self *SNatGateway) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PostpaidExpireInput) (jsonutils.JSONObject, error) {
@@ -918,41 +900,15 @@ func (self *SNatGateway) PerformPostpaidExpire(ctx context.Context, userCred mcc
return nil, httperrors.NewBadRequestError("nat gateway billing type is %s", self.BillingType)
}
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
releaseAt, err := input.GetReleaseAt()
if err != nil {
return nil, err
}
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
return nil, err
}
func (self *SNatGateway) SaveRenewInfo(
ctx context.Context, userCred mcclient.TokenCredential,
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
) error {
_, err := db.Update(self, func() error {
if billingType == "" {
billingType = billing_api.BILLING_TYPE_PREPAID
}
if self.BillingType == "" {
self.BillingType = billingType
}
if expireAt != nil && !expireAt.IsZero() {
self.ExpiredAt = *expireAt
} else {
self.BillingCycle = bc.String()
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
}
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update")
}
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
return nil
}
func (self *SNatGateway) PerformRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.RenewInput) (jsonutils.JSONObject, error) {
if !utils.IsInStringArray(self.Status, []string{api.NAT_STAUTS_AVAILABLE}) {
return nil, httperrors.NewInvalidStatusError("Cannot do renew nat gateway in status %s required status %s", self.Status, api.NAT_SKU_AVAILABLE)
+1 -2
View File
@@ -16,7 +16,6 @@ package models
import (
"context"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
@@ -237,7 +236,7 @@ type IElasticcacheDriver interface {
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
RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, bc billing.SBillingCycle) (time.Time, error)
RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, bc billing.SBillingCycle) error
RequestElasticcacheSetAutoRenew(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, autoRenew bool, 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
+2 -3
View File
@@ -17,7 +17,6 @@ package regiondrivers
import (
"context"
"fmt"
"time"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
@@ -358,8 +357,8 @@ func (self *SBaseRegionDriver) GetRdsSupportSecgroupCount() int {
return 0
}
func (self *SBaseRegionDriver) RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SElasticcache, bc billing.SBillingCycle) (time.Time, error) {
return time.Time{}, fmt.Errorf("Not Implement RequestRenewElasticcache")
func (self *SBaseRegionDriver) RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SElasticcache, bc billing.SBillingCycle) error {
return errors.Wrapf(cloudprovider.ErrNotImplemented, "RequestRenewElasticcache")
}
func (self *SBaseRegionDriver) IsSupportedElasticcacheAutoRenew() bool {
+10 -6
View File
@@ -2843,25 +2843,25 @@ func (self *SManagedVirtualizationRegionDriver) RequestSyncSecgroupsForElasticca
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, bc billing.SBillingCycle) (time.Time, error) {
func (self *SManagedVirtualizationRegionDriver) RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, bc billing.SBillingCycle) error {
iregion, err := ec.GetIRegion(ctx)
if err != nil {
return time.Time{}, errors.Wrap(err, "GetIRegion")
return errors.Wrap(err, "GetIRegion")
}
if len(ec.GetExternalId()) == 0 {
return time.Time{}, errors.Wrap(err, "ExternalId is empty")
return errors.Wrap(err, "ExternalId is empty")
}
iec, err := iregion.GetIElasticcacheById(ec.GetExternalId())
if err != nil {
return time.Time{}, errors.Wrap(err, "GetIElasticcacheById")
return errors.Wrap(err, "GetIElasticcacheById")
}
oldExpired := iec.GetExpiredAt()
err = iec.Renew(bc)
if err != nil {
return time.Time{}, err
return err
}
//避免有些云续费后过期时间刷新比较慢问题
cloudprovider.WaitCreated(15*time.Second, 5*time.Minute, func() bool {
@@ -2875,7 +2875,11 @@ func (self *SManagedVirtualizationRegionDriver) RequestRenewElasticcache(ctx con
}
return false
})
return iec.GetExpiredAt(), nil
db.Update(ec, func() error {
ec.ExpiredAt = iec.GetExpiredAt()
return nil
})
return nil
}
func (self *SManagedVirtualizationRegionDriver) IsSupportedElasticcacheAutoRenew() bool {
@@ -72,6 +72,7 @@ func (self *DiskChangeBillingTypeTask) OnInit(ctx context.Context, obj db.IStand
db.Update(disk, func() error {
disk.BillingType = billType
disk.ExpiredAt = time.Time{}
disk.AutoRenew = false
if disk.BillingType == billing_api.BILLING_TYPE_PREPAID {
disk.AutoRenew = idisk.IsAutoRenew()
disk.ExpiredAt = idisk.GetExpiredAt()
@@ -16,10 +16,8 @@ package elasticcache
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
@@ -37,27 +35,27 @@ func init() {
taskman.RegisterTask(ElasticcacheRenewTask{})
}
func (self *ElasticcacheRenewTask) taskFail(ctx context.Context, cache *models.SElasticcache, err error) {
db.OpsLog.LogEvent(cache, db.ACT_REW_FAIL, err, self.UserCred)
logclient.AddActionLogWithStartable(self, cache, logclient.ACT_RENEW, err, self.UserCred, false)
cache.SetStatus(ctx, self.GetUserCred(), api.ELASTIC_CACHE_RENEW_FAILED, err.Error())
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
}
func (self *ElasticcacheRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
instance := obj.(*models.SElasticcache)
durationStr, _ := self.GetParams().GetString("duration")
bc, _ := billing.ParseBillingCycle(durationStr)
region, _ := instance.GetRegion()
exp, err := region.GetDriver().RequestRenewElasticcache(ctx, self.UserCred, instance, bc)
region, err := instance.GetRegion()
if err != nil {
db.OpsLog.LogEvent(instance, db.ACT_REW_FAIL, err, self.UserCred)
logclient.AddActionLogWithStartable(self, instance, logclient.ACT_RENEW, err, self.UserCred, false)
instance.SetStatus(ctx, self.GetUserCred(), api.ELASTIC_CACHE_RENEW_FAILED, err.Error())
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
self.taskFail(ctx, instance, err)
return
}
err = instance.SaveRenewInfo(ctx, self.UserCred, &bc, &exp, "")
err = region.GetDriver().RequestRenewElasticcache(ctx, self.UserCred, instance, bc)
if err != nil {
msg := fmt.Sprintf("SaveRenewInfo fail %s", err)
log.Errorf(msg)
self.SetStageFailed(ctx, jsonutils.NewString(msg))
self.taskFail(ctx, instance, err)
return
}
+1 -1
View File
@@ -266,7 +266,7 @@ func (self *GuestCreateTask) OnDeployEipComplete(ctx context.Context, obj db.ISt
if len(duration) > 0 {
bc, err := billing.ParseBillingCycle(duration)
if err == nil && guest.ExpiredAt.IsZero() {
guest.SaveRenewInfo(ctx, self.GetUserCred(), &bc, nil, "")
models.SaveRenewInfo(ctx, self.GetUserCred(), guest, &bc, nil, "")
}
if jsonutils.QueryBoolean(self.GetParams(), "auto_prepaid_recycle", false) {
err := guest.CanPerformPrepaidRecycle()
+1 -1
View File
@@ -65,7 +65,7 @@ func (self *GuestRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
return
}
err = guest.SaveRenewInfo(ctx, self.UserCred, &bc, &exp, "")
err = models.SaveRenewInfo(ctx, self.UserCred, guest, &bc, &exp, "")
if err != nil {
msg := fmt.Sprintf("SaveRenewInfo fail %s", err)
log.Errorf(msg)
+1 -1
View File
@@ -113,7 +113,7 @@ const (
ACT_UNFREEZE = "unfreeze"
ACT_CHANGE_BILLING_TYPE = "change_billing_type"
// 到期释放
ACT_SET_EXPIRED_TIME = "set_expired_time"
ACT_SET_RELEASE_TIME = "set_release_time"
ACT_VM_SYNC_ISOLATED_DEVICE = "vm_sync_isolated_device"
ACT_CACHED_IMAGE = "cached_image"
+2 -2
View File
@@ -104,8 +104,8 @@ func init() {
EN("Guest Detach Isolated Device").
CN("卸载透传设备"),
)
t.Set(ACT_SET_EXPIRED_TIME, i18n.NewTableEntry().
EN("Set Resource Expire Time").
t.Set(ACT_SET_RELEASE_TIME, i18n.NewTableEntry().
EN("Set Resource Release Time").
CN("到期释放"),
)
t.Set(ACT_VM_SYNC_ISOLATED_DEVICE, i18n.NewTableEntry().