Files
cloudpods/pkg/cloudcommon/db/quotas/quotakeys.go
T

441 lines
10 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package quotas
import (
"fmt"
"strings"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SBaseDomainQuotaKeys struct {
// 配额适用的域ID
DomainId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"domain_id"`
}
type SBaseProjectQuotaKeys struct {
SBaseDomainQuotaKeys
// 配额适用的项目ID
ProjectId string `name:"tenant_id" width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"project_id"`
}
type SBaseDomainQuotaDetailKeys struct {
// 配额适用的项目的域名称
Domain string `json:"domain"`
}
type SBaseProjectQuotaDetailKeys struct {
SBaseDomainQuotaDetailKeys
// 配额适用的项目名称
Project string `json:"project"`
}
type SCloudResourceBaseKeys struct {
// 配额适用的平台名称,参考List接口的平台列表
Provider string `width:"32" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"provider"`
// 配额适用的品牌名称,参考List接口的品牌列表
Brand string `width:"32" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"brand"`
// 配额适用的云环境,参考List接口的云环境列表
CloudEnv string `width:"32" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"cloud_env"`
// 配额适用的云账号ID
AccountId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"account_id"`
// 配额适用的云订阅ID
ManagerId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"manager_id"`
}
type SCloudResourceKeys struct {
SBaseProjectQuotaKeys
SCloudResourceBaseKeys
}
type SCloudResourceDetailKeys struct {
SBaseProjectQuotaDetailKeys
SCloudResourceDetailBaseKeys
}
type SCloudResourceDetailBaseKeys struct {
// 配额适用的云账号名称
Account string `json:"account"`
// 配额适用的云订阅名称
Manager string `json:"manager"`
}
type SRegionalBaseKeys struct {
// 配额适用的区域ID
RegionId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"region_id"`
}
type SRegionalCloudResourceKeys struct {
SCloudResourceKeys
SRegionalBaseKeys
}
type SRegionalCloudResourceDetailKeys struct {
SCloudResourceDetailKeys
SRegionalCloudResourceDetailBaseKeys
}
type SRegionalCloudResourceDetailBaseKeys struct {
// 配额适用的区域名称
Region string `json:"region"`
}
type SDomainRegionalCloudResourceKeys struct {
SBaseProjectQuotaKeys
SCloudResourceBaseKeys
SRegionalBaseKeys
}
type SDomainRegionalCloudResourceDetailKeys struct {
SBaseDomainQuotaDetailKeys
SCloudResourceDetailBaseKeys
SRegionalCloudResourceDetailBaseKeys
}
type SZonalCloudResourceKeys struct {
SRegionalCloudResourceKeys
// 配额适用的可用区ID
ZoneId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"zone_id"`
}
type SZonalCloudResourceDetailKeys struct {
SRegionalCloudResourceDetailKeys
// 配额适用的可用区名称
Zone string `json:"zone"`
}
func (k SBaseDomainQuotaKeys) Fields() []string {
return []string{
"domain_id",
}
}
func (k SBaseProjectQuotaKeys) Fields() []string {
return append(k.SBaseDomainQuotaKeys.Fields(),
"tenant_id",
)
}
func (k SCloudResourceKeys) Fields() []string {
return append(k.SBaseProjectQuotaKeys.Fields(),
"provider",
"brand",
"cloud_env",
"account_id",
"manager_id",
)
}
func (k SRegionalCloudResourceKeys) Fields() []string {
return append(k.SCloudResourceKeys.Fields(),
"region_id",
)
}
func (k SZonalCloudResourceKeys) Fields() []string {
return append(k.SRegionalCloudResourceKeys.Fields(),
"zone_id",
)
}
func (k SBaseDomainQuotaKeys) Values() []string {
return []string{
k.DomainId,
}
}
func (k SBaseProjectQuotaKeys) Values() []string {
return append(k.SBaseDomainQuotaKeys.Values(),
k.ProjectId,
)
}
func (k SCloudResourceKeys) Values() []string {
return append(k.SBaseProjectQuotaKeys.Values(),
k.Provider,
k.Brand,
k.CloudEnv,
k.AccountId,
k.ManagerId,
)
}
func (k SRegionalCloudResourceKeys) Values() []string {
return append(k.SCloudResourceKeys.Values(),
k.RegionId,
)
}
func (k SZonalCloudResourceKeys) Values() []string {
return append(k.SRegionalCloudResourceKeys.Values(),
k.ZoneId,
)
}
func (k1 SBaseDomainQuotaKeys) Compare(ik IQuotaKeys) int {
k2 := ik.(SBaseDomainQuotaKeys)
if k1.DomainId < k2.DomainId {
return -1
} else if k1.DomainId > k2.DomainId {
return 1
}
return 0
}
func (k1 SBaseProjectQuotaKeys) Compare(ik IQuotaKeys) int {
k2 := ik.(SBaseProjectQuotaKeys)
r := k1.SBaseDomainQuotaKeys.Compare(k2.SBaseDomainQuotaKeys)
if r != 0 {
return r
}
if k1.ProjectId < k2.ProjectId {
return -1
} else if k1.ProjectId > k2.ProjectId {
return 1
}
return 0
}
func (k1 SCloudResourceKeys) Compare(ik IQuotaKeys) int {
k2 := ik.(SCloudResourceKeys)
r := k1.SBaseProjectQuotaKeys.Compare(k2.SBaseProjectQuotaKeys)
if r != 0 {
return r
}
if k1.CloudEnv < k2.CloudEnv {
return -1
} else if k1.CloudEnv > k2.CloudEnv {
return 1
}
if k1.Provider < k2.Provider {
return -1
} else if k1.Provider > k2.Provider {
return 1
}
if k1.Brand < k2.Brand {
return -1
} else if k1.Brand > k2.Brand {
return 1
}
return 0
}
func (k1 SRegionalCloudResourceKeys) Compare(ik IQuotaKeys) int {
k2 := ik.(SRegionalCloudResourceKeys)
r := k1.SCloudResourceKeys.Compare(k2.SCloudResourceKeys)
if r != 0 {
return r
}
if k1.RegionId < k2.RegionId {
return -1
} else if k1.RegionId > k2.RegionId {
return 1
}
return 0
}
func (k1 SZonalCloudResourceKeys) Compare(ik IQuotaKeys) int {
k2 := ik.(SZonalCloudResourceKeys)
r := k1.SRegionalCloudResourceKeys.Compare(k2.SRegionalCloudResourceKeys)
if r != 0 {
return r
}
if k1.ZoneId < k2.ZoneId {
return -1
} else if k1.ZoneId > k2.ZoneId {
return 1
}
return 0
}
func QuotaKeyWeight(k IQuotaKeys) uint64 {
w := uint64(0)
for i, v := range k.Values() {
if len(v) > 0 {
w += (uint64(1) << uint(i))
}
}
return w
}
func (k SBaseDomainQuotaKeys) Scope() rbacutils.TRbacScope {
if len(k.DomainId) > 0 {
return rbacutils.ScopeDomain
} else {
return rbacutils.ScopeSystem
}
}
func (k SBaseProjectQuotaKeys) Scope() rbacutils.TRbacScope {
if len(k.DomainId) > 0 && len(k.ProjectId) > 0 {
return rbacutils.ScopeProject
} else if len(k.DomainId) > 0 && len(k.ProjectId) == 0 {
return rbacutils.ScopeDomain
} else if len(k.DomainId) == 0 && len(k.ProjectId) == 0 {
return rbacutils.ScopeSystem
} else {
return rbacutils.ScopeNone
}
}
func (k SBaseDomainQuotaKeys) OwnerId() mcclient.IIdentityProvider {
return &db.SOwnerId{DomainId: k.DomainId}
}
func (k SBaseProjectQuotaKeys) OwnerId() mcclient.IIdentityProvider {
return &db.SOwnerId{
DomainId: k.DomainId,
ProjectId: k.ProjectId,
}
}
func QuotaKeyString(k IQuotaKeys) string {
parts := make([]string, 0)
fields := k.Fields()
values := k.Values()
for i := range fields {
if len(values[i]) > 0 {
parts = append(parts, fmt.Sprintf("%s=%s", fields[i], values[i]))
}
}
return strings.Join(parts, ",")
}
func IsBaseProjectQuotaKeys(k IQuotaKeys) bool {
fields := k.Fields()
values := k.Values()
for i := range fields {
if fields[i] != "domain_id" && fields[i] != "tenant_id" && len(values[i]) > 0 {
return false
}
}
return true
}
func IsBaseDomainQuotaKeys(k IQuotaKeys) bool {
fields := k.Fields()
values := k.Values()
for i := range fields {
if fields[i] != "domain_id" && len(values[i]) > 0 {
return false
}
}
return true
}
func OwnerIdProjectQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) SBaseProjectQuotaKeys {
if scope == rbacutils.ScopeDomain {
return SBaseProjectQuotaKeys{
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
},
}
} else {
return SBaseProjectQuotaKeys{
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
},
ProjectId: ownerId.GetProjectId(),
}
}
}
func OwnerIdDomainQuotaKeys(ownerId mcclient.IIdentityProvider) SBaseDomainQuotaKeys {
return SBaseDomainQuotaKeys{DomainId: ownerId.GetProjectDomainId()}
}
type TQuotaKeysRelation string
const (
QuotaKeysContain = TQuotaKeysRelation("contain")
QuotaKeysBelong = TQuotaKeysRelation("belong")
QuotaKeysEqual = TQuotaKeysRelation("equal")
QuotaKeysExclude = TQuotaKeysRelation("exclude")
)
func stringRelation(s1, s2 string) TQuotaKeysRelation {
if s1 == s2 {
return QuotaKeysEqual
} else if len(s1) == 0 {
return QuotaKeysContain
} else if len(s2) == 0 {
return QuotaKeysBelong
} else {
return QuotaKeysExclude
}
}
func relation(k1, k2 IQuotaKeys) TQuotaKeysRelation {
a1 := k1.Values()
a2 := k2.Values()
relationMap := make(map[TQuotaKeysRelation]int, 0)
for i := 0; i < len(a1); i += 1 {
rel := stringRelation(a1[i], a2[i])
if _, ok := relationMap[rel]; ok {
relationMap[rel] = relationMap[rel] + 1
} else {
relationMap[rel] = 1
}
}
switch len(relationMap) {
case 1:
for k := range relationMap {
return k
}
case 2:
_, equalExist := relationMap[QuotaKeysEqual]
if equalExist {
if _, ok := relationMap[QuotaKeysContain]; ok {
return QuotaKeysContain
}
if _, ok := relationMap[QuotaKeysBelong]; ok {
return QuotaKeysBelong
}
return QuotaKeysExclude
}
}
return QuotaKeysExclude
}
type TQuotaList []IQuota
func (a TQuotaList) Len() int { return len(a) }
func (a TQuotaList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a TQuotaList) Less(i, j int) bool {
iKeys := a[i].GetKeys()
jKeys := a[j].GetKeys()
relation := relation(iKeys, jKeys)
switch relation {
case QuotaKeysContain:
return true
case QuotaKeysBelong:
return false
}
iw := QuotaKeyWeight(iKeys)
jw := QuotaKeyWeight(jKeys)
if iw < jw {
return true
} else if iw > jw {
return false
}
return iKeys.Compare(jKeys) < 0
}