diff --git a/pkg/cloudprovider/cloudprovider.go b/pkg/cloudprovider/cloudprovider.go index b74769c2c6..5b4b6fdcb3 100644 --- a/pkg/cloudprovider/cloudprovider.go +++ b/pkg/cloudprovider/cloudprovider.go @@ -26,6 +26,8 @@ type ICloudProviderFactory interface { ValidateChangeBandwidth(instanceId string, bandwidth int64) error ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, cloudaccount string) (*SCloudaccount, error) + + IsPublicCloud() bool } type ICloudProvider interface { @@ -33,7 +35,6 @@ type ICloudProvider interface { GetName() string GetSysInfo() (jsonutils.JSONObject, error) GetVersion() string - IsPublicCloud() bool IsOnPremiseInfrastructure() bool GetIRegions() []ICloudRegion diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index 343b393ebe..c4bbb40d7d 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -52,8 +52,8 @@ type SCloudaccount struct { LastSync time.Time `get:"admin" list:"admin"` // = Column(DateTime, nullable=True) // Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True) - - Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"` + IsPublicCloud bool `nullable:"false" get:"user" create:"required" list:"user"` + Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"` } func (self *SCloudaccountManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { @@ -146,6 +146,7 @@ func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, use if err := providerDriver.ValidateCreateCloudaccountData(ctx, userCred, data); err != nil { return nil, err } + data.Set("is_public_cloud", jsonutils.NewBool(providerDriver.IsPublicCloud())) // check duplication // url, account, provider must be unique account, _ := data.GetString("account") @@ -319,6 +320,18 @@ func (self *SCloudaccount) StartSyncCloudProviderInfoTask(ctx context.Context, u params.Add(jsonutils.Marshal(syncRange), "sync_range") } + providerDriver, _ := cloudprovider.GetProviderDriver(self.Provider) + isPublicCloud := providerDriver.IsPublicCloud() + if self.IsPublicCloud != isPublicCloud { + _, err := self.GetModelManager().TableSpec().Update(self, func() error { + self.IsPublicCloud = isPublicCloud + return nil + }) + if err != nil { + log.Errorf("Update cloudaccount %s public attr error: %v", self.Name, err) + } + } + if cloudProviders == nil { cloudProviders = self.GetCloudproviders() } diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index 5b402b9f28..cb5b397573 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -139,6 +139,44 @@ func (self *SCloudprovider) ValidateDeleteCondition(ctx context.Context) error { return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx) } +func (manager *SCloudproviderManager) GetPublicProviderIds() []string { + return manager.GetProviderIds(true) +} + +func (manager *SCloudproviderManager) GetPrivateProviderIds() []string { + return manager.GetProviderIds(false) +} + +func (manager *SCloudproviderManager) GetProviderIds(isPublic bool) []string { + providerIds := []string{} + q := manager.Query("id") + account := CloudaccountManager.Query().SubQuery() + q = q.Join(account, sqlchemy.Equals( + account.Field("id"), q.Field("cloudaccount_id")), + ) + if isPublic { + q = q.Filter(sqlchemy.IsTrue(account.Field("is_public_cloud"))) + } else { + q = q.Filter(sqlchemy.IsFalse(account.Field("is_public_cloud"))) + } + rows, err := q.Rows() + if err != nil { + log.Errorf("Get providerIds err: %v", err) + return providerIds + } + defer rows.Close() + for rows.Next() { + var providerId string + err = rows.Scan(&providerId) + if err != nil { + log.Errorf("Get providerId err: %v", err) + return providerIds + } + providerIds = append(providerIds, providerId) + } + return providerIds +} + func (self *SCloudprovider) CleanSchedCache() { hosts := []SHost{} q := HostManager.Query().Equals("manager_id", self.Id) diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 4ebb561e42..6bb8768014 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -167,12 +167,17 @@ func (manager *SDiskManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu sq := storages.Query(storages.Field("id")).Filter(sqlchemy.NotIn(storages.Field("storage_type"), STORAGE_LOCAL_TYPES)) q = q.Filter(sqlchemy.In(q.Field("storage_id"), sq)) } - + publicProviderIds := CloudproviderManager.GetPublicProviderIds() if jsonutils.QueryBoolean(query, "public_cloud", false) { - sq := storages.Query(storages.Field("id")).Filter(sqlchemy.IsNotNull(storages.Field("manager_id"))) + sq := storages.Query(storages.Field("id")).Filter(sqlchemy.In(storages.Field("manager_id"), publicProviderIds)) q = q.Filter(sqlchemy.In(q.Field("storage_id"), sq)) } else if jsonutils.QueryBoolean(query, "private_cloud", false) { - sq := storages.Query(storages.Field("id")).Filter(sqlchemy.IsNull(storages.Field("manager_id"))) + sq := storages.Query(storages.Field("id")).Filter( + sqlchemy.OR( + sqlchemy.NotIn(storages.Field("manager_id"), publicProviderIds), + sqlchemy.IsNullOrEmpty(storages.Field("manager_id")), + ), + ) q = q.Filter(sqlchemy.In(q.Field("storage_id"), sq)) } diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index ca214b3906..e99279e3c4 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -1710,7 +1710,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T diskIdx += 1 } - provider, e := self.GetHost().GetDriver() + provider, e := self.GetHost().GetProviderDriver() if e != nil || !provider.IsPublicCloud() { for storageId, needSize := range diskSizes { iStorage, err := StorageManager.FetchById(storageId) @@ -1723,7 +1723,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T } } } else { - log.Debugf("Skip storage free capacity validating for public cloud: %s", provider.GetName()) + log.Debugf("Skip storage free capacity validating for public cloud: %s", provider.GetId()) } if newDisks.Length() > 0 { diff --git a/pkg/compute/models/managedresource.go b/pkg/compute/models/managedresource.go index c8a7dfb016..4039455878 100644 --- a/pkg/compute/models/managedresource.go +++ b/pkg/compute/models/managedresource.go @@ -28,6 +28,17 @@ func (self *SManagedResourceBase) GetCloudaccount() *SCloudaccount { return cp.GetCloudaccount() } +func (self *SManagedResourceBase) GetProviderDriver() (cloudprovider.ICloudProviderFactory, error) { + provider := self.GetCloudprovider() + if provider == nil { + if len(self.ManagerId) > 0 { + return nil, cloudprovider.ErrInvalidProvider + } + return nil, fmt.Errorf("Resource is self managed") + } + return provider.GetProviderDriver() +} + func (self *SManagedResourceBase) GetDriver() (cloudprovider.ICloudProvider, error) { provider := self.GetCloudprovider() if provider == nil { diff --git a/pkg/compute/models/snapshots.go b/pkg/compute/models/snapshots.go index cdfa96b6be..1a83480ef9 100644 --- a/pkg/compute/models/snapshots.go +++ b/pkg/compute/models/snapshots.go @@ -130,6 +130,18 @@ func (manager *SSnapshotManager) ListItemFilter(ctx context.Context, q *sqlchemy q = q.In("manager_id", sq) } + publicProviderIds := CloudproviderManager.GetPublicProviderIds() + if jsonutils.QueryBoolean(query, "public_cloud", false) { + q = q.Filter(sqlchemy.In(q.Field("manager_id"), publicProviderIds)) + } else if jsonutils.QueryBoolean(query, "private_cloud", false) { + q = q.Filter( + sqlchemy.OR( + sqlchemy.NotIn(q.Field("manager_id"), publicProviderIds), + sqlchemy.IsNullOrEmpty(q.Field("manager_id")), + ), + ) + } + if managerStr := jsonutils.GetAnyString(query, []string{"manager", "manager_id"}); len(managerStr) > 0 { managerObj, err := CloudproviderManager.FetchByIdOrName(nil, managerStr) if err != nil { diff --git a/pkg/util/aliyun/provider/provider.go b/pkg/util/aliyun/provider/provider.go index d64a04a349..3c35c8df41 100644 --- a/pkg/util/aliyun/provider/provider.go +++ b/pkg/util/aliyun/provider/provider.go @@ -23,6 +23,10 @@ func (self *SAliyunProviderFactory) ValidateChangeBandwidth(instanceId string, b return nil } +func (self *SAliyunProviderFactory) IsPublicCloud() bool { + return true +} + func (self *SAliyunProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { accessKeyID, _ := data.GetString("access_key_id") if len(accessKeyID) == 0 { @@ -90,10 +94,6 @@ type SAliyunProvider struct { client *aliyun.SAliyunClient } -func (self *SAliyunProvider) IsPublicCloud() bool { - return true -} - func (self *SAliyunProvider) IsOnPremiseInfrastructure() bool { return false } diff --git a/pkg/util/aws/provider/provider.go b/pkg/util/aws/provider/provider.go index ceb9eeb620..834d15c534 100644 --- a/pkg/util/aws/provider/provider.go +++ b/pkg/util/aws/provider/provider.go @@ -21,6 +21,10 @@ func (self *SAwsProviderFactory) ValidateChangeBandwidth(instanceId string, band return nil } +func (self *SAwsProviderFactory) IsPublicCloud() bool { + return true +} + func (self *SAwsProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { accessKeyID, _ := data.GetString("access_key_id") if len(accessKeyID) == 0 { @@ -101,10 +105,6 @@ func (self *SAwsProvider) GetVersion() string { return aws.AWS_API_VERSION } -func (self *SAwsProvider) IsPublicCloud() bool { - return true -} - func (self *SAwsProvider) IsOnPremiseInfrastructure() bool { return false } diff --git a/pkg/util/azure/provider/provider.go b/pkg/util/azure/provider/provider.go index 277414dc9b..b6f7fba30a 100644 --- a/pkg/util/azure/provider/provider.go +++ b/pkg/util/azure/provider/provider.go @@ -23,6 +23,10 @@ func (self *SAzureProviderFactory) ValidateChangeBandwidth(instanceId string, ba return fmt.Errorf("Changing %s bandwidth is not supported", azure.CLOUD_PROVIDER_AZURE) } +func (self *SAzureProviderFactory) IsPublicCloud() bool { + return true +} + func (self *SAzureProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { directoryID, _ := data.GetString("directory_id") if len(directoryID) == 0 { @@ -79,10 +83,6 @@ type SAzureProvider struct { client *azure.SAzureClient } -func (self *SAzureProvider) IsPublicCloud() bool { - return true -} - func (self *SAzureProvider) IsOnPremiseInfrastructure() bool { return false } diff --git a/pkg/util/esxi/provider/provider.go b/pkg/util/esxi/provider/provider.go index da1a16d468..1349ee05de 100644 --- a/pkg/util/esxi/provider/provider.go +++ b/pkg/util/esxi/provider/provider.go @@ -27,6 +27,10 @@ func (self *SESXiProviderFactory) ValidateChangeBandwidth(instanceId string, ban return fmt.Errorf("Changing %s bandwidth is not supported", esxi.CLOUD_PROVIDER_VMWARE) } +func (self *SESXiProviderFactory) IsPublicCloud() bool { + return false +} + func (self *SESXiProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { username, _ := data.GetString("username") if len(username) == 0 { @@ -111,10 +115,6 @@ type SESXiProvider struct { client *esxi.SESXiClient } -func (self *SESXiProvider) IsPublicCloud() bool { - return false -} - func (self *SESXiProvider) IsOnPremiseInfrastructure() bool { return true } diff --git a/pkg/util/huawei/provider/provider.go b/pkg/util/huawei/provider/provider.go index 880a1e910a..71252720a1 100644 --- a/pkg/util/huawei/provider/provider.go +++ b/pkg/util/huawei/provider/provider.go @@ -17,6 +17,10 @@ func (self *SHuaweiProviderFactory) ValidateChangeBandwidth(instanceId string, b return nil } +func (self *SHuaweiProviderFactory) IsPublicCloud() bool { + return true +} + func (self *SHuaweiProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { accessKeyID, _ := data.GetString("access_key_id") if len(accessKeyID) == 0 { @@ -93,10 +97,6 @@ func (self *SHuaweiProvider) GetSysInfo() (jsonutils.JSONObject, error) { return info, nil } -func (self *SHuaweiProvider) IsPublicCloud() bool { - return true -} - func (self *SHuaweiProvider) IsOnPremiseInfrastructure() bool { return false } diff --git a/pkg/util/openstack/provider/provider.go b/pkg/util/openstack/provider/provider.go index 703a06b17f..861b8c8085 100644 --- a/pkg/util/openstack/provider/provider.go +++ b/pkg/util/openstack/provider/provider.go @@ -25,6 +25,10 @@ func (self *SOpenStackProviderFactory) ValidateChangeBandwidth(instanceId string return nil } +func (self *SOpenStackProviderFactory) IsPublicCloud() bool { + return false +} + func (self *SOpenStackProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { projectName, _ := data.GetString("project_name") if len(projectName) == 0 { @@ -94,10 +98,6 @@ type SOpenStackProvider struct { client *openstack.SOpenStackClient } -func (self *SOpenStackProvider) IsPublicCloud() bool { - return false -} - func (self *SOpenStackProvider) GetVersion() string { return "" } diff --git a/pkg/util/qcloud/provider/provider.go b/pkg/util/qcloud/provider/provider.go index fbde5b066b..1c73cf44ee 100644 --- a/pkg/util/qcloud/provider/provider.go +++ b/pkg/util/qcloud/provider/provider.go @@ -27,6 +27,10 @@ func (self *SQcloudProviderFactory) ValidateChangeBandwidth(instanceId string, b return nil } +func (self *SQcloudProviderFactory) IsPublicCloud() bool { + return true +} + func (self *SQcloudProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error { appID, _ := data.GetString("app_id") if len(appID) == 0 { @@ -86,10 +90,6 @@ type SQcloudProvider struct { client *qcloud.SQcloudClient } -func (self *SQcloudProvider) IsPublicCloud() bool { - return true -} - func (self *SQcloudProvider) IsOnPremiseInfrastructure() bool { return false }