From 068136d6abd764a0a2713646d28a9d8ac0c6d7b5 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Wed, 8 Aug 2018 23:00:01 +0800 Subject: [PATCH 1/4] temporary commit --- pkg/compute/models/cloudproviders.go | 7 +++++-- pkg/compute/models/networks.go | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index 823a79aa53..c01c64420e 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -51,7 +51,7 @@ type SCloudprovider struct { LastSync time.Time `get:"admin" list:"admin"` // = Column(DateTime, nullable=True) - // Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True) + Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True) Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True) @@ -138,6 +138,9 @@ func (self *SCloudprovider) getPassword() (string, error) { } func (self *SCloudprovider) CanSync() bool { + if ! self.Enabled { + return false + } if self.Status == CLOUD_PROVIDER_SYNCING { if self.LastSync.IsZero() || time.Now().Sub(self.LastSync) > 900*time.Second { return true @@ -215,7 +218,7 @@ func (self *SCloudprovider) PerformUpdateCredential(ctx context.Context, userCre } changed = true } - if changed && self.CanSync() { + if changed { self.SetStatus(userCred, CLOUD_PROVIDER_INIT, "Change credential") self.startSyncCloudProviderInfoTask(ctx, userCred, nil, "") } diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index c2e530d8e7..7bfdb91174 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -834,7 +834,7 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred maskLen64 = int64(prefix.MaskLen) } else { ipStartStr, _ := data.GetString("guest_ip_start") - ipEndStr, _ := data.GetString("guest_ip_start") + ipEndStr, _ := data.GetString("guest_ip_end") startIp, err = netutils.NewIPV4Addr(ipStartStr) if err != nil { return nil, httperrors.NewInputParameterError("Invalid start ip: %s %s", ipStartStr, err) @@ -971,7 +971,7 @@ func (self *SNetwork) ValidateUpdateData(ctx context.Context, userCred mcclient. var err error ipStartStr, _ := data.GetString("guest_ip_start") - ipEndStr, _ := data.GetString("guest_ip_start") + ipEndStr, _ := data.GetString("guest_ip_end") if len(ipStartStr) > 0 || len(ipEndStr) > 0 { if self.isManaged() { From fa6176267a2877c1d3b389e6a54247babc701f40 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 9 Aug 2018 00:38:36 +0800 Subject: [PATCH 2/4] temp commit --- cmd/climc/shell/cloudproviders.go | 4 ++++ pkg/compute/models/cloudproviders.go | 21 ++++++++++++------- .../tasks/cloud_provider_sync_info_task.go | 6 +++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/cmd/climc/shell/cloudproviders.go b/cmd/climc/shell/cloudproviders.go index 8f56210327..fae9483f5f 100644 --- a/cmd/climc/shell/cloudproviders.go +++ b/cmd/climc/shell/cloudproviders.go @@ -142,6 +142,7 @@ func init() { type CloudproviderSyncOptions struct { ID string `help:"ID or Name of cloud provider"` Force bool `help:"Force sync no matter what"` + FullSync bool `help:"Synchronize everything"` Region []string `help:"region to sync"` Zone []string `help:"region to sync"` Host []string `help:"region to sync"` @@ -151,6 +152,9 @@ func init() { if args.Force { params.Add(jsonutils.JSONTrue, "force") } + if args.FullSync { + params.Add(jsonutils.JSONTrue, "full_sync") + } if len(args.Region) > 0 { params.Add(jsonutils.NewStringArray(args.Region), "region") } diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index c01c64420e..d971bfb65b 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -138,9 +138,6 @@ func (self *SCloudprovider) getPassword() (string, error) { } func (self *SCloudprovider) CanSync() bool { - if ! self.Enabled { - return false - } if self.Status == CLOUD_PROVIDER_SYNCING { if self.LastSync.IsZero() || time.Now().Sub(self.LastSync) > 900*time.Second { return true @@ -153,10 +150,11 @@ func (self *SCloudprovider) CanSync() bool { } type SSyncRange struct { - Force bool - Region []string - Zone []string - Host []string + Force bool + FullSync bool + Region []string + Zone []string + Host []string } func (self *SCloudprovider) AllowPerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { @@ -164,10 +162,13 @@ func (self *SCloudprovider) AllowPerformSync(ctx context.Context, userCred mccli } func (self *SCloudprovider) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if ! self.Enabled { + return nil, httperrors.NewInvalidStatusError("Cloudprovider disabled") + } syncRange := SSyncRange{} err := data.Unmarshal(&syncRange) if err != nil { - return nil, httperrors.NewInputParameterError("invalud input %s", err) + return nil, httperrors.NewInputParameterError("invalid input %s", err) } if self.CanSync() || syncRange.Force { err = self.startSyncCloudProviderInfoTask(ctx, userCred, &syncRange, "") @@ -180,6 +181,10 @@ func (self *SCloudprovider) AllowPerformUpdateCredential(ctx context.Context, us } func (self *SCloudprovider) PerformUpdateCredential(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if ! self.Enabled { + return nil, httperrors.NewInvalidStatusError("Cloudprovider disabled") + } + var err error changed := false secret, _ := data.GetString("secret") diff --git a/pkg/compute/tasks/cloud_provider_sync_info_task.go b/pkg/compute/tasks/cloud_provider_sync_info_task.go index ba0b27e77b..2cf6e2a02e 100644 --- a/pkg/compute/tasks/cloud_provider_sync_info_task.go +++ b/pkg/compute/tasks/cloud_provider_sync_info_task.go @@ -80,7 +80,7 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider, db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred) for i := 0; i < len(localRegions); i += 1 { - if len(syncRange.Region) > 0 && !utils.IsInStringArray(remoteRegions[i].GetId(), syncRange.Region) { + if !syncRange.FullSync && len(syncRange.Region) > 0 && !utils.IsInStringArray(remoteRegions[i].GetId(), syncRange.Region) { continue } @@ -91,7 +91,7 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider, if localZones != nil && remoteZones != nil { for j := 0; j < len(localZones); j += 1 { - if len(syncRange.Zone) > 0 && !utils.IsInStringArray(remoteZones[j].GetId(), syncRange.Zone) { + if !syncRange.FullSync && len(syncRange.Zone) > 0 && !utils.IsInStringArray(remoteZones[j].GetId(), syncRange.Zone) { continue } syncZoneStorages(ctx, provider, task, &localZones[j], remoteZones[j]) @@ -258,7 +258,7 @@ func syncZoneHosts(ctx context.Context, provider *models.SCloudprovider, task *C db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred) for i := 0; i < len(localHosts); i += 1 { - if len(syncRange.Host) > 0 && !utils.IsInStringArray(remoteHosts[i].GetGlobalId(), syncRange.Host) { + if !syncRange.FullSync && len(syncRange.Host) > 0 && !utils.IsInStringArray(remoteHosts[i].GetGlobalId(), syncRange.Host) { continue } syncHostStorages(ctx, provider, task, &localHosts[i], remoteHosts[i]) From f0ec8a563ebabbeeceb231542d323158d71eba42 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 9 Aug 2018 17:49:17 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9A1.=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4VPC=E5=AF=BC=E8=87=B4hostwire=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=B8=8D=E4=B8=80=E8=87=B4=E9=97=AE=E9=A2=98=202.=20=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91=E4=B8=BB=E6=9C=BA=E6=97=A0=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E4=BF=A1=E6=81=AF=203.=20=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E4=B8=80=E4=BA=9BBUGfix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cloudcommon/db/taskman/subtasks.go | 5 +- pkg/compute/guestdrivers/aliyun.go | 18 +++- pkg/compute/guestdrivers/managedvirtual.go | 17 +++- pkg/compute/guestdrivers/virtualization.go | 10 +- pkg/compute/models/cloudproviders.go | 99 ++++++++++++++++++- pkg/compute/models/hosts.go | 35 ++++++- pkg/compute/models/networks.go | 9 +- pkg/compute/models/storagecachedimages.go | 14 +-- pkg/compute/models/storagecaches.go | 2 +- pkg/compute/models/vpcs.go | 49 +++++---- pkg/compute/models/wires.go | 47 ++++++++- .../tasks/cloud_provider_sync_info_task.go | 9 +- pkg/compute/tasks/guest_syncstatus_task.go | 1 + pkg/compute/tasks/vpc_delete_task.go | 4 + pkg/util/aliyun/aliyun.go | 5 +- pkg/util/aliyun/instance.go | 6 +- pkg/util/aliyun/provider/provider.go | 1 + pkg/util/aliyun/region.go | 23 +++++ pkg/util/aliyun/shell/instance.go | 9 ++ pkg/util/seclib2/seclib.go | 47 +++++++++ 20 files changed, 363 insertions(+), 47 deletions(-) create mode 100644 pkg/util/seclib2/seclib.go diff --git a/pkg/cloudcommon/db/taskman/subtasks.go b/pkg/cloudcommon/db/taskman/subtasks.go index efbe83a605..40b3c6d23b 100644 --- a/pkg/cloudcommon/db/taskman/subtasks.go +++ b/pkg/cloudcommon/db/taskman/subtasks.go @@ -5,6 +5,7 @@ import ( "github.com/yunionio/log" "github.com/yunionio/onecloud/pkg/cloudcommon/db" + "database/sql" ) const ( @@ -37,7 +38,9 @@ func (manager *SSubTaskmanager) GetSubTask(ptaskId string, subtaskId string) *SS subtask := SSubTask{} err := manager.Query().Equals("task_id", ptaskId).Equals("subtask_id", subtaskId).First(&subtask) if err != nil { - log.Errorf("GetSubTask fail %s", err) + if err != sql.ErrNoRows { + log.Errorf("GetSubTask fail %s", err) + } return nil } return &subtask diff --git a/pkg/compute/guestdrivers/aliyun.go b/pkg/compute/guestdrivers/aliyun.go index 3e7b821dfb..77933e033e 100644 --- a/pkg/compute/guestdrivers/aliyun.go +++ b/pkg/compute/guestdrivers/aliyun.go @@ -9,13 +9,13 @@ import ( "github.com/yunionio/log" "github.com/yunionio/onecloud/pkg/httperrors" "github.com/yunionio/onecloud/pkg/mcclient" - "github.com/yunionio/pkg/util/seclib" "github.com/yunionio/pkg/utils" "github.com/yunionio/onecloud/pkg/cloudcommon/db" "github.com/yunionio/onecloud/pkg/cloudcommon/db/taskman" "github.com/yunionio/onecloud/pkg/cloudprovider" "github.com/yunionio/onecloud/pkg/compute/models" + "github.com/yunionio/onecloud/pkg/util/seclib2" ) type SAliyunGuestDriver struct { @@ -62,6 +62,8 @@ func (self *SAliyunGuestDriver) ValidateCreateData(ctx context.Context, userCred type SAliyunVMCreateConfig struct { Name string ExternalImageId string + OsDistribution string + OsVersion string Cpu int Memory int ExternalNetworkId string @@ -101,6 +103,11 @@ func (self *SAliyunGuestDriver) GetJsonDescAtHost(ctx context.Context, guest *mo imageId := disk.GetTemplateId() scimg := models.StoragecachedimageManager.GetStoragecachedimage(cache.Id, imageId) config.ExternalImageId = scimg.ExternalId + + img := scimg.GetCachedimage() + config.OsDistribution, _ = img.Info.GetString("properties", "os_distribution") + config.OsVersion, _ = img.Info.GetString("properties", "os_version") + config.SysDiskSize = disk.DiskSize / 1024 // MB => GB } else { config.DataDisks[i-1] = disk.DiskSize / 1024 // MB => GB @@ -143,7 +150,7 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu } taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - passwd := seclib.RandomPassword(12) + passwd := seclib2.RandomPassword2(12) iVM, err := ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId, desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, desc.PublicKey) @@ -180,6 +187,13 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu data.Add(jsonutils.NewString("root"), "account") data.Add(jsonutils.NewString(encpasswd), "key") + if len(desc.OsDistribution) > 0 { + data.Add(jsonutils.NewString(desc.OsDistribution), "distro") + } + if len(desc.OsVersion) > 0 { + data.Add(jsonutils.NewString(desc.OsVersion), "version") + } + idisks, err := iVM.GetIDisks() if err != nil { diff --git a/pkg/compute/guestdrivers/managedvirtual.go b/pkg/compute/guestdrivers/managedvirtual.go index ed31af62c8..844bc16907 100644 --- a/pkg/compute/guestdrivers/managedvirtual.go +++ b/pkg/compute/guestdrivers/managedvirtual.go @@ -111,8 +111,23 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncstatusOnHost(ctx context. log.Errorf("fail to find ivm by id %s", err) return nil, err } + + status := ivm.GetStatus() + switch status { + case models.VM_RUNNING: + status = cloudprovider.CloudVMStatusRunning + case models.VM_READY: + status = cloudprovider.CloudVMStatusStopped + case models.VM_STARTING: + status = cloudprovider.CloudVMStatusStopped + case models.VM_STOPPING: + status = cloudprovider.CloudVMStatusRunning + default: + status = cloudprovider.CloudVMStatusOther + } + body := jsonutils.NewDict() - body.Add(jsonutils.NewString(ivm.GetStatus()), "status") + body.Add(jsonutils.NewString(status), "status") return body, nil } diff --git a/pkg/compute/guestdrivers/virtualization.go b/pkg/compute/guestdrivers/virtualization.go index fc0b1a8a8f..3d5ba86572 100644 --- a/pkg/compute/guestdrivers/virtualization.go +++ b/pkg/compute/guestdrivers/virtualization.go @@ -6,6 +6,7 @@ import ( "regexp" "github.com/yunionio/jsonutils" + "github.com/yunionio/log" "github.com/yunionio/onecloud/pkg/httperrors" "github.com/yunionio/onecloud/pkg/mcclient" @@ -41,11 +42,18 @@ func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest, if len(netConfig.Wire) > 0 { wirePattern = regexp.MustCompile(netConfig.Wire) } - hostwires := host.GetWires() + hostwires := host.GetHostwires() netsAvaiable := make([]models.SNetwork, 0) for i := 0; i < len(hostwires); i += 1 { hostwire := hostwires[i] wire := hostwire.GetWire() + + if wire == nil { + continue + } + + log.Debugf("Wire %#v", wire) + if wirePattern != nil && !wirePattern.MatchString(wire.Id) && wirePattern.MatchString(wire.Name) { continue } diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index 64d5149b92..bac94dc7d9 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -123,10 +123,21 @@ func (self *SCloudprovider) PostCreate(ctx context.Context, userCred mcclient.To } func (self *SCloudprovider) savePassword(secret string) error { - sec, err := utils.EncryptAESBase64(self.Id, self.Secret) + sec, err := utils.EncryptAESBase64(self.Id, secret) if err != nil { return err } + + /*log.Debugf("savePassword %s => %s", secret, sec) + newsec, err := utils.DescryptAESBase64(self.Id, sec) + if err != nil { + return err + } + if newsec != secret { + log.Errorf("Encrypt/Descrypt mismatch!!") + return fmt.Errorf("Encrypt/Descrypt mismatch!!") + }*/ + _, err = self.GetModelManager().TableSpec().Update(self, func() error { self.Secret = sec return nil @@ -158,6 +169,89 @@ type SSyncRange struct { Host []string } +func (sr *SSyncRange) NeedSyncInfo() bool { + if sr.FullSync { + return true + } + if sr.Region != nil && len(sr.Region) > 0 { + return true + } + if sr.Zone != nil && len(sr.Zone) > 0 { + return true + } + if sr.Host != nil && len(sr.Host) > 0 { + return true + } + return false +} + +func (sr *SSyncRange) normalizeRegionIds() error { + for i := 0; i < len(sr.Region); i += 1 { + obj, err := CloudregionManager.FetchByIdOrName("", sr.Region[i]) + if err != nil { + if err == sql.ErrNoRows { + return httperrors.NewResourceNotFoundError("Region %s not found", sr.Region[i]) + } else { + return err + } + } + sr.Region[i] = obj.GetId() + } + return nil +} + +func (sr *SSyncRange) normalizeZoneIds() error { + for i := 0; i < len(sr.Zone); i += 1 { + obj, err := ZoneManager.FetchByIdOrName("", sr.Zone[i]) + if err != nil { + if err == sql.ErrNoRows { + return httperrors.NewResourceNotFoundError("Zone %s not found", sr.Zone[i]) + } else { + return err + } + } + sr.Zone[i] = obj.GetId() + } + return nil +} + +func (sr *SSyncRange) normalizeHostIds() error { + for i := 0; i < len(sr.Host); i += 1 { + obj, err := HostManager.FetchByIdOrName("", sr.Host[i]) + if err != nil { + if err == sql.ErrNoRows { + return httperrors.NewResourceNotFoundError("Host %s not found", sr.Host[i]) + } else { + return err + } + } + sr.Host[i] = obj.GetId() + } + return nil +} + +func (sr *SSyncRange) Normalize() error { + if sr.Region != nil && len(sr.Region) > 0 { + err := sr.normalizeRegionIds() + if err != nil { + return err + } + } + if sr.Zone != nil && len(sr.Zone) > 0 { + err := sr.normalizeZoneIds() + if err != nil { + return err + } + } + if sr.Host != nil && len(sr.Host) > 0 { + err := sr.normalizeHostIds() + if err != nil { + return err + } + } + return nil +} + func (self *SCloudprovider) AllowPerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { return userCred.IsSystemAdmin() } @@ -260,10 +354,13 @@ func (self *SCloudprovider) GetDriver() (cloudprovider.ICloudProvider, error) { if !self.Enabled { return nil, fmt.Errorf("Cloud provider is not enabled") } + secret, err := self.getPassword() if err != nil { return nil, fmt.Errorf("Invalid password %s", err) } + // log.Debugf("XXXXX secret: %s", secret) + return cloudprovider.GetProvider(self.Id, self.Name, self.AccessUrl, self.Account, secret, self.Provider) } diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index a784d4375c..69e3ff7fa5 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -344,8 +344,9 @@ func (self *SHost) RealDelete(ctx context.Context, userCred mcclient.TokenCreden for _, netif := range self.GetNetInterfaces() { netif.Remove(ctx, userCred) } - for _, hostwire := range self.GetWires() { - hostwire.Delete(ctx, userCred) + for _, hostwire := range self.GetHostwires() { + hostwire.Detach(ctx, userCred) + // hostwire.Delete(ctx, userCred) } return self.SEnabledStatusStandaloneResourceBase.Delete(ctx, userCred) } @@ -572,7 +573,7 @@ func (self *SHost) GetWireCount() int { return self.GetWiresQuery().Count() } -func (self *SHost) GetWires() []SHostwire { +func (self *SHost) GetHostwires() []SHostwire { hw := make([]SHostwire, 0) q := self.GetWiresQuery() err := db.FetchModelObjects(HostwireManager, q, &hw) @@ -897,7 +898,19 @@ func (manager *SHostManager) newFromCloudHost(extHost cloudprovider.ICloudHost, func (self *SHost) SyncHostStorages(ctx context.Context, userCred mcclient.TokenCredential, storages []cloudprovider.ICloudStorage) compare.SyncResult { syncResult := compare.SyncResult{} - dbStorages := self._getAttachedStorages(tristate.None, tristate.None) + dbStorages := make([]SStorage, 0) + + hostStorages := self.GetHoststorages() + for i := 0; i < len(hostStorages); i += 1 { + storage := hostStorages[i].GetStorage() + if storage == nil { + hostStorages[i].Delete(ctx, userCred) + } else { + dbStorages = append(dbStorages, *storage) + } + } + + // dbStorages := self._getAttachedStorages(tristate.None, tristate.None) removed := make([]SStorage, 0) commondb := make([]SStorage, 0) @@ -980,7 +993,19 @@ func (self *SHost) newCloudHostStorage(ctx context.Context, userCred mcclient.To func (self *SHost) SyncHostWires(ctx context.Context, userCred mcclient.TokenCredential, wires []cloudprovider.ICloudWire) compare.SyncResult { syncResult := compare.SyncResult{} - dbWires := self.getAttachedWires() + dbWires := make([]SWire, 0) + + hostWires := self.GetHostwires() + for i := 0; i < len(hostWires); i += 1 { + wire := hostWires[i].GetWire() + if wire == nil { + hostWires[i].Delete(ctx, userCred) + } else { + dbWires = append(dbWires, *wire) + } + } + + // dbWires := self.getAttachedWires() removed := make([]SWire, 0) commondb := make([]SWire, 0) diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index 7bfdb91174..b804684420 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -41,6 +41,7 @@ const ( NETWORK_STATUS_PENDING = "pending" NETWORK_STATUS_AVAILABLE = "available" NETWORK_STATUS_FAILED = "failed" + NETWORK_STATUS_UNKNOWN = "unknown" NETWORK_STATUS_START_DELETE = "start_delete" NETWORK_STATUS_DELETING = "deleting" NETWORK_STATUS_DELETED = "deleted" @@ -413,7 +414,7 @@ func (manager *SNetworkManager) SyncNetworks(ctx context.Context, userCred mccli } for i := 0; i < len(removed); i += 1 { - err = removed[i].ValidateDeleteCondition(ctx) + /*err = removed[i].ValidateDeleteCondition(ctx) if err != nil { // cannot delete syncResult.DeleteError(err) } else { @@ -423,6 +424,12 @@ func (manager *SNetworkManager) SyncNetworks(ctx context.Context, userCred mccli } else { syncResult.Delete() } + }*/ + err = removed[i].SetStatus(userCred, NETWORK_STATUS_UNKNOWN, "Sync to remove") + if err != nil { + syncResult.DeleteError(err) + } else { + syncResult.Delete() } } for i := 0; i < len(commondb); i += 1 { diff --git a/pkg/compute/models/storagecachedimages.go b/pkg/compute/models/storagecachedimages.go index c40282b28b..ef9825973d 100644 --- a/pkg/compute/models/storagecachedimages.go +++ b/pkg/compute/models/storagecachedimages.go @@ -78,7 +78,7 @@ func (manager *SStoragecachedimageManager) AllowListDescendent(ctx context.Conte return userCred.IsSystemAdmin() } -func (self *SStoragecachedimage) getCachedimage() *SCachedimage { +func (self *SStoragecachedimage) GetCachedimage() *SCachedimage { cachedImage, _ := CachedimageManager.FetchById(self.CachedimageId) if cachedImage != nil { return cachedImage.(*SCachedimage) @@ -86,7 +86,7 @@ func (self *SStoragecachedimage) getCachedimage() *SCachedimage { return nil } -func (self *SStoragecachedimage) getStoragecache() *SStoragecache { +func (self *SStoragecachedimage) GetStoragecache() *SStoragecache { cache, _ := StoragecacheManager.FetchById(self.StoragecacheId) if cache != nil { return cache.(*SStoragecache) @@ -95,11 +95,11 @@ func (self *SStoragecachedimage) getStoragecache() *SStoragecache { } func (self *SStoragecachedimage) getExtraDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict { - storagecache := self.getStoragecache() + storagecache := self.GetStoragecache() if storagecache != nil { extra.Add(jsonutils.NewStringArray(storagecache.getStorageNames()), "storages") } - cachedImage := self.getCachedimage() + cachedImage := self.GetCachedimage() if cachedImage != nil { extra.Add(jsonutils.NewString(cachedImage.getName()), "image") extra.Add(jsonutils.NewInt(cachedImage.Size), "size") @@ -158,7 +158,7 @@ func (self *SStoragecachedimage) ValidateDeleteCondition(ctx context.Context) er if !self.isDownloadSessionExpire() { return httperrors.NewResourceBusyError("Active download session not expired") } - image := self.getCachedimage() + image := self.GetCachedimage() if !image.canDeleteLastCache() { return httperrors.NewResourceBusyError("Cannot delete the last cache") } @@ -179,8 +179,8 @@ func (self *SStoragecachedimage) markDeleting(ctx context.Context, userCred mccl return err } - cache := self.getStoragecache() - image := self.getCachedimage() + cache := self.GetStoragecache() + image := self.GetCachedimage() lockman.LockJointObject(ctx, cache, image) defer lockman.ReleaseJointObject(ctx, cache, image) diff --git a/pkg/compute/models/storagecaches.go b/pkg/compute/models/storagecaches.go index fd9b2e8cbf..8be99871c8 100644 --- a/pkg/compute/models/storagecaches.go +++ b/pkg/compute/models/storagecaches.go @@ -136,7 +136,7 @@ func (self *SStoragecache) getCachedImageSize() int64 { } var size int64 = 0 for _, img := range images { - imginfo := img.getCachedimage() + imginfo := img.GetCachedimage() size += imginfo.Size } return size diff --git a/pkg/compute/models/vpcs.go b/pkg/compute/models/vpcs.go index bfe95fd84f..762396dd73 100644 --- a/pkg/compute/models/vpcs.go +++ b/pkg/compute/models/vpcs.go @@ -25,6 +25,7 @@ const ( VPC_STATUS_DELETING = "deleting" VPC_STATUS_DELETE_FAILED = "delete_failed" VPC_STATUS_DELETED = "deleted" + VPC_STATUS_UNKNOWN = "unknown" MAX_VPC_PER_REGION = 3 ) @@ -189,25 +190,26 @@ func (manager *SVpcManager) SyncVPCs(ctx context.Context, userCred mcclient.Toke } for i := 0; i < len(removed); i += 1 { - err = removed[i].ValidateDeleteCondition(ctx) - if err != nil { // cannot delete - _, err = removed[i].PerformDisable(ctx, userCred, nil, nil) - if err == nil { - err = removed[i].SetStatus(userCred, VPC_STATUS_PENDING, "sync to delete") - } - if err != nil { - syncResult.DeleteError(err) - } else { - syncResult.Delete() - } - } else { - err = removed[i].Delete(ctx, userCred) - if err != nil { - syncResult.DeleteError(err) - } else { - syncResult.Delete() - } + // err = removed[i].ValidateDeleteCondition(ctx) + // if err != nil { // cannot delete + removed[i].markAllNetworksUnknown(userCred) + _, err = removed[i].PerformDisable(ctx, userCred, nil, nil) + if err == nil { + err = removed[i].SetStatus(userCred, VPC_STATUS_UNKNOWN, "sync to delete") } + if err != nil { + syncResult.DeleteError(err) + } else { + syncResult.Delete() + } + // } else { + // err = removed[i].Delete(ctx, userCred) + // if err != nil { + // syncResult.DeleteError(err) + // } else { + // syncResult.Delete() + // } + // } } for i := 0; i < len(commondb); i += 1 { err = commondb[i].SyncWithCloudVpc(commonext[i]) @@ -274,6 +276,17 @@ func (manager *SVpcManager) newFromCloudVpc(extVPC cloudprovider.ICloudVpc, regi return &vpc, nil } +func (self *SVpc) markAllNetworksUnknown(userCred mcclient.TokenCredential) error { + wires := self.GetWires() + if wires == nil || len(wires) == 0 { + return nil + } + for i := 0; i <= len(wires); i += 1 { + wires[i].markNetworkUnknown(userCred) + } + return nil +} + func (manager *SVpcManager) InitializeData() error { vpcObj, err := manager.FetchById("default") if err != nil { diff --git a/pkg/compute/models/wires.go b/pkg/compute/models/wires.go index 5708343f77..e3223a6645 100644 --- a/pkg/compute/models/wires.go +++ b/pkg/compute/models/wires.go @@ -83,11 +83,25 @@ func (wire *SWire) ValidateDeleteCondition(ctx context.Context) error { return wire.SStandaloneResourceBase.ValidateDeleteCondition(ctx) } +func (wire *SWire) getHostwireQuery() *sqlchemy.SQuery { + return HostwireManager.Query().Equals("wire_id", wire.Id) +} + func (wire *SWire) HostCount() int { - q := HostwireManager.Query().Equals("wire_id", wire.Id) + q := wire.getHostwireQuery() return q.Count() } +func (wire *SWire) GetHostwires() ([]SHostwire, error) { + q := wire.getHostwireQuery() + hostwires := make([]SHostwire, 0) + err := db.FetchModelObjects(HostwireManager, q, &hostwires) + if err != nil { + return nil, err + } + return hostwires, nil +} + func (wire *SWire) NetworkCount() int { q := NetworkManager.Query().Equals("wire_id", wire.Id) return q.Count() @@ -141,7 +155,13 @@ func (manager *SWireManager) SyncWires(ctx context.Context, userCred mcclient.To } for i := 0; i < len(removed); i += 1 { - err = removed[i].ValidateDeleteCondition(ctx) + err = removed[i].markNetworkUnknown(userCred) + if err != nil { // cannot delete + syncResult.DeleteError(err) + } else { + syncResult.Delete() + } + /* err = removed[i].ValidateDeleteCondition(ctx) if err != nil { // cannot delete syncResult.DeleteError(err) } else { @@ -151,7 +171,7 @@ func (manager *SWireManager) SyncWires(ctx context.Context, userCred mcclient.To } else { syncResult.Delete() } - } + }*/ } for i := 0; i < len(commondb); i += 1 { err = commondb[i].syncWithCloudWire(commonext[i]) @@ -192,6 +212,17 @@ func (self *SWire) syncWithCloudWire(extWire cloudprovider.ICloudWire) error { return err } +func (self *SWire) markNetworkUnknown(userCred mcclient.TokenCredential) error { + nets, err := self.getNetworks() + if err != nil { + return err + } + for i := 0; i < len(nets); i += 1 { + nets[i].SetStatus(userCred, NETWORK_STATUS_UNKNOWN, "wire sync to remove") + } + return nil +} + func (manager *SWireManager) newFromCloudWire(extWire cloudprovider.ICloudWire, vpc *SVpc) (*SWire, error) { wire := SWire{} wire.SetModelManager(manager) @@ -303,6 +334,16 @@ func (self *SWire) getNetworkQuery() *sqlchemy.SQuery { return NetworkManager.Query().Equals("wire_id", self.Id) } +func (self *SWire) getNetworks() ([]SNetwork, error) { + q := self.getNetworkQuery() + nets := make([]SNetwork, 0) + err := db.FetchModelObjects(NetworkManager, q, &nets) + if err != nil { + return nil, err + } + return nets, nil +} + func (self *SWire) getGatewayNetworkQuery() *sqlchemy.SQuery { q := self.getNetworkQuery() q = q.IsNotNull("guest_gateway").IsNotEmpty("guest_gateway") diff --git a/pkg/compute/tasks/cloud_provider_sync_info_task.go b/pkg/compute/tasks/cloud_provider_sync_info_task.go index 2cf6e2a02e..a6f6cf2348 100644 --- a/pkg/compute/tasks/cloud_provider_sync_info_task.go +++ b/pkg/compute/tasks/cloud_provider_sync_info_task.go @@ -52,7 +52,8 @@ func (self *CloudProviderSyncInfoTask) OnInit(ctx context.Context, obj db.IStand if syncRangeJson != nil { syncRange := models.SSyncRange{} err = syncRangeJson.Unmarshal(&syncRange) - if err == nil { + if err == nil && syncRange.NeedSyncInfo() { + syncRange.Normalize() syncCloudProviderInfo(ctx, provider, self, driver, &syncRange) } } @@ -80,7 +81,7 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider, db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred) for i := 0; i < len(localRegions); i += 1 { - if !syncRange.FullSync && len(syncRange.Region) > 0 && !utils.IsInStringArray(remoteRegions[i].GetId(), syncRange.Region) { + if len(syncRange.Region) > 0 && !utils.IsInStringArray(localRegions[i].Id, syncRange.Region) { continue } @@ -91,7 +92,7 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider, if localZones != nil && remoteZones != nil { for j := 0; j < len(localZones); j += 1 { - if !syncRange.FullSync && len(syncRange.Zone) > 0 && !utils.IsInStringArray(remoteZones[j].GetId(), syncRange.Zone) { + if len(syncRange.Zone) > 0 && !utils.IsInStringArray(localZones[j].Id, syncRange.Zone) { continue } syncZoneStorages(ctx, provider, task, &localZones[j], remoteZones[j]) @@ -258,7 +259,7 @@ func syncZoneHosts(ctx context.Context, provider *models.SCloudprovider, task *C db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred) for i := 0; i < len(localHosts); i += 1 { - if !syncRange.FullSync && len(syncRange.Host) > 0 && !utils.IsInStringArray(remoteHosts[i].GetGlobalId(), syncRange.Host) { + if len(syncRange.Host) > 0 && !utils.IsInStringArray(localHosts[i].Id, syncRange.Host) { continue } syncHostStorages(ctx, provider, task, &localHosts[i], remoteHosts[i]) diff --git a/pkg/compute/tasks/guest_syncstatus_task.go b/pkg/compute/tasks/guest_syncstatus_task.go index 201c20cd66..bb8431fff3 100644 --- a/pkg/compute/tasks/guest_syncstatus_task.go +++ b/pkg/compute/tasks/guest_syncstatus_task.go @@ -23,6 +23,7 @@ func (self *GuestSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneM guest := obj.(*models.SGuest) host := guest.GetHost() if host == nil || host.HostStatus == models.HOST_OFFLINE { + log.Errorf("host is not reachable") guest.SetStatus(self.UserCred, models.VM_UNKNOWN, "Host not responding") self.SetStageComplete(ctx, nil) return diff --git a/pkg/compute/tasks/vpc_delete_task.go b/pkg/compute/tasks/vpc_delete_task.go index d2e2d96b8c..e6957fb81d 100644 --- a/pkg/compute/tasks/vpc_delete_task.go +++ b/pkg/compute/tasks/vpc_delete_task.go @@ -60,6 +60,10 @@ func (self *VpcDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, 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) } } diff --git a/pkg/util/aliyun/aliyun.go b/pkg/util/aliyun/aliyun.go index d33b2d686b..fcdda7b02d 100644 --- a/pkg/util/aliyun/aliyun.go +++ b/pkg/util/aliyun/aliyun.go @@ -14,6 +14,8 @@ const ( CLOUD_PROVIDER_ALIYUN_CN = "阿里云" ALIYUN_DEFAULT_REGION = "cn-hangzhou" + + ALIYUN_API_VERSION = "2014-05-26" ) type SAliyunClient struct { @@ -36,7 +38,7 @@ func NewAliyunClient(providerId string, providerName string, accessKey string, s func jsonRequest(client *sdk.Client, apiName string, params map[string]string) (jsonutils.JSONObject, error) { req := requests.NewCommonRequest() req.Domain = "ecs.aliyuncs.com" - req.Version = "2014-05-26" + req.Version = ALIYUN_API_VERSION req.ApiName = apiName if params != nil { for k, v := range params { @@ -72,6 +74,7 @@ func (self *SAliyunClient) jsonRequest(apiName string, params map[string]string) func (self *SAliyunClient) fetchRegions() error { body, err := self.jsonRequest("DescribeRegions", nil) if err != nil { + log.Errorf("fetchRegions fail %s", err) return err } diff --git a/pkg/util/aliyun/instance.go b/pkg/util/aliyun/instance.go index cb62d9b1e5..2df08dd2cd 100644 --- a/pkg/util/aliyun/instance.go +++ b/pkg/util/aliyun/instance.go @@ -343,7 +343,11 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st params["InternetMaxBandwidthIn"] = "200" params["InternetMaxBandwidthOut"] = "100" params["HostName"] = name - params["Password"] = passwd + if len(passwd) > 0 { + params["Password"] = passwd + } else { + params["PasswordInherit"] = "True" + } params["IoOptimized"] = "optimized" for i, d := range disks { if i == 0 { diff --git a/pkg/util/aliyun/provider/provider.go b/pkg/util/aliyun/provider/provider.go index 363837606c..030c287943 100644 --- a/pkg/util/aliyun/provider/provider.go +++ b/pkg/util/aliyun/provider/provider.go @@ -55,6 +55,7 @@ func (self *SAliyunProvider) GetSysInfo() (jsonutils.JSONObject, error) { regions := self.client.GetIRegions() info := jsonutils.NewDict() info.Add(jsonutils.NewInt(int64(len(regions))), "region_count") + info.Add(jsonutils.NewString(aliyun.ALIYUN_API_VERSION), "api_version") return info, nil } diff --git a/pkg/util/aliyun/region.go b/pkg/util/aliyun/region.go index 7fd9ec4f69..86945feef5 100644 --- a/pkg/util/aliyun/region.go +++ b/pkg/util/aliyun/region.go @@ -541,3 +541,26 @@ func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStorag } return nil, cloudprovider.ErrNotFound } + +func (self *SRegion) updateInstance(instId string, name, desc, passwd, hostname string) error { + params := make(map[string]string) + params["InstanceId"] = instId + if len(name) > 0 { + params["InstanceName"] = name + } + if len(desc) > 0 { + params["Description"] = desc + } + if len(passwd) > 0 { + params["Password"] = passwd + } + if len(hostname) > 0 { + params["HostName"] = hostname + } + _, err := self.ecsRequest("ModifyInstanceAttribute", params) + return err +} + +func (self *SRegion) UpdateInstancePassword(instId string, passwd string) error { + return self.updateInstance(instId, "", "", passwd, "") +} \ No newline at end of file diff --git a/pkg/util/aliyun/shell/instance.go b/pkg/util/aliyun/shell/instance.go index d57dfa7231..49718529a6 100644 --- a/pkg/util/aliyun/shell/instance.go +++ b/pkg/util/aliyun/shell/instance.go @@ -80,4 +80,13 @@ func init() { } return nil }) + + type InstanceUpdatePasswordOptions struct { + ID string `help:"Instance ID"` + PASSWD string `help:"new password"` + } + shellutils.R(&InstanceUpdatePasswordOptions{}, "instance-update-password", "Update instance password", func(cli *aliyun.SRegion, args *InstanceUpdatePasswordOptions) error { + err := cli.UpdateInstancePassword(args.ID, args.PASSWD) + return err + }) } diff --git a/pkg/util/seclib2/seclib.go b/pkg/util/seclib2/seclib.go new file mode 100644 index 0000000000..86cee26422 --- /dev/null +++ b/pkg/util/seclib2/seclib.go @@ -0,0 +1,47 @@ +package seclib2 + +import ( + "fmt" + "strings" + "bytes" + "math/rand" +) + +const ( + DIGITS = "23456789" + LETTERS = "abcdefghjkmnpqrstuvwxyz" + PUNC = "()~@#$%^&*-+={}[]:;<>,.?/" +) + +var CHARS = fmt.Sprintf("%s%s%s%s", DIGITS, LETTERS, strings.ToUpper(LETTERS), PUNC) + +func RandomPassword2(width int) string { + if width < 6 { + width = 6 + } + for { + var buf bytes.Buffer + digitsCnt := 0 + letterCnt := 0 + upperCnt := 0 + puncCnt := 0 + for i := 0; i < width; i += 1 { + index := rand.Intn(len(CHARS)) + ch := CHARS[index] + if strings.IndexByte(DIGITS, ch) >= 0 { + digitsCnt += 1 + } else if strings.IndexByte(LETTERS, ch) >= 0 { + letterCnt += 1 + } else if strings.IndexByte(LETTERS, ch+32) >= 0 { + upperCnt += 1 + } else if strings.IndexByte(PUNC, ch) >= 0 { + puncCnt += 1 + } + buf.WriteByte(ch) + } + if digitsCnt > 1 && letterCnt > 1 && upperCnt > 1 && puncCnt >=1 && puncCnt <= 2 { + return buf.String() + } + } + return "" +} From 1585d24302c5f0bfe28f769ad2aeef86a8afed9c Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 9 Aug 2018 23:58:11 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9A=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91=E5=9B=9E=E6=94=B6=E7=AB=99=E4=B8=BB=E6=9C=BA?= =?UTF-8?q?=E6=81=A2=E5=A4=8D=E5=90=8E=E6=97=A0=E7=B3=BB=E7=BB=9F=E7=9B=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cloudcommon/db/virtualresource.go | 4 ++++ pkg/compute/models/disks.go | 15 +++++++++++++- pkg/compute/models/guests.go | 30 +++++++++++++++++++-------- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/pkg/cloudcommon/db/virtualresource.go b/pkg/cloudcommon/db/virtualresource.go index a07ac9e192..6d1f94c3ba 100644 --- a/pkg/cloudcommon/db/virtualresource.go +++ b/pkg/cloudcommon/db/virtualresource.go @@ -256,6 +256,10 @@ func (model *SVirtualResourceBase) AllowPerformCancelDelete(ctx context.Context, return false } +/*func DoCancelPendingDelete(model IVirtualModel, ctx context.Context, userCred mcclient.TokenCredential) error { + return model.DoCancelPendingDelete(ctx, userCred) +}*/ + func (model *SVirtualResourceBase) PerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { if model.PendingDeleted { err := model.DoCancelPendingDelete(ctx, userCred) diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 038d27e24b..9d362c69ef 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -486,7 +486,8 @@ func (self *SDisk) fetchDiskInfo(diskConfig *SDiskConfig) { if len(diskConfig.ImageId) > 0 { self.TemplateId = diskConfig.ImageId self.DiskType = DISK_TYPE_SYS - } else if len(diskConfig.Fs) > 0 { + } + if len(diskConfig.Fs) > 0 { self.FsFormat = diskConfig.Fs } if self.FsFormat == "swap" { @@ -619,3 +620,15 @@ func (self *SDisk) isReady() bool { func (self *SDisk) isInit() bool { return self.Status == DISK_INIT } + +func (model *SDisk) AllowPerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return userCred.IsSystemAdmin() +} + +func (self *SDisk) PerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if self.PendingDeleted { + err := self.DoCancelPendingDelete(ctx, userCred) + return nil, err + } + return nil, nil +} \ No newline at end of file diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index d7490a5f42..3d375eb287 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1953,7 +1953,7 @@ func (self *SGuest) DoPendingDelete(ctx context.Context, userCred mcclient.Token for _, guestdisk := range self.GetDisks() { disk := guestdisk.GetDisk() storage := disk.GetStorage() - if utils.IsInStringArray(storage.StorageType, sysutils.LOCAL_STORAGE_TYPES) || disk.DiskType == DISK_TYPE_SYS || disk.DiskType == DISK_TYPE_SWAP { + if utils.IsInStringArray(storage.StorageType, sysutils.LOCAL_STORAGE_TYPES) || disk.DiskType == DISK_TYPE_SYS || disk.DiskType == DISK_TYPE_SWAP || self.Hypervisor == HYPERVISOR_ALIYUN { disk.DoPendingDelete(ctx, userCred) } else { self.detachDisk(ctx, disk, userCred) @@ -1962,6 +1962,26 @@ func (self *SGuest) DoPendingDelete(ctx context.Context, userCred mcclient.Token self.SVirtualResourceBase.DoPendingDelete(ctx, userCred) } +func (model *SGuest) AllowPerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return userCred.IsSystemAdmin() +} + +func (self *SGuest) PerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if self.PendingDeleted { + err := self.DoCancelPendingDelete(ctx, userCred) + return nil, err + } + return nil, nil +} + +func (self *SGuest) DoCancelPendingDelete(ctx context.Context, userCred mcclient.TokenCredential) error { + for _, guestdisk := range self.GetDisks() { + disk := guestdisk.GetDisk() + disk.DoCancelPendingDelete(ctx, userCred) + } + return self.SVirtualResourceBase.DoCancelPendingDelete(ctx, userCred) +} + func (self *SGuest) StartUndeployGuestTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, targetHostId string) error { data := jsonutils.NewDict() if len(targetHostId) > 0 { @@ -2548,10 +2568,6 @@ func (self *SGuest) GetDetailsVnc(ctx context.Context, userCred mcclient.TokenCr } } -func (model *SGuestManager) AllowPerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { - return userCred.IsSystemAdmin() -} - func (self *SGuest) GetKeypairPublicKey() string { keypair := self.getKeypair() if keypair != nil { @@ -2560,10 +2576,6 @@ func (self *SGuest) GetKeypairPublicKey() string { return "" } -func (model *SGuest) AllowPerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { - return userCred.IsSystemAdmin() -} - func (manager *SGuestManager) GetIpInProjectWithName(projectId, name string, isExitOnly bool) []string { guestnics := GuestnetworkManager.Query().SubQuery() guests := manager.Query().SubQuery()