From 86b3b38f41362b81994aee7c108fa13fc37ca4b6 Mon Sep 17 00:00:00 2001 From: wanyaoqi Date: Tue, 11 Dec 2018 20:31:36 +0800 Subject: [PATCH] add snapshot reference count, fix code --- pkg/appsrv/response.go | 3 +-- pkg/compute/models/disks.go | 9 ++++++--- pkg/compute/models/guest_actions.go | 17 ++++++++++++++++- pkg/compute/models/guestdisks.go | 6 ++++++ pkg/compute/models/guests.go | 1 - pkg/compute/models/snapshots.go | 17 +++++++++++++++++ pkg/compute/tasks/disk_delete_task.go | 3 +++ pkg/compute/tasks/guest_create_disk_task.go | 1 - pkg/hostimage/host_image_service.go | 1 - 9 files changed, 49 insertions(+), 9 deletions(-) diff --git a/pkg/appsrv/response.go b/pkg/appsrv/response.go index ac611719af..89e64a49ce 100644 --- a/pkg/appsrv/response.go +++ b/pkg/appsrv/response.go @@ -2,9 +2,8 @@ package appsrv import ( "context" - "net/http" - "fmt" + "net/http" "yunion.io/x/onecloud/pkg/httperrors" ) diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index f80c298bd5..a95aae1ff8 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -100,6 +100,9 @@ type SDisk struct { // # backing template id and type TemplateId string `width:"256" charset:"ascii" nullable:"true" list:"user"` // Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=True) + // backing snapshot id + SnapshotId string `width:"256" charset:"ascii" nullable:"true" list:"user"` + // # file system FsFormat string `width:"32" charset:"ascii" nullable:"true" list:"user"` // Column(VARCHAR(32, charset='ascii'), nullable=True) // # disk type, OS, SWAP, DAT @@ -446,6 +449,8 @@ func (self *SDisk) StartAllocate(ctx context.Context, host *SHost, storage *SSto content.Add(jsonutils.NewInt(int64(self.DiskSize)), "size") if len(snapshot) > 0 { content.Add(jsonutils.NewString(snapshot), "snapshot") + SnapshotManager.AddRefCount(self.SnapshotId, 1) + self.SetMetadata(ctx, "merge_snapshot", jsonutils.JSONTrue, userCred) } else if len(templateId) > 0 { content.Add(jsonutils.NewString(templateId), "image_id") } @@ -1078,7 +1083,6 @@ func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info } else if strings.HasPrefix(p, "snapshot-") { // HACK: use snapshot creat disk format snapshot-id // example: snapshot-3140cecb-ccc4-4865-abae-3a5ba8c69d9b - log.Errorln("The snapshot XXXXXXX Create disk", p[len("snapshot-"):]) if err := fillDiskConfigBySnapshot(userCred, &diskConfig, p[len("snapshot-"):]); err != nil { return nil, err } @@ -1167,8 +1171,7 @@ func (self *SDisk) fetchDiskInfo(diskConfig *SDiskConfig) { self.TemplateId = diskConfig.ImageId self.DiskType = DISK_TYPE_SYS } else if len(diskConfig.SnapshotId) > 0 { - // XXX: HACK reuse template id as snapshot id - // self.TemplateId = "snapshot-" + diskConfig.SnapshotId + self.SnapshotId = diskConfig.SnapshotId self.DiskType = diskConfig.DiskType } if len(diskConfig.Fs) > 0 { diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 19f0397e3e..dac61120c5 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -8,6 +8,7 @@ import ( "net/http" "strconv" "strings" + "time" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" @@ -22,7 +23,6 @@ import ( "yunion.io/x/onecloud/pkg/util/logclient" "yunion.io/x/onecloud/pkg/util/seclib2" - "time" "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/onecloud/pkg/util/billing" @@ -2112,3 +2112,18 @@ func (self *SGuest) doSaveRenewInfo(userCred mcclient.TokenCredential, bc *billi db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(), userCred) return nil } + +func (self *SGuest) AllowPerformStreamDisksComplete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return db.IsAdminAllowPerform(userCred, self, "stream-disks-complete") +} + +func (self *SGuest) PerformStreamDisksComplete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + for _, disk := range self.GetDisks() { + d := disk.GetDisk() + if len(d.SnapshotId) > 0 { + SnapshotManager.AddRefCount(d.SnapshotId, -1) + d.SetMetadata(ctx, "merge_snapshot", jsonutils.JSONFalse, userCred) + } + } + return nil, nil +} diff --git a/pkg/compute/models/guestdisks.go b/pkg/compute/models/guestdisks.go index ab86de0496..e6000e0917 100644 --- a/pkg/compute/models/guestdisks.go +++ b/pkg/compute/models/guestdisks.go @@ -166,6 +166,12 @@ func (self *SGuestdisk) GetJsonDescAtHost(host *SHost) jsonutils.JSONObject { if len(tid) > 0 { desc.Add(jsonutils.NewString(tid), "template_id") } + if len(disk.SnapshotId) > 0 { + needMerge := disk.GetMetadata("merge_snapshot", nil) + if needMerge == "true" { + desc.Set("merge_snapshot", jsonutils.JSONTrue) + } + } fs := disk.GetFsFormat() if len(fs) > 0 { desc.Add(jsonutils.NewString(fs), "fs") diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index de39aae35e..1420bcc813 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -2350,7 +2350,6 @@ func (self *SGuest) CreateDisksOnHost(ctx context.Context, userCred mcclient.Tok return err } data.Add(jsonutils.NewString(disk.Id), fmt.Sprintf("disk.%d.id", idx)) - log.Errorln("CreateDisksOnHost XXXXXXXXXX", diskConfig.SnapshotId) if len(diskConfig.SnapshotId) > 0 { data.Add(jsonutils.NewString(diskConfig.SnapshotId), fmt.Sprintf("disk.%d.snapshot", idx)) } diff --git a/pkg/compute/models/snapshots.go b/pkg/compute/models/snapshots.go index ed9c81a6c4..2a68fdc766 100644 --- a/pkg/compute/models/snapshots.go +++ b/pkg/compute/models/snapshots.go @@ -49,6 +49,9 @@ type SSnapshot struct { FakeDeleted bool `nullable:"false" default:"false" index:"true"` DiskType string `width:"32" charset:"ascii" nullable:"true" list:"user"` + // create disk from snapshot, snapshot as disk backing file + RefCount int `nullable:"false" default:"0" list:"user"` + CloudregionId string `width:"36" charset:"ascii" nullable:"true" list:"user"` } @@ -246,6 +249,17 @@ func (self *SSnapshot) GetHost() *SHost { return storage.GetMasterHost() } +func (self *SSnapshotManager) AddRefCount(snapshotId string, count int) { + iSnapshot, _ := self.FetchById(snapshotId) + snapshot := iSnapshot.(*SSnapshot) + if snapshot != nil { + self.TableSpec().Update(snapshot, func() error { + snapshot.RefCount += count + return nil + }) + } +} + func (self *SSnapshotManager) GetDiskSnapshotsByCreate(diskId, createdBy string) []SSnapshot { dest := make([]SSnapshot, 0) q := self.Query().SubQuery() @@ -343,6 +357,9 @@ func (self *SSnapshot) StartSnapshotDeleteTask(ctx context.Context, userCred mcc } func (self *SSnapshot) ValidateDeleteCondition(ctx context.Context) error { + if self.RefCount > 0 { + return fmt.Errorf("Snapshot reference(by disk) count > 0, can not delete") + } return nil } diff --git a/pkg/compute/tasks/disk_delete_task.go b/pkg/compute/tasks/disk_delete_task.go index 3eac8a0371..ea433d2204 100644 --- a/pkg/compute/tasks/disk_delete_task.go +++ b/pkg/compute/tasks/disk_delete_task.go @@ -93,6 +93,9 @@ func (self *DiskDeleteTask) OnGuestDiskDeleteComplete(ctx context.Context, obj d disk := obj.(*models.SDisk) self.CleanHostSchedCache(disk) db.OpsLog.LogEvent(disk, db.ACT_DELOCATE, disk.GetShortDesc(), self.UserCred) + if len(disk.SnapshotId) > 0 && disk.GetMetadata("merge_snapshot", nil) == "true" { + models.SnapshotManager.AddRefCount(disk.SnapshotId, -1) + } disk.RealDelete(ctx, self.UserCred) self.SetStageComplete(ctx, nil) } diff --git a/pkg/compute/tasks/guest_create_disk_task.go b/pkg/compute/tasks/guest_create_disk_task.go index 264689b650..2b9181df40 100644 --- a/pkg/compute/tasks/guest_create_disk_task.go +++ b/pkg/compute/tasks/guest_create_disk_task.go @@ -67,7 +67,6 @@ func (self *KVMGuestCreateDiskTask) OnKvmDiskPrepared(ctx context.Context, obj d disk := iDisk.(*models.SDisk) if disk.Status == models.DISK_INIT { snapshotId, _ := self.Params.GetString(fmt.Sprintf("disk.%d.snapshot", diskIndex)) - log.Errorln("XXXXXXXXXXXXXX", snapshotId) err = disk.StartDiskCreateTask(ctx, self.UserCred, false, snapshotId, self.GetTaskId()) if err != nil { self.SetStageFailed(ctx, err.Error()) diff --git a/pkg/hostimage/host_image_service.go b/pkg/hostimage/host_image_service.go index fb8a2846f6..1b04b596be 100644 --- a/pkg/hostimage/host_image_service.go +++ b/pkg/hostimage/host_image_service.go @@ -73,7 +73,6 @@ func inputCheck(ctx context.Context) (string, error) { var userCred = auth.FetchUserCredential(ctx, nil) if !userCred.HasSystemAdminPrivelege() { return "", httperrors.NewForbiddenError("System admin only") - } var params = appctx.AppContextParams(ctx)