Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@

package org.apache.cloudstack.api;

import java.util.List;

import javax.inject.Inject;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.metrics.MetricsService;
import org.apache.cloudstack.response.VmMetricsResponse;

import javax.inject.Inject;
import java.util.List;

/**
* API supported for backward compatibility. Use the {@link ListVMsUsageHistoryCmd} API instead. <br>
* The reasons for this are: <br>
Expand All @@ -42,9 +44,8 @@
*/
@APICommand(name = ListVMsMetricsCmd.APINAME, description = "Lists VM metrics", responseObject = VmMetricsResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full,
since = "4.9.3", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
@Deprecated(since = "4.17.0")
public class ListVMsMetricsCmd extends ListVMsCmd {
since = "4.9.3", authorized = {RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class ListVMsMetricsCmd extends ListVMsCmd implements UserCmd {
public static final String APINAME = "listVirtualMachinesMetrics";

@Inject
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// 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.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.command.admin.AdminCmd;
import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.response.VmMetricsResponse;

@APICommand(name = ListVMsMetricsCmd.APINAME, description = "Lists VM metrics", responseObject = VmMetricsResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full,
authorized = {RoleType.Admin})
public class ListVMsMetricsCmdByAdmin extends ListVMsMetricsCmd implements AdminCmd {

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////

@Parameter(name=ApiConstants.HOST_ID, type= BaseCmd.CommandType.UUID, entityType= HostResponse.class,
description="the host ID")
private Long hostId;

@Parameter(name=ApiConstants.POD_ID, type= BaseCmd.CommandType.UUID, entityType= PodResponse.class,
description="the pod ID")
private Long podId;

@Parameter(name=ApiConstants.STORAGE_ID, type= BaseCmd.CommandType.UUID, entityType= StoragePoolResponse.class,
description="the storage ID where vm's volumes belong to")
private Long storageId;

@Parameter(name = ApiConstants.CLUSTER_ID, type = BaseCmd.CommandType.UUID, entityType = ClusterResponse.class,
description = "the cluster ID")
private Long clusterId;


/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////

public Long getHostId() {
return hostId;
}

public Long getPodId() {
return podId;
}

public Long getStorageId() {
return storageId;
}

public Long getClusterId() {
return clusterId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.apache.cloudstack.metrics;

import static com.cloud.utils.NumbersUtil.toReadableSize;

import java.lang.reflect.InvocationTargetException;
import java.text.DecimalFormat;
import java.util.ArrayList;
Expand All @@ -28,14 +30,6 @@

import javax.inject.Inject;

import com.cloud.server.DbStatsCollection;
import com.cloud.server.StatsCollector;
import com.cloud.usage.UsageJobVO;
import com.cloud.usage.dao.UsageJobDao;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.db.DbUtil;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.script.Script;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ListClustersMetricsCmd;
import org.apache.cloudstack.api.ListDbMetricsCmd;
Expand All @@ -45,15 +39,16 @@
import org.apache.cloudstack.api.ListStoragePoolsMetricsCmd;
import org.apache.cloudstack.api.ListUsageServerMetricsCmd;
import org.apache.cloudstack.api.ListVMsMetricsCmd;
import org.apache.cloudstack.api.ListVMsMetricsCmdByAdmin;
import org.apache.cloudstack.api.ListVMsUsageHistoryCmd;
import org.apache.cloudstack.api.ListVolumesMetricsCmd;
import org.apache.cloudstack.api.ListZonesMetricsCmd;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.StatsResponse;
import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.StatsResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
Expand All @@ -76,6 +71,10 @@
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.log4j.Logger;

import com.cloud.agent.api.VmStatsEntryBase;
import com.cloud.alert.AlertManager;
Expand Down Expand Up @@ -103,13 +102,21 @@
import com.cloud.org.Cluster;
import com.cloud.org.Grouping;
import com.cloud.org.Managed;
import com.cloud.server.DbStatsCollection;
import com.cloud.server.ManagementServerHostStats;
import com.cloud.server.StatsCollector;
import com.cloud.usage.UsageJobVO;
import com.cloud.usage.dao.UsageJobDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.Pair;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.db.DbUtil;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.script.Script;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
Expand All @@ -119,12 +126,6 @@
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.dao.VmStatsDao;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.log4j.Logger;

import static com.cloud.utils.NumbersUtil.toReadableSize;

public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements MetricsService {
private static final Logger LOGGER = Logger.getLogger(MetricsServiceImpl.class);
Expand Down Expand Up @@ -878,6 +879,9 @@ public List<Class<?>> getCommands() {
cmdList.add(ListVolumesMetricsCmd.class);
cmdList.add(ListZonesMetricsCmd.class);
cmdList.add(ListVMsUsageHistoryCmd.class);

// separate Admin commands
cmdList.add(ListVMsMetricsCmdByAdmin.class);
return cmdList;
}

Expand Down
26 changes: 18 additions & 8 deletions server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
// under the License.
package com.cloud.api.query;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -65,7 +67,6 @@
import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd;
import org.apache.cloudstack.api.command.admin.template.ListTemplatesCmdByAdmin;
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
import org.apache.cloudstack.api.command.admin.vm.ListVMsCmdByAdmin;
import org.apache.cloudstack.api.command.admin.zone.ListZonesCmdByAdmin;
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
Expand Down Expand Up @@ -971,6 +972,17 @@ public ListResponse<UserVmResponse> searchForUserVMs(ListVMsCmd cmd) {
return response;
}

private Object getObjectPossibleMethodValue(Object obj, String methodName) {
Object result = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DaanHoogland could you add a unit test to cover this method?


try {
Method m = obj.getClass().getMethod(methodName);
result = m.invoke(obj);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not even logged?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps log here? @DaanHoogland or do you think we may never hit this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was thinking that as well, but didn´t want to change to much anymore. We will hit this for sure in the current state if ListVMsCmd is called in the API. It will try to add the attributes that don´t exist and we are supposed to ignore those.

Suggested change
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) {}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) {/*ignored when non-ByAdmin are calling this.*/}


return result;
}

private Pair<List<UserVmJoinVO>, Integer> searchForUserVMsInternal(ListVMsCmd cmd) {
Account caller = CallContext.current().getCallingAccount();
List<Long> permittedAccounts = new ArrayList<Long>();
Expand Down Expand Up @@ -1035,16 +1047,14 @@ private Pair<List<UserVmJoinVO>, Integer> searchForUserVMsInternal(ListVMsCmd cm
Object backupOfferingId = cmd.getBackupOfferingId();
Object isHaEnabled = cmd.getHaEnabled();
Object pod = null;
Long clusterId = null;
Object clusterId = null;
Object hostId = null;
Object storageId = null;
if (_accountMgr.isRootAdmin(caller.getId())) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DaanHoogland I am afraid the below code may not work as cmd will be an instance of ListVMsMetricsCmdByAdmin and not ListVMsCmdByAdmin

@DaanHoogland DaanHoogland Dec 9, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, you are right, thanks. so it needs to be checking for both possibilities.

You actually justified using reflection now, I didn´t see that before.

if (cmd instanceof ListVMsCmdByAdmin) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we remove this, do we still need the extra class, or can we just implement the extra parameters in ListVMsMetricsCmd?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ListVMsMetricsCmd is accessible to all users therefore new ByAdmin class added and new params not added in the original

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does that matter? they will just not be able to use the extra parameters.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think is this a common pattern (unless we want to deprecate this) used across 54 APIs:

> find . | grep ByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vmsnapshot/RevertToVMSnapshotCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/iso/UpdateIsoCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/iso/DetachIsoCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/iso/ListIsoPermissionsCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/iso/AttachIsoCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/iso/CopyIsoCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/iso/RegisterIsoCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/zone/ListZonesCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworksCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/template/CreateTemplateCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterTemplateCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateTemplateCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/template/CopyTemplateCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListTemplatePermissionsCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/StopVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DestroyVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ScaleVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVMsCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/StartVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/RebootVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/RemoveNicFromVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/UpdateDefaultNicForVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/UpgradeVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ResetVMSSHKeyCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/UpdateVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/RestoreVMCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ResetVMPasswordCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/address/ListPublicIpAddressesCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/ListVPCsCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/affinitygroup/UpdateVMAffinityGroupCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/account/ListAccountsCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ResizeVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ListVolumesCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/UpdateVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/CreateVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/AttachVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/MigrateVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/UploadVolumeCmdByAdmin.java
./api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DetachVolumeCmdByAdmin.java

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But these use the if (cmd instaceof <...>ByAdmin) {} pattern. Or we changing this? It is a good improvement in some ways but would justify its own PR.

pod = ((ListVMsCmdByAdmin) cmd).getPodId();
clusterId = ((ListVMsCmdByAdmin) cmd).getClusterId();
hostId = ((ListVMsCmdByAdmin) cmd).getHostId();
storageId = ((ListVMsCmdByAdmin) cmd).getStorageId();
}
pod = getObjectPossibleMethodValue(cmd, "getPodId");
clusterId = getObjectPossibleMethodValue(cmd, "getClusterId");
hostId = getObjectPossibleMethodValue(cmd, "getHostId");
storageId = getObjectPossibleMethodValue(cmd, "getStorageId");
}

sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
Expand Down