diff --git a/pkg/apis/image/consts.go b/pkg/apis/image/consts.go index c154e1c840..e483f6fc03 100644 --- a/pkg/apis/image/consts.go +++ b/pkg/apis/image/consts.go @@ -26,6 +26,7 @@ const ( // IMAGE_STATUS_QUEUED = "queued" IMAGE_STATUS_SAVING = "saving" + IMAGE_STATUS_SAVE_FAIL = "save_fail" IMAGE_STATUS_ACTIVE = "active" IMAGE_STATUS_CONVERTING = "converting" diff --git a/pkg/image/models/image_subs.go b/pkg/image/models/image_subs.go index 9053d72ab2..23e00de038 100644 --- a/pkg/image/models/image_subs.go +++ b/pkg/image/models/image_subs.go @@ -244,7 +244,13 @@ func (self *SImageSubformat) RemoveFiles() error { return err } } - return RemoveImage(self.Location) + if err := RemoveImage(self.Location); err != nil { + if strings.Contains(err.Error(), "no such file or directory") { + return nil + } + return err + } + return nil } type SImageSubformatDetails struct { @@ -290,7 +296,7 @@ func (self *SImageSubformat) isTorrentActive() bool { return isActive(self.getLocalTorrentLocation(), self.TorrentSize, self.TorrentChecksum, "", false) } -func (self *SImageSubformat) setStatus(status string) error { +func (self *SImageSubformat) SetStatus(status string) error { _, err := db.Update(self, func() error { self.Status = status return nil @@ -310,7 +316,7 @@ func (self *SImageSubformat) checkStatus(useFast bool) { if strings.HasPrefix(self.Location, LocalFilePrefix) { if self.isActive(useFast) { if self.Status != api.IMAGE_STATUS_ACTIVE { - self.setStatus(api.IMAGE_STATUS_ACTIVE) + self.SetStatus(api.IMAGE_STATUS_ACTIVE) } if len(self.FastHash) == 0 { fastHash, err := fileutils2.FastCheckSum(self.GetLocalLocation()) @@ -328,7 +334,7 @@ func (self *SImageSubformat) checkStatus(useFast bool) { } } else { if self.Status != api.IMAGE_STATUS_QUEUED { - self.setStatus(api.IMAGE_STATUS_QUEUED) + self.SetStatus(api.IMAGE_STATUS_QUEUED) } } if self.isTorrentActive() { diff --git a/pkg/image/models/storage.go b/pkg/image/models/storage.go index 5f2d7ab656..b40d7f966f 100644 --- a/pkg/image/models/storage.go +++ b/pkg/image/models/storage.go @@ -80,6 +80,7 @@ func Init(storageBackend string) { } type Storage interface { + Type() string SaveImage(string) (string, error) CleanTempfile(string) error GetImage(string) (int64, io.ReadCloser, error) @@ -90,6 +91,10 @@ type Storage interface { type LocalStorage struct{} +func (s *LocalStorage) Type() string { + return "local" +} + func (s *LocalStorage) SaveImage(imagePath string) (string, error) { return fmt.Sprintf("%s%s", LocalFilePrefix, imagePath), nil } @@ -125,6 +130,10 @@ func imagePathToName(imagePath string) string { return segs[len(segs)-1] } +func (s *S3Storage) Type() string { + return "s3" +} + func (s *S3Storage) SaveImage(imagePath string) (string, error) { return s3.Put(imagePath, imagePathToName(imagePath)) } diff --git a/pkg/image/tasks/image_convert_task.go b/pkg/image/tasks/image_convert_task.go index 5b3f19287d..d7eee82c08 100644 --- a/pkg/image/tasks/image_convert_task.go +++ b/pkg/image/tasks/image_convert_task.go @@ -16,6 +16,7 @@ package tasks import ( "context" + "fmt" "strings" "yunion.io/x/jsonutils" @@ -72,9 +73,14 @@ func (self *PutImageTask) OnInit(ctx context.Context, obj db.IStandaloneModel, d if strings.HasPrefix(image.Location, models.LocalFilePrefix) { imagePath := image.GetLocalLocation() image.SetStatus(self.UserCred, api.IMAGE_STATUS_SAVING, "save image to specific storage") - location, err := models.GetStorage().SaveImage(imagePath) + storage := models.GetStorage() + location, err := storage.SaveImage(imagePath) if err != nil { log.Errorf("Failed save image to specific storage %s", err) + errStr := fmt.Sprintf("save image to storage %s: %v", storage.Type(), err) + image.SetStatus(self.UserCred, api.IMAGE_STATUS_SAVE_FAIL, errStr) + self.SetStageFailed(ctx, jsonutils.NewString(errStr)) + return } else if location != image.Location { _, err = db.Update(image, func() error { image.Location = location @@ -117,9 +123,14 @@ func (self *PutImageTask) OnInit(ctx context.Context, obj db.IStandaloneModel, d } } else { imagePath := subimgs[i].GetLocalLocation() + storage := models.GetStorage() location, err := models.GetStorage().SaveImage(imagePath) if err != nil { log.Errorf("Failed save image to sepcific storage %s", err) + errStr := fmt.Sprintf("save sub image %s to storage %s: %v", subimgs[i].Format, storage.Type(), err) + subimgs[i].SetStatus(api.IMAGE_STATUS_SAVE_FAIL) + self.SetStageFailed(ctx, jsonutils.NewString(errStr)) + return } else if subimgs[i].Location != location { _, err := db.Update(&subimgs[i], func() error { subimgs[i].Location = location