diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 2a63983462..254c7d64ee 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -100,7 +100,7 @@ const ( VM_RESTORE_STATE = "restore_state" VM_RESTORE_FAILED = "restore_failed" - VM_ASSOCIATE_EIP = "associate_eip" + VM_ASSOCIATE_EIP = "associate_eip" VM_DISSOCIATE_EIP = "dissociate_eip" VM_REMOVE_STATEFILE = "remove_state" @@ -276,8 +276,8 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ if count > 0 { sgq := guestdisks.Query(guestdisks.Field("guest_id")). Filter(sqlchemy.AND( - sqlchemy.Equals(guestdisks.Field("disk_id"), disk.Id), - sqlchemy.IsFalse(guestdisks.Field("deleted")))) + sqlchemy.Equals(guestdisks.Field("disk_id"), disk.Id), + sqlchemy.IsFalse(guestdisks.Field("deleted")))) q = q.Filter(sqlchemy.In(q.Field("id"), sgq)) } else { hosts := HostManager.Query().SubQuery() @@ -285,11 +285,11 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ storages := StorageManager.Query().SubQuery() sq := hosts.Query(hosts.Field("id")). Join(hoststorages, sqlchemy.AND( - sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id")), - sqlchemy.IsFalse(hoststorages.Field("deleted")))). + sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id")), + sqlchemy.IsFalse(hoststorages.Field("deleted")))). Join(storages, sqlchemy.AND( - sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")), - sqlchemy.IsFalse(storages.Field("deleted")))). + sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")), + sqlchemy.IsFalse(storages.Field("deleted")))). Filter(sqlchemy.Equals(storages.Field("id"), disk.StorageId)).SubQuery() q = q.In("host_id", sq) } @@ -343,8 +343,8 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ isodev := IsolatedDeviceManager.Query().SubQuery() sgq := isodev.Query(isodev.Field("guest_id")). Filter(sqlchemy.AND( - sqlchemy.IsNotNull(isodev.Field("guest_id")), - sqlchemy.Startswith(isodev.Field("dev_type"), "GPU"))) + sqlchemy.IsNotNull(isodev.Field("guest_id")), + sqlchemy.Startswith(isodev.Field("dev_type"), "GPU"))) showGpu := utils.ToBool(gpu) cond := sqlchemy.NotIn if showGpu { @@ -568,7 +568,7 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m resetPassword := jsonutils.QueryBoolean(data, "reset_password", true) passwd, _ := data.GetString("password") if resetPassword && len(passwd) > 0 { - if ! seclib2.MeetComplxity(passwd) { + if !seclib2.MeetComplxity(passwd) { return nil, httperrors.NewWeakPasswordError() } } @@ -1394,10 +1394,10 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient. func (manager *SGuestManager) TotalCount( projectId string, rangeObj db.IStandaloneModel, - status []string, hypervisor string, + status []string, hypervisors []string, includeSystem bool, pendingDelete bool, hostType string, ) SGuestCountStat { - return totalGuestResourceCount(projectId, rangeObj, status, hypervisor, includeSystem, pendingDelete, hostType) + return totalGuestResourceCount(projectId, rangeObj, status, hypervisors, includeSystem, pendingDelete, hostType) } func (self *SGuest) detachNetwork(ctx context.Context, userCred mcclient.TokenCredential, network *SNetwork, reserve bool, deploy bool) error { @@ -1910,8 +1910,15 @@ type SGuestCountStat struct { TotalIsolatedCount int } -func totalGuestResourceCount(projectId string, rangeObj db.IStandaloneModel, status []string, hypervisor string, - includeSystem bool, pendingDelete bool, hostType string) SGuestCountStat { +func totalGuestResourceCount( + projectId string, + rangeObj db.IStandaloneModel, + status []string, + hypervisors []string, + includeSystem bool, + pendingDelete bool, + hostType string, +) SGuestCountStat { guestdisks := GuestdiskManager.Query().SubQuery() disks := DiskManager.Query().SubQuery() @@ -1951,8 +1958,8 @@ func totalGuestResourceCount(projectId string, rangeObj db.IStandaloneModel, sta if len(status) > 0 { q = q.Filter(sqlchemy.In(guests.Field("status"), status)) } - if len(hypervisor) > 0 { - q = q.Filter(sqlchemy.Equals(guests.Field("hypervisor"), hypervisor)) + if len(hypervisors) > 0 { + q = q.Filter(sqlchemy.In(guests.Field("hypervisor"), hypervisors)) } if !includeSystem { q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(guests.Field("is_system")), sqlchemy.IsFalse(guests.Field("is_system")))) @@ -2440,7 +2447,7 @@ func (self *SGuest) AllowPerformRebuildRoot(ctx context.Context, userCred mcclie func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { imageId, _ := data.GetString("image_id") - if ! utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING, VM_ADMIN}) { + if !utils.IsInStringArray(self.Status, []string{VM_READY, VM_RUNNING, VM_ADMIN}) { return nil, httperrors.NewInvalidStatusError("Cannot reset root in status %s", self.Status) } @@ -2469,7 +2476,7 @@ func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.To resetPasswd := jsonutils.QueryBoolean(data, "reset_password", true) passwd, _ := data.GetString("password") if len(passwd) > 0 { - if ! seclib2.MeetComplxity(passwd) { + if !seclib2.MeetComplxity(passwd) { return nil, httperrors.NewWeakPasswordError() } } @@ -4008,7 +4015,7 @@ func (manager *SGuestManager) GetIpInProjectWithName(projectId, name string, isE sqlchemy.IsFalse(guests.Field("pending_deleted"))), sqlchemy.IsFalse(guests.Field("deleted")))). Join(networks, sqlchemy.AND(sqlchemy.Equals(networks.Field("id"), guestnics.Field("network_id")), - sqlchemy.IsFalse(networks.Field("deleted")))). + sqlchemy.IsFalse(networks.Field("deleted")))). Filter(sqlchemy.Equals(guests.Field("name"), name)). Filter(sqlchemy.NotEquals(guestnics.Field("ip_addr"), "")). Filter(sqlchemy.IsNotNull(guestnics.Field("ip_addr"))). diff --git a/pkg/compute/models/quotas.go b/pkg/compute/models/quotas.go index 8634b9c7a7..a92cb7c84b 100644 --- a/pkg/compute/models/quotas.go +++ b/pkg/compute/models/quotas.go @@ -70,7 +70,7 @@ func (self *SQuota) FetchSystemQuota() { func (self *SQuota) FetchUsage(projectId string) error { diskSize := totalDiskSize(projectId, tristate.None, tristate.None, false) net := totalGuestNicCount(projectId, nil, false) - guest := totalGuestResourceCount(projectId, nil, nil, "", false, false, "") + guest := totalGuestResourceCount(projectId, nil, nil, nil, false, false, "") eipUsage := ElasticipManager.TotalCount(projectId, nil, nil) // XXX // keypair belongs to user diff --git a/pkg/compute/usages/handler.go b/pkg/compute/usages/handler.go index b6212002df..5356c1e007 100644 --- a/pkg/compute/usages/handler.go +++ b/pkg/compute/usages/handler.go @@ -7,6 +7,10 @@ import ( json "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/tristate" + "yunion.io/x/pkg/util/sets" + "yunion.io/x/pkg/utils" + "yunion.io/x/onecloud/pkg/appctx" "yunion.io/x/onecloud/pkg/appsrv" "yunion.io/x/onecloud/pkg/cloudcommon/db" @@ -14,8 +18,6 @@ import ( "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/mcclient/auth" - "yunion.io/x/pkg/tristate" - "yunion.io/x/pkg/utils" ) type Usage map[string]interface{} @@ -160,12 +162,8 @@ func ReportCloudRegionUsage(userCred mcclient.TokenCredential, cloudRegion db.IS //func ReportGuestUsage() -func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) (count Usage, err error) { +func getAdminGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) (count Usage, err error) { count = ZoneUsage() - if !userCred.IsSystemAdmin() { - return - } - var pmemTotal float64 var pcpuTotal float64 @@ -181,9 +179,14 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo count.Add("memory.virtual", host.GetVirtualMemorySize()) count.Add("cpu.virtual", host.GetVirtualCPUCount()) } - guestRunningUsage := GuestRunningUsage(userCred, rangeObj, hostTypes) + guestRunningUsage := GuestRunningUsage("all.running_servers", nil, rangeObj, hostTypes) runningMem := guestRunningUsage.Get("all.running_servers.memory").(int) runningCpu := guestRunningUsage.Get("all.running_servers.cpu").(int) + containerRunningUsage := containerUsage("all.containers", nil, rangeObj) + containerRunningMem := containerRunningUsage.Get("all.containers.memory").(int) + containerRunningCpu := containerRunningUsage.Get("all.containers.cpu").(int) + runningMem += containerRunningMem + runningCpu += containerRunningCpu runningCpuCmtRate := 0.0 runningMemCmtRate := 0.0 if pmemTotal > 0 { @@ -209,19 +212,50 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo hostEnabledUsage, BaremetalUsage(userCred, rangeObj, hostTypes), storageUsage, - GuestNormalUsage(userCred, rangeObj, hostTypes), - GuestPendingDeleteUsage(userCred, rangeObj, hostTypes), - GuestReadyUsage(userCred, rangeObj, hostTypes), + GuestNormalUsage("all.servers", nil, rangeObj, hostTypes), + GuestPendingDeleteUsage("all.pending_delete_servers", nil, rangeObj, hostTypes), + GuestReadyUsage("all.ready_servers", nil, rangeObj, hostTypes), guestRunningUsage, + containerRunningUsage, IsolatedDeviceUsage(rangeObj, hostTypes), WireUsage(rangeObj, hostTypes), - NetworkUsage(userCred, rangeObj), EipUsage(rangeObj, hostTypes), ) return } +func getCommonGeneralUsage(cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) (count Usage, err error) { + guestNormalUsage := GuestNormalUsage("servers", cred, rangeObj, hostTypes) + guestRunningUsage := GuestRunningUsage("running_servers", cred, rangeObj, hostTypes) + guestPendingDeleteUsage := GuestPendingDeleteUsage("pending_delete_servers", cred, rangeObj, hostTypes) + guestReadyUsage := GuestReadyUsage("ready_servers", cred, rangeObj, hostTypes) + containerUsage := containerUsage("containers", cred, rangeObj) + count = guestNormalUsage.Include( + guestRunningUsage, + guestPendingDeleteUsage, + guestReadyUsage, + containerUsage, + ) + return +} + +func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) (count Usage, err error) { + count = make(map[string]interface{}) + if userCred.IsSystemAdmin() { + count, err = getAdminGeneralUsage(userCred, rangeObj, hostTypes) + if err != nil { + return + } + } + commonUsage, err := getCommonGeneralUsage(userCred, rangeObj, hostTypes) + if err != nil { + return + } + count.Include(commonUsage) + return +} + func ZoneUsage() Usage { count := make(map[string]interface{}) count["zones"] = models.ZoneManager.Count() @@ -294,27 +328,29 @@ func hostUsage( return count } -func GuestNormalUsage(cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { - prefix := "all.servers" +func GuestNormalUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { return guestUsage(prefix, cred, rangeObj, hostTypes, nil, false) } -func GuestPendingDeleteUsage(cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { - prefix := "all.pending_delete_servers" +func GuestPendingDeleteUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { return guestUsage(prefix, cred, rangeObj, hostTypes, nil, true) } -func GuestRunningUsage(cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { - prefix := "all.running_servers" +func GuestRunningUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { return guestUsage(prefix, cred, rangeObj, hostTypes, []string{models.VM_RUNNING}, false) } -func GuestReadyUsage(cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { - prefix := "all.ready_servers" +func GuestReadyUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage { return guestUsage(prefix, cred, rangeObj, hostTypes, []string{models.VM_READY}, false) } -func guestUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes, status []string, pendingDelete bool) Usage { +func guestHypervisorsUsage( + prefix string, + userCred mcclient.TokenCredential, + rangeObj db.IStandaloneModel, + hostTypes, status, hypervisors []string, + pendingDelete bool, +) Usage { hostType := "" if len(hostTypes) != 0 { hostType = hostTypes[0] @@ -323,17 +359,33 @@ func guestUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IS if userCred != nil { projectId = userCred.GetProjectId() } - guest := models.GuestManager.TotalCount(projectId, rangeObj, status, "", true, pendingDelete, hostType) + guest := models.GuestManager.TotalCount(projectId, rangeObj, status, hypervisors, true, pendingDelete, hostType) count := make(map[string]interface{}) count[prefix] = guest.TotalGuestCount count[fmt.Sprintf("%s.cpu", prefix)] = guest.TotalCpuCount count[fmt.Sprintf("%s.memory", prefix)] = guest.TotalMemSize + + if len(hypervisors) == 1 && hypervisors[0] == models.HYPERVISOR_CONTAINER { + return count + } + count[fmt.Sprintf("%s.disk", prefix)] = guest.TotalDiskSize count[fmt.Sprintf("%s.isolated_devices", prefix)] = guest.TotalIsolatedCount return count } +func guestUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes, status []string, pendingDelete bool) Usage { + hypervisors := sets.NewString(models.HYPERVISORS...) + hypervisors.Delete(models.HYPERVISOR_CONTAINER) + return guestHypervisorsUsage(prefix, userCred, rangeObj, hostTypes, status, hypervisors.List(), pendingDelete) +} + +func containerUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel) Usage { + hypervisors := []string{models.HYPERVISOR_CONTAINER} + return guestHypervisorsUsage(prefix, userCred, rangeObj, nil, nil, hypervisors, false) +} + func IsolatedDeviceUsage(rangeObj db.IStandaloneModel, hostType []string) Usage { prefix := "isolated_devices" ret := models.IsolatedDeviceManager.TotalCount(hostType, rangeObj)