From 6db5f7831f937c788768605610d6c0ef89bbefad Mon Sep 17 00:00:00 2001 From: wanyaoqi Date: Tue, 23 Apr 2019 16:19:45 +0800 Subject: [PATCH] fix aliyun snapshot delete failed, delete linked images first --- pkg/compute/tasks/guest_disk_snapshot_task.go | 2 ++ pkg/util/aliyun/image.go | 19 +++++++++++++-- pkg/util/aliyun/shell/snapshot.go | 3 +++ pkg/util/aliyun/snapshot.go | 24 +++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/pkg/compute/tasks/guest_disk_snapshot_task.go b/pkg/compute/tasks/guest_disk_snapshot_task.go index a6a8b05c8f..a70b4e3741 100644 --- a/pkg/compute/tasks/guest_disk_snapshot_task.go +++ b/pkg/compute/tasks/guest_disk_snapshot_task.go @@ -317,6 +317,8 @@ func (self *SnapshotDeleteTask) TaskFailed(ctx context.Context, snapshot *models if snapshot.Status == api.SNAPSHOT_DELETING { snapshot.SetStatus(self.UserCred, api.SNAPSHOT_READY, "On SnapshotDeleteTask TaskFailed") } + db.OpsLog.LogEvent(snapshot, db.ACT_SNAPSHOT_DELETE_FAIL, reason, self.UserCred) + logclient.AddActionLogWithStartable(self, snapshot, logclient.ACT_DELOCATE, reason, self.UserCred, false) self.SetStageFailed(ctx, reason) guest, err := snapshot.GetGuest() if err != nil { diff --git a/pkg/util/aliyun/image.go b/pkg/util/aliyun/image.go index f1d3740d0d..01b8977a6a 100644 --- a/pkg/util/aliyun/image.go +++ b/pkg/util/aliyun/image.go @@ -278,7 +278,7 @@ func (self *SRegion) GetImage(imageId string) (*SImage, error) { return nil, err } if len(images) == 0 { - return nil, fmt.Errorf("image %s not found", imageId) + return nil, cloudprovider.ErrNotFound } return &images[0], nil } @@ -294,6 +294,19 @@ func (self *SRegion) GetImageByName(name string) (*SImage, error) { return &images[0], nil } +func (self *SRegion) GetImagesBySnapshot(snapshotId string, offset int, limit int) ([]SImage, int, error) { + if limit > 50 || limit <= 0 { + limit = 50 + } + params := make(map[string]string) + params["RegionId"] = self.RegionId + params["PageSize"] = fmt.Sprintf("%d", limit) + params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) + params["SnapshotId"] = snapshotId + + return self.getImages(params) +} + func (self *SRegion) GetImageStatus(imageId string) (ImageStatusType, error) { image, err := self.GetImage(imageId) if err != nil { @@ -327,8 +340,10 @@ func (self *SRegion) GetImages(status ImageStatusType, owner ImageOwnerType, ima params["ImageName"] = name } - // log.Debugf("%s", params) + return self.getImages(params) +} +func (self *SRegion) getImages(params map[string]string) ([]SImage, int, error) { body, err := self.ecsRequest("DescribeImages", params) if err != nil { log.Errorf("DescribeImages fail %s", err) diff --git a/pkg/util/aliyun/shell/snapshot.go b/pkg/util/aliyun/shell/snapshot.go index 548826ff25..5531eb6c0a 100644 --- a/pkg/util/aliyun/shell/snapshot.go +++ b/pkg/util/aliyun/shell/snapshot.go @@ -44,6 +44,9 @@ func init() { } shellutils.R(&SnapshotDeleteOptions{}, "snapshot-delete", "Delete snapshot", func(cli *aliyun.SRegion, args *SnapshotDeleteOptions) error { + if err := cli.SnapshotPreDelete(args.ID); err != nil { + return fmt.Errorf("Snapshot PreDelete error: %s", err) + } return cli.DeleteSnapshot(args.ID) }) diff --git a/pkg/util/aliyun/snapshot.go b/pkg/util/aliyun/snapshot.go index b3aff76c84..3e2327127e 100644 --- a/pkg/util/aliyun/snapshot.go +++ b/pkg/util/aliyun/snapshot.go @@ -15,7 +15,9 @@ package aliyun import ( + "context" "fmt" + "time" "yunion.io/x/jsonutils" "yunion.io/x/log" @@ -127,6 +129,9 @@ func (self *SSnapshot) Delete() error { if self.region == nil { return fmt.Errorf("not init region for snapshot %s", self.SnapshotId) } + if err := self.region.SnapshotPreDelete(self.SnapshotId); err != nil { + return err + } return self.region.DeleteSnapshot(self.SnapshotId) } @@ -197,3 +202,22 @@ func (self *SRegion) DeleteSnapshot(snapshotId string) error { func (self *SSnapshot) GetProjectId() string { return "" } + +// If snapshot linked images can't be delete +// delete images first -- Aliyun +func (self *SRegion) SnapshotPreDelete(snapshotId string) error { + images, _, err := self.GetImagesBySnapshot(snapshotId, 0, 0) + if err != nil { + return fmt.Errorf("PreDelete get images by snapshot %s error: %s", snapshotId, err) + } + for _, image := range images { + image.storageCache = &SStoragecache{region: self} + if err := image.Delete(context.Background()); err != nil { + return fmt.Errorf("PreDelete image %s error: %s", image.GetId(), err) + } + if err := cloudprovider.WaitDeleted(&image, 3*time.Second, 300*time.Second); err != nil { + return fmt.Errorf("PreDelete waite image %s deleted error: %s", image.GetId(), err) + } + } + return nil +}