mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #13631 from rainzm/instancebackup/force_delete
Instancebackup force delete
This commit is contained in:
@@ -34,7 +34,7 @@ func init() {
|
||||
dbCmd := shell.NewResourceCmd(&modules.DiskBackups)
|
||||
dbCmd.List(&compute.DiskBackupListOptions{})
|
||||
dbCmd.Show(&compute.DiskBackupIdOptions{})
|
||||
dbCmd.Delete(&compute.DiskBackupIdOptions{})
|
||||
dbCmd.DeleteWithParam(&compute.DiskBackupDeleteOptions{})
|
||||
dbCmd.Create(&compute.DiskBackupCreateOptions{})
|
||||
dbCmd.Perform("recovery", &compute.DiskBackupRecoveryOptions{})
|
||||
dbCmd.Perform("syncstatus", &compute.DiskBackupSyncstatusOptions{})
|
||||
@@ -42,7 +42,7 @@ func init() {
|
||||
ibCmd := shell.NewResourceCmd(&modules.InstanceBackups)
|
||||
ibCmd.List(&compute.InstanceBackupListOptions{})
|
||||
ibCmd.Show(&compute.InstanceBackupIdOptions{})
|
||||
ibCmd.Delete(&compute.InstanceBackupIdOptions{})
|
||||
ibCmd.DeleteWithParam(&compute.InstanceBackupDeleteOptions{})
|
||||
ibCmd.Perform("recovery", &compute.InstanceBackupRecoveryOptions{})
|
||||
ibCmd.Perform("pack", &compute.InstanceBackupPackOptions{})
|
||||
ibCmd.PerformClass("create-from-package", &compute.InstanceBackupManagerCreateFromPackageOptions{})
|
||||
|
||||
@@ -362,6 +362,32 @@ func (cmd ResourceCmd) Delete(args IDeleteOpt) {
|
||||
cmd.RunWithDesc("delete", fmt.Sprintf("Delete %s", man.GetKeyword()), args, callback)
|
||||
}
|
||||
|
||||
type IDeleteWithParamOpt interface {
|
||||
IDeleteOpt
|
||||
QueryParams() (jsonutils.JSONObject, error)
|
||||
}
|
||||
|
||||
func (cmd ResourceCmd) DeleteWithParam(args IDeleteWithParamOpt) {
|
||||
man := cmd.manager
|
||||
callback := func(s *mcclient.ClientSession, args IDeleteWithParamOpt) error {
|
||||
queryParams, err := args.QueryParams()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := man.(modulebase.Manager).DeleteWithParam(s, args.GetId(), queryParams, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
PrintObject(ret)
|
||||
return nil
|
||||
}
|
||||
cmd.RunWithDesc("delete", fmt.Sprintf("Delete %s", man.GetKeyword()), args, callback)
|
||||
}
|
||||
|
||||
type IWithDescOpt interface {
|
||||
Description() string
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ const (
|
||||
BACKUP_NOT_EXIST = "not_exist"
|
||||
)
|
||||
|
||||
const (
|
||||
BackupStorageOffline = "backup storage offline"
|
||||
)
|
||||
|
||||
type BackupStorageCreateInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseCreateInput
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
@@ -221,10 +222,23 @@ func (dm *SDiskBackupManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if disk.Status != api.DISK_READY {
|
||||
return input, httperrors.NewInvalidStatusError("disk %s status is not %s", disk.Name, api.DISK_READY)
|
||||
}
|
||||
_, err = validators.ValidateModel(userCred, BackupStorageManager, &input.BackupStorageId)
|
||||
ibs, err := BackupStorageManager.FetchByIdOrName(userCred, input.BackupStorageId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return input, httperrors.NewResourceNotFoundError2(BackupStorageManager.Keyword(), input.BackupStorageId)
|
||||
}
|
||||
if errors.Cause(err) == sqlchemy.ErrDuplicateEntry {
|
||||
return input, httperrors.NewDuplicateResourceError(BackupStorageManager.Keyword(), input.BackupStorageId)
|
||||
}
|
||||
return input, httperrors.NewGeneralError(err)
|
||||
}
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
bs := ibs.(*SBackupStorage)
|
||||
if bs.Status != api.BACKUPSTORAGE_STATUS_ONLINE {
|
||||
return input, httperrors.NewForbiddenError("can't backup guest to backup storage with status %s", bs.Status)
|
||||
}
|
||||
storage, err := disk.GetStorage()
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "unable to get storage of disk %s", disk.GetId())
|
||||
@@ -356,13 +370,18 @@ func (self *SDiskBackup) RealDelete(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
|
||||
func (self *SDiskBackup) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return self.StartBackupDeleteTask(ctx, userCred, "")
|
||||
forceDelete := jsonutils.QueryBoolean(query, "force", false)
|
||||
return self.StartBackupDeleteTask(ctx, userCred, "", forceDelete)
|
||||
}
|
||||
|
||||
func (self *SDiskBackup) StartBackupDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
func (self *SDiskBackup) StartBackupDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, forceDelete bool) error {
|
||||
self.SetStatus(userCred, api.BACKUP_STATUS_DELETING, "")
|
||||
log.Infof("start to delete diskbackup %s and set deleting", self.GetId())
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DiskBackupDeleteTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
params := jsonutils.NewDict()
|
||||
if forceDelete {
|
||||
params.Set("force_delete", jsonutils.JSONTrue)
|
||||
}
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DiskBackupDeleteTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
|
||||
@@ -4748,9 +4748,19 @@ func (self *SGuest) PerformInstanceBackup(ctx context.Context, userCred mcclient
|
||||
if backupStorageId == "" {
|
||||
return nil, httperrors.NewMissingParameterError("backup_storage_id")
|
||||
}
|
||||
_, err = BackupStorageManager.FetchById(backupStorageId)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewInputParameterError("unkown backup_storage_id %s", backupStorageId)
|
||||
ibs, err := BackupStorageManager.FetchByIdOrName(userCred, backupStorageId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(BackupStorageManager.Keyword(), backupStorageId)
|
||||
}
|
||||
if errors.Cause(err) == sqlchemy.ErrDuplicateEntry {
|
||||
return nil, httperrors.NewDuplicateResourceError(BackupStorageManager.Keyword(), backupStorageId)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
bs := ibs.(*SBackupStorage)
|
||||
if bs.Status != api.BACKUPSTORAGE_STATUS_ONLINE {
|
||||
return nil, httperrors.NewForbiddenError("can't backup guest to backup storage with status %s", bs.Status)
|
||||
}
|
||||
instanceBackup, err := InstanceBackupManager.CreateInstanceBackup(ctx, userCred, self, name, backupStorageId)
|
||||
if err != nil {
|
||||
|
||||
@@ -376,14 +376,17 @@ func (self *SInstanceBackup) ValidateDeleteCondition(ctx context.Context, info j
|
||||
func (self *SInstanceBackup) CustomizeDelete(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
|
||||
return self.StartInstanceBackupDeleteTask(ctx, userCred, "")
|
||||
forceDelete := jsonutils.QueryBoolean(query, "force", false)
|
||||
return self.StartInstanceBackupDeleteTask(ctx, userCred, "", forceDelete)
|
||||
}
|
||||
|
||||
func (self *SInstanceBackup) StartInstanceBackupDeleteTask(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "InstanceBackupDeleteTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, forceDelete bool) error {
|
||||
params := jsonutils.NewDict()
|
||||
if forceDelete {
|
||||
params.Set("force_delete", jsonutils.JSONTrue)
|
||||
}
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "InstanceBackupDeleteTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
|
||||
@@ -1056,7 +1056,8 @@ func (self *SKVMRegionDriver) RequestDeleteInstanceBackup(ctx context.Context, i
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("del_backup_id", jsonutils.NewString(backups[0].Id))
|
||||
task.SetStage("OnKvmDiskBackupDelete", params)
|
||||
err = backups[0].StartBackupDeleteTask(ctx, task.GetUserCred(), task.GetTaskId())
|
||||
forceDelete := jsonutils.QueryBoolean(task.GetParams(), "force_delete", false)
|
||||
err = backups[0].StartBackupDeleteTask(ctx, task.GetUserCred(), task.GetTaskId(), forceDelete)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -16,8 +16,10 @@ package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -64,5 +66,15 @@ func (self *DiskBackupDeleteTask) OnDelete(ctx context.Context, backup *models.S
|
||||
}
|
||||
|
||||
func (self *DiskBackupDeleteTask) OnDeleteFailed(ctx context.Context, backup *models.SDiskBackup, data jsonutils.JSONObject) {
|
||||
self.taskFailed(ctx, backup, data)
|
||||
log.Infof("params: %s", self.Params)
|
||||
log.Infof("OnDeleteFailed data: %s", data)
|
||||
if forceDelete := jsonutils.QueryBoolean(self.Params, "force_delete", false); !forceDelete {
|
||||
self.taskFailed(ctx, backup, data)
|
||||
}
|
||||
reason, _ := data.GetString("__reason__")
|
||||
if !strings.Contains(reason, api.BackupStorageOffline) {
|
||||
self.taskFailed(ctx, backup, data)
|
||||
}
|
||||
log.Infof("delete backup %s failed, force delete", backup.GetId())
|
||||
self.taskSuccess(ctx, backup, nil)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import (
|
||||
|
||||
const BackupStoragePath = "/opt/cloud/workspace/backupstorage"
|
||||
|
||||
var ErrorBackupStorageOffline error = errors.Error("backup storage offline")
|
||||
var ErrorBackupStorageOffline error = errors.Error(api.BackupStorageOffline)
|
||||
|
||||
type SNFSBackupStorage struct {
|
||||
BackupStorageId string
|
||||
|
||||
@@ -43,6 +43,15 @@ func (opts *DiskBackupIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type DiskBackupDeleteOptions struct {
|
||||
DiskBackupIdOptions
|
||||
Force bool `help:"force delete"`
|
||||
}
|
||||
|
||||
func (opts *DiskBackupDeleteOptions) QueryParams() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type DiskBackupCreateOptions struct {
|
||||
options.BaseCreateOptions
|
||||
DISKID string `help:"disk id" json:"disk_id"`
|
||||
@@ -121,7 +130,7 @@ func (opts *InstanceBackupListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
}
|
||||
|
||||
type InstanceBackupIdOptions struct {
|
||||
ID string `help:"instance backup id"`
|
||||
ID string `help:"instance backup id" json:"-"`
|
||||
}
|
||||
|
||||
func (opts *InstanceBackupIdOptions) GetId() string {
|
||||
@@ -132,6 +141,15 @@ func (opts *InstanceBackupIdOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type InstanceBackupDeleteOptions struct {
|
||||
InstanceBackupIdOptions
|
||||
Force bool `help:"force delete"`
|
||||
}
|
||||
|
||||
func (opts *InstanceBackupDeleteOptions) QueryParams() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type InstanceBackupRecoveryOptions struct {
|
||||
DiskBackupIdOptions
|
||||
Name string `help:"server name" json:"name"`
|
||||
|
||||
Reference in New Issue
Block a user