mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #886 in YUNIONIO/onecloud from ~QIUJIAN/onecloud:feature/qj-vipkid-prepaid-features to release/2.5.0
* commit 'ffe6d3910d8dccbab848fb1c08f81a8c0521ee65':
增加climc zone-update-status命令
server-create创建prepaid主机,增加auto_prepaid_recycle参数,创建后自动加入包年包月资源池
minor fixes
minor changes: 防止float类型的column设置default后每次都要更新
增加:1. 包年包月主机加入资源池后,如果auto_delete=true,则自动删除该主机 2. 包年包月资源池的宿主机支持续费操作Perform(host.id, "renew-prepaid-recycle", {"duration": "1m"})
This commit is contained in:
@@ -15,6 +15,7 @@ type BaseEventListOptions struct {
|
||||
Offset int64 `help:"Offset"`
|
||||
Ascending bool `help:"Ascending order"`
|
||||
Descending bool `help:"Descending order"`
|
||||
OrderBy string `help:"order by specific field"`
|
||||
Action []string `help:"Log action"`
|
||||
}
|
||||
|
||||
@@ -62,6 +63,9 @@ func doEventList(man modules.ResourceManager, s *mcclient.ClientSession, args *E
|
||||
} else if !args.Ascending && args.Descending {
|
||||
params.Add(jsonutils.NewString("desc"), "order")
|
||||
}
|
||||
if len(args.OrderBy) > 0 {
|
||||
params.Add(jsonutils.NewString(args.OrderBy), "order_by")
|
||||
}
|
||||
if len(args.Action) > 0 {
|
||||
params.Add(jsonutils.NewStringArray(args.Action), "action")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -126,4 +126,21 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type ZoneStatusOptions struct {
|
||||
ID string `help:"ID or name of zone"`
|
||||
STATUS string `help:"zone status" choices:"enable|disable|soldout"`
|
||||
REASON string `help:"why update status"`
|
||||
}
|
||||
R(&ZoneStatusOptions{}, "zone-update-status", "Update zone status", func(s *mcclient.ClientSession, args *ZoneStatusOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("status", jsonutils.NewString(args.STATUS))
|
||||
params.Set("reason", jsonutils.NewString(args.REASON))
|
||||
result, err := modules.Zones.PerformAction(s, args.ID, "status", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -447,7 +447,6 @@ func ListItems(manager IModelManager, ctx context.Context, userCred mcclient.Tok
|
||||
limit = maxLimit
|
||||
}
|
||||
orderBy := jsonutils.GetQueryStringArray(queryDict, "order_by")
|
||||
order := sqlchemy.SQL_ORDER_DESC
|
||||
if len(orderBy) == 0 {
|
||||
colSpec := manager.TableSpec().ColumnSpec("id")
|
||||
if err == nil && colSpec != nil && colSpec.IsNumeric() {
|
||||
@@ -455,11 +454,11 @@ func ListItems(manager IModelManager, ctx context.Context, userCred mcclient.Tok
|
||||
} else {
|
||||
orderBy = []string{"created_at"}
|
||||
}
|
||||
} else {
|
||||
orderStr, _ := queryDict.GetString("order")
|
||||
if orderStr == "asc" {
|
||||
order = sqlchemy.SQL_ORDER_ASC
|
||||
}
|
||||
}
|
||||
order := sqlchemy.SQL_ORDER_DESC
|
||||
orderStr, _ := queryDict.GetString("order")
|
||||
if orderStr == "asc" {
|
||||
order = sqlchemy.SQL_ORDER_ASC
|
||||
}
|
||||
if order == sqlchemy.SQL_ORDER_ASC {
|
||||
for _, orderByField := range orderBy {
|
||||
|
||||
@@ -9,6 +9,12 @@ var (
|
||||
Action: PolicyActionPerform,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "hosts",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "zones",
|
||||
|
||||
@@ -63,6 +63,14 @@ func (self *SBaseGuestDriver) OnGuestCreateTaskComplete(ctx context.Context, gue
|
||||
if err == nil && guest.ExpiredAt.IsZero() {
|
||||
guest.SaveRenewInfo(ctx, task.GetUserCred(), &bc, nil)
|
||||
}
|
||||
if jsonutils.QueryBoolean(task.GetParams(), "auto_prepaid_recycle", false) {
|
||||
err := guest.CanPerformPrepaidRecycle()
|
||||
if err == nil {
|
||||
task.SetStageComplete(ctx, nil)
|
||||
guest.DoPerformPrepaidRecycle(ctx, task.GetUserCred(), true)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if jsonutils.QueryBoolean(task.GetParams(), "auto_start", false) {
|
||||
task.SetStage("on_auto_start_guest", nil)
|
||||
|
||||
@@ -52,7 +52,7 @@ func getHypervisors(zone *SZone) []string {
|
||||
q = q.Equals("zone_id", zone.Id)
|
||||
}
|
||||
q = q.IsNotEmpty("host_type").IsNotNull("host_type")
|
||||
q = q.Equals("host_status", HOST_ONLINE)
|
||||
// q = q.Equals("host_status", HOST_ONLINE)
|
||||
q = q.IsTrue("enabled")
|
||||
q = q.Distinct()
|
||||
rows, err := q.Rows()
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -56,7 +58,11 @@ func (self *SGuest) PerformPrepaidRecycle(ctx context.Context, userCred mcclient
|
||||
return nil, httperrors.NewInvalidStatusError(err.Error())
|
||||
}
|
||||
|
||||
err = self.doPrepaidRecycle(ctx, userCred)
|
||||
return self.DoPerformPrepaidRecycle(ctx, userCred, jsonutils.QueryBoolean(data, "auto_delete", false))
|
||||
}
|
||||
|
||||
func (self *SGuest) DoPerformPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, autoDelete bool) (jsonutils.JSONObject, error) {
|
||||
err := self.doPrepaidRecycle(ctx, userCred)
|
||||
if err != nil {
|
||||
logclient.AddActionLog(self, logclient.ACT_RECYCLE_PREPAID, self.GetShortDesc(ctx), userCred, false)
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
@@ -65,6 +71,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)
|
||||
|
||||
if autoDelete {
|
||||
self.StartDeleteGuestTask(ctx, userCred, "", false, true)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -656,3 +666,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)
|
||||
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" 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"`
|
||||
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
ZONE_ENABLE = "enable"
|
||||
ZONE_DISABLE = "disable"
|
||||
ZONE_SOLDOUT = "soldout"
|
||||
ZONE_LACK = "lack"
|
||||
// ZONE_LACK = "lack"
|
||||
)
|
||||
|
||||
type SZoneManager struct {
|
||||
@@ -469,6 +469,12 @@ func (manager *SZoneManager) InitializeData() error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if z.Status == "init" {
|
||||
manager.TableSpec().Update(&z, func() error {
|
||||
z.Status = ZONE_ENABLE
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -529,6 +535,21 @@ func (manager *SZoneManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
|
||||
sqlchemy.In(q.Field("id"), sq.SubQuery()),
|
||||
sqlchemy.In(q.Field("id"), sq2.SubQuery()),
|
||||
))
|
||||
q = q.Equals("status", ZONE_ENABLE)
|
||||
}
|
||||
managerStr, _ := query.GetString("manager")
|
||||
if len(managerStr) > 0 {
|
||||
provider := CloudproviderManager.FetchCloudproviderByIdOrName(managerStr)
|
||||
if provider == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Cloud provider/manager %s not found", managerStr)
|
||||
}
|
||||
subq := CloudregionManager.Query("id").Equals("provider", provider.Provider).SubQuery()
|
||||
q = q.In("cloudregion_id", subq)
|
||||
}
|
||||
providerStr, _ := query.GetString("provider")
|
||||
if len(providerStr) > 0 {
|
||||
subq := CloudregionManager.Query("id").Equals("provider", providerStr).SubQuery()
|
||||
q = q.In("cloudregion_id", subq)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
@@ -595,5 +616,6 @@ func (manager *SZoneManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
regionId = "default"
|
||||
}
|
||||
data.Add(jsonutils.NewString(regionId), "cloudregion_id")
|
||||
data.Set("status", jsonutils.NewString(ZONE_ENABLE))
|
||||
return manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -94,8 +94,9 @@ func ParseServerDeployInfoList(list []string) (*jsonutils.JSONDict, error) {
|
||||
type ServerCreateOptions struct {
|
||||
ScheduleOptions
|
||||
|
||||
NAME string `help:"Name of server" json:"-"`
|
||||
MEMSPEC string `help:"Memory size Or Instance Type" metavar:"MEMSPEC" json:"-"`
|
||||
NAME string `help:"Name of server" json:"-"`
|
||||
MEMSPEC string `help:"Memory size Or Instance Type" metavar:"MEMSPEC" json:"-"`
|
||||
|
||||
Disk []string `help:"Disk descriptions" nargs:"+"`
|
||||
Net []string `help:"Network descriptions" metavar:"NETWORK"`
|
||||
IsolatedDevice []string `help:"Isolated device model or ID" metavar:"ISOLATED_DEVICE"`
|
||||
@@ -127,6 +128,8 @@ type ServerCreateOptions struct {
|
||||
|
||||
Duration string `help:"valid duration of the server, e.g. 1H, 1D, 1W, 1M, 1Y, ADMIN ONLY option"`
|
||||
|
||||
AutoPrepaidRecycle bool `help:"automatically enable prepaid recycling after server is created successfully" json:",omitfalse"`
|
||||
|
||||
GenerateName bool `help:"name is generated by pattern" json:"-"`
|
||||
}
|
||||
|
||||
|
||||
@@ -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