From 31146aa5ec84c6a931050c375735fcb8f6196cd7 Mon Sep 17 00:00:00 2001 From: Rain Date: Tue, 24 Sep 2019 10:12:28 +0800 Subject: [PATCH] fix log for snapshotpolicy docs auto sync add performCache for snapshotpolicy detach snapshotpolicy after detach disk and guest fix sync snapshot of disk in qcloud --- cmd/climc/shell/disks.go | 2 + cmd/climc/shell/snapshot_policy.go | 20 +++ docs/index.yaml | 2 + docs/parameters/disk.yaml | 6 + docs/schemas/snapshotpolicy.yaml | 15 +++ docs/snapshotpolicy/cache.yaml | 17 +++ pkg/cloudcommon/db/opslog.go | 8 ++ pkg/compute/models/disks.go | 114 +++++++++++++++++- pkg/compute/models/snapshotpolicy.go | 32 ++++- pkg/compute/models/snapshotpolicydisks.go | 16 ++- pkg/compute/regiondrivers/managedvirtual.go | 16 ++- pkg/compute/regiondrivers/qcloud.go | 4 +- pkg/compute/service/service.go | 1 + .../tasks/disk_clean_overdued_snapshots.go | 2 +- pkg/compute/tasks/guest_detach_disk_task.go | 8 ++ pkg/compute/tasks/snapshotpolicy_disk_task.go | 44 +++++-- pkg/multicloud/qcloud/snapshot.go | 2 +- pkg/util/logclient/consts.go | 2 + 18 files changed, 279 insertions(+), 32 deletions(-) create mode 100644 docs/snapshotpolicy/cache.yaml diff --git a/cmd/climc/shell/disks.go b/cmd/climc/shell/disks.go index 51789e815e..720b0850cb 100644 --- a/cmd/climc/shell/disks.go +++ b/cmd/climc/shell/disks.go @@ -34,6 +34,8 @@ func init() { CloudType string `help:"Public cloud or private cloud" choices:"Public|Private"` BillingType string `help:"billing type" choices:"postpaid|prepaid"` + + SnapshotpolicyId string `help:"snapshotpolicy id"` } R(&DiskListOptions{}, "disk-list", "List virtual disks", func(s *mcclient.ClientSession, opts *DiskListOptions) error { params, err := options.ListStructToParams(opts) diff --git a/cmd/climc/shell/snapshot_policy.go b/cmd/climc/shell/snapshot_policy.go index 0f5a3f6532..6ba5e36f5b 100644 --- a/cmd/climc/shell/snapshot_policy.go +++ b/cmd/climc/shell/snapshot_policy.go @@ -101,4 +101,24 @@ func init() { printObject(sp) return nil }) + + type SnapshotPolicyCacheOptions struct { + ID string `help:"SnasphotPolicy ID"` + REGIONID string `help:"Region ID"` + PROVIDER string `help:"Provider ID"` + } + R(&SnapshotPolicyCacheOptions{}, "snapshot-policy-cache", "upload local snapshotpolicy to cloud", + func(s *mcclient.ClientSession, opts *SnapshotPolicyCacheOptions) error { + params, err := options.StructToParams(opts) + if err != nil { + return err + } + sp, err := modules.SnapshotPoliciy.PerformAction(s, opts.ID, "cache", params) + if err != nil { + return err + } + printObject(sp) + return nil + }, + ) } diff --git a/docs/index.yaml b/docs/index.yaml index c12a3f682c..77587b961e 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -279,6 +279,8 @@ paths: $ref: "./snapshotpolicy/bind-disk.yaml" /snapshotpolicies/{snapshotpolicyId}/unbind-disks: $ref: "./snapshotpolicy/unbind-disk.yaml" + /snapshotpolicies/{snapshotpolicyId}/cache: + $ref: "./snapshotpolicy/cache.yaml" /loadbalancers: $ref: "./loadbalancer/loadbalancers.yaml" diff --git a/docs/parameters/disk.yaml b/docs/parameters/disk.yaml index 52bea145c3..7fa8dba7e1 100644 --- a/docs/parameters/disk.yaml +++ b/docs/parameters/disk.yaml @@ -48,4 +48,10 @@ cloud_type: type: string enum: [Public,Private] description: 列出公有云或私有云的磁盘 +snapshotpolicy_id: + name: snapshotpolicy_id + required: false + in: query + type: string + description: 列出绑定了此快照策略的磁盘 diff --git a/docs/schemas/snapshotpolicy.yaml b/docs/schemas/snapshotpolicy.yaml index 1c75dc3bf2..c650b97815 100644 --- a/docs/schemas/snapshotpolicy.yaml +++ b/docs/schemas/snapshotpolicy.yaml @@ -189,3 +189,18 @@ SnapshotPolicyBindDisk: type: string example: dd100399-79ef-43a3-8fc3-23adc74b8b87 description: 待绑定的disk的ID + +SnapshotPolicyCache: + type: object + required: + - region_id + - provider_id + properties: + region_id: + type: string + example: d2ea8591-68b2-4066-802d-c896d1828417 + description: Region ID + provider_id: + type: string + example: 42fde9ca-8642-4318-8c84-2ead0bdc78d2 + description: Provider ID diff --git a/docs/snapshotpolicy/cache.yaml b/docs/snapshotpolicy/cache.yaml new file mode 100644 index 0000000000..e524c50377 --- /dev/null +++ b/docs/snapshotpolicy/cache.yaml @@ -0,0 +1,17 @@ +post: + summary: 将本地的自动快照策略同步到云上 + parameters: + - $ref: '../parameters/snapshotpolicy.yaml#/snapshotpolicyId' + - in: body + name: snapshotpolicy + required: true + schema: + $ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyCache' + responses: + 200: + description: 自动快照策略 + schema: + $ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyResponse' + tags: + - snapshotpolicy + diff --git a/pkg/cloudcommon/db/opslog.go b/pkg/cloudcommon/db/opslog.go index d137f948ef..d73daf7872 100644 --- a/pkg/cloudcommon/db/opslog.go +++ b/pkg/cloudcommon/db/opslog.go @@ -104,11 +104,19 @@ const ( ACT_CANCEL_SNAPSHOT_POLICY = "cancel_snapshot_policy" ACT_CANCEL_SNAPSHOT_POLICY_FAILED = "cancel_snapshot_policy_failed" + ACT_SNAPSHOT_POLICY_BIND_DISK = "snapshot_policy_bind_disk" + ACT_SNAPSHOT_POLICY_BIND_DISK_FAIL = "snapshot_policy_bind_disk_fail" + ACT_SNAPSHOT_POLICY_UNBIND_DISK = "snapshot_policy_unbind_disk" + ACT_SNAPSHOT_POLICY_UNBIND_DISK_FAIL = "snapshot_policy_unbind_disk_fail" + ACT_DISK_CLEAN_UP_SNAPSHOTS = "disk_clean_up_snapshots" ACT_DISK_CLEAN_UP_SNAPSHOTS_FAIL = "disk_clean_up_snapshots_fail" ACT_DISK_AUTO_SNAPSHOT = "disk_auto_snapshot" ACT_DISK_AUTO_SNAPSHOT_FAIL = "disk_auto_snapshot_fail" + ACT_DISK_AUTO_SYNC_SNAPSHOT = "disk_auto_sync_snapshot" + ACT_DISK_AUTO_SYNC_SNAPSHOT_FAIL = "disk_auto_sync_snapshot_fail" + ACT_ALLOCATING = "allocating" ACT_BACKUP_ALLOCATING = "backup_allocating" ACT_ALLOCATE = "allocate" diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 1cd7ff4c73..1a7242ef20 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -274,6 +274,18 @@ func (manager *SDiskManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu if diskType := jsonutils.GetAnyString(query, []string{"type", "disk_type"}); diskType != "" { q = q.Filter(sqlchemy.Equals(q.Field("disk_type"), diskType)) } + + // for snapshotpolicy_id + snapshotpolicyStr := jsonutils.GetAnyString(queryDict, []string{"snapshotpolicy", "snapshotpolicy_id"}) + if len(snapshotpolicyStr) > 0 { + snapshotpolicyObj, err := SnapshotPolicyManager.FetchByIdOrName(userCred, snapshotpolicyStr) + if err != nil { + return nil, httperrors.NewResourceNotFoundError("snapshotpolicy %s not found: %s", snapshotpolicyStr, err) + } + snapshotpolicyId := snapshotpolicyObj.GetId() + sq := SnapshotPolicyDiskManager.Query("disk_id").Equals("snapshotpolicy_id", snapshotpolicyId) + q = q.In("id", sq) + } return q, nil } @@ -342,7 +354,7 @@ func (self *SDisk) GetRuningGuestCount() (int, error) { Filter(sqlchemy.Equals(guests.Field("status"), api.VM_RUNNING)).CountWithError() } -func (self *SDisk) DetachAfterDelete(ctx context.Context, userCred mcclient.TokenCredential) error { +func (self *SDisk) DetachAllSnapshotpolicies(ctx context.Context, userCred mcclient.TokenCredential) error { err := SnapshotPolicyDiskManager.SyncDetachByDisk(ctx, userCred, nil, self) if err != nil { return errors.Wrap(err, "detach after delete failed") @@ -1578,7 +1590,7 @@ func (self *SDisk) RealDelete(ctx context.Context, userCred mcclient.TokenCreden return err } - return self.DetachAfterDelete(ctx, userCred) + return self.DetachAllSnapshotpolicies(ctx, userCred) } func (self *SDisk) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { @@ -1889,7 +1901,7 @@ func (manager *SDiskManager) CleanPendingDeleteDisks(ctx context.Context, userCr } } -func (manager *SDiskManager) getAutoSnapshotDisksId() ([]SSnapshotPolicyDisk, error) { +func (manager *SDiskManager) getAutoSnapshotDisksId(isExternal bool) ([]SSnapshotPolicyDisk, error) { t := time.Now() week := t.Weekday() @@ -1913,7 +1925,11 @@ func (manager *SDiskManager) getAutoSnapshotDisksId() ([]SSnapshotPolicyDisk, er diskQ := DiskManager.Query().SubQuery() spdq.Join(diskQ, sqlchemy.Equals(spdq.Field("disk_id"), diskQ.Field("id"))) - spdq.Filter(sqlchemy.IsNullOrEmpty(diskQ.Field("external_id"))) + if !isExternal { + spdq.Filter(sqlchemy.IsNullOrEmpty(diskQ.Field("external_id"))) + } else { + spdq.Filter(sqlchemy.IsNotEmpty(diskQ.Field("external_id"))) + } err = spdq.All(&spds) if err != nil { return nil, err @@ -1944,7 +1960,7 @@ func (disk *SDisk) validateDiskAutoCreateSnapshot() error { } func (manager *SDiskManager) AutoDiskSnapshot(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) { - spds, err := manager.getAutoSnapshotDisksId() + spds, err := manager.getAutoSnapshotDisksId(false) if err != nil { log.Errorf("Get auto snapshot disks id failed: %s", err) return @@ -1957,7 +1973,7 @@ func (manager *SDiskManager) AutoDiskSnapshot(ctx context.Context, userCred mccl for i := 0; i < len(spds); i++ { var ( disk = manager.FetchDiskById(spds[i].DiskId) - snapshotPolicy = SnapshotPolicyManager.FetchSnapshotPolicyById(spds[i].SnapshotpolicyId) + snapshotPolicy, _ = SnapshotPolicyManager.FetchSnapshotPolicyById(spds[i].SnapshotpolicyId) snapshotName = generateAutoSnapshotName() autoSnapshotCount = options.Options.DefaultMaxSnapshotCount - options.Options.DefaultMaxManualSnapshotCount err error @@ -2113,3 +2129,89 @@ func (self *SDisk) UpdataSnapshotsBackingDisk(backingDiskId string) error { } return nil } + +func (manager *SDiskManager) AutoSyncExtDiskSnapshot(ctx context.Context, userCred mcclient.TokenCredential, + isStart bool) { + + spds, err := manager.getAutoSnapshotDisksId(true) + if err != nil { + log.Errorf("Get auto snapshot ext disks id failed: %s", err) + return + } + if len(spds) == 0 { + log.Infof("CronJob AutoSyncExtDiskSnapshot: No external disk need sync snapshot") + return + } + + for i := 0; i < len(spds); i++ { + disk := manager.FetchDiskById(spds[i].DiskId) + + syncResult := disk.syncSnapshots(ctx, userCred) + if syncResult.IsError() { + db.OpsLog.LogEvent(disk, db.ACT_DISK_AUTO_SYNC_SNAPSHOT_FAIL, syncResult.Result(), userCred) + continue + } + db.OpsLog.LogEvent(disk, db.ACT_DISK_AUTO_SYNC_SNAPSHOT, "disk auto sync snapshot successfully", userCred) + } +} + +func (self *SDisk) syncSnapshots(ctx context.Context, userCred mcclient.TokenCredential) compare.SyncResult { + syncResult := compare.SyncResult{} + + extDisk, err := self.GetIDisk() + if err != nil { + syncResult.Error(err) + return syncResult + } + provider := self.GetCloudprovider() + syncOwnerId := provider.GetOwnerId() + region := self.GetStorage().GetRegion() + + extSnapshots, err := extDisk.GetISnapshots() + if err != nil { + syncResult.Error(err) + return syncResult + } + localSnapshots := SnapshotManager.GetDiskSnapshots(self.Id) + + lockman.LockClass(ctx, SnapshotManager, db.GetLockClassKey(SnapshotManager, syncOwnerId)) + defer lockman.ReleaseClass(ctx, SnapshotManager, db.GetLockClassKey(SnapshotManager, syncOwnerId)) + + removed := make([]SSnapshot, 0) + commondb := make([]SSnapshot, 0) + commonext := make([]cloudprovider.ICloudSnapshot, 0) + added := make([]cloudprovider.ICloudSnapshot, 0) + + err = compare.CompareSets(localSnapshots, extSnapshots, &removed, &commondb, &commonext, &added) + if err != nil { + syncResult.Error(err) + return syncResult + } + for i := 0; i < len(removed); i += 1 { + err = removed[i].syncRemoveCloudSnapshot(ctx, userCred) + if err != nil { + syncResult.DeleteError(err) + } else { + syncResult.Delete() + } + } + for i := 0; i < len(commondb); i += 1 { + err = commondb[i].SyncWithCloudSnapshot(ctx, userCred, commonext[i], syncOwnerId, region) + if err != nil { + syncResult.UpdateError(err) + } else { + syncMetadata(ctx, userCred, &commondb[i], commonext[i]) + syncResult.Update() + } + } + for i := 0; i < len(added); i += 1 { + local, err := SnapshotManager.newFromCloudSnapshot(ctx, userCred, added[i], region, syncOwnerId, provider) + if err != nil { + syncResult.AddError(err) + } else { + syncMetadata(ctx, userCred, local, added[i]) + syncResult.Add() + } + } + return syncResult +} diff --git a/pkg/compute/models/snapshotpolicy.go b/pkg/compute/models/snapshotpolicy.go index e4a1c5ddf8..5efd2f8086 100644 --- a/pkg/compute/models/snapshotpolicy.go +++ b/pkg/compute/models/snapshotpolicy.go @@ -117,13 +117,12 @@ func (manager *SSnapshotPolicyManager) GetSnapshotPoliciesAt(week, timePoint uin return nil, nil } -func (manager *SSnapshotPolicyManager) FetchSnapshotPolicyById(spId string) *SSnapshotPolicy { +func (manager *SSnapshotPolicyManager) FetchSnapshotPolicyById(spId string) (*SSnapshotPolicy, error) { sp, err := manager.FetchById(spId) if err != nil { - log.Errorf("FetchBId fail %s", err) - return nil + return nil, err } - return sp.(*SSnapshotPolicy) + return sp.(*SSnapshotPolicy), nil } func (manager *SSnapshotPolicyManager) FetchAllByIds(spIds []string) ([]SSnapshotPolicy, error) { @@ -569,6 +568,31 @@ func (sp *SSnapshotPolicy) GenerateCreateSpParams() *cloudprovider.SnapshotPolic } // ==================================================== action ========================================================= +func (sp *SSnapshotPolicy) AllowPerformCache(ctx context.Context, userCred mcclient.TokenCredential, + query jsonutils.JSONObject) bool { + + return sp.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, sp, "cache") +} + +func (sp *SSnapshotPolicy) PerformCache(ctx context.Context, userCred mcclient.TokenCredential, + query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + + regionId := jsonutils.GetAnyString(data, []string{"region_id", "cloudregion_id"}) + if len(regionId) == 0 { + return nil, httperrors.NewMissingParameterError("region_id or cloudregion_id") + } + providerId, err := data.GetString("provider_id") + if err != nil { + return nil, httperrors.NewMissingParameterError("provider_id") + } + _, err = SnapshotPolicyCacheManager.NewCache(ctx, userCred, sp.Id, regionId, providerId) + if err != nil { + return nil, err + } + + return nil, nil +} + func (sp *SSnapshotPolicy) AllowPerformBindDisks(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { diff --git a/pkg/compute/models/snapshotpolicydisks.go b/pkg/compute/models/snapshotpolicydisks.go index 0cbe5af041..09a8ea834b 100644 --- a/pkg/compute/models/snapshotpolicydisks.go +++ b/pkg/compute/models/snapshotpolicydisks.go @@ -20,6 +20,7 @@ import ( "database/sql" "fmt" "strings" + "yunion.io/x/sqlchemy" "yunion.io/x/jsonutils" "yunion.io/x/log" @@ -132,7 +133,7 @@ func (m *SSnapshotPolicyDiskManager) FetchBySnapshotPolicyDisk(spId, diskId stri return nil, err } if len(ret) == 0 { - return nil, fmt.Errorf("Not Found") + return nil, nil } return &ret[0], nil } @@ -150,8 +151,10 @@ func (m *SSnapshotPolicyDiskManager) FetchAllBySnapshotpolicyID(ctx context.Cont } func (m *SSnapshotPolicyDiskManager) FetchDiskCountBySPID(snapshotpolicyID string) (int, error) { - - q := m.Query().Equals("snapshotpolicy_id", snapshotpolicyID) + disksq := DiskManager.Query("id").IsFalse("pending_deleted").SubQuery() + sdsq := m.Query().SubQuery() + q := sdsq.Query().Join(disksq, sqlchemy.Equals(disksq.Field("id"), + sdsq.Field("disk_id"))).Equals("snapshotpolicy_id", snapshotpolicyID) return q.CountWithError() } @@ -393,8 +396,11 @@ func (self *SSnapshotPolicyDiskManager) ValidateCreateData(ctx context.Context, diskId, _ := data.GetString(self.GetMasterFieldName()) snapshotPolicyId, _ := data.GetString(self.GetSlaveFieldName()) disk := DiskManager.FetchDiskById(diskId) - snapshotPolicy := SnapshotPolicyManager.FetchSnapshotPolicyById(snapshotPolicyId) - err := disk.GetStorage().GetRegion().GetDriver().ValidateCreateSnapshopolicyDiskData(ctx, userCred, disk, snapshotPolicy) + snapshotPolicy, err := SnapshotPolicyManager.FetchSnapshotPolicyById(snapshotPolicyId) + if err != nil { + return nil, err + } + err = disk.GetStorage().GetRegion().GetDriver().ValidateCreateSnapshopolicyDiskData(ctx, userCred, disk, snapshotPolicy) if err != nil { return nil, err } diff --git a/pkg/compute/regiondrivers/managedvirtual.go b/pkg/compute/regiondrivers/managedvirtual.go index 7bde3804d2..4742d29da3 100644 --- a/pkg/compute/regiondrivers/managedvirtual.go +++ b/pkg/compute/regiondrivers/managedvirtual.go @@ -1103,9 +1103,9 @@ func (self *SManagedVirtualizationRegionDriver) RequestApplySnapshotPolicy(ctx c taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - spcache, err := models.SnapshotPolicyCacheManager.Register(ctx, userCred, sp.GetId(), - disk.GetStorage().GetRegion().GetId(), - disk.GetStorage().ManagerId) + regionId := disk.GetStorage().GetRegion().GetId() + providerId := disk.GetStorage().ManagerId + spcache, err := models.SnapshotPolicyCacheManager.Register(ctx, userCred, sp.GetId(), regionId, providerId) if err != nil { return nil, errors.Wrap(err, "registersnapshotpolicy cache failed") } @@ -1130,8 +1130,14 @@ func (self *SManagedVirtualizationRegionDriver) RequestCancelSnapshotPolicy(ctx TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - spcache, err := models.SnapshotPolicyCacheManager.FetchSnapshotPolicyCache(sp.GetId(), - disk.GetStorage().GetRegion().GetId(), disk.GetStorage().ManagerId) + + regionId := disk.GetStorage().GetRegion().GetId() + providerId := disk.GetStorage().ManagerId + spcache, err := models.SnapshotPolicyCacheManager.FetchSnapshotPolicyCache(sp.GetId(), regionId, providerId) + + if err != nil { + return nil, errors.Wrap(err, "registersnapshotpolicy cache failed") + } iRegion, err := spcache.GetIRegion() if err != nil { diff --git a/pkg/compute/regiondrivers/qcloud.go b/pkg/compute/regiondrivers/qcloud.go index ccb3987929..c1a4400d67 100644 --- a/pkg/compute/regiondrivers/qcloud.go +++ b/pkg/compute/regiondrivers/qcloud.go @@ -966,7 +966,9 @@ func (self *SQcloudRegionDriver) RequestPreSnapshotPolicyApply(ctx context.Conte } spcache, err := models.SnapshotPolicyCacheManager.FetchSnapshotPolicyCache(sp.GetId(), disk.GetStorage().GetRegion().GetId(), disk.GetStorage().ManagerId) - + if err != nil { + return nil, err + } iRegion, err := spcache.GetIRegion() if err != nil { return nil, err diff --git a/pkg/compute/service/service.go b/pkg/compute/service/service.go index 05efdb8138..74d1ec76c1 100644 --- a/pkg/compute/service/service.go +++ b/pkg/compute/service/service.go @@ -87,6 +87,7 @@ func StartService() { cron.AddJobEveryFewHour("AutoDiskSnapshot", 1, 5, 0, models.DiskManager.AutoDiskSnapshot, false) cron.AddJobEveryFewHour("SnapshotsCleanup", 1, 35, 0, models.SnapshotManager.CleanupSnapshots, false) + cron.AddJobEveryFewHour("AutoSyncExtDiskSnapshot", 1, 10, 0, models.DiskManager.AutoSyncExtDiskSnapshot, false) cron.AddJobEveryFewDays("SyncSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncSkus, true) cron.AddJobEveryFewDays("StorageSnapshotsRecycle", 1, 2, 0, 0, models.StorageManager.StorageSnapshotsRecycle, false) diff --git a/pkg/compute/tasks/disk_clean_overdued_snapshots.go b/pkg/compute/tasks/disk_clean_overdued_snapshots.go index 93552d74b9..acfae3ea12 100644 --- a/pkg/compute/tasks/disk_clean_overdued_snapshots.go +++ b/pkg/compute/tasks/disk_clean_overdued_snapshots.go @@ -41,7 +41,7 @@ func init() { func (self *DiskCleanOverduedSnapshots) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { disk := obj.(*models.SDisk) spId, _ := self.Params.GetString("snapshotpolicy_id") - sp := models.SnapshotPolicyManager.FetchSnapshotPolicyById(spId) + sp, _ := models.SnapshotPolicyManager.FetchSnapshotPolicyById(spId) if sp == nil { self.SetStageFailed(ctx, "missing snapshot policy ???") return diff --git a/pkg/compute/tasks/guest_detach_disk_task.go b/pkg/compute/tasks/guest_detach_disk_task.go index 459712d386..c2a156649f 100644 --- a/pkg/compute/tasks/guest_detach_disk_task.go +++ b/pkg/compute/tasks/guest_detach_disk_task.go @@ -91,6 +91,14 @@ func (self *GuestDetachDiskTask) OnDetachDiskComplete(ctx context.Context, guest self.OnTaskFail(ctx, guest, nil, fmt.Errorf("Connot find disk %s", diskId)) return } + // detach disk and snapshotpolicy if hypervisor is kvm + if guest.Hypervisor == api.HYPERVISOR_KVM { + err := disk.DetachAllSnapshotpolicies(ctx, self.UserCred) + if err != nil { + self.OnTaskFail(ctx, guest, nil, fmt.Errorf("detach all snapshotpolicies failed: %s", err.Error())) + return + } + } disk.SetStatus(self.UserCred, api.DISK_READY, "") keepDisk := jsonutils.QueryBoolean(self.Params, "keep_disk", true) host := guest.GetHost() diff --git a/pkg/compute/tasks/snapshotpolicy_disk_task.go b/pkg/compute/tasks/snapshotpolicy_disk_task.go index 86f931ab55..272aab7134 100644 --- a/pkg/compute/tasks/snapshotpolicy_disk_task.go +++ b/pkg/compute/tasks/snapshotpolicy_disk_task.go @@ -46,9 +46,15 @@ func (self *SnapshotPolicyApplyTask) taskFail(ctx context.Context, disk *models. if err != nil { log.Errorf("Delete snapshotpolicydisk %s failed, need to delete", spd.GetId()) } + snapshotpolicy, err := models.SnapshotPolicyManager.FetchSnapshotPolicyById(spd.SnapshotpolicyId) + if err == nil { + db.OpsLog.LogEvent(snapshotpolicy, db.ACT_SNAPSHOT_POLICY_BIND_DISK_FAIL, "", self.UserCred) + logclient.AddActionLogWithStartable(self, snapshotpolicy, logclient.ACT_BIND_DISK, "", self.UserCred, false) + } } disk.SetStatus(self.UserCred, compute.DISK_APPLY_SNAPSHOT_FAIL, reason) + db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY_FAILED, reason, self.UserCred) logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, reason, self.UserCred, false) notifyclient.NotifySystemError(disk.GetId(), disk.Name, compute.DISK_APPLY_SNAPSHOT_FAIL, reason) @@ -97,21 +103,22 @@ func (self *SnapshotPolicyApplyTask) OnPreSnapshotPolicyApplyCompleteFailed(ctx func (self *SnapshotPolicyApplyTask) OnPreSnapshotPolicyApplyComplete(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) { + snapshotPolicy := models.SSnapshotPolicy{} + spd := models.SSnapshotPolicyDisk{} + data.Unmarshal(&snapshotPolicy, "snapshotPolicy") + data.Unmarshal(&spd, "snapshotPolicyDisk") + if data.Contains("need_detach") { snapshotPolicyID, _ := data.GetString("need_detach") spd1, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(snapshotPolicyID, disk.GetId()) if err != nil { - self.taskFail(ctx, disk, spd1, err.Error()) + self.taskFail(ctx, disk, &spd, err.Error()) return } if spd1 != nil { spd1.RealDetach(ctx, self.UserCred) } - } - snapshotPolicy, spd := models.SSnapshotPolicy{}, models.SSnapshotPolicyDisk{} - data.Unmarshal(&snapshotPolicy, "snapshotPolicy") - data.Unmarshal(&spd, "snapshotPolicyDisk") self.SetStage("OnSnapshotPolicyApply", nil) // pass data to next Stage without inserting database through this way @@ -138,9 +145,15 @@ func (self *SnapshotPolicyApplyTask) OnSnapshotPolicyApply(ctx context.Context, sp_id, _ := data.GetString("snapshotpolicy_id") spd, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(sp_id, disk.GetId()) if err != nil { - log.Errorf("Fechsnapshotpolicy disk failed") + log.Errorf("Fetch snapshotpolicy disk failed") + } else if spd != nil { + spd.SetStatus(self.UserCred, compute.SNAPSHOT_POLICY_DISK_READY, "") + snapshotpolicy, err := models.SnapshotPolicyManager.FetchSnapshotPolicyById(spd.SnapshotpolicyId) + if err == nil { + db.OpsLog.LogEvent(snapshotpolicy, db.ACT_SNAPSHOT_POLICY_BIND_DISK, "", self.UserCred) + logclient.AddActionLogWithStartable(self, snapshotpolicy, logclient.ACT_BIND_DISK, "", self.UserCred, true) + } } - spd.SetStatus(self.UserCred, compute.SNAPSHOT_POLICY_DISK_READY, "") db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred) logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred, true) self.SetStageComplete(ctx, nil) @@ -155,8 +168,14 @@ type SnapshotPolicyCancelTask struct { func (self *SnapshotPolicyCancelTask) taskFail(ctx context.Context, disk *models.SDisk, spd *models.SSnapshotPolicyDisk, reason string) { if spd != nil { spd.SetStatus(self.UserCred, compute.SNAPSHOT_POLICY_DISK_DELETE_FAILED, "") + snapshotpolicy, err := models.SnapshotPolicyManager.FetchSnapshotPolicyById(spd.SnapshotpolicyId) + if err == nil { + db.OpsLog.LogEvent(snapshotpolicy, db.ACT_SNAPSHOT_POLICY_UNBIND_DISK_FAIL, "", self.UserCred) + logclient.AddActionLogWithStartable(self, snapshotpolicy, logclient.ACT_UNBIND_DISK, "", self.UserCred, false) + } } disk.SetStatus(self.UserCred, compute.DISK_CALCEL_SNAPSHOT_FAIL, reason) + db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY_FAILED, reason, self.UserCred) logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, reason, self.UserCred, false) self.SetStageFailed(ctx, reason) @@ -201,8 +220,15 @@ func (self *SnapshotPolicyCancelTask) OnSnapshotPolicyCancel(ctx context.Context if err != nil { log.Errorf("Fechsnapshotpolicy disk failed") } - //real detach - spd.RealDetach(ctx, self.UserCred) + if spd != nil { + //real detach + spd.RealDetach(ctx, self.UserCred) + snapshotpolicy, err := models.SnapshotPolicyManager.FetchSnapshotPolicyById(spd.SnapshotpolicyId) + if err == nil { + db.OpsLog.LogEvent(snapshotpolicy, db.ACT_SNAPSHOT_POLICY_UNBIND_DISK, "", self.UserCred) + logclient.AddActionLogWithStartable(self, snapshotpolicy, logclient.ACT_UNBIND_DISK, "", self.UserCred, true) + } + } db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred) logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred, true) diff --git a/pkg/multicloud/qcloud/snapshot.go b/pkg/multicloud/qcloud/snapshot.go index 113bd0868c..5567343316 100644 --- a/pkg/multicloud/qcloud/snapshot.go +++ b/pkg/multicloud/qcloud/snapshot.go @@ -115,7 +115,7 @@ func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName } if len(diskId) > 0 { params[fmt.Sprintf("Filters.%d.Name", filter)] = "disk-id" - params[fmt.Sprintf("Filters.%d.Values", filter)] = diskId + params[fmt.Sprintf("Filters.%d.Values.0", filter)] = diskId filter++ } if len(snapshotName) > 0 { diff --git a/pkg/util/logclient/consts.go b/pkg/util/logclient/consts.go index cfd84b4116..f4ebe9ba22 100644 --- a/pkg/util/logclient/consts.go +++ b/pkg/util/logclient/consts.go @@ -119,6 +119,8 @@ const ( ACT_DELETE_BACKUP = "删除备份机" ACT_APPLY_SNAPSHOT_POLICY = "绑定快照策略" ACT_CANCEL_SNAPSHOT_POLICY = "取消快照策略" + ACT_BIND_DISK = "绑定磁盘" + ACT_UNBIND_DISK = "解绑磁盘" ACT_ATTACH_HOST = "关联宿主机" ACT_DETACH_HOST = "取消关联宿主机" ACT_VM_IO_THROTTLE = "虚拟机磁盘限速"