Retrieve only resource count on user dashboard (#7617)

* Allow retrieving only the count of resources on APIs listPublicIpAddresses, listNetworks, listVirtualMachines and listVolumes

* Use parameter to retrieve only the count of resources in the dashboard

* Create abstract class
This commit is contained in:
Daniel Augusto Veronezi Salvador 2023-06-30 11:09:55 -03:00 committed by GitHub
parent 5975ea80c9
commit c6237c48ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 83 additions and 45 deletions

View File

@ -372,6 +372,7 @@ public class ApiConstants {
public static final String RESOURCE_TYPE = "resourcetype";
public static final String RESOURCE_TYPE_NAME = "resourcetypename";
public static final String RESPONSE = "response";
public static final String RETRIEVE_ONLY_RESOURCE_COUNT = "retrieveonlyresourcecount";
public static final String REVERTABLE = "revertable";
public static final String REVOKED = "revoked";
public static final String REGISTERED = "registered";

View File

@ -0,0 +1,28 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 org.apache.cloudstack.api;
import org.apache.commons.lang3.BooleanUtils;
public abstract class BaseListRetrieveOnlyResourceCountCmd extends BaseListTaggedResourcesCmd {
@Parameter(name = ApiConstants.RETRIEVE_ONLY_RESOURCE_COUNT, type = CommandType.BOOLEAN, description = "makes the API's response contains only the resource count")
private Boolean retrieveOnlyResourceCount;
public Boolean getRetrieveOnlyResourceCount() {
return BooleanUtils.toBooleanDefaultIfNull(retrieveOnlyResourceCount, false);
}
}

View File

@ -25,7 +25,7 @@ import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
import org.apache.cloudstack.api.BaseListRetrieveOnlyResourceCountCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.UserCmd;
@ -42,7 +42,7 @@ import com.cloud.utils.Pair;
@APICommand(name = "listPublicIpAddresses", description = "Lists all public IP addresses", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class })
public class ListPublicIpAddressesCmd extends BaseListTaggedResourcesCmd implements UserCmd {
public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd {
public static final Logger s_logger = Logger.getLogger(ListPublicIpAddressesCmd.class.getName());
private static final String s_name = "listpublicipaddressesresponse";
@ -173,10 +173,6 @@ public class ListPublicIpAddressesCmd extends BaseListTaggedResourcesCmd impleme
return forVirtualNetwork;
}
public Boolean getForLoadBalancing() {
return forLoadBalancing;
}
public String getState() {
return state;
}
@ -194,10 +190,13 @@ public class ListPublicIpAddressesCmd extends BaseListTaggedResourcesCmd impleme
Pair<List<? extends IpAddress>, Integer> result = _mgr.searchForIPAddresses(this);
ListResponse<IPAddressResponse> response = new ListResponse<>();
List<IPAddressResponse> ipAddrResponses = new ArrayList<>();
for (IpAddress ipAddress : result.first()) {
IPAddressResponse ipResponse = _responseGenerator.createIPAddressResponse(getResponseView(), ipAddress);
ipResponse.setObjectName("publicipaddress");
ipAddrResponses.add(ipResponse);
if (!getRetrieveOnlyResourceCount()) {
for (IpAddress ipAddress : result.first()) {
IPAddressResponse ipResponse = _responseGenerator.createIPAddressResponse(getResponseView(), ipAddress);
ipResponse.setObjectName("publicipaddress");
ipAddrResponses.add(ipResponse);
}
}
response.setResponses(ipAddrResponses, result.second());

View File

@ -23,12 +23,13 @@ import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
import org.apache.cloudstack.api.BaseListRetrieveOnlyResourceCountCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.UserCmd;
@ -44,7 +45,7 @@ import org.apache.commons.lang3.StringUtils;
@APICommand(name = "listNetworks", description = "Lists all available networks.", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListNetworksCmd extends BaseListTaggedResourcesCmd implements UserCmd {
public class ListNetworksCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd {
public static final Logger s_logger = Logger.getLogger(ListNetworksCmd.class.getName());
private static final String s_name = "listnetworksresponse";
@ -190,14 +191,11 @@ public class ListNetworksCmd extends BaseListTaggedResourcesCmd implements UserC
@Override
public Boolean getDisplay() {
if (display != null) {
return display;
}
return super.getDisplay();
return BooleanUtils.toBooleanDefaultIfNull(display, super.getDisplay());
}
public Boolean getShowIcon() {
return showIcon != null ? showIcon : false;
return BooleanUtils.toBooleanDefaultIfNull(showIcon, false);
}
public String getNetworkFilter() {
@ -215,16 +213,21 @@ public class ListNetworksCmd extends BaseListTaggedResourcesCmd implements UserC
@Override
public void execute() {
Pair<List<? extends Network>, Integer> networks = _networkService.searchForNetworks(this);
ListResponse<NetworkResponse> response = new ListResponse<NetworkResponse>();
List<NetworkResponse> networkResponses = new ArrayList<NetworkResponse>();
for (Network network : networks.first()) {
NetworkResponse networkResponse = _responseGenerator.createNetworkResponse(getResponseView(), network);
networkResponses.add(networkResponse);
ListResponse<NetworkResponse> response = new ListResponse<>();
List<NetworkResponse> networkResponses = new ArrayList<>();
if (!getRetrieveOnlyResourceCount()) {
for (Network network : networks.first()) {
NetworkResponse networkResponse = _responseGenerator.createNetworkResponse(getResponseView(), network);
networkResponses.add(networkResponse);
}
}
response.setResponses(networkResponses, networks.second());
response.setResponseName(getCommandName());
setResponseObject(response);
if (response != null && response.getCount() > 0 && getShowIcon()) {
if (!getRetrieveOnlyResourceCount() && response.getCount() > 0 && getShowIcon()) {
updateNetworkResponse(response.getResponses());
}
}

View File

@ -26,7 +26,7 @@ import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
import org.apache.cloudstack.api.BaseListRetrieveOnlyResourceCountCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.UserCmd;
@ -44,6 +44,7 @@ import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VpcResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.log4j.Logger;
import com.cloud.exception.InvalidParameterValueException;
@ -54,7 +55,7 @@ import com.cloud.vm.VirtualMachine;
@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
public class ListVMsCmd extends BaseListTaggedResourcesCmd implements UserCmd {
public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd {
public static final Logger s_logger = Logger.getLogger(ListVMsCmd.class.getName());
private static final String s_name = "listvirtualmachinesresponse";
@ -148,7 +149,6 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd implements UserCmd {
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.BOOLEAN, description = "Whether to return the VMs' user data or not. By default, user data will not be returned.", since = "4.18.0.0")
private Boolean showUserData;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -255,14 +255,11 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd implements UserCmd {
@Override
public Boolean getDisplay() {
if (display != null) {
return display;
}
return super.getDisplay();
return BooleanUtils.toBooleanDefaultIfNull(display, super.getDisplay());
}
public Boolean getShowIcon() {
return showIcon != null ? showIcon : false;
return BooleanUtils.toBooleanDefaultIfNull(showIcon, false);
}
public Boolean getAccumulate() {

View File

@ -22,7 +22,7 @@ import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
import org.apache.cloudstack.api.BaseListRetrieveOnlyResourceCountCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.UserCmd;
@ -35,13 +35,14 @@ import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.log4j.Logger;
import com.cloud.storage.Volume;
@APICommand(name = "listVolumes", description = "Lists all volumes.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {
Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListVolumesCmd extends BaseListTaggedResourcesCmd implements UserCmd {
public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd {
public static final Logger s_logger = Logger.getLogger(ListVolumesCmd.class.getName());
private static final String s_name = "listvolumesresponse";
@ -145,15 +146,13 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd implements UserCm
@Override
public Boolean getDisplay() {
if (display != null) {
return display;
}
return super.getDisplay();
return BooleanUtils.toBooleanDefaultIfNull(display, super.getDisplay());
}
public String getState() {
return state;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -973,7 +973,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override
public ListResponse<UserVmResponse> searchForUserVMs(ListVMsCmd cmd) {
Pair<List<UserVmJoinVO>, Integer> result = searchForUserVMsInternal(cmd);
ListResponse<UserVmResponse> response = new ListResponse<UserVmResponse>();
ListResponse<UserVmResponse> response = new ListResponse<>();
if (cmd.getRetrieveOnlyResourceCount()) {
response.setResponses(new ArrayList<>(), result.second());
return response;
}
ResponseView respView = ResponseView.Restricted;
Account caller = CallContext.current().getCallingAccount();
if (_accountMgr.isRootAdmin(caller.getId())) {
@ -2062,7 +2068,12 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override
public ListResponse<VolumeResponse> searchForVolumes(ListVolumesCmd cmd) {
Pair<List<VolumeJoinVO>, Integer> result = searchForVolumesInternal(cmd);
ListResponse<VolumeResponse> response = new ListResponse<VolumeResponse>();
ListResponse<VolumeResponse> response = new ListResponse<>();
if (cmd.getRetrieveOnlyResourceCount()) {
response.setResponses(new ArrayList<>(), result.second());
return response;
}
ResponseView respView = cmd.getResponseView();
Account account = CallContext.current().getCallingAccount();

View File

@ -169,7 +169,7 @@ export default {
methods: {
fetchData () {
this.stats = [{}, {}, {}, {}, {}, {}]
api('listVirtualMachines', { state: 'Running', listall: true }).then(json => {
api('listVirtualMachines', { state: 'Running', listall: true, retrieveonlyresourcecount: true }).then(json => {
var count = 0
if (json && json.listvirtualmachinesresponse) {
count = json.listvirtualmachinesresponse.count
@ -177,7 +177,7 @@ export default {
var tileColor = this.$config.theme['@dashboard-tile-runningvms-bg'] || '#dfe9cc'
this.stats.splice(0, 1, { name: this.$t('label.running.vms'), count: count, icon: 'desktop-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'running', filter: 'running' } })
})
api('listVirtualMachines', { state: 'Stopped', listall: true }).then(json => {
api('listVirtualMachines', { state: 'Stopped', listall: true, retrieveonlyresourcecount: true }).then(json => {
var count = 0
if (json && json.listvirtualmachinesresponse) {
count = json.listvirtualmachinesresponse.count
@ -185,7 +185,7 @@ export default {
var tileColor = this.$config.theme['@dashboard-tile-stoppedvms-bg'] || '#edcbce'
this.stats.splice(1, 1, { name: this.$t('label.stopped.vms'), count: count, icon: 'poweroff-outlined', bgcolor: tileColor, path: '/vm', query: { state: 'stopped', filter: 'stopped' } })
})
api('listVirtualMachines', { listall: true }).then(json => {
api('listVirtualMachines', { listall: true, retrieveonlyresourcecount: true }).then(json => {
var count = 0
if (json && json.listvirtualmachinesresponse) {
count = json.listvirtualmachinesresponse.count
@ -193,7 +193,7 @@ export default {
var tileColor = this.$config.theme['@dashboard-tile-totalvms-bg'] || '#ffffff'
this.stats.splice(2, 1, { name: this.$t('label.total.vms'), count: count, icon: 'number-outlined', bgcolor: tileColor, path: '/vm' })
})
api('listVolumes', { listall: true }).then(json => {
api('listVolumes', { listall: true, retrieveonlyresourcecount: true }).then(json => {
var count = 0
if (json && json.listvolumesresponse) {
count = json.listvolumesresponse.count
@ -201,7 +201,7 @@ export default {
var tileColor = this.$config.theme['@dashboard-tile-totalvolumes-bg'] || '#ffffff'
this.stats.splice(3, 1, { name: this.$t('label.total.volume'), count: count, icon: 'database-outlined', bgcolor: tileColor, path: '/volume' })
})
api('listNetworks', { listall: true }).then(json => {
api('listNetworks', { listall: true, retrieveonlyresourcecount: true }).then(json => {
var count = 0
if (json && json.listnetworksresponse) {
count = json.listnetworksresponse.count
@ -209,7 +209,7 @@ export default {
var tileColor = this.$config.theme['@dashboard-tile-totalnetworks-bg'] || '#ffffff'
this.stats.splice(4, 1, { name: this.$t('label.total.network'), count: count, icon: 'apartment-outlined', bgcolor: tileColor, path: '/guestnetwork' })
})
api('listPublicIpAddresses', { listall: true }).then(json => {
api('listPublicIpAddresses', { listall: true, retrieveonlyresourcecount: true }).then(json => {
var count = 0
if (json && json.listpublicipaddressesresponse) {
count = json.listpublicipaddressesresponse.count