fix: 1. image status should be converting after upload 2. move consts to

apis 3. add image-event command
This commit is contained in:
Qiu Jian
2019-04-17 22:45:28 +08:00
parent 8d1cb49cc7
commit d89d17cfa5
7 changed files with 104 additions and 72 deletions
+9
View File
@@ -52,6 +52,10 @@ func doComputeEventList(s *mcclient.ClientSession, args *EventListOptions) error
return doEventList(modules.Logs, s, args)
}
func doImageEventList(s *mcclient.ClientSession, args *EventListOptions) error {
return doEventList(modules.ImageLogs, s, args)
}
func doEventList(man modules.ResourceManager, s *mcclient.ClientSession, args *EventListOptions) error {
params := jsonutils.NewDict()
if len(args.Type) > 0 {
@@ -158,4 +162,9 @@ func init() {
nargs := EventListOptions{BaseEventListOptions: args.BaseEventListOptions, Id: args.ID, Type: []string{"kubemachine"}}
return doK8sEventList(s, &nargs)
})
R(&TypeEventListOptions{}, "image-event", "Show operation event logs of glance images", func(s *mcclient.ClientSession, args *TypeEventListOptions) error {
nargs := EventListOptions{BaseEventListOptions: args.BaseEventListOptions, Id: args.ID, Type: []string{"image"}}
return doImageEventList(s, &nargs)
})
}
+26
View File
@@ -0,0 +1,26 @@
package image
type TImageType string
const (
// https://docs.openstack.org/glance/pike/user/statuses.html
//
IMAGE_STATUS_QUEUED = "queued"
IMAGE_STATUS_SAVING = "saving"
IMAGE_STATUS_ACTIVE = "active"
IMAGE_STATUS_CONVERTING = "converting"
IMAGE_STATUS_DEACTIVATED = "deactivated"
IMAGE_STATUS_KILLED = "killed"
IMAGE_STATUS_DELETED = "deleted"
IMAGE_STATUS_PENDING_DELETE = "pending_delete"
ImageTypeTemplate = TImageType("image")
ImageTypeISO = TImageType("iso")
LocalFilePrefix = "file://"
)
var (
ImageDeadStatus = []string{IMAGE_STATUS_DEACTIVATED, IMAGE_STATUS_KILLED, IMAGE_STATUS_DELETED, IMAGE_STATUS_PENDING_DELETE}
)
+17 -16
View File
@@ -22,6 +22,7 @@ import (
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/image"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/image/options"
"yunion.io/x/onecloud/pkg/image/torrent"
@@ -113,15 +114,15 @@ func (self *SImageSubformat) DoConvert(image *SImage) error {
}
func (self *SImageSubformat) Save(image *SImage) error {
if self.Status == IMAGE_STATUS_ACTIVE {
if self.Status == api.IMAGE_STATUS_ACTIVE {
return nil
}
if self.Status != IMAGE_STATUS_QUEUED {
if self.Status != api.IMAGE_STATUS_QUEUED {
return nil // httperrors.NewInvalidStatusError("cannot save in status %s", self.Status)
}
location := image.GetPath(self.Format)
_, err := db.Update(self, func() error {
self.Status = IMAGE_STATUS_SAVING
self.Status = api.IMAGE_STATUS_SAVING
self.Location = fmt.Sprintf("%s%s", LocalFilePrefix, location)
return nil
})
@@ -150,7 +151,7 @@ func (self *SImageSubformat) Save(image *SImage) error {
return err
}
_, err = db.Update(self, func() error {
self.Status = IMAGE_STATUS_ACTIVE
self.Status = api.IMAGE_STATUS_ACTIVE
self.Location = fmt.Sprintf("%s%s", LocalFilePrefix, location)
self.Checksum = checksum
self.FastHash = fastHash
@@ -165,16 +166,16 @@ func (self *SImageSubformat) Save(image *SImage) error {
}
func (self *SImageSubformat) SaveTorrent() error {
if self.TorrentStatus == IMAGE_STATUS_ACTIVE {
if self.TorrentStatus == api.IMAGE_STATUS_ACTIVE {
return nil
}
if self.TorrentStatus != IMAGE_STATUS_QUEUED {
if self.TorrentStatus != api.IMAGE_STATUS_QUEUED {
return nil // httperrors.NewInvalidStatusError("cannot save torrent in status %s", self.Status)
}
imgPath := self.getLocalLocation()
torrentPath := filepath.Join(options.Options.TorrentStoreDir, fmt.Sprintf("%s.torrent", filepath.Base(imgPath)))
_, err := db.Update(self, func() error {
self.TorrentStatus = IMAGE_STATUS_SAVING
self.TorrentStatus = api.IMAGE_STATUS_SAVING
self.TorrentLocation = fmt.Sprintf("%s%s", LocalFilePrefix, torrentPath)
return nil
})
@@ -193,7 +194,7 @@ func (self *SImageSubformat) SaveTorrent() error {
return err
}
_, err = db.Update(self, func() error {
self.TorrentStatus = IMAGE_STATUS_ACTIVE
self.TorrentStatus = api.IMAGE_STATUS_ACTIVE
self.TorrentLocation = fmt.Sprintf("%s%s", LocalFilePrefix, torrentPath)
self.TorrentChecksum = checksum
self.TorrentSize = fileutils2.FileSize(torrentPath)
@@ -312,8 +313,8 @@ func (self *SImageSubformat) setTorrentStatus(status string) error {
func (self *SImageSubformat) checkStatus(useFast bool) {
if self.isActive(useFast) {
if self.Status != IMAGE_STATUS_ACTIVE {
self.setStatus(IMAGE_STATUS_ACTIVE)
if self.Status != api.IMAGE_STATUS_ACTIVE {
self.setStatus(api.IMAGE_STATUS_ACTIVE)
}
if len(self.FastHash) == 0 {
fastHash, err := fileutils2.FastCheckSum(self.getLocalLocation())
@@ -330,17 +331,17 @@ func (self *SImageSubformat) checkStatus(useFast bool) {
}
}
} else {
if self.Status != IMAGE_STATUS_QUEUED {
self.setStatus(IMAGE_STATUS_QUEUED)
if self.Status != api.IMAGE_STATUS_QUEUED {
self.setStatus(api.IMAGE_STATUS_QUEUED)
}
}
if self.isTorrentActive() {
if self.TorrentStatus != IMAGE_STATUS_ACTIVE {
self.setTorrentStatus(IMAGE_STATUS_ACTIVE)
if self.TorrentStatus != api.IMAGE_STATUS_ACTIVE {
self.setTorrentStatus(api.IMAGE_STATUS_ACTIVE)
}
} else {
if self.TorrentStatus != IMAGE_STATUS_QUEUED {
self.setTorrentStatus(IMAGE_STATUS_QUEUED)
if self.TorrentStatus != api.IMAGE_STATUS_QUEUED {
self.setTorrentStatus(api.IMAGE_STATUS_QUEUED)
}
}
}
+34 -53
View File
@@ -33,6 +33,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/image"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
@@ -47,31 +48,10 @@ import (
"yunion.io/x/onecloud/pkg/util/streamutils"
)
type TImageType string
const (
// https://docs.openstack.org/glance/pike/user/statuses.html
//
IMAGE_STATUS_QUEUED = "queued"
IMAGE_STATUS_SAVING = "saving"
IMAGE_STATUS_ACTIVE = "active"
// IMAGE_STATUS_CONVERTING = "converting"
IMAGE_STATUS_DEACTIVATED = "deactivated"
IMAGE_STATUS_KILLED = "killed"
IMAGE_STATUS_DELETED = "deleted"
IMAGE_STATUS_PENDING_DELETE = "pending_delete"
ImageTypeTemplate = TImageType("image")
ImageTypeISO = TImageType("iso")
LocalFilePrefix = "file://"
)
var (
imageDeadStatus = []string{IMAGE_STATUS_DEACTIVATED, IMAGE_STATUS_KILLED, IMAGE_STATUS_DELETED, IMAGE_STATUS_PENDING_DELETE}
)
type SImageManager struct {
db.SSharableVirtualResourceBaseManager
}
@@ -212,7 +192,7 @@ func (self *SImage) CustomizedGetDetailsBody(ctx context.Context, userCred mccli
}
}
if status != IMAGE_STATUS_ACTIVE {
if status != api.IMAGE_STATUS_ACTIVE {
return nil, httperrors.NewInvalidStatusError("cannot download in status %s", status)
}
@@ -349,7 +329,7 @@ func (self *SImage) CustomizeCreate(ctx context.Context, userCred mcclient.Token
if err != nil {
return err
}
self.Status = IMAGE_STATUS_QUEUED
self.Status = api.IMAGE_STATUS_QUEUED
self.Owner = self.ProjectId
return nil
}
@@ -383,13 +363,14 @@ func (self *SImage) OnSaveTaskSuccess(task taskman.ITask, userCred mcclient.Toke
}
func (self *SImage) saveSuccess(userCred mcclient.TokenCredential, msg string) {
self.SetStatus(userCred, IMAGE_STATUS_ACTIVE, msg)
// do not set this status, until image converting complete
// self.SetStatus(userCred, api.IMAGE_STATUS_ACTIVE, msg)
db.OpsLog.LogEvent(self, db.ACT_SAVE, msg, userCred)
}
func (self *SImage) saveFailed(userCred mcclient.TokenCredential, msg string) {
log.Errorf(msg)
self.SetStatus(userCred, IMAGE_STATUS_QUEUED, msg)
self.SetStatus(userCred, api.IMAGE_STATUS_QUEUED, msg)
db.OpsLog.LogEvent(self, db.ACT_SAVE_FAIL, msg, userCred)
}
@@ -460,7 +441,7 @@ func (self *SImage) PostCreate(ctx context.Context, userCred mcclient.TokenCrede
appParams := appsrv.AppContextGetParams(ctx)
if appParams.Request.ContentLength > 0 {
db.OpsLog.LogEvent(self, db.ACT_SAVING, "create upload", userCred)
self.SetStatus(userCred, IMAGE_STATUS_SAVING, "create upload")
self.SetStatus(userCred, api.IMAGE_STATUS_SAVING, "create upload")
err := self.SaveImageFromStream(appParams.Request.Body)
if err != nil {
@@ -480,7 +461,7 @@ func (self *SImage) PostCreate(ctx context.Context, userCred mcclient.TokenCrede
}
func (self *SImage) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
if self.Status != IMAGE_STATUS_QUEUED {
if self.Status != api.IMAGE_STATUS_QUEUED {
appParams := appsrv.AppContextGetParams(ctx)
if appParams != nil && appParams.Request.ContentLength > 0 {
return nil, httperrors.NewInvalidStatusError("cannot upload in status %s", self.Status)
@@ -489,7 +470,7 @@ func (self *SImage) ValidateUpdateData(ctx context.Context, userCred mcclient.To
appParams := appsrv.AppContextGetParams(ctx)
if appParams != nil {
if appParams.Request.ContentLength > 0 {
self.SetStatus(userCred, IMAGE_STATUS_SAVING, "update start upload")
self.SetStatus(userCred, api.IMAGE_STATUS_SAVING, "update start upload")
err := self.SaveImageFromStream(appParams.Request.Body)
if err != nil {
self.OnSaveFailed(ctx, userCred, fmt.Sprintf("update upload failed %s", err))
@@ -570,8 +551,8 @@ func (self *SImage) CustomizeDelete(ctx context.Context, userCred mcclient.Token
purge = jsonutils.QueryBoolean(query, "purge", false)
}
if utils.IsInStringArray(self.Status, []string{
IMAGE_STATUS_KILLED,
IMAGE_STATUS_QUEUED,
api.IMAGE_STATUS_KILLED,
api.IMAGE_STATUS_QUEUED,
}) {
overridePendingDelete = true
}
@@ -588,7 +569,7 @@ func (self *SImage) startDeleteImageTask(ctx context.Context, userCred mcclient.
}
params.Add(jsonutils.NewString(self.Status), "image_status")
self.SetStatus(userCred, IMAGE_STATUS_DEACTIVATED, "")
self.SetStatus(userCred, api.IMAGE_STATUS_DEACTIVATED, "")
task, err := taskman.TaskManager.NewTask(ctx, "ImageDeleteTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
@@ -603,7 +584,7 @@ func (self *SImage) startImageCopyFromUrlTask(ctx context.Context, userCred mccl
params.Add(jsonutils.NewString(copyFrom), "copy_from")
msg := fmt.Sprintf("copy from url %s", copyFrom)
self.SetStatus(userCred, IMAGE_STATUS_SAVING, msg)
self.SetStatus(userCred, api.IMAGE_STATUS_SAVING, msg)
db.OpsLog.LogEvent(self, db.ACT_SAVING, msg, userCred)
task, err := taskman.TaskManager.NewTask(ctx, "ImageCopyFromUrlTask", self, userCred, params, parentTaskId, "", nil)
@@ -685,7 +666,7 @@ func (self *SImage) DoPendingDelete(ctx context.Context, userCred mcclient.Token
return err
}
_, err = db.Update(self, func() error {
self.Status = IMAGE_STATUS_PENDING_DELETE
self.Status = api.IMAGE_STATUS_PENDING_DELETE
return nil
})
return err
@@ -697,7 +678,7 @@ func (self *SImage) DoCancelPendingDelete(ctx context.Context, userCred mcclient
return err
}
_, err = db.Update(self, func() error {
self.Status = IMAGE_STATUS_ACTIVE
self.Status = api.IMAGE_STATUS_ACTIVE
return nil
})
return err
@@ -773,11 +754,11 @@ func expandUsageCount(usages map[string]int64, prefix, imgType, state string, co
func (manager *SImageManager) Usage(projectId string, prefix string) map[string]int64 {
usages := make(map[string]int64)
count := manager.count(projectId, IMAGE_STATUS_ACTIVE, tristate.False, false)
count := manager.count(projectId, api.IMAGE_STATUS_ACTIVE, tristate.False, false)
expandUsageCount(usages, prefix, "img", "", count)
count = manager.count(projectId, IMAGE_STATUS_ACTIVE, tristate.True, false)
count = manager.count(projectId, api.IMAGE_STATUS_ACTIVE, tristate.True, false)
expandUsageCount(usages, prefix, "iso", "", count)
count = manager.count(projectId, IMAGE_STATUS_ACTIVE, tristate.None, false)
count = manager.count(projectId, api.IMAGE_STATUS_ACTIVE, tristate.None, false)
expandUsageCount(usages, prefix, "imgiso", "", count)
count = manager.count(projectId, "", tristate.False, true)
expandUsageCount(usages, prefix, "img", "pending_delete", count)
@@ -788,11 +769,11 @@ func (manager *SImageManager) Usage(projectId string, prefix string) map[string]
return usages
}
func (self *SImage) GetImageType() TImageType {
func (self *SImage) GetImageType() api.TImageType {
if self.DiskFormat == string(qemuimg.ISO) {
return ImageTypeISO
return api.ImageTypeISO
} else {
return ImageTypeTemplate
return api.ImageTypeTemplate
}
}
@@ -807,13 +788,13 @@ func (self *SImage) newSubformat(format qemuimg.TImageFormat, migrate bool) erro
subformat.Size = self.Size
subformat.Checksum = self.Checksum
subformat.FastHash = self.FastHash
subformat.Status = IMAGE_STATUS_ACTIVE
subformat.Status = api.IMAGE_STATUS_ACTIVE
subformat.Location = self.Location
} else {
subformat.Status = IMAGE_STATUS_QUEUED
subformat.Status = api.IMAGE_STATUS_QUEUED
}
subformat.TorrentStatus = IMAGE_STATUS_QUEUED
subformat.TorrentStatus = api.IMAGE_STATUS_QUEUED
err := ImageSubformatManager.TableSpec().Insert(subformat)
if err != nil {
@@ -838,7 +819,7 @@ func (self *SImage) MigrateSubImage() error {
if err != nil {
return err
}
if self.GetImageType() != ImageTypeISO && imgInst.IsSparse() {
if self.GetImageType() != api.ImageTypeISO && imgInst.IsSparse() {
// need to convert again
return self.newSubformat(qemuimg.String2ImageFormat(self.DiskFormat), false)
} else {
@@ -863,7 +844,7 @@ func (self *SImage) MigrateSubImage() error {
}
func (self *SImage) MakeSubImages() error {
if self.GetImageType() == ImageTypeISO {
if self.GetImageType() == api.ImageTypeISO {
return nil
}
log.Debugf("[MakeSubImages] convert image to %#v", options.Options.TargetImageFormats)
@@ -945,7 +926,7 @@ func (self *SImage) RemoveFiles() error {
func (manager *SImageManager) getAllAliveImages() []SImage {
images := make([]SImage, 0)
q := manager.Query().NotIn("status", imageDeadStatus)
q := manager.Query().NotIn("status", api.ImageDeadStatus)
err := db.FetchModelObjects(manager, q, &images)
if err != nil {
log.Errorf("fail to query active images %s", err)
@@ -1026,12 +1007,12 @@ func (self *SImage) isActive(useFast bool) bool {
}
func (self *SImage) DoCheckStatus(ctx context.Context, userCred mcclient.TokenCredential, useFast bool) {
if utils.IsInStringArray(self.Status, imageDeadStatus) {
if utils.IsInStringArray(self.Status, api.ImageDeadStatus) {
return
}
if self.isActive(useFast) {
if self.Status != IMAGE_STATUS_ACTIVE {
self.SetStatus(userCred, IMAGE_STATUS_ACTIVE, "check active")
if self.Status != api.IMAGE_STATUS_ACTIVE {
self.SetStatus(userCred, api.IMAGE_STATUS_ACTIVE, "check active")
}
if len(self.FastHash) == 0 {
fastHash, err := fileutils2.FastCheckSum(self.getLocalLocation())
@@ -1066,8 +1047,8 @@ func (self *SImage) DoCheckStatus(ctx context.Context, userCred mcclient.TokenCr
log.Warningf("fail to check image size of %s(%s)", self.Id, self.Name)
}
} else {
if self.Status != IMAGE_STATUS_QUEUED {
self.SetStatus(userCred, IMAGE_STATUS_QUEUED, "check inactive")
if self.Status != api.IMAGE_STATUS_QUEUED {
self.SetStatus(userCred, api.IMAGE_STATUS_QUEUED, "check inactive")
}
}
needConvert := false
@@ -1077,11 +1058,11 @@ func (self *SImage) DoCheckStatus(ctx context.Context, userCred mcclient.TokenCr
}
for i := 0; i < len(subimgs); i += 1 {
subimgs[i].checkStatus(useFast)
if (subimgs[i].Status != IMAGE_STATUS_ACTIVE || subimgs[i].TorrentStatus != IMAGE_STATUS_ACTIVE) && utils.IsInStringArray(subimgs[i].Format, options.Options.TargetImageFormats) {
if (subimgs[i].Status != api.IMAGE_STATUS_ACTIVE || subimgs[i].TorrentStatus != api.IMAGE_STATUS_ACTIVE) && utils.IsInStringArray(subimgs[i].Format, options.Options.TargetImageFormats) {
needConvert = true
}
}
if self.Status == IMAGE_STATUS_ACTIVE {
if self.Status == api.IMAGE_STATUS_ACTIVE {
if needConvert {
log.Infof("Image %s is active and need convert", self.Name)
self.StartImageConvertTask(ctx, userCred, "")
+12 -2
View File
@@ -16,9 +16,11 @@ package tasks
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/image"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
@@ -39,9 +41,17 @@ func (self *ImageConvertTask) OnInit(ctx context.Context, obj db.IStandaloneMode
self.SetStage("OnConvertComplete", nil)
taskman.LocalTaskRun(self, func() (jsonutils.JSONObject, error) {
// image.SetStatus(self.UserCred, models.IMAGE_STATUS_CONVERTING, "start convert")
// defer image.SetStatus(self.UserCred, models.IMAGE_STATUS_ACTIVE, "convert failed")
image.SetStatus(self.UserCred, api.IMAGE_STATUS_CONVERTING, "start convert")
err := image.ConvertAllSubformats()
var msg string
if err != nil {
msg = fmt.Sprintf("convert failed: %s", err)
} else {
msg = fmt.Sprintf("convert success")
}
image.SetStatus(self.UserCred, api.IMAGE_STATUS_ACTIVE, msg)
return nil, err
})
}
+2 -1
View File
@@ -21,6 +21,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/image"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/image/models"
@@ -69,7 +70,7 @@ func (self *ImageDeleteTask) startDeleteImage(ctx context.Context, image *models
return
}
image.SetStatus(self.UserCred, models.IMAGE_STATUS_DELETED, "delete")
image.SetStatus(self.UserCred, api.IMAGE_STATUS_DELETED, "delete")
image.RealDelete(ctx, self.UserCred)
+4
View File
@@ -601,6 +601,7 @@ func (this *SImageUsageManager) GetUsage(session *mcclient.ClientSession, params
var (
ImageUsages SImageUsageManager
ImageLogs ResourceManager
)
func init() {
@@ -608,5 +609,8 @@ func init() {
[]string{},
[]string{})}
ImageLogs = NewImageManager("event", "events",
[]string{"id", "ops_time", "obj_id", "obj_type", "obj_name", "user", "user_id", "tenant", "tenant_id", "owner_tenant_id", "action", "notes"},
[]string{})
// register(&ImageUsages)
}