This commit is contained in:
wanyaoqi
2018-09-06 20:30:08 +08:00
parent 4f2b50a869
commit 5b57339166
5 changed files with 113 additions and 33 deletions
+19 -2
View File
@@ -10,14 +10,18 @@ import (
func init() {
type SnapshotsListOptions struct {
options.BaseListOptions
Disk string `help:"Disk snapshots"`
Disk string `help:"Disk snapshots"`
FakeDeleted bool `help:"Show fake deleted snapshot or not"`
}
R(&SnapshotsListOptions{}, "snapshot-list", "Show snapshots", func(s *mcclient.ClientSession, args *SnapshotsListOptions) error {
params, err := args.BaseListOptions.Params()
if err != nil {
return err
}
params.Add(jsonutils.NewString(args.Disk), "disk_id")
if len(args.Disk) > 0 {
params.Add(jsonutils.NewString(args.Disk), "disk_id")
}
params.Add(jsonutils.NewBool(args.FakeDeleted), "fake_deleted")
result, err := modules.Snapshots.List(s, params)
if err != nil {
return err
@@ -37,4 +41,17 @@ func init() {
printObject(result)
return nil
})
type DiskDeleteSnapshotsOptions struct {
DISK string `help:"ID of disk"`
}
R(&DiskDeleteSnapshotsOptions{}, "disk-delete-snapshots", "Delete a disk snapshots", func(s *mcclient.ClientSession, args *DiskDeleteSnapshotsOptions) error {
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(args.DISK), "disk_id")
result, err := modules.Snapshots.PerformClassAction(s, "delete-disk-snapshots", params)
if err != nil {
return err
}
printObject(result)
return nil
})
}
+7 -4
View File
@@ -355,14 +355,17 @@ func (self *SDisk) GetDetailsConvertSnapshot(ctx context.Context, userCred mccli
if err != nil {
return nil, httperrors.NewBadRequestError("Get convert snapshot failed: %s", err.Error())
}
var pendingDelete bool
if deleteSnapshot.CreatedBy == MANUAL && !deleteSnapshot.PendingDeleted {
pendingDelete = true
if convertSnapshot == nil {
return nil, httperrors.NewBadRequestError("Snapshot %s dose not have convert snapshot", deleteSnapshot.Id)
}
var FakeDelete bool
if deleteSnapshot.CreatedBy == MANUAL && !deleteSnapshot.FakeDeleted {
FakeDelete = true
}
ret := jsonutils.NewDict()
ret.Set("delete_snapshot", jsonutils.NewString(deleteSnapshot.Id))
ret.Set("convert_snapshot", jsonutils.NewString(convertSnapshot.Id))
ret.Set("pending_delete", jsonutils.NewBool(pendingDelete))
ret.Set("pending_delete", jsonutils.NewBool(FakeDelete))
return ret, nil
}
+39 -10
View File
@@ -32,12 +32,13 @@ type SSnapshotManager struct {
type SSnapshot struct {
db.SVirtualResourceBase
DiskId string `width:"36" charset:"ascii" nullable:"false" create:"required" key_index:"true" list:"user"`
StorageId string `width:"36" charset:"ascii" nullable:"true" list:"admin"`
CreatedBy string `width:"36" charset:"ascii" nullable:"false" default:"manual" list:"admin"`
Location string `charset:"ascii" nullable:"false" list:"admin"`
Size int `nullable:"false" list:"user"` // MB
OutOfChain bool `nullable:"false" default:"false" index:"true" get:"admin"`
DiskId string `width:"36" charset:"ascii" nullable:"false" create:"required" key_index:"true" list:"user"`
StorageId string `width:"36" charset:"ascii" nullable:"true" list:"admin"`
CreatedBy string `width:"36" charset:"ascii" nullable:"false" default:"manual" list:"admin"`
Location string `charset:"ascii" nullable:"false" list:"admin"`
Size int `nullable:"false" list:"user"` // MB
OutOfChain bool `nullable:"false" default:"false" index:"true" get:"admin"`
FakeDeleted bool `nullable:"false" default:"false" index:"true"`
}
var SnapshotManager *SSnapshotManager
@@ -50,6 +51,19 @@ func (self *SSnapshot) AllowListItems(ctx context.Context, userCred mcclient.Tok
return self.IsOwner(userCred)
}
func (manager *SSnapshotManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
q, err := manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
if err != nil {
return nil, err
}
if jsonutils.QueryBoolean(query, "fake_deleted", false) {
q = q.Equals("fake_deleted", true)
} else {
q = q.Equals("fake_deleted", false)
}
return q, nil
}
func (self *SSnapshot) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return false
}
@@ -97,7 +111,7 @@ func (self *SSnapshotManager) GetDiskSnapshotsByCreate(diskId, createdBy string)
q := self.Query().SubQuery()
err := q.Query().Filter(sqlchemy.AND(sqlchemy.Equals(q.Field("disk_id"), diskId),
sqlchemy.Equals(q.Field("created_by"), createdBy),
sqlchemy.Equals(q.Field("pending_deleted"), false))).All(&dest)
sqlchemy.Equals(q.Field("fake_deleted"), false))).All(&dest)
if err != nil {
log.Errorf("GetDiskSnapshots error: %s", err)
return nil
@@ -139,7 +153,7 @@ func (self *SSnapshotManager) GetDiskFirstSnapshot(diskId string) *SSnapshot {
func (self *SSnapshotManager) GetDiskSnapshotCount(diskId string) int {
q := self.Query().SubQuery()
return q.Query().Filter(sqlchemy.AND(sqlchemy.Equals(q.Field("disk_id"), diskId),
sqlchemy.Equals(q.Field("pending_deleted"), false))).Count()
sqlchemy.Equals(q.Field("fake_deleted"), false))).Count()
}
func (self *SSnapshotManager) CreateSnapshot(ctx context.Context, userCred mcclient.TokenCredential, createdBy, diskId, guestId, location, name string) (*SSnapshot, error) {
@@ -187,8 +201,8 @@ func (self *SSnapshot) ValidateDeleteCondition(ctx context.Context) error {
func (self *SSnapshot) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
if self.CreatedBy == MANUAL {
if !self.PendingDeleted {
return self.SVirtualResourceBase.PendingDelete()
if !self.FakeDeleted {
return self.FakeDelete()
} else {
return self.StartSnapshotDeleteTask(ctx, userCred, false, "")
}
@@ -233,6 +247,8 @@ func (self *SSnapshotManager) GetConvertSnapshot(deleteSnapshot *SSnapshot) (*SS
if len(dest) == 2 && dest[0].Id == deleteSnapshot.Id {
dest[1].SetModelManager(self)
return &dest[1], nil
} else if len(dest) == 1 && dest[0].Id == deleteSnapshot.Id {
return nil, nil
}
return nil, fmt.Errorf("Snapshot %s cannot convert", deleteSnapshot.Id)
}
@@ -254,6 +270,11 @@ func (self *SSnapshotManager) PerformDeleteDiskSnapshots(ctx context.Context, us
if snapshots == nil || len(snapshots) == 0 {
return nil, httperrors.NewNotFoundError("Disk %s dose not have snapshot", diskId)
}
for i := 0; i < len(snapshots); i++ {
if snapshots[i].CreatedBy == MANUAL && snapshots[i].FakeDeleted == false {
return nil, httperrors.NewBadRequestError("Can not delete disk snapshots, have manual snapshot")
}
}
err = snapshots[0].StartSnapshotsDeleteTask(ctx, userCred, "")
return nil, err
}
@@ -273,6 +294,14 @@ func (self *SSnapshot) RealDelete(ctx context.Context, userCred mcclient.TokenCr
return db.DeleteModel(ctx, userCred, self)
}
func (self *SSnapshot) FakeDelete() error {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.FakeDeleted = true
return nil
})
return err
}
func (self *SSnapshot) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return nil
}
+39 -17
View File
@@ -2,6 +2,7 @@ package tasks
import (
"context"
"database/sql"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -109,12 +110,13 @@ func (self *SnapshotDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneMo
snapshot := obj.(*models.SSnapshot)
guest, err := snapshot.GetGuest()
if err != nil {
self.SetStageFailed(ctx, err.Error())
return
}
if guest == nil {
self.SetStageFailed(ctx, "Cannot delete without guest")
return
if err != sql.ErrNoRows {
self.SetStageFailed(ctx, err.Error())
return
} else {
self.DeleteStaticSnapshot(ctx, snapshot)
return
}
}
if jsonutils.QueryBoolean(self.Params, "reload_disk", false) && snapshot.OutOfChain {
self.StartReloadDisk(ctx, snapshot, guest)
@@ -140,16 +142,20 @@ func (self *SnapshotDeleteTask) StartDeleteSnapshot(ctx context.Context, snapsho
self.TaskFailed(ctx, snapshot, err.Error())
return
}
if convertSnapshot == nil {
self.TaskFailed(ctx, snapshot, "snapshot dose not have convert snapshot")
return
}
params := jsonutils.NewDict()
params.Set("delete_snapshot", jsonutils.NewString(snapshot.Id))
params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
if !snapshot.OutOfChain {
params.Set("convert_snapshot", jsonutils.NewString(convertSnapshot.Id))
var pendingDelete = jsonutils.JSONFalse
if snapshot.CreatedBy == models.MANUAL && snapshot.PendingDeleted == false {
pendingDelete = jsonutils.JSONTrue
var FakeDelete = jsonutils.JSONFalse
if snapshot.CreatedBy == models.MANUAL && snapshot.FakeDeleted == false {
FakeDelete = jsonutils.JSONTrue
}
params.Set("pending_delete", pendingDelete)
params.Set("pending_delete", FakeDelete)
} else {
params.Set("auto_deleted", jsonutils.JSONTrue)
}
@@ -162,6 +168,23 @@ func (self *SnapshotDeleteTask) StartDeleteSnapshot(ctx context.Context, snapsho
}
}
func (self *SnapshotDeleteTask) DeleteStaticSnapshot(ctx context.Context, snapshot *models.SSnapshot) {
// convertSnapshot, err := models.SnapshotManager.GetConvertSnapshot(snapshot)
// if err != nil {
// self.TaskFailed(ctx, snapshot, err.Error())
// return
// }
// if convertSnapshot == nil {
// self.TaskFailed(ctx, snapshot, "Snapshot dose not have convert snapshot")
// }
err := snapshot.FakeDelete()
if err != nil {
self.TaskFailed(ctx, snapshot, err.Error())
return
}
self.SetStageComplete(ctx, nil)
}
func (self *SnapshotDeleteTask) OnDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
if !jsonutils.QueryBoolean(data, "deleted", false) {
log.Infof("OnDeleteSnapshot with no deleted")
@@ -176,13 +199,12 @@ func (self *SnapshotDeleteTask) OnDeleteSnapshot(ctx context.Context, snapshot *
self.SetStageFailed(ctx, err.Error())
return
}
var pendingDelete = false
if snapshot.CreatedBy == models.MANUAL && snapshot.PendingDeleted == false &&
!jsonutils.QueryBoolean(self.Params, "force_delete", false) {
pendingDelete = true
var FakeDelete = false
if snapshot.CreatedBy == models.MANUAL && snapshot.FakeDeleted == false {
FakeDelete = true
}
if pendingDelete {
snapshot.PendingDelete()
if FakeDelete {
snapshot.FakeDelete()
} else {
snapshot.RealDelete(ctx, self.UserCred)
}
@@ -207,7 +229,7 @@ func (self *SnapshotDeleteTask) OnReloadDiskSnapshot(ctx context.Context, snapsh
return
}
} else {
err := snapshot.SVirtualResourceBase.PendingDelete()
err := snapshot.FakeDelete()
if err != nil {
self.TaskFailed(ctx, snapshot, err.Error())
return
+9
View File
@@ -351,6 +351,15 @@ func (this *ResourceManager) PerformActionInContexts(session *mcclient.ClientSes
return this._post(session, path, this.params2Body(params), this.Keyword)
}
func (this *ResourceManager) PerformClassAction(session *mcclient.ClientSession, action string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return this.PerformClassActionInContexts(session, action, params, nil)
}
func (this *ResourceManager) PerformClassActionInContexts(session *mcclient.ClientSession, action string, params jsonutils.JSONObject, ctxs []ManagerContext) (jsonutils.JSONObject, error) {
path := fmt.Sprintf("/%s/%s", this.ContextPath(ctxs), url.PathEscape(action))
return this._post(session, path, params, this.Keyword)
}
func (this *ResourceManager) BatchPerformAction(session *mcclient.ClientSession, idlist []string, action string, params jsonutils.JSONObject) []SubmitResult {
return this.BatchPerformActionInContexts(session, idlist, action, params, nil)
}