This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch 4.19
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.19 by this push:
     new 0d5047b8b73 Improve listing of HA and non-HA hosts when ha.tag setting 
is defined and hosts have multiple tags along with ha tag (#10240)
0d5047b8b73 is described below

commit 0d5047b8b730758bfabfe183c02d284e4db3260b
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Fri Jan 31 18:37:00 2025 +0530

    Improve listing of HA and non-HA hosts when ha.tag setting is defined and 
hosts have multiple tags along with ha tag (#10240)
---
 .../main/java/com/cloud/host/dao/HostDaoImpl.java  | 93 +++++++++++++---------
 .../com/cloud/server/ManagementServerImpl.java     |  4 +-
 .../java/com/cloud/vm/FirstFitPlannerTest.java     |  2 -
 3 files changed, 57 insertions(+), 42 deletions(-)

diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java 
b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
index da829a5fe24..4f0ae3cce9c 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
@@ -60,6 +60,7 @@ import com.cloud.org.Grouping;
 import com.cloud.org.Managed;
 import com.cloud.resource.ResourceState;
 import com.cloud.utils.DateUtil;
+import com.cloud.utils.StringUtils;
 import com.cloud.utils.db.Attribute;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.Filter;
@@ -83,13 +84,13 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
     private static final Logger status_logger = Logger.getLogger(Status.class);
     private static final Logger state_logger = 
Logger.getLogger(ResourceState.class);
 
-    private static final String LIST_HOST_IDS_BY_COMPUTETAGS = "SELECT 
filtered.host_id, COUNT(filtered.tag) AS tag_count "
-                                                             + "FROM (SELECT 
host_id, tag, is_tag_a_rule FROM host_tags GROUP BY host_id,tag) AS filtered "
-                                                             + "WHERE tag 
IN(%s) AND is_tag_a_rule = 0 "
+    private static final String LIST_HOST_IDS_BY_HOST_TAGS = "SELECT 
filtered.host_id, COUNT(filtered.tag) AS tag_count "
+                                                             + "FROM (SELECT 
host_id, tag, is_tag_a_rule FROM host_tags GROUP BY host_id,tag,is_tag_a_rule) 
AS filtered "
+                                                             + "WHERE tag IN 
(%s) AND (is_tag_a_rule = 0 OR is_tag_a_rule IS NULL) "
                                                              + "GROUP BY 
host_id "
                                                              + "HAVING 
tag_count = %s ";
     private static final String SEPARATOR = ",";
-    private static final String LIST_CLUSTERID_FOR_HOST_TAG = "select distinct 
cluster_id from host join ( %s ) AS selected_hosts ON host.id = 
selected_hosts.host_id";
+    private static final String LIST_CLUSTER_IDS_FOR_HOST_TAGS = "select 
distinct cluster_id from host join ( %s ) AS selected_hosts ON host.id = 
selected_hosts.host_id";
     private static final String GET_HOSTS_OF_ACTIVE_VMS = "select h.id " +
             "from vm_instance vm " +
             "join host h on (vm.host_id=h.id) " +
@@ -785,6 +786,15 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
 
     @Override
     public List<HostVO> listByHostTag(Host.Type type, Long clusterId, Long 
podId, long dcId, String hostTag) {
+        return listHostsWithOrWithoutHostTags(type, clusterId, podId, dcId, 
hostTag, true);
+    }
+
+    private List<HostVO> listHostsWithOrWithoutHostTags(Host.Type type, Long 
clusterId, Long podId, long dcId, String hostTags, boolean withHostTags) {
+        if (StringUtils.isEmpty(hostTags)) {
+            s_logger.debug("Host tags not specified, to list hosts");
+            return new ArrayList();
+        }
+
         SearchBuilder<HostVO> hostSearch = createSearchBuilder();
         HostVO entity = hostSearch.entity();
         hostSearch.and("type", entity.getType(), SearchCriteria.Op.EQ);
@@ -795,7 +805,9 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
         hostSearch.and("resourceState", entity.getResourceState(), 
SearchCriteria.Op.EQ);
 
         SearchCriteria<HostVO> sc = hostSearch.create();
-        sc.setParameters("type", type.toString());
+        if (type != null) {
+            sc.setParameters("type", type.toString());
+        }
         if (podId != null) {
             sc.setParameters("pod", podId);
         }
@@ -806,27 +818,38 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
         sc.setParameters("status", Status.Up.toString());
         sc.setParameters("resourceState", ResourceState.Enabled.toString());
 
-        List<HostVO> tmpHosts = listBy(sc);
-        List<HostVO> correctHostsByHostTags = new ArrayList();
-        List<Long> hostIdsByComputeOffTags = 
findHostByComputeOfferings(hostTag);
+        List<HostVO> upAndEnabledHosts = listBy(sc);
+        if (CollectionUtils.isEmpty(upAndEnabledHosts)) {
+            return new ArrayList();
+        }
 
-        tmpHosts.forEach((host) -> { 
if(hostIdsByComputeOffTags.contains(host.getId())) 
correctHostsByHostTags.add(host);});
+        List<Long> hostIdsByHostTags = findHostIdsByHostTags(hostTags);
+        if (CollectionUtils.isEmpty(hostIdsByHostTags)) {
+            return withHostTags ? new ArrayList() : upAndEnabledHosts;
+        }
 
-        return correctHostsByHostTags;
+        if (withHostTags) {
+            List<HostVO> upAndEnabledHostsWithHostTags = new ArrayList();
+            upAndEnabledHosts.forEach((host) -> { if 
(hostIdsByHostTags.contains(host.getId())) 
upAndEnabledHostsWithHostTags.add(host);});
+            return upAndEnabledHostsWithHostTags;
+        } else {
+            List<HostVO> upAndEnabledHostsWithoutHostTags = new ArrayList();
+            upAndEnabledHosts.forEach((host) -> { if 
(!hostIdsByHostTags.contains(host.getId())) 
upAndEnabledHostsWithoutHostTags.add(host);});
+            return upAndEnabledHostsWithoutHostTags;
+        }
     }
 
     @Override
     public List<HostVO> listAllUpAndEnabledNonHAHosts(Type type, Long 
clusterId, Long podId, long dcId, String haTag) {
+        if (StringUtils.isNotEmpty(haTag)) {
+            return listHostsWithOrWithoutHostTags(type, clusterId, podId, 
dcId, haTag, false);
+        }
+
         SearchBuilder<HostTagVO> hostTagSearch = 
_hostTagsDao.createSearchBuilder();
         hostTagSearch.and();
         hostTagSearch.op("isTagARule", hostTagSearch.entity().getIsTagARule(), 
Op.EQ);
         hostTagSearch.or("tagDoesNotExist", 
hostTagSearch.entity().getIsTagARule(), Op.NULL);
         hostTagSearch.cp();
-        if (haTag != null && !haTag.isEmpty()) {
-            hostTagSearch.and().op("tag", hostTagSearch.entity().getTag(), 
SearchCriteria.Op.NEQ);
-            hostTagSearch.or("tagNull", hostTagSearch.entity().getTag(), 
SearchCriteria.Op.NULL);
-            hostTagSearch.cp();
-        }
 
         SearchBuilder<HostVO> hostSearch = createSearchBuilder();
 
@@ -837,18 +860,12 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
         hostSearch.and("status", hostSearch.entity().getStatus(), 
SearchCriteria.Op.EQ);
         hostSearch.and("resourceState", 
hostSearch.entity().getResourceState(), SearchCriteria.Op.EQ);
 
-
         hostSearch.join("hostTagSearch", hostTagSearch, 
hostSearch.entity().getId(), hostTagSearch.entity().getHostId(), 
JoinBuilder.JoinType.LEFTOUTER);
 
-
         SearchCriteria<HostVO> sc = hostSearch.create();
 
         sc.setJoinParameters("hostTagSearch", "isTagARule", false);
 
-        if (haTag != null && !haTag.isEmpty()) {
-            sc.setJoinParameters("hostTagSearch", "tag", haTag);
-        }
-
         if (type != null) {
             sc.setParameters("type", type);
         }
@@ -1300,19 +1317,19 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
     }
 
     @Override
-    public List<Long> listClustersByHostTag(String computeOfferingTags) {
+    public List<Long> listClustersByHostTag(String hostTags) {
         TransactionLegacy txn = TransactionLegacy.currentTxn();
-        String sql = this.LIST_CLUSTERID_FOR_HOST_TAG;
+        String selectStmtToListClusterIdsByHostTags = 
this.LIST_CLUSTER_IDS_FOR_HOST_TAGS;
         PreparedStatement pstmt = null;
         List<Long> result = new ArrayList();
-        List<String> tags = 
Arrays.asList(computeOfferingTags.split(this.SEPARATOR));
-        String subselect = getHostIdsByComputeTags(tags);
-        sql = String.format(sql, subselect);
+        List<String> tags = Arrays.asList(hostTags.split(this.SEPARATOR));
+        String selectStmtToListHostIdsByHostTags = 
getSelectStmtToListHostIdsByHostTags(tags);
+        selectStmtToListClusterIdsByHostTags = 
String.format(selectStmtToListClusterIdsByHostTags, 
selectStmtToListHostIdsByHostTags);
 
         try {
-            pstmt = txn.prepareStatement(sql);
+            pstmt = txn.prepareStatement(selectStmtToListClusterIdsByHostTags);
 
-            for(int i = 0; i < tags.size(); i++){
+            for (int i = 0; i < tags.size(); i++){
                 pstmt.setString(i+1, tags.get(i));
             }
 
@@ -1323,20 +1340,20 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
             pstmt.close();
             return result;
         } catch (SQLException e) {
-            throw new CloudRuntimeException("DB Exception on: " + sql, e);
+            throw new CloudRuntimeException("DB Exception on: " + 
selectStmtToListClusterIdsByHostTags, e);
         }
     }
 
-    private List<Long> findHostByComputeOfferings(String computeOfferingTags){
+    private List<Long> findHostIdsByHostTags(String hostTags){
         TransactionLegacy txn = TransactionLegacy.currentTxn();
         PreparedStatement pstmt = null;
         List<Long> result = new ArrayList();
-        List<String> tags = 
Arrays.asList(computeOfferingTags.split(this.SEPARATOR));
-        String select = getHostIdsByComputeTags(tags);
+        List<String> tags = Arrays.asList(hostTags.split(this.SEPARATOR));
+        String selectStmtToListHostIdsByHostTags = 
getSelectStmtToListHostIdsByHostTags(tags);
         try {
-            pstmt = txn.prepareStatement(select);
+            pstmt = txn.prepareStatement(selectStmtToListHostIdsByHostTags);
 
-            for(int i = 0; i < tags.size(); i++){
+            for (int i = 0; i < tags.size(); i++){
                 pstmt.setString(i+1, tags.get(i));
             }
 
@@ -1347,7 +1364,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
             pstmt.close();
             return result;
         } catch (SQLException e) {
-            throw new CloudRuntimeException("DB Exception on: " + select, e);
+            throw new CloudRuntimeException("DB Exception on: " + 
selectStmtToListHostIdsByHostTags, e);
         }
     }
 
@@ -1372,10 +1389,10 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
         return new ArrayList<>(result);
     }
 
-    private String getHostIdsByComputeTags(List<String> offeringTags){
+    private String getSelectStmtToListHostIdsByHostTags(List<String> hostTags){
         List<String> questionMarks = new ArrayList();
-        offeringTags.forEach((tag) -> { questionMarks.add("?"); });
-        return String.format(this.LIST_HOST_IDS_BY_COMPUTETAGS, 
String.join(",", questionMarks),questionMarks.size());
+        hostTags.forEach((tag) -> { questionMarks.add("?"); });
+        return String.format(this.LIST_HOST_IDS_BY_HOST_TAGS, String.join(",", 
questionMarks), questionMarks.size());
     }
 
     @Override
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java 
b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index c032019510f..7ccd6b5e289 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -1919,7 +1919,7 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
 
         final String haTag = _haMgr.getHaTag();
         SearchBuilder<HostTagVO> hostTagSearch = null;
-        if (haHosts != null && haTag != null && !haTag.isEmpty()) {
+        if (haHosts != null && StringUtils.isNotEmpty(haTag)) {
             hostTagSearch = _hostTagsDao.createSearchBuilder();
             if ((Boolean)haHosts) {
                 hostTagSearch.and().op("tag", hostTagSearch.entity().getTag(), 
SearchCriteria.Op.EQ);
@@ -1980,7 +1980,7 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
             sc.setParameters("resourceState", resourceState);
         }
 
-        if (haHosts != null && haTag != null && !haTag.isEmpty()) {
+        if (haHosts != null && StringUtils.isNotEmpty(haTag)) {
             sc.setJoinParameters("hostTagSearch", "tag", haTag);
         }
 
diff --git a/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java 
b/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java
index eecd7cc2d35..5b795ac6a34 100644
--- a/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java
+++ b/server/src/test/java/com/cloud/vm/FirstFitPlannerTest.java
@@ -217,8 +217,6 @@ public class FirstFitPlannerTest {
     }
 
     private List<Long> initializeForClusterListBasedOnHostTag(ServiceOffering 
offering) {
-
-
         when(offering.getHostTag()).thenReturn("hosttag1");
         initializeForClusterThresholdDisabled();
         List<Long> matchingClusters = new ArrayList<>();

Reply via email to