From a2417ef77b29787d3b2cbdd99dbd22724a1ffbe2 Mon Sep 17 00:00:00 2001 From: Jian Qiu Date: Mon, 8 Apr 2019 22:04:33 +0800 Subject: [PATCH] Feature: allow delete cloud-account with resources (#252) --- pkg/compute/models/cloudaccounts.go | 54 +- pkg/compute/models/cloudproviderregions.go | 4 +- pkg/compute/models/cloudproviders.go | 68 +- pkg/compute/models/external_projects.go | 10 +- pkg/compute/models/hosts.go | 12 +- pkg/compute/models/loadbalanceracls.go | 4 + .../models/loadbalancerbackendgroups.go | 4 + pkg/compute/models/loadbalancerbackends.go | 4 + .../models/loadbalancercertificates.go | 4 + .../models/loadbalancerlistenerrules.go | 4 + pkg/compute/models/loadbalancerlisteners.go | 4 + pkg/compute/models/loadbalancernetworks.go | 2 +- pkg/compute/models/loadbalancers.go | 12 +- pkg/compute/models/managedresource.go | 5 + pkg/compute/models/networks.go | 8 +- pkg/compute/models/purge.go | 680 ++++++++++++++++++ pkg/compute/models/storages.go | 11 + .../tasks/cloud_account_delete_task.go | 54 ++ pkg/compute/tasks/guest_delete_task.go | 2 +- pkg/compute/tasks/vpc_delete_task.go | 15 +- pkg/util/aws/region.go | 2 +- pkg/util/aws/shell/s3.go | 24 + pkg/util/aws/storagecache.go | 10 +- pkg/util/esxi/shell/host.go | 13 + 24 files changed, 923 insertions(+), 87 deletions(-) create mode 100644 pkg/compute/models/purge.go create mode 100644 pkg/compute/tasks/cloud_account_delete_task.go create mode 100644 pkg/util/aws/shell/s3.go diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index f479b507f8..9dbde23c69 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -144,6 +144,9 @@ func (self *SCloudaccount) ValidateDeleteCondition(ctx context.Context) error { if self.Enabled { return httperrors.NewInvalidStatusError("account is enabled") } + if self.SyncStatus != api.CLOUD_PROVIDER_SYNC_STATUS_IDLE { + return httperrors.NewInvalidStatusError("account is not idle") + } cloudproviders := self.GetCloudproviders() for i := 0; i < len(cloudproviders); i++ { if err := cloudproviders[i].ValidateDeleteCondition(ctx); err != nil { @@ -154,14 +157,10 @@ func (self *SCloudaccount) ValidateDeleteCondition(ctx context.Context) error { return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx) } -func (self *SCloudaccount) PreDelete(ctx context.Context, userCred mcclient.TokenCredential) { - cloudproviders := self.GetCloudproviders() - for i := 0; i < len(cloudproviders); i++ { - cloudproviders[i].Delete(ctx, userCred) - } -} - func (self *SCloudaccount) PerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if strings.Index(self.Status, "delet") >= 0 { + return nil, httperrors.NewInvalidStatusError("Cannot enable deleting account") + } _, err := self.SEnabledStatusStandaloneResourceBase.PerformEnable(ctx, userCred, query, data) if err != nil { return nil, err @@ -177,10 +176,6 @@ func (self *SCloudaccount) PerformEnable(ctx context.Context, userCred mcclient. } func (self *SCloudaccount) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { - _, err := self.SEnabledStatusStandaloneResourceBase.PerformDisable(ctx, userCred, query, data) - if err != nil { - return nil, err - } cloudproviders := self.GetCloudproviders() for i := 0; i < len(cloudproviders); i++ { _, err := cloudproviders[i].PerformDisable(ctx, userCred, query, data) @@ -188,6 +183,16 @@ func (self *SCloudaccount) PerformDisable(ctx context.Context, userCred mcclient return nil, err } } + if self.EnableAutoSync { + err := self.disableAutoSync(ctx, userCred) + if err != nil { + return nil, err + } + } + _, err := self.SEnabledStatusStandaloneResourceBase.PerformDisable(ctx, userCred, query, data) + if err != nil { + return nil, err + } return nil, nil } @@ -1216,3 +1221,30 @@ func (account *SCloudaccount) SyncCallSyncAccountTask(ctx context.Context, userC err := <-waitChan return err } + +func (self *SCloudaccount) Delete(ctx context.Context, userCred mcclient.TokenCredential) error { + // override + log.Infof("cloud account delete do nothing") + return nil +} + +func (self *SCloudaccount) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + self.SetStatus(userCred, api.CLOUD_PROVIDER_DELETED, "real delete") + return self.SEnabledStatusStandaloneResourceBase.Delete(ctx, userCred) +} + +func (self *SCloudaccount) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error { + return self.StartCloudaccountDeleteTask(ctx, userCred, "") +} + +func (self *SCloudaccount) StartCloudaccountDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error { + params := jsonutils.NewDict() + task, err := taskman.TaskManager.NewTask(ctx, "CloudAccountDeleteTask", self, userCred, params, parentTaskId, "", nil) + if err != nil { + log.Errorf("%s", err) + return err + } + self.SetStatus(userCred, api.CLOUD_PROVIDER_START_DELETE, "StartCloudaccountDeleteTask") + task.ScheduleRun(nil) + return nil +} diff --git a/pkg/compute/models/cloudproviderregions.go b/pkg/compute/models/cloudproviderregions.go index 664a60d35e..703e3aa374 100644 --- a/pkg/compute/models/cloudproviderregions.go +++ b/pkg/compute/models/cloudproviderregions.go @@ -376,8 +376,8 @@ func (cpr *SCloudproviderregion) isEmpty(resKey string) bool { return true } -func (cprm *SCloudproviderregionManager) fetchRecordsForCloudprovider(manager *SCloudprovider) ([]SCloudproviderregion, error) { - q := cprm.Query().Equals("cloudprovider_id", manager.Id) +func (cprm *SCloudproviderregionManager) fetchRecordsByCloudproviderId(providerId string) ([]SCloudproviderregion, error) { + q := cprm.Query().Equals("cloudprovider_id", providerId) recs := make([]SCloudproviderregion, 0) err := db.FetchModelObjects(cprm, q, &recs) if err != nil { diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index f39df2ef66..d2702a8f63 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -118,10 +118,13 @@ func (self *SCloudprovider) ValidateDeleteCondition(ctx context.Context) error { if self.Enabled { return httperrors.NewInvalidStatusError("provider is enabled") } - usage := self.getUsage() - if !usage.isEmpty() { - return httperrors.NewNotEmptyError("Not an empty cloud provider") + if self.SyncStatus != api.CLOUD_PROVIDER_SYNC_STATUS_IDLE { + return httperrors.NewInvalidStatusError("provider is not idle") } + // usage := self.getUsage() + // if !usage.isEmpty() { + // return httperrors.NewNotEmptyError("Not an empty cloud provider") + // } return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx) } @@ -932,45 +935,34 @@ func (self *SCloudprovider) Delete(ctx context.Context, userCred mcclient.TokenC } func (self *SCloudprovider) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { - err := self.deleteSyncedRegions(ctx, userCred) - if err != nil { - return err - } - err = self.deleteProjectsMapping(ctx, userCred) - if err != nil { - return err + var err error + + for _, manager := range []IPurgeableManager{ + HostManager, + SnapshotManager, + StorageManager, + StoragecacheManager, + LoadbalancerBackendManager, + LoadbalancerBackendGroupManager, + LoadbalancerListenerRuleManager, + LoadbalancerListenerManager, + LoadbalancerManager, + LoadbalancerAclManager, + LoadbalancerCertificateManager, + VpcManager, + ElasticipManager, + CloudproviderRegionManager, + ExternalProjectManager, + } { + manager.purgeAll(ctx, userCred, self.Id) + if err != nil { + return err + } } + return self.SEnabledStatusStandaloneResourceBase.Delete(ctx, userCred) } -func (self *SCloudprovider) deleteSyncedRegions(ctx context.Context, userCred mcclient.TokenCredential) error { - cprs, err := CloudproviderRegionManager.fetchRecordsForCloudprovider(self) - if err != nil { - return err - } - for i := range cprs { - err = cprs[i].Detach(ctx, userCred) - if err != nil { - return err - } - } - return nil -} - -func (self *SCloudprovider) deleteProjectsMapping(ctx context.Context, userCred mcclient.TokenCredential) error { - projs, err := ExternalProjectManager.getProjectsByProvider(self) - if err != nil { - return err - } - for i := range projs { - err = projs[i].Delete(ctx, userCred) - if err != nil { - return err - } - } - return nil -} - func (self *SCloudprovider) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error { return self.StartCloudproviderDeleteTask(ctx, userCred, "") } diff --git a/pkg/compute/models/external_projects.go b/pkg/compute/models/external_projects.go index b9e0758f8d..e4f69bc981 100644 --- a/pkg/compute/models/external_projects.go +++ b/pkg/compute/models/external_projects.go @@ -77,13 +77,9 @@ func (self *SExternalProject) ValidateUpdateData(ctx context.Context, userCred m return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data) } -func (manager *SExternalProjectManager) getProjectsByProvider(provider *SCloudprovider) ([]SExternalProject, error) { +func (manager *SExternalProjectManager) getProjectsByProviderId(providerId string) ([]SExternalProject, error) { projects := []SExternalProject{} - q := manager.Query() - if provider != nil { - q = q.Equals("manager_id", provider.Id) - } - err := db.FetchModelObjects(manager, q, &projects) + err := fetchByManagerId(manager, providerId, &projects) if err != nil { return nil, err } @@ -140,7 +136,7 @@ func (manager *SExternalProjectManager) SyncProjects(ctx context.Context, userCr syncResult := compare.SyncResult{} - dbProjects, err := manager.getProjectsByProvider(provider) + dbProjects, err := manager.getProjectsByProviderId(provider.Id) if err != nil { syncResult.Error(err) return syncResult diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index b8374c07b9..9c93b087dc 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -484,7 +484,15 @@ func (self *SHost) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenC }*/ func (self *SHost) ValidateDeleteCondition(ctx context.Context) error { - if self.IsBaremetal && self.HostType != HOST_TYPE_BAREMETAL { + return self.validateDeleteCondition(ctx, false) +} + +func (self *SHost) ValidatePurgeCondition(ctx context.Context) error { + return self.validateDeleteCondition(ctx, true) +} + +func (self *SHost) validateDeleteCondition(ctx context.Context, purge bool) error { + if !purge && self.IsBaremetal && self.HostType != HOST_TYPE_BAREMETAL { return httperrors.NewInvalidStatusError("Host is a converted baremetal, should be unconverted before delete") } if self.Enabled { @@ -537,10 +545,10 @@ func (self *SHost) RealDelete(ctx context.Context, userCred mcclient.TokenCreden } for _, hoststorage := range self.GetHoststorages() { storage := hoststorage.GetStorage() + hoststorage.Delete(ctx, userCred) if storage != nil && storage.IsLocal() { storage.Delete(ctx, userCred) } - hoststorage.Delete(ctx, userCred) } for _, bn := range self.GetBaremetalnetworks() { self.DeleteBaremetalnetwork(ctx, userCred, &bn, false) diff --git a/pkg/compute/models/loadbalanceracls.go b/pkg/compute/models/loadbalanceracls.go index a25823d1bc..908013e6a1 100644 --- a/pkg/compute/models/loadbalanceracls.go +++ b/pkg/compute/models/loadbalanceracls.go @@ -325,6 +325,10 @@ func (lbacl *SLoadbalancerAcl) Delete(ctx context.Context, userCred mcclient.Tok return nil } +func (lbacl *SLoadbalancerAcl) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + return lbacl.SSharableVirtualResourceBase.Delete(ctx, userCred) +} + func (man *SLoadbalancerAclManager) getLoadbalancerAclsByRegion(region *SCloudregion, provider *SCloudprovider) ([]SLoadbalancerAcl, error) { acls := []SLoadbalancerAcl{} q := man.Query().Equals("cloudregion_id", region.Id).Equals("manager_id", provider.Id) diff --git a/pkg/compute/models/loadbalancerbackendgroups.go b/pkg/compute/models/loadbalancerbackendgroups.go index 4e47f51846..d163ad76e5 100644 --- a/pkg/compute/models/loadbalancerbackendgroups.go +++ b/pkg/compute/models/loadbalancerbackendgroups.go @@ -331,6 +331,10 @@ func (lbbg *SLoadbalancerBackendGroup) Delete(ctx context.Context, userCred mccl return nil } +func (lbbg *SLoadbalancerBackendGroup) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + return lbbg.SVirtualResourceBase.Delete(ctx, userCred) +} + func (man *SLoadbalancerBackendGroupManager) getLoadbalancerBackendgroupsByLoadbalancer(lb *SLoadbalancer) ([]SLoadbalancerBackendGroup, error) { lbbgs := []SLoadbalancerBackendGroup{} q := man.Query().Equals("loadbalancer_id", lb.Id) diff --git a/pkg/compute/models/loadbalancerbackends.go b/pkg/compute/models/loadbalancerbackends.go index aa946e4fd3..2498bd720c 100644 --- a/pkg/compute/models/loadbalancerbackends.go +++ b/pkg/compute/models/loadbalancerbackends.go @@ -241,6 +241,10 @@ func (lbb *SLoadbalancerBackend) Delete(ctx context.Context, userCred mcclient.T return nil } +func (lbb *SLoadbalancerBackend) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + return lbb.SVirtualResourceBase.Delete(ctx, userCred) +} + func (lbb *SLoadbalancerBackend) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { return db.IsAdminAllowPerform(userCred, lbb, "purge") } diff --git a/pkg/compute/models/loadbalancercertificates.go b/pkg/compute/models/loadbalancercertificates.go index 56eb6a3be4..b9725f6429 100644 --- a/pkg/compute/models/loadbalancercertificates.go +++ b/pkg/compute/models/loadbalancercertificates.go @@ -260,6 +260,10 @@ func (lbcert *SLoadbalancerCertificate) Delete(ctx context.Context, userCred mcc return nil } +func (lbcert *SLoadbalancerCertificate) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + return lbcert.SVirtualResourceBase.Delete(ctx, userCred) +} + func (lbcert *SLoadbalancerCertificate) GetRegion() *SCloudregion { region, err := CloudregionManager.FetchById(lbcert.CloudregionId) if err != nil { diff --git a/pkg/compute/models/loadbalancerlistenerrules.go b/pkg/compute/models/loadbalancerlistenerrules.go index f07e9fce01..051bc2093a 100644 --- a/pkg/compute/models/loadbalancerlistenerrules.go +++ b/pkg/compute/models/loadbalancerlistenerrules.go @@ -285,6 +285,10 @@ func (lbr *SLoadbalancerListenerRule) Delete(ctx context.Context, userCred mccli return nil } +func (lbr *SLoadbalancerListenerRule) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + return lbr.SVirtualResourceBase.Delete(ctx, userCred) +} + // Delete, Update func (man *SLoadbalancerListenerRuleManager) getLoadbalancerListenerRulesByListener(listener *SLoadbalancerListener) ([]SLoadbalancerListenerRule, error) { diff --git a/pkg/compute/models/loadbalancerlisteners.go b/pkg/compute/models/loadbalancerlisteners.go index 0836705bfb..aa971655a1 100644 --- a/pkg/compute/models/loadbalancerlisteners.go +++ b/pkg/compute/models/loadbalancerlisteners.go @@ -581,6 +581,10 @@ func (lblis *SLoadbalancerListener) Delete(ctx context.Context, userCred mcclien return nil } +func (lblis *SLoadbalancerListener) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + return lblis.SVirtualResourceBase.Delete(ctx, userCred) +} + func (lblis *SLoadbalancerListener) GetLoadbalancerListenerParams() (*cloudprovider.SLoadbalancerListener, error) { listener := &cloudprovider.SLoadbalancerListener{ Name: lblis.Name, diff --git a/pkg/compute/models/loadbalancernetworks.go b/pkg/compute/models/loadbalancernetworks.go index 75bc5b2ba5..165e189c30 100644 --- a/pkg/compute/models/loadbalancernetworks.go +++ b/pkg/compute/models/loadbalancernetworks.go @@ -138,7 +138,7 @@ func (m *SLoadbalancernetworkManager) DeleteLoadbalancerNetwork(ctx context.Cont return nil } -func (m *SLoadbalancernetworkManager) SyncLoadbalancerNetwork(ctx context.Context, userCred mcclient.TokenCredential, req *SLoadbalancerNetworkRequestData) error { +func (m *SLoadbalancernetworkManager) syncLoadbalancerNetwork(ctx context.Context, userCred mcclient.TokenCredential, req *SLoadbalancerNetworkRequestData) error { _network, err := NetworkManager.FetchById(req.NetworkId) if err != nil { return err diff --git a/pkg/compute/models/loadbalancers.go b/pkg/compute/models/loadbalancers.go index 587a144ea2..23ff2a7612 100644 --- a/pkg/compute/models/loadbalancers.go +++ b/pkg/compute/models/loadbalancers.go @@ -368,9 +368,9 @@ func (lb *SLoadbalancer) AllowPerformPurge(ctx context.Context, userCred mcclien } func (lb *SLoadbalancer) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { - parasm := jsonutils.NewDict() - parasm.Add(jsonutils.JSONTrue, "purge") - return nil, lb.StartLoadBalancerDeleteTask(ctx, userCred, parasm, "") + params := jsonutils.NewDict() + params.Add(jsonutils.JSONTrue, "purge") + return nil, lb.StartLoadBalancerDeleteTask(ctx, userCred, params, "") } func (lb *SLoadbalancer) StartLoadBalancerDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error { @@ -462,6 +462,10 @@ func (lb *SLoadbalancer) Delete(ctx context.Context, userCred mcclient.TokenCred return nil } +func (lb *SLoadbalancer) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + return lb.SVirtualResourceBase.Delete(ctx, userCred) +} + func (man *SLoadbalancerManager) getLoadbalancersByRegion(region *SCloudregion, provider *SCloudprovider) ([]SLoadbalancer, error) { lbs := []SLoadbalancer{} q := man.Query().Equals("cloudregion_id", region.Id).Equals("manager_id", provider.Id) @@ -599,7 +603,7 @@ func (lb *SLoadbalancer) syncLoadbalancerNetwork(ctx context.Context, userCred m NetworkId: lb.NetworkId, Address: lb.Address, } - err := LoadbalancernetworkManager.SyncLoadbalancerNetwork(ctx, userCred, lbNetReq) + err := LoadbalancernetworkManager.syncLoadbalancerNetwork(ctx, userCred, lbNetReq) if err != nil { log.Errorf("failed to create loadbalancer network: %v", err) } diff --git a/pkg/compute/models/managedresource.go b/pkg/compute/models/managedresource.go index fe82c2da21..85c54b5d7f 100644 --- a/pkg/compute/models/managedresource.go +++ b/pkg/compute/models/managedresource.go @@ -309,3 +309,8 @@ func MakeCloudProviderInfo(region *SCloudregion, zone *SZone, provider *SCloudpr return info } + +func fetchByManagerId(manager db.IModelManager, providerId string, receiver interface{}) error { + q := manager.Query().Equals("manager_id", providerId) + return db.FetchModelObjects(manager, q, receiver) +} diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index 11ea8bf0f5..169352c19c 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -1564,7 +1564,7 @@ func (self *SNetwork) PerformMerge(ctx context.Context, userCred mcclient.TokenC } guestnetworks := make([]SGuestnetwork, 0) - err = GuestnetworkManager.Query().Equals("network_id", self.Id).All(&guestnetworks) + err = db.FetchModelObjects(GuestnetworkManager, GuestnetworkManager.Query().Equals("network_id", self.Id), &guestnetworks) if err != nil { logclient.AddActionLogWithContext(ctx, self, logclient.ACT_MERGE, err.Error(), userCred, false) return nil, err @@ -1583,7 +1583,7 @@ func (self *SNetwork) PerformMerge(ctx context.Context, userCred mcclient.TokenC } hostnetworks := make([]SHostnetwork, 0) - err = HostnetworkManager.Query().Equals("network_id", self.Id).All(&hostnetworks) + err = db.FetchModelObjects(HostnetworkManager, HostnetworkManager.Query().Equals("network_id", self.Id), &hostnetworks) if err != nil { logclient.AddActionLogWithContext(ctx, self, logclient.ACT_MERGE, err.Error(), userCred, false) return nil, err @@ -1602,7 +1602,7 @@ func (self *SNetwork) PerformMerge(ctx context.Context, userCred mcclient.TokenC } reservedips := make([]SReservedip, 0) - err = ReservedipManager.Query().Equals("network_id", self.Id).All(&reservedips) + err = db.FetchModelObjects(ReservedipManager, ReservedipManager.Query().Equals("network_id", self.Id), &reservedips) if err != nil { logclient.AddActionLogWithContext(ctx, self, logclient.ACT_MERGE, err.Error(), userCred, false) return nil, err @@ -1621,7 +1621,7 @@ func (self *SNetwork) PerformMerge(ctx context.Context, userCred mcclient.TokenC } groupnetwroks := make([]SGroupnetwork, 0) - err = GroupnetworkManager.Query().Equals("network_id", self.Id).All(&groupnetwroks) + err = db.FetchModelObjects(GroupnetworkManager, GroupnetworkManager.Query().Equals("network_id", self.Id), &groupnetwroks) if err != nil { logclient.AddActionLogWithContext(ctx, self, logclient.ACT_MERGE, err.Error(), userCred, false) return nil, err diff --git a/pkg/compute/models/purge.go b/pkg/compute/models/purge.go new file mode 100644 index 0000000000..505c836b20 --- /dev/null +++ b/pkg/compute/models/purge.go @@ -0,0 +1,680 @@ +package models + +import ( + "context" + + "yunion.io/x/log" + + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/pkg/tristate" +) + +type IPurgeableManager interface { + purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error +} + +func (eipManager *SElasticipManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + eips := make([]SElasticip, 0) + err := fetchByManagerId(eipManager, providerId, &eips) + if err != nil { + return err + } + for i := range eips { + err := eips[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (eip *SElasticip) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, eip) + defer lockman.ReleaseObject(ctx, eip) + + err := eip.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return eip.RealDelete(ctx, userCred) +} + +func (hostManager *SHostManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + hosts := make([]SHost, 0) + err := fetchByManagerId(hostManager, providerId, &hosts) + if err != nil { + return err + } + for i := range hosts { + err := hosts[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (host *SHost) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, host) + defer lockman.ReleaseObject(ctx, host) + + _, err := host.PerformDisable(ctx, userCred, nil, nil) + if err != nil { + return err + } + + guests := host.GetGuests() + for i := range guests { + err := guests[i].purge(ctx, userCred) + if err != nil { + return err + } + } + + // clean all disks on locally attached storages + storages := host._getAttachedStorages(tristate.None, tristate.None, STORAGE_LOCAL) + for i := range storages { + err := storages[i].purgeDisks(ctx, userCred) + if err != nil { + return err + } + } + + err = host.ValidatePurgeCondition(ctx) + if err != nil { + return err + } + + return host.RealDelete(ctx, userCred) +} + +func (guest *SGuest) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, guest) + defer lockman.ReleaseObject(ctx, guest) + + guest.SetDisableDelete(userCred, false) + + IsolatedDeviceManager.ReleaseDevicesOfGuest(ctx, guest, userCred) + guest.RevokeAllSecgroups(ctx, userCred) + guest.LeaveAllGroups(ctx, userCred) + guest.DetachAllNetworks(ctx, userCred) + guest.EjectIso(userCred) + guest.DeleteEip(ctx, userCred) + guest.DeleteAllDisksInDB(ctx, userCred) + + err := guest.ValidatePurgeCondition(ctx) + if err != nil { + return err + } + return guest.RealDelete(ctx, userCred) +} + +func (storage *SStorage) purgeDisks(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, storage) + defer lockman.ReleaseObject(ctx, storage) + + disks := storage.GetDisks() + for i := range disks { + err := disks[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (disk *SDisk) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, disk) + defer lockman.ReleaseObject(ctx, disk) + + err := disk.ValidatePurgeCondition(ctx) + if err != nil { + return err + } + + return disk.RealDelete(ctx, userCred) +} + +func (manager *SLoadbalancerCertificateManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + lbcs := make([]SLoadbalancerCertificate, 0) + err := fetchByManagerId(manager, providerId, &lbcs) + if err != nil { + return err + } + for i := range lbcs { + err := lbcs[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (lbcert *SLoadbalancerCertificate) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, lbcert) + defer lockman.ReleaseObject(ctx, lbcert) + + err := lbcert.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + + return lbcert.RealDelete(ctx, userCred) +} + +func (manager *SLoadbalancerAclManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + lbacls := make([]SLoadbalancerAcl, 0) + err := fetchByManagerId(manager, providerId, &lbacls) + if err != nil { + return err + } + for i := range lbacls { + err := lbacls[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (lbacl *SLoadbalancerAcl) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, lbacl) + defer lockman.ReleaseObject(ctx, lbacl) + + err := lbacl.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + + return lbacl.RealDelete(ctx, userCred) +} + +func (manager *SLoadbalancerManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + lbs := make([]SLoadbalancer, 0) + err := fetchByManagerId(manager, providerId, &lbs) + if err != nil { + return err + } + for i := range lbs { + err := lbs[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (manager *SLoadbalancernetworkManager) getAllLoadbalancerNetworks(lbId string) ([]SLoadbalancerNetwork, error) { + lbnets := make([]SLoadbalancerNetwork, 0) + q := manager.Query().Equals("loadbalancer_id", lbId) + err := db.FetchModelObjects(manager, q, &lbnets) + if err != nil { + log.Errorf("getAllLoadbalancerNetworks fail %s", err) + return nil, err + } + return lbnets, nil +} + +func (lb *SLoadbalancer) detachAllNetworks(ctx context.Context, userCred mcclient.TokenCredential) error { + lbnets, err := LoadbalancernetworkManager.getAllLoadbalancerNetworks(lb.Id) + if err != nil { + return err + } + for i := range lbnets { + err = lbnets[i].Delete(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (lb *SLoadbalancer) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, lb) + defer lockman.ReleaseObject(ctx, lb) + + err := lb.detachAllNetworks(ctx, userCred) + if err != nil { + return err + } + + err = lb.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + + return lb.RealDelete(ctx, userCred) +} + +func (manager *SLoadbalancerListenerManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + lbls := make([]SLoadbalancerListener, 0) + err := fetchByManagerId(manager, providerId, &lbls) + if err != nil { + return err + } + for i := range lbls { + err := lbls[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (lbl *SLoadbalancerListener) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, lbl) + defer lockman.ReleaseObject(ctx, lbl) + + err := lbl.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + + return lbl.RealDelete(ctx, userCred) +} + +func (manager *SLoadbalancerListenerRuleManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + lblrs := make([]SLoadbalancerListenerRule, 0) + err := fetchByManagerId(manager, providerId, &lblrs) + if err != nil { + return err + } + for i := range lblrs { + err := lblrs[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (lblr *SLoadbalancerListenerRule) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, lblr) + defer lockman.ReleaseObject(ctx, lblr) + + err := lblr.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return lblr.RealDelete(ctx, userCred) +} + +func (manager *SLoadbalancerBackendGroupManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + lbbgs := make([]SLoadbalancerBackendGroup, 0) + err := fetchByManagerId(manager, providerId, &lbbgs) + if err != nil { + return err + } + for i := range lbbgs { + err := lbbgs[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (lbbg *SLoadbalancerBackendGroup) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, lbbg) + defer lockman.ReleaseObject(ctx, lbbg) + + err := lbbg.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + + return lbbg.RealDelete(ctx, userCred) +} + +func (manager *SLoadbalancerBackendManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + lbbs := make([]SLoadbalancerBackend, 0) + err := fetchByManagerId(manager, providerId, &lbbs) + if err != nil { + return err + } + for i := range lbbs { + err := lbbs[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (lbb *SLoadbalancerBackend) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, lbb) + defer lockman.ReleaseObject(ctx, lbb) + + err := lbb.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return lbb.RealDelete(ctx, userCred) +} + +func (manager *SSnapshotManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + snapshots := make([]SSnapshot, 0) + err := fetchByManagerId(manager, providerId, &snapshots) + if err != nil { + return err + } + for i := range snapshots { + err := snapshots[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (snapshot *SSnapshot) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, snapshot) + defer lockman.ReleaseObject(ctx, snapshot) + + err := snapshot.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return snapshot.RealDelete(ctx, userCred) +} + +func (manager *SStoragecacheManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + scs := make([]SStoragecache, 0) + err := fetchByManagerId(manager, providerId, &scs) + if err != nil { + return err + } + for i := range scs { + err := scs[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (sc *SStoragecache) purgeAllCachedimages(ctx context.Context, userCred mcclient.TokenCredential) error { + cachedimages := sc.getCachedImages() + for i := range cachedimages { + err := cachedimages[i].syncRemoveCloudImage(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (sc *SStoragecache) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, sc) + defer lockman.ReleaseObject(ctx, sc) + + err := sc.purgeAllCachedimages(ctx, userCred) + if err != nil { + return err + } + + err = sc.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return sc.Delete(ctx, userCred) +} + +func (manager *SStorageManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + storages := make([]SStorage, 0) + err := fetchByManagerId(manager, providerId, &storages) + if err != nil { + return err + } + for i := range storages { + err := storages[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (storage *SStorage) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, storage) + defer lockman.ReleaseObject(ctx, storage) + + err := storage.purgeDisks(ctx, userCred) + if err != nil { + return err + } + + err = storage.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + + return storage.Delete(ctx, userCred) +} + +func (manager *SVpcManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + vpcs := make([]SVpc, 0) + err := fetchByManagerId(manager, providerId, &vpcs) + if err != nil { + return err + } + for i := range vpcs { + err := vpcs[i].Purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (net *SNetwork) purgeGuestnetworks(ctx context.Context, userCred mcclient.TokenCredential) error { + q := GuestnetworkManager.Query().Equals("network_id", net.Id) + gns := make([]SGuestnetwork, 0) + err := db.FetchModelObjects(GuestnetworkManager, q, &gns) + if err != nil { + return err + } + for i := range gns { + err = gns[i].Delete(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (net *SNetwork) purgeHostnetworks(ctx context.Context, userCred mcclient.TokenCredential) error { + q := HostnetworkManager.Query().Equals("network_id", net.Id) + hns := make([]SHostnetwork, 0) + err := db.FetchModelObjects(HostnetworkManager, q, &hns) + if err != nil { + return err + } + for i := range hns { + err = hns[i].Delete(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (net *SNetwork) purgeGroupnetworks(ctx context.Context, userCred mcclient.TokenCredential) error { + q := GroupnetworkManager.Query().Equals("network_id", net.Id) + grns := make([]SGroupnetwork, 0) + err := db.FetchModelObjects(GroupnetworkManager, q, &grns) + if err != nil { + return err + } + for i := range grns { + err = grns[i].Delete(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (net *SNetwork) purgeLoadbalancernetworks(ctx context.Context, userCred mcclient.TokenCredential) error { + q := LoadbalancernetworkManager.Query().Equals("network_id", net.Id) + lbns := make([]SLoadbalancerNetwork, 0) + err := db.FetchModelObjects(LoadbalancernetworkManager, q, &lbns) + if err != nil { + return err + } + for i := range lbns { + err = lbns[i].Delete(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (net *SNetwork) purgeReservedIps(ctx context.Context, userCred mcclient.TokenCredential) error { + q := ReservedipManager.Query().Equals("network_id", net.Id) + rips := make([]SReservedip, 0) + err := db.FetchModelObjects(ReservedipManager, q, &rips) + if err != nil { + return err + } + for i := range rips { + err = rips[i].Delete(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (net *SNetwork) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, net) + defer lockman.ReleaseObject(ctx, net) + + err := net.purgeGuestnetworks(ctx, userCred) + if err != nil { + return err + } + err = net.purgeHostnetworks(ctx, userCred) + if err != nil { + return err + } + err = net.purgeGroupnetworks(ctx, userCred) + if err != nil { + return err + } + err = net.purgeLoadbalancernetworks(ctx, userCred) + if err != nil { + return err + } + err = net.purgeReservedIps(ctx, userCred) + if err != nil { + return err + } + + err = net.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return net.RealDelete(ctx, userCred) +} + +func (wire *SWire) purgeNetworks(ctx context.Context, userCred mcclient.TokenCredential) error { + nets, err := wire.getNetworks() + if err != nil { + return err + } + for i := range nets { + err := nets[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (wire *SWire) purgeHostwires(ctx context.Context, userCred mcclient.TokenCredential) error { + hws, _ := wire.GetHostwires() + for j := range hws { + err := hws[j].Detach(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (wire *SWire) purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, wire) + defer lockman.ReleaseObject(ctx, wire) + + err := wire.purgeNetworks(ctx, userCred) + if err != nil { + return err + } + err = wire.purgeHostwires(ctx, userCred) + if err != nil { + return err + } + err = wire.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return wire.Delete(ctx, userCred) +} + +func (vpc *SVpc) purgeWires(ctx context.Context, userCred mcclient.TokenCredential) error { + wires := vpc.GetWires() + for i := range wires { + err := wires[i].purge(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (vpc *SVpc) Purge(ctx context.Context, userCred mcclient.TokenCredential) error { + lockman.LockObject(ctx, vpc) + defer lockman.ReleaseObject(ctx, vpc) + + err := vpc.purgeWires(ctx, userCred) + if err != nil { + return err + } + err = vpc.ValidateDeleteCondition(ctx) + if err != nil { + return err + } + return vpc.RealDelete(ctx, userCred) +} + +func (manager *SCloudproviderregionManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + cprs, err := CloudproviderRegionManager.fetchRecordsByCloudproviderId(providerId) + if err != nil { + return err + } + for i := range cprs { + err = cprs[i].Detach(ctx, userCred) + if err != nil { + return err + } + } + return nil +} + +func (manager *SExternalProjectManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error { + projs, err := manager.getProjectsByProviderId(providerId) + if err != nil { + return err + } + for i := range projs { + err = projs[i].Delete(ctx, userCred) + if err != nil { + return err + } + } + return nil +} diff --git a/pkg/compute/models/storages.go b/pkg/compute/models/storages.go index c2ddfa9fc4..52dded9c35 100644 --- a/pkg/compute/models/storages.go +++ b/pkg/compute/models/storages.go @@ -338,6 +338,17 @@ func (self *SStorage) GetDiskCount() int { return DiskManager.Query().Equals("storage_id", self.Id).Count() } +func (self *SStorage) GetDisks() []SDisk { + disks := make([]SDisk, 0) + q := DiskManager.Query().Equals("storage_id", self.Id) + err := db.FetchModelObjects(DiskManager, q, &disks) + if err != nil { + log.Errorf("GetDisks fail %s", err) + return nil + } + return disks +} + func (self *SStorage) GetSnapshotCount() int { return SnapshotManager.Query().Equals("storage_id", self.Id).Count() } diff --git a/pkg/compute/tasks/cloud_account_delete_task.go b/pkg/compute/tasks/cloud_account_delete_task.go new file mode 100644 index 0000000000..91abf75544 --- /dev/null +++ b/pkg/compute/tasks/cloud_account_delete_task.go @@ -0,0 +1,54 @@ +package tasks + +import ( + "context" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/compute/models" +) + +type CloudAccountDeleteTask struct { + taskman.STask +} + +func init() { + taskman.RegisterTask(CloudAccountDeleteTask{}) +} + +func (self *CloudAccountDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) { + account := obj.(*models.SCloudaccount) + + account.SetStatus(self.UserCred, api.CLOUD_PROVIDER_DELETING, "deleting") + + providers := account.GetCloudproviders() + + self.SetStage("OnAllCloudProviderDeleteComplete", nil) + + for i := range providers { + err := providers[i].StartCloudproviderDeleteTask(ctx, self.UserCred, self.GetTaskId()) + if err != nil { + account.SetStatus(self.UserCred, api.CLOUD_PROVIDER_DELETE_FAILED, err.Error()) + self.SetStageFailed(ctx, err.Error()) + return + } + } +} + +func (self *CloudAccountDeleteTask) OnAllCloudProviderDeleteComplete(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) { + account := obj.(*models.SCloudaccount) + + account.RealDelete(ctx, self.UserCred) + + self.SetStageComplete(ctx, nil) +} + +func (self *CloudAccountDeleteTask) OnAllCloudProviderDeleteCompleteFailed(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) { + account := obj.(*models.SCloudaccount) + + account.SetStatus(self.UserCred, api.CLOUD_PROVIDER_DELETE_FAILED, body.String()) + self.SetStageFailed(ctx, body.String()) +} diff --git a/pkg/compute/tasks/guest_delete_task.go b/pkg/compute/tasks/guest_delete_task.go index 7ff1ce6878..a8bffaeccd 100644 --- a/pkg/compute/tasks/guest_delete_task.go +++ b/pkg/compute/tasks/guest_delete_task.go @@ -270,7 +270,7 @@ func (self *GuestDeleteTask) OnGuestDeleteComplete(ctx context.Context, obj db.I func (self *GuestDeleteTask) DeleteGuest(ctx context.Context, guest *models.SGuest) { isPendingDeleted := guest.PendingDeleted guest.RealDelete(ctx, self.UserCred) - guest.RemoveAllMetadata(ctx, self.UserCred) + // guest.RemoveAllMetadata(ctx, self.UserCred) db.OpsLog.LogEvent(guest, db.ACT_DELOCATE, nil, self.UserCred) logclient.AddActionLogWithStartable(self, guest, logclient.ACT_DELOCATE, nil, self.UserCred, true) if !guest.IsSystem && !isPendingDeleted { diff --git a/pkg/compute/tasks/vpc_delete_task.go b/pkg/compute/tasks/vpc_delete_task.go index 8062393c88..041ee50fb2 100644 --- a/pkg/compute/tasks/vpc_delete_task.go +++ b/pkg/compute/tasks/vpc_delete_task.go @@ -72,18 +72,11 @@ func (self *VpcDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, return } - wires := vpc.GetWires() - if wires != nil { - for i := 0; i < len(wires); i += 1 { - hws, _ := wires[i].GetHostwires() - for j := 0; hws != nil && j < len(hws); j += 1 { - hws[j].Detach(ctx, self.UserCred) - } - wires[i].Delete(ctx, self.UserCred) - } + err = vpc.Purge(ctx, self.UserCred) + if err != nil { + self.taskFailed(ctx, vpc, err) + return } - vpc.RealDelete(ctx, self.UserCred) - self.SetStageComplete(ctx, nil) } diff --git a/pkg/util/aws/region.go b/pkg/util/aws/region.go index ab1de2061d..0778fb4b94 100644 --- a/pkg/util/aws/region.go +++ b/pkg/util/aws/region.go @@ -111,7 +111,7 @@ func (self *SRegion) getIamClient() (*iam.IAM, error) { return self.iamClient, nil } -func (self *SRegion) getS3Client() (*s3.S3, error) { +func (self *SRegion) GetS3Client() (*s3.S3, error) { if self.s3Client == nil { s, err := self.getAwsSession() diff --git a/pkg/util/aws/shell/s3.go b/pkg/util/aws/shell/s3.go new file mode 100644 index 0000000000..e0dbac5c9b --- /dev/null +++ b/pkg/util/aws/shell/s3.go @@ -0,0 +1,24 @@ +package shell + +import ( + "github.com/aws/aws-sdk-go/service/s3" + "yunion.io/x/onecloud/pkg/util/aws" + "yunion.io/x/onecloud/pkg/util/shellutils" +) + +func init() { + type S3BucketListOptions struct { + } + shellutils.R(&S3BucketListOptions{}, "s3-list", "List all buckets", func(cli *aws.SRegion, args *S3BucketListOptions) error { + s3cli, err := cli.GetS3Client() + if err != nil { + return err + } + output, err := s3cli.ListBuckets(&s3.ListBucketsInput{}) + if err != nil { + return err + } + printList(output.Buckets, 0, 0, 0, nil) + return nil + }) +} diff --git a/pkg/util/aws/storagecache.go b/pkg/util/aws/storagecache.go index f74790f46b..639cb6737e 100644 --- a/pkg/util/aws/storagecache.go +++ b/pkg/util/aws/storagecache.go @@ -164,7 +164,7 @@ func (self *SStoragecache) uploadImage(ctx context.Context, userCred mcclient.To } // checking remote - s3client, err := self.region.getS3Client() + s3client, err := self.region.GetS3Client() if err != nil { return "", err } @@ -297,7 +297,7 @@ func (self *SStoragecache) downloadImage(userCred mcclient.TokenCredential, imag return nil, err } - s3Client, err := self.region.getS3Client() + s3Client, err := self.region.GetS3Client() if err != nil { return nil, err } @@ -338,7 +338,7 @@ func (self *SRegion) checkBucket(bucketName string) error { } func (self *SRegion) IsBucketExist(bucketName string) (bool, error) { - s3Client, err := self.getS3Client() + s3Client, err := self.GetS3Client() if err != nil { return false, err } @@ -359,7 +359,7 @@ func (self *SRegion) IsBucketExist(bucketName string) (bool, error) { } func (self *SRegion) GetBucketRegionId(bucketName string) (string, error) { - s3Client, err := self.getS3Client() + s3Client, err := self.GetS3Client() if err != nil { return "", err } @@ -491,7 +491,7 @@ func (self *SRegion) initVmimportBucket(bucketName string) error { return nil } - s3Client, err := self.getS3Client() + s3Client, err := self.GetS3Client() if err != nil { return err } diff --git a/pkg/util/esxi/shell/host.go b/pkg/util/esxi/shell/host.go index 617bd334b9..565b4e51ac 100644 --- a/pkg/util/esxi/shell/host.go +++ b/pkg/util/esxi/shell/host.go @@ -47,4 +47,17 @@ func init() { printObject(host) return nil }) + + shellutils.R(&HostShowOptions{}, "host-storages", "Show all storages of a given host", func(cli *esxi.SESXiClient, args *HostShowOptions) error { + host, err := cli.FindHostByIp(args.IP) + if err != nil { + return err + } + storages, err := host.GetIStorages() + if err != nil { + return err + } + printList(storages, nil) + return nil + }) }