From 4de66f98555c16741a9b580512b1c66c8788fa5f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 12 Dec 2022 11:22:07 +0530 Subject: [PATCH] server: fix listing vm metrics for infra resources (#6851) Fixes #6786 listVirtualMachinesMetrics does not support some of the params that are supported by admin API call for listVirtualMachines. These parameters are used in UI. Signed-off-by: Abhishek Kumar Signed-off-by: Abhishek Kumar Co-authored-by: Rohit Yadav Co-authored-by: Daan Hoogland --- .../cloudstack/api/ListVMsMetricsCmd.java | 13 ++-- .../api/ListVMsMetricsCmdByAdmin.java | 73 +++++++++++++++++++ .../metrics/MetricsServiceImpl.java | 34 +++++---- .../com/cloud/api/query/QueryManagerImpl.java | 26 +++++-- 4 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmdByAdmin.java diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java index 89d596e1f05..38001cedb09 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java @@ -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.
* The reasons for this are:
@@ -42,9 +44,8 @@ import java.util.List; */ @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 diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmdByAdmin.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmdByAdmin.java new file mode 100644 index 00000000000..80c69126bbd --- /dev/null +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmdByAdmin.java @@ -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; + } +} diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index 3d24990050b..3c1700965d4 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -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; @@ -28,14 +30,6 @@ import java.util.Properties; 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; @@ -45,6 +39,7 @@ import org.apache.cloudstack.api.ListMgmtsMetricsCmd; 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; @@ -52,8 +47,8 @@ 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; @@ -76,6 +71,10 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; 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; @@ -103,13 +102,21 @@ import com.cloud.network.router.VirtualRouter; 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; @@ -119,12 +126,6 @@ import com.cloud.vm.dao.UserVmDao; 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); @@ -878,6 +879,9 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements cmdList.add(ListVolumesMetricsCmd.class); cmdList.add(ListZonesMetricsCmd.class); cmdList.add(ListVMsUsageHistoryCmd.class); + + // separate Admin commands + cmdList.add(ListVMsMetricsCmdByAdmin.class); return cmdList; } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 57c9aa82ca5..d5ce58b6c88 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -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; @@ -65,7 +67,6 @@ import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; 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; @@ -971,6 +972,17 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q return response; } + private Object getObjectPossibleMethodValue(Object obj, String methodName) { + Object result = null; + + try { + Method m = obj.getClass().getMethod(methodName); + result = m.invoke(obj); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) {} + + return result; + } + private Pair, Integer> searchForUserVMsInternal(ListVMsCmd cmd) { Account caller = CallContext.current().getCallingAccount(); List permittedAccounts = new ArrayList(); @@ -1035,16 +1047,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q 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())) { - if (cmd instanceof ListVMsCmdByAdmin) { - 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);