diff --git a/go.mod b/go.mod index ed8f38cbed..6074de2507 100644 --- a/go.mod +++ b/go.mod @@ -155,7 +155,7 @@ require ( yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7 yunion.io/x/pkg v0.0.0-20220406030238-39fbc60d5d4e yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e - yunion.io/x/sqlchemy v0.0.0-20220411140620-728b325acd1c + yunion.io/x/sqlchemy v0.0.0-20220413030837-de1642aeb626 yunion.io/x/structarg v0.0.0-20220312084958-9c6c79c7d1c6 ) diff --git a/go.sum b/go.sum index cf8edc9141..a31c858254 100644 --- a/go.sum +++ b/go.sum @@ -998,7 +998,7 @@ yunion.io/x/pkg v0.0.0-20220406030238-39fbc60d5d4e h1:ovxSHuAa8hOBiZPU+ezrwqmVuC yunion.io/x/pkg v0.0.0-20220406030238-39fbc60d5d4e/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-20220411140620-728b325acd1c h1:fgVbPIAVbdgnUo0JPyDR6acRh8i2PMk9k0MiveUGJw4= -yunion.io/x/sqlchemy v0.0.0-20220411140620-728b325acd1c/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI= +yunion.io/x/sqlchemy v0.0.0-20220413030837-de1642aeb626 h1:fueDcEnHrVrT8alcmOZrPeeaMMVtqCFm9jTPM/Yj0Ns= +yunion.io/x/sqlchemy v0.0.0-20220413030837-de1642aeb626/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI= yunion.io/x/structarg v0.0.0-20220312084958-9c6c79c7d1c6 h1:WuWXhY3DvhdRTzWCJ/kwt3Ss6KIq7+KqJwb+esvNGwU= yunion.io/x/structarg v0.0.0-20220312084958-9c6c79c7d1c6/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng= diff --git a/pkg/apis/compute/host.go b/pkg/apis/compute/host.go index e3c79088fb..c4e5205288 100644 --- a/pkg/apis/compute/host.go +++ b/pkg/apis/compute/host.go @@ -132,6 +132,18 @@ type HostListInput struct { // 按存储大小排序 // enmu: asc,desc OrderByStorage string `json:"order_by_storage"` + + // 按存储超分率排序 + // enmu: asc,desc + OrderByStorageCommitRate string `json:"order_by_storage_commit_rate"` + + // 按cpu超分率排序 + // enmu: asc,desc + OrderByCpuCommitRate string `json:"order_by_cpu_commit_rate"` + + // 按内存超分率排序 + // enmu: asc,desc + OrderByMemCommitRate string `json:"order_by_mem_commit_rate"` } type HostDetails struct { diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 535bd37d39..b0d9695a83 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -491,6 +491,38 @@ func (manager *SHostManager) OrderByExtraFields( db.OrderByFields(q, []string{query.OrderByServerCount}, []sqlchemy.IQueryField{guestCounts.Field("guest_count")}) } + if db.NeedOrderQuery([]string{query.OrderByCpuCommitRate}) { + guestsQ := GuestManager.Query() + if options.Options.IgnoreNonrunningGuests { + guestsQ = guestsQ.Equals("status", api.VM_RUNNING) + } + guests := guestsQ.SubQuery() + hosts := HostManager.Query().SubQuery() + hostQ := hosts.Query( + hosts.Field("id"), + hosts.Field("cpu_count"), + hosts.Field("cpu_reserved"), + sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")), + ).LeftJoin(guests, sqlchemy.Equals(hosts.Field("id"), guests.Field("host_id"))) + + hostSQ := hostQ.GroupBy(hostQ.Field("host_id")).SubQuery() + + divSQ := hostSQ.Query( + hostSQ.Field("id"), + sqlchemy.SUB("vcpu_count", hostSQ.Field("cpu_count"), hostSQ.Field("cpu_reserved")), + hostSQ.Field("guest_vcpu_count"), + ).SubQuery() + + sq := divSQ.Query( + divSQ.Field("id").Label("host_id"), + sqlchemy.DIV("cpu_commit_rate", divSQ.Field("guest_vcpu_count"), divSQ.Field("vcpu_count")), + ).SubQuery() + + q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("host_id"))) + + db.OrderByFields(q, []string{query.OrderByCpuCommitRate}, []sqlchemy.IQueryField{sq.Field("cpu_commit_rate")}) + } + if db.NeedOrderQuery([]string{query.OrderByStorage}) { hoststorages := HoststorageManager.Query().SubQuery() storages := StorageManager.Query().IsTrue("enabled").In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery() @@ -498,6 +530,7 @@ func (manager *SHostManager) OrderByExtraFields( hoststorages.Field("host_id"), sqlchemy.SUM("storage_capacity", storages.Field("capacity")), ) + hoststoragesQ = hoststoragesQ.LeftJoin(storages, sqlchemy.Equals(hoststoragesQ.Field("storage_id"), storages.Field("id"))) hoststoragesSQ := hoststoragesQ.GroupBy(hoststoragesQ.Field("host_id")).SubQuery() @@ -505,6 +538,78 @@ func (manager *SHostManager) OrderByExtraFields( db.OrderByFields(q, []string{query.OrderByStorage}, []sqlchemy.IQueryField{hoststoragesSQ.Field("storage_capacity")}) } + if db.NeedOrderQuery([]string{query.OrderByStorageCommitRate}) { + hoststorages := HoststorageManager.Query().SubQuery() + disks := DiskManager.Query().Equals("status", api.DISK_READY).SubQuery() + storages := StorageManager.Query().IsTrue("enabled").In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery() + + disksQ := disks.Query( + disks.Field("storage_id"), + sqlchemy.SUM("disk_size", disks.Field("disk_size")), + storages.Field("capacity"), + storages.Field("reserved"), + ).LeftJoin(storages, sqlchemy.Equals(disks.Field("storage_id"), storages.Field("id"))) + + disksSQ := disksQ.GroupBy(disksQ.Field("storage_id")).SubQuery() + + divSQ := disksSQ.Query( + disksSQ.Field("storage_id"), + disksSQ.Field("disk_size"), + sqlchemy.SUB("storage_capacity", disksSQ.Field("capacity"), disksSQ.Field("reserved")), + ).SubQuery() + + hoststoragesQ := hoststorages.Query( + hoststorages.Field("host_id"), + sqlchemy.SUM("storage_used", divSQ.Field("disk_size")), + sqlchemy.SUM("storage_capacity", divSQ.Field("storage_capacity")), + ) + hoststoragesQ = hoststoragesQ.LeftJoin(divSQ, sqlchemy.Equals(hoststoragesQ.Field("storage_id"), divSQ.Field("storage_id"))) + hoststoragesSQ1 := hoststoragesQ.GroupBy(hoststoragesQ.Field("host_id")).SubQuery() + + hoststoragesSQ := hoststoragesSQ1.Query( + hoststoragesSQ1.Field("host_id"), + sqlchemy.DIV("storage_commit_rate", + hoststoragesSQ1.Field("storage_used"), + hoststoragesSQ1.Field("storage_capacity"), + ), + ).SubQuery() + + q = q.LeftJoin(hoststoragesSQ, sqlchemy.Equals(q.Field("id"), hoststoragesSQ.Field("host_id"))) + db.OrderByFields(q, []string{query.OrderByStorageCommitRate}, []sqlchemy.IQueryField{hoststoragesSQ.Field("storage_commit_rate")}) + } + + if db.NeedOrderQuery([]string{query.OrderByMemCommitRate}) { + guestsQ := GuestManager.Query() + if options.Options.IgnoreNonrunningGuests { + guestsQ = guestsQ.Equals("status", api.VM_RUNNING) + } + guests := guestsQ.SubQuery() + hosts := HostManager.Query().SubQuery() + hostQ := hosts.Query( + hosts.Field("id"), + hosts.Field("mem_size"), + hosts.Field("mem_reserved"), + sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")), + ).LeftJoin(guests, sqlchemy.Equals(hosts.Field("id"), guests.Field("host_id"))) + + hostSQ := hostQ.GroupBy(hostQ.Field("host_id")).SubQuery() + + divSQ := hostSQ.Query( + hostSQ.Field("id"), + sqlchemy.SUB("vmem_size", hostSQ.Field("mem_size"), hostSQ.Field("mem_reserved")), + hostSQ.Field("guest_vmem_size"), + ).SubQuery() + + sq := divSQ.Query( + divSQ.Field("id").Label("host_id"), + sqlchemy.DIV("mem_commit_rate", divSQ.Field("guest_vmem_size"), divSQ.Field("vmem_size")), + ).SubQuery() + + q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("host_id"))) + + db.OrderByFields(q, []string{query.OrderByMemCommitRate}, []sqlchemy.IQueryField{sq.Field("mem_commit_rate")}) + } + return q, nil } diff --git a/pkg/mcclient/options/compute/host.go b/pkg/mcclient/options/compute/host.go index 310f2542fd..029951b953 100644 --- a/pkg/mcclient/options/compute/host.go +++ b/pkg/mcclient/options/compute/host.go @@ -52,8 +52,11 @@ type HostListOptions struct { Sn string `help:"find host by sn"` - OrderByServerCount string `help:"Order by server count" choices:"desc|asc"` - OrderByStorage string `help:"Order by host storage" choices:"desc|asc"` + OrderByServerCount string `help:"Order by server count" choices:"desc|asc"` + OrderByStorage string `help:"Order by host storage" choices:"desc|asc"` + OrderByStorageCommitRate string `help:"Order by host storage commite rate" choices:"desc|asc"` + OrderByCpuCommitRate string `help:"Order by host cpu commit rate" choices:"desc|asc"` + OrderByMemCommitRate string `help:"Order by host meme commit rate" choices:"desc|asc"` options.BaseListOptions } diff --git a/vendor/modules.txt b/vendor/modules.txt index 26daee3376..0b4e417500 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1265,7 +1265,7 @@ yunion.io/x/pkg/util/workqueue yunion.io/x/pkg/utils # yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e yunion.io/x/s3cli -# yunion.io/x/sqlchemy v0.0.0-20220411140620-728b325acd1c +# yunion.io/x/sqlchemy v0.0.0-20220413030837-de1642aeb626 yunion.io/x/sqlchemy yunion.io/x/sqlchemy/backends yunion.io/x/sqlchemy/backends/clickhouse diff --git a/vendor/yunion.io/x/sqlchemy/functions.go b/vendor/yunion.io/x/sqlchemy/functions.go index ff1811745e..2cb55ff7c1 100644 --- a/vendor/yunion.io/x/sqlchemy/functions.go +++ b/vendor/yunion.io/x/sqlchemy/functions.go @@ -287,3 +287,27 @@ func TimestampAdd(name string, field IQueryField, offsetSeconds int) IQueryField func CAST(field IQueryField, typeStr string, fieldname string) IQueryField { return NewFunctionField(fieldname, `CAST(%s AS `+typeStr+`)`, field) } + +func bc(name, op string, fields ...IQueryField) IQueryField { + exps := []string{} + for i := 0; i < len(fields); i++ { + exps = append(exps, "%s") + } + return NewFunctionField(name, strings.Join(exps, fmt.Sprintf(" %s ", op)), fields...) +} + +func ADD(name string, fields ...IQueryField) IQueryField { + return bc(name, "+", fields...) +} + +func SUB(name string, fields ...IQueryField) IQueryField { + return bc(name, "-", fields...) +} + +func MUL(name string, fields ...IQueryField) IQueryField { + return bc(name, "*", fields...) +} + +func DIV(name string, fields ...IQueryField) IQueryField { + return bc(name, "/", fields...) +}