mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #9108 from ioito/hotfix/qx-guest-delete
Hotfix/qx guest delete
This commit is contained in:
@@ -106,6 +106,7 @@ type DiskListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
apis.MultiArchResourceBaseListInput
|
||||
apis.AutoDeleteResourceBaseListInput
|
||||
billing.BillingResourceListInput
|
||||
StorageFilterListInput
|
||||
|
||||
@@ -134,8 +135,6 @@ type DiskListInput struct {
|
||||
|
||||
DiskSize int `json:"disk_size"`
|
||||
|
||||
AutoDelete *bool `json:"auto_delete"`
|
||||
|
||||
FsFormat string `json:"fs_format"`
|
||||
|
||||
// 镜像
|
||||
|
||||
@@ -482,3 +482,25 @@ type ServerSaveImageInput struct {
|
||||
// swagger: ignore
|
||||
ImageId string
|
||||
}
|
||||
|
||||
type ServerDeleteInput struct {
|
||||
// 是否越过回收站直接删除
|
||||
// default: false
|
||||
OverridePendingDelete bool
|
||||
|
||||
// 是否仅删除本地资源
|
||||
// default: false
|
||||
Purge bool
|
||||
|
||||
// 是否删除快照
|
||||
// default: false
|
||||
DeleteSnapshots bool
|
||||
|
||||
// 是否删除关联的EIP
|
||||
// default: false
|
||||
DeleteEip bool
|
||||
|
||||
// 是否删除关联的数据盘
|
||||
// default: false
|
||||
DeleteDisks bool
|
||||
}
|
||||
|
||||
@@ -319,3 +319,7 @@ type EnabledStatusInfrasResourceBaseListInput struct {
|
||||
type MultiArchResourceBaseListInput struct {
|
||||
OsArch string `json:"os_arch"`
|
||||
}
|
||||
|
||||
type AutoDeleteResourceBaseListInput struct {
|
||||
AutoDelete *bool
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by model-api-gen. DO NOT EDIT.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
// +onecloud:model-api-gen
|
||||
type SAutoDeleteResourceBase struct {
|
||||
// 是否跟随资源自动删除
|
||||
// example: false
|
||||
AutoDelete bool `nullable:"false" default:"false" get:"user" update:"user" json:"auto_delete"`
|
||||
}
|
||||
|
||||
type SAutoDeleteResourceBaseManager struct{}
|
||||
|
||||
func (manager *SAutoDeleteResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query apis.AutoDeleteResourceBaseListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if query.AutoDelete != nil {
|
||||
q = q.Equals("auto_delete", *query.AutoDelete)
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SAutoDeleteResourceBase) SetAutoDelete(model IModel, userCred mcclient.TokenCredential, autoDelete bool) error {
|
||||
_, err := Update(model, func() error {
|
||||
self.AutoDelete = autoDelete
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -60,6 +60,7 @@ type SDiskManager struct {
|
||||
SStorageResourceBaseManager
|
||||
SBillingResourceBaseManager
|
||||
db.SMultiArchResourceBaseManager
|
||||
db.SAutoDeleteResourceBaseManager
|
||||
}
|
||||
|
||||
var DiskManager *SDiskManager
|
||||
@@ -83,6 +84,7 @@ type SDisk struct {
|
||||
SBillingResourceBase
|
||||
SStorageResourceBase `width:"128" charset:"ascii" nullable:"true" list:"admin" create:"optional"`
|
||||
db.SMultiArchResourceBase
|
||||
db.SAutoDeleteResourceBase
|
||||
|
||||
// 磁盘存储类型
|
||||
// example: qcow2
|
||||
@@ -93,10 +95,6 @@ type SDisk struct {
|
||||
// 磁盘路径
|
||||
AccessPath string `width:"256" charset:"ascii" nullable:"true" get:"user" json:"access_path"`
|
||||
|
||||
// 是否跟随云主机自动删除, 仅绑定到云主机时才生效
|
||||
// example: false
|
||||
AutoDelete bool `nullable:"false" default:"false" get:"user" update:"user" json:"auto_delete"`
|
||||
|
||||
// 存储Id
|
||||
// StorageId string `width:"128" charset:"ascii" nullable:"true" list:"admin" create:"optional"`
|
||||
|
||||
@@ -174,6 +172,11 @@ func (manager *SDiskManager) ListItemFilter(
|
||||
return nil, errors.Wrap(err, "SMultiArchResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
q, err = manager.SAutoDeleteResourceBaseManager.ListItemFilter(ctx, q, userCred, query.AutoDeleteResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAutoDeleteResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
if query.Unused != nil {
|
||||
guestdisks := GuestdiskManager.Query().SubQuery()
|
||||
sq := guestdisks.Query(guestdisks.Field("disk_id"))
|
||||
@@ -224,14 +227,6 @@ func (manager *SDiskManager) ListItemFilter(
|
||||
q = q.Equals("disk_size", query.DiskSize)
|
||||
}
|
||||
|
||||
if query.AutoDelete != nil {
|
||||
if *query.AutoDelete {
|
||||
q = q.IsTrue("auto_delete")
|
||||
} else {
|
||||
q = q.IsFalse("auto_delete")
|
||||
}
|
||||
}
|
||||
|
||||
if len(query.FsFormat) > 0 {
|
||||
q = q.Equals("fs_format", query.FsFormat)
|
||||
}
|
||||
|
||||
@@ -1074,24 +1074,17 @@ func (self *SGuest) StartSyncstatus(ctx context.Context, userCred mcclient.Token
|
||||
|
||||
func (self *SGuest) StartAutoDeleteGuestTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
db.OpsLog.LogEvent(self, db.ACT_DELETE, "auto-delete after stop", userCred)
|
||||
return self.StartDeleteGuestTask(ctx, userCred, parentTaskId, false, false, false)
|
||||
opts := api.ServerDeleteInput{}
|
||||
return self.StartDeleteGuestTask(ctx, userCred, parentTaskId, opts)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartDeleteGuestTask(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string,
|
||||
isPurge, overridePendingDelete, deleteSnapshots bool,
|
||||
opts api.ServerDeleteInput,
|
||||
) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(self.Status), "guest_status")
|
||||
if isPurge {
|
||||
params.Add(jsonutils.JSONTrue, "purge")
|
||||
}
|
||||
if overridePendingDelete {
|
||||
params.Add(jsonutils.JSONTrue, "override_pending_delete")
|
||||
}
|
||||
if deleteSnapshots {
|
||||
params.Add(jsonutils.JSONTrue, "delete_snapshots")
|
||||
}
|
||||
params.Update(jsonutils.Marshal(opts))
|
||||
self.SetStatus(userCred, api.VM_START_DELETE, "")
|
||||
return self.GetDriver().StartDeleteGuestTask(ctx, userCred, self, params, parentTaskId)
|
||||
}
|
||||
@@ -1388,7 +1381,10 @@ func (self *SGuest) PerformPurge(ctx context.Context, userCred mcclient.TokenCre
|
||||
if host != nil && host.GetEnabled() {
|
||||
return nil, httperrors.NewInvalidStatusError("Cannot purge server on enabled host")
|
||||
}
|
||||
err = self.StartDeleteGuestTask(ctx, userCred, "", true, false, false)
|
||||
opts := api.ServerDeleteInput{
|
||||
Purge: true,
|
||||
}
|
||||
err = self.StartDeleteGuestTask(ctx, userCred, "", opts)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -3823,18 +3823,9 @@ func (self *SGuest) AllowDeleteItem(ctx context.Context, userCred mcclient.Token
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowDelete(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SGuest) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
var (
|
||||
overridePendingDelete = false
|
||||
purge = false
|
||||
deleteSnapshots = false
|
||||
)
|
||||
if query != nil {
|
||||
overridePendingDelete = jsonutils.QueryBoolean(query, "override_pending_delete", false)
|
||||
purge = jsonutils.QueryBoolean(query, "purge", false)
|
||||
deleteSnapshots = jsonutils.QueryBoolean(query, "delete_snapshots", false)
|
||||
}
|
||||
return self.StartDeleteGuestTask(ctx, userCred, "", purge, overridePendingDelete, deleteSnapshots)
|
||||
// 删除虚拟机
|
||||
func (self *SGuest) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query api.ServerDeleteInput, data jsonutils.JSONObject) error {
|
||||
return self.StartDeleteGuestTask(ctx, userCred, "", query)
|
||||
}
|
||||
|
||||
func (self *SGuest) DeleteAllDisksInDB(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
@@ -4644,7 +4635,10 @@ func (manager *SGuestManager) CleanPendingDeleteServers(ctx context.Context, use
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(guests); i += 1 {
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, true, false)
|
||||
opts := api.ServerDeleteInput{
|
||||
OverridePendingDelete: true,
|
||||
}
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", opts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4715,7 +4709,7 @@ func (manager *SGuestManager) DeleteExpiredPrepaidServers(ctx context.Context, u
|
||||
if guests == nil {
|
||||
return
|
||||
}
|
||||
deteleSnapshot := options.Options.DeleteSnapshotExpiredRelease
|
||||
deleteSnapshot := options.Options.DeleteSnapshotExpiredRelease
|
||||
for i := 0; i < len(guests); i += 1 {
|
||||
// fake delete expired prepaid servers
|
||||
if len(guests[i].ExternalId) > 0 {
|
||||
@@ -4725,7 +4719,10 @@ func (manager *SGuestManager) DeleteExpiredPrepaidServers(ctx context.Context, u
|
||||
}
|
||||
}
|
||||
guests[i].SetDisableDelete(userCred, false)
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, false, deteleSnapshot)
|
||||
opts := api.ServerDeleteInput{
|
||||
DeleteSnapshots: deleteSnapshot,
|
||||
}
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", opts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4761,7 +4758,8 @@ func (manager *SGuestManager) DeleteExpiredPostpaidServers(ctx context.Context,
|
||||
}
|
||||
}
|
||||
guests[i].SetDisableDelete(userCred, false)
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, false, deleteSnapshot)
|
||||
opts := api.ServerDeleteInput{DeleteSnapshots: deleteSnapshot}
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", opts)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,10 @@ func (self *SGuest) DoPerformPrepaidRecycle(ctx context.Context, userCred mcclie
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_RECYCLE_PREPAID, self.GetShortDesc(ctx), userCred, true)
|
||||
|
||||
if autoDelete {
|
||||
self.StartDeleteGuestTask(ctx, userCred, "", false, true, false)
|
||||
opts := api.ServerDeleteInput{
|
||||
OverridePendingDelete: true,
|
||||
}
|
||||
self.StartDeleteGuestTask(ctx, userCred, "", opts)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
@@ -90,7 +90,8 @@ func (self *BaremetalConvertHypervisorTask) OnGuestDeployCompleteFailed(ctx cont
|
||||
guest := self.getGuest()
|
||||
guest.SetDisableDelete(self.UserCred, false)
|
||||
self.SetStage("OnGuestDeleteComplete", nil)
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), false, true, false)
|
||||
opts := api.ServerDeleteInput{OverridePendingDelete: true}
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), opts)
|
||||
logclient.AddActionLogWithStartable(self, baremetal, logclient.ACT_BM_CONVERT_HYPER, fmt.Sprintf("convert deploy failed: %s", body.String()), self.UserCred, false)
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ func (self *BaremetalUnconvertHypervisorTask) OnInit(ctx context.Context, obj db
|
||||
if len(guests) == 1 {
|
||||
guest := guests[0]
|
||||
self.SetStage("OnGuestDeleteComplete", nil)
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), false, true, false)
|
||||
opts := api.ServerDeleteInput{OverridePendingDelete: true}
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), opts)
|
||||
} else {
|
||||
self.OnGuestDeleteComplete(ctx, baremetal, nil)
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ func (self *GuestDeleteTask) OnStartEipDissociate(ctx context.Context, guest *mo
|
||||
self.OnEipDissociateComplete(ctx, guest, nil)
|
||||
} else {
|
||||
self.SetStage("OnEipDissociateComplete", nil)
|
||||
eip.StartEipDissociateTask(ctx, self.UserCred, false, self.GetTaskId())
|
||||
autoDelete := jsonutils.QueryBoolean(self.GetParams(), "delete_eip", false)
|
||||
eip.StartEipDissociateTask(ctx, self.UserCred, autoDelete, self.GetTaskId())
|
||||
}
|
||||
} else {
|
||||
self.OnEipDissociateComplete(ctx, guest, nil)
|
||||
@@ -157,6 +158,10 @@ func (self *GuestDeleteTask) OnDiskDetachComplete(ctx context.Context, obj db.IS
|
||||
}
|
||||
// detach last detachable disk
|
||||
lastDisk := guestdisks[len(guestdisks)-1].GetDisk()
|
||||
deleteDisks := jsonutils.QueryBoolean(self.Params, "delete_disks", false)
|
||||
if deleteDisks {
|
||||
lastDisk.SetAutoDelete(lastDisk, self.GetUserCred(), true)
|
||||
}
|
||||
log.Debugf("lastDisk IsDetachable?? %v", lastDisk.IsDetachable())
|
||||
if !lastDisk.IsDetachable() {
|
||||
// no more disk need detach
|
||||
|
||||
@@ -98,7 +98,9 @@ func (self *GuestDetachScalingGroupTask) OnDetachLoadbalancerComplete(ctx contex
|
||||
}
|
||||
self.Params.Set("guest_name", jsonutils.NewString(guest.GetName()))
|
||||
self.SetStage("OnDeleteGuestComplete", nil)
|
||||
if err := guest.StartDeleteGuestTask(ctx, self.UserCred, self.Id, false, true, true); err != nil {
|
||||
opts := api.ServerDeleteInput{Purge: false, OverridePendingDelete: true, DeleteSnapshots: true}
|
||||
err := guest.StartDeleteGuestTask(ctx, self.UserCred, self.Id, opts)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, sg, nil, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,6 +614,8 @@ type ServerDeleteOptions struct {
|
||||
ServerIdsOptions
|
||||
OverridePendingDelete *bool `help:"Delete server directly instead of pending delete" short-token:"f"`
|
||||
DeleteSnapshots *bool `help:"Delete server snapshots"`
|
||||
DeleteDisks *bool `help:"Delete server disks"`
|
||||
DeleteEip *bool `help:"Delete eip"`
|
||||
}
|
||||
|
||||
func (o *ServerDeleteOptions) QueryParams() (jsonutils.JSONObject, error) {
|
||||
|
||||
Reference in New Issue
Block a user