quota recode

This commit is contained in:
Qiu Jian
2019-12-02 22:58:06 +08:00
parent 5750d6dd59
commit 3dba5360d7
156 changed files with 5904 additions and 2181 deletions
+27
View File
@@ -54,6 +54,33 @@ func init() {
printObject(result)
return nil
})
R(&QuotaOptions{}, "project-quota", "Show project-quota for current user or tenant", func(s *mcclient.ClientSession, args *QuotaOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.ProjectQuotas.GetQuota(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&QuotaOptions{}, "region-quota", "Show region-quota for current user or tenant", func(s *mcclient.ClientSession, args *QuotaOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.RegionQuotas.GetQuota(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&QuotaOptions{}, "zone-quota", "Show zone-quota for current user or tenant", func(s *mcclient.ClientSession, args *QuotaOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.ZoneQuotas.GetQuota(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&QuotaOptions{}, "image-quota", "Show image quota for current user or tenant", func(s *mcclient.ClientSession, args *QuotaOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.ImageQuotas.GetQuota(s, params)
+2 -2
View File
@@ -102,7 +102,7 @@ require (
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/pflag v1.0.3 // indirect
github.com/stretchr/testify v1.3.0
github.com/stretchr/testify v1.4.0
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181108132626-805d01dd0e2e
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20191108095731-8ca4b370cde4
github.com/tinylib/msgp v1.1.0 // indirect
@@ -137,7 +137,7 @@ require (
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d
yunion.io/x/pkg v0.0.0-20191121110824-e03b47b93fe0
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/sqlchemy v0.0.0-20191122085525-2d3bfdb3f51c
yunion.io/x/sqlchemy v0.0.0-20191206101534-32ae27ae30cb
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3
)
+8 -4
View File
@@ -10,6 +10,7 @@ github.com/Azure/azure-sdk-for-go v36.1.0+incompatible h1:smHlbChr/JDmsyUqELZXLs
github.com/Azure/azure-sdk-for-go v36.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest v10.15.5+incompatible h1:vdxx6wM1rVkKt/3niByPVjguoLWkWImOcJNvEykgBzY=
github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/dd-trace-go v0.6.1 h1:nsZ2lohbSw1CKtfNRu3wPh1jFirv6XSz8vqNpuIYWbM=
github.com/DataDog/dd-trace-go v0.6.1/go.mod h1:SmQTTcC37XMyEm75HV0AWiZIYxDiaNhRi49zorIpW+o=
@@ -460,6 +461,8 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syncthing/syncthing v0.14.48-rc.4/go.mod h1:nw3siZwHPA6M8iSfjDCWQ402eqvEIasMQOE8nFOxy7M=
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181108132626-805d01dd0e2e h1:CtKVGXKh2bfmepZ/YogAjvL/CrSy9NGZET500K7arf4=
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181108132626-805d01dd0e2e/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
@@ -592,6 +595,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.zx2c4.com/wireguard v0.0.20190908 h1:SUoXDdwSMtomLdvke+zz83/u9tNvl4hHmcTIWp38tow=
golang.zx2c4.com/wireguard v0.0.20190908/go.mod h1:LhfXh5z6bLC2lW2ve6BzYZFwnnsXK3OQjySR0Yh2dO8=
@@ -658,8 +662,8 @@ yunion.io/x/executor v0.0.0-20191202093616-92e2e6119257 h1:LZ6eC1uoLDAp7NQlaCy+D
yunion.io/x/executor v0.0.0-20191202093616-92e2e6119257/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051 h1:vtZw2iwGrsARNSwRTREGjmr2BWPdxbmXVkb3kI1qu28=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7 h1:9NcHs2OFMyN8O8SmJ3sFm5AJSVXP3u1N3avJsbyX3RI=
yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
yunion.io/x/jsonutils v0.0.0-20191203054634-2178957d86cf h1:F7lWnVAPAi7qfpKaatKosNbnXyKkmgMK28tLncJe5Lg=
yunion.io/x/jsonutils v0.0.0-20191203054634-2178957d86cf/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b h1:Z9z+7iegu0HXuL+S8taVWRd1P4b9JJOgPXIeoqYrj7c=
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d h1:59zrDL7Ft+hDukguJRmLr/Gdu/9V75x+yX99ovZwfaA=
@@ -671,7 +675,7 @@ yunion.io/x/pkg v0.0.0-20191121110824-e03b47b93fe0 h1:gMENCnVkKO5BlwtbKSKW5liEeH
yunion.io/x/pkg v0.0.0-20191121110824-e03b47b93fe0/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v0.0.0-20191122085525-2d3bfdb3f51c h1:4zMTt6JASU+hwm9AOb1sQkAgXlKbludSIQ6G7i7mPPA=
yunion.io/x/sqlchemy v0.0.0-20191122085525-2d3bfdb3f51c/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/sqlchemy v0.0.0-20191206101534-32ae27ae30cb h1:NYGUHfl8aelOGMp/LCCbnPZwLZl2tybN9ZM+XMnja8Y=
yunion.io/x/sqlchemy v0.0.0-20191206101534-32ae27ae30cb/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3 h1:bfC8EhXYvyGYldRWlzxiCM39Zfj3s3+zham9mW2h2LE=
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
+34 -33
View File
@@ -121,10 +121,10 @@ type ServerConfigs struct {
// ResourceType "shared|prepaid|dedicated"`
ResourceType string `json:"resource_type"`
InstanceType string `json:"instance_type"`
Project string `json:"project_id"`
Domain string `json:"domain_id"`
Backup bool `json:"backup"`
Count int `json:"count"`
// Project string `json:"project_id"`
// Domain string `json:"domain_id"`
Backup bool `json:"backup"`
Count int `json:"count"`
Disks []*DiskConfig `json:"disks"`
Networks []*NetworkConfig `json:"nets"`
@@ -156,39 +156,40 @@ type DeployConfig struct {
}
type ServerCreateInput struct {
apis.Meta
apis.VirtualResourceCreateInput
DeletePreventableCreateInput
*ServerConfigs
Name string `json:"name"`
GenerateName string `json:"generate_name"`
VmemSize int `json:"vmem_size"`
VcpuCount int `json:"vcpu_count"`
UserData string `json:"user_data"`
// Name string `json:"name"`
// GenerateName string `json:"generate_name"`
VmemSize int `json:"vmem_size"`
VcpuCount int `json:"vcpu_count"`
UserData string `json:"user_data"`
KeypairId string `json:"keypair_id"`
Password string `json:"password"`
Cdrom string `json:"cdrom"`
Vga string `json:"vga"`
Vdi string `json:"vdi"`
Bios string `json:"bios"`
Description string `json:"description"`
BootOrder string `json:"boot_order"`
EnableCloudInit bool `json:"enable_cloud_init"`
ResetPassword *bool `json:"reset_password"`
DisableDelete *bool `json:"disable_delete"`
ShutdownBehavior string `json:"shutdown_behavior"`
AutoStart bool `json:"auto_start"`
DeployConfigs []*DeployConfig `json:"deploy_configs"`
IsSystem bool `json:"is_system"`
Duration string `json:"duration"`
AutoPrepaidRecycle bool `json:"auto_prepaid_recycle,omitfalse"`
SecgroupId string `json:"secgrp_id"`
EipBw int `json:"eip_bw,omitzero"`
EipChargeType string `json:"eip_charge_type,omitempty"`
Eip string `json:"eip,omitempty"`
InstanceSnapshotId string `json:"instance_snapshot_id,omitempty"`
Secgroups []string `json:"secgroups"`
KeypairId string `json:"keypair_id"`
Password string `json:"password"`
Cdrom string `json:"cdrom"`
Vga string `json:"vga"`
Vdi string `json:"vdi"`
Bios string `json:"bios"`
// Description string `json:"description"`
BootOrder string `json:"boot_order"`
EnableCloudInit bool `json:"enable_cloud_init"`
ResetPassword *bool `json:"reset_password"`
// DisableDelete *bool `json:"disable_delete"`
ShutdownBehavior string `json:"shutdown_behavior"`
AutoStart bool `json:"auto_start"`
DeployConfigs []*DeployConfig `json:"deploy_configs"`
// IsSystem bool `json:"is_system"`
Duration string `json:"duration"`
AutoPrepaidRecycle bool `json:"auto_prepaid_recycle,omitfalse"`
SecgroupId string `json:"secgrp_id"`
EipBw int `json:"eip_bw,omitzero"`
EipChargeType string `json:"eip_charge_type,omitempty"`
Eip string `json:"eip,omitempty"`
InstanceSnapshotId string `json:"instance_snapshot_id,omitempty"`
Secgroups []string `json:"secgroups"`
OsType string `json:"os_type"`
// Fill by server
+3 -5
View File
@@ -36,13 +36,11 @@ const (
)
type BucketCreateInput struct {
apis.Meta
apis.VirtualResourceCreateInput
RegionalResourceCreateInput
ManagedResourceCreateInput
Name string `json:"name"`
Cloudregion string `json:"cloudregion"`
Manager string `json:"manager"`
StorageClass string `json:"storage_class"`
Description string `json:"description"`
}
type BucketDetail struct {
+1 -2
View File
@@ -53,7 +53,7 @@ type CloudaccountCredentialInput struct {
}
type CloudaccountCreateInput struct {
apis.Meta
apis.EnabledStatusStandaloneResourceCreateInput
Provider string
Brand string
@@ -63,7 +63,6 @@ type CloudaccountCreateInput struct {
Secret string
AccessUrl string
TenantId string
Name string
Description string
Enabled bool
EnableAutoSync bool
+1
View File
@@ -54,6 +54,7 @@ const (
CITY_BAO_DING = "Baoding" //保定
CITY_NAN_JING = "Nanjing" //南京
CITY_FO_SHAN = "Foshan" //佛山
CITY_QUAN_ZHOU = "Quanzhou" //泉州
// 日本
CITY_TOKYO = "Tokyo" //东京
+18 -13
View File
@@ -19,7 +19,7 @@ import (
)
type DiskCreateInput struct {
apis.Meta
apis.VirtualResourceCreateInput
*DiskConfig
@@ -29,16 +29,14 @@ type DiskCreateInput struct {
PreferWire string `json:"prefer_wire_id"`
PreferHost string `json:"prefer_host_id"`
Name string `json:"name"`
Description string `json:"description"`
Hypervisor string `json:"hypervisor"`
Project string `json:"project"`
Domain string `json:"domain_id"`
Hypervisor string `json:"hypervisor"`
// Project string `json:"project"`
// Domain string `json:"domain_id"`
}
// ToServerCreateInput used by disk schedule
func (req *DiskCreateInput) ToServerCreateInput() *ServerCreateInput {
return &ServerCreateInput{
input := ServerCreateInput{
ServerConfigs: &ServerConfigs{
PreferRegion: req.PreferRegion,
PreferZone: req.PreferZone,
@@ -46,22 +44,29 @@ func (req *DiskCreateInput) ToServerCreateInput() *ServerCreateInput {
PreferHost: req.PreferHost,
Hypervisor: req.Hypervisor,
Disks: []*DiskConfig{req.DiskConfig},
Project: req.Project,
Domain: req.Domain,
// Project: req.Project,
// Domain: req.Domain,
},
Name: req.Name,
}
input.Name = req.Name
input.Project = req.Project
input.ProjectId = req.ProjectId
input.Domain = req.Domain
input.DomainId = req.DomainId
return &input
}
func (req *ServerCreateInput) ToDiskCreateInput() *DiskCreateInput {
return &DiskCreateInput{
input := DiskCreateInput{
DiskConfig: req.Disks[0],
PreferRegion: req.PreferRegion,
PreferHost: req.PreferHost,
PreferZone: req.PreferZone,
PreferWire: req.PreferWire,
Name: req.Name,
Project: req.Project,
Hypervisor: req.Hypervisor,
}
input.Name = req.Name
input.Project = req.Project
input.Domain = req.Domain
return &input
}
+8
View File
@@ -244,3 +244,11 @@ const (
VM_METADATA_OS_NAME = "os_name"
VM_METADATA_OS_VERSION = "os_version"
)
func Hypervisors2HostTypes(hypervisors []string) []string {
hostTypes := make([]string, len(hypervisors))
for i := range hypervisors {
hostTypes[i] = HYPERVISOR_HOSTTYPE[hypervisors[i]]
}
return hostTypes
}
+15
View File
@@ -0,0 +1,15 @@
package compute
type RegionalResourceCreateInput struct {
Cloudregion string `json:"cloudregion"`
CloudregionId string `json:"cloudregion_id"`
}
type ManagedResourceCreateInput struct {
Manager string `json:"manager"`
ManagerId string `json:"manager_id"`
}
type DeletePreventableCreateInput struct {
DisableDelete *bool `json:"disable_delete"`
}
+1 -3
View File
@@ -48,9 +48,7 @@ type NetworkListInput struct {
}
type NetworkCreateInput struct {
apis.Meta
IsSystem bool `json:"is_system"`
apis.SharableVirtualResourceCreateInput
// description: network name
// unique: true
+3 -6
View File
@@ -26,7 +26,7 @@ import (
)
type SSecgroupRuleCreateInput struct {
apis.Meta
apis.ResourceBaseCreateInput
Priority int
Protocol string
@@ -70,12 +70,9 @@ func (input *SSecgroupRuleCreateInput) Check() error {
}
type SSecgroupCreateInput struct {
apis.Meta
apis.SharableVirtualResourceCreateInput
Name string
Status string
Description string
Rules []SSecgroupRuleCreateInput
Rules []SSecgroupRuleCreateInput `json:"rules"`
}
type SSecgroupListFilterInput struct {
+97
View File
@@ -0,0 +1,97 @@
package apis
type DomainizedResourceCreateInput struct {
// description: the owner domain name or id
// required: false
Domain string `json:"project_domain"`
// description: the owner domain name or id, alias field of domain
// required: false
DomainId string `json:"domain_id"`
}
type ProjectizedResourceCreateInput struct {
DomainizedResourceCreateInput
// description: the owner project name or id
// required: false
Project string `json:"project"`
// description: the owner project name or id, alias field of project
// required: false
ProjectId string `json:"project_id"`
}
type SharableVirtualResourceCreateInput struct {
VirtualResourceCreateInput
// description: indicate the resource is a public resource
// required: false
IsPublic *bool `json:"is_public"`
// description: indicate the shared scope for a public resource, which can be domain or system or none
// required: false
PublicScope string `json:"public_scope"`
}
type VirtualResourceCreateInput struct {
StatusStandaloneResourceCreateInput
ProjectizedResourceCreateInput
// description: indicate the resource is a system resource, which is not visible to user
// required: false
IsSystem *bool `json:"is_system"`
}
type EnabledStatusStandaloneResourceCreateInput struct {
StatusStandaloneResourceCreateInput
// description: indicate the resource is enabled/disabled by administrator
// required: false
Enabled *bool `json:"enabled"`
}
type StatusStandaloneResourceCreateInput struct {
StandaloneResourceCreateInput
// description: the status of the resource
// required: false
Status string `json:"status"`
}
type StandaloneResourceCreateInput struct {
ResourceBaseCreateInput
// description: resource name, required if generated_name is not given
// unique: true
// required: false
// example: test-network
Name string `json:"name"`
// description: generated resource name, given a pattern to generate name, required if name is not given
// unique: false
// required: false
// example: test###
GenerateName string `json:"generate_name"`
// description: resource description
// required: false
// example: test create network
Description string `json:"description"`
// description: the resource is an emulated resource
// required: false
IsEmulated *bool `json:"is_emulated"`
}
type JoinResourceBaseCreateInput struct {
ResourceBaseCreateInput
}
type ResourceBaseCreateInput struct {
ModelBaseCreateInput
}
type ModelBaseCreateInput struct {
Meta
}
+3
View File
@@ -53,6 +53,9 @@ type ServerConfig struct {
GuestStatus string `json:"guest_status"`
Cdrom string `json:"cdrom"`
Project string `json:"project_id"`
Domain string `json:"domain_id"`
// DEPRECATED
Metadata map[string]string `json:"__meta__"`
ForGuests []*ForGuest `json:"for_guests"`
+1
View File
@@ -89,6 +89,7 @@ func convertParams(params []*param) []reflect.Value {
type param struct {
pType reflect.Type
input interface{}
isPtr bool
}
func newParam(pType reflect.Type, input interface{}) *param {
+2 -2
View File
@@ -1108,7 +1108,7 @@ func (dispatcher *DBModelDispatcher) Create(ctx context.Context, query jsonutils
}()
OpsLog.LogEvent(model, ACT_CREATE, model.GetShortDesc(ctx), userCred)
dispatcher.modelManager.OnCreateComplete(ctx, []IModel{model}, userCred, query, data)
dispatcher.modelManager.OnCreateComplete(ctx, []IModel{model}, userCred, ownerId, query, data)
return getItemDetails(dispatcher.modelManager, model, ctx, userCred, query)
}
@@ -1239,7 +1239,7 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
lockman.LockClass(ctx, manager, GetLockClassKey(manager, ownerId))
defer lockman.ReleaseClass(ctx, manager, GetLockClassKey(manager, ownerId))
manager.OnCreateComplete(ctx, models, userCred, query, multiData[0])
manager.OnCreateComplete(ctx, models, userCred, ownerId, query, multiData[0])
}
return results, nil
}
+1 -1
View File
@@ -187,7 +187,7 @@ func attachItems(dispatcher *DBJointModelDispatcher, master IStandaloneModel, sl
}
item.PostCreate(ctx, userCred, nil, query, data)
OpsLog.LogAttachEvent(ctx, master, slave, userCred, jsonutils.Marshal(item))
dispatcher.modelManager.OnCreateComplete(ctx, []IModel{item}, userCred, query, data)
dispatcher.modelManager.OnCreateComplete(ctx, []IModel{item}, userCred, nil, query, data)
return getItemDetails(dispatcher.JointModelManager(), item, ctx, userCred, query)
}
@@ -19,7 +19,9 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
@@ -78,3 +80,12 @@ func (self *SEnabledStatusStandaloneResourceBase) PerformDisable(ctx context.Con
}
return nil, nil
}
func (manager *SEnabledStatusStandaloneResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.EnabledStatusStandaloneResourceCreateInput) (apis.EnabledStatusStandaloneResourceCreateInput, error) {
var err error
input.StatusStandaloneResourceCreateInput, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput)
if err != nil {
return input, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ValidateCreateData")
}
return input, nil
}
+1 -1
View File
@@ -83,7 +83,7 @@ type IModelManager interface {
BatchCreateValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
// ValidateCreateData dynamic called by dispatcher
// ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
OnCreateComplete(ctx context.Context, items []IModel, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject)
OnCreateComplete(ctx context.Context, items []IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject)
BatchPreValidate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
query jsonutils.JSONObject, data *jsonutils.JSONDict, count int) (func(), error)
+10
View File
@@ -24,6 +24,7 @@ import (
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
@@ -226,3 +227,12 @@ func (manager *SJointResourceBaseManager) ResourceScope() rbacutils.TRbacScope {
func (manager *SJointResourceBaseManager) NamespaceScope() rbacutils.TRbacScope {
return rbacutils.ScopeSystem
}
func (manager *SJointResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.JoinResourceBaseCreateInput) (apis.JoinResourceBaseCreateInput, error) {
var err error
input.ResourceBaseCreateInput, err = manager.SResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.ResourceBaseCreateInput)
if err != nil {
return input, err
}
return input, nil
}
+3 -3
View File
@@ -193,11 +193,11 @@ func (manager *SModelBaseManager) AllowCreateItem(ctx context.Context, userCred
return false
}
func (manager *SModelBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
return data, nil
func (manager *SModelBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.ModelBaseCreateInput) (apis.ModelBaseCreateInput, error) {
return input, nil
}
func (manager *SModelBaseManager) OnCreateComplete(ctx context.Context, items []IModel, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
func (manager *SModelBaseManager) OnCreateComplete(ctx context.Context, items []IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
// do nothing
}
+6
View File
@@ -17,6 +17,8 @@ package quotas
import (
"fmt"
"strings"
"yunion.io/x/onecloud/pkg/httperrors"
)
type SOutOfQuotaError struct {
@@ -29,6 +31,10 @@ type SOutOfQuotaErrors struct {
errors []SOutOfQuotaError
}
func (e *SOutOfQuotaError) Cause() error {
return httperrors.ErrOutOfQuota
}
func (e *SOutOfQuotaError) Error() string {
return fmt.Sprintf("%s limit %d used %d", e.name, e.limit, e.used)
}
+96 -288
View File
@@ -25,7 +25,6 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/appctx"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -88,51 +87,45 @@ func AddQuotaHandler(manager *SQuotaBaseManager, prefix string, app *appsrv.Appl
auth.Authenticate(checkQuotaHanlder), nil, "check_quota", nil)*/
}
func (manager *SQuotaBaseManager) queryQuota(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platforma []string, refresh bool) (*jsonutils.JSONDict, IQuota, error) {
func (manager *SQuotaBaseManager) queryQuota(ctx context.Context, quota IQuota, refresh bool) (*jsonutils.JSONDict, error) {
ret := jsonutils.NewDict()
quota := manager.newQuota()
err := manager.GetQuota(ctx, scope, ownerId, platforma, quota)
if err != nil {
return nil, nil, err
}
keys := quota.GetKeys()
usage := manager.newQuota()
err = manager.usageStore.GetQuota(ctx, scope, ownerId, platforma, usage)
err := manager.usageStore.GetQuota(ctx, keys, usage)
if err != nil {
return nil, nil, err
return nil, err
}
if usage.IsEmpty() || refresh {
if refresh {
usageChan := make(chan IQuota)
manager.PostUsageJob(scope, ownerId, nil, usageChan, false, true)
manager.PostUsageJob(keys, usageChan, true)
usage = <-usageChan
}
pending := manager.newQuota()
err = manager.GetPendingUsage(ctx, scope, ownerId, nil, pending)
pendings, err := manager.GetPendingUsages(ctx, keys)
if err != nil {
return nil, nil, err
return nil, err
}
ret.Update(jsonutils.Marshal(keys))
ret.Update(quota.ToJSON(""))
ret.Update(usage.ToJSON("usage"))
if !pending.IsEmpty() {
ret.Update(pending.ToJSON("pending"))
}
if scope == rbacutils.ScopeDomain {
total, err := manager.getDomainTotalQuota(ctx, ownerId.GetProjectDomainId(), nil)
if err == nil {
ret.Update(total.ToJSON("total"))
if len(pendings) > 0 {
pendingArray := jsonutils.NewArray()
for _, q := range pendings {
pendingArray.Add(q.ToJSON(""))
}
ret.Add(pendingArray, "pending")
}
return ret, usage, nil
return ret, nil
}
func (manager *SQuotaBaseManager) getQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request) {
params, query, _ := appsrv.FetchEnv(ctx, w, r)
userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
params := appctx.AppContextParams(ctx)
var ownerId mcclient.IIdentityProvider
var scope rbacutils.TRbacScope
@@ -157,27 +150,24 @@ func (manager *SQuotaBaseManager) getQuotaHanlder(ctx context.Context, w http.Re
scope = rbacutils.ScopeProject
}
quota, _, err := manager.queryQuota(ctx, scope, ownerId, nil, true)
keys := OwnerIdQuotaKeys(scope, ownerId)
refresh := jsonutils.QueryBoolean(query, "refresh", false)
quotaList, err := manager.listQuotas(ctx, userCred, keys.DomainId, keys.ProjectId, refresh)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
body := jsonutils.NewDict()
body.Add(quota, manager.KeywordPlural())
appsrv.SendJSON(w, body)
manager.sendQuotaList(w, quotaList)
}
func FetchSetQuotaScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (mcclient.IIdentityProvider, rbacutils.TRbacScope, rbacutils.TRbacScope, error) {
func (manager *SQuotaBaseManager) fetchSetQuotaScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (mcclient.IIdentityProvider, rbacutils.TRbacScope, rbacutils.TRbacScope, error) {
var scope rbacutils.TRbacScope
ownerId, err := db.FetchProjectInfo(ctx, data)
if err != nil {
return nil, scope, scope, err
}
var requestScope rbacutils.TRbacScope
ownerScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), quotaKeywords, policy.PolicyActionUpdate)
ownerScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionUpdate)
if ownerId != nil {
if len(ownerId.GetProjectId()) > 0 {
// project level
@@ -204,8 +194,8 @@ func FetchSetQuotaScope(ctx context.Context, userCred mcclient.TokenCredential,
}
func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request) {
params, _, body := appsrv.FetchEnv(ctx, w, r)
userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
params := appctx.AppContextParams(ctx)
projectId := params["<tenantid>"]
domainId := params["<domainid>"]
@@ -215,18 +205,23 @@ func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.Re
} else if len(domainId) > 0 {
data.Add(jsonutils.NewString(domainId), "project_domain")
}
ownerId, scope, allowScope, err := FetchSetQuotaScope(ctx, userCred, data)
ownerId, scope, _, err := manager.fetchSetQuotaScope(ctx, userCred, data)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
body, err := appsrv.FetchJSON(r)
if err != nil {
log.Errorf("Fail to decode JSON request body: %s", err)
if body == nil {
httperrors.InvalidInputError(w, "fail to decode body")
return
}
keys := SBaseQuotaKeys{}
body.Unmarshal(&keys, manager.KeywordPlural())
paramKeys := OwnerIdQuotaKeys(scope, ownerId)
keys.DomainId = paramKeys.DomainId
keys.ProjectId = paramKeys.ProjectId
quota := manager.newQuota()
err = body.Unmarshal(quota, manager.KeywordPlural())
if err != nil {
@@ -234,8 +229,10 @@ func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.Re
httperrors.InvalidInputError(w, "fail to decode body")
return
}
quota.SetKeys(keys)
oquota := manager.newQuota()
err = manager.GetQuota(ctx, scope, ownerId, nil, oquota)
err = manager.GetQuota(ctx, keys, oquota)
if err != nil {
log.Errorf("get quota fail %s", err)
httperrors.GeneralServerError(w, err)
@@ -246,72 +243,14 @@ func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.Re
case QUOTA_ACTION_ADD:
oquota.Add(quota)
case QUOTA_ACTION_RESET:
oquota.FetchSystemQuota(scope, ownerId)
oquota.FetchSystemQuota()
case QUOTA_ACTION_REPLACE:
oquota = quota
default:
oquota.Update(quota)
}
if consts.GetNonDefaultDomainProjects() {
// only if non-default-domain-project is turned ON, check the conformance between project quotas and domain quotas
if scope == rbacutils.ScopeProject {
total, err := manager.getDomainTotalQuota(ctx, ownerId.GetProjectDomainId(), []string{ownerId.GetProjectId()})
if err != nil {
log.Errorf("get total quota fail %s", err)
httperrors.GeneralServerError(w, err)
return
}
domainQuota := manager.newQuota()
err = manager.GetQuota(ctx, rbacutils.ScopeDomain, ownerId, nil, domainQuota)
if err != nil {
log.Errorf("GetQuota for domain %s fail %s", ownerId.GetProjectDomainId(), err)
httperrors.GeneralServerError(w, err)
return
}
total.Add(oquota)
err = total.Exceed(quota, domainQuota)
if err != nil {
// exeed domain quota
cascade, _ := body.Bool(manager.KeywordPlural(), "cascade")
if !cascade {
log.Errorf("project quota exeed domain quota: %s", err)
httperrors.OutOfQuotaError(w, "project quota exeed domain quota")
return
} else {
if allowScope != rbacutils.ScopeSystem {
httperrors.OutOfQuotaError(w, "project quota exeed domain quota, no previlige to cascade set")
return
} else {
// cascade set domain quota
err = manager.SetQuota(ctx, userCred, rbacutils.ScopeDomain, ownerId, nil, total)
if err != nil {
log.Errorf("cascade set quota fail %s", err)
httperrors.GeneralServerError(w, err)
return
}
}
}
}
} else {
total, err := manager.getDomainTotalQuota(ctx, ownerId.GetProjectDomainId(), nil)
if err != nil {
log.Errorf("get total quota fail %s", err)
httperrors.GeneralServerError(w, err)
return
}
err = total.Exceed(quota, oquota)
if err != nil {
log.Errorf("project quota exeed domain quota: %s", err)
httperrors.OutOfQuotaError(w, "project quota exeed domain quota")
return
}
}
}
err = manager.SetQuota(ctx, userCred, scope, ownerId, nil, oquota)
err = manager.SetQuota(ctx, userCred, oquota)
if err != nil {
log.Errorf("set quota fail %s", err)
httperrors.GeneralServerError(w, err)
@@ -323,6 +262,7 @@ func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.Re
}
func (manager *SQuotaBaseManager) listDomainQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request) {
_, query, _ := appsrv.FetchEnv(ctx, w, r)
userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
if consts.IsRbacEnabled() {
@@ -338,11 +278,16 @@ func (manager *SQuotaBaseManager) listDomainQuotaHanlder(ctx context.Context, w
}
}
quotaList, err := manager.listQuotas(ctx, "")
refresh := jsonutils.QueryBoolean(query, "refresh", false)
quotaList, err := manager.listQuotas(ctx, userCred, "", "", refresh)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
manager.sendQuotaList(w, quotaList)
}
func (manager *SQuotaBaseManager) sendQuotaList(w http.ResponseWriter, quotaList []jsonutils.JSONObject) {
rbody := jsonutils.NewDict()
rbody.Set(manager.KeywordPlural(), jsonutils.NewArray(quotaList...))
appsrv.SendJSON(w, rbody)
@@ -375,218 +320,81 @@ func (manager *SQuotaBaseManager) listProjectQuotaHanlder(ctx context.Context, w
}
domainId := owner.GetProjectDomainId()
quotaList, err := manager.listQuotas(ctx, domainId)
refresh := jsonutils.QueryBoolean(query, "refresh", false)
quotaList, err := manager.listQuotas(ctx, userCred, domainId, "", refresh)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
rbody := jsonutils.NewDict()
rbody.Set(manager.KeywordPlural(), jsonutils.NewArray(quotaList...))
appsrv.SendJSON(w, rbody)
manager.sendQuotaList(w, quotaList)
}
func (manager *SQuotaBaseManager) getDomainTotalQuota(ctx context.Context, targetDomainId string, excludes []string) (IQuota, error) {
q := manager.Query("domain_id", "tenant_id", "platform")
q = q.Equals("domain_id", targetDomainId)
q = q.IsNotEmpty("tenant_id")
if len(excludes) > 0 {
q = q.NotIn("tenant_id", excludes)
}
// dsable platform
q = q.IsNullOrEmpty("platform")
rows, err := q.Rows()
if err != nil && err != sql.ErrNoRows {
return nil, err
}
defer rows.Close()
ret := manager.newQuota()
for rows.Next() {
var domainId, projectId, platformStr string
err := rows.Scan(&domainId, &projectId, &platformStr)
if err != nil {
return nil, errors.Wrap(err, "scan")
}
scope := rbacutils.ScopeProject
owner := db.SOwnerId{
DomainId: domainId,
ProjectId: projectId,
}
platform := strings.Split(platformStr, nameSeparator)
quota := manager.newQuota()
err = manager.GetQuota(ctx, scope, &owner, platform, quota)
if err != nil {
return nil, errors.Wrap(err, "GetQuota")
}
ret.Add(quota)
}
return ret, nil
}
func (manager *SQuotaBaseManager) listQuotas(ctx context.Context, targetDomainId string) ([]jsonutils.JSONObject, error) {
q := manager.Query("domain_id", "tenant_id", "platform")
func (manager *SQuotaBaseManager) listQuotas(ctx context.Context, userCred mcclient.TokenCredential, targetDomainId string, targetProjectId string, refresh bool) ([]jsonutils.JSONObject, error) {
q := manager.Query()
if len(targetDomainId) > 0 {
q = q.Equals("domain_id", targetDomainId)
if len(targetProjectId) > 0 {
q = q.Equals("tenant_id", targetProjectId)
}else {
q = q.IsNotEmpty("tenant_id")
}
} else {
// domain only
q = q.IsNotEmpty("domain_id")
q = q.IsNullOrEmpty("tenant_id")
}
// if tuen OFF NonDefaultDOmainProjects
// no domain quota should return
if !consts.GetNonDefaultDomainProjects() {
q = q.IsNotEmpty("tenant_id")
}
// dsable platform
q = q.IsNullOrEmpty("platform")
rows, err := q.Rows()
if err != nil && err != sql.ErrNoRows {
log.Errorf("query quotas fail %s", err)
return nil, httperrors.NewInternalServerError("query quotas %s", err)
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
return nil, httperrors.NewInternalServerError("query quotas %s", err)
}else {
return nil, nil
}
}
defer rows.Close()
quotaList := make([]IQuota, 0)
keyList := make([]IQuotaKeys, 0)
ret := make([]jsonutils.JSONObject, 0)
for rows.Next() {
var domainId, projectId, platformStr string
err := rows.Scan(&domainId, &projectId, &platformStr)
quota := manager.newQuota()
err := q.Row2Struct(rows, quota)
if err != nil {
log.Errorf("scan domain_id, project_id, platform error %s", err)
return nil, httperrors.NewInternalServerError("scan quotas %s", err)
return nil, errors.Wrap(err, "q.Row2Struct")
}
scope := rbacutils.ScopeProject
owner := db.SOwnerId{
DomainId: domainId,
ProjectId: projectId,
}
if len(projectId) == 0 {
scope = rbacutils.ScopeDomain
}
platform := strings.Split(platformStr, nameSeparator)
quota, _, err := manager.queryQuota(ctx, scope, &owner, platform, false)
if err != nil {
log.Errorf("query quota for %s fail %s", getMemoryStoreKey(scope, &owner, platform), err)
continue
}
if len(projectId) > 0 {
quota.Set("tenant_id", jsonutils.NewString(projectId))
quota.Set("domain_id", jsonutils.NewString(domainId))
// fetch without cache expiration check
project, err := db.TenantCacheManager.FetchTenantByIdWithoutExpireCheck(ctx, projectId)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
continue
}
log.Errorf("fail to query project %s", projectId)
return nil, err
}
quota.Set("tenant", jsonutils.NewString(project.Name))
quota.Set("project_domain", jsonutils.NewString(project.Domain))
} else {
quota.Set("domain_id", jsonutils.NewString(domainId))
// fetch without cache expiration check
domain, err := db.TenantCacheManager.FetchDomainByIdWithoutExpireCheck(ctx, domainId)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
continue
}
log.Errorf("fail to query domain %s", domainId)
return nil, err
}
quota.Set("project_domain", jsonutils.NewString(domain.Name))
}
if len(platformStr) > 0 {
quota.Set("platform", jsonutils.NewString(platformStr))
}
ret = append(ret, quota)
quotaList = append(quotaList, quota)
keyList = append(keyList, quota.GetKeys())
}
// if no projects for a domain and NonDefaultDomainProjects is turned ON
if len(ret) == 0 && len(targetDomainId) > 0 && consts.GetNonDefaultDomainProjects() {
// return the initial quota of targetDomainId
scope := rbacutils.ScopeDomain
owner := db.SOwnerId{
DomainId: targetDomainId,
idNameMap, err := manager.keyList2IdNameMap(ctx, keyList)
var fields []string
for i := range quotaList {
keys := quotaList[i].GetKeys()
keyJson := jsonutils.Marshal(keys).(*jsonutils.JSONDict)
if idNameMap != nil {
// no error, do check
if len(fields) == 0 {
fields = keys.Fields()
}
values := keys.Values()
for i := range fields {
if strings.HasSuffix(fields[i], "_id") && len(values[i]) > 0 {
if len(idNameMap[fields[i]][values[i]]) == 0 {
manager.DeleteAllQuotas(ctx, userCred, keys)
manager.pendingStore.DeleteAllQuotas(ctx, userCred, keys)
manager.usageStore.DeleteAllQuotas(ctx, userCred, keys)
continue
}else {
keyJson.Add(jsonutils.NewString(idNameMap[fields[i]][values[i]]), fields[i][:len(fields[i])-3])
}
}
}
}
platform := []string{}
quota, _, err := manager.queryQuota(ctx, scope, &owner, platform, false)
quotaJson, err := manager.queryQuota(ctx, quotaList[i], refresh)
if err != nil {
return nil, httperrors.NewInternalServerError("query domain initial quotas %s", err)
return nil, errors.Wrap(err, "manager.queryQuota")
}
quota.Set("domain_id", jsonutils.NewString(targetDomainId))
// fetch without cache expiration check
domain, err := db.TenantCacheManager.FetchDomainByIdWithoutExpireCheck(ctx, targetDomainId)
if err != nil {
log.Errorf("fail to query target domain %s", targetDomainId)
return nil, err
}
quota.Set("project_domain", jsonutils.NewString(domain.Name))
ret = append(ret, quota)
quotaJson.Update(keyJson)
ret = append(ret, quotaJson)
}
return ret, nil
}
/*func checkQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request) {
userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
isAllow := false
if consts.IsRbacEnabled() {
isAllow = policy.PolicyManager.Allow(rbacutils.ScopeSystem, userCred, consts.GetServiceType(),
policy.PolicyDelegation, policy.PolicyActionGet) == rbacutils.Allow
} else {
isAllow = userCred.IsAllow(rbacutils.ScopeSystem, consts.GetServiceType(),
policy.PolicyDelegation, policy.PolicyActionGet)
}
if !isAllow {
httperrors.ForbiddenError(w, "not allow to delegate check quota")
return
}
if consts.IsRbacEnabled() {
if policy.PolicyManager.Allow(rbacutils.ScopeSystem, userCred, consts.GetServiceType(),
_manager.Keyword(), policy.PolicyActionGet) != rbacutils.Allow {
httperrors.ForbiddenError(w, "not allow to query quota")
return
}
}
params := appctx.AppContextParams(ctx)
var ownerId mcclient.IIdentityProvider
projectId := params["<tenantid>"]
if len(projectId) == 0 {
ownerId = userCred
} else {
tenant, err := db.TenantCacheManager.FetchTenantByIdOrName(ctx, projectId)
if err != nil {
if err == sql.ErrNoRows {
httperrors.TenantNotFoundError(w, "project %s not found", projectId)
return
} else {
httperrors.GeneralServerError(w, err)
return
}
}
ownerId = &db.SOwnerId{
DomainId: tenant.DomainId,
Domain: tenant.Domain,
ProjectId: tenant.Id,
Project: tenant.Name,
}
}
body, err := appsrv.FetchJSON(r)
quota := _manager.newQuota()
err = body.Unmarshal(quota, _manager.Keyword())
if err != nil {
log.Errorf("Fail to decode JSON request body: %s", err)
httperrors.InvalidInputError(w, "fail to decode body")
return
}
used, err := _manager.CheckQuota(ctx, userCred, rbacutils.ScopeProject, ownerId, quota)
if err != nil {
httperrors.OutOfQuotaError(w, "Out of quota: %s", err)
return
}
rbody := jsonutils.NewDict()
rbody.Add(used.ToJSON(""), _manager.Keyword())
appsrv.SendJSON(w, rbody)
}*/
+48
View File
@@ -0,0 +1,48 @@
package quotas
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
)
type IQuotaKeys interface {
Fields() []string
Values() []string
Compare(IQuotaKeys) int
}
type IQuota interface {
GetKeys() IQuotaKeys
SetKeys(IQuotaKeys)
FetchSystemQuota()
FetchUsage(ctx context.Context) error
Update(quota IQuota)
Add(quota IQuota)
Sub(quota IQuota)
Exceed(request IQuota, quota IQuota) error
IsEmpty() bool
ToJSON(prefix string) jsonutils.JSONObject
}
type IQuotaStore interface {
GetQuota(ctx context.Context, keys IQuotaKeys, quota IQuota) error
GetChildrenQuotas(ctx context.Context, keys IQuotaKeys) ([]IQuota, error)
GetParentQuotas(ctx context.Context, keys IQuotaKeys) ([]IQuota, error)
SetQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error
AddQuota(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota, target IQuota) error
SubQuota(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota, target IQuota) error
DeleteQuota(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error
DeleteAllQuotas(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error
}
type IQuotaManager interface {
db.IResourceModelManager
FetchIdNames(ctx context.Context, idMap map[string]map[string]string) (map[string]map[string]string, error)
}
+27
View File
@@ -0,0 +1,27 @@
package quotas
import (
"context"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
)
const (
QuotaLockName = "quotas"
)
func LockQuota(ctx context.Context, quota IQuota) {
LockQuotaKeys(ctx, quota.GetKeys())
}
func ReleaseQuota(ctx context.Context, quota IQuota) {
ReleaseQuotaKeys(ctx, quota.GetKeys())
}
func LockQuotaKeys(ctx context.Context, keys IQuotaKeys) {
lockman.LockRawObject(ctx, QuotaLockName, QuotaKeyString(keys))
}
func ReleaseQuotaKeys(ctx context.Context, keys IQuotaKeys) {
lockman.ReleaseRawObject(ctx, QuotaLockName, QuotaKeyString(keys))
}
+118 -71
View File
@@ -18,11 +18,12 @@ import (
"context"
"database/sql"
"reflect"
"strings"
"sort"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/sqlchemy"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -40,18 +41,16 @@ type SQuotaBaseManager struct {
}
const (
nameSeparator = "."
quotaKeyword = "quota"
quotaKeywords = "quotas"
// quotaKeyword = "quota"
// quotaKeywords = "quotas"
quotaUsageKeyword = "quota-usage"
quotaUsageKeywords = "quota-usages"
)
func NewQuotaBaseManager(model interface{}, tableName string, pendingStore IQuotaStore, usageStore IQuotaStore) SQuotaBaseManager {
func NewQuotaBaseManager(model interface{}, tableName string, pendingStore IQuotaStore, usageStore IQuotaStore, keyword, keywordPlural string) SQuotaBaseManager {
return SQuotaBaseManager{
SResourceBaseManager: db.NewResourceBaseManager(model, tableName, quotaKeyword, quotaKeywords),
SResourceBaseManager: db.NewResourceBaseManager(model, tableName, keyword, keywordPlural),
pendingStore: pendingStore,
usageStore: usageStore,
autoCreate: true,
@@ -66,89 +65,134 @@ func NewQuotaUsageManager(model interface{}, tableName string) SQuotaBaseManager
type SQuotaBase struct {
db.SResourceBase
DomainId string `width:"128" charset:"ascii" nullable:"false" primary:"true" list:"user"`
ProjectId string `name:"tenant_id" width:"128" charset:"ascii" nullable:"false" primary:"true" list:"user"`
Platform string `width:"128" charset:"utf8" nullable:"false" primary:"true" list:"user"`
}
func (manager *SQuotaBaseManager) getQuotaInternal(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error {
func (manager *SQuotaBaseManager) GetIQuotaManager() IQuotaManager {
return manager.GetIResourceModelManager().(IQuotaManager)
}
func (manager *SQuotaBaseManager) FetchIdNames(ctx context.Context, idMap map[string]map[string]string) (map[string]map[string]string, error) {
return idMap, nil
}
func (manager *SQuotaBaseManager) getQuotaByKeys(ctx context.Context, keys IQuotaKeys, quota IQuota) error {
q := manager.Query()
q = q.Equals("domain_id", ownerId.GetProjectDomainId())
if scope == rbacutils.ScopeProject {
q = q.Equals("tenant_id", ownerId.GetProjectId())
} else {
q = q.IsNullOrEmpty("tenant_id")
fields := keys.Fields()
values := keys.Values()
for i := range fields {
if len(values[i]) == 0 {
q = q.IsNullOrEmpty(fields[i])
} else {
q = q.Equals(fields[i], values[i])
}
}
var key string
if len(platform) > 0 {
key = strings.Join(platform, nameSeparator)
}
q = q.Equals("platform", key)
err := q.First(quota)
if err != nil && err != sql.ErrNoRows {
return err
} else if err == sql.ErrNoRows && manager.autoCreate {
quota.FetchSystemQuota(scope, ownerId)
return manager.setQuotaInternal(ctx, nil, scope, ownerId, platform, quota)
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
return errors.Wrap(err, "q.First")
}
}
quota.SetKeys(keys)
return nil
}
func (manager *SQuotaBaseManager) setQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error {
base := SQuotaBase{}
base.DomainId = ownerId.GetProjectDomainId()
if scope == rbacutils.ScopeProject {
base.ProjectId = ownerId.GetProjectId()
func filterParentByKey(q *sqlchemy.SQuery, fieldName string, value string) *sqlchemy.SQuery {
if len(value) > 0 {
q = q.Filter(sqlchemy.OR(
sqlchemy.IsNullOrEmpty(q.Field(fieldName)),
sqlchemy.Equals(q.Field(fieldName), value),
))
} else {
q = q.Filter(sqlchemy.IsNullOrEmpty(q.Field(fieldName)))
}
if len(platform) > 0 {
base.Platform = strings.Join(platform, nameSeparator)
}
base.SetModelManager(manager, quota.(db.IModel))
if !reflectutils.FillEmbededStructValue(reflect.Indirect(reflect.ValueOf(quota)), reflect.ValueOf(base)) {
return errors.Error("no embed SBaseQuota")
}
return manager.TableSpec().InsertOrUpdate(quota)
return q
}
func (manager *SQuotaBaseManager) deleteQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string) error {
q := manager.Query("domain_id", "tenant_id", "platform")
q = q.Equals("domain_id", ownerId.GetProjectDomainId())
if scope == rbacutils.ScopeProject {
q = q.Equals("tenant_id", ownerId.GetProjectId())
func filterChildrenByKey(q *sqlchemy.SQuery, fieldName string, value string) *sqlchemy.SQuery {
if len(value) > 0 {
q = q.Equals(fieldName, value)
}
if platform != nil {
q = q.Equals("platform", strings.Join(platform, nameSeparator))
return q
}
func (manager *SQuotaBaseManager) getQuotasInternal(ctx context.Context, keys IQuotaKeys, isParent bool) ([]IQuota, error) {
q := manager.Query()
fields := keys.Fields()
values := keys.Values()
for i := range fields {
if isParent {
q = filterParentByKey(q, fields[i], values[i])
} else {
q = filterChildrenByKey(q, fields[i], values[i])
}
}
rows, err := q.Rows()
if err != nil {
if err != sql.ErrNoRows {
return errors.Wrap(err, "sql.Rows")
if errors.Cause(err) == sql.ErrNoRows {
return nil, nil
} else {
return nil, errors.Wrap(err, "q.Rows")
}
}
defer rows.Close()
results := make([]IQuota, 0)
for rows.Next() {
r := manager.newQuota()
err := q.Row2Struct(rows, r)
if err != nil {
return nil, errors.Wrap(err, "q.Row2Struct")
}
results = append(results, r)
}
sort.Sort(TQuotaList(results))
return results, nil
}
func (manager *SQuotaBaseManager) setQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error {
return manager.TableSpec().InsertOrUpdate(quota)
}
func (manager *SQuotaBaseManager) addQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota, quota IQuota) error {
return manager.TableSpec().Increment(diff, quota)
}
func (manager *SQuotaBaseManager) subQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, cancel IQuota, quota IQuota) error {
return manager.TableSpec().Decrement(cancel, quota)
}
func (manager *SQuotaBaseManager) deleteQuotaByKeys(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error {
quota := manager.newQuota()
quota.SetKeys(keys)
_, err := db.Update(quota.(db.IModel), func() error {
return quota.(db.IModel).MarkDelete()
})
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
return errors.Wrap(err, "Delete")
}
}
return nil
}
func (manager *SQuotaBaseManager) deleteAllQuotas(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error {
quotas, err := manager.getQuotasInternal(ctx, keys, false)
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
return errors.Wrap(err, "manager.getQuotasInternal")
} else {
return nil
}
}
defer rows.Close()
for rows.Next() {
var domainId, tenantId, platform string
err := rows.Scan(&domainId, &tenantId, &platform)
for i := range quotas {
err := manager.deleteQuotaByKeys(ctx, userCred, quotas[i].GetKeys())
if err != nil {
return errors.Wrap(err, "rows.Scan")
}
base := SQuotaBase{
DomainId: domainId,
ProjectId: tenantId,
Platform: platform,
}
base.SetModelManager(manager, &base)
err = base.Delete(ctx, nil)
if err != nil {
return errors.Wrap(err, "Update")
if errors.Cause(err) != sql.ErrNoRows {
return errors.Wrapf(err, "manager.deleteQuotaByKeys %s", QuotaKeyString(quotas[i].GetKeys()))
}
}
}
return nil
@@ -195,18 +239,21 @@ func (manager *SQuotaBaseManager) InitializeData() error {
}
quota := manager.newQuota()
baseKeys := OwnerIdQuotaKeys(scope, ownerId)
if !reflectutils.FillEmbededStructValue(reflect.Indirect(reflect.ValueOf(quota)), reflect.ValueOf(baseKeys)) {
log.Fatalf("invalid quota??? fail to find SBaseQuotaKey")
}
err := metaQuota.GetQuota(context.Background(), scope, ownerId, quota)
if err != nil && err != sql.ErrNoRows {
log.Errorf("metaQuota.GetQuota error %s for %s", err, ownerId)
continue
}
if quota.IsEmpty() {
quota.FetchSystemQuota(scope, ownerId)
quota.FetchSystemQuota()
}
baseQuota := SQuotaBase{}
baseQuota := SBaseQuotaKeys{}
baseQuota.DomainId = ownerId.GetProjectDomainId()
baseQuota.ProjectId = ownerId.GetProjectId()
baseQuota.SetModelManager(manager, quota.(db.IModel))
reflectutils.FillEmbededStructValue(reflect.Indirect(reflect.ValueOf(quota)), reflect.ValueOf(baseQuota))
err = manager.TableSpec().Insert(quota)
+304
View File
@@ -0,0 +1,304 @@
// 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 (
"strings"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SBaseQuotaKeys struct {
DomainId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user"`
ProjectId string `name:"tenant_id" width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user"`
}
type SCloudResourceKeys struct {
SBaseQuotaKeys
// provider
Provider string `width:"32" charset:"ascii" nullable:"false" primary:"true" list:"user"`
// brand
Brand string `width:"32" charset:"ascii" nullable:"false" primary:"true" list:"user"`
// Env
CloudEnv string `width:"32" charset:"ascii" nullable:"false" primary:"true" list:"user"`
// cloudaccount
AccountId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user"`
// cloudprovider
ManagerId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user"`
}
type SRegionalCloudResourceKeys struct {
SCloudResourceKeys
// region
RegionId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user"`
}
type SZonalCloudResourceKeys struct {
SRegionalCloudResourceKeys
// zone
ZoneId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user"`
}
func (k SBaseQuotaKeys) Fields() []string {
return []string{
"domain_id",
"tenant_id",
}
}
func (k SCloudResourceKeys) Fields() []string {
return append(k.SBaseQuotaKeys.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 SBaseQuotaKeys) Values() []string {
return []string{
k.DomainId,
k.ProjectId,
}
}
func (k SCloudResourceKeys) Values() []string {
return append(k.SBaseQuotaKeys.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 SBaseQuotaKeys) Compare(ik IQuotaKeys) int {
k2 := ik.(SBaseQuotaKeys)
if k1.DomainId < k2.DomainId {
return -1
} else if k1.DomainId > k2.DomainId {
return 1
}
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.SBaseQuotaKeys.Compare(k2.SBaseQuotaKeys)
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 SBaseQuotaKeys) 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 SBaseQuotaKeys) OwnerId() mcclient.IIdentityProvider {
return &db.SOwnerId{
DomainId: k.DomainId,
ProjectId: k.ProjectId,
}
}
func QuotaKeyString(k IQuotaKeys) string {
return strings.Join(k.Values(), "-")
}
func OwnerIdQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) SBaseQuotaKeys {
switch scope {
case rbacutils.ScopeDomain:
return SBaseQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
}
case rbacutils.ScopeProject:
return SBaseQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
ProjectId: ownerId.GetProjectId(),
}
}
return SBaseQuotaKeys{}
}
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
}
+244
View File
@@ -0,0 +1,244 @@
package quotas
import (
"testing"
)
func TestRelation(t *testing.T) {
keys := []SZonalCloudResourceKeys{
//Top :=
{},
// Domain1 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain1",
},
},
},
},
// Domain2 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain2",
},
},
},
},
// Project11 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain1",
ProjectId: "project1",
},
},
},
},
// Project12 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain1",
ProjectId: "project2",
},
},
},
},
// Project21 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain2",
ProjectId: "project1",
},
},
},
},
// Project11Region1 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain1",
ProjectId: "project1",
},
},
RegionId: "region1",
},
},
// Project11Region2 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain1",
ProjectId: "project1",
},
},
RegionId: "region2",
},
},
// Project11Aliyun :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain1",
ProjectId: "project1",
},
Provider: "Aliyun",
},
},
},
// Project11AliyunRegion1 :=
{
SRegionalCloudRegionKeys: SRegionalCloudRegionKeys{
SCloudResourceKeys: SCloudResourceKeys{
SBaseQuotaKeys: SBaseQuotaKeys{
DomainId: "domain1",
ProjectId: "project1",
},
Provider: "Aliyun",
},
RegionId: "region1",
},
},
}
want := [][]TQuotaKeysRelation{
{
QuotaKeysEqual,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
},
{
QuotaKeysBelong,
QuotaKeysEqual,
QuotaKeysExclude,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysExclude,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
},
{
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysEqual,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysContain,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
},
{
QuotaKeysBelong,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysEqual,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
QuotaKeysContain,
},
{
QuotaKeysBelong,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysEqual,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
},
{
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysEqual,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
},
{
QuotaKeysBelong,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysEqual,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysContain,
},
{
QuotaKeysBelong,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysEqual,
QuotaKeysExclude,
QuotaKeysExclude,
},
{
QuotaKeysBelong,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysEqual,
QuotaKeysContain,
},
{
QuotaKeysBelong,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysBelong,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysExclude,
QuotaKeysEqual,
},
}
for i := range keys {
for j := range keys {
rel := relation(keys[i], keys[j])
if rel != want[i][j] {
t.Errorf("%#v %#v got %s want %s", keys[i], keys[j], rel, want[i][j])
}
}
}
}
+128 -113
View File
@@ -16,39 +16,15 @@ package quotas
import (
"context"
"database/sql"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
const (
METADATA_KEY = "quota"
)
type IQuota interface {
FetchSystemQuota(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider)
FetchUsage(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string) error
Update(quota IQuota)
Add(quota IQuota)
Sub(quota IQuota)
Exceed(request IQuota, quota IQuota) error
IsEmpty() bool
ToJSON(prefix string) jsonutils.JSONObject
}
/*type SQuotaManager struct {
keyword string
quotaType reflect.Type
persistenStore IQuotaStore
pendingStore IQuotaStore
}*/
func (manager *SQuotaBaseManager) ResourceScope() rbacutils.TRbacScope {
return rbacutils.ScopeProject
}
@@ -62,121 +38,160 @@ func (manager *SQuotaBaseManager) newQuota() IQuota {
return model.(IQuota)
}
func (manager *SQuotaBaseManager) CancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, localUsage IQuota, cancelUsage IQuota) error {
lockman.LockClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
defer lockman.ReleaseClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
func (manager *SQuotaBaseManager) CancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, localUsage IQuota, cancelUsage IQuota) error {
LockQuota(ctx, localUsage)
defer ReleaseQuota(ctx, localUsage)
return manager._cancelPendingUsage(ctx, userCred, scope, ownerId, nil, localUsage, cancelUsage)
return manager._cancelPendingUsage(ctx, userCred, localUsage, cancelUsage)
}
func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, localUsage IQuota, cancelUsage IQuota) error {
quota := manager.newQuota()
err := manager.pendingStore.GetQuota(ctx, scope, ownerId, platform, quota)
func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, localUsage IQuota, cancelUsage IQuota) error {
pendingUsage := manager.newQuota()
err := manager.pendingStore.SubQuota(ctx, userCred, cancelUsage, pendingUsage)
if err != nil {
log.Errorf("%s", err)
return err
}
quota.Sub(cancelUsage)
err = manager.pendingStore.SetQuota(ctx, userCred, scope, ownerId, platform, quota)
if err != nil {
log.Errorf("%s", err)
return errors.Wrap(err, "manager.pendingStore.SubQuota")
}
//
if localUsage != nil {
localUsage.Sub(cancelUsage)
}
// update usage
manager.PostUsageJob(scope, ownerId, platform, nil, false, false)
return err
}
func (manager *SQuotaBaseManager) GetPendingUsage(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error {
return manager.pendingStore.GetQuota(ctx, scope, ownerId, nil, quota)
}
func (manager *SQuotaBaseManager) GetQuota(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error {
err := manager.getQuotaInternal(ctx, scope, ownerId, nil, quota)
if err != nil && err != sql.ErrNoRows {
return err
// update usages
quotas, err := manager.usageStore.GetParentQuotas(ctx, cancelUsage.GetKeys())
if err != nil {
return errors.Wrap(err, "manager.usageStore.GetParentQuotas")
}
for i := range quotas {
cancelUsage.SetKeys(quotas[i].GetKeys())
err := manager.usageStore.AddQuota(ctx, userCred, cancelUsage, quotas[i])
if err != nil {
return errors.Wrap(err, "manager.usageStore.AddQuota")
}
}
/*if quota.IsEmpty() && manager.autoCreate {
quota.FetchSystemQuota()
}*/
return nil
}
func (manager *SQuotaBaseManager) SetQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error {
lockman.LockClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
defer lockman.ReleaseClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
/*func (manager *SQuotaBaseManager) GetPendingUsage(ctx context.Context, keys SQuotaKeys, quota IQuota) error {
return manager.pendingStore.GetQuota(ctx, keys, quota)
}*/
return manager.setQuotaInternal(ctx, userCred, scope, ownerId, nil, quota)
}
func (manager *SQuotaBaseManager) DeleteQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string) error {
lockman.LockClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
defer lockman.ReleaseClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
return manager.deleteQuotaInternal(ctx, userCred, scope, ownerId, nil)
}
func (manager *SQuotaBaseManager) CheckQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, request IQuota) (IQuota, error) {
lockman.LockClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
defer lockman.ReleaseClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
return manager._checkQuota(ctx, userCred, scope, ownerId, nil, request)
}
func (manager *SQuotaBaseManager) _checkQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, request IQuota) (IQuota, error) {
stored := manager.newQuota()
err := manager.GetQuota(ctx, scope, ownerId, platform, stored)
func (manager *SQuotaBaseManager) GetPendingUsages(ctx context.Context, keys IQuotaKeys) ([]IQuota, error) {
quotas, err := manager.pendingStore.GetChildrenQuotas(ctx, keys)
if err != nil {
log.Errorf("fail to get quota %s", err)
return nil, err
return nil, errors.Wrap(err, "manager.pendingStore.GetChildrenQuotas")
}
ret := make([]IQuota, 0)
for _, q := range quotas {
if !q.IsEmpty() {
ret = append(ret, q)
}
}
if len(ret) == 0 {
return nil, nil
}
return ret, nil
}
func (manager *SQuotaBaseManager) GetQuota(ctx context.Context, keys IQuotaKeys, quota IQuota) error {
return manager.getQuotaByKeys(ctx, keys, quota)
}
func (manager *SQuotaBaseManager) GetChildrenQuotas(ctx context.Context, keys IQuotaKeys) ([]IQuota, error) {
return manager.getQuotasInternal(ctx, keys, false)
}
func (manager *SQuotaBaseManager) GetParentQuotas(ctx context.Context, keys IQuotaKeys) ([]IQuota, error) {
return manager.getQuotasInternal(ctx, keys, true)
}
func (manager *SQuotaBaseManager) SetQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error {
LockQuota(ctx, quota)
defer ReleaseQuota(ctx, quota)
return manager.setQuotaInternal(ctx, userCred, quota)
}
func (manager *SQuotaBaseManager) AddQuota(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota, target IQuota) error {
LockQuota(ctx, diff)
defer ReleaseQuota(ctx, diff)
return manager.addQuotaInternal(ctx, userCred, diff, target)
}
func (manager *SQuotaBaseManager) SubQuota(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota, target IQuota) error {
LockQuota(ctx, diff)
defer ReleaseQuota(ctx, diff)
return manager.subQuotaInternal(ctx, userCred, diff, target)
}
func (manager *SQuotaBaseManager) DeleteQuota(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error {
LockQuotaKeys(ctx, keys)
defer ReleaseQuotaKeys(ctx, keys)
return manager.deleteQuotaByKeys(ctx, userCred, keys)
}
func (manager *SQuotaBaseManager) DeleteAllQuotas(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error {
LockQuotaKeys(ctx, keys)
defer ReleaseQuotaKeys(ctx, keys)
return manager.deleteAllQuotas(ctx, userCred, keys)
}
func (manager *SQuotaBaseManager) CheckQuota(ctx context.Context, request IQuota) error {
LockQuota(ctx, request)
defer ReleaseQuota(ctx, request)
return manager._checkQuota(ctx, request)
}
func (manager *SQuotaBaseManager) __checkQuota(ctx context.Context, quota IQuota, request IQuota) error {
used := manager.newQuota()
err = used.FetchUsage(ctx, scope, ownerId, platform)
err := manager.usageStore.GetQuota(ctx, quota.GetKeys(), used)
if err != nil {
log.Errorf("fail to get quota usage %s", err)
return nil, err
return errors.Wrap(err, "manager.usageStore.GetQuotaByKeys")
}
pending := manager.newQuota()
err = manager.GetPendingUsage(ctx, scope, ownerId, platform, pending)
pendings, err := manager.pendingStore.GetChildrenQuotas(ctx, quota.GetKeys())
if err != nil {
log.Errorf("fail to get pending usage %s", err)
return nil, err
return errors.Wrap(err, "manager.pendingStore.GetChildrenQuotas")
}
used.Add(pending)
used.Add(request)
err = used.Exceed(request, stored)
if err != nil {
return nil, err
for i := range pendings {
used.Add(pendings[i])
}
return used, nil
return used.Exceed(quota, request)
}
func (manager *SQuotaBaseManager) CheckSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error {
lockman.LockClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
defer lockman.ReleaseClass(ctx, manager, mcclient.OwnerIdString(ownerId, scope))
return manager._checkSetPendingQuota(ctx, userCred, scope, ownerId, nil, quota)
func (manager *SQuotaBaseManager) _checkQuota(ctx context.Context, request IQuota) error {
quotas, err := manager.GetParentQuotas(ctx, request.GetKeys())
if err != nil {
return errors.Wrap(err, "manager.getMatchedQuotas")
}
for i := range quotas {
err := manager.__checkQuota(ctx, quotas[i], request)
if err != nil {
return errors.Wrap(err, "manager.__checkQuota")
}
}
return nil
}
func (manager *SQuotaBaseManager) _checkSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error {
_, err := manager._checkQuota(ctx, userCred, scope, ownerId, platform, quota)
func (manager *SQuotaBaseManager) CheckSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error {
LockQuota(ctx, quota)
defer ReleaseQuota(ctx, quota)
return manager._checkSetPendingQuota(ctx, userCred, quota, true)
}
func (manager *SQuotaBaseManager) _checkSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota, setPending bool) error {
err := manager._checkQuota(ctx, quota)
if err != nil {
return err
}
pending := manager.newQuota()
err = manager.pendingStore.GetQuota(ctx, scope, ownerId, platform, pending)
if err != nil {
log.Errorf("GetQuota fail %s", err)
return err
if setPending {
target := manager.newQuota()
err = manager.pendingStore.AddQuota(ctx, userCred, quota, target)
if err != nil {
return errors.Wrap(err, "manager.pendingStore.AddQuota")
}
}
pending.Add(quota)
return manager.pendingStore.SetQuota(ctx, userCred, scope, ownerId, platform, pending)
return nil
}
+3 -71
View File
@@ -16,7 +16,6 @@ package quotas
import (
"context"
"strings"
"yunion.io/x/jsonutils"
@@ -25,58 +24,9 @@ import (
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type IQuotaStore interface {
GetQuota(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error
SetQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, quota IQuota) error
DeleteQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string) error
}
type SMemoryQuotaStore struct {
store map[string]jsonutils.JSONObject
}
func NewMemoryQuotaStore() *SMemoryQuotaStore {
return &SMemoryQuotaStore{
store: make(map[string]jsonutils.JSONObject),
}
}
func getMemoryStoreKey(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, name []string) string {
keys := make([]string, 0)
keys = append(keys, ownerId.GetProjectDomainId())
if scope == rbacutils.ScopeProject {
keys = append(keys, ownerId.GetProjectId())
}
if len(name) > 0 {
keys = append(keys, name...)
}
return strings.Join(keys, nameSeparator)
}
func (self *SMemoryQuotaStore) GetQuota(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, name []string, quota IQuota) error {
key := getMemoryStoreKey(scope, ownerId, name)
json, ok := self.store[key]
if ok {
return json.Unmarshal(quota)
}
return nil
}
func (self *SMemoryQuotaStore) SetQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, name []string, quota IQuota) error {
key := getMemoryStoreKey(scope, ownerId, name)
if quota.IsEmpty() {
delete(self.store, key)
} else {
self.store[key] = jsonutils.Marshal(quota)
}
return nil
}
func (self *SMemoryQuotaStore) DeleteQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, name []string) error {
key := getMemoryStoreKey(scope, ownerId, name)
delete(self.store, key)
return nil
}
const (
METADATA_KEY = "quota"
)
type SDBQuotaStore struct {
}
@@ -106,21 +56,3 @@ func (store *SDBQuotaStore) GetQuota(ctx context.Context, scope rbacutils.TRbacS
}
return nil
}
/*func (store *SDBQuotaStore) SetQuota(ctx context.Context, userCred mcclient.TokenCredential, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, quota IQuota) error {
var tenant *db.STenant
var err error
switch scope {
case rbacutils.ScopeDomain:
tenant, err = db.TenantCacheManager.FetchDomainById(ctx, ownerId.GetProjectDomainId())
default:
tenant, err = db.TenantCacheManager.FetchTenantById(ctx, ownerId.GetProjectId())
}
if err != nil {
return err
}
quotaJson := jsonutils.Marshal(quota)
return tenant.SetMetadata(ctx, METADATA_KEY, quotaJson, userCred)
}*/
+68 -75
View File
@@ -17,20 +17,14 @@ package quotas
import (
"context"
"database/sql"
"strings"
"sync"
"strings"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
var (
@@ -41,13 +35,6 @@ var (
usageDirtyMapLock = &sync.Mutex{}
)
type sUsageCalculateJob struct {
manager *SQuotaBaseManager
scope rbacutils.TRbacScope
ownerId mcclient.IIdentityProvider
platform []string
}
func setDirty(key string) {
usageDirtyMapLock.Lock()
defer usageDirtyMapLock.Unlock()
@@ -72,8 +59,8 @@ func isDirty(key string) bool {
return false
}
func (manager *SQuotaBaseManager) PostUsageJob(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, platform []string, usageChan chan IQuota, cleanEmpty bool, realTime bool) {
key := getMemoryStoreKey(scope, ownerId, platform)
func (manager *SQuotaBaseManager) PostUsageJob(keys IQuotaKeys, usageChan chan IQuota, realTime bool) {
key := QuotaKeyString(keys)
setDirty(key)
var worker *appsrv.SWorkerManager
@@ -92,53 +79,13 @@ func (manager *SQuotaBaseManager) PostUsageJob(scope rbacutils.TRbacScope, owner
clearDirty(key)
usage := manager.newQuota()
err := usage.FetchUsage(ctx, scope, ownerId, platform)
usage.SetKeys(keys)
err := usage.FetchUsage(ctx)
if err != nil {
return
}
var save bool
if usage.IsEmpty() && cleanEmpty {
// check existence of project
s := auth.GetAdminSession(ctx, consts.GetRegion(), "v1")
if scope == rbacutils.ScopeDomain {
domain, err := modules.Domains.GetById(s, ownerId.GetProjectDomainId(), nil)
if err == nil {
// update cache
domainId, _ := domain.GetString("id")
domainName, _ := domain.GetString("name")
db.TenantCacheManager.Save(ctx, domainId, domainName, identityapi.KeystoneDomainRoot, identityapi.KeystoneDomainRoot)
save = true
} else if httputils.ErrorCode(err) == 404 {
// remove cache and quota
db.TenantCacheManager.Delete(ctx, ownerId.GetProjectDomainId())
save = false
}
} else {
proj, err := modules.Projects.GetById(s, ownerId.GetProjectId(), nil)
if err == nil {
// update cache
projId, _ := proj.GetString("id")
projName, _ := proj.GetString("name")
projDomainId, _ := proj.GetString("domain_id")
projDomain, _ := proj.GetString("project_domain")
db.TenantCacheManager.Save(ctx, projId, projName, projDomainId, projDomain)
save = true
} else if httputils.ErrorCode(err) == 404 {
// remove cache and quota
db.TenantCacheManager.Delete(ctx, ownerId.GetProjectId())
save = false
}
}
} else {
save = true
}
if save {
manager.usageStore.SetQuota(ctx, nil, scope, ownerId, platform, usage)
} else {
manager.usageStore.DeleteQuota(ctx, nil, scope, ownerId, platform)
manager.DeleteQuota(ctx, nil, scope, ownerId, platform)
}
manager.usageStore.SetQuota(ctx, nil, usage)
clearDirty(key)
@@ -150,9 +97,15 @@ func (manager *SQuotaBaseManager) PostUsageJob(scope rbacutils.TRbacScope, owner
func (manager *SQuotaBaseManager) CalculateQuotaUsages(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
log.Infof("CalculateQuotaUsages")
rows, err := manager.Query("domain_id", "tenant_id", "platform").IsNullOrEmpty("platform").Rows()
quota := manager.newQuota()
keys := quota.GetKeys()
keyFields := keys.Fields()
q := manager.Query(keyFields...)
keyList := make([]IQuotaKeys, 0)
rows, err := q.Rows()
if err != nil {
if err != sql.ErrNoRows {
if errors.Cause(err) != sql.ErrNoRows {
log.Errorf("query quotas fail %s", err)
}
return
@@ -160,22 +113,62 @@ func (manager *SQuotaBaseManager) CalculateQuotaUsages(ctx context.Context, user
defer rows.Close()
for rows.Next() {
var domainId, projectId, platform string
err := rows.Scan(&domainId, &projectId, &platform)
quota := manager.newQuota()
err = q.Row2Struct(rows, quota)
if err != nil {
log.Errorf("scan domain_id, project_id, platform error %s", err)
log.Errorf("Row2Struct fail %s", err)
return
}
scope := rbacutils.ScopeProject
owner := db.SOwnerId{
DomainId: domainId,
ProjectId: projectId,
keyList = append(keyList, quota.GetKeys())
}
var fields []string
idNameMap, _ := manager.keyList2IdNameMap(ctx, keyList)
for _, keys := range keyList {
if idNameMap != nil {
// no error, do check
if len(fields) == 0 {
fields = keys.Fields()
}
values := keys.Values()
for i := range fields {
if strings.HasSuffix(fields[i], "_id") && len(values[i]) > 0 && len(idNameMap[fields[i]][values[i]]) == 0 {
manager.DeleteAllQuotas(ctx, userCred, keys)
manager.pendingStore.DeleteAllQuotas(ctx, userCred, keys)
manager.usageStore.DeleteAllQuotas(ctx, userCred, keys)
continue
}
}
}
if len(projectId) == 0 {
scope = rbacutils.ScopeDomain
}
platforms := strings.Split(platform, nameSeparator)
// log.Debugf("PostUsageJob %s %s %s", scope, owner, platforms)
manager.PostUsageJob(scope, &owner, platforms, nil, true, false)
manager.PostUsageJob(keys, nil, false)
}
}
func (manager *SQuotaBaseManager) keyList2IdNameMap(ctx context.Context, keyList []IQuotaKeys) (map[string]map[string]string, error) {
idMap := make(map[string]map[string]string)
var fields []string
for _, keys := range keyList {
if len(fields) == 0 {
fields = keys.Fields()
}
values := keys.Values()
for i := range fields {
if strings.HasSuffix(fields[i], "_id") && len(values[i]) > 0 {
if _, ok := idMap[fields[i]]; !ok {
idMap[fields[i]] = make(map[string]string)
}
if _, ok := idMap[fields[i]][values[i]]; !ok {
idMap[fields[i]][values[i]] = ""
}
}
}
}
ret, err := manager.GetIQuotaManager().FetchIdNames(ctx, idMap)
if err != nil {
return nil, err
}else {
return ret, nil
}
}
+12
View File
@@ -18,9 +18,12 @@ import (
"context"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/mcclient"
)
@@ -108,3 +111,12 @@ func (model *SResourceBase) MarkUnDelete() error {
func (model *SResourceBase) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return DeleteModel(ctx, userCred, model.GetIResourceModel())
}
func (manager *SResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.ResourceBaseCreateInput) (apis.ResourceBaseCreateInput, error) {
var err error
input.ModelBaseCreateInput, err = manager.SModelBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.ModelBaseCreateInput)
if err != nil {
return input, errors.Wrap(err, "SModelBaseManager.ValidateCreateData")
}
return input, nil
}
+10
View File
@@ -19,6 +19,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
@@ -312,3 +313,12 @@ func (model *SSharableVirtualResourceBase) GetExtraDetails(ctx context.Context,
}
return model.getMoreDetails(ctx, userCred, query, extra), nil
}
func (manager *SSharableVirtualResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.SharableVirtualResourceCreateInput) (apis.SharableVirtualResourceCreateInput, error) {
var err error
input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
if err != nil {
return input, errors.Wrap(err, "manager.VirtualResourceBaseManager.ValidateCreateData")
}
return input, nil
}
+9
View File
@@ -470,6 +470,15 @@ func (model *SStandaloneResourceBase) AppendDescription(userCred mcclient.TokenC
return nil
}
func (manager *SStandaloneResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.StandaloneResourceCreateInput) (apis.StandaloneResourceCreateInput, error) {
var err error
input.ResourceBaseCreateInput, err = manager.SResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.ResourceBaseCreateInput)
if err != nil {
return input, errors.Wrap(err, "SResourceBaseManager.ValidateCreateData")
}
return input, nil
}
/*
func (model SStandaloneResourceBase) GetExternalId() string {
return model.ExternalId
+11
View File
@@ -19,8 +19,10 @@ import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
@@ -89,3 +91,12 @@ func (model *SStatusStandaloneResourceBase) GetDetailsStatus(ctx context.Context
ret.Add(jsonutils.NewString(model.Status), "status")
return ret, nil
}
func (manager *SStatusStandaloneResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.StatusStandaloneResourceCreateInput) (apis.StatusStandaloneResourceCreateInput, error) {
var err error
input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput)
if err != nil {
return input, errors.Wrap(err, "SStandaloneResourceBaseManager.ValidateCreateData")
}
return input, nil
}
+2 -2
View File
@@ -39,6 +39,6 @@ type ITask interface {
SetStageComplete(ctx context.Context, data *jsonutils.JSONDict)
SetStageFailed(ctx context.Context, reason string)
GetPendingUsage(quota quotas.IQuota) error
ClearPendingUsage() error
GetPendingUsage(quota quotas.IQuota, index int) error
ClearPendingUsage(index int) error
}
+64 -21
View File
@@ -21,11 +21,13 @@ import (
"net/http"
"reflect"
"runtime/debug"
"strconv"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/pkg/util/stringutils"
"yunion.io/x/pkg/util/timeutils"
@@ -178,12 +180,23 @@ func (self *STask) GetName() string {
return self.TaskName
}
func fetchTaskParams(ctx context.Context, taskName string, taskData *jsonutils.JSONDict,
parentTaskId string, parentTaskNotifyUrl string,
pendingUsage quotas.IQuota) *jsonutils.JSONDict {
func fetchTaskParams(
ctx context.Context,
taskName string,
taskData *jsonutils.JSONDict,
parentTaskId string,
parentTaskNotifyUrl string,
pendingUsages []quotas.IQuota,
) *jsonutils.JSONDict {
var data *jsonutils.JSONDict
if taskData != nil {
data = taskData.CopyExcludes(PARENT_TASK_ID_KEY, PARENT_TASK_NOTIFY_KEY, PENDING_USAGE_KEY)
excludeKeys := []string{
PARENT_TASK_ID_KEY, PARENT_TASK_NOTIFY_KEY, PENDING_USAGE_KEY,
}
for i := 1; taskData.Contains(pendingUsageKey(i)); i += 1 {
excludeKeys = append(excludeKeys, pendingUsageKey(i))
}
data = taskData.CopyExcludes(excludeKeys...)
} else {
data = jsonutils.NewDict()
}
@@ -210,16 +223,29 @@ func fetchTaskParams(ctx context.Context, taskName string, taskData *jsonutils.J
}
}
}
if pendingUsage != nil {
data.Add(jsonutils.Marshal(pendingUsage), PENDING_USAGE_KEY)
if len(pendingUsages) > 0 {
for i := range pendingUsages {
pendingUsage := pendingUsages[i]
if gotypes.IsNil(pendingUsage) || pendingUsage.IsEmpty() {
continue
}
key := pendingUsageKey(i)
data.Add(jsonutils.Marshal(pendingUsage), key)
}
}
return data
}
func (manager *STaskManager) NewTask(ctx context.Context, taskName string, obj db.IStandaloneModel,
userCred mcclient.TokenCredential, taskData *jsonutils.JSONDict,
parentTaskId string, parentTaskNotifyUrl string,
pendingUsage quotas.IQuota) (*STask, error) {
func (manager *STaskManager) NewTask(
ctx context.Context,
taskName string,
obj db.IStandaloneModel,
userCred mcclient.TokenCredential,
taskData *jsonutils.JSONDict,
parentTaskId string,
parentTaskNotifyUrl string,
pendingUsage ...quotas.IQuota,
) (*STask, error) {
if !isTaskExist(taskName) {
return nil, fmt.Errorf("task %s not found", taskName)
}
@@ -253,10 +279,16 @@ func (manager *STaskManager) NewTask(ctx context.Context, taskName string, obj d
return &task, nil
}
func (manager *STaskManager) NewParallelTask(ctx context.Context, taskName string, objs []db.IStandaloneModel,
userCred mcclient.TokenCredential, taskData *jsonutils.JSONDict,
parentTaskId string, parentTaskNotifyUrl string,
pendingUsage quotas.IQuota) (*STask, error) {
func (manager *STaskManager) NewParallelTask(
ctx context.Context,
taskName string,
objs []db.IStandaloneModel,
userCred mcclient.TokenCredential,
taskData *jsonutils.JSONDict,
parentTaskId string,
parentTaskNotifyUrl string,
pendingUsage ...quotas.IQuota,
) (*STask, error) {
if !isTaskExist(taskName) {
return nil, fmt.Errorf("task %s not found", taskName)
}
@@ -675,18 +707,28 @@ func (self *STask) IsCurrentStageComplete() bool {
}
}
func (self *STask) GetPendingUsage(quota quotas.IQuota) error {
quotaJson, err := self.Params.Get(PENDING_USAGE_KEY)
func (self *STask) GetPendingUsage(quota quotas.IQuota, index int) error {
key := pendingUsageKey(index)
quotaJson, err := self.Params.Get(key)
if err != nil {
return err
}
return quotaJson.Unmarshal(quota)
}
func (self *STask) SetPendingUsage(quota quotas.IQuota) error {
func pendingUsageKey(index int) string {
key := PENDING_USAGE_KEY
if index > 0 {
key += "." + strconv.FormatInt(int64(index), 10)
}
return key
}
func (self *STask) SetPendingUsage(quota quotas.IQuota, index int) error {
_, err := db.Update(self, func() error {
params := self.Params.CopyExcludes(PENDING_USAGE_KEY)
params.Add(jsonutils.Marshal(quota), PENDING_USAGE_KEY)
key := pendingUsageKey(index)
params := self.Params.CopyExcludes(key)
params.Add(jsonutils.Marshal(quota), key)
self.Params = params
return nil
})
@@ -696,9 +738,10 @@ func (self *STask) SetPendingUsage(quota quotas.IQuota) error {
return err
}
func (self *STask) ClearPendingUsage() error {
func (self *STask) ClearPendingUsage(index int) error {
_, err := db.Update(self, func() error {
params := self.Params.CopyExcludes(PENDING_USAGE_KEY)
key := pendingUsageKey(index)
params := self.Params.CopyExcludes(key)
self.Params = params
return nil
})
+10 -5
View File
@@ -21,6 +21,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
@@ -163,12 +164,16 @@ func (manager *SVirtualResourceBaseManager) FetchByIdOrName(userCred mcclient.II
return FetchByIdOrName(manager, userCred, idStr)
}
func (manager *SVirtualResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
isSystem, err := data.Bool("is_system")
if err == nil && isSystem && !IsAdminAllowCreate(userCred, manager) {
return nil, httperrors.NewNotSufficientPrivilegeError("non-admin user not allowed to create system object")
func (manager *SVirtualResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.VirtualResourceCreateInput) (apis.VirtualResourceCreateInput, error) {
var err error
if input.IsSystem != nil && *input.IsSystem && !IsAdminAllowCreate(userCred, manager) {
return input, httperrors.NewNotSufficientPrivilegeError("non-admin user not allowed to create system object")
}
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input.StatusStandaloneResourceCreateInput, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput)
if err != nil {
return input, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ValidateCreateData")
}
return input, nil
}
func (model *SVirtualResourceBase) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
+8
View File
@@ -36,6 +36,12 @@ import (
"yunion.io/x/onecloud/pkg/util/atexit"
)
const (
DefaultQuotaUnlimit = "unlimit"
DefaultQuotaZero = "zero"
DefaultQuotaDefault = "default"
)
type BaseOptions struct {
Region string `help:"Region name or ID" alias:"auth-region"`
@@ -70,6 +76,8 @@ type BaseOptions struct {
IsSlaveNode bool `help:"Region service slave node"`
CronJobWorkerCount int `help:"Cron job worker count" default:"4"`
DefaultQuotaValue string `help:"default quota value" choices:"unlimit|zero|default"`
CalculateQuotaUsageIntervalSeconds int `help:"interval to calculate quota usages, default 30 minutes" default:"900"`
NonDefaultDomainProjects bool `help:"allow projects in non-default domains" default:"false"`
+4
View File
@@ -41,6 +41,10 @@ func (region *SFakeOnPremiseRegion) GetStatus() string {
return "available"
}
func (region *SFakeOnPremiseRegion) GetCloudEnv() string {
return ""
}
func (region *SFakeOnPremiseRegion) Refresh() error {
return nil
}
+1
View File
@@ -132,6 +132,7 @@ type ICloudRegion interface {
GetIElasticcacheById(id string) (ICloudElasticcache, error)
CreateIElasticcaches(ec *SCloudElasticCacheInput) (ICloudElasticcache, error)
GetCloudEnv() string
GetProvider() string
GetICloudEvents(start time.Time, end time.Time, withReadEvent bool) ([]ICloudEvent, error) //获取公有云操作日志接口
+9 -5
View File
@@ -21,11 +21,13 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SAliyunGuestDriver struct {
@@ -45,11 +47,13 @@ func (self *SAliyunGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_ALIYUN
}
func (self *SAliyunGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_ALIYUN,
}
func (self *SAliyunGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_ALIYUN
// ignore brand
return keys
}
func (self *SAliyunGuestDriver) GetDefaultSysDiskBackend() string {
+9 -5
View File
@@ -26,11 +26,13 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SAwsGuestDriver struct {
@@ -92,11 +94,13 @@ func (self *SAwsGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_AWS
}
func (self *SAwsGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_AWS,
}
func (self *SAwsGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_AWS
// ignore brand
return keys
}
func (self *SAwsGuestDriver) GetDefaultSysDiskBackend() string {
+9 -5
View File
@@ -22,11 +22,13 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SAzureGuestDriver struct {
@@ -46,11 +48,13 @@ func (self *SAzureGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_AZURE
}
func (self *SAzureGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_AZURE,
}
func (self *SAzureGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_AZURE
// ignore brand
return keys
}
func (self *SAzureGuestDriver) GetDefaultSysDiskBackend() string {
+9 -6
View File
@@ -36,6 +36,7 @@ import (
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SBaremetalGuestDriver struct {
@@ -55,12 +56,14 @@ func (self *SBaremetalGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_ONECLOUD
}
func (self *SBaremetalGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_ON_PREMISE,
api.CLOUD_PROVIDER_ONECLOUD,
api.HYPERVISOR_BAREMETAL,
}
func (self *SBaremetalGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_ON_PREMISE
keys.Provider = api.CLOUD_PROVIDER_ONECLOUD
// ignore brand
keys.Hypervisor = api.HYPERVISOR_BAREMETAL
return keys
}
func (self *SBaremetalGuestDriver) GetDefaultSysDiskBackend() string {
+10 -6
View File
@@ -22,12 +22,14 @@ import (
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
var (
@@ -55,12 +57,14 @@ func (self *SContainerDriver) GetProvider() string {
return api.CLOUD_PROVIDER_ONECLOUD
}
func (self *SContainerDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_ON_PREMISE,
api.CLOUD_PROVIDER_ONECLOUD,
api.HYPERVISOR_CONTAINER,
}
// for backward compatibility, deprecated driver
func (self *SContainerDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_ON_PREMISE
keys.Provider = api.CLOUD_PROVIDER_ONECLOUD
keys.Hypervisor = api.HYPERVISOR_CONTAINER
return keys
}
func (self *SContainerDriver) GetDefaultSysDiskBackend() string {
+10 -5
View File
@@ -22,6 +22,9 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
)
type SCtyunGuestDriver struct {
@@ -36,11 +39,13 @@ func (self *SCtyunGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_CTYUN
}
func (self *SCtyunGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_CTYUN,
}
func (self *SCtyunGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_CTYUN
// ignore brand
return keys
}
func (self *SCtyunGuestDriver) GetDefaultSysDiskBackend() string {
+10 -6
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/options"
@@ -33,6 +34,7 @@ import (
"yunion.io/x/onecloud/pkg/multicloud/esxi"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SESXiGuestDriver struct {
@@ -58,12 +60,14 @@ func (self *SESXiGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_VMWARE
}
func (self *SESXiGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_ON_PREMISE,
api.CLOUD_PROVIDER_VMWARE,
api.HYPERVISOR_ESXI,
}
func (self *SESXiGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_ON_PREMISE
keys.Provider = api.CLOUD_PROVIDER_VMWARE
// ignore brand
// ignore hypervisor keys.Hypervisor = api.HYPERVISOR_ESXI
return keys
}
func (self *SESXiGuestDriver) GetDefaultSysDiskBackend() string {
+10 -5
View File
@@ -16,7 +16,10 @@ package guestdrivers
import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SGoogleGuestDriver struct {
@@ -28,11 +31,13 @@ func init() {
models.RegisterGuestDriver(&driver)
}
func (self *SGoogleGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_GOOGLE,
}
func (self *SGoogleGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_GOOGLE
// ignore brand
return keys
}
func (self *SGoogleGuestDriver) GetHypervisor() string {
+10 -5
View File
@@ -20,9 +20,12 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SHuaweiGuestDriver struct {
@@ -42,11 +45,13 @@ func (self *SHuaweiGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_HUAWEI
}
func (self *SHuaweiGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_HUAWEI,
}
func (self *SHuaweiGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_HUAWEI
// ignore brand
return keys
}
func (self *SHuaweiGuestDriver) GetDefaultSysDiskBackend() string {
+10 -6
View File
@@ -27,12 +27,14 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SKVMGuestDriver struct {
@@ -52,12 +54,14 @@ func (self *SKVMGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_ONECLOUD
}
func (self *SKVMGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_ON_PREMISE,
api.CLOUD_PROVIDER_ONECLOUD,
api.HYPERVISOR_KVM,
}
func (self *SKVMGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_ON_PREMISE
keys.Provider = api.CLOUD_PROVIDER_ONECLOUD
// ignore brand keys.Brand = brand
keys.Hypervisor = api.HYPERVISOR_KVM
return keys
}
func (self *SKVMGuestDriver) GetDefaultSysDiskBackend() string {
+9 -5
View File
@@ -22,12 +22,14 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SOpenStackGuestDriver struct {
@@ -55,11 +57,13 @@ func (self *SOpenStackGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_OPENSTACK
}
func (self *SOpenStackGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PRIVATE_CLOUD,
api.CLOUD_PROVIDER_OPENSTACK,
}
func (self *SOpenStackGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PRIVATE_CLOUD
keys.Provider = api.CLOUD_PROVIDER_OPENSTACK
keys.Brand = brand
return keys
}
func (self *SOpenStackGuestDriver) IsSupportEip() bool {
+10 -5
View File
@@ -21,11 +21,13 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SQcloudGuestDriver struct {
@@ -45,11 +47,14 @@ func (self *SQcloudGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_QCLOUD
}
func (self *SQcloudGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_QCLOUD,
}
func (self *SQcloudGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_QCLOUD
// ignore brand keys.Brand = brand
// ignore hypervisor
return keys
}
func (self *SQcloudGuestDriver) GetDefaultSysDiskBackend() string {
+11 -5
View File
@@ -20,8 +20,11 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SUCloudGuestDriver struct {
@@ -36,11 +39,14 @@ func (self *SUCloudGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_UCLOUD
}
func (self *SUCloudGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PUBLIC_CLOUD,
api.CLOUD_PROVIDER_UCLOUD,
}
func (self *SUCloudGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_UCLOUD
// ignore brand
// ignore hypervisor
return keys
}
func (self *SUCloudGuestDriver) GetDefaultSysDiskBackend() string {
+10 -5
View File
@@ -22,11 +22,13 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SZStackGuestDriver struct {
@@ -54,11 +56,14 @@ func (self *SZStackGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_ZSTACK
}
func (self *SZStackGuestDriver) GetQuotaPlatformID() []string {
return []string{
api.CLOUD_ENV_PRIVATE_CLOUD,
api.CLOUD_PROVIDER_ZSTACK,
}
func (self *SZStackGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PRIVATE_CLOUD
keys.Provider = api.CLOUD_PROVIDER_ZSTACK
keys.Brand = brand
// ignore hypervisor
return keys
}
func (self *SZStackGuestDriver) GetDefaultSysDiskBackend() string {
+7 -6
View File
@@ -75,13 +75,14 @@ func (self *SBaseHostDriver) PrepareConvert(host *models.SHost, image, raid stri
ServerConfigs: &api.ServerConfigs{
PreferHost: host.Id,
},
Description: "Baremetal convered Hypervisor",
VcpuCount: int(host.CpuCount),
VmemSize: host.MemSize,
AutoStart: true,
IsSystem: true,
Baremetal: true,
VcpuCount: int(host.CpuCount),
VmemSize: host.MemSize,
AutoStart: true,
Baremetal: true,
}
params.Description = "Baremetal convered Hypervisor"
isSystem := true
params.IsSystem = &isSystem
name, err := data.GetString("name")
if err == nil {
params.Name = name
+12 -1
View File
@@ -23,6 +23,7 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -118,7 +119,17 @@ func (manager *SBaremetalagentManager) ValidateCreateData(ctx context.Context, u
if count > 0 {
return nil, httperrors.NewDuplicateResourceError("Duplicate manager_uri %s", mangerUri)
}
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (self *SBaremetalagent) AllowPerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
+74 -76
View File
@@ -34,6 +34,7 @@ import (
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -391,9 +392,10 @@ func (manager *SBucketManager) ValidateCreateData(
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
query jsonutils.JSONObject,
input *api.BucketCreateInput,
) (*jsonutils.JSONDict, error) {
input api.BucketCreateInput,
) (api.BucketCreateInput, error) {
data := input.JSON(input)
cloudRegionV := validators.NewModelIdOrNameValidator("cloudregion", CloudregionManager.Keyword(), ownerId)
managerV := validators.NewModelIdOrNameValidator("manager", CloudproviderManager.Keyword(), ownerId)
for _, v := range []validators.IValidator{
@@ -402,26 +404,50 @@ func (manager *SBucketManager) ValidateCreateData(
} {
err := v.Validate(data)
if err != nil {
return nil, err
return input, err
}
}
nameStr, _ := data.GetString("name")
if len(nameStr) == 0 {
return nil, httperrors.NewInputParameterError("missing name")
}
err := isValidBucketName(nameStr)
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid bucket name: %s", err)
return input, httperrors.NewInternalServerError("unmarshal input fail %s", err)
}
cloudprovider := managerV.Model.(*SCloudprovider)
quotaPlatformId := cloudprovider.GetQuotaPlatformID()
pendingUsage := SQuota{Bucket: 1}
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatformId, &pendingUsage); err != nil {
return nil, httperrors.NewOutOfQuotaError("%s", err)
if len(input.Name) == 0 {
return input, httperrors.NewInputParameterError("missing name")
}
err = isValidBucketName(input.Name)
if err != nil {
return input, httperrors.NewInputParameterError("invalid bucket name %s: %s", input.Name, err)
}
return manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
quotaKeys := fetchRegionalQuotaKeys(rbacutils.ScopeProject, ownerId,
cloudRegionV.Model.(*SCloudregion),
managerV.Model.(*SCloudprovider))
pendingUsage := SRegionQuota{Bucket: 1}
pendingUsage.SetKeys(quotaKeys)
if err := RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
return input, httperrors.NewOutOfQuotaError("%s", err)
}
input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
if err != nil {
return input, err
}
return input, nil
}
func (bucket *SBucket) GetQuotaKeys() (quotas.IQuotaKeys, error) {
region, _ := bucket.GetRegion()
if region == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid region")
}
return fetchRegionalQuotaKeys(
rbacutils.ScopeProject,
bucket.GetOwnerId(),
region,
bucket.GetCloudprovider(),
), nil
}
func (bucket *SBucket) PostCreate(
@@ -431,12 +457,16 @@ func (bucket *SBucket) PostCreate(
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) {
cloudprovider := bucket.GetCloudprovider()
quotaPlatformId := cloudprovider.GetQuotaPlatformID()
pendingUsage := SQuota{Bucket: 1}
err := QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatformId, &pendingUsage, &pendingUsage)
pendingUsage := SRegionQuota{Bucket: 1}
keys, err := bucket.GetQuotaKeys()
if err != nil {
log.Errorf("CancelPendingUsage error %s", err)
log.Errorf("bucket.GetQuotaKeys fail %s", err)
} else {
pendingUsage.SetKeys(keys)
err = RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
if err != nil {
log.Errorf("CancelPendingUsage error %s", err)
}
}
bucket.SetStatus(userCred, api.BUCKET_STATUS_START_CREATE, "PostCreate")
@@ -725,13 +755,14 @@ func (bucket *SBucket) PerformMakedir(
if bucket.ObjectCntLimit > 0 && bucket.ObjectCntLimit < bucket.ObjectCnt+1 {
return nil, httperrors.NewOutOfQuotaError("object count limit exceeds")
}
manager := bucket.GetCloudprovider()
quotaPlatformId := manager.GetQuotaPlatformID()
pendingUsage := SQuota{ObjectGB: 0, ObjectCnt: 1}
if !pendingUsage.IsEmpty() {
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, bucket.GetOwnerId(), quotaPlatformId, &pendingUsage); err != nil {
return nil, httperrors.NewOutOfQuotaError("%s", err)
}
pendingUsage := SRegionQuota{ObjectGB: 0, ObjectCnt: 1}
keys, err := bucket.GetQuotaKeys()
if err != nil {
return nil, httperrors.NewInternalServerError("bucket.GetQuotaKeys %s", err)
}
pendingUsage.SetKeys(keys)
if err := RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
return nil, httperrors.NewOutOfQuotaError("%s", err)
}
err = cloudprovider.Makedir(ctx, iBucket, key+"/")
@@ -744,9 +775,7 @@ func (bucket *SBucket) PerformMakedir(
bucket.syncWithCloudBucket(ctx, userCred, iBucket, nil, true)
if !pendingUsage.IsEmpty() {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, bucket.GetOwnerId(), quotaPlatformId, &pendingUsage, &pendingUsage)
}
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
return nil, nil
}
@@ -894,11 +923,14 @@ func (bucket *SBucket) PerformUpload(
return nil, httperrors.NewOutOfQuotaError("object count limit exceeds")
}
manager := bucket.GetCloudprovider()
quotaPlatformId := manager.GetQuotaPlatformID()
pendingUsage := SQuota{ObjectGB: int(inc.SizeBytes / 1000 / 1000 / 1000), ObjectCnt: inc.ObjectCount}
pendingUsage := SRegionQuota{ObjectGB: int(inc.SizeBytes / 1000 / 1000 / 1000), ObjectCnt: inc.ObjectCount}
keys, err := bucket.GetQuotaKeys()
if err != nil {
return nil, httperrors.NewInternalServerError("bucket.GetQuotaKeys fail %s", err)
}
pendingUsage.SetKeys(keys)
if !pendingUsage.IsEmpty() {
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, bucket.GetOwnerId(), quotaPlatformId, &pendingUsage); err != nil {
if err := RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
return nil, httperrors.NewOutOfQuotaError("%s", err)
}
}
@@ -914,7 +946,7 @@ func (bucket *SBucket) PerformUpload(
bucket.syncWithCloudBucket(ctx, userCred, iBucket, nil, true)
if !pendingUsage.IsEmpty() {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, bucket.GetOwnerId(), quotaPlatformId, &pendingUsage, &pendingUsage)
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
}
return nil, nil
@@ -1102,39 +1134,12 @@ func (manager *SBucketManager) usageQByCloudEnv(q *sqlchemy.SQuery, providers []
return CloudProviderFilter(q, q.Field("manager_id"), providers, brands, cloudEnv)
}
func (manager *SBucketManager) usageQByRange(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
if rangeObj == nil {
return q
}
kw := rangeObj.Keyword()
switch kw {
case "zone":
zone := rangeObj.(*SZone)
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "wire":
wire := rangeObj.(*SWire)
zone := wire.GetZone()
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "host":
host := rangeObj.(*SHost)
zone := host.GetZone()
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "cloudprovider":
q = q.Filter(sqlchemy.Equals(q.Field("manager_id"), rangeObj.GetId()))
case "cloudaccount":
cloudproviders := CloudproviderManager.Query().SubQuery()
subq := cloudproviders.Query(cloudproviders.Field("id")).Equals("cloudaccount_id", rangeObj.GetId()).SubQuery()
q = q.Filter(sqlchemy.In(q.Field("manager_id"), subq))
case "cloudregion":
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), rangeObj.GetId()))
}
return q
func (manager *SBucketManager) usageQByRanges(q *sqlchemy.SQuery, rangeObjs []db.IStandaloneModel) *sqlchemy.SQuery {
return rangeObjectsFilter(q, rangeObjs, q.Field("cloudregion_id"), nil, q.Field("manager_id"))
}
func (manager *SBucketManager) usageQ(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, providers []string, brands []string, cloudEnv string) *sqlchemy.SQuery {
q = manager.usageQByRange(q, rangeObj)
func (manager *SBucketManager) usageQ(q *sqlchemy.SQuery, rangeObjs []db.IStandaloneModel, providers []string, brands []string, cloudEnv string) *sqlchemy.SQuery {
q = manager.usageQByRanges(q, rangeObjs)
q = manager.usageQByCloudEnv(q, providers, brands, cloudEnv)
return q
}
@@ -1145,7 +1150,7 @@ type SBucketUsages struct {
Bytes int64
}
func (manager *SBucketManager) TotalCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, rangeObj db.IStandaloneModel, providers []string, brands []string, cloudEnv string) SBucketUsages {
func (manager *SBucketManager) TotalCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, rangeObjs []db.IStandaloneModel, providers []string, brands []string, cloudEnv string) SBucketUsages {
usage := SBucketUsages{}
buckets := manager.Query().SubQuery()
q := buckets.Query(
@@ -1153,15 +1158,8 @@ func (manager *SBucketManager) TotalCount(scope rbacutils.TRbacScope, ownerId mc
sqlchemy.SUM("objects", buckets.Field("object_cnt")),
sqlchemy.SUM("bytes", buckets.Field("size_bytes")),
)
q = manager.usageQ(q, rangeObj, providers, brands, cloudEnv)
switch scope {
case rbacutils.ScopeSystem:
// do nothing
case rbacutils.ScopeDomain:
q = q.Equals("domain_id", ownerId.GetProjectDomainId())
case rbacutils.ScopeProject:
q = q.Equals("tenant_id", ownerId.GetProjectId())
}
q = manager.usageQ(q, rangeObjs, providers, brands, cloudEnv)
q = scopeOwnerIdFilter(q, scope, ownerId)
err := q.First(&usage)
if err != nil {
log.Errorf("Query bucket usage error %s", err)
+21 -21
View File
@@ -259,33 +259,33 @@ func (self *SCloudaccount) ValidateUpdateData(ctx context.Context, userCred mccl
return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.CloudaccountCreateInput) (api.CloudaccountCreateInput, error) {
// check domainId
err := db.ValidateCreateDomainId(ownerId.GetProjectDomainId())
if err != nil {
return nil, err
return input, err
}
data := jsonutils.Marshal(input).(*jsonutils.JSONDict)
tenantV := validators.NewModelIdOrNameValidator("tenant", "tenant", ownerId)
tenantV.Optional(true)
err = tenantV.Validate(data)
if err != nil {
return nil, err
return input, err
}
input := &api.CloudaccountCreateInput{}
err = data.Unmarshal(input)
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInputParameterError("failed to unmarshal input params error: %v", err)
return input, httperrors.NewInputParameterError("failed to unmarshal input params error: %v", err)
}
if !cloudprovider.IsSupported(input.Provider) {
return nil, httperrors.NewInputParameterError("Unsupported provider %s", input.Provider)
return input, httperrors.NewInputParameterError("Unsupported provider %s", input.Provider)
}
providerDriver, _ := cloudprovider.GetProviderFactory(input.Provider)
err = providerDriver.ValidateCreateCloudaccountData(ctx, userCred, input)
err = providerDriver.ValidateCreateCloudaccountData(ctx, userCred, &input)
if err != nil {
return nil, err
return input, err
}
if len(input.Brand) > 0 && input.Brand != providerDriver.GetName() {
brands := providerDriver.GetSupportedBrands()
@@ -293,7 +293,7 @@ func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, use
brands = append(brands, providerDriver.GetName())
}
if !utils.IsInStringArray(input.Brand, brands) {
return nil, httperrors.NewUnsupportOperationError("Not support brand %s, only support %s", input.Brand, brands)
return input, httperrors.NewUnsupportOperationError("Not support brand %s, only support %s", input.Brand, brands)
}
}
input.IsPublicCloud = providerDriver.IsPublicCloud()
@@ -309,29 +309,29 @@ func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, use
cnt, err := q.CountWithError()
if err != nil {
return nil, httperrors.NewInternalServerError("check uniqness fail %s", err)
return input, httperrors.NewInternalServerError("check uniqness fail %s", err)
}
if cnt > 0 {
return nil, httperrors.NewConflictError("The account has been registered")
return input, httperrors.NewConflictError("The account has been registered")
}
accountId, err := cloudprovider.IsValidCloudAccount(input.AccessUrl, input.Account, input.Secret, input.Provider)
if err != nil {
if err == cloudprovider.ErrNoSuchProvder {
return nil, httperrors.NewResourceNotFoundError("no such provider %s", input.Provider)
return input, httperrors.NewResourceNotFoundError("no such provider %s", input.Provider)
}
//log.Debugf("ValidateCreateData %s", err.Error())
return nil, httperrors.NewInputParameterError("invalid cloud account info error: %s", err.Error())
return input, httperrors.NewInputParameterError("invalid cloud account info error: %s", err.Error())
}
// check accountId uniqueness
if len(accountId) > 0 {
cnt, err := manager.Query().Equals("account_id", accountId).CountWithError()
if err != nil {
return nil, httperrors.NewInternalServerError("check account_id duplication error %s", err)
return input, httperrors.NewInternalServerError("check account_id duplication error %s", err)
}
if cnt > 0 {
return nil, httperrors.NewDuplicateResourceError("the account has been registerd %s", accountId)
return input, httperrors.NewDuplicateResourceError("the account has been registerd %s", accountId)
}
data.Set("account_id", jsonutils.NewString(accountId))
}
@@ -348,20 +348,20 @@ func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, use
params := jsonutils.Marshal(map[string]string{"domain_id": ownerId.GetProjectDomainId()})
tenants, err := modules.Projects.List(s, params)
if err != nil {
return nil, err
return input, err
}
if tenants.Total == 0 {
return nil, httperrors.NewInputParameterError("There are no projects under the domain %s", ownerId.GetProjectDomainId())
return input, httperrors.NewInputParameterError("There is no projects under the domain %s", ownerId.GetProjectDomainId())
}
}
}
data, err = manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input.EnabledStatusStandaloneResourceCreateInput, err = manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusStandaloneResourceCreateInput)
if err != nil {
return nil, err
return input, err
}
return input.JSON(input), nil
return input, nil
}
func (self *SCloudaccount) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
+5 -2
View File
@@ -60,6 +60,7 @@ type SCloudregion struct {
cloudprovider.SGeographicInfo
CloudEnv string `width:"32" charset:"ascii" list:"user"`
Provider string `width:"64" charset:"ascii" list:"user" nullable:"false" default:"OneCloud"`
}
@@ -402,6 +403,7 @@ func (self *SCloudregion) syncWithCloudRegion(ctx context.Context, userCred mccl
self.Status = cloudRegion.GetStatus()
self.SGeographicInfo = cloudRegion.GetGeographicInfo()
self.Provider = cloudRegion.GetProvider()
self.CloudEnv = cloudRegion.GetCloudEnv()
self.IsEmulated = cloudRegion.IsEmulated()
@@ -433,6 +435,7 @@ func (manager *SCloudregionManager) newFromCloudRegion(ctx context.Context, user
region.Status = cloudRegion.GetStatus()
region.Enabled = true
region.Provider = cloudRegion.GetProvider()
region.CloudEnv = cloudRegion.GetCloudEnv()
region.IsEmulated = cloudRegion.IsEmulated()
@@ -704,9 +707,9 @@ func (manager *SCloudregionManager) ListItemFilter(ctx context.Context, q *sqlch
return q, nil
}
func (manager *SCloudregionManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
/*func (manager *SCloudregionManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
return manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
}
}*/
func (self *SCloudregion) isManaged() bool {
if len(self.ExternalId) > 0 {
+14
View File
@@ -40,6 +40,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/stringutils2"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SDBInstanceManager struct {
@@ -1374,3 +1375,16 @@ func (manager *SDBInstanceManager) newFromCloudDBInstance(ctx context.Context, u
return &instance, nil
}
func (man *SDBInstanceManager) TotalCount(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
rangeObjs []db.IStandaloneModel,
providers []string, brands []string, cloudEnv string,
) (int, error) {
q := man.Query()
q = scopeOwnerIdFilter(q, scope, ownerId)
q = CloudProviderFilter(q, q.Field("manager_id"), providers, brands, cloudEnv)
q = rangeObjectsFilter(q, rangeObjs, q.Field("cloudregion_id"), nil, q.Field("manager_id"))
return q.CountWithError()
}
+153 -31
View File
@@ -54,14 +54,14 @@ import (
)
type SDiskManager struct {
db.SSharableVirtualResourceBaseManager
db.SVirtualResourceBaseManager
}
var DiskManager *SDiskManager
func init() {
DiskManager = &SDiskManager{
SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
SDisk{},
"disks_tbl",
"disk",
@@ -72,7 +72,7 @@ func init() {
}
type SDisk struct {
db.SSharableVirtualResourceBase
db.SVirtualResourceBase
db.SExternalizedResourceBase
SBillingResourceBase
@@ -147,7 +147,7 @@ func (manager *SDiskManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
queryDict.Remove("billing_type")
}
q, err = manager.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
q, err = manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
if err != nil {
return nil, err
}
@@ -369,7 +369,7 @@ func (self *SDisk) CustomizeCreate(ctx context.Context, userCred mcclient.TokenC
return err
}
self.fetchDiskInfo(input.DiskConfig)
return self.SSharableVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
return self.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
}
func (self *SDisk) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
@@ -397,6 +397,37 @@ func (self *SDisk) ValidateUpdateData(ctx context.Context, userCred mcclient.Tok
return self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
func diskCreateInput2ComputeQuotaKeys(input api.DiskCreateInput, ownerId mcclient.IIdentityProvider) SComputeResourceKeys {
// input.Hypervisor must be set
keys := GetDriver(input.Hypervisor).GetComputeQuotaKeys(
rbacutils.ScopeProject,
ownerId,
"",
)
if len(input.PreferHost) > 0 {
hostObj, _ := HostManager.FetchById(input.PreferHost)
host := hostObj.(*SHost)
zone := host.GetZone()
keys.ZoneId = zone.Id
keys.RegionId = zone.CloudregionId
} else if len(input.PreferZone) > 0 {
zoneObj, _ := ZoneManager.FetchById(input.PreferZone)
zone := zoneObj.(*SZone)
keys.ZoneId = zone.Id
keys.RegionId = zone.CloudregionId
} else if len(input.PreferWire) > 0 {
wireObj, _ := WireManager.FetchById(input.PreferWire)
wire := wireObj.(*SWire)
zone := wire.GetZone()
keys.ZoneId = zone.Id
keys.RegionId = zone.CloudregionId
} else if len(input.PreferRegion) > 0 {
regionObj, _ := CloudregionManager.FetchById(input.PreferRegion)
keys.RegionId = regionObj.GetId()
}
return keys
}
func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
input, err := cmdline.FetchDiskCreateInputByJSON(data)
if err != nil {
@@ -410,6 +441,8 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
input.Project = ownerId.GetProjectId()
input.Domain = ownerId.GetProjectDomainId()
var quotaKey quotas.IQuotaKeys
storageID := input.Storage
if storageID != "" {
storageObj, err := StorageManager.FetchByIdOrName(nil, storageID)
@@ -418,7 +451,8 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
}
storage := storageObj.(*SStorage)
if provider := storage.GetCloudprovider(); provider != nil {
provider := storage.GetCloudprovider()
if provider != nil {
if !provider.Enabled {
return nil, httperrors.NewInputParameterError("provider %s(%s) is disabled, you need enable provider first", provider.Name, provider.Id)
}
@@ -432,7 +466,7 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
host := storage.GetMasterHost()
if host == nil {
return nil, httperrors.NewResourceNotFoundError("storage %s(%s) need onlne and attach host for create disk", storage.Name, storage.Id)
return nil, httperrors.NewResourceNotFoundError("storage %s(%s) need online and attach host for create disk", storage.Name, storage.Id)
}
input.Hypervisor = host.GetHostDriver().GetHypervisor()
if len(diskConfig.Backend) == 0 {
@@ -443,6 +477,14 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
return nil, err
}
input.Storage = storage.Id
quotaKey = fetchComputeQuotaKeys(
rbacutils.ScopeProject,
ownerId,
storage.getZone(),
provider,
input.Hypervisor,
)
} else {
diskConfig.Backend = api.STORAGE_LOCAL
serverInput, err := ValidateScheduleCreateData(ctx, userCred, input.ToServerCreateInput(), input.Hypervisor)
@@ -450,15 +492,17 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
return nil, err
}
input = serverInput.ToDiskCreateInput()
quotaKey = diskCreateInput2ComputeQuotaKeys(*input, ownerId)
}
if _, err := manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
if err != nil {
return nil, err
}
pendingUsage := SQuota{Storage: diskConfig.SizeMb}
quotaName := GetDriver(input.Hypervisor).GetQuotaPlatformID()
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, userCred, quotaName, &pendingUsage); err != nil {
pendingUsage := SQuota{Storage: diskConfig.SizeMb}
pendingUsage.SetKeys(quotaKey)
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
return nil, httperrors.NewOutOfQuotaError("%s", err)
}
return input.JSON(input), nil
@@ -549,11 +593,26 @@ func (disk *SDisk) SetStorageByHost(hostId string, diskConfig *api.DiskConfig, s
return err
}
func getDiskResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, count int) SQuota {
diskSize, _ := data.Int("disk", "size")
return SQuota{
Storage: int(diskSize) * count,
func getDiskResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DiskCreateInput, count int) SQuota {
req := SQuota{
Storage: input.SizeMb * count,
}
var quotaKey SComputeResourceKeys
if len(input.Storage) > 0 {
storageObj, _ := StorageManager.FetchById(input.Storage)
storage := storageObj.(*SStorage)
quotaKey = fetchComputeQuotaKeys(
rbacutils.ScopeProject,
ownerId,
storage.getZone(),
storage.GetCloudprovider(),
input.Hypervisor,
)
} else {
quotaKey = diskCreateInput2ComputeQuotaKeys(input, ownerId)
}
req.SetKeys(quotaKey)
return req
}
/*func (manager *SDiskManager) convertToBatchCreateData(data jsonutils.JSONObject) *jsonutils.JSONDict {
@@ -563,9 +622,14 @@ func getDiskResourceRequirements(ctx context.Context, userCred mcclient.TokenCre
return newData
}*/
func (manager *SDiskManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
pendingUsage := getDiskResourceRequirements(ctx, userCred, data, len(items))
RunBatchCreateTask(ctx, items, userCred, data, pendingUsage, "DiskBatchCreateTask", "")
func (manager *SDiskManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
input := api.DiskCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
log.Errorf("!!!data.Unmarshal api.DiskCreateInput fail %s", err)
}
pendingUsage := getDiskResourceRequirements(ctx, userCred, ownerId, input, len(items))
RunBatchCreateTask(ctx, items, userCred, data, pendingUsage, SRegionQuota{}, "DiskBatchCreateTask", "")
}
func (self *SDisk) StartDiskCreateTask(ctx context.Context, userCred mcclient.TokenCredential, rebuild bool, snapshot string, parentTaskId string) error {
@@ -777,6 +841,40 @@ func (disk *SDisk) PerformResize(ctx context.Context, userCred mcclient.TokenCre
return nil, nil
}
func (disk *SDisk) getHypervisor() string {
storage := disk.GetStorage()
if storage != nil {
host := storage.GetMasterHost()
if host != nil {
return host.GetHostDriver().GetHypervisor()
}
}
hypervisor := disk.GetMetadata("hypervisor", nil)
return hypervisor
}
func (disk *SDisk) GetQuotaKeys() (quotas.IQuotaKeys, error) {
storage := disk.GetStorage()
if storage == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid storage")
}
provider := storage.GetCloudprovider()
if provider == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid manager")
}
zone := storage.getZone()
if zone == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid zone")
}
return fetchComputeQuotaKeys(
rbacutils.ScopeProject,
disk.GetOwnerId(),
zone,
provider,
disk.getHypervisor(),
), nil
}
func (disk *SDisk) doResize(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, guest *SGuest) error {
sizeStr, err := data.GetString("size")
if err != nil {
@@ -811,10 +909,14 @@ func (disk *SDisk) doResize(ctx context.Context, userCred mcclient.TokenCredenti
}
}
pendingUsage := SQuota{Storage: int(addDisk)}
quotaName := storage.getQuotaPlatformID()
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, userCred, quotaName, &pendingUsage); err != nil {
return httperrors.NewOutOfQuotaError(err.Error())
keys, err := disk.GetQuotaKeys()
if err != nil {
return httperrors.NewInternalServerError("disk.GetQuotaKeys fail %s", err)
}
pendingUsage.SetKeys(keys)
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
if err != nil {
return httperrors.NewGeneralError(err)
}
if guest != nil {
@@ -955,7 +1057,7 @@ func (self *SDisk) validateDeleteCondition(ctx context.Context, isPurge bool) er
return httperrors.NewBadRequestError("not allow to delete %s disk with snapshots", storage.StorageType)
}
}
return self.SSharableVirtualResourceBase.ValidateDeleteCondition(ctx)
return self.SVirtualResourceBase.ValidateDeleteCondition(ctx)
}
func (self *SDisk) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
@@ -1379,13 +1481,33 @@ func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mccl
return &disk, nil
}
func totalDiskSize(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, active tristate.TriState, ready tristate.TriState, includeSystem bool, pendingDelete bool) int {
func totalDiskSize(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
active tristate.TriState,
ready tristate.TriState,
includeSystem bool,
pendingDelete bool,
rangeObjs []db.IStandaloneModel,
providers []string,
brands []string,
cloudEnv string,
hypervisors []string,
) int {
disks := DiskManager.Query().SubQuery()
q := disks.Query(sqlchemy.SUM("total", disks.Field("disk_size")))
storages := StorageManager.Query().SubQuery()
q = q.Join(storages, sqlchemy.Equals(storages.Field("id"), disks.Field("storage_id")))
q = CloudProviderFilter(q, storages.Field("manager_id"), providers, brands, cloudEnv)
q = rangeObjectsFilter(q, rangeObjs, nil, storages.Field("zone_id"), storages.Field("manager_id"))
if len(hypervisors) > 0 {
hoststorages := HoststorageManager.Query().SubQuery()
hosts := HostManager.Query().SubQuery()
q = q.Join(hoststorages, sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")))
q = q.Join(hosts, sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id")))
q = q.Filter(sqlchemy.In(hosts.Field("host_type"), api.Hypervisors2HostTypes(hypervisors)))
}
if !active.IsNone() {
storages := StorageManager.Query().SubQuery()
q = q.Join(storages, sqlchemy.AND(sqlchemy.IsFalse(storages.Field("deleted")),
sqlchemy.Equals(storages.Field("id"), disks.Field("storage_id"))))
if active.IsTrue() {
q = q.Filter(sqlchemy.In(storages.Field("status"), []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}))
} else {
@@ -1626,7 +1748,7 @@ func (self *SDisk) RealDelete(ctx context.Context, userCred mcclient.TokenCreden
guestdisk.Detach(ctx, userCred)
}
}
err := self.SSharableVirtualResourceBase.Delete(ctx, userCred)
err := self.SVirtualResourceBase.Delete(ctx, userCred)
if err != nil {
return err
}
@@ -1756,7 +1878,7 @@ func (self *SDisk) getMoreDetails(ctx context.Context, userCred mcclient.TokenCr
}
func (self *SDisk) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
extra, err := self.SSharableVirtualResourceBase.GetExtraDetails(ctx, userCred, query)
extra, err := self.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query)
if err != nil {
return nil, err
}
@@ -1764,7 +1886,7 @@ func (self *SDisk) GetExtraDetails(ctx context.Context, userCred mcclient.TokenC
}
func (self *SDisk) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SSharableVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query)
extra := self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query)
return self.getMoreDetails(ctx, userCred, extra)
}
@@ -1859,7 +1981,7 @@ func (self *SDisk) ClearHostSchedCache() error {
}
func (self *SDisk) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
desc := self.SSharableVirtualResourceBase.GetShortDesc(ctx)
desc := self.SVirtualResourceBase.GetShortDesc(ctx)
desc.Add(jsonutils.NewInt(int64(self.DiskSize)), "size")
storage := self.GetStorage()
if storage != nil {
+12 -1
View File
@@ -24,6 +24,7 @@ import (
"yunion.io/x/pkg/tristate"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -158,7 +159,17 @@ func (manager *SDynamicschedtagManager) ValidateCreateData(ctx context.Context,
if err != nil {
return nil, err
}
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (self *SDynamicschedtag) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
+9 -1
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -220,10 +221,17 @@ func (manager *SElasticcacheAccountManager) ValidateCreateData(ctx context.Conte
return nil, httperrors.NewMissingParameterError("elasticcache_id")
}
data, err := manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StatusStandaloneResourceCreateInput{}
var err error
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return region.GetDriver().ValidateCreateElasticcacheAccountData(ctx, userCred, ownerId, data)
}
+9 -1
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -204,10 +205,17 @@ func (manager *SElasticcacheAclManager) ValidateCreateData(ctx context.Context,
return nil, httperrors.NewMissingParameterError("elasticcache")
}
data, err := manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
var err error
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return region.GetDriver().ValidateCreateElasticcacheAclData(ctx, userCred, ownerId, data)
}
+9 -1
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -248,10 +249,17 @@ func (manager *SElasticcacheBackupManager) ValidateCreateData(ctx context.Contex
return nil, err
}
data, err := manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
var err error
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return driver.ValidateCreateElasticcacheBackupData(ctx, userCred, ownerId, data)
}
+22 -1
View File
@@ -28,6 +28,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -490,10 +491,17 @@ func (manager *SElasticcacheManager) ValidateCreateData(ctx context.Context, use
return nil, fmt.Errorf("getting region failed")
}
data, err := manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.VirtualResourceCreateInput{}
var err error
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return region.GetDriver().ValidateCreateElasticcacheData(ctx, userCred, nil, data)
}
@@ -1245,3 +1253,16 @@ func (self *SElasticcache) DeleteSubResources(ctx context.Context, userCred mccl
}(m)
}
}
func (man *SElasticcacheManager) TotalCount(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
rangeObjs []db.IStandaloneModel,
providers []string, brands []string, cloudEnv string,
) (int, error) {
q := man.Query()
q = scopeOwnerIdFilter(q, scope, ownerId)
q = CloudProviderFilter(q, q.Field("manager_id"), providers, brands, cloudEnv)
q = rangeObjectsFilter(q, rangeObjs, q.Field("cloudregion_id"), nil, q.Field("manager_id"))
return q.CountWithError()
}
+78 -48
View File
@@ -27,6 +27,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -685,7 +686,7 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
return nil, httperrors.NewMissingParameterError("manager_id")
}
provider, err := CloudproviderManager.FetchByIdOrName(nil, managerStr)
providerObj, err := CloudproviderManager.FetchByIdOrName(nil, managerStr)
if err != nil {
if err != sql.ErrNoRows {
return nil, httperrors.NewGeneralError(err)
@@ -693,7 +694,8 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
return nil, httperrors.NewResourceNotFoundError("Cloud provider %s not found", managerStr)
}
}
data.Add(jsonutils.NewString(provider.GetId()), "manager_id")
provider := providerObj.(*SCloudprovider)
data.Add(jsonutils.NewString(provider.Id), "manager_id")
chargeType := jsonutils.GetAnyString(data, []string{"charge_type"})
if len(chargeType) == 0 {
@@ -706,31 +708,55 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
data.Add(jsonutils.NewString(chargeType), "charge_type")
data, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.VirtualResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
//避免参数重名后还有pending.eip残留
eipPendingUsage := &SQuota{Eip: 1}
quotaPlatform := provider.(*SCloudprovider).GetQuotaPlatformID()
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, userCred, quotaPlatform, eipPendingUsage)
eipPendingUsage := &SRegionQuota{Eip: 1}
quotaKeys := fetchRegionalQuotaKeys(rbacutils.ScopeProject, ownerId, region, provider)
eipPendingUsage.SetKeys(quotaKeys)
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, eipPendingUsage)
if err != nil {
return nil, httperrors.NewOutOfQuotaError("Out of eip quota: %s", err)
return nil, err
}
return region.GetDriver().ValidateCreateEipData(ctx, userCred, data)
}
func (eip *SElasticip) GetQuotaKeys() (quotas.IQuotaKeys, error) {
region := eip.GetRegion()
if region == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid region")
}
return fetchRegionalQuotaKeys(
rbacutils.ScopeProject,
eip.GetOwnerId(),
region,
eip.GetCloudprovider(),
), nil
}
func (self *SElasticip) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
quotaPlatform := self.GetQuotaPlatformID()
eipPendingUsage := &SQuota{Eip: 1}
err := QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatform, eipPendingUsage, eipPendingUsage)
eipPendingUsage := &SRegionQuota{Eip: 1}
keys, err := self.GetQuotaKeys()
if err != nil {
log.Errorf("SElasticip CancelPendingUsage error: %s", err)
log.Errorf("GetQuotaKeys fail %s", err)
} else {
eipPendingUsage.SetKeys(keys)
err := RegionQuotaManager.CancelPendingUsage(ctx, userCred, eipPendingUsage, eipPendingUsage)
if err != nil {
log.Errorf("SElasticip CancelPendingUsage error: %s", err)
}
}
self.startEipAllocateTask(ctx, userCred, data.(*jsonutils.JSONDict), "")
@@ -1069,8 +1095,15 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
return nil, err
}
eipPendingUsage := &SQuota{Eip: 1}
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, vm.GetOwnerId(), vm.GetQuotaPlatformID(), pendingUsage, eipPendingUsage)
eipPendingUsage := &SRegionQuota{Eip: 1}
keys := fetchRegionalQuotaKeys(
rbacutils.ScopeProject,
vm.GetOwnerId(),
region,
host.GetCloudprovider(),
)
eipPendingUsage.SetKeys(keys)
QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, eipPendingUsage)
return &eip, nil
}
@@ -1168,52 +1201,49 @@ func (manager *SElasticipManager) usageQByCloudEnv(q *sqlchemy.SQuery, providers
return CloudProviderFilter(q, q.Field("manager_id"), providers, brands, cloudEnv)
}
func (manager *SElasticipManager) usageQByRange(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
if rangeObj == nil {
return q
func (manager *SElasticipManager) usageQByRanges(q *sqlchemy.SQuery, rangeObjs []db.IStandaloneModel) *sqlchemy.SQuery {
for _, rangeObj := range rangeObjs {
kw := rangeObj.Keyword()
// log.Debugf("rangeObj keyword: %s", kw)
switch kw {
case "zone":
zone := rangeObj.(*SZone)
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "wire":
wire := rangeObj.(*SWire)
zone := wire.GetZone()
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "host":
host := rangeObj.(*SHost)
zone := host.GetZone()
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "cloudprovider":
q = q.Filter(sqlchemy.Equals(q.Field("manager_id"), rangeObj.GetId()))
case "cloudaccount":
cloudproviders := CloudproviderManager.Query().SubQuery()
subq := cloudproviders.Query(cloudproviders.Field("id")).Equals("cloudaccount_id", rangeObj.GetId()).SubQuery()
q = q.Filter(sqlchemy.In(q.Field("manager_id"), subq))
case "cloudregion":
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), rangeObj.GetId()))
}
}
kw := rangeObj.Keyword()
// log.Debugf("rangeObj keyword: %s", kw)
switch kw {
case "zone":
zone := rangeObj.(*SZone)
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "wire":
wire := rangeObj.(*SWire)
zone := wire.GetZone()
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "host":
host := rangeObj.(*SHost)
zone := host.GetZone()
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
case "cloudprovider":
q = q.Filter(sqlchemy.Equals(q.Field("manager_id"), rangeObj.GetId()))
case "cloudaccount":
cloudproviders := CloudproviderManager.Query().SubQuery()
subq := cloudproviders.Query(cloudproviders.Field("id")).Equals("cloudaccount_id", rangeObj.GetId()).SubQuery()
q = q.Filter(sqlchemy.In(q.Field("manager_id"), subq))
case "cloudregion":
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), rangeObj.GetId()))
}
return q
}
func (manager *SElasticipManager) usageQ(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, providers []string, brands []string, cloudEnv string) *sqlchemy.SQuery {
q = manager.usageQByRange(q, rangeObj)
func (manager *SElasticipManager) usageQ(q *sqlchemy.SQuery, rangeObjs []db.IStandaloneModel, providers []string, brands []string, cloudEnv string) *sqlchemy.SQuery {
q = manager.usageQByRanges(q, rangeObjs)
q = manager.usageQByCloudEnv(q, providers, brands, cloudEnv)
return q
}
func (manager *SElasticipManager) TotalCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, rangeObj db.IStandaloneModel, providers []string, brands []string, cloudEnv string) EipUsage {
func (manager *SElasticipManager) TotalCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, rangeObjs []db.IStandaloneModel, providers []string, brands []string, cloudEnv string) EipUsage {
usage := EipUsage{}
q1 := manager.Query().Equals("mode", api.EIP_MODE_INSTANCE_PUBLICIP)
q1 = manager.usageQ(q1, rangeObj, providers, brands, cloudEnv)
q1 = manager.usageQ(q1, rangeObjs, providers, brands, cloudEnv)
q2 := manager.Query().Equals("mode", api.EIP_MODE_STANDALONE_EIP)
q2 = manager.usageQ(q2, rangeObj, providers, brands, cloudEnv)
q2 = manager.usageQ(q2, rangeObjs, providers, brands, cloudEnv)
q3 := manager.Query().Equals("mode", api.EIP_MODE_STANDALONE_EIP).IsNotEmpty("associate_id")
q3 = manager.usageQ(q3, rangeObj, providers, brands, cloudEnv)
q3 = manager.usageQ(q3, rangeObjs, providers, brands, cloudEnv)
switch scope {
case rbacutils.ScopeSystem:
// do nothing
+86
View File
@@ -0,0 +1,86 @@
// 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 models
import (
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/onecloud/pkg/mcclient"
)
func rangeObjectsFilter(q *sqlchemy.SQuery, rangeObjs []db.IStandaloneModel, regionField sqlchemy.IQueryField, zoneField sqlchemy.IQueryField, managerField sqlchemy.IQueryField) *sqlchemy.SQuery {
for _, rangeObj := range rangeObjs {
q = rangeObjFilter(q, rangeObj, regionField, zoneField, managerField)
}
return q
}
func rangeObjFilter(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, regionField sqlchemy.IQueryField, zoneField sqlchemy.IQueryField, managerField sqlchemy.IQueryField) *sqlchemy.SQuery {
kw := rangeObj.Keyword()
switch kw {
case "zone":
zone := rangeObj.(*SZone)
if regionField != nil {
q = q.Filter(sqlchemy.Equals(regionField, zone.CloudregionId))
} else if zoneField != nil {
q = q.Filter(sqlchemy.Equals(zoneField, zone.Id))
}
case "wire":
wire := rangeObj.(*SWire)
if regionField != nil {
vpc := wire.getVpc()
q = q.Filter(sqlchemy.Equals(regionField, vpc.CloudregionId))
} else if zoneField != nil {
q = q.Filter(sqlchemy.Equals(zoneField, wire.ZoneId))
}
case "host":
host := rangeObj.(*SHost)
if regionField != nil {
zone := host.GetZone()
q = q.Filter(sqlchemy.Equals(regionField, zone.CloudregionId))
} else if zoneField != nil {
q = q.Filter(sqlchemy.Equals(zoneField, host.ZoneId))
}
case "cloudprovider":
q = q.Filter(sqlchemy.Equals(managerField, rangeObj.GetId()))
case "cloudaccount":
cloudproviders := CloudproviderManager.Query().SubQuery()
subq := cloudproviders.Query(cloudproviders.Field("id")).Equals("cloudaccount_id", rangeObj.GetId()).SubQuery()
q = q.Filter(sqlchemy.In(managerField, subq))
case "cloudregion":
if regionField != nil {
q = q.Filter(sqlchemy.Equals(regionField, rangeObj.GetId()))
} else if zoneField != nil {
zones := ZoneManager.Query().SubQuery()
subq := zones.Query(zones.Field("id")).Equals("cloudregion_id", rangeObj.GetId()).SubQuery()
q = q.Filter(sqlchemy.In(zoneField, subq))
}
}
return q
}
func scopeOwnerIdFilter(q *sqlchemy.SQuery, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) *sqlchemy.SQuery {
switch scope {
case rbacutils.ScopeSystem:
// do nothing
case rbacutils.ScopeDomain:
q = q.Equals("domain_id", ownerId.GetProjectDomainId())
case rbacutils.ScopeProject:
q = q.Equals("tenant_id", ownerId.GetProjectId())
}
return q
}
+99 -61
View File
@@ -57,7 +57,6 @@ import (
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/rand"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/onecloud/pkg/util/seclib2"
)
@@ -498,14 +497,19 @@ func (self *SGuest) PerformClone(ctx context.Context, userCred mcclient.TokenCre
db.OpsLog.LogEvent(model, db.ACT_CREATE, model.GetShortDesc(ctx), userCred)
logclient.AddActionLogWithContext(ctx, model, logclient.ACT_CREATE, "", userCred, true)
pendingUsage := getGuestResourceRequirements(ctx, userCred, createInput, 1, false)
if task, err := taskman.TaskManager.NewTask(ctx, "GuestCloneTask", model.(db.IStandaloneModel), userCred,
dataDict, "", "", &pendingUsage); err != nil {
pendingUsage, pendingRegionUsage := getGuestResourceRequirements(ctx, userCred, *createInput, userCred, 1, false)
task, err := taskman.TaskManager.NewTask(ctx,
"GuestCloneTask",
model.(db.IStandaloneModel),
userCred,
dataDict,
"", "",
&pendingUsage, &pendingRegionUsage)
if err != nil {
log.Errorln(err)
return nil, err
} else {
task.ScheduleRun(nil)
}
task.ScheduleRun(nil)
return nil, nil
}
@@ -1524,7 +1528,12 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
pendingUsage := &SQuota{
Storage: diskSize,
}
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), host.GetQuotaPlatformID(), pendingUsage)
keys, err := self.GetQuotaKeys()
if err != nil {
return nil, err
}
pendingUsage.SetKeys(keys)
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
if err != nil {
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, err.Error(), userCred, false)
return nil, httperrors.NewOutOfQuotaError(err.Error())
@@ -1535,7 +1544,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage, false, false, nil, nil, false)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), host.GetQuotaPlatformID(), nil, pendingUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage)
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, err.Error(), userCred, false)
return nil, httperrors.NewBadRequestError(err.Error())
}
@@ -2089,22 +2098,25 @@ func (self *SGuest) PerformAttachnetwork(ctx context.Context, userCred mcclient.
inicCnt = 1
ibw = conf.BwLimit
}
pendingUsage := &SQuota{
pendingUsage := &SRegionQuota{
Port: inicCnt,
Eport: enicCnt,
Bw: ibw,
Ebw: ebw,
}
ownerId := self.GetOwnerId()
quotaPlatform := self.GetQuotaPlatformID()
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatform, pendingUsage)
keys, err := self.GetQuotaKeys()
if err != nil {
return nil, err
}
pendingUsage.SetKeys(keys)
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
if err != nil {
return nil, httperrors.NewOutOfQuotaError(err.Error())
}
host := self.GetHost()
_, err = self.attach2NetworkDesc(ctx, userCred, host, conf, pendingUsage, nil)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatform, nil, pendingUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, nil, pendingUsage)
return nil, httperrors.NewBadRequestError(err.Error())
}
host.ClearSchedDescCache()
@@ -2378,19 +2390,22 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
pendingUsage.Storage = addDisk
}
quotaPlatform := self.GetQuotaPlatformID()
keys, err := self.GetQuotaKeys()
if err != nil {
return nil, err
}
pendingUsage.SetKeys(keys)
if !pendingUsage.IsEmpty() {
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, pendingUsage)
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
if err != nil {
return nil, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
return nil, err
}
}
if len(newDisks) > 0 {
err := self.CreateDisksOnHost(ctx, userCred, host, newDisks, pendingUsage, false, false, nil, nil, false)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, nil, pendingUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, nil, pendingUsage)
return nil, httperrors.NewBadRequestError("Create disk on host error: %s", err)
}
confs.Add(jsonutils.Marshal(newDisks), "create")
@@ -2408,13 +2423,13 @@ func (self *SGuest) confToSchedDesc(addCpu, addMem, addDisk int) *schedapi.Sched
ServerConfig: schedapi.ServerConfig{
ServerConfigs: &api.ServerConfigs{
Hypervisor: self.Hypervisor,
Project: self.ProjectId,
Domain: self.DomainId,
PreferHost: self.HostId,
Disks: []*api.DiskConfig{diskInfo},
},
Memory: addMem,
Ncpu: addCpu,
Memory: addMem,
Ncpu: addCpu,
Project: self.ProjectId,
Domain: self.DomainId,
},
}
return desc
@@ -2850,11 +2865,13 @@ func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.Toke
return nil, err
}
quotaPlatform := self.GetQuotaPlatformID()
eipPendingUsage := &SQuota{Eip: 1}
ownerCred := self.GetOwnerId()
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, ownerCred, quotaPlatform, eipPendingUsage)
eipPendingUsage := &SRegionQuota{Eip: 1}
keys, err := self.GetRegionalQuotaKeys()
if err != nil {
return nil, err
}
eipPendingUsage.SetKeys(keys)
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, eipPendingUsage)
if err != nil {
return nil, httperrors.NewOutOfQuotaError("Out of eip quota: %s", err)
}
@@ -3203,10 +3220,13 @@ func (self *SGuest) PerformCreateBackup(ctx context.Context, userCred mcclient.T
return nil, httperrors.NewBadRequestError("Cannot create backup with snapshot")
}
quotaPlatform := self.GetQuotaPlatformID()
req := self.getGuestBackupResourceRequirements(ctx, userCred)
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, &req)
keys, err := self.GetQuotaKeys()
if err != nil {
return nil, err
}
req.SetKeys(keys)
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, &req)
if err != nil {
return nil, httperrors.NewOutOfQuotaError(err.Error())
}
@@ -3215,7 +3235,7 @@ func (self *SGuest) PerformCreateBackup(ctx context.Context, userCred mcclient.T
params.Set("guest_status", jsonutils.NewString(self.Status))
task, err := taskman.TaskManager.NewTask(ctx, "GuestCreateBackupTask", self, userCred, params, "", "", &req)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, nil, &req)
QuotaManager.CancelPendingUsage(ctx, userCred, nil, &req)
log.Errorln(err)
return nil, err
} else {
@@ -4053,8 +4073,11 @@ func (self *SGuest) AllowPerformInstanceSnapshot(ctx context.Context,
}
func (self *SGuest) validateCreateInstanceSnapshot(
ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject,
) (*SQuota, error) {
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
data jsonutils.JSONObject,
) (*SRegionQuota, error) {
if self.Hypervisor != api.HYPERVISOR_KVM {
return nil, httperrors.NewBadRequestError("guest hypervisor %s can't create instance snapshot", self.Hypervisor)
@@ -4099,9 +4122,13 @@ func (self *SGuest) validateCreateInstanceSnapshot(
}
}
}
quotaPlatform := self.GetQuotaPlatformID()
pendingUsage := &SQuota{Snapshot: len(disks)}
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatform, pendingUsage)
pendingUsage := &SRegionQuota{Snapshot: len(disks)}
keys, err := self.GetRegionalQuotaKeys()
if err != nil {
return nil, err
}
pendingUsage.SetKeys(keys)
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
if err != nil {
return nil, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
}
@@ -4125,22 +4152,25 @@ func (self *SGuest) PerformInstanceSnapshot(
instanceSnapshot, err := InstanceSnapshotManager.CreateInstanceSnapshot(ctx, ownerId, self, name, false)
if err != nil {
QuotaManager.CancelPendingUsage(
ctx, userCred, rbacutils.ScopeProject, ownerId, self.GetQuotaPlatformID(), pendingUsage, pendingUsage)
ctx, userCred, pendingUsage, pendingUsage)
return nil, httperrors.NewInternalServerError("create instance snapshot failed: %s", err)
}
err = self.InstaceCreateSnapshot(ctx, userCred, ownerId, instanceSnapshot, pendingUsage)
if err != nil {
QuotaManager.CancelPendingUsage(
ctx, userCred, rbacutils.ScopeProject, ownerId, self.GetQuotaPlatformID(), pendingUsage, pendingUsage)
RegionQuotaManager.CancelPendingUsage(
ctx, userCred, pendingUsage, pendingUsage)
return nil, httperrors.NewInternalServerError("start create snapshot task failed: %s", err)
}
return nil, nil
}
func (self *SGuest) InstaceCreateSnapshot(
ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
instanceSnapshot *SInstanceSnapshot, pendingUsage *SQuota) error {
ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
instanceSnapshot *SInstanceSnapshot,
pendingUsage *SRegionQuota,
) error {
self.SetStatus(userCred, api.VM_START_INSTANCE_SNAPSHOT, "instance snapshot")
return instanceSnapshot.StartCreateInstanceSnapshotTask(ctx, userCred, ownerId, pendingUsage, "")
}
@@ -4224,44 +4254,52 @@ func (self *SGuest) PerformSnapshotAndClone(
return nil, err
}
// set guest pending usage
pendingUsage, err := self.getGuestUsage(int(count))
pendingUsage, pendingRegionUsage, err := self.getGuestUsage(int(count))
keys, err := self.GetQuotaKeys()
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(),
self.GetQuotaPlatformID(), snapshotUsage, snapshotUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage)
return nil, err
}
err = QuotaManager.CheckSetPendingQuota(ctx, userCred,
rbacutils.ScopeProject, self.GetOwnerId(), self.GetQuotaPlatformID(), pendingUsage)
pendingUsage.SetKeys(keys)
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(),
self.GetQuotaPlatformID(), snapshotUsage, snapshotUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage)
return nil, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
}
pendingUsage.Snapshot = snapshotUsage.Snapshot
regionKeys, err := self.GetRegionalQuotaKeys()
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
return nil, err
}
pendingRegionUsage.SetKeys(regionKeys)
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingRegionUsage)
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
return nil, err
}
pendingRegionUsage.Snapshot = snapshotUsage.Snapshot
instanceSnapshotName, err := db.GenerateName(InstanceSnapshotManager, self.GetOwnerId(),
fmt.Sprintf("%s-%s", newlyGuestName, rand.String(8)))
if err != nil {
QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(),
self.GetQuotaPlatformID(), pendingUsage, pendingUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
return nil, httperrors.NewInternalServerError("Generate snapshot name failed %s", err)
}
instanceSnapshot, err := InstanceSnapshotManager.CreateInstanceSnapshot(
ctx, self.GetOwnerId(), self, instanceSnapshotName,
jsonutils.QueryBoolean(data, "auto_delete_instance_snapshot", false))
if err != nil {
QuotaManager.CancelPendingUsage(
ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(),
self.GetQuotaPlatformID(), pendingUsage, pendingUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
return nil, httperrors.NewInternalServerError("create instance snapshot failed: %s", err)
}
err = self.StartInstanceSnapshotAndCloneTask(
ctx, userCred, newlyGuestName, pendingUsage, instanceSnapshot, data.(*jsonutils.JSONDict))
ctx, userCred, newlyGuestName, &pendingUsage, &pendingRegionUsage, instanceSnapshot, data.(*jsonutils.JSONDict))
if err != nil {
QuotaManager.CancelPendingUsage(
ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(),
self.GetQuotaPlatformID(), pendingUsage, pendingUsage)
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
return nil, err
}
return nil, nil
@@ -4269,12 +4307,12 @@ func (self *SGuest) PerformSnapshotAndClone(
func (self *SGuest) StartInstanceSnapshotAndCloneTask(
ctx context.Context, userCred mcclient.TokenCredential, newlyGuestName string,
pendingUsage *SQuota, instanceSnapshot *SInstanceSnapshot, data *jsonutils.JSONDict) error {
pendingUsage *SQuota, pendingRegionUsage *SRegionQuota, instanceSnapshot *SInstanceSnapshot, data *jsonutils.JSONDict) error {
params := jsonutils.NewDict()
params.Set("guest_params", data)
if task, err := taskman.TaskManager.NewTask(
ctx, "InstanceSnapshotAndCloneTask", instanceSnapshot, userCred, params, "", "", pendingUsage); err != nil {
ctx, "InstanceSnapshotAndCloneTask", instanceSnapshot, userCred, params, "", "", pendingUsage, pendingRegionUsage); err != nil {
return err
} else {
self.SetStatus(userCred, api.VM_START_INSTANCE_SNAPSHOT, "instance snapshot")
+2 -1
View File
@@ -27,6 +27,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type IGuestScheduleDriver interface {
@@ -41,7 +42,7 @@ type IGuestDriver interface {
GetHypervisor() string
GetProvider() string
GetQuotaPlatformID() []string
GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) SComputeResourceKeys
GetMaxVCpuCount() int
GetMaxVMemSizeGB() int
+15 -17
View File
@@ -472,26 +472,24 @@ func (self *SGuestnetwork) Detach(ctx context.Context, userCred mcclient.TokenCr
return db.DetachJoint(ctx, userCred, self)
}
func totalGuestNicCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, rangeObj db.IStandaloneModel, includeSystem bool) GuestnicsCount {
func totalGuestNicCount(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
rangeObjs []db.IStandaloneModel,
includeSystem bool,
providers []string,
brands []string,
cloudEnv string,
) GuestnicsCount {
guests := GuestManager.Query().SubQuery()
hosts := HostManager.Query().SubQuery()
guestnics := GuestnetworkManager.Query().SubQuery()
q := guestnics.Query().Join(guests, sqlchemy.Equals(guests.Field("id"), guestnics.Field("guest_id")))
if rangeObj != nil {
if rangeObj.Keyword() == "zone" {
hosts := HostManager.Query().SubQuery()
q = q.Join(hosts, sqlchemy.Equals(guests.Field("host_id"), hosts.Field("id"))).Filter(sqlchemy.Equals(hosts.Field("zone_id"), rangeObj.GetId()))
} else if rangeObj.Keyword() == "wire" {
hosts := HostManager.Query().SubQuery()
hostwires := HostwireManager.Query().SubQuery()
q = q.Join(hosts, sqlchemy.Equals(guests.Field("host_id"), hosts.Field("id"))).Join(hostwires, sqlchemy.Equals(hosts.Field("id"), hostwires.Field("host_id"))).Filter(sqlchemy.Equals(hostwires.Field("wire_id"), rangeObj.GetId()))
} else if rangeObj.Keyword() == "host" {
q := guestnics.Query()
q = q.Join(guests, sqlchemy.Equals(guests.Field("id"), guestnics.Field("guest_id")))
q = q.Join(hosts, sqlchemy.Equals(guests.Field("host_id"), hosts.Field("id")))
} else if rangeObj.Keyword() == "vcenter" {
} else if rangeObj.Keyword() == "schedtag" {
}
}
q = CloudProviderFilter(q, hosts.Field("manager_id"), providers, brands, cloudEnv)
q = rangeObjectsFilter(q, rangeObjs, nil, hosts.Field("zone_id"), hosts.Field("manager_id"))
switch scope {
case rbacutils.ScopeSystem:
+183 -73
View File
@@ -29,7 +29,7 @@ import (
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/compare"
errors_aggr "yunion.io/x/pkg/util/errors"
// errors_aggr "yunion.io/x/pkg/util/errors"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/util/osprofile"
"yunion.io/x/pkg/util/regutils"
@@ -845,6 +845,37 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
return self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
func serverCreateInput2ComputeQuotaKeys(input api.ServerCreateInput, ownerId mcclient.IIdentityProvider) SComputeResourceKeys {
// input.Hypervisor must be set
keys := GetDriver(input.Hypervisor).GetComputeQuotaKeys(
rbacutils.ScopeProject,
ownerId,
"",
)
if len(input.PreferHost) > 0 {
hostObj, _ := HostManager.FetchById(input.PreferHost)
host := hostObj.(*SHost)
zone := host.GetZone()
keys.ZoneId = zone.Id
keys.RegionId = zone.CloudregionId
} else if len(input.PreferZone) > 0 {
zoneObj, _ := ZoneManager.FetchById(input.PreferZone)
zone := zoneObj.(*SZone)
keys.ZoneId = zone.Id
keys.RegionId = zone.CloudregionId
} else if len(input.PreferWire) > 0 {
wireObj, _ := WireManager.FetchById(input.PreferWire)
wire := wireObj.(*SWire)
zone := wire.GetZone()
keys.ZoneId = zone.Id
keys.RegionId = zone.CloudregionId
} else if len(input.PreferRegion) > 0 {
regionObj, _ := CloudregionManager.FetchById(input.PreferRegion)
keys.RegionId = regionObj.GetId()
}
return keys
}
func (manager *SGuestManager) BatchPreValidate(
ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
query jsonutils.JSONObject, data *jsonutils.JSONDict, count int,
@@ -853,8 +884,8 @@ func (manager *SGuestManager) BatchPreValidate(
if err != nil {
return nil, err
}
if !input.IsSystem {
reqQuota, err := manager.checkCreateQuota(ctx, userCred, ownerId, input, input.Backup, count)
if input.IsSystem == nil || *input.IsSystem == false {
reqQuota, reqRegionQuota, err := manager.checkCreateQuota(ctx, userCred, ownerId, *input, input.Backup, count)
if err != nil {
return nil, err
}
@@ -862,20 +893,22 @@ func (manager *SGuestManager) BatchPreValidate(
Cpu: reqQuota.Cpu / count,
Memory: reqQuota.Memory / count,
Storage: reqQuota.Storage / count,
Port: reqQuota.Port / count,
Eport: reqQuota.Eport / count,
Bw: reqQuota.Bw / count,
Ebw: reqQuota.Ebw / count,
IsolatedDevice: reqQuota.IsolatedDevice / count,
Eip: reqQuota.Eip / count,
}
quotaPlatform := make([]string, 0)
if len(input.Hypervisor) > 0 {
quotaPlatform = GetDriver(input.Hypervisor).GetQuotaPlatformID()
regionQuota := &SRegionQuota{
Port: reqRegionQuota.Port / count,
Eport: reqRegionQuota.Eport / count,
Bw: reqRegionQuota.Bw / count,
Ebw: reqRegionQuota.Ebw / count,
Eip: reqRegionQuota.Eip / count,
}
keys := serverCreateInput2ComputeQuotaKeys(*input, ownerId)
regionKeys := keys.SRegionalCloudResourceKeys
quota.SetKeys(keys)
regionQuota.SetKeys(regionKeys)
return func() {
QuotaManager.CancelPendingUsage(
ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatform, quota, quota)
QuotaManager.CancelPendingUsage(ctx, userCred, quota, quota)
RegionQuotaManager.CancelPendingUsage(ctx, userCred, regionQuota, regionQuota)
}, nil
}
return nil, nil
@@ -1243,15 +1276,10 @@ func (manager *SGuestManager) validateCreateData(
}
}
data, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.JSON(input))
input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
if err != nil {
return nil, err
}
if err := data.Unmarshal(input); err != nil {
return nil, err
}
log.Debugf("Create data: %s", data)
if err := userdata.ValidateUserdata(input.UserData); err != nil {
return nil, httperrors.NewInputParameterError("Invalid userdata: %v", err)
@@ -1276,8 +1304,8 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
if err != nil {
return nil, err
}
if !input.IsSystem {
_, err = manager.checkCreateQuota(ctx, userCred, ownerId, input, input.Backup, 1)
if input.IsSystem == nil || !(*input.IsSystem) {
_, _, err = manager.checkCreateQuota(ctx, userCred, ownerId, *input, input.Backup, 1)
if err != nil {
return nil, err
}
@@ -1331,20 +1359,23 @@ func (self *SGuest) PostUpdate(ctx context.Context, userCred mcclient.TokenCrede
}
func (manager *SGuestManager) checkCreateQuota(
ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
input *api.ServerCreateInput, hasBackup bool, count int) (*SQuota, error) {
req := getGuestResourceRequirements(ctx, userCred, input, count, hasBackup)
quotaPlatform := make([]string, 0)
if len(input.Hypervisor) > 0 {
quotaPlatform = GetDriver(input.Hypervisor).GetQuotaPlatformID()
}
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, rbacutils.ScopeProject, ownerId, quotaPlatform, &req)
ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
input api.ServerCreateInput,
hasBackup bool,
count int,
) (*SQuota, *SRegionQuota, error) {
req, regionReq := getGuestResourceRequirements(ctx, userCred, input, ownerId, count, hasBackup)
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, &req)
if err != nil {
return nil, httperrors.NewOutOfQuotaError(err.Error())
} else {
return &req, nil
return nil, nil, err
}
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &regionReq)
if err != nil {
return nil, nil, err
}
return &req, &regionReq, nil
}
func (self *SGuest) checkUpdateQuota(ctx context.Context, userCred mcclient.TokenCredential, vcpuCount int, vmemSize int) error {
@@ -1358,13 +1389,24 @@ func (self *SGuest) checkUpdateQuota(ctx context.Context, userCred mcclient.Toke
req.Memory = vmemSize - self.VmemSize
}
quotaPlatform := self.GetQuotaPlatformID()
_, err := QuotaManager.CheckQuota(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, &req)
keys, err := self.GetQuotaKeys()
if err != nil {
return errors.Wrap(err, "self.GetQuotaKeys")
}
req.SetKeys(keys)
err = QuotaManager.CheckQuota(ctx, &req)
return err
}
func getGuestResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput, count int, hasBackup bool) SQuota {
func getGuestResourceRequirements(
ctx context.Context,
userCred mcclient.TokenCredential,
input api.ServerCreateInput,
ownerId mcclient.IIdentityProvider,
count int,
hasBackup bool,
) (SQuota, SRegionQuota) {
vcpuCount := input.VcpuCount
if vcpuCount == 0 {
vcpuCount = 1
@@ -1405,17 +1447,23 @@ func getGuestResourceRequirements(ctx context.Context, userCred mcclient.TokenCr
eipCnt = 1
}
return SQuota{
req := SQuota{
Cpu: int(vcpuCount) * count,
Memory: int(vmemSize) * count,
Storage: diskSize * count,
Port: iNicCnt * count,
Eport: eNicCnt * count,
Bw: iBw * count,
Ebw: eBw * count,
IsolatedDevice: devCount * count,
Eip: eipCnt * count,
}
regionReq := SRegionQuota{
Port: iNicCnt * count,
Eport: eNicCnt * count,
Bw: iBw * count,
Ebw: eBw * count,
Eip: eipCnt * count,
}
keys := serverCreateInput2ComputeQuotaKeys(input, ownerId)
req.SetKeys(keys)
regionReq.SetKeys(keys.SRegionalCloudResourceKeys)
return req, regionReq
}
func (guest *SGuest) getGuestBackupResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential) SQuota {
@@ -1503,14 +1551,14 @@ func (manager *SGuestManager) SetPropertiesWithInstanceSnapshot(
}
}
func (manager *SGuestManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
input := new(api.ServerCreateInput)
data.Unmarshal(input)
func (manager *SGuestManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
input := api.ServerCreateInput{}
data.Unmarshal(&input)
if len(input.InstanceSnapshotId) > 0 {
manager.SetPropertiesWithInstanceSnapshot(ctx, userCred, input.InstanceSnapshotId, items)
}
pendingUsage := getGuestResourceRequirements(ctx, userCred, input, len(items), input.Backup)
RunBatchCreateTask(ctx, items, userCred, data, pendingUsage, "GuestBatchCreateTask", input.ParentTaskId)
pendingUsage, pendingRegionUsage := getGuestResourceRequirements(ctx, userCred, input, ownerId, len(items), input.Backup)
RunBatchCreateTask(ctx, items, userCred, data, pendingUsage, pendingRegionUsage, "GuestBatchCreateTask", input.ParentTaskId)
}
func (guest *SGuest) GetGroups() []SGroupguest {
@@ -2383,12 +2431,12 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
func (manager *SGuestManager) TotalCount(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
rangeObj db.IStandaloneModel,
rangeObjs []db.IStandaloneModel,
status []string, hypervisors []string,
includeSystem bool, pendingDelete bool,
hostTypes []string, resourceTypes []string, providers []string, brands []string, cloudEnv string,
) SGuestCountStat {
return totalGuestResourceCount(scope, ownerId, rangeObj, status, hypervisors, includeSystem, pendingDelete, hostTypes, resourceTypes, providers, brands, cloudEnv)
return totalGuestResourceCount(scope, ownerId, rangeObjs, status, hypervisors, includeSystem, pendingDelete, hostTypes, resourceTypes, providers, brands, cloudEnv)
}
func (self *SGuest) detachNetworks(ctx context.Context, userCred mcclient.TokenCredential, gns []SGuestnetwork, reserve bool, deploy bool) error {
@@ -2499,7 +2547,7 @@ func (self *SGuest) attach2NetworkOnce(ctx context.Context, userCred mcclient.To
network.updateGuestNetmap(guestnic)
bwLimit = guestnic.getBandwidth()
if pendingUsage != nil && len(teamWithMac) == 0 {
cancelUsage := SQuota{}
cancelUsage := SRegionQuota{}
if network.IsExitNetwork() {
cancelUsage.Eport = 1
cancelUsage.Ebw = bwLimit
@@ -2507,8 +2555,12 @@ func (self *SGuest) attach2NetworkOnce(ctx context.Context, userCred mcclient.To
cancelUsage.Port = 1
cancelUsage.Bw = bwLimit
}
quotaPlatform := self.GetQuotaPlatformID()
err = QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, pendingUsage, &cancelUsage)
keys, err := self.GetRegionalQuotaKeys()
if err != nil {
log.Warningf("self.GetRegionalQuotaKeys fail %s", err)
}
cancelUsage.SetKeys(keys)
err = QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
if err != nil {
log.Warningf("QuotaManager.CancelPendingUsage fail %s", err)
}
@@ -2814,14 +2866,14 @@ func (self *SGuest) SyncVMDisks(ctx context.Context, userCred mcclient.TokenCred
return result
}
func filterGuestByRange(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string, brands []string, cloudEnv string) *sqlchemy.SQuery {
func filterGuestByRange(q *sqlchemy.SQuery, rangeObjs []db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string, brands []string, cloudEnv string) *sqlchemy.SQuery {
hosts := HostManager.Query().SubQuery()
q = q.Join(hosts, sqlchemy.Equals(hosts.Field("id"), q.Field("host_id")))
//q = q.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
// q = q.Filter(sqlchemy.Equals(hosts.Field("host_status"), HOST_ONLINE))
q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObj)
q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObjs)
return q
}
@@ -2840,7 +2892,7 @@ type SGuestCountStat struct {
func totalGuestResourceCount(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
rangeObj db.IStandaloneModel,
rangeObjs []db.IStandaloneModel,
status []string,
hypervisors []string,
includeSystem bool,
@@ -2899,7 +2951,7 @@ func totalGuestResourceCount(
q = q.LeftJoin(isoDevSubQuery, sqlchemy.Equals(isoDevSubQuery.Field("guest_id"), guests.Field("id")))
q = filterGuestByRange(q, rangeObj, hostTypes, resourceTypes, providers, brands, cloudEnv)
q = filterGuestByRange(q, rangeObjs, hostTypes, resourceTypes, providers, brands, cloudEnv)
switch scope {
case rbacutils.ScopeSystem:
@@ -3007,7 +3059,7 @@ func (self *SGuest) attach2NetworkDesc(
}
errs = append(errs, err)
}
return nil, errors_aggr.NewAggregate(errs)
return nil, errors.NewAggregate(errs)
} else {
netConfig.Network = ""
return self.attach2RandomNetwork(ctx, userCred, host, netConfig, pendingUsage)
@@ -3101,11 +3153,14 @@ func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.T
return nil, err
}
quotaPlatform := self.GetQuotaPlatformID()
cancelUsage := SQuota{}
cancelUsage.Storage = disk.DiskSize
err = QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, pendingUsage, &cancelUsage)
keys, err := self.GetQuotaKeys()
if err != nil {
return nil, err
}
cancelUsage.SetKeys(keys)
err = QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
return disk, nil
}
@@ -3188,10 +3243,13 @@ func (self *SGuest) createIsolatedDeviceOnHost(ctx context.Context, userCred mcc
return err
}
quotaPlatform := self.GetQuotaPlatformID()
cancelUsage := SQuota{IsolatedDevice: 1}
err = QuotaManager.CancelPendingUsage(ctx, userCred, rbacutils.ScopeProject, self.GetOwnerId(), quotaPlatform, pendingUsage, &cancelUsage)
keys, err := self.GetQuotaKeys()
if err != nil {
return err
}
cancelUsage.SetKeys(keys)
err = QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
return err
}
@@ -4619,7 +4677,9 @@ func (self *SGuest) ToCreateInput(userCred mcclient.TokenCredential) *api.Server
userInput.KeypairId = genInput.KeypairId
userInput.EipBw = genInput.EipBw
userInput.EipChargeType = genInput.EipChargeType
userInput.Project = genInput.Project
// cloned server should belongs to the project creating it
userInput.Project = userCred.GetProjectId()
userInput.Domain = userCred.GetProjectDomainId()
userInput.Secgroups = []string{}
secgroups := self.GetSecgroups()
for _, secgroup := range secgroups {
@@ -4658,7 +4718,7 @@ func (self *SGuest) toCreateInput() *api.ServerCreateInput {
*r.DisableDelete = self.DisableDelete.Bool()
r.ShutdownBehavior = self.ShutdownBehavior
// ignore r.DeployConfigs
r.IsSystem = self.IsSystem
r.IsSystem = &self.IsSystem
r.SecgroupId = self.SecgrpId
r.ServerConfigs = new(api.ServerConfigs)
@@ -4834,22 +4894,30 @@ func (self *SGuest) GetDiskSnapshotsNotInInstanceSnapshots() ([]SSnapshot, error
return snapshots, nil
}
func (self *SGuest) getGuestUsage(guestCount int) (*SQuota, error) {
usage := new(SQuota)
func (self *SGuest) getGuestUsage(guestCount int) (SQuota, SRegionQuota, error) {
usage := SQuota{}
regionUsage := SRegionQuota{}
usage.Cpu = int(self.VcpuCount) * guestCount
usage.Memory = int(self.VmemSize * guestCount)
diskSize := self.getDiskSize()
if diskSize < 0 {
return nil, httperrors.NewInternalServerError("fetch disk size failed")
return usage, regionUsage, httperrors.NewInternalServerError("fetch disk size failed")
}
usage.Storage = self.getDiskSize() * guestCount
netCount, err := self.NetworkCount()
if err != nil && err != sql.ErrNoRows {
return nil, err
if err != nil && errors.Cause(err) != sql.ErrNoRows {
return usage, regionUsage, err
}
usage.Port = netCount
usage.Bw = self.getBandwidth(false)
return usage, err
regionUsage.Port = netCount
regionUsage.Bw = self.getBandwidth(false)
eip, err := self.GetEip()
if err != nil && errors.Cause(err) != sql.ErrNoRows {
return usage, regionUsage, err
}
if eip != nil {
regionUsage.Eip = 1
}
return usage, regionUsage, nil
}
func (self *SGuestManager) checkGuestImage(ctx context.Context, input *api.ServerCreateInput) error {
@@ -4918,3 +4986,45 @@ func (self *SGuest) GetDiskIndex(diskId string) int8 {
}
return -1
}
func (guest *SGuest) GetRegionalQuotaKeys() (quotas.IQuotaKeys, error) {
host := guest.GetHost()
if host == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid host")
}
provider := host.GetCloudprovider()
if provider == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid manager")
}
region := host.GetRegion()
if region == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid region")
}
return fetchRegionalQuotaKeys(rbacutils.ScopeProject, guest.GetOwnerId(), region, provider), nil
}
func (guest *SGuest) GetQuotaKeys() (quotas.IQuotaKeys, error) {
host := guest.GetHost()
if host == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid host")
}
provider := host.GetCloudprovider()
if provider == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid manager")
}
zone := host.GetZone()
if zone == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid zone")
}
hypervisor := guest.Hypervisor
if !utils.IsInStringArray(hypervisor, api.ONECLOUD_HYPERVISORS) {
hypervisor = ""
}
return fetchComputeQuotaKeys(
rbacutils.ScopeProject,
guest.GetOwnerId(),
zone,
provider,
hypervisor,
), nil
}
+2 -1
View File
@@ -38,6 +38,7 @@ func RunBatchCreateTask(
userCred mcclient.TokenCredential,
data jsonutils.JSONObject,
pendingUsage SQuota,
pendingRegionUsage SRegionQuota,
taskName string,
parentTaskId string,
) {
@@ -46,7 +47,7 @@ func RunBatchCreateTask(
taskItems[i] = t.(db.IStandaloneModel)
}
params := data.(*jsonutils.JSONDict)
task, err := taskman.TaskManager.NewParallelTask(ctx, taskName, taskItems, userCred, params, parentTaskId, "", &pendingUsage)
task, err := taskman.TaskManager.NewParallelTask(ctx, taskName, taskItems, userCred, params, parentTaskId, "", &pendingUsage, &pendingRegionUsage)
if err != nil {
log.Errorf("%s newTask error %s", taskName, err)
} else {
+30 -14
View File
@@ -36,6 +36,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/appsrv"
@@ -2027,7 +2028,7 @@ func (manager *SHostManager) FetchHostById(hostId string) *SHost {
func (manager *SHostManager) totalCountQ(
userCred mcclient.IIdentityProvider,
rangeObj db.IStandaloneModel,
rangeObjs []db.IStandaloneModel,
hostStatus, status string,
hostTypes []string,
resourceTypes []string,
@@ -2035,15 +2036,6 @@ func (manager *SHostManager) totalCountQ(
enabled, isBaremetal tristate.TriState,
) *sqlchemy.SQuery {
hosts := manager.Query().SubQuery()
/*
MemSize int
MemReserved int
MemCmtbound float32
CpuCount int8
CpuReserved int8
CpuCmtbound float32
StorageSize int
*/
q := hosts.Query(
hosts.Field("mem_size"),
hosts.Field("mem_reserved"),
@@ -2073,7 +2065,7 @@ func (manager *SHostManager) totalCountQ(
}
q = q.Filter(cond(hosts.Field("is_baremetal")))
}
q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObj)
q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObjs)
return q
}
@@ -2152,14 +2144,28 @@ func (manager *SHostManager) calculateCount(q *sqlchemy.SQuery) HostsCountStat {
func (manager *SHostManager) TotalCount(
userCred mcclient.IIdentityProvider,
rangeObj db.IStandaloneModel,
rangeObjs []db.IStandaloneModel,
hostStatus, status string,
hostTypes []string,
resourceTypes []string,
providers []string, brands []string, cloudEnv string,
enabled, isBaremetal tristate.TriState,
) HostsCountStat {
return manager.calculateCount(manager.totalCountQ(userCred, rangeObj, hostStatus, status, hostTypes, resourceTypes, providers, brands, cloudEnv, enabled, isBaremetal))
return manager.calculateCount(
manager.totalCountQ(
userCred,
rangeObjs,
hostStatus,
status,
hostTypes,
resourceTypes,
providers,
brands,
cloudEnv,
enabled,
isBaremetal,
),
)
}
/*
@@ -2779,7 +2785,17 @@ func (manager *SHostManager) ValidateCreateData(ctx context.Context, userCred mc
}
}
return manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.EnabledStatusStandaloneResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal EnabledStatusStandaloneCreateInput fail %s", err)
}
input, err = manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (self *SHost) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
+12 -1
View File
@@ -22,6 +22,7 @@ import (
"yunion.io/x/pkg/tristate"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
@@ -135,7 +136,17 @@ func (manager *SHoststorageManager) ValidateCreateData(ctx context.Context, user
return nil, err
}
return manager.SJointResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.JoinResourceBaseCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal JoinResourceBaseCreateInput fail %s", err)
}
input, err = manager.SJointResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (self *SHoststorage) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
+7 -3
View File
@@ -133,10 +133,14 @@ func (self *SInstanceSnapshot) GetExtraDetails(ctx context.Context, userCred mcc
extra = self.getMoreDetails(userCred, extra)
return extra, nil
}
func (self *SInstanceSnapshot) StartCreateInstanceSnapshotTask(
ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
pendingUsage quotas.IQuota, parentTaskId string) error {
func (self *SInstanceSnapshot) StartCreateInstanceSnapshotTask(
ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
pendingUsage quotas.IQuota,
parentTaskId string,
) error {
if task, err := taskman.TaskManager.NewTask(
ctx, "InstanceSnapshotCreateTask", self, userCred, nil, parentTaskId, "", pendingUsage); err != nil {
return err
+51 -9
View File
@@ -26,6 +26,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -117,7 +118,18 @@ func (manager *SIsolatedDeviceManager) ValidateCreateData(ctx context.Context, u
name = fmt.Sprintf("dev_%s_%d", host.GetName(), time.Now().UnixNano())
data.Set("name", jsonutils.NewString(name))
}
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneRes ourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (self *SIsolatedDevice) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
@@ -437,8 +449,9 @@ func (manager *SIsolatedDeviceManager) ReleaseDevicesOfGuest(ctx context.Context
func (manager *SIsolatedDeviceManager) totalCountQ(
devType []string, hostTypes []string,
resourceTypes []string, providers []string, brands []string, cloudEnv string,
rangeObj db.IStandaloneModel,
resourceTypes []string,
providers []string, brands []string, cloudEnv string,
rangeObjs []db.IStandaloneModel,
) *sqlchemy.SQuery {
hosts := HostManager.Query().SubQuery()
devs := manager.Query().SubQuery()
@@ -447,7 +460,7 @@ func (manager *SIsolatedDeviceManager) totalCountQ(
if len(devType) != 0 {
q = q.Filter(sqlchemy.In(devs.Field("dev_type"), devType))
}
return AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObj)
return AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObjs)
}
type IsolatedDeviceCountStat struct {
@@ -455,17 +468,46 @@ type IsolatedDeviceCountStat struct {
Gpus int
}
func (manager *SIsolatedDeviceManager) totalCount(devType, hostTypes []string, resourceTypes []string, providers []string, brands []string, cloudEnv string, rangeObj db.IStandaloneModel) (int, error) {
return manager.totalCountQ(devType, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObj).CountWithError()
func (manager *SIsolatedDeviceManager) totalCount(
devType,
hostTypes []string,
resourceTypes []string,
providers []string,
brands []string,
cloudEnv string,
rangeObjs []db.IStandaloneModel,
) (int, error) {
return manager.totalCountQ(
devType,
hostTypes,
resourceTypes,
providers,
brands,
cloudEnv,
rangeObjs,
).CountWithError()
}
func (manager *SIsolatedDeviceManager) TotalCount(hostType []string, resourceTypes []string, providers []string, brands []string, cloudEnv string, rangeObj db.IStandaloneModel) (IsolatedDeviceCountStat, error) {
func (manager *SIsolatedDeviceManager) TotalCount(
hostType []string,
resourceTypes []string,
providers []string,
brands []string,
cloudEnv string,
rangeObjs []db.IStandaloneModel,
) (IsolatedDeviceCountStat, error) {
stat := IsolatedDeviceCountStat{}
devCnt, err := manager.totalCount(nil, hostType, resourceTypes, providers, brands, cloudEnv, rangeObj)
devCnt, err := manager.totalCount(
nil, hostType, resourceTypes,
providers, brands, cloudEnv,
rangeObjs)
if err != nil {
return stat, err
}
gpuCnt, err := manager.totalCount(VALID_GPU_TYPES, hostType, resourceTypes, providers, brands, cloudEnv, rangeObj)
gpuCnt, err := manager.totalCount(
VALID_GPU_TYPES, hostType, resourceTypes,
providers, brands, cloudEnv,
rangeObjs)
if err != nil {
return stat, err
}
+12 -1
View File
@@ -24,6 +24,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -185,7 +186,17 @@ func (manager *SKeypairManager) ValidateCreateData(ctx context.Context, userCred
data.Set("scheme", jsonutils.NewString(scheme))
data.Set("owner_id", jsonutils.NewString(userCred.GetUserId()))
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneRes ourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (self *SKeypair) ValidateDeleteCondition(ctx context.Context) error {
+10 -1
View File
@@ -30,6 +30,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
@@ -180,9 +181,17 @@ func (man *SLoadbalancerAclManager) ValidateCreateData(ctx context.Context, user
if err != nil {
return nil, err
}
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
managerIdV := validators.NewModelIdOrNameValidator("manager", "cloudprovider", ownerId)
managerIdV.Optional(true)
+13 -1
View File
@@ -28,6 +28,7 @@ import (
"yunion.io/x/pkg/gotypes"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
@@ -364,7 +365,18 @@ func (man *SLoadbalancerAgentManager) ValidateCreateData(ctx context.Context, us
otherCluster.Name, otherCluster.Id, vrrpRouterId)
}
}
return man.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = man.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (man *SLoadbalancerAgentManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -106,9 +107,18 @@ func (man *SLoadbalancerBackendGroupManager) ValidateCreateData(ctx context.Cont
if err != nil {
return nil, err
}
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
lb := lbV.Model.(*SLoadbalancer)
data.Set("manager_id", jsonutils.NewString(lb.ManagerId))
data.Set("cloudregion_id", jsonutils.NewString(lb.CloudregionId))
+11 -1
View File
@@ -26,6 +26,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -158,9 +159,18 @@ func (man *SLoadbalancerBackendManager) ValidateCreateData(ctx context.Context,
backendGroup := backendGroupV.Model.(*SLoadbalancerBackendGroup)
lb := backendGroup.GetLoadbalancer()
var backendModel db.IModel
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
region := lb.GetRegion()
if region == nil {
return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer %s", lb.Name)
+10 -1
View File
@@ -24,6 +24,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -134,9 +135,17 @@ func (man *SCachedLoadbalancerAclManager) ValidateCreateData(ctx context.Context
data.Set("manager_id", jsonutils.NewString(provider.Id))
name, _ := db.GenerateName(man, ownerId, aclV.Model.GetName())
data.Set("name", jsonutils.NewString(name))
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -165,9 +166,17 @@ func (man *SCachedLoadbalancerCertificateManager) ValidateCreateData(ctx context
data.Set("manager_id", jsonutils.NewString(provider.Id))
name, _ := db.GenerateName(man, ownerId, certificateV.Model.GetName())
data.Set("name", jsonutils.NewString(name))
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
+10 -1
View File
@@ -29,6 +29,7 @@ import (
"yunion.io/x/log"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
@@ -265,9 +266,17 @@ func (man *SLoadbalancerCertificateManager) ValidateCreateData(ctx context.Conte
if err != nil {
return nil, err
}
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
data.Remove("cloudregion_id")
data.Remove("manager_id")
+24 -13
View File
@@ -17,12 +17,12 @@ package models
import (
"context"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -112,7 +112,18 @@ func (man *SLoadbalancerClusterManager) ValidateCreateData(ctx context.Context,
wire.ZoneId, zone.Name, zone.Id)
}
}
return man.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = man.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (lbc *SLoadbalancerCluster) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
@@ -177,19 +188,19 @@ func (lbc *SLoadbalancerCluster) CustomizeDelete(ctx context.Context, userCred m
lbagents := []SLoadbalancerAgent{}
q := LoadbalancerAgentManager.Query().Equals("cluster_id", lbc.Id)
if err := db.FetchModelObjects(LoadbalancerAgentManager, q, &lbagents); err != nil {
return errors.WithMessagef(err, "lbcluster %s(%s): find lbagents", lbc.Name, lbc.Id)
return errors.Wrapf(err, "lbcluster %s(%s): find lbagents", lbc.Name, lbc.Id)
}
for i := range lbagents {
lbagent := &lbagents[i]
if err := lbagent.ValidateDeleteCondition(ctx); err != nil {
return errors.WithMessagef(err, "lbagent %s(%s): validate delete", lbagent.Name, lbagent.Id)
return errors.Wrapf(err, "lbagent %s(%s): validate delete", lbagent.Name, lbagent.Id)
}
if err := lbagent.CustomizeDelete(ctx, userCred, query, data); err != nil {
return errors.WithMessagef(err, "lbagent %s(%s): customize delete", lbagent.Name, lbagent.Id)
return errors.Wrapf(err, "lbagent %s(%s): customize delete", lbagent.Name, lbagent.Id)
}
lbagent.PreDelete(ctx, userCred)
if err := lbagent.Delete(ctx, userCred); err != nil {
return errors.WithMessagef(err, "lbagent %s(%s): delete", lbagent.Name, lbagent.Id)
return errors.Wrapf(err, "lbagent %s(%s): delete", lbagent.Name, lbagent.Id)
}
lbagent.PostDelete(ctx, userCred)
}
@@ -248,7 +259,7 @@ func (man *SLoadbalancerClusterManager) InitializeData() error {
IsNullOrEmpty("manager_id").
IsNullOrEmpty("cluster_id")
if err := db.FetchModelObjects(LoadbalancerManager, lbQ, &lbs); err != nil {
return errors.WithMessage(err, "find lb with empty cluster_id")
return errors.Wrap(err, "find lb with empty cluster_id")
}
// create 1 cluster for each zone
@@ -267,13 +278,13 @@ func (man *SLoadbalancerClusterManager) InitializeData() error {
if len(lbcs) == 0 {
m, err := db.NewModelObject(man)
if err != nil {
return errors.WithMessage(err, "new model object")
return errors.Wrap(err, "new model object")
}
lbc = m.(*SLoadbalancerCluster)
lbc.Name = "auto-lbc-" + zoneId
lbc.ZoneId = zoneId
if err := man.TableSpec().Insert(lbc); err != nil {
return errors.WithMessage(err, "insert lbcluster model")
return errors.Wrap(err, "insert lbcluster model")
}
} else {
if len(lbcs) > 1 {
@@ -287,7 +298,7 @@ func (man *SLoadbalancerClusterManager) InitializeData() error {
lb.ClusterId = lbc.Id
return nil
}); err != nil {
return errors.WithMessagef(err, "lb %s(%s): assign cluster: %s(%s)", lb.Name, lb.Name, lbc.Name, lbc.Id)
return errors.Wrapf(err, "lb %s(%s): assign cluster: %s(%s)", lb.Name, lb.Name, lbc.Name, lbc.Id)
}
}
@@ -301,7 +312,7 @@ func (man *SLoadbalancerClusterManager) InitializeData() error {
q := LoadbalancerAgentManager.Query().
IsNullOrEmpty("cluster_id")
if err := db.FetchModelObjects(LoadbalancerAgentManager, q, &lbagents); err != nil {
return errors.WithMessage(err, "find lbagents with empty cluster_id")
return errors.Wrap(err, "find lbagents with empty cluster_id")
}
for i := range lbagents {
lbagent := &lbagents[i]
@@ -309,7 +320,7 @@ func (man *SLoadbalancerClusterManager) InitializeData() error {
lbagent.ClusterId = lbc.Id
return nil
}); err != nil {
return errors.WithMessagef(err, "lbagent %s(%s): assign cluster: %s(%s)",
return errors.Wrapf(err, "lbagent %s(%s): assign cluster: %s(%s)",
lbagent.Name, lbagent.Id, lbc.Name, lbc.Id)
}
}
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -396,9 +397,16 @@ func (man *SLoadbalancerListenerRuleManager) ListItemFilter(ctx context.Context,
}
func (man *SLoadbalancerListenerRuleManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
listenerV := validators.NewModelIdOrNameValidator("listener", "loadbalancerlistener", ownerId)
backendGroupV := validators.NewModelIdOrNameValidator("backend_group", "loadbalancerbackendgroup", ownerId)
+9 -1
View File
@@ -26,6 +26,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -225,9 +226,16 @@ func (man *SLoadbalancerListenerManager) ValidateCreateData(ctx context.Context,
return nil, err
}
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
lb := lbV.Model.(*SLoadbalancer)
region := lb.GetRegion()
+12 -2
View File
@@ -218,10 +218,18 @@ func (ln *SLoadbalancerNetwork) GetCustomizeColumns(ctx context.Context, userCre
return db.JointModelExtra(ln, extra)
}
func totalLBNicCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) (int, error) {
func totalLBNicCount(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
rangeObjs []db.IStandaloneModel,
providers []string,
brands []string,
cloudEnv string,
) (int, error) {
lbs := LoadbalancerManager.Query().SubQuery()
lbnics := LoadbalancernetworkManager.Query().SubQuery()
q := lbnics.Query().Join(lbs, sqlchemy.Equals(lbs.Field("id"), lbnics.Field("loadbalancer_id")))
q := lbnics.Query()
q = q.Join(lbs, sqlchemy.Equals(lbs.Field("id"), lbnics.Field("loadbalancer_id")))
switch scope {
case rbacutils.ScopeSystem:
// do nothing
@@ -230,5 +238,7 @@ func totalLBNicCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvi
case rbacutils.ScopeProject:
q = q.Filter(sqlchemy.Equals(lbs.Field("tenant_id"), ownerId.GetProjectId()))
}
q = rangeObjectsFilter(q, rangeObjs, nil, lbs.Field("zone_id"), lbs.Field("manager_id"))
q = CloudProviderFilter(q, lbs.Field("manager_id"), providers, brands, cloudEnv)
return q.CountWithError()
}
+23 -1
View File
@@ -26,6 +26,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -34,6 +35,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SLoadbalancerManager struct {
@@ -144,9 +146,16 @@ func (man *SLoadbalancerManager) ValidateCreateData(ctx context.Context, userCre
return nil, httperrors.NewBadRequestError("cannot find region info")
}
if _, err := man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data); err != nil {
input := apis.VirtualResourceCreateInput{}
err := data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
ctx = context.WithValue(ctx, "ownerId", ownerId)
return region.GetDriver().ValidateCreateLoadbalancerData(ctx, userCred, data)
@@ -861,3 +870,16 @@ func (man *SLoadbalancerManager) getLoadbalancer(lbId string) (*SLoadbalancer, e
}
return lb, nil
}
func (man *SLoadbalancerManager) TotalCount(
scope rbacutils.TRbacScope,
ownerId mcclient.IIdentityProvider,
rangeObjs []db.IStandaloneModel,
providers []string, brands []string, cloudEnv string,
) (int, error) {
q := man.Query()
q = scopeOwnerIdFilter(q, scope, ownerId)
q = CloudProviderFilter(q, q.Field("manager_id"), providers, brands, cloudEnv)
q = rangeObjectsFilter(q, rangeObjs, nil, q.Field("zone_id"), q.Field("manager_id"))
return q.CountWithError()
}
+51 -35
View File
@@ -737,7 +737,7 @@ func (manager *SNetworkManager) GetOnPremiseNetworkOfIP(ipAddr string, serverTyp
return nil, sql.ErrNoRows
}
func (manager *SNetworkManager) allNetworksQ(providers []string, brands []string, cloudEnv string, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
func (manager *SNetworkManager) allNetworksQ(providers []string, brands []string, cloudEnv string, rangeObjs []db.IStandaloneModel) *sqlchemy.SQuery {
networks := manager.Query().SubQuery()
hostwires := HostwireManager.Query().SubQuery()
hosts := HostManager.Query().SubQuery()
@@ -748,11 +748,18 @@ func (manager *SNetworkManager) allNetworksQ(providers []string, brands []string
q = q.Filter(sqlchemy.OR(
sqlchemy.Equals(hosts.Field("host_type"), api.HOST_TYPE_BAREMETAL),
sqlchemy.Equals(hosts.Field("host_status"), api.HOST_ONLINE)))
return AttachUsageQuery(q, hosts, nil, nil, providers, brands, cloudEnv, rangeObj)
return AttachUsageQuery(q, hosts, nil, nil, providers, brands, cloudEnv, rangeObjs)
}
func (manager *SNetworkManager) totalPortCountQ(scope rbacutils.TRbacScope, userCred mcclient.IIdentityProvider, providers []string, brands []string, cloudEnv string, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
q := manager.allNetworksQ(providers, brands, cloudEnv, rangeObj)
func (manager *SNetworkManager) totalPortCountQ(
scope rbacutils.TRbacScope,
userCred mcclient.IIdentityProvider,
providers []string,
brands []string,
cloudEnv string,
rangeObjs []db.IStandaloneModel,
) *sqlchemy.SQuery {
q := manager.allNetworksQ(providers, brands, cloudEnv, rangeObjs)
switch scope {
case rbacutils.ScopeSystem:
case rbacutils.ScopeDomain:
@@ -772,10 +779,15 @@ func (manager *SNetworkManager) TotalPortCount(
scope rbacutils.TRbacScope,
userCred mcclient.IIdentityProvider,
providers []string, brands []string, cloudEnv string,
rangeObj db.IStandaloneModel,
rangeObjs []db.IStandaloneModel,
) NetworkPortStat {
nets := make([]SNetwork, 0)
err := manager.totalPortCountQ(scope, userCred, providers, brands, cloudEnv, rangeObj).All(&nets)
err := manager.totalPortCountQ(
scope,
userCred,
providers, brands, cloudEnv,
rangeObjs,
).All(&nets)
if err != nil {
log.Errorf("TotalPortCount: %v", err)
}
@@ -1169,13 +1181,13 @@ func (manager *SNetworkManager) newIfnameHint(hint string) (string, error) {
return r, nil
}
func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.NetworkCreateInput) (*jsonutils.JSONDict, error) {
func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.NetworkCreateInput) (api.NetworkCreateInput, error) {
var err error
var startIp, endIp netutils.IPV4Addr
if len(input.GuestIpPrefix) > 0 {
prefix, err := netutils.NewIPV4Prefix(input.GuestIpPrefix)
if err != nil {
return nil, httperrors.NewInputParameterError("ip_prefix error: %s", err)
return input, httperrors.NewInputParameterError("ip_prefix error: %s", err)
}
iprange := prefix.ToIPRange()
startIp = iprange.StartIp().StepUp()
@@ -1184,11 +1196,11 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
} else {
startIp, err = netutils.NewIPV4Addr(input.GuestIpStart)
if err != nil {
return nil, httperrors.NewInputParameterError("Invalid start ip: %s %s", input.GuestIpStart, err)
return input, httperrors.NewInputParameterError("Invalid start ip: %s %s", input.GuestIpStart, err)
}
endIp, err = netutils.NewIPV4Addr(input.GuestIpEnd)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid end ip: %s %s", input.GuestIpEnd, err)
return input, httperrors.NewInputParameterError("invalid end ip: %s %s", input.GuestIpEnd, err)
}
if startIp > endIp {
tmp := startIp
@@ -1200,7 +1212,7 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
input.GuestIpEnd = endIp.String()
if !isValidMaskLen(input.GuestIpMask) {
return nil, httperrors.NewInputParameterError("Invalid masklen %d", input.GuestIpMask)
return input, httperrors.NewInputParameterError("Invalid masklen %d", input.GuestIpMask)
}
{
@@ -1209,7 +1221,7 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
}
input.IfnameHint, err = manager.newIfnameHint(input.IfnameHint)
if err != nil {
return nil, httperrors.NewBadRequestError("cannot derive valid ifname hint: %v", err)
return input, httperrors.NewBadRequestError("cannot derive valid ifname hint: %v", err)
}
}
@@ -1219,22 +1231,22 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
ipList := strings.Split(ipStr, ",")
for _, ipstr := range ipList {
if !regutils.MatchIPAddr(ipstr) {
return nil, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipstr)
return input, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipstr)
}
}
} else if !regutils.MatchIPAddr(ipStr) {
return nil, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipStr)
return input, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipStr)
}
}
}
nets := manager.getAllNetworks("")
if nets == nil {
return nil, httperrors.NewInternalServerError("query all networks fail")
return input, httperrors.NewInternalServerError("query all networks fail")
}
if isOverlapNetworks(nets, startIp, endIp) {
return nil, httperrors.NewInputParameterError("Conflict address space with existing networks")
return input, httperrors.NewInputParameterError("Conflict address space with existing networks")
}
if len(input.WireId) > 0 {
@@ -1245,9 +1257,9 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
wireObj, err := WireManager.FetchByIdOrName(userCred, input.Wire)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("wire %s not found", input.Wire)
return input, httperrors.NewNotFoundError("wire %s not found", input.Wire)
} else {
return nil, httperrors.NewInternalServerError("query wire %s error %s", input.Wire, err)
return input, httperrors.NewInternalServerError("query wire %s error %s", input.Wire, err)
}
}
input.WireId = wireObj.GetId()
@@ -1257,24 +1269,24 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
zoneObj, err := ZoneManager.FetchByIdOrName(userCred, input.Zone)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("zone %s not found", input.Zone)
return input, httperrors.NewNotFoundError("zone %s not found", input.Zone)
} else {
return nil, httperrors.NewInternalServerError("query zone %s error %s", input.Zone, err)
return input, httperrors.NewInternalServerError("query zone %s error %s", input.Zone, err)
}
}
vpcObj, err := VpcManager.FetchByIdOrName(userCred, input.Vpc)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewNotFoundError("vpc %s not found", input.Vpc)
return input, httperrors.NewNotFoundError("vpc %s not found", input.Vpc)
} else {
return nil, httperrors.NewInternalServerError("query vpc %s error %s", input.Vpc, err)
return input, httperrors.NewInternalServerError("query vpc %s error %s", input.Vpc, err)
}
}
vpc := vpcObj.(*SVpc)
zone := zoneObj.(*SZone)
region := zone.GetRegion()
if region == nil {
return nil, httperrors.NewInternalServerError("zone %s related region not found", zone.Id)
return input, httperrors.NewInternalServerError("zone %s related region not found", zone.Id)
}
// 华为云,ucloud wire zone_id 为空
@@ -1286,37 +1298,37 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
}
if err != nil {
return nil, httperrors.NewInternalServerError("query wire for zone %s and vpc %s: %v", input.Zone, input.Vpc, err)
return input, httperrors.NewInternalServerError("query wire for zone %s and vpc %s: %v", input.Zone, input.Vpc, err)
}
if len(wires) == 0 {
return nil, httperrors.NewNotFoundError("wire not found for zone %s and vpc %s", input.Zone, input.Vpc)
return input, httperrors.NewNotFoundError("wire not found for zone %s and vpc %s", input.Zone, input.Vpc)
} else if len(wires) > 1 {
return nil, httperrors.NewConflictError("found %d wires for zone %s and vpc %s", len(wires), input.Zone, input.Vpc)
return input, httperrors.NewConflictError("found %d wires for zone %s and vpc %s", len(wires), input.Zone, input.Vpc)
} else {
input.WireId = wires[0].Id
}
} else {
return nil, httperrors.NewInputParameterError("No either wire or vpc provided")
return input, httperrors.NewInputParameterError("No either wire or vpc provided")
}
} else {
return nil, httperrors.NewInvalidStatusError("No either wire or zone provided")
return input, httperrors.NewInvalidStatusError("No either wire or zone provided")
}
}
if len(input.WireId) == 0 {
return nil, httperrors.NewMissingParameterError("wire_id")
return input, httperrors.NewMissingParameterError("wire_id")
}
wire := WireManager.FetchWireById(input.WireId)
if wire == nil {
return nil, httperrors.NewResourceNotFoundError("wire %s not found", input.WireId)
return input, httperrors.NewResourceNotFoundError("wire %s not found", input.WireId)
}
vpc := wire.getVpc()
if vpc == nil {
return nil, httperrors.NewInputParameterError("no valid vpc ???")
return input, httperrors.NewInputParameterError("no valid vpc ???")
}
if vpc.Status != api.VPC_STATUS_AVAILABLE {
return nil, httperrors.NewInvalidStatusError("VPC not ready")
return input, httperrors.NewInvalidStatusError("VPC not ready")
}
vpcRanges := vpc.getIPRanges()
@@ -1332,16 +1344,20 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
}
if !inRange {
return nil, httperrors.NewInputParameterError("Network not in range of VPC cidrblock %s", vpc.CidrBlock)
return input, httperrors.NewInputParameterError("Network not in range of VPC cidrblock %s", vpc.CidrBlock)
}
if len(input.ServerType) == 0 {
input.ServerType = api.NETWORK_TYPE_GUEST
} else if !utils.IsInStringArray(input.ServerType, ALL_NETWORK_TYPES) {
return nil, httperrors.NewInputParameterError("Invalid server_type: %s", input.ServerType)
return input, httperrors.NewInputParameterError("Invalid server_type: %s", input.ServerType)
}
return manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.JSON(input))
input.SharableVirtualResourceCreateInput, err = manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.SharableVirtualResourceCreateInput)
if err != nil {
return input, err
}
return input, nil
}
func (self *SNetwork) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
+157
View File
@@ -0,0 +1,157 @@
// 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 models
import (
"context"
"yunion.io/x/jsonutils"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
commonOptions "yunion.io/x/onecloud/pkg/cloudcommon/options"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
var (
ProjectQuota SProjectQuota
ProjectQuotaManager *SQuotaManager
ProjectUsageManager *SQuotaManager
ProjectPendingUsageManager *SQuotaManager
)
func init() {
ProjectQuota = SProjectQuota{}
ProjectUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(RegionQuota, "project_quota_usage_tbl"),
}
ProjectUsageManager.SetVirtualObject(ProjectUsageManager)
ProjectPendingUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(RegionQuota, "project_quota_pending_usage_tbl"),
}
ProjectPendingUsageManager.SetVirtualObject(ProjectPendingUsageManager)
ProjectQuotaManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaBaseManager(RegionQuota,
"project_quota_tbl",
ProjectPendingUsageManager,
ProjectUsageManager,
"project_quota",
"project_quotas",
),
}
ProjectQuotaManager.SetVirtualObject(ProjectQuotaManager)
}
type SProjectQuota struct {
quotas.SQuotaBase
quotas.SBaseQuotaKeys
Secgroup int
}
func (self *SProjectQuota) GetKeys() quotas.IQuotaKeys {
return self.SBaseQuotaKeys
}
func (self *SProjectQuota) SetKeys(keys quotas.IQuotaKeys) {
self.SBaseQuotaKeys = keys.(quotas.SBaseQuotaKeys)
}
func (self *SProjectQuota) FetchSystemQuota() {
keys := self.SBaseQuotaKeys
base := 0
switch options.Options.DefaultQuotaValue {
case commonOptions.DefaultQuotaUnlimit:
base = -1
case commonOptions.DefaultQuotaZero:
base = 0
if keys.Scope() == rbacutils.ScopeDomain { // domain level quota
base = 10
} else if keys.DomainId == identityapi.DEFAULT_DOMAIN_ID && keys.ProjectId == auth.AdminCredential().GetProjectId() {
base = 1
}
case commonOptions.DefaultQuotaDefault:
base = 1
if keys.Scope() == rbacutils.ScopeDomain {
base = 10
}
}
defaultValue := func(def int) int {
if base < 0 {
return -1
} else {
return def * base
}
}
self.Secgroup = defaultValue(options.Options.DefaultSecgroupQuota)
}
func (self *SProjectQuota) FetchUsage(ctx context.Context) error {
regionKeys := self.SBaseQuotaKeys
scope := regionKeys.Scope()
ownerId := regionKeys.OwnerId()
self.Secgroup, _ = totalSecurityGroupCount(scope, ownerId)
return nil
}
func (self *SProjectQuota) IsEmpty() bool {
if self.Secgroup > 0 {
return false
}
return true
}
func (self *SProjectQuota) Add(quota quotas.IQuota) {
squota := quota.(*SProjectQuota)
self.Secgroup = self.Secgroup + quotas.NonNegative(squota.Secgroup)
}
func (self *SProjectQuota) Sub(quota quotas.IQuota) {
squota := quota.(*SProjectQuota)
self.Secgroup = nonNegative(self.Secgroup - squota.Secgroup)
}
func (self *SProjectQuota) Update(quota quotas.IQuota) {
squota := quota.(*SProjectQuota)
if squota.Secgroup > 0 {
self.Secgroup = squota.Secgroup
}
}
func (self *SProjectQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
err := quotas.NewOutOfQuotaError()
sreq := request.(*SProjectQuota)
squota := quota.(*SProjectQuota)
if sreq.Secgroup > 0 && self.Secgroup > squota.Secgroup {
err.Add("secgroup", squota.Secgroup, self.Secgroup)
}
if err.IsError() {
return err
} else {
return nil
}
}
func (self *SProjectQuota) ToJSON(prefix string) jsonutils.JSONObject {
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewInt(int64(self.Secgroup)), keyName(prefix, "secgroup"))
return ret
}
-85
View File
@@ -1,85 +0,0 @@
// 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 models
import (
api "yunion.io/x/onecloud/pkg/apis/compute"
)
func (account *SCloudaccount) GetQuotaPlatformID() []string {
return []string{
account.getCloudEnv(),
account.Provider,
}
}
func (provider *SCloudprovider) GetQuotaPlatformID() []string {
return provider.GetCloudaccount().GetQuotaPlatformID()
}
func (base *SManagedResourceBase) GetQuotaPlatformID() []string {
account := base.GetCloudaccount()
if account != nil {
return account.GetQuotaPlatformID()
} else {
return []string{
api.CLOUD_ENV_ON_PREMISE, api.CLOUD_PROVIDER_ONECLOUD,
}
}
}
func (host *SHost) GetQuotaPlatformID() []string {
ids := host.SManagedResourceBase.GetQuotaPlatformID()
switch host.HostType {
case api.HOST_TYPE_HYPERVISOR:
ids = append(ids, api.HYPERVISOR_KVM)
case api.HOST_TYPE_BAREMETAL:
ids = append(ids, api.HYPERVISOR_BAREMETAL)
case api.HOST_TYPE_KUBELET:
ids = append(ids, api.HYPERVISOR_CONTAINER)
}
return ids
}
func (storage *SStorage) getQuotaPlatformID() []string {
hosts := storage.GetAttachedHosts()
if len(hosts) > 0 {
return hosts[0].GetQuotaPlatformID()
}
return storage.SManagedResourceBase.GetQuotaPlatformID()
}
func (guest *SGuest) GetQuotaPlatformID() []string {
host := guest.GetHost()
if host != nil {
return host.GetQuotaPlatformID()
}
return GetDriver(guest.GetHypervisor()).GetQuotaPlatformID()
}
func (disk *SDisk) GetQuotaPlatformID() []string {
storage := disk.GetStorage()
if storage != nil {
return storage.getQuotaPlatformID()
}
return []string{}
}
func GetQuotaPlatformID(hypervisor string) []string {
if len(hypervisor) > 0 {
return GetDriver(hypervisor).GetQuotaPlatformID()
}
return []string{}
}
+275 -193
View File
@@ -16,17 +16,22 @@ package models
import (
"context"
"database/sql"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/sets"
api "yunion.io/x/onecloud/pkg/apis/compute"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
commonOptions "yunion.io/x/onecloud/pkg/cloudcommon/options"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/utils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
@@ -34,103 +39,149 @@ type SQuotaManager struct {
quotas.SQuotaBaseManager
}
var QuotaManager *SQuotaManager
var QuotaUsageManager *SQuotaManager
var (
Quota SQuota
QuotaManager *SQuotaManager
QuotaUsageManager *SQuotaManager
QuotaPendingUsageManager *SQuotaManager
)
func init() {
pendingStore := quotas.NewMemoryQuotaStore()
Quota = SQuota{}
QuotaUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(SQuota{}, "quota_usage_tbl"),
SQuotaBaseManager: quotas.NewQuotaUsageManager(Quota, "quota_usage_tbl"),
}
QuotaUsageManager.SetVirtualObject(QuotaUsageManager)
QuotaPendingUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(Quota, "quota_pending_usage_tbl"),
}
QuotaPendingUsageManager.SetVirtualObject(QuotaPendingUsageManager)
QuotaManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaBaseManager(SQuota{}, "quota_tbl", pendingStore, QuotaUsageManager),
SQuotaBaseManager: quotas.NewQuotaBaseManager(Quota,
"quota_tbl",
QuotaPendingUsageManager,
QuotaUsageManager,
"quota",
"quotas",
),
}
QuotaManager.SetVirtualObject(QuotaManager)
}
type SQuota struct {
quotas.SQuotaBase
SComputeResourceKeys
Count int
Cpu int
Memory int
Storage int
Port int
Eip int
Eport int
Bw int
Ebw int
// Keypair int
// Image int
Group int
Secgroup int
IsolatedDevice int
Snapshot int
Bucket int
ObjectGB int
ObjectCnt int
}
func (self *SQuota) FetchSystemQuota(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) {
func (self *SQuota) GetKeys() quotas.IQuotaKeys {
return self.SComputeResourceKeys
}
func (self *SQuota) SetKeys(keys quotas.IQuotaKeys) {
self.SComputeResourceKeys = keys.(SComputeResourceKeys)
}
func (self *SQuota) FetchSystemQuota() {
keys := self.SComputeResourceKeys
base := 0
if scope == rbacutils.ScopeDomain {
base = 10
} else if ownerId.GetProjectDomainId() == identityapi.DEFAULT_DOMAIN_ID && ownerId.GetProjectName() == identityapi.SystemAdminProject {
switch options.Options.DefaultQuotaValue {
case commonOptions.DefaultQuotaUnlimit:
base = -1
case commonOptions.DefaultQuotaZero:
base = 0
if keys.Scope() == rbacutils.ScopeDomain { // domain level quota
base = 10
} else if keys.DomainId == identityapi.DEFAULT_DOMAIN_ID && keys.ProjectId == auth.AdminCredential().GetProjectId() {
base = 1
}
case commonOptions.DefaultQuotaDefault:
base = 1
if keys.Scope() == rbacutils.ScopeDomain {
base = 10
}
}
self.Cpu = options.Options.DefaultCpuQuota * base
self.Memory = options.Options.DefaultMemoryQuota * base
self.Storage = options.Options.DefaultStorageQuota * base
self.Port = options.Options.DefaultPortQuota * base
self.Eip = options.Options.DefaultEipQuota * base
self.Eport = options.Options.DefaultEportQuota * base
self.Bw = options.Options.DefaultBwQuota * base
self.Ebw = options.Options.DefaultEbwQuota * base
self.Group = options.Options.DefaultGroupQuota * base
self.Secgroup = options.Options.DefaultSecgroupQuota * base
self.IsolatedDevice = options.Options.DefaultIsolatedDeviceQuota * base
self.Snapshot = options.Options.DefaultSnapshotQuota * base
self.Bucket = options.Options.DefaultBucketQuota * base
self.ObjectGB = options.Options.DefaultObjectGBQuota * base
self.ObjectCnt = options.Options.DefaultObjectCntQuota * base
defaultValue := func(def int) int {
if base < 0 {
return -1
} else {
return def * base
}
}
self.Count = defaultValue(options.Options.DefaultServerQuota)
self.Cpu = defaultValue(options.Options.DefaultCpuQuota)
self.Memory = defaultValue(options.Options.DefaultMemoryQuota)
self.Storage = defaultValue(options.Options.DefaultStorageQuota)
self.Group = defaultValue(options.Options.DefaultGroupQuota)
self.IsolatedDevice = defaultValue(options.Options.DefaultIsolatedDeviceQuota)
}
func (self *SQuota) FetchUsage(ctx context.Context, scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, name []string) error {
diskSize := totalDiskSize(scope, ownerId, tristate.None, tristate.None, false, false)
net := totalGuestNicCount(scope, ownerId, nil, false)
lbnic, _ := totalLBNicCount(scope, ownerId)
// net := WireManager.TotalCount(nil, nil, nil, "", scope, ownerId)
hypervisors := sets.NewString(api.HYPERVISORS...)
hypervisors.Delete(api.HYPERVISOR_CONTAINER)
guest := totalGuestResourceCount(scope, ownerId, nil, nil, hypervisors.List(), false, false, nil, nil, nil, nil, "")
eipUsage := ElasticipManager.TotalCount(scope, ownerId, nil, nil, nil, "")
snapshotCount, _ := TotalSnapshotCount(scope, ownerId, nil, nil, nil, "")
bucketUsage := BucketManager.TotalCount(scope, ownerId, nil, nil, nil, "")
// XXX
// keypair belongs to user
// keypair := totalKeypairCount(projectId)
func (self *SQuota) FetchUsage(ctx context.Context) error {
keys := self.SComputeResourceKeys
scope := keys.Scope()
ownerId := keys.OwnerId()
rangeObjs := make([]db.IStandaloneModel, 0)
if len(keys.ManagerId) > 0 {
obj, err := CloudproviderManager.FetchById(keys.ManagerId)
if err != nil {
return errors.Wrap(err, "CloudproviderManager.FetchById")
}
rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
} else if len(keys.AccountId) > 0 {
obj, err := CloudaccountManager.FetchById(keys.AccountId)
if err != nil {
return errors.Wrap(err, "CloudaccountManager.FetchById")
}
rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
}
if len(keys.ZoneId) > 0 {
obj, err := ZoneManager.FetchById(keys.ZoneId)
if err != nil {
return errors.Wrap(err, "ZoneManager.FetchById")
}
rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
} else if len(keys.RegionId) > 0 {
obj, err := CloudregionManager.FetchById(keys.RegionId)
if err != nil {
return errors.Wrap(err, "CloudregionManager.FetchById")
}
rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
}
var hypervisors []string
if len(keys.Hypervisor) > 0 {
hypervisors = []string{keys.Hypervisor}
}
var providers []string
if len(keys.Provider) > 0 {
providers = []string{keys.Provider}
}
var brands []string
if len(keys.Brand) > 0 {
brands = []string{keys.Brand}
}
diskSize := totalDiskSize(scope, ownerId, tristate.None, tristate.None, false, false, rangeObjs, providers, brands, keys.CloudEnv, hypervisors)
guest := totalGuestResourceCount(scope, ownerId, rangeObjs, nil, hypervisors, false, false, nil, nil, providers, brands, keys.CloudEnv)
self.Count = guest.TotalGuestCount
self.Cpu = guest.TotalCpuCount
self.Memory = guest.TotalMemSize
self.Storage = diskSize
self.Eip = eipUsage.Total()
// log.Debugf("%d %d %d\n", net.InternalNicCount, net.InternalVirtualNicCount, lbnic)
self.Port = net.InternalNicCount + net.InternalVirtualNicCount + lbnic
self.Eport = net.ExternalNicCount + net.ExternalVirtualNicCount
self.Bw = net.InternalBandwidth
self.Ebw = net.ExternalBandwidth
// self.Port = net.GuestNicCount + net.GroupNicCount + net.LbNicCount
// if scope == rbacutils.ScopeSystem {
// self.Port += net.HostNicCount + net.ReservedCount
// }
self.Group = 0
self.Secgroup, _ = totalSecurityGroupCount(scope, ownerId)
self.IsolatedDevice = guest.TotalIsolatedCount
self.Snapshot = snapshotCount
self.Bucket = bucketUsage.Buckets
self.ObjectGB = int(bucketUsage.Bytes / 1000 / 1000 / 1000)
self.ObjectCnt = bucketUsage.Objects
return nil
}
@@ -144,62 +195,22 @@ func (self *SQuota) IsEmpty() bool {
if self.Storage > 0 {
return false
}
if self.Port > 0 {
return false
}
if self.Eip > 0 {
return false
}
if self.Eport > 0 {
return false
}
if self.Bw > 0 {
return false
}
if self.Ebw > 0 {
return false
}
if self.Group > 0 {
return false
}
if self.Secgroup > 0 {
return false
}
if self.IsolatedDevice > 0 {
return false
}
if self.Snapshot > 0 {
return false
}
if self.Bucket > 0 {
return false
}
if self.ObjectGB > 0 {
return false
}
if self.ObjectCnt > 0 {
return false
}
return true
}
func (self *SQuota) Add(quota quotas.IQuota) {
squota := quota.(*SQuota)
self.Cpu = self.Cpu + squota.Cpu
self.Memory = self.Memory + squota.Memory
self.Storage = self.Storage + squota.Storage
self.Port = self.Port + squota.Port
self.Eip = self.Eip + squota.Eip
self.Eport = self.Eport + squota.Eport
self.Bw = self.Bw + squota.Bw
self.Ebw = self.Ebw + squota.Ebw
self.Group = self.Group + squota.Group
self.Secgroup = self.Secgroup + squota.Secgroup
self.IsolatedDevice = self.IsolatedDevice + squota.IsolatedDevice
self.Snapshot = self.Snapshot + squota.Snapshot
self.Bucket = self.Bucket + squota.Bucket
self.ObjectGB = self.ObjectGB + squota.ObjectGB
self.ObjectCnt = self.ObjectCnt + squota.ObjectCnt
self.Cpu = self.Cpu + quotas.NonNegative(squota.Cpu)
self.Memory = self.Memory + quotas.NonNegative(squota.Memory)
self.Storage = self.Storage + quotas.NonNegative(squota.Storage)
self.Group = self.Group + quotas.NonNegative(squota.Group)
self.IsolatedDevice = self.IsolatedDevice + quotas.NonNegative(squota.IsolatedDevice)
}
func nonNegative(val int) int {
@@ -211,18 +222,8 @@ func (self *SQuota) Sub(quota quotas.IQuota) {
self.Cpu = nonNegative(self.Cpu - squota.Cpu)
self.Memory = nonNegative(self.Memory - squota.Memory)
self.Storage = nonNegative(self.Storage - squota.Storage)
self.Port = nonNegative(self.Port - squota.Port)
self.Eip = nonNegative(self.Eip - squota.Eip)
self.Eport = nonNegative(self.Eport - squota.Eport)
self.Bw = nonNegative(self.Bw - squota.Bw)
self.Ebw = nonNegative(self.Ebw - squota.Ebw)
self.Group = nonNegative(self.Group - squota.Group)
self.Secgroup = nonNegative(self.Secgroup - squota.Secgroup)
self.IsolatedDevice = nonNegative(self.IsolatedDevice - squota.IsolatedDevice)
self.Snapshot = nonNegative(self.Snapshot - squota.Snapshot)
self.Bucket = nonNegative(self.Bucket - squota.Bucket)
self.ObjectGB = nonNegative(self.ObjectGB - squota.ObjectGB)
self.ObjectCnt = nonNegative(self.ObjectCnt - squota.ObjectCnt)
}
func (self *SQuota) Update(quota quotas.IQuota) {
@@ -236,42 +237,12 @@ func (self *SQuota) Update(quota quotas.IQuota) {
if squota.Storage > 0 {
self.Storage = squota.Storage
}
if squota.Port > 0 {
self.Port = squota.Port
}
if squota.Eip > 0 {
self.Eip = squota.Eip
}
if squota.Eport > 0 {
self.Eport = squota.Eport
}
if squota.Bw > 0 {
self.Bw = squota.Bw
}
if squota.Ebw > 0 {
self.Ebw = squota.Ebw
}
if squota.Group > 0 {
self.Group = squota.Group
}
if squota.Secgroup > 0 {
self.Secgroup = squota.Secgroup
}
if squota.IsolatedDevice > 0 {
self.IsolatedDevice = squota.IsolatedDevice
}
if squota.Snapshot > 0 {
self.Snapshot = squota.Snapshot
}
if squota.Bucket > 0 {
self.Bucket = squota.Bucket
}
if squota.ObjectGB > 0 {
self.ObjectGB = squota.ObjectGB
}
if squota.ObjectCnt > 0 {
self.ObjectCnt = squota.ObjectCnt
}
}
func (self *SQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
@@ -287,42 +258,12 @@ func (self *SQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
if sreq.Storage > 0 && self.Storage > squota.Storage {
err.Add("storage", squota.Storage, self.Storage)
}
if sreq.Port > 0 && self.Port > squota.Port {
err.Add("port", squota.Port, self.Port)
}
if sreq.Eip > 0 && self.Eip > squota.Eip {
err.Add("eip", squota.Eip, self.Eip)
}
if sreq.Eport > 0 && self.Eport > squota.Eport {
err.Add("eport", squota.Eport, self.Eport)
}
if sreq.Bw > 0 && self.Bw > squota.Bw {
err.Add("bw", squota.Bw, self.Bw)
}
if sreq.Ebw > 0 && self.Ebw > squota.Ebw {
err.Add("ebw", squota.Ebw, self.Ebw)
}
if sreq.Group > 0 && self.Group > squota.Group {
err.Add("group", squota.Group, self.Group)
}
if sreq.Secgroup > 0 && self.Secgroup > squota.Secgroup {
err.Add("secgroup", squota.Secgroup, self.Secgroup)
}
if sreq.IsolatedDevice > 0 && self.IsolatedDevice > squota.IsolatedDevice {
err.Add("isolated_device", squota.IsolatedDevice, self.IsolatedDevice)
}
if sreq.Snapshot > 0 && self.Snapshot > squota.Snapshot {
err.Add("snapshot", squota.Snapshot, self.Snapshot)
}
if sreq.Bucket > 0 && self.Bucket > squota.Bucket {
err.Add("bucket", squota.Bucket, self.Bucket)
}
if sreq.ObjectGB > 0 && self.ObjectGB > squota.ObjectGB {
err.Add("object_gb", squota.ObjectGB, self.ObjectGB)
}
if sreq.ObjectCnt > 0 && self.ObjectCnt > squota.ObjectCnt {
err.Add("object_cnt", squota.ObjectCnt, self.ObjectCnt)
}
if err.IsError() {
return err
} else {
@@ -343,17 +284,158 @@ func (self *SQuota) ToJSON(prefix string) jsonutils.JSONObject {
ret.Add(jsonutils.NewInt(int64(self.Cpu)), keyName(prefix, "cpu"))
ret.Add(jsonutils.NewInt(int64(self.Memory)), keyName(prefix, "memory"))
ret.Add(jsonutils.NewInt(int64(self.Storage)), keyName(prefix, "storage"))
ret.Add(jsonutils.NewInt(int64(self.Port)), keyName(prefix, "port"))
ret.Add(jsonutils.NewInt(int64(self.Eip)), keyName(prefix, "eip"))
ret.Add(jsonutils.NewInt(int64(self.Eport)), keyName(prefix, "eport"))
ret.Add(jsonutils.NewInt(int64(self.Bw)), keyName(prefix, "bw"))
ret.Add(jsonutils.NewInt(int64(self.Ebw)), keyName(prefix, "ebw"))
ret.Add(jsonutils.NewInt(int64(self.Group)), keyName(prefix, "group"))
ret.Add(jsonutils.NewInt(int64(self.Secgroup)), keyName(prefix, "secgroup"))
ret.Add(jsonutils.NewInt(int64(self.IsolatedDevice)), keyName(prefix, "isolated_device"))
ret.Add(jsonutils.NewInt(int64(self.Snapshot)), keyName(prefix, "snapshot"))
ret.Add(jsonutils.NewInt(int64(self.Bucket)), keyName(prefix, "bucket"))
ret.Add(jsonutils.NewInt(int64(self.ObjectGB)), keyName(prefix, "object_gb"))
ret.Add(jsonutils.NewInt(int64(self.ObjectCnt)), keyName(prefix, "object_cnt"))
return ret
}
func (manager *SQuotaManager) FetchIdMap(ctx context.Context, idMap map[string]map[string]string) (map[string]map[string]string, error) {
for field := range idMap {
switch field {
case "domain_id":
fieldIdMap, err := utils.FetchDomainNames(ctx, idMap[field])
if err != nil {
return nil, errors.Wrap(err, "utils.FetchDomainNames")
}
idMap[field] = fieldIdMap
case "tenant_id":
fieldIdMap, err := utils.FetchTenantNames(ctx, idMap[field])
if err != nil {
return nil, errors.Wrap(err, "utils.FetchTenantNames")
}
idMap[field] = fieldIdMap
case "region_id":
fieldIdMap, err := fetchRegionNames(idMap[field])
if err != nil {
return nil, errors.Wrap(err, "fetchRegionNames")
}
idMap[field] = fieldIdMap
case "zone_id":
fieldIdMap, err := fetchZoneNames(idMap[field])
if err != nil {
return nil, errors.Wrap(err, "fetchZoneNames")
}
idMap[field] = fieldIdMap
case "account_id":
fieldIdMap, err := fetchAccountNames(idMap[field])
if err != nil {
return nil, errors.Wrap(err, "fetchAccountNames")
}
idMap[field] = fieldIdMap
case "manager_id":
fieldIdMap, err := fetchManagerNames(idMap[field])
if err != nil {
return nil, errors.Wrap(err, "fetchManagerNames")
}
idMap[field] = fieldIdMap
}
}
return idMap, nil
}
func dbFetchIdNameMap(manager db.IStandaloneModelManager, idMap map[string]string) (map[string]string, error) {
q := manager.Query("id", "name").In("id", utils.MapKeys(idMap))
rows, err := q.Rows()
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return idMap, nil
} else {
return idMap, errors.Wrap(err, "Query")
}
}
defer rows.Close()
for rows.Next() {
var id string
var name string
err := rows.Scan(&id, &name)
if err != nil {
return idMap, errors.Wrap(err, "rows.Scan")
}
idMap[id] = name
}
return idMap, nil
}
func fetchRegionNames(idMap map[string]string) (map[string]string, error) {
return dbFetchIdNameMap(CloudregionManager, idMap)
}
func fetchZoneNames(idMap map[string]string) (map[string]string, error) {
return dbFetchIdNameMap(ZoneManager, idMap)
}
func fetchAccountNames(idMap map[string]string) (map[string]string, error) {
return dbFetchIdNameMap(CloudaccountManager, idMap)
}
func fetchManagerNames(idMap map[string]string) (map[string]string, error) {
return dbFetchIdNameMap(CloudproviderManager, idMap)
}
type SComputeResourceKeys struct {
quotas.SZonalCloudResourceKeys
Hypervisor string `width:"16" charset:"ascii" nullable:"false" primary:"true" list:"user"`
}
func (k SComputeResourceKeys) Fields() []string {
return append(k.SZonalCloudResourceKeys.Fields(), "hypervisor")
}
func (k SComputeResourceKeys) Values() []string {
return append(k.SZonalCloudResourceKeys.Values(), k.Hypervisor)
}
func (k1 SComputeResourceKeys) Compare(ik quotas.IQuotaKeys) int {
k2 := ik.(SComputeResourceKeys)
r := k1.SZonalCloudResourceKeys.Compare(k2.SZonalCloudResourceKeys)
if r != 0 {
return r
}
if k1.Hypervisor < k2.Hypervisor {
return -1
} else if k1.Hypervisor > k2.Hypervisor {
return 1
}
return 0
}
func fetchCloudQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, manager *SCloudprovider) quotas.SCloudResourceKeys {
keys := quotas.SCloudResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
if manager != nil {
account := manager.GetCloudaccount()
keys.Provider = account.Provider
keys.Brand = account.Brand
keys.CloudEnv = account.getCloudEnv()
keys.AccountId = account.Id
keys.ManagerId = manager.Id
} else {
keys.Provider = api.CLOUD_PROVIDER_ONECLOUD
keys.Brand = api.ONECLOUD_BRAND_ONECLOUD
keys.CloudEnv = api.CLOUD_ENV_ON_PREMISE
}
return keys
}
func fetchRegionalQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, region *SCloudregion, manager *SCloudprovider) quotas.SRegionalCloudResourceKeys {
keys := quotas.SRegionalCloudResourceKeys{}
keys.SCloudResourceKeys = fetchCloudQuotaKeys(scope, ownerId, manager)
keys.RegionId = region.Id
return keys
}
func fetchZonalQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, zone *SZone, manager *SCloudprovider) quotas.SZonalCloudResourceKeys {
keys := quotas.SZonalCloudResourceKeys{}
keys.SCloudResourceKeys = fetchCloudQuotaKeys(scope, ownerId, manager)
keys.RegionId = zone.CloudregionId
keys.ZoneId = zone.Id
return keys
}
func fetchComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, zone *SZone, manager *SCloudprovider, hypervisor string) SComputeResourceKeys {
keys := SComputeResourceKeys{}
keys.SZonalCloudResourceKeys = fetchZonalQuotaKeys(scope, ownerId, zone, manager)
keys.Hypervisor = hypervisor
return keys
}
+355
View File
@@ -0,0 +1,355 @@
// 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 models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
commonOptions "yunion.io/x/onecloud/pkg/cloudcommon/options"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
var (
RegionQuota SRegionQuota
RegionQuotaManager *SQuotaManager
RegionUsageManager *SQuotaManager
RegionPendingUsageManager *SQuotaManager
)
func init() {
RegionQuota = SRegionQuota{}
RegionUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(RegionQuota, "region_quota_usage_tbl"),
}
RegionUsageManager.SetVirtualObject(RegionUsageManager)
RegionPendingUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(RegionQuota, "region_quota_pending_usage_tbl"),
}
RegionPendingUsageManager.SetVirtualObject(RegionPendingUsageManager)
RegionQuotaManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaBaseManager(RegionQuota,
"region_quota_tbl",
RegionPendingUsageManager,
RegionUsageManager,
"region_quota",
"region_quotas",
),
}
RegionQuotaManager.SetVirtualObject(RegionQuotaManager)
}
type SRegionQuota struct {
quotas.SQuotaBase
quotas.SRegionalCloudResourceKeys
Eip int
Port int
Eport int
Bw int
Ebw int
Snapshot int
Bucket int
ObjectGB int
ObjectCnt int
Rds int
Cache int
}
func (self *SRegionQuota) GetKeys() quotas.IQuotaKeys {
return self.SRegionalCloudResourceKeys
}
func (self *SRegionQuota) SetKeys(keys quotas.IQuotaKeys) {
self.SRegionalCloudResourceKeys = keys.(quotas.SRegionalCloudResourceKeys)
}
func (self *SRegionQuota) FetchSystemQuota() {
keys := self.SRegionalCloudResourceKeys
base := 0
switch options.Options.DefaultQuotaValue {
case commonOptions.DefaultQuotaUnlimit:
base = -1
case commonOptions.DefaultQuotaZero:
base = 0
if keys.Scope() == rbacutils.ScopeDomain { // domain level quota
base = 10
} else if keys.DomainId == identityapi.DEFAULT_DOMAIN_ID && keys.ProjectId == auth.AdminCredential().GetProjectId() {
base = 1
}
case commonOptions.DefaultQuotaDefault:
base = 1
if keys.Scope() == rbacutils.ScopeDomain {
base = 10
}
}
defaultValue := func(def int) int {
if base < 0 {
return -1
} else {
return def * base
}
}
self.Eip = defaultValue(options.Options.DefaultEipQuota)
self.Port = defaultValue(options.Options.DefaultPortQuota)
self.Eport = defaultValue(options.Options.DefaultEportQuota)
self.Bw = defaultValue(options.Options.DefaultBwQuota)
self.Ebw = defaultValue(options.Options.DefaultEbwQuota)
self.Snapshot = defaultValue(options.Options.DefaultSnapshotQuota)
self.Bucket = defaultValue(options.Options.DefaultBucketQuota)
self.ObjectGB = defaultValue(options.Options.DefaultObjectGBQuota)
self.ObjectCnt = defaultValue(options.Options.DefaultObjectCntQuota)
self.Rds = defaultValue(options.Options.DefaultRdsQuota)
self.Cache = defaultValue(options.Options.DefaultCacheQuota)
}
func (self *SRegionQuota) FetchUsage(ctx context.Context) error {
regionKeys := self.SRegionalCloudResourceKeys
scope := regionKeys.Scope()
ownerId := regionKeys.OwnerId()
var rangeObjs []db.IStandaloneModel
if len(regionKeys.RegionId) > 0 {
obj, err := CloudregionManager.FetchById(regionKeys.RegionId)
if err != nil {
return errors.Wrap(err, "CloudregionManager.FetchById")
}
rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
}
if len(regionKeys.ManagerId) > 0 {
obj, err := CloudproviderManager.FetchById(regionKeys.ManagerId)
if err != nil {
return errors.Wrap(err, "CloudproviderManager.FetchById")
}
rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
} else if len(regionKeys.AccountId) > 0 {
obj, err := CloudaccountManager.FetchById(regionKeys.AccountId)
if err != nil {
return errors.Wrap(err, "CloudaccountManager.FetchById")
}
rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
}
var providers []string
if len(regionKeys.Provider) > 0 {
providers = []string{regionKeys.Provider}
}
var brands []string
if len(regionKeys.Brand) > 0 {
brands = []string{regionKeys.Brand}
}
net := totalGuestNicCount(scope, ownerId, rangeObjs, false, providers, brands, regionKeys.CloudEnv)
lbnic, _ := totalLBNicCount(scope, ownerId, rangeObjs, providers, brands, regionKeys.CloudEnv)
eipUsage := ElasticipManager.TotalCount(scope, ownerId, rangeObjs, providers, brands, regionKeys.CloudEnv)
self.Eip = eipUsage.Total()
self.Port = net.InternalNicCount + net.InternalVirtualNicCount + lbnic
self.Eport = net.ExternalNicCount + net.ExternalVirtualNicCount
self.Bw = net.InternalBandwidth
self.Ebw = net.ExternalBandwidth
snapshotCount, _ := TotalSnapshotCount(scope, ownerId, rangeObjs, providers, brands, regionKeys.CloudEnv)
self.Snapshot = snapshotCount
bucketUsage := BucketManager.TotalCount(scope, ownerId, rangeObjs, providers, brands, regionKeys.CloudEnv)
self.Bucket = bucketUsage.Buckets
self.ObjectGB = int(bucketUsage.Bytes / 1000 / 1000 / 1000)
self.ObjectCnt = bucketUsage.Objects
self.Rds, _ = DBInstanceManager.TotalCount(scope, ownerId, rangeObjs, providers, brands, regionKeys.CloudEnv)
self.Cache, _ = ElasticcacheManager.TotalCount(scope, ownerId, rangeObjs, providers, brands, regionKeys.CloudEnv)
return nil
}
func (self *SRegionQuota) IsEmpty() bool {
if self.Port > 0 {
return false
}
if self.Eip > 0 {
return false
}
if self.Eport > 0 {
return false
}
if self.Bw > 0 {
return false
}
if self.Ebw > 0 {
return false
}
if self.Snapshot > 0 {
return false
}
if self.Bucket > 0 {
return false
}
if self.ObjectGB > 0 {
return false
}
if self.ObjectCnt > 0 {
return false
}
if self.Rds > 0 {
return false
}
if self.Cache > 0 {
return false
}
return true
}
func (self *SRegionQuota) Add(quota quotas.IQuota) {
squota := quota.(*SRegionQuota)
self.Port = self.Port + quotas.NonNegative(squota.Port)
self.Eip = self.Eip + quotas.NonNegative(squota.Eip)
self.Eport = self.Eport + quotas.NonNegative(squota.Eport)
self.Bw = self.Bw + quotas.NonNegative(squota.Bw)
self.Ebw = self.Ebw + quotas.NonNegative(squota.Ebw)
self.Snapshot = self.Snapshot + quotas.NonNegative(squota.Snapshot)
self.Bucket = self.Bucket + quotas.NonNegative(squota.Bucket)
self.ObjectGB = self.ObjectGB + quotas.NonNegative(squota.ObjectGB)
self.ObjectCnt = self.ObjectCnt + quotas.NonNegative(squota.ObjectCnt)
self.Rds = self.Rds + quotas.NonNegative(squota.Rds)
self.Cache = self.Cache + quotas.NonNegative(squota.Cache)
}
func (self *SRegionQuota) Sub(quota quotas.IQuota) {
squota := quota.(*SRegionQuota)
self.Port = nonNegative(self.Port - squota.Port)
self.Eip = nonNegative(self.Eip - squota.Eip)
self.Eport = nonNegative(self.Eport - squota.Eport)
self.Bw = nonNegative(self.Bw - squota.Bw)
self.Ebw = nonNegative(self.Ebw - squota.Ebw)
self.Snapshot = nonNegative(self.Snapshot - squota.Snapshot)
self.Bucket = nonNegative(self.Bucket - squota.Bucket)
self.ObjectGB = nonNegative(self.ObjectGB - squota.ObjectGB)
self.ObjectCnt = nonNegative(self.ObjectCnt - squota.ObjectCnt)
self.Rds = nonNegative(self.Rds - squota.Rds)
self.Cache = nonNegative(self.Cache - squota.Cache)
}
func (self *SRegionQuota) Update(quota quotas.IQuota) {
squota := quota.(*SRegionQuota)
if squota.Port > 0 {
self.Port = squota.Port
}
if squota.Eip > 0 {
self.Eip = squota.Eip
}
if squota.Eport > 0 {
self.Eport = squota.Eport
}
if squota.Bw > 0 {
self.Bw = squota.Bw
}
if squota.Ebw > 0 {
self.Ebw = squota.Ebw
}
if squota.Snapshot > 0 {
self.Snapshot = squota.Snapshot
}
if squota.Bucket > 0 {
self.Bucket = squota.Bucket
}
if squota.ObjectGB > 0 {
self.ObjectGB = squota.ObjectGB
}
if squota.ObjectCnt > 0 {
self.ObjectCnt = squota.ObjectCnt
}
if squota.Rds > 0 {
self.Rds = squota.Rds
}
if squota.Cache > 0 {
self.Cache = squota.Cache
}
}
func (self *SRegionQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
err := quotas.NewOutOfQuotaError()
sreq := request.(*SRegionQuota)
squota := quota.(*SRegionQuota)
if sreq.Port > 0 && self.Port > squota.Port {
err.Add("port", squota.Port, self.Port)
}
if sreq.Eip > 0 && self.Eip > squota.Eip {
err.Add("eip", squota.Eip, self.Eip)
}
if sreq.Eport > 0 && self.Eport > squota.Eport {
err.Add("eport", squota.Eport, self.Eport)
}
if sreq.Bw > 0 && self.Bw > squota.Bw {
err.Add("bw", squota.Bw, self.Bw)
}
if sreq.Ebw > 0 && self.Ebw > squota.Ebw {
err.Add("ebw", squota.Ebw, self.Ebw)
}
if sreq.Snapshot > 0 && self.Snapshot > squota.Snapshot {
err.Add("snapshot", squota.Snapshot, self.Snapshot)
}
if sreq.Bucket > 0 && self.Bucket > squota.Bucket {
err.Add("bucket", squota.Bucket, self.Bucket)
}
if sreq.ObjectGB > 0 && self.ObjectGB > squota.ObjectGB {
err.Add("object_gb", squota.ObjectGB, self.ObjectGB)
}
if sreq.ObjectCnt > 0 && self.ObjectCnt > squota.ObjectCnt {
err.Add("object_cnt", squota.ObjectCnt, self.ObjectCnt)
}
if sreq.Rds > 0 && self.Rds > squota.Rds {
err.Add("rds", squota.Rds, self.Rds)
}
if sreq.Cache > 0 && self.Cache > squota.Cache {
err.Add("cache", squota.Cache, self.Cache)
}
if err.IsError() {
return err
} else {
return nil
}
}
func (self *SRegionQuota) ToJSON(prefix string) jsonutils.JSONObject {
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewInt(int64(self.Port)), keyName(prefix, "port"))
ret.Add(jsonutils.NewInt(int64(self.Eip)), keyName(prefix, "eip"))
ret.Add(jsonutils.NewInt(int64(self.Eport)), keyName(prefix, "eport"))
ret.Add(jsonutils.NewInt(int64(self.Bw)), keyName(prefix, "bw"))
ret.Add(jsonutils.NewInt(int64(self.Ebw)), keyName(prefix, "ebw"))
ret.Add(jsonutils.NewInt(int64(self.Snapshot)), keyName(prefix, "snapshot"))
ret.Add(jsonutils.NewInt(int64(self.Bucket)), keyName(prefix, "bucket"))
ret.Add(jsonutils.NewInt(int64(self.ObjectGB)), keyName(prefix, "object_gb"))
ret.Add(jsonutils.NewInt(int64(self.ObjectCnt)), keyName(prefix, "object_cnt"))
ret.Add(jsonutils.NewInt(int64(self.Rds)), keyName(prefix, "rds"))
ret.Add(jsonutils.NewInt(int64(self.Cache)), keyName(prefix, "cache"))
return ret
}
+13 -1
View File
@@ -26,6 +26,7 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
@@ -221,7 +222,18 @@ func (man *SRouteTableManager) ValidateCreateData(ctx context.Context, userCred
return nil, httperrors.NewConflictError("failed getting region of vpc %s(%s)", vpc.Name, vpc.Id)
}
data.Set("cloudregion_id", jsonutils.NewString(cloudregion.Id))
return man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.VirtualResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err)
}
input, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (manager *SRouteTableManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
+12 -1
View File
@@ -23,6 +23,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -104,7 +105,17 @@ func (manager *SSchedpolicyManager) ValidateCreateData(ctx context.Context, user
return nil, err
}
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (self *SSchedpolicy) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
+13 -1
View File
@@ -21,6 +21,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -92,7 +93,18 @@ func (man *SSchedtagJointsManager) ValidateCreateData(ctx context.Context, userC
if resourceType != schedtag.ResourceType {
return nil, httperrors.NewInputParameterError("Schedtag %s resource_type mismatch: %s != %s", schedtag.GetName(), schedtag.ResourceType, resourceType)
}
return man.SJointResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.JoinResourceBaseCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal JointResourceCreateInput fail %s", err)
}
input, err = man.SJointResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (man *SSchedtagJointsManager) AllowListDescendent(ctx context.Context, userCred mcclient.TokenCredential, model db.IStandaloneModel, query jsonutils.JSONObject) bool {
+13 -1
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -207,7 +208,18 @@ func (manager *SSchedtagManager) ValidateCreateData(ctx context.Context, userCre
if err != nil {
return nil, err
}
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
input := apis.StandaloneResourceCreateInput{}
err = data.Unmarshal(&input)
if err != nil {
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
}
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return nil, err
}
data.Update(jsonutils.Marshal(input))
return data, nil
}
func (manager *SSchedtagManager) GetResourceSchedtags(resType string) ([]SSchedtag, error) {

Some files were not shown because too many files have changed in this diff Show More