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 "" +}