Merge pull request #9108 from ioito/hotfix/qx-guest-delete

Hotfix/qx guest delete
This commit is contained in:
Zexi Li
2020-12-28 16:01:09 +08:00
committed by GitHub
13 changed files with 129 additions and 47 deletions
+1 -2
View File
@@ -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"`
// 镜像
+22
View File
@@ -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
}
+4
View File
@@ -319,3 +319,7 @@ type EnabledStatusInfrasResourceBaseListInput struct {
type MultiArchResourceBaseListInput struct {
OsArch string `json:"os_arch"`
}
type AutoDeleteResourceBaseListInput struct {
AutoDelete *bool
}
+54
View File
@@ -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
}
+7 -12
View File
@@ -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)
}
+8 -12
View File
@@ -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
}
+14 -16
View File
@@ -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)
}
}
+4 -1
View File
@@ -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)
}
+6 -1
View File
@@ -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()))
}
}
+2
View File
@@ -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) {