diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 28e4ba3bb30..b060b5a2176 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -711,6 +711,7 @@ public class ApiConstants { public static final String UCS_BLADE_DN = "bladedn"; public static final String UCS_BLADE_ID = "bladeid"; public static final String VM_GUEST_IP = "vmguestip"; + public static final String HEALTHCHECK_FAILED = "healthchecksfailed"; public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout"; public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime"; public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java index 4fabcf5df76..3c9b684c0c8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java @@ -81,6 +81,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { @Parameter(name = ApiConstants.VERSION, type = CommandType.STRING, description = "list virtual router elements by version") private String version; + @Parameter(name = ApiConstants.HEALTHCHECK_FAILED, type = CommandType.BOOLEAN, since = "4.16", + description = "if this parameter is passed, list only routers by health check results") + private Boolean healthCheckFailed; + @Parameter(name = ApiConstants.FETCH_ROUTER_HEALTH_CHECK_RESULTS, type = CommandType.BOOLEAN, since = "4.14", description = "if true is passed for this parameter, also fetch last executed health check results for the router. Default is false") private Boolean fetchHealthCheckResults; @@ -137,6 +141,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { return Role.VIRTUAL_ROUTER.toString(); } + public Boolean isHealthCheckFailed() { + return healthCheckFailed; + } + public boolean shouldFetchHealthCheckResults() { return BooleanUtils.isTrue(fetchHealthCheckResults); } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java index 0a4a456aed2..563d6a9f961 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java @@ -225,7 +225,7 @@ public class DomainRouterResponse extends BaseResponse implements ControlledView @Param(description = "true if the router template requires upgrader") private boolean requiresUpgrade; - @SerializedName("healthchecksfailed") + @SerializedName(ApiConstants.HEALTHCHECK_FAILED) @Param(description = "true if any health checks had failed") private boolean healthChecksFailed; 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 e388a7539ec..0c8a7f79435 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -187,6 +187,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.RouterHealthCheckResult; import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.dao.RouterHealthCheckResultDao; +import com.cloud.network.dao.RouterHealthCheckResultVO; import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.network.security.SecurityGroupVMMapVO; import com.cloud.network.security.dao.SecurityGroupVMMapDao; @@ -232,6 +233,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; import com.cloud.utils.Ternary; import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -1262,7 +1264,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Override public ListResponse searchForRouters(ListRoutersCmd cmd) { Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), cmd.getClusterId(), - cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), cmd.getVersion()); + cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), cmd.getVersion(), cmd.isHealthCheckFailed()); ListResponse response = new ListResponse(); List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { @@ -1282,7 +1284,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Override public ListResponse searchForInternalLbVms(ListInternalLBVMsCmd cmd) { Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, cmd.getHostId(), - cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), null); + cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), null, null); ListResponse response = new ListResponse(); List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { @@ -1301,7 +1303,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } private Pair, Integer> searchForRoutersInternal(BaseListProjectAndAccountResourcesCmd cmd, Long id, String name, String state, Long zoneId, Long podId, Long clusterId, - Long hostId, String keyword, Long networkId, Long vpcId, Boolean forVpc, String role, String version) { + Long hostId, String keyword, Long networkId, Long vpcId, Boolean forVpc, String role, String version, Boolean isHealthCheckFailed) { Account caller = CallContext.current().getCallingAccount(); List permittedAccounts = new ArrayList(); @@ -1345,6 +1347,27 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q sb.and("networkId", sb.entity().getNetworkId(), SearchCriteria.Op.EQ); } + List routersWithFailures = null; + if (isHealthCheckFailed != null) { + GenericSearchBuilder routerHealthCheckResultSearch = routerHealthCheckResultDao.createSearchBuilder(Long.class); + routerHealthCheckResultSearch.and("checkResult", routerHealthCheckResultSearch.entity().getCheckResult(), SearchCriteria.Op.EQ); + routerHealthCheckResultSearch.selectFields(routerHealthCheckResultSearch.entity().getRouterId()); + routerHealthCheckResultSearch.done(); + SearchCriteria ssc = routerHealthCheckResultSearch.create(); + ssc.setParameters("checkResult", false); + routersWithFailures = routerHealthCheckResultDao.customSearch(ssc, null); + + if (routersWithFailures != null && ! routersWithFailures.isEmpty()) { + if (isHealthCheckFailed) { + sb.and("routerId", sb.entity().getId(), SearchCriteria.Op.IN); + } else { + sb.and("routerId", sb.entity().getId(), SearchCriteria.Op.NIN); + } + } else if (isHealthCheckFailed) { + return new Pair, Integer>(Collections.emptyList(), 0); + } + } + SearchCriteria sc = sb.create(); _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); @@ -1403,6 +1426,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q sc.setParameters("version", "Cloudstack Release " + version + "%"); } + if (routersWithFailures != null && ! routersWithFailures.isEmpty()) { + sc.setParameters("routerId", routersWithFailures.toArray(new Object[routersWithFailures.size()])); + } + // search VR details by ids Pair, Integer> uniqueVrPair = _routerJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueVrPair.second();