mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
fix(region): support change vm billing type (#22092)
This commit is contained in:
@@ -51,6 +51,7 @@ func init() {
|
||||
cmd.BatchPut(new(options.ServerUpdateOptions))
|
||||
cmd.GetMetadata(new(options.ServerIdOptions))
|
||||
cmd.Perform("clone", new(options.ServerCloneOptions))
|
||||
cmd.Perform("change-billing-type", new(options.ServerChangeBillingTypeOptions))
|
||||
cmd.BatchPerform("start", new(options.ServerStartOptions))
|
||||
cmd.BatchPerform("syncstatus", new(options.ServerIdsOptions))
|
||||
cmd.BatchPerform("sync", new(options.ServerIdsOptions))
|
||||
|
||||
2
go.mod
2
go.mod
@@ -93,7 +93,7 @@ require (
|
||||
k8s.io/cri-api v0.22.17
|
||||
k8s.io/klog/v2 v2.20.0
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250212024104-a8836a46c50a
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250214014132-42e126bc0593
|
||||
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256
|
||||
yunion.io/x/jsonutils v1.0.1-0.20240930100528-1671a2d0d22f
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1376,8 +1376,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250212024104-a8836a46c50a h1:TpQ8OnCqN2TlkdlZ8DKNaQVJPFBdfkuyHX6qUGN/Wgg=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250212024104-a8836a46c50a/go.mod h1:KQ/jWx7bZlmjCE711KEWuvHW/dzpdr/UTlBjjutkj0Y=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250214014132-42e126bc0593 h1:SFEvPEeQcxxPNxQrv0VnXtPYDZCWyckAqwiHGMXJsck=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250214014132-42e126bc0593/go.mod h1:KQ/jWx7bZlmjCE711KEWuvHW/dzpdr/UTlBjjutkj0Y=
|
||||
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256 h1:kLKQ6zbgPDQflRwoHFAjxNChcbhXIFgsUVLkJwiXu/8=
|
||||
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
|
||||
@@ -180,6 +180,10 @@ const (
|
||||
VM_QGA_SET_NETWORK = "qga_set_network"
|
||||
VM_QGA_SET_NETWORK_FAILED = "qga_set_network_failed"
|
||||
|
||||
// 更改计费模式
|
||||
VM_CHANGE_BILLING_TYPE = "change_billing_type"
|
||||
VM_CHANGE_BILLING_TYPE_FAILED = "change_billing_type_failed"
|
||||
|
||||
SHUTDOWN_STOP = "stop"
|
||||
SHUTDOWN_TERMINATE = "terminate"
|
||||
SHUTDOWN_STOP_RELEASE_GPU = "stop_release_gpu"
|
||||
|
||||
@@ -635,6 +635,7 @@ type ServerStopInput struct {
|
||||
TimeoutSecs int `json:"timeout_secs"`
|
||||
|
||||
// 是否关机停止计费, 若平台不支持停止计费,此参数无作用
|
||||
// 若包年包月机器关机设置此参数,则先转换计费模式到按量计费,再关机不收费
|
||||
// 目前仅阿里云,腾讯云此参数生效
|
||||
StopCharging bool `json:"stop_charging"`
|
||||
}
|
||||
@@ -1273,6 +1274,8 @@ type GuestPerformStartInput struct {
|
||||
// 指定启动虚拟机的Qemu版本,可选值:2.12.1, 4.2.0
|
||||
// 仅适用于KVM虚拟机
|
||||
QemuVersion string `json:"qemu_version"`
|
||||
// 按量机器自动转换为包年包月
|
||||
AutoPrepaid bool `json:"auto_prepaid"`
|
||||
}
|
||||
|
||||
type ServerSetOSInfoInput struct {
|
||||
@@ -1396,3 +1399,10 @@ type ServerReleasedIsolatedDevice struct {
|
||||
DevType string `json:"dev_type"`
|
||||
Model string `json:"model"`
|
||||
}
|
||||
|
||||
type ServerChangeBillingTypeInput struct {
|
||||
// 仅在虚拟机开机或关机状态下调用
|
||||
// enmu: [postpaid, prepaid]
|
||||
// required: true
|
||||
BillingType string `json:"billing_type"`
|
||||
}
|
||||
|
||||
@@ -125,6 +125,10 @@ func (drv *SBaseGuestDriver) RequestDetachDisk(ctx context.Context, guest *model
|
||||
return nil
|
||||
}
|
||||
|
||||
func (drv *SBaseGuestDriver) RequestChangeBillingType(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return errors.Wrapf(cloudprovider.ErrNotImplemented, "RequestChangeBillingType")
|
||||
}
|
||||
|
||||
func (drv *SBaseGuestDriver) RequestAttachDisk(ctx context.Context, guest *models.SGuest, disk *models.SDisk, task taskman.ITask) error {
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
|
||||
@@ -480,6 +480,14 @@ func (drv *SManagedVirtualizedGuestDriver) RequestStartOnHost(ctx context.Contex
|
||||
|
||||
result := jsonutils.NewDict()
|
||||
if ivm.GetStatus() != api.VM_RUNNING {
|
||||
|
||||
if guest.BillingType == billing_api.BILLING_TYPE_POSTPAID && jsonutils.QueryBoolean(task.GetParams(), "auto_prepaid", false) {
|
||||
err = ivm.ChangeBillingType(billing_api.BILLING_TYPE_PREPAID)
|
||||
if err != nil && errors.Cause(err) != cloudprovider.ErrNotImplemented {
|
||||
logclient.AddSimpleActionLog(guest, logclient.ACT_VM_CHANGE_BILLING_TYPE, errors.Wrapf(err, billing_api.BILLING_TYPE_PREPAID), userCred, false)
|
||||
}
|
||||
}
|
||||
|
||||
err := ivm.StartVM(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "StartVM")
|
||||
@@ -972,6 +980,15 @@ func (drv *SManagedVirtualizedGuestDriver) RequestStopOnHost(ctx context.Context
|
||||
if ivm.GetStatus() != api.VM_READY {
|
||||
opts := &cloudprovider.ServerStopOptions{}
|
||||
task.GetParams().Unmarshal(opts)
|
||||
|
||||
// 包年包月实例关机不收费,先转按量付费再关机
|
||||
if opts.StopCharging && guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
err = ivm.ChangeBillingType(billing_api.BILLING_TYPE_POSTPAID)
|
||||
if err != nil && errors.Cause(err) != cloudprovider.ErrNotImplemented {
|
||||
logclient.AddSimpleActionLog(guest, logclient.ACT_VM_CHANGE_BILLING_TYPE, errors.Wrapf(err, billing_api.BILLING_TYPE_POSTPAID), task.GetUserCred(), false)
|
||||
}
|
||||
}
|
||||
|
||||
err = ivm.StopVM(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ivm.StopVM")
|
||||
@@ -988,6 +1005,51 @@ func (drv *SManagedVirtualizedGuestDriver) RequestStopOnHost(ctx context.Context
|
||||
return nil
|
||||
}
|
||||
|
||||
func (drv *SManagedVirtualizedGuestDriver) RequestChangeBillingType(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
ivm, err := guest.GetIVM(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "guest.GetIVM")
|
||||
}
|
||||
billType := ""
|
||||
switch guest.BillingType {
|
||||
case billing_api.BILLING_TYPE_POSTPAID:
|
||||
billType = billing_api.BILLING_TYPE_PREPAID
|
||||
case billing_api.BILLING_TYPE_PREPAID:
|
||||
billType = billing_api.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
err = ivm.ChangeBillingType(billType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ChangeBillingType")
|
||||
}
|
||||
err = cloudprovider.Wait(time.Second*5, time.Minute*3, func() (bool, error) {
|
||||
err = ivm.Refresh()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if ivm.GetBillingType() != billType {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Wait vm billing type changed")
|
||||
}
|
||||
_, err = db.Update(guest, func() error {
|
||||
guest.BillingType = ivm.GetBillingType()
|
||||
guest.Status = ivm.GetStatus()
|
||||
guest.ExpiredAt = time.Time{}
|
||||
if guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
guest.AutoRenew = ivm.IsAutoRenew()
|
||||
guest.ExpiredAt = ivm.GetExpiredAt()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return nil, err
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (drv *SManagedVirtualizedGuestDriver) RequestSyncstatusOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, userCred mcclient.TokenCredential, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
ihost, err := host.GetIHost(ctx)
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
|
||||
"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"
|
||||
@@ -247,7 +248,21 @@ func fetchExpiredModels(manager db.IModelManager, advanceDay int) ([]IBillingMod
|
||||
upLimit := time.Now().AddDate(0, 0, advanceDay+1)
|
||||
downLimit := time.Now().AddDate(0, 0, advanceDay)
|
||||
v := reflect.MakeSlice(reflect.SliceOf(manager.TableSpec().DataType()), 0, 0)
|
||||
q := manager.Query().LE("expired_at", upLimit).GE("expired_at", downLimit)
|
||||
q := manager.Query()
|
||||
q = q.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("billing_type"), billing_api.BILLING_TYPE_POSTPAID),
|
||||
sqlchemy.LE(q.Field("expired_at"), upLimit),
|
||||
sqlchemy.GE(q.Field("expired_at"), downLimit),
|
||||
),
|
||||
// 跳过自动续费实例
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("billing_type"), billing_api.BILLING_TYPE_PREPAID),
|
||||
sqlchemy.LE(q.Field("expired_at"), upLimit),
|
||||
sqlchemy.GE(q.Field("expired_at"), downLimit),
|
||||
sqlchemy.IsFalse(q.Field("auto_renew")),
|
||||
)))
|
||||
|
||||
vp := reflect.New(v.Type())
|
||||
vp.Elem().Set(v)
|
||||
|
||||
@@ -6609,3 +6609,29 @@ func (g *SGuest) PerformSetRootDiskMatcher(ctx context.Context, userCred mcclien
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (g *SGuest) PerformChangeBillingType(ctx context.Context, userCred mcclient.TokenCredential, _ jsonutils.JSONObject, input *api.ServerChangeBillingTypeInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(g.Status, []string{api.VM_RUNNING, api.VM_READY}) {
|
||||
return nil, httperrors.NewServerStatusError("Cannot change guest billing type in status %s", g.Status)
|
||||
}
|
||||
if len(input.BillingType) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("billing_type")
|
||||
}
|
||||
if !utils.IsInStringArray(input.BillingType, []string{billing_api.BILLING_TYPE_POSTPAID, billing_api.BILLING_TYPE_PREPAID}) {
|
||||
return nil, httperrors.NewInputParameterError("invalid billing_type %s", input.BillingType)
|
||||
}
|
||||
if g.BillingType == input.BillingType {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, g.StartChangeBillingTypeTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SGuest) StartChangeBillingTypeTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
self.SetStatus(ctx, userCred, api.VM_CHANGE_BILLING_TYPE, "")
|
||||
kwargs := jsonutils.NewDict()
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestChangeBillingTypeTask", self, userCred, kwargs, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ type IGuestDriver interface {
|
||||
RequestStartOnHost(ctx context.Context, guest *SGuest, host *SHost, userCred mcclient.TokenCredential, task taskman.ITask) error
|
||||
|
||||
RequestStopOnHost(ctx context.Context, guest *SGuest, host *SHost, task taskman.ITask, syncStatus bool) error
|
||||
RequestChangeBillingType(ctx context.Context, guest *SGuest, task taskman.ITask) error
|
||||
|
||||
StartDeleteGuestTask(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, params *jsonutils.JSONDict, parentTaskId string) error
|
||||
|
||||
|
||||
60
pkg/compute/tasks/guest_change_billing_type_task.go
Normal file
60
pkg/compute/tasks/guest_change_billing_type_task.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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"
|
||||
|
||||
"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 GuestChangeBillingTypeTask struct {
|
||||
SGuestBaseTask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(GuestChangeBillingTypeTask{})
|
||||
}
|
||||
|
||||
func (self *GuestChangeBillingTypeTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
self.SetStage("OnGuestChangeBillingTypeTaskComplete", nil)
|
||||
drv, err := guest.GetDriver()
|
||||
if err != nil {
|
||||
self.OnGuestChangeBillingTypeTaskCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
}
|
||||
err = drv.RequestChangeBillingType(ctx, guest, self)
|
||||
if err != nil {
|
||||
self.OnGuestChangeBillingTypeTaskCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestChangeBillingTypeTask) OnGuestChangeBillingTypeTaskComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_CHANGE_BILLING_TYPE, guest.BillingType, self.UserCred, false)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *GuestChangeBillingTypeTask) OnGuestChangeBillingTypeTaskCompleteFailed(ctx context.Context, guest *models.SGuest, reason jsonutils.JSONObject) {
|
||||
guest.SetStatus(ctx, self.GetUserCred(), api.VM_CHANGE_BILLING_TYPE_FAILED, "")
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_CHANGE_BILLING_TYPE, reason.String(), self.UserCred, false)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
@@ -125,6 +125,7 @@ type ServerStartOptions struct {
|
||||
ServerIdsOptions
|
||||
|
||||
QemuVersion string `help:"prefer qemu version" json:"qemu_version"`
|
||||
AutoPrepaid *bool `help:"Auto convert postpaid to prepaid"`
|
||||
}
|
||||
|
||||
func (o *ServerStartOptions) Params() (jsonutils.JSONObject, error) {
|
||||
@@ -1553,3 +1554,12 @@ func (o *ServerSetRootDiskMatcher) Params() (jsonutils.JSONObject, error) {
|
||||
}
|
||||
return jsonutils.Marshal(matcher), nil
|
||||
}
|
||||
|
||||
type ServerChangeBillingTypeOptions struct {
|
||||
ServerIdOptions
|
||||
BillingType string `choices:"prepaid|postpaid"`
|
||||
}
|
||||
|
||||
func (o *ServerChangeBillingTypeOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(map[string]string{"billing_type": o.BillingType}), nil
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ const (
|
||||
ACT_VM_SETSECGROUP = "vm_setsecgroup"
|
||||
ACT_VM_CPUSET = "vm_cpuset"
|
||||
ACT_VM_CPUSET_REMOVE = "vm_cpuset_remove"
|
||||
ACT_VM_CHANGE_BILLING_TYPE = "vm_change_billing_type"
|
||||
ACT_RESET_DISK = "reset_disk"
|
||||
ACT_SYNC_STATUS = "sync_status"
|
||||
ACT_SYNC_CONF = "sync_conf"
|
||||
|
||||
@@ -1533,4 +1533,8 @@ func init() {
|
||||
EN("Set Commit Bound").
|
||||
CN("设置超售比"),
|
||||
)
|
||||
o.Set(ACT_VM_CHANGE_BILLING_TYPE, i18n.NewTableEntry().
|
||||
EN("Change Billing Type").
|
||||
CN("更改计费模式"),
|
||||
)
|
||||
}
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -1785,7 +1785,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
|
||||
# sigs.k8s.io/yaml v1.2.0
|
||||
## explicit; go 1.12
|
||||
sigs.k8s.io/yaml
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250212024104-a8836a46c50a
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250214014132-42e126bc0593
|
||||
## explicit; go 1.21
|
||||
yunion.io/x/cloudmux/pkg/apis
|
||||
yunion.io/x/cloudmux/pkg/apis/billing
|
||||
|
||||
1
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/resources.go
generated
vendored
1
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/resources.go
generated
vendored
@@ -63,6 +63,7 @@ type IBillingResource interface {
|
||||
GetExpiredAt() time.Time
|
||||
SetAutoRenew(bc billing.SBillingCycle) error
|
||||
Renew(bc billing.SBillingCycle) error
|
||||
ChangeBillingType(billType string) error
|
||||
IsAutoRenew() bool
|
||||
}
|
||||
|
||||
|
||||
37
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/instance.go
generated
vendored
37
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/instance.go
generated
vendored
@@ -995,6 +995,43 @@ func (self *SInstance) GetBillingType() string {
|
||||
return convertChargeType(self.InstanceChargeType)
|
||||
}
|
||||
|
||||
func (self *SInstance) ChangeBillingType(billingType string) error {
|
||||
return self.host.zone.region.ModifyInstanceChargeType(self.InstanceId, billingType)
|
||||
}
|
||||
|
||||
func (region *SRegion) ModifyInstanceChargeType(vmId string, billingType string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"IncludeDataDisks": "true",
|
||||
"AutoPay": "true",
|
||||
"ClientToken": utils.GenRequestId(20),
|
||||
"InstanceIds": jsonutils.Marshal([]string{vmId}).String(),
|
||||
}
|
||||
switch billingType {
|
||||
case billing_api.BILLING_TYPE_POSTPAID:
|
||||
params["InstanceChargeType"] = "PostPaid"
|
||||
case billing_api.BILLING_TYPE_PREPAID:
|
||||
params["InstanceChargeType"] = "PrePaid"
|
||||
params["Period"] = "1"
|
||||
params["PeriodUnit"] = "Month"
|
||||
default:
|
||||
return fmt.Errorf("invalid billing_type %s", billingType)
|
||||
}
|
||||
_, err := region.ecsRequest("ModifyInstanceChargeType", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if billingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
cycle := billing.SBillingCycle{
|
||||
AutoRenew: true,
|
||||
Count: 1,
|
||||
Unit: billing.BillingCycleMonth,
|
||||
}
|
||||
region.SetInstanceAutoRenew(vmId, cycle)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetCreatedAt() time.Time {
|
||||
return self.CreationTime
|
||||
}
|
||||
|
||||
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/billing_base.go
generated
vendored
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/billing_base.go
generated
vendored
@@ -44,3 +44,7 @@ func (self *SBillingBase) IsAutoRenew() bool {
|
||||
func (self *SBillingBase) Renew(bc billing.SBillingCycle) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotImplemented, "Renew")
|
||||
}
|
||||
|
||||
func (self *SBillingBase) ChangeBillingType(billType string) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotImplemented, "ChangeBillingType")
|
||||
}
|
||||
|
||||
1
vendor/yunion.io/x/cloudmux/pkg/multicloud/hcso/modelarts.go
generated
vendored
1
vendor/yunion.io/x/cloudmux/pkg/multicloud/hcso/modelarts.go
generated
vendored
@@ -32,6 +32,7 @@ import (
|
||||
type SModelartsPool struct {
|
||||
region *SRegion
|
||||
multicloud.SResourceBase
|
||||
multicloud.SBillingBase
|
||||
|
||||
Metadata SModelartsPoolMetadata `json:"metadata"`
|
||||
Spec SModelartsPoolSpec `json:"spec"`
|
||||
|
||||
1
vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/modelarts_pool.go
generated
vendored
1
vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/modelarts_pool.go
generated
vendored
@@ -34,6 +34,7 @@ import (
|
||||
type SModelartsPool struct {
|
||||
region *SRegion
|
||||
multicloud.SResourceBase
|
||||
multicloud.SBillingBase
|
||||
|
||||
Metadata SModelartsPoolMetadata `json:"metadata"`
|
||||
Spec SModelartsPoolSpec `json:"spec"`
|
||||
|
||||
24
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/instance.go
generated
vendored
24
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/instance.go
generated
vendored
@@ -911,6 +911,30 @@ func (self *SInstance) GetBillingType() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SInstance) ChangeBillingType(billingType string) error {
|
||||
return self.host.zone.region.ModifyInstanceChargeType(self.InstanceId, billingType)
|
||||
}
|
||||
|
||||
func (region *SRegion) ModifyInstanceChargeType(vmId string, billingType string) error {
|
||||
params := map[string]string{
|
||||
"Region": region.Region,
|
||||
"ModifyPortableDataDisk": "true",
|
||||
"InstanceIds.0": vmId,
|
||||
}
|
||||
switch billingType {
|
||||
case billing_api.BILLING_TYPE_POSTPAID:
|
||||
params["InstanceChargeType"] = "POSTPAID_BY_HOUR"
|
||||
case billing_api.BILLING_TYPE_PREPAID:
|
||||
params["InstanceChargeType"] = "PREPAID"
|
||||
params["InstanceChargePrepaid.Period"] = "1"
|
||||
params["InstanceChargePrepaid.RenewFlag"] = "NOTIFY_AND_AUTO_RENEW"
|
||||
default:
|
||||
return fmt.Errorf("invalid billing_type %s", billingType)
|
||||
}
|
||||
_, err := region.cvmRequest("ModifyInstancesChargeType", params, false)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SInstance) GetCreatedAt() time.Time {
|
||||
return self.CreatedTime
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user