mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-30 18:23:35 +08:00
recode quota and usage for image service
This commit is contained in:
@@ -450,4 +450,29 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type ImageChangeOwnerOptions struct {
|
||||
ID string `help:"Image to change owner"`
|
||||
PROJECT string `help:"Project ID or change"`
|
||||
RawId bool `help:"User raw ID, instead of name"`
|
||||
}
|
||||
R(&ImageChangeOwnerOptions{}, "image-change-owner", "Change owner project of an image", func(s *mcclient.ClientSession, opts *ImageChangeOwnerOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if opts.RawId {
|
||||
projid, err := modules.Projects.GetId(s, opts.PROJECT, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(projid), "tenant")
|
||||
params.Add(jsonutils.JSONTrue, "raw_id")
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(opts.PROJECT), "tenant")
|
||||
}
|
||||
srv, err := modules.Images.PerformAction(s, opts.ID, "change-owner", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(srv)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type QuotaBaseOptions struct {
|
||||
Cpu int64 `help:"CPU count" json:"cpu:omitzero"`
|
||||
Cpu int64 `help:"CPU count" json:"cpu,omitzero"`
|
||||
Memory int64 `help:"Memory size in MB" json:"memory,omitzero"`
|
||||
Storage int64 `help:"Storage size in MB" json:"storage,omitzero"`
|
||||
Port int64 `help:"Internal NIC count" json:"port,omitzero"`
|
||||
@@ -17,10 +17,7 @@ type QuotaBaseOptions struct {
|
||||
Ebw int64 `help:"External bandwidth in Mbps" json:"ebw,omitzero"`
|
||||
IsolatedDevice int64 `help:"Isolated device count" json:"isolated_device,omitzero"`
|
||||
Snapshot int64 `help:"Snapshot count" json:"snapshot,omitzero"`
|
||||
}
|
||||
|
||||
type ImageQuotaBaseOptions struct {
|
||||
Image int64 `help:"Template count" json:"image,omitzero"`
|
||||
Image int64 `help:"Template count" json:"image,omitzero"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -60,20 +57,6 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type ImageQuotaSetOptions struct {
|
||||
Tenant string `help:"Tenant name or ID to set quota" json:"tenant,omitempty"`
|
||||
ImageQuotaBaseOptions
|
||||
}
|
||||
R(&ImageQuotaSetOptions{}, "image-quota-set", "Set image quota for tenant", func(s *mcclient.ClientSession, args *ImageQuotaSetOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, e := modules.ImageQuotas.DoQuotaSet(s, params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type QuotaCheckOptions struct {
|
||||
TENANT string `help:"Tenant name or ID to check quota" json:"tenant,omitempty"`
|
||||
QuotaBaseOptions
|
||||
@@ -88,18 +71,4 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type ImageQuotaCheckOptions struct {
|
||||
TENANT string `help:"Tenant name or ID to check quota" json:"tenant,omitempty"`
|
||||
ImageQuotaBaseOptions
|
||||
}
|
||||
R(&ImageQuotaCheckOptions{}, "image-quota-check", "Check quota for tenant", func(s *mcclient.ClientSession, args *ImageQuotaCheckOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, e := modules.ImageQuotas.DoQuotaCheck(s, params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func init() {
|
||||
if args.Project != "" {
|
||||
params.Add(jsonutils.NewString(args.Project), "project")
|
||||
}
|
||||
result, err := modules.ImageUsages.GetUsage(s, params)
|
||||
result, err := modules.Images.GetUsage(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+61
-24
@@ -20,7 +20,6 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"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/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/image/options"
|
||||
@@ -650,41 +649,79 @@ type SImageUsage struct {
|
||||
Size int64
|
||||
}
|
||||
|
||||
func (manager *SImageManager) count(projectId string, isISO tristate.TriState, pendingDelete bool) SImageUsage {
|
||||
images := manager.Query().SubQuery()
|
||||
q := images.Query(sqlchemy.COUNT("count"), sqlchemy.SUM("size", images.Field("size")))
|
||||
func (manager *SImageManager) count(projectId string, status string, isISO tristate.TriState, pendingDelete bool) map[string]SImageUsage {
|
||||
sq := manager.Query("id")
|
||||
if len(projectId) > 0 {
|
||||
q = q.Equals("tenant_id", projectId)
|
||||
sq = sq.Equals("tenant_id", projectId)
|
||||
}
|
||||
if len(status) > 0 {
|
||||
sq = sq.Equals("status", status)
|
||||
}
|
||||
if pendingDelete {
|
||||
q = q.IsTrue("pending_deleted")
|
||||
sq = sq.IsTrue("pending_deleted")
|
||||
} else {
|
||||
q = q.IsFalse("pending_deleted")
|
||||
sq = sq.IsFalse("pending_deleted")
|
||||
}
|
||||
if isISO.IsTrue() {
|
||||
q = q.Equals("disk_format", "iso")
|
||||
sq = sq.Equals("disk_format", "iso")
|
||||
} else if isISO.IsFalse() {
|
||||
q = q.NotEquals("disk_format", "iso")
|
||||
sq = sq.NotEquals("disk_format", "iso")
|
||||
}
|
||||
subimages := ImageSubformatManager.Query().SubQuery()
|
||||
q := subimages.Query(subimages.Field("format"),
|
||||
sqlchemy.COUNT("count"),
|
||||
sqlchemy.SUM("size", subimages.Field("size")))
|
||||
q = q.In("image_id", sq.SubQuery())
|
||||
q = q.GroupBy(subimages.Field("format"))
|
||||
type sFormatImageUsage struct {
|
||||
Format string
|
||||
Count int64
|
||||
Size int64
|
||||
}
|
||||
var usages []sFormatImageUsage
|
||||
err := q.All(&usages)
|
||||
if err != nil {
|
||||
log.Errorf("query usage fail %s", err)
|
||||
return nil
|
||||
}
|
||||
ret := make(map[string]SImageUsage)
|
||||
totalSize := int64(0)
|
||||
for _, u := range usages {
|
||||
ret[u.Format] = SImageUsage{Count: u.Count, Size: u.Size}
|
||||
totalSize += u.Size
|
||||
}
|
||||
ret["total"] = SImageUsage{Count: int64(sq.Count()), Size: totalSize}
|
||||
return ret
|
||||
}
|
||||
|
||||
func expandUsageCount(usages map[string]int64, prefix, imgType, state string, count map[string]SImageUsage) {
|
||||
for k, u := range count {
|
||||
key := []string{}
|
||||
if len(prefix) > 0 {
|
||||
key = append(key, prefix)
|
||||
}
|
||||
key = append(key, imgType)
|
||||
if len(state) > 0 {
|
||||
key = append(key, state)
|
||||
}
|
||||
key = append(key, k)
|
||||
countKey := strings.Join(append(key, "count"), ".")
|
||||
sizeKey := strings.Join(append(key, "size"), ".")
|
||||
usages[countKey] = u.Count
|
||||
usages[sizeKey] = u.Size
|
||||
}
|
||||
usage := SImageUsage{}
|
||||
q.First(&usage)
|
||||
return usage
|
||||
}
|
||||
|
||||
func (manager *SImageManager) Usage(projectId string, prefix string) map[string]int64 {
|
||||
usages := make(map[string]int64)
|
||||
count := manager.count(projectId, tristate.False, false)
|
||||
usages[quotas.KeyName(prefix, "img.count")] = count.Count
|
||||
usages[quotas.KeyName(prefix, "img.size")] = count.Size
|
||||
count = manager.count(projectId, tristate.True, false)
|
||||
usages[quotas.KeyName(prefix, "iso.count")] = count.Count
|
||||
usages[quotas.KeyName(prefix, "iso.size")] = count.Size
|
||||
count = manager.count(projectId, tristate.False, true)
|
||||
usages[quotas.KeyName(prefix, "img.pending_delete.count")] = count.Count
|
||||
usages[quotas.KeyName(prefix, "img.pending_delete.size")] = count.Size
|
||||
count = manager.count(projectId, tristate.True, true)
|
||||
usages[quotas.KeyName(prefix, "iso.pending_delete.count")] = count.Count
|
||||
usages[quotas.KeyName(prefix, "iso.pending_delete.size")] = count.Size
|
||||
count := manager.count(projectId, IMAGE_STATUS_ACTIVE, tristate.False, false)
|
||||
expandUsageCount(usages, prefix, "img", "", count)
|
||||
count = manager.count(projectId, IMAGE_STATUS_ACTIVE, tristate.True, false)
|
||||
expandUsageCount(usages, prefix, "iso", "", count)
|
||||
count = manager.count(projectId, "", tristate.False, true)
|
||||
expandUsageCount(usages, prefix, "img", "pending_delete", count)
|
||||
count = manager.count(projectId, "", tristate.True, true)
|
||||
expandUsageCount(usages, prefix, "iso", "pending_delete", count)
|
||||
return usages
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ func init() {
|
||||
dbStore := quotas.NewDBQuotaStore()
|
||||
pendingStore := quotas.NewMemoryQuotaStore()
|
||||
|
||||
QuotaManager = quotas.NewQuotaManager("image-quotas", SQuota{}, dbStore, pendingStore)
|
||||
QuotaManager = quotas.NewQuotaManager("quotas", SQuota{}, dbStore, pendingStore)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -33,8 +33,8 @@ func (self *SQuota) FetchSystemQuota() {
|
||||
}
|
||||
|
||||
func (self *SQuota) FetchUsage(ctx context.Context, projectId string) error {
|
||||
count := ImageManager.count(projectId, tristate.None, false)
|
||||
self.Image = int(count.Count)
|
||||
count := ImageManager.count(projectId, "", tristate.None, false)
|
||||
self.Image = int(count["total"].Count)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ func ReportGeneralUsage(ctx context.Context, w http.ResponseWriter, r *http.Requ
|
||||
var adminUsage map[string]int64
|
||||
var projectUsage map[string]int64
|
||||
if isAdmin {
|
||||
adminUsage = models.ImageManager.Usage(userCred.GetProjectId(), "all")
|
||||
adminUsage = models.ImageManager.Usage("", "all")
|
||||
}
|
||||
|
||||
isProject := false
|
||||
|
||||
@@ -210,7 +210,7 @@ func (this *ImageManager) countUsage(session *mcclient.ClientSession, deleted bo
|
||||
}
|
||||
|
||||
func (this *ImageManager) GetUsage(session *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
body := jsonutils.NewDict()
|
||||
/*body := jsonutils.NewDict()
|
||||
pendingDelete := jsonutils.NewDict()
|
||||
for deleted, data := range map[bool]*jsonutils.JSONDict{false: body, true: pendingDelete} {
|
||||
if ret, err := this.countUsage(session, deleted); err != nil {
|
||||
@@ -226,6 +226,8 @@ func (this *ImageManager) GetUsage(session *mcclient.ClientSession, params jsonu
|
||||
}
|
||||
body.Add(pendingDelete, "pending_delete")
|
||||
return body, nil
|
||||
*/
|
||||
return ImageUsages.GetUsage(session, params)
|
||||
}
|
||||
|
||||
func setImageMeta(params jsonutils.JSONObject) (http.Header, error) {
|
||||
|
||||
@@ -27,32 +27,55 @@ func (this *QuotaManager) getURL(params jsonutils.JSONObject) string {
|
||||
}
|
||||
|
||||
func (this *QuotaManager) GetQuota(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
return this._get(s, this.getURL(params), this.KeywordPlural)
|
||||
computeQuota, err := this._get(s, this.getURL(params), this.KeywordPlural)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imageQuota, err := ImageQuotas._get(s, ImageQuotas.getURL(params), ImageQuotas.KeywordPlural)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
computeQuotaDict := computeQuota.(*jsonutils.JSONDict)
|
||||
computeQuotaDict.Update(imageQuota)
|
||||
return computeQuotaDict, nil
|
||||
}
|
||||
|
||||
func (this *QuotaManager) DoQuotaSet(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
url := this.getURL(params)
|
||||
func (this *QuotaManager) doPost(s *mcclient.ClientSession, params jsonutils.JSONObject, url string) (jsonutils.JSONObject, error) {
|
||||
quotas, ok := params.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Invalid input")
|
||||
}
|
||||
data := quotas.Copy("tenant", "user")
|
||||
body := jsonutils.NewDict()
|
||||
body.Add(data, this.KeywordPlural)
|
||||
return this._post(s, url, body, this.KeywordPlural)
|
||||
data := quotas.CopyExcludes("tenant", "user", "image")
|
||||
var err error
|
||||
if data.Size() > 0 {
|
||||
body := jsonutils.NewDict()
|
||||
body.Add(data, this.KeywordPlural)
|
||||
_, err = this._post(s, url, body, this.KeywordPlural)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
data = quotas.CopyIncludes("image")
|
||||
if data.Size() > 0 {
|
||||
body := jsonutils.NewDict()
|
||||
body.Add(data, ImageQuotas.KeywordPlural)
|
||||
_, err = ImageQuotas._post(s, url, body, ImageQuotas.KeywordPlural)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return jsonutils.NewDict(), nil
|
||||
}
|
||||
|
||||
func (this *QuotaManager) DoQuotaSet(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
url := this.getURL(params)
|
||||
return this.doPost(s, params, url)
|
||||
}
|
||||
|
||||
func (this *QuotaManager) DoQuotaCheck(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
url := this.getURL(params)
|
||||
url = fmt.Sprintf("%s/check_quota", url)
|
||||
quotas, ok := params.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Invalid input")
|
||||
}
|
||||
data := quotas.Copy("tenant", "user")
|
||||
body := jsonutils.NewDict()
|
||||
body.Add(data, this.KeywordPlural)
|
||||
return this._post(s, url, body, this.KeywordPlural)
|
||||
return this.doPost(s, params, url)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -66,8 +89,8 @@ func init() {
|
||||
[]string{})}
|
||||
registerCompute(&Quotas)
|
||||
|
||||
ImageQuotas = QuotaManager{NewImageManager("image-quota", "image-quotas",
|
||||
ImageQuotas = QuotaManager{NewImageManager("quota", "quotas",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
registerV2(&ImageQuotas)
|
||||
// registerV2(&ImageQuotas)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user