fix: 1. vpc, cloudprovider should not violate the sharing limit of cloud account 2.

sharing mode of host and attached local storage should be consistent. 3.
cannot change owner of shared resource
This commit is contained in:
Qiu Jian
2020-05-08 23:27:28 +08:00
parent 0c45818c5c
commit f2e0fcf4e9
14 changed files with 142 additions and 31 deletions
@@ -245,4 +245,13 @@ func init() {
printObject(result)
return nil
})
R(&CloudproviderShowOptions{}, "cloud-provider-change-owner-candidate-domains", "Show candiate domains of a cloud provider changing owner", func(s *mcclient.ClientSession, args *CloudproviderShowOptions) error {
result, err := modules.Cloudproviders.GetSpecific(s, args.ID, "change-owner-candidate-domains", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
}
+45
View File
@@ -215,4 +215,49 @@ func init() {
printObject(storage)
return nil
})
type StorageChangeOwnerOptions struct {
ID string `help:"ID or name of storage" json:"-"`
ProjectDomain string `json:"project_domain" help:"target domain"`
}
R(&StorageChangeOwnerOptions{}, "storage-change-owner", "Change owner domain of storage", func(s *mcclient.ClientSession, args *StorageChangeOwnerOptions) error {
if len(args.ProjectDomain) == 0 {
return fmt.Errorf("empty project_domain")
}
params := jsonutils.Marshal(args)
ret, err := modules.Storages.PerformAction(s, args.ID, "change-owner", params)
if err != nil {
return err
}
printObject(ret)
return nil
})
type StoragePublicOptions struct {
ID string `help:"ID or name of storage" json:"-"`
Scope string `help:"sharing scope" choices:"system|domain"`
SharedDomains []string `help:"share to domains"`
}
R(&StoragePublicOptions{}, "storage-public", "Make a storage public", func(s *mcclient.ClientSession, args *StoragePublicOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Storages.PerformAction(s, args.ID, "public", params)
if err != nil {
return err
}
printObject(result)
return nil
})
type StoragePrivateOptions struct {
ID string `help:"ID or name of storage" json:"-"`
}
R(&StoragePrivateOptions{}, "storage-private", "Make a storage private", func(s *mcclient.ClientSession, args *StoragePrivateOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Storages.PerformAction(s, args.ID, "private", params)
if err != nil {
return err
}
printObject(result)
return nil
})
}
+19
View File
@@ -15,6 +15,8 @@
package compute
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -218,4 +220,21 @@ func init() {
printObject(result)
return nil
})
type VpcChangeOwnerOptions struct {
ID string `help:"ID or name of vpc" json:"-"`
ProjectDomain string `json:"project_domain" help:"target domain"`
}
R(&VpcChangeOwnerOptions{}, "vpc-change-owner", "Change owner domain of vpc", func(s *mcclient.ClientSession, args *VpcChangeOwnerOptions) error {
if len(args.ProjectDomain) == 0 {
return fmt.Errorf("empty project_domain")
}
params := jsonutils.Marshal(args)
ret, err := modules.Vpcs.PerformAction(s, args.ID, "change-owner", params)
if err != nil {
return err
}
printObject(ret)
return nil
})
}
+4
View File
@@ -133,6 +133,10 @@ func (model *SDomainLevelResourceBase) AllowPerformChangeOwner(ctx context.Conte
}
func (model *SDomainLevelResourceBase) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
if model.GetIStandaloneModel().IsShared() {
return nil, errors.Wrap(httperrors.ErrForbidden, "cannot change owner of shared resource")
}
manager := model.GetModelManager()
data := jsonutils.Marshal(input)
+4
View File
@@ -258,6 +258,10 @@ func (model *SVirtualResourceBase) AllowPerformChangeOwner(ctx context.Context,
}
func (model *SVirtualResourceBase) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) (jsonutils.JSONObject, error) {
if model.GetIStandaloneModel().IsShared() {
return nil, errors.Wrap(httperrors.ErrForbidden, "cannot change owner of shared resource")
}
manager := model.GetModelManager()
data := jsonutils.Marshal(input)
+1 -1
View File
@@ -1054,7 +1054,7 @@ func (self *SManagedVirtualizedGuestDriver) chooseHostStorage(
if len(storageIds) != 0 {
return models.StorageManager.FetchStorageById(storageIds[0])
}
storages := host.GetAttachedStorages("")
storages := host.GetAttachedEnabledHostStorages(nil)
for i := 0; i < len(storages); i += 1 {
if storages[i].StorageType == backend {
return &storages[i]
+21
View File
@@ -1524,3 +1524,24 @@ func (provider *SCloudprovider) IsSharable(reqUsrId mcclient.IIdentityProvider)
}
return false
}
func (provider *SCloudprovider) AllowGetDetailsChangeOwnerCandidateDomains(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return provider.DomainId == userCred.GetProjectDomainId() || db.IsAdminAllowGetSpec(userCred, provider, "change-owner-candidate-domains")
}
func (provider *SCloudprovider) GetDetailsChangeOwnerCandidateDomains(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (apis.ChangeOwnerCandidateDomainsOutput, error) {
return db.IOwnerResourceBaseModelGetChangeOwnerCandidateDomains(provider)
}
func (provider *SCloudprovider) GetChangeOwnerCandidateDomainIds() []string {
account := provider.GetCloudaccount()
if account.ShareMode == api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN {
return []string{account.DomainId}
}
// if account's public_scope=domain and share_mode=provider_domain, only allow to share to specific domains
if account.PublicScope == string(rbacutils.ScopeDomain) {
sharedDomains := account.GetSharedDomains()
return append(sharedDomains, account.DomainId)
}
return []string{}
}
+1 -1
View File
@@ -580,7 +580,7 @@ func (disk *SDisk) SetStorageByHost(hostId string, diskConfig *api.DiskConfig, s
storage = host.GetLeastUsedStorage(backend)
} else {
// unlimited pulic cloud storages
storages := host.GetAttachedStorages("")
storages := host.GetAttachedEnabledHostStorages(nil)
for _, s := range storages {
if s.StorageType == backend {
tmpS := s
+19 -25
View File
@@ -888,11 +888,11 @@ func (self *SHost) GetFetchUrl(disableHttps bool) string {
return fmt.Sprintf("%s://%s:%d", managerUrl.Scheme, strings.Split(managerUrl.Host, ":")[0], port+40000)
}
func (self *SHost) GetAttachedStorages(storageType string) []SStorage {
func (self *SHost) GetAttachedEnabledHostStorages(storageType []string) []SStorage {
return self._getAttachedStorages(tristate.False, tristate.True, storageType)
}
func (self *SHost) _getAttachedStorages(isBaremetal tristate.TriState, enabled tristate.TriState, storageType string) []SStorage {
func (self *SHost) _getAttachedStorages(isBaremetal tristate.TriState, enabled tristate.TriState, storageType []string) []SStorage {
storages := StorageManager.Query().SubQuery()
hoststorages := HoststorageManager.Query().SubQuery()
q := storages.Query()
@@ -908,7 +908,7 @@ func (self *SHost) _getAttachedStorages(isBaremetal tristate.TriState, enabled t
q = q.NotEquals("storage_type", api.STORAGE_BAREMETAL)
}
if len(storageType) > 0 {
q = q.Equals("storage_type", storageType)
q = q.In("storage_type", storageType)
}
q = q.Filter(sqlchemy.Equals(hoststorages.Field("host_id"), self.Id))
ret := make([]SStorage, 0)
@@ -921,7 +921,7 @@ func (self *SHost) _getAttachedStorages(isBaremetal tristate.TriState, enabled t
}
func (self *SHost) SyncAttachedStorageStatus() {
storages := self.GetAttachedStorages("")
storages := self.GetAttachedEnabledHostStorages(nil)
if storages != nil {
for _, storage := range storages {
storage.SyncStatusWithHosts()
@@ -1212,26 +1212,15 @@ func (cap *SStorageCapacity) toCapacityInfo() api.SStorageCapacityInfo {
func (self *SHost) GetAttachedLocalStorageCapacity() SStorageCapacity {
ret := SStorageCapacity{}
storages := self.GetAttachedStorages("")
storages := self.GetAttachedEnabledHostStorages(api.HOST_STORAGE_LOCAL_TYPES)
for _, s := range storages {
if !utils.IsInStringArray(s.StorageType, api.HOST_STORAGE_LOCAL_TYPES) {
continue
}
ret.Add(s.getStorageCapacity())
}
return ret
}
func (self *SHost) GetAttachedLocalStorages() []SStorage {
ret := make([]SStorage, 0)
storages := self.GetAttachedStorages("")
for _, s := range storages {
if !utils.IsInStringArray(s.StorageType, api.HOST_STORAGE_LOCAL_TYPES) {
continue
}
ret = append(ret, s)
}
return ret
return self.GetAttachedEnabledHostStorages(api.HOST_STORAGE_LOCAL_TYPES)
}
func _getLeastUsedStorage(storages []SStorage, backends []string) *SStorage {
@@ -1267,7 +1256,7 @@ func getLeastUsedStorage(storages []SStorage, backend string) *SStorage {
}
func (self *SHost) GetLeastUsedStorage(backend string) *SStorage {
storages := self.GetAttachedStorages("")
storages := self.GetAttachedEnabledHostStorages(nil)
if storages != nil {
return getLeastUsedStorage(storages, backend)
}
@@ -2704,7 +2693,7 @@ func (self *SHost) Request(ctx context.Context, userCred mcclient.TokenCredentia
}
func (self *SHost) GetLocalStoragecache() *SStoragecache {
localStorages := self.GetAttachedStorages(api.STORAGE_LOCAL)
localStorages := self.GetAttachedLocalStorages()
for i := 0; i < len(localStorages); i += 1 {
sc := localStorages[i].GetStoragecache()
if sc != nil {
@@ -2715,7 +2704,7 @@ func (self *SHost) GetLocalStoragecache() *SStoragecache {
}
func (self *SHost) GetStoragecache() *SStoragecache {
localStorages := self.GetAttachedStorages("")
localStorages := self.GetAttachedEnabledHostStorages(nil)
for i := 0; i < len(localStorages); i += 1 {
sc := localStorages[i].GetStoragecache()
if sc != nil {
@@ -5075,15 +5064,20 @@ func (model *SHost) CustomizeCreate(ctx context.Context, userCred mcclient.Token
}
func (host *SHost) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
localStorages := host.GetAttachedLocalStorages()
ret, err := host.SEnabledStatusInfrasResourceBase.PerformChangeOwner(ctx, userCred, query, input)
if err != nil {
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformChangeOwner")
}
localStorages := host._getAttachedStorages(tristate.None, tristate.None, api.HOST_STORAGE_LOCAL_TYPES)
for i := range localStorages {
_, err := localStorages[i].PerformChangeOwner(ctx, userCred, query, input)
_, err := localStorages[i].performChangeOwnerInternal(ctx, userCred, query, input)
if err != nil {
return nil, errors.Wrap(err, "local storage change owner")
}
}
return host.SEnabledStatusInfrasResourceBase.PerformChangeOwner(ctx, userCred, query, input)
return ret, nil
}
func GetHostQuotaKeysFromCreateInput(input api.HostCreateInput) quotas.SDomainRegionalCloudResourceKeys {
@@ -5125,7 +5119,7 @@ func (host *SHost) GetUsages() []db.IUsage {
func (host *SHost) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicDomainInput) (jsonutils.JSONObject, error) {
// perform public for all connected local storage
storages := host.GetAttachedLocalStorages()
storages := host._getAttachedStorages(tristate.None, tristate.None, api.HOST_STORAGE_LOCAL_TYPES)
for i := range storages {
_, err := storages[i].performPublicInternal(ctx, userCred, query, input)
if err != nil {
@@ -5137,7 +5131,7 @@ func (host *SHost) PerformPublic(ctx context.Context, userCred mcclient.TokenCre
func (host *SHost) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
// perform private for all connected local storage
storages := host.GetAttachedLocalStorages()
storages := host._getAttachedStorages(tristate.None, tristate.None, api.HOST_STORAGE_LOCAL_TYPES)
for i := range storages {
_, err := storages[i].performPrivateInternal(ctx, userCred, query, input)
if err != nil {
+1 -1
View File
@@ -2567,7 +2567,7 @@ func (net *SNetwork) PerformStatus(ctx context.Context, userCred mcclient.TokenC
func (net *SNetwork) GetChangeOwnerCandidateDomainIds() []string {
candidates := [][]string{
net.SSharableVirtualResourceBase.GetChangeOwnerCandidateDomainIds(),
db.ISharableChangeOwnerCandidateDomainIds(net),
}
wire := net.GetWire()
if wire != nil {
+1 -1
View File
@@ -94,7 +94,7 @@ func (host *SHost) purge(ctx context.Context, userCred mcclient.TokenCredential)
}
// clean all disks on locally attached storages
storages := host._getAttachedStorages(tristate.None, tristate.None, api.STORAGE_LOCAL)
storages := host._getAttachedStorages(tristate.None, tristate.None, api.HOST_STORAGE_LOCAL_TYPES)
for i := range storages {
err := storages[i].purgeDisks(ctx, userCred)
if err != nil {
+15
View File
@@ -1458,6 +1458,21 @@ func (self *SStorage) StartDeleteRbdDisks(ctx context.Context, userCred mcclient
return nil
}
func (storage *SStorage) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
// not allow to perform public for locally connected storage
if storage.IsLocal() {
hosts := storage.GetAttachedHosts()
if len(hosts) > 0 {
return nil, errors.Wrap(httperrors.ErrForbidden, "not allow to change owner for local storage")
}
}
return storage.performChangeOwnerInternal(ctx, userCred, query, input)
}
func (storage *SStorage) performChangeOwnerInternal(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
return storage.SEnabledStatusInfrasResourceBase.PerformChangeOwner(ctx, userCred, query, input)
}
func (storage *SStorage) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicDomainInput) (jsonutils.JSONObject, error) {
// not allow to perform public for locally connected storage
if storage.IsLocal() {
+1 -1
View File
@@ -1093,7 +1093,7 @@ func (manager *SVpcManager) totalCount(
func (vpc *SVpc) GetChangeOwnerCandidateDomainIds() []string {
candidates := [][]string{
vpc.SEnabledStatusInfrasResourceBase.GetChangeOwnerCandidateDomainIds(),
db.ISharableChangeOwnerCandidateDomainIds(vpc),
}
globalVpc, _ := vpc.GetGlobalVpc()
if globalVpc != nil {
+1 -1
View File
@@ -1012,7 +1012,7 @@ func (model *SWire) CustomizeCreate(ctx context.Context, userCred mcclient.Token
func (wire *SWire) GetChangeOwnerCandidateDomainIds() []string {
candidates := [][]string{
wire.SInfrasResourceBase.GetChangeOwnerCandidateDomainIds(),
db.ISharableChangeOwnerCandidateDomainIds(wire),
}
vpc := wire.GetVpc()
if vpc != nil {