diff --git a/pkg/apis/compute/instance_snapshot.go b/pkg/apis/compute/instance_snapshot.go index 7456f8641a..022838fa93 100644 --- a/pkg/apis/compute/instance_snapshot.go +++ b/pkg/apis/compute/instance_snapshot.go @@ -27,6 +27,8 @@ type SimpleSnapshot struct { DiskType string `json:"disk_type"` // 区域Id CloudregionId string `json:"cloudregion_id"` + // 快照大小 + Size int `json:"size"` } type InstnaceSnapshotDetails struct { diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index a862793d3f..34c699a6a5 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -3479,20 +3479,37 @@ func (self *SGuest) PerformPostpaidExpire(ctx context.Context, userCred mcclient return nil, httperrors.NewBadRequestError("guest billing type is %s", self.BillingType) } - durationStr := jsonutils.GetAnyString(data, []string{"duration"}) - if len(durationStr) == 0 { - return nil, httperrors.NewInputParameterError("missong duration") - } - - bc, err := billing.ParseBillingCycle(durationStr) - if err != nil { - return nil, httperrors.NewInputParameterError("invalid duration %s: %s", durationStr, err) - } - if !self.GetDriver().IsSupportPostpaidExpire() { return nil, httperrors.NewBadRequestError("guest %s unsupport postpaid expire", self.Hypervisor) } + var ( + bc billing.SBillingCycle + err error + durationStr string + ) + durationStr, _ = data.GetString("duration") + if len(durationStr) == 0 { + expireTime, err := data.GetTime("expire_time") + if err != nil { + return nil, httperrors.NewInputParameterError("missing duration/expire_time") + } + timeC := self.ExpiredAt + if timeC.IsZero() { + timeC = time.Now() + } + dur := 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) + } + } + err = self.SaveRenewInfo(ctx, userCred, &bc, nil, billing_api.BILLING_TYPE_POSTPAID) return nil, err } @@ -3502,7 +3519,7 @@ func (self *SGuest) AllowPerformRenew(ctx context.Context, userCred mcclient.Tok } func (self *SGuest) PerformRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { - durationStr := jsonutils.GetAnyString(data, []string{"duration"}) + durationStr, _ := data.GetString("duration") if len(durationStr) == 0 { return nil, httperrors.NewInputParameterError("missong duration") } diff --git a/pkg/compute/models/instance_snapshots.go b/pkg/compute/models/instance_snapshots.go index 6d6cf60c53..edc9636c1a 100644 --- a/pkg/compute/models/instance_snapshots.go +++ b/pkg/compute/models/instance_snapshots.go @@ -124,6 +124,7 @@ func (self *SInstanceSnapshot) getMoreDetails(userCred mcclient.TokenCredential, StorageId: snapshots[i].StorageId, DiskType: snapshots[i].DiskType, CloudregionId: snapshots[i].CloudregionId, + Size: snapshots[i].Size, }) if len(snapshots[i].StorageId) > 0 { diff --git a/pkg/util/billing/billingcycle.go b/pkg/util/billing/billingcycle.go index e51841dfb3..3511a5470e 100644 --- a/pkg/util/billing/billingcycle.go +++ b/pkg/util/billing/billingcycle.go @@ -37,6 +37,7 @@ const ( var ( ErrInvalidBillingCycle = errors.New("invalid billing cycle") + ErrInvalidDuration = errors.New("invalid duration") ) type SBillingCycle struct { @@ -74,6 +75,14 @@ func ParseBillingCycle(cycleStr string) (SBillingCycle, error) { return cycle, nil } +// parse duration to minute unit billing cycle +func DurationToBillingCycle(dur time.Duration) SBillingCycle { + return SBillingCycle{ + Unit: BillingCycleMinute, + Count: int(dur.Minutes()), + } +} + func (cycle *SBillingCycle) String() string { return fmt.Sprintf("%d%s", cycle.Count, cycle.Unit) }