From b27be13cc391f4869ffcbeaf41f46ea642295882 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Mon, 22 Oct 2018 11:24:54 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9A=E8=A1=A5?= =?UTF-8?q?=E5=85=852.2.0=20purge=20eip/snapshot=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/climc/shell/elasticips.go | 12 ++++++++++++ cmd/climc/shell/snapshots.go | 13 +++++++++++++ pkg/compute/models/cloudproviders.go | 9 +++++++++ pkg/compute/models/elasticips.go | 19 +++++++++++++++++++ pkg/compute/models/snapshots.go | 19 +++++++++++++++++++ 5 files changed, 72 insertions(+) diff --git a/cmd/climc/shell/elasticips.go b/cmd/climc/shell/elasticips.go index 054283940c..74e6e0f281 100644 --- a/cmd/climc/shell/elasticips.go +++ b/cmd/climc/shell/elasticips.go @@ -187,4 +187,16 @@ func init() { return nil }) + type EipPurgeOptions struct { + ID string `help:"ID or name of EIP"` + } + R(&EipPurgeOptions{}, "eip-purge", "Purge EIP db records", func(s *mcclient.ClientSession, args *EipPurgeOptions) error { + result, err := modules.Elasticips.PerformAction(s, args.ID, "purge", nil) + if err != nil { + return err + } + printObject(result) + return nil + }) + } diff --git a/cmd/climc/shell/snapshots.go b/cmd/climc/shell/snapshots.go index 3be5a0ad2b..d809a1226e 100644 --- a/cmd/climc/shell/snapshots.go +++ b/cmd/climc/shell/snapshots.go @@ -84,4 +84,17 @@ func init() { printObject(result) return nil }) + + type SnapshotPurgeOptions struct { + ID string `help:"ID or name of Snapshot"` + } + R(&SnapshotPurgeOptions{}, "snapshot-purge", "Purge Snapshot db records", func(s *mcclient.ClientSession, args *SnapshotPurgeOptions) error { + result, err := modules.Snapshots.PerformAction(s, args.ID, "purge", nil) + if err != nil { + return err + } + printObject(result) + return nil + }) + } diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index 31afc0984f..d3e9b0e5bf 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -96,6 +96,10 @@ func (self *SCloudprovider) getEipCount() int { return ElasticipManager.Query().Equals("manager_id", self.Id).Count() } +func (self *SCloudprovider) getSnapshotCount() int { + return SnapshotManager.Query().Equals("manager_id", self.Id).Count() +} + func (self *SCloudprovider) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data) } @@ -425,6 +429,7 @@ type SCloudproviderUsage struct { StorageCount int StorageCacheCount int EipCount int + SnapshotCount int } func (usage *SCloudproviderUsage) isEmpty() bool { @@ -443,6 +448,9 @@ func (usage *SCloudproviderUsage) isEmpty() bool { if usage.EipCount > 0 { return false } + if usage.SnapshotCount > 0 { + return false + } return true } @@ -454,6 +462,7 @@ func (self *SCloudprovider) getUsage() *SCloudproviderUsage { usage.StorageCount = self.getStorageCount() usage.StorageCacheCount = self.getStoragecacheCount() usage.EipCount = self.getEipCount() + usage.SnapshotCount = self.getSnapshotCount() return &usage } diff --git a/pkg/compute/models/elasticips.go b/pkg/compute/models/elasticips.go index 5c5ad97792..a164e35ada 100644 --- a/pkg/compute/models/elasticips.go +++ b/pkg/compute/models/elasticips.go @@ -799,3 +799,22 @@ func (manager *SElasticipManager) TotalCount(projectId string, rangeObj db.IStan usage.EIPUsedCount = q3.Count() return usage } + +func (self *SElasticip) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return userCred.IsSystemAdmin() +} + +func (self *SElasticip) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + err := self.ValidateDeleteCondition(ctx) + if err != nil { + return nil, err + } + provider := self.GetCloudprovider() + if provider != nil { + if provider.Enabled { + return nil, httperrors.NewInvalidStatusError("Cannot purge elastic_ip on enabled cloud provider") + } + } + err = self.RealDelete(ctx, userCred) + return nil, err +} diff --git a/pkg/compute/models/snapshots.go b/pkg/compute/models/snapshots.go index 3367203ee4..5d5073710c 100644 --- a/pkg/compute/models/snapshots.go +++ b/pkg/compute/models/snapshots.go @@ -530,3 +530,22 @@ func (self *SSnapshot) GetISnapshotRegion() (cloudprovider.ICloudRegion, error) } return provider.GetIRegionById(region.GetExternalId()) } + +func (self *SSnapshot) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return userCred.IsSystemAdmin() +} + +func (self *SSnapshot) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + err := self.ValidateDeleteCondition(ctx) + if err != nil { + return nil, err + } + provider := self.GetCloudprovider() + if provider != nil { + if provider.Enabled { + return nil, httperrors.NewInvalidStatusError("Cannot purge snapshot on enabled cloud provider") + } + } + err = self.RealDelete(ctx, userCred) + return nil, err +} From 46a39b56124ee5a6b3f318f86aaf13d4820ec985 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Mon, 22 Oct 2018 12:04:55 +0800 Subject: [PATCH 2/3] allow snapshot-list --manager --- cmd/climc/shell/snapshots.go | 5 +++++ cmd/climc/shell/vpcs.go | 2 +- pkg/compute/models/snapshots.go | 12 ++++++++++++ pkg/compute/models/storages.go | 6 +++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cmd/climc/shell/snapshots.go b/cmd/climc/shell/snapshots.go index d809a1226e..967abb7387 100644 --- a/cmd/climc/shell/snapshots.go +++ b/cmd/climc/shell/snapshots.go @@ -16,6 +16,8 @@ func init() { Share bool `help:"Show shared snapshots"` DiskType string `help: "Filter by disk type" choices:"sys|data"` Provider string `help: "Cloud provider" choices:"Aliyun|VMware|Azure"` + + Manager string `help:"Show snapshots belongs to a specific cloud provider"` } R(&SnapshotsListOptions{}, "snapshot-list", "Show snapshots", func(s *mcclient.ClientSession, args *SnapshotsListOptions) error { params, err := args.BaseListOptions.Params() @@ -41,6 +43,9 @@ func init() { if len(args.Provider) > 0 { params.Add(jsonutils.NewString(args.Provider), "provider") } + if len(args.Manager) > 0 { + params.Add(jsonutils.NewString(args.Manager), "manager") + } result, err := modules.Snapshots.List(s, params) if err != nil { return err diff --git a/cmd/climc/shell/vpcs.go b/cmd/climc/shell/vpcs.go index 547a775dd0..79517f2880 100644 --- a/cmd/climc/shell/vpcs.go +++ b/cmd/climc/shell/vpcs.go @@ -11,7 +11,7 @@ func init() { type VpcListOptions struct { options.BaseListOptions Region string `help:"ID or Name of region"` - Manager string `help:"Show regions belongs to the cloud provider"` + Manager string `help:"Show vpcs belongs to the cloud provider"` } R(&VpcListOptions{}, "vpc-list", "List VPCs", func(s *mcclient.ClientSession, args *VpcListOptions) error { var params *jsonutils.JSONDict diff --git a/pkg/compute/models/snapshots.go b/pkg/compute/models/snapshots.go index 5d5073710c..34fe6a4945 100644 --- a/pkg/compute/models/snapshots.go +++ b/pkg/compute/models/snapshots.go @@ -112,6 +112,18 @@ func (manager *SSnapshotManager) ListItemFilter(ctx context.Context, q *sqlchemy sq := cloudproviderTbl.Query(cloudproviderTbl.Field("id")).Equals("provider", provider) q = q.In("manager_id", sq) } + + if managerStr := jsonutils.GetAnyString(query, []string{"manager", "manager_id"}); len(managerStr) > 0 { + managerObj, err := CloudproviderManager.FetchByIdOrName("", managerStr) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewNotFoundError("manager %s not found", managerStr) + } + return nil, httperrors.NewGeneralError(err) + } + q = q.Equals("manager_id", managerObj.GetId()) + } + return q, nil } diff --git a/pkg/compute/models/storages.go b/pkg/compute/models/storages.go index 060c266c62..256321c33c 100644 --- a/pkg/compute/models/storages.go +++ b/pkg/compute/models/storages.go @@ -83,7 +83,7 @@ func (manager *SStorageManager) GetContextManager() []db.IModelManager { } func (self *SStorage) ValidateDeleteCondition(ctx context.Context) error { - if self.GetHostCount() > 0 || self.GetDiskCount() > 0 { + if self.GetHostCount() > 0 || self.GetDiskCount() > 0 || self.GetSnapshotCount() > 0 { return httperrors.NewNotEmptyError("Not an empty storage provider") } return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx) @@ -97,6 +97,10 @@ func (self *SStorage) GetDiskCount() int { return DiskManager.Query().Equals("storage_id", self.Id).Count() } +func (self *SStorage) GetSnapshotCount() int { + return SnapshotManager.Query().Equals("storage_id", self.Id).Count() +} + func (self *SStorage) IsLocal() bool { return self.StorageType == STORAGE_LOCAL || self.StorageType == STORAGE_BAREMETAL } From 2adec7a7926fea8ebf0a4531cb73608f989ed88b Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Mon, 22 Oct 2018 15:21:42 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9A=E5=88=A0?= =?UTF-8?q?=E9=99=A4guest=E6=97=B6=E5=80=99=E6=B2=A1=E6=9C=89=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E6=B8=85=E7=90=86eip=E7=9A=84=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/models/elasticips.go | 8 ++++++++ pkg/compute/models/guests.go | 20 ++++++++++++++++---- pkg/compute/models/storagecachedimages.go | 4 ++-- pkg/compute/models/storagecaches.go | 2 +- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/pkg/compute/models/elasticips.go b/pkg/compute/models/elasticips.go index a164e35ada..69db4e1e1a 100644 --- a/pkg/compute/models/elasticips.go +++ b/pkg/compute/models/elasticips.go @@ -818,3 +818,11 @@ func (self *SElasticip) PerformPurge(ctx context.Context, userCred mcclient.Toke err = self.RealDelete(ctx, userCred) return nil, err } + +func (self *SElasticip) DoPendingDelete(ctx context.Context, userCred mcclient.TokenCredential) { + if self.Mode == EIP_MODE_INSTANCE_PUBLICIP { + self.SVirtualResourceBase.DoPendingDelete(ctx, userCred) + return + } + self.Dissociate(ctx, userCred) +} \ No newline at end of file diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 922c21b4b3..85f3e3c909 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -3086,6 +3086,10 @@ func (self *SGuest) StartChangeConfigTask(ctx context.Context, userCred mcclient } func (self *SGuest) DoPendingDelete(ctx context.Context, userCred mcclient.TokenCredential) { + eip, _ := self.GetEip() + if eip != nil { + eip.DoPendingDelete(ctx, userCred) + } for _, guestdisk := range self.GetDisks() { disk := guestdisk.GetDisk() storage := disk.GetStorage() @@ -4479,10 +4483,18 @@ func (self *SGuest) DeleteEip(ctx context.Context, userCred mcclient.TokenCreden if eip == nil { return nil } - err = eip.Delete(ctx, userCred) - if err != nil { - log.Errorf("Delete eip fail %s", err) - return err + if eip.Mode == EIP_MODE_INSTANCE_PUBLICIP { + err = eip.RealDelete(ctx, userCred) + if err != nil { + log.Errorf("Delete eip on delete server fail %s", err) + return err + } + } else { + err = eip.Dissociate(ctx, userCred) + if err != nil { + log.Errorf("Dissociate eip on delete server fail %s", err) + return err + } } return nil } diff --git a/pkg/compute/models/storagecachedimages.go b/pkg/compute/models/storagecachedimages.go index 0bafb4624b..30d24a13cb 100644 --- a/pkg/compute/models/storagecachedimages.go +++ b/pkg/compute/models/storagecachedimages.go @@ -225,7 +225,7 @@ func (self *SStoragecachedimage) isDownloadSessionExpire() bool { } } -func (self *SStoragecachedimage) markDeleting(ctx context.Context, userCred mcclient.TokenCredential) error { +func (self *SStoragecachedimage) markDeleting(ctx context.Context, userCred mcclient.TokenCredential, isForce bool) error { err := self.ValidateDeleteCondition(ctx) if err != nil { return err @@ -237,7 +237,7 @@ func (self *SStoragecachedimage) markDeleting(ctx context.Context, userCred mccl lockman.LockJointObject(ctx, cache, image) defer lockman.ReleaseJointObject(ctx, cache, image) - if utils.IsInStringArray(self.Status, []string{CACHED_IMAGE_STATUS_READY, CACHED_IMAGE_STATUS_DELETING}) { + if !isForce && ! utils.IsInStringArray(self.Status, []string{CACHED_IMAGE_STATUS_READY, CACHED_IMAGE_STATUS_DELETING}) { return httperrors.NewInvalidStatusError("Cannot uncache in status %s", self.Status) } _, err = self.GetModelManager().TableSpec().Update(self, func() error { diff --git a/pkg/compute/models/storagecaches.go b/pkg/compute/models/storagecaches.go index 04546e8429..5e46d08c31 100644 --- a/pkg/compute/models/storagecaches.go +++ b/pkg/compute/models/storagecaches.go @@ -315,7 +315,7 @@ func (self *SStoragecache) PerformUncacheImage(ctx context.Context, userCred mcc return nil, err } - err = scimg.markDeleting(ctx, userCred) + err = scimg.markDeleting(ctx, userCred, isForce) if err != nil { return nil, httperrors.NewInvalidStatusError("Fail to mark cache status: %s", err) }