mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-20 21:26:01 +08:00
增加:1.
包年包月主机加入资源池后,如果auto_delete=true,则自动删除该主机 2.
包年包月资源池的宿主机支持续费操作Perform(host.id,
"renew-prepaid-recycle", {"duration": "1m"})
This commit is contained in:
@@ -497,4 +497,19 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type PrepaidRecycleHostRenewOptions struct {
|
||||
ID string `help:"ID or name of server to renew"`
|
||||
DURATION string `help:"Duration of renew, ADMIN only command"`
|
||||
}
|
||||
R(&PrepaidRecycleHostRenewOptions{}, "host-renew-prepaid-recycle", "Renew a prepaid recycle host", func(s *mcclient.ClientSession, args *PrepaidRecycleHostRenewOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.DURATION), "duration")
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "renew-prepaid-recycle", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -634,10 +634,14 @@ func init() {
|
||||
})
|
||||
|
||||
type ServerPrepaidRecycleOptions struct {
|
||||
ID string `help:"ID or name of server to recycle"`
|
||||
ID string `help:"ID or name of server to recycle"`
|
||||
AutoDelete bool `help:"after joining the pool, remove the server automatically"`
|
||||
}
|
||||
R(&ServerPrepaidRecycleOptions{}, "server-enable-recycle", "Put a prepaid server into recycle pool, so that it can be shared", func(s *mcclient.ClientSession, args *ServerPrepaidRecycleOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if args.AutoDelete {
|
||||
params.Add(jsonutils.JSONTrue, "auto_delete")
|
||||
}
|
||||
result, err := modules.Servers.PerformAction(s, args.ID, "prepaid-recycle", params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -3429,7 +3429,8 @@ func (manager *SGuestManager) DeleteExpiredPrepaidServers(ctx context.Context, u
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(guests); i += 1 {
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, true)
|
||||
// fake delete expired prepaid servers
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,12 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"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/logclient"
|
||||
)
|
||||
|
||||
@@ -65,6 +67,10 @@ func (self *SGuest) PerformPrepaidRecycle(ctx context.Context, userCred mcclient
|
||||
db.OpsLog.LogEvent(self, db.ACT_RECYCLE_PREPAID, self.GetShortDesc(ctx), userCred)
|
||||
logclient.AddActionLog(self, logclient.ACT_RECYCLE_PREPAID, self.GetShortDesc(ctx), userCred, true)
|
||||
|
||||
autoDelete := jsonutils.QueryBoolean(data, "auto_delete", false)
|
||||
if autoDelete {
|
||||
self.StartDeleteGuestTask(ctx, userCred, "", false, true)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -656,3 +662,63 @@ func (manager *SHostManager) GetHostByRealExternalId(eid string) *SHost {
|
||||
|
||||
return &host
|
||||
}
|
||||
|
||||
func (self *SHost) AllowPerformRenewPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "renew-prepaid-recycle")
|
||||
}
|
||||
|
||||
func (self *SHost) PerformRenewPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
durationStr := jsonutils.GetAnyString(data, []string{"duration"})
|
||||
if len(durationStr) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("missing duration")
|
||||
}
|
||||
|
||||
bc, err := billing.ParseBillingCycle(durationStr)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid duration %s: %s", durationStr, err)
|
||||
}
|
||||
|
||||
if !GetDriver(HOSTTYPE_HYPERVISOR[self.HostType]).IsSupportedBillingCycle(bc) {
|
||||
return nil, httperrors.NewInputParameterError("unsupported duration %s", durationStr)
|
||||
}
|
||||
|
||||
err = self.startPrepaidRecycleHostRenewTask(ctx, userCred, durationStr, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SHost) startPrepaidRecycleHostRenewTask(ctx context.Context, userCred mcclient.TokenCredential, duration string, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(duration), "duration")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "PrepaidRecycleHostRenewTask", self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("fail to crate GuestRenewTask %s", err)
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) DoSaveRenewInfo(ctx context.Context, userCred mcclient.TokenCredential, bc *billing.SBillingCycle, expireAt *time.Time) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
if self.BillingType != BILLING_TYPE_PREPAID {
|
||||
self.BillingType = BILLING_TYPE_PREPAID
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -138,11 +138,11 @@ type SHost struct {
|
||||
CpuMhz int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu MHz
|
||||
CpuCache int `nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # cpu Cache in KB
|
||||
CpuReserved int8 `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(TINYINT, nullable=True, default=0)
|
||||
CpuCmtbound float32 `nullable:"true" default:"8.0" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True)
|
||||
CpuCmtbound float32 `nullable:"true" default:"8" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True)
|
||||
|
||||
MemSize int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # memory size in MB
|
||||
MemReserved int `nullable:"true" default:"0" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True, default=0) # memory reserved in MB
|
||||
MemCmtbound float32 `nullable:"true" default:"1.0" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True)
|
||||
MemCmtbound float32 `nullable:"true" default:"1" list:"admin" update:"admin" create:"admin_optional"` // = Column(Float, nullable=True)
|
||||
|
||||
StorageSize int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(Integer, nullable=True) # storage size in MB
|
||||
StorageType string `width:"20" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(20, charset='ascii'), nullable=True)
|
||||
|
||||
@@ -120,7 +120,7 @@ type SStorage struct {
|
||||
Reserved int `nullable:"true" default:"0" list:"admin" update:"admin"` // Column(Integer, nullable=True, default=0)
|
||||
StorageType string `width:"32" charset:"ascii" nullable:"false" list:"user" update:"admin" create:"admin_required"` // Column(VARCHAR(32, charset='ascii'), nullable=False)
|
||||
MediumType string `width:"32" charset:"ascii" nullable:"false" list:"user" update:"admin" create:"admin_required"` // Column(VARCHAR(32, charset='ascii'), nullable=False)
|
||||
Cmtbound float32 `nullable:"true" default:"1.0" list:"admin" update:"admin"` // Column(Float, nullable=True)
|
||||
Cmtbound float32 `nullable:"true" default:"1" list:"admin" update:"admin"` // Column(Float, nullable=True)
|
||||
StorageConf jsonutils.JSONObject `nullable:"true" get:"admin" update:"admin"` // = Column(JSONEncodedDict, nullable=True)
|
||||
|
||||
ZoneId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"admin_required"`
|
||||
|
||||
@@ -153,8 +153,9 @@ func (self *GuestDeleteTask) OnSyncConfigComplete(ctx context.Context, obj db.IS
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnSyncConfigCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
self.OnFailed(ctx, guest, err)
|
||||
// guest := obj.(*models.SGuest)
|
||||
// self.OnFailed(ctx, guest, err)
|
||||
self.OnSyncConfigComplete(ctx, obj, err) // ignore sync config failed error
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestDeleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
|
||||
@@ -19,6 +19,7 @@ type GuestRenewTask struct {
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(GuestRenewTask{})
|
||||
taskman.RegisterTask(PrepaidRecycleHostRenewTask{})
|
||||
}
|
||||
|
||||
func (self *GuestRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
@@ -45,3 +46,50 @@ func (self *GuestRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
type PrepaidRecycleHostRenewTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func (self *PrepaidRecycleHostRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
host := obj.(*models.SHost)
|
||||
|
||||
durationStr, _ := self.GetParams().GetString("duration")
|
||||
bc, _ := billing.ParseBillingCycle(durationStr)
|
||||
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("host.GetIHost fail %s", err)
|
||||
log.Errorf(msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
iVM, err := ihost.GetIVMById(host.RealExternalId)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("ihost.GetIVMById fail %s", err)
|
||||
log.Errorf(msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = iVM.Renew(bc)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("iVM.Renew fail %s", err)
|
||||
log.Errorf(msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
exp := iVM.GetExpiredAt()
|
||||
|
||||
err = host.DoSaveRenewInfo(ctx, self.UserCred, &bc, &exp)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("SaveRenewInfo fail %s", err)
|
||||
log.Errorf(msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func _jsonRequest(client *sdk.Client, domain string, version string, apiName str
|
||||
|
||||
resp, err := processCommonRequest(client, req)
|
||||
if err != nil {
|
||||
log.Errorf("request error %s", err)
|
||||
log.Errorf("request error %s parameters %s", err, params)
|
||||
return nil, err
|
||||
}
|
||||
body, err := jsonutils.Parse(resp.GetHttpContentBytes())
|
||||
|
||||
@@ -905,7 +905,13 @@ func (self *SInstance) GetBillingType() string {
|
||||
}
|
||||
|
||||
func (self *SInstance) GetExpiredAt() time.Time {
|
||||
return self.ExpiredTime
|
||||
if !self.ExpiredTime.IsZero() {
|
||||
now := time.Now()
|
||||
if self.ExpiredTime.Sub(now) < time.Hour*24*365*6 {
|
||||
return self.ExpiredTime
|
||||
}
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateUserData(userData string) error {
|
||||
@@ -925,10 +931,10 @@ func (region *SRegion) RenewInstance(instanceId string, bc billing.SBillingCycle
|
||||
params["InstanceId"] = instanceId
|
||||
if bc.GetWeeks() <= 4 {
|
||||
params["PeriodUnit"] = "Week"
|
||||
params["Period"] = fmt.Sprintf("%s", bc.GetWeeks())
|
||||
params["Period"] = fmt.Sprintf("%d", bc.GetWeeks())
|
||||
} else {
|
||||
params["PeriodUnit"] = "Month"
|
||||
params["Period"] = fmt.Sprintf("%s", bc.GetMonths())
|
||||
params["Period"] = fmt.Sprintf("%d", bc.GetMonths())
|
||||
}
|
||||
params["ClientToken"] = utils.GenRequestId(20)
|
||||
_, err := region.ecsRequest("RenewInstance", params)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -134,7 +135,7 @@ func (self *SZone) IsEmulated() bool {
|
||||
}
|
||||
|
||||
func (self *SZone) GetStatus() string {
|
||||
if len(self.AvailableResourceCreation.ResourceTypes) == 0 {
|
||||
if len(self.AvailableResourceCreation.ResourceTypes) == 0 || !utils.IsInStringArray("Instance", self.AvailableResourceCreation.ResourceTypes) {
|
||||
return models.ZONE_SOLDOUT
|
||||
} else {
|
||||
return models.ZONE_ENABLE
|
||||
|
||||
Reference in New Issue
Block a user