Xiaolei Shi has uploaded a new change for review.

Change subject: Numa engine/vdsm integration patch
......................................................................

Numa engine/vdsm integration patch

Change-Id: I050bc9d80a90ac73b5642ccd7630dd352eba236e
Signed-off-by: Bruce Shi <xiao-lei....@hp.com>
---
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAO.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAODbFacadeImpl.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsBrokerObjectsBuilder.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilderBase.java
7 files changed, 426 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/83/27083/1

diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAO.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAO.java
index 8503e89..3603f1a 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAO.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAO.java
@@ -57,4 +57,13 @@
      */
     void removeAllVdsNumaNodeByVdsId(Guid vdsId);
 
+    /**
+     * Remove vds numa nodes using a more efficient method to remove all of 
them at once,
+     * rather than each at a time.
+     *
+     * @param vdsNumaNodeIds
+     *            the vds numa node ids to be removed
+     */
+    void massRemoveVdsNumaNodeByVdsNumaNodeId(List<Guid> vdsNumaNodeIds);
+
 }
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAODbFacadeImpl.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAODbFacadeImpl.java
index 17609f9..6109984 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAODbFacadeImpl.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VdsNumaNodeDAODbFacadeImpl.java
@@ -206,4 +206,13 @@
                 }
             };
 
+    @Override
+    public void massRemoveVdsNumaNodeByVdsNumaNodeId(List<Guid> 
vdsNumaNodeIds) {
+        List<MapSqlParameterSource> executions = new 
ArrayList<>(vdsNumaNodeIds.size());
+        for (Guid id : vdsNumaNodeIds) {
+            
executions.add(getCustomMapSqlParameterSource().addValue("numa_node_id", id));
+        }
+        getCallsHandler().executeStoredProcAsBatch("DeleteNumaNode", 
executions);
+    }
+
 }
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
index cda207b..0b46bb2 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsManager.java
@@ -4,6 +4,7 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
@@ -19,6 +20,7 @@
 import org.ovirt.engine.core.common.businessentities.VDSDomainsData;
 import org.ovirt.engine.core.common.businessentities.VDSStatus;
 import org.ovirt.engine.core.common.businessentities.VdsDynamic;
+import org.ovirt.engine.core.common.businessentities.VdsNumaNode;
 import org.ovirt.engine.core.common.businessentities.VdsSpmStatus;
 import org.ovirt.engine.core.common.businessentities.VdsStatistics;
 import org.ovirt.engine.core.common.businessentities.VmDynamic;
@@ -31,6 +33,7 @@
 import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
 import 
org.ovirt.engine.core.common.vdscommands.VdsIdAndVdsVDSCommandParametersBase;
 import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.compat.TransactionScopeOption;
 import org.ovirt.engine.core.compat.Version;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
 import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
@@ -43,6 +46,8 @@
 import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation;
 import org.ovirt.engine.core.utils.timer.SchedulerUtil;
 import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl;
+import org.ovirt.engine.core.utils.transaction.TransactionMethod;
+import org.ovirt.engine.core.utils.transaction.TransactionSupport;
 import org.ovirt.engine.core.vdsbroker.irsbroker.IRSErrorException;
 import org.ovirt.engine.core.vdsbroker.irsbroker.IrsBrokerCommand;
 import 
org.ovirt.engine.core.vdsbroker.vdsbroker.CollectVdsNetworkDataVDSCommand;
@@ -78,6 +83,10 @@
     private boolean isSetNonOperationalExecuted;
     private MonitoringStrategy monitoringStrategy;
     private EngineLock monitoringLock;
+
+    private final List<VdsNumaNode> saveNodeList = new ArrayList<>();
+    private final List<VdsNumaNode> updateNodeList = new ArrayList<>();
+    private final List<Guid> removeNodeList = new ArrayList<>();
     public Object getLockObj() {
         return _lockObj;
     }
@@ -377,6 +386,59 @@
         DbFacade.getInstance().getVdsStatisticsDao().update(statisticsData);
     }
 
+    /**
+     * Save or update numa data to DB
+     *
+     * @param vds
+     */
+    public void updateNumaData(VDS vds) {
+        List<VdsNumaNode> vdsNumaNodes = vds.getNumaNodeList();
+        List<VdsNumaNode> dbVdsNumaNodes = DbFacade.getInstance()
+                .getVdsNumaNodeDAO().getAllVdsNumaNodeByVdsId(vds.getId());
+        for (VdsNumaNode node : vdsNumaNodes) {
+            VdsNumaNode searchNode = getVdsNumaNodeByIndex(dbVdsNumaNodes, 
node.getIndex());
+            if (searchNode != null) {
+                node.setId(searchNode.getId());
+                updateNodeList.add(node);
+                dbVdsNumaNodes.remove(searchNode);
+            }
+            else {
+                node.setId(Guid.newGuid());
+                saveNodeList.add(node);
+            }
+        }
+        for (VdsNumaNode node : dbVdsNumaNodes) {
+            removeNodeList.add(node.getId());
+        }
+        //The database operation should be in one transaction
+        TransactionSupport.executeInScope(TransactionScopeOption.Required,
+                new TransactionMethod<Void>() {
+                    @Override
+                    public Void runInTransaction() {
+                        if (!removeNodeList.isEmpty()){
+                            
DbFacade.getInstance().getVdsNumaNodeDAO().massRemoveVdsNumaNodeByVdsNumaNodeId(removeNodeList);
+                        }
+                        if (!updateNodeList.isEmpty()){
+                            
DbFacade.getInstance().getVdsNumaNodeDAO().massUpdateVdsNumaNode(updateNodeList);
+                        }
+                        if (!saveNodeList.isEmpty()){
+                            
DbFacade.getInstance().getVdsNumaNodeDAO().massSaveVdsNumaNode(saveNodeList, 
_vds.getId());
+                        }
+                        return null;
+                    }
+                });
+
+    }
+
+    private static VdsNumaNode getVdsNumaNodeByIndex(List<VdsNumaNode> 
numaNodes, int index) {
+        for (VdsNumaNode numaNode : numaNodes) {
+            if (index == numaNode.getIndex()) {
+                return numaNode;
+            }
+        }
+        return null;
+    }
+
     public VDS activate() {
         VDS vds = null;
         try {
@@ -405,6 +467,7 @@
         } finally {
             if (vds != null) {
                 updateDynamicData(vds.getDynamicData());
+                updateNumaData(vds);
 
                 // Update VDS after testing special hardware capabilities
                 monitoringStrategy.processHardwareCapabilities(vds);
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
index 1760fc1..d0c138a 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfo.java
@@ -18,6 +18,7 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.exception.ExceptionUtils;
 import org.ovirt.engine.core.common.AuditLogType;
+import org.ovirt.engine.core.common.businessentities.CpuStatistics;
 import org.ovirt.engine.core.common.businessentities.Disk;
 import org.ovirt.engine.core.common.businessentities.Disk.DiskStorageType;
 import org.ovirt.engine.core.common.businessentities.DiskImage;
@@ -36,6 +37,7 @@
 import org.ovirt.engine.core.common.businessentities.VM;
 import org.ovirt.engine.core.common.businessentities.VMStatus;
 import org.ovirt.engine.core.common.businessentities.VdsDynamic;
+import org.ovirt.engine.core.common.businessentities.VdsNumaNode;
 import org.ovirt.engine.core.common.businessentities.VdsStatistics;
 import org.ovirt.engine.core.common.businessentities.VmBalloonInfo;
 import org.ovirt.engine.core.common.businessentities.VmDevice;
@@ -108,6 +110,8 @@
     private final List<Guid> _vmsMovedToDown = new ArrayList<>();
     private final List<Guid> _vmsToRemoveFromAsync = new ArrayList<>();
     private final List<Guid> _succededToRunVms = new ArrayList<>();
+    private final List<CpuStatistics> cpuStatisticsToSave = new ArrayList<>();
+    private final List<VdsNumaNode> vdsNumaNodesToSave = new ArrayList<>();
     private static final Map<Guid, Integer> vmsWithBalloonDriverProblem = new 
HashMap<>();
     private static final Map<Guid, Integer> vmsWithUncontrolledBalloon = new 
HashMap<>();
     private final List<VmStatic> _externalVmsToAdd = new ArrayList<>();
@@ -188,6 +192,8 @@
         saveVmDevicesToDb();
         saveVmGuestAgentNetworkDevices();
         getVdsEventListener().addExternallyManagedVms(_externalVmsToAdd);
+        saveCpuStatisticsDataToDb();
+        saveNumaStatisticsDataToDb();
     }
 
     private void saveVmGuestAgentNetworkDevices() {
@@ -240,6 +246,94 @@
         }
     }
 
+    private void saveCpuStatisticsDataToDb() {
+        
cpuStatisticsToSave.addAll(_vds.getStatisticsData().getCpuCoreStatistics());
+        if (!cpuStatisticsToSave.isEmpty()) {
+            List<CpuStatistics> dbCpuStats = 
getDbFacade().getVdsCpuStatisticsDAO()
+                    .getAllCpuStatisticsByVdsId(_vds.getId());
+            if (dbCpuStats.isEmpty()) {
+                
TransactionSupport.executeInScope(TransactionScopeOption.Required,
+                        new TransactionMethod<Void>() {
+                            @Override
+                            public Void runInTransaction() {
+                                
getDbFacade().getVdsCpuStatisticsDAO().massSaveCpuStatistics(
+                                        cpuStatisticsToSave, _vds.getId());
+                                return null;
+                            }
+                        });
+            }
+            else {
+                boolean needRemoveAndSave = false;
+                if (dbCpuStats.size() != cpuStatisticsToSave.size()) {
+                    needRemoveAndSave = true;
+                }
+                else {
+                    Map<Integer, CpuStatistics> cpuStatsMap = new HashMap<>();
+                    for (CpuStatistics cpuStat : dbCpuStats) {
+                        cpuStatsMap.put(cpuStat.getCpuId(), cpuStat);
+                    }
+                    for (CpuStatistics cpuStat : cpuStatisticsToSave) {
+                        if (!cpuStatsMap.containsKey(cpuStat.getCpuId())) {
+                            needRemoveAndSave = true;
+                            break;
+                        }
+                    }
+                }
+                if (needRemoveAndSave) {
+                    
TransactionSupport.executeInScope(TransactionScopeOption.Required,
+                            new TransactionMethod<Void>() {
+                                @Override
+                                public Void runInTransaction() {
+                                    
getDbFacade().getVdsCpuStatisticsDAO().removeAllCpuStatisticsByVdsId(_vds.getId());
+                                    
getDbFacade().getVdsCpuStatisticsDAO().massSaveCpuStatistics(
+                                            cpuStatisticsToSave, _vds.getId());
+                                    return null;
+                                }
+                            });
+                }
+                else {
+                    
TransactionSupport.executeInScope(TransactionScopeOption.Required,
+                            new TransactionMethod<Void>() {
+                                @Override
+                                public Void runInTransaction() {
+                                    
getDbFacade().getVdsCpuStatisticsDAO().massUpdateVdsNumaNodeStatistics(
+                                            cpuStatisticsToSave, _vds.getId());
+                                    return null;
+                                }
+                            });
+                }
+            }
+        }
+    }
+
+    private void saveNumaStatisticsDataToDb() {
+        List<VdsNumaNode> updateNumaNodes = _vds.getNumaNodeList();
+        if (!updateNumaNodes.isEmpty()) {
+            List<VdsNumaNode> dbVdsNumaNodes = 
getDbFacade().getVdsNumaNodeDAO()
+                    .getAllVdsNumaNodeByVdsId(_vds.getId());
+            Map<Integer, VdsNumaNode> nodesMap = new HashMap<>();
+            for (VdsNumaNode node : dbVdsNumaNodes) {
+                nodesMap.put(node.getIndex(), node);
+            }
+            for (VdsNumaNode node : updateNumaNodes) {
+                if (nodesMap.containsKey(node.getIndex())) {
+                    node.setId(nodesMap.get(node.getIndex()).getId());
+                    vdsNumaNodesToSave.add(node);
+                }
+            }
+        }
+        if (!vdsNumaNodesToSave.isEmpty()) {
+            TransactionSupport.executeInScope(TransactionScopeOption.Required,
+                    new TransactionMethod<Void>() {
+                        @Override
+                        public Void runInTransaction() {
+                            
getDbFacade().getVdsNumaNodeDAO().massUpdateVdsNumaNodeStatistics(vdsNumaNodesToSave);
+                            return null;
+                        }
+                    });
+        }
+    }
+
     /**
      * check if value is less than configurable threshold , if yes , generated 
event log message
      *
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsBrokerObjectsBuilder.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsBrokerObjectsBuilder.java
index 5dcc0a8..e6e5208 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsBrokerObjectsBuilder.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsBrokerObjectsBuilder.java
@@ -2,6 +2,7 @@
 
 import java.nio.file.Paths;
 import java.text.DateFormat;
+import java.text.DecimalFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -18,17 +19,21 @@
 import org.apache.commons.lang.StringUtils;
 import org.ovirt.engine.core.common.AuditLogType;
 import org.ovirt.engine.core.common.FeatureSupported;
+import org.ovirt.engine.core.common.businessentities.AutoNumaBalanceStatus;
+import org.ovirt.engine.core.common.businessentities.CpuStatistics;
 import org.ovirt.engine.core.common.businessentities.DiskImageDynamic;
 import org.ovirt.engine.core.common.businessentities.DisplayType;
 import org.ovirt.engine.core.common.businessentities.Entities;
 import org.ovirt.engine.core.common.businessentities.KdumpStatus;
 import org.ovirt.engine.core.common.businessentities.LUNs;
+import org.ovirt.engine.core.common.businessentities.NumaNodeStatistics;
 import org.ovirt.engine.core.common.businessentities.SessionState;
 import org.ovirt.engine.core.common.businessentities.StoragePool;
 import org.ovirt.engine.core.common.businessentities.StorageType;
 import org.ovirt.engine.core.common.businessentities.VDS;
 import org.ovirt.engine.core.common.businessentities.VDSDomainsData;
 import org.ovirt.engine.core.common.businessentities.VMStatus;
+import org.ovirt.engine.core.common.businessentities.VdsNumaNode;
 import 
org.ovirt.engine.core.common.businessentities.VdsTransparentHugePagesState;
 import org.ovirt.engine.core.common.businessentities.VmBalloonInfo;
 import org.ovirt.engine.core.common.businessentities.VmDynamic;
@@ -371,6 +376,7 @@
         vds.setSupportedClusterLevels(AssignStringValueFromArray(xmlRpcStruct, 
VdsProperties.supported_cluster_levels));
 
         updateNetworkData(vds, xmlRpcStruct);
+        updateNumaNodesData(vds, xmlRpcStruct);
 
         vds.setCpuThreads(AssignIntValue(xmlRpcStruct, 
VdsProperties.cpuThreads));
         vds.setCpuCores(AssignIntValue(xmlRpcStruct, VdsProperties.cpu_cores));
@@ -703,6 +709,69 @@
 
         vds.setBootTime(AssignLongValue(xmlRpcStruct, VdsProperties.bootTime));
 
+        updateNumaStatisticsData(vds, xmlRpcStruct);
+
+    }
+
+    public static void updateNumaStatisticsData(VDS vds, Map<String, Object> 
xmlRpcStruct) {
+        List<VdsNumaNode> vdsNumaNodes = new ArrayList<>();
+        List<CpuStatistics> cpuStatsData = new ArrayList<>();
+        if (xmlRpcStruct.containsKey(VdsProperties.CPU_STATS)) {
+            Map<String, Map<String, Object>> cpuStats = (Map<String, 
Map<String, Object>>)
+                    xmlRpcStruct.get(VdsProperties.CPU_STATS);
+            Map<Integer, List<CpuStatistics>> numaNodeCpuStats = new 
HashMap<>();
+            for (Map.Entry<String, Map<String, Object>> item : 
cpuStats.entrySet()) {
+                CpuStatistics data = new CpuStatistics();
+                data.setCpuId(Integer.valueOf(item.getKey()));
+                data.setCpuUser(AssignDoubleValue(item.getValue(), 
VdsProperties.NUMA_CPU_USER));
+                data.setCpuSys(AssignDoubleValue(item.getValue(), 
VdsProperties.NUMA_CPU_SYS));
+                data.setCpuIdle(AssignDoubleValue(item.getValue(), 
VdsProperties.NUMA_CPU_IDLE));
+                data.setCpuUsagePercent((int) (data.getCpuSys() + 
data.getCpuUser()));
+                cpuStatsData.add(data);
+                int numaNodeIndex = AssignIntValue(item.getValue(), 
VdsProperties.NUMA_NODE_INDEX);
+                if (!numaNodeCpuStats.containsKey(numaNodeIndex)) {
+                    numaNodeCpuStats.put(numaNodeIndex, new 
ArrayList<CpuStatistics>());
+                }
+                numaNodeCpuStats.get(numaNodeIndex).add(data);
+            }
+            DecimalFormat percentageFormatter = new DecimalFormat("#.##");
+            for (Map.Entry<Integer, List<CpuStatistics>> item : 
numaNodeCpuStats.entrySet()) {
+                VdsNumaNode node = new VdsNumaNode();
+                NumaNodeStatistics nodeStat = new NumaNodeStatistics();
+                double nodeCpuUser = 0.0;
+                double nodeCpuSys = 0.0;
+                double nodeCpuIdle = 0.0;
+                for (CpuStatistics cpuStat : item.getValue()) {
+                    nodeCpuUser += cpuStat.getCpuUser();
+                    nodeCpuSys += cpuStat.getCpuSys();
+                    nodeCpuIdle += cpuStat.getCpuIdle();
+                }
+                
nodeStat.setCpuUser(Double.valueOf(percentageFormatter.format(nodeCpuUser / 
item.getValue().size())));
+                
nodeStat.setCpuSys(Double.valueOf(percentageFormatter.format(nodeCpuSys / 
item.getValue().size())));
+                
nodeStat.setCpuIdle(Double.valueOf(percentageFormatter.format(nodeCpuIdle / 
item.getValue().size())));
+                nodeStat.setCpuUsagePercent((int) (nodeStat.getCpuSys() + 
nodeStat.getCpuUser()));
+                node.setIndex(item.getKey());
+                node.setNumaNodeStatistics(nodeStat);
+                vdsNumaNodes.add(node);
+            }
+        }
+        if (xmlRpcStruct.containsKey(VdsProperties.NUMA_NODE_FREE_MEM_STAT)) {
+            Map<String, Map<String, Object>> memStats = (Map<String, 
Map<String, Object>>)
+                    xmlRpcStruct.get(VdsProperties.NUMA_NODE_FREE_MEM_STAT);
+            for (Map.Entry<String, Map<String, Object>> item : 
memStats.entrySet()) {
+                VdsNumaNode node = getVdsNumaNodeByIndex(vdsNumaNodes, 
Integer.valueOf(item.getKey()));
+                if (node != null) {
+                    
node.getNumaNodeStatistics().setMemFree(AssignLongValue(item.getValue(),
+                            VdsProperties.NUMA_NODE_FREE_MEM));
+                    
node.getNumaNodeStatistics().setMemUsagePercent(AssignIntValue(item.getValue(),
+                            VdsProperties.NUMA_NODE_MEM_PERCENT));
+                }
+            }
+        }
+        vds.getNumaNodeList().clear();
+        vds.getNumaNodeList().addAll(vdsNumaNodes);
+        vds.getStatisticsData().getCpuCoreStatistics().clear();
+        vds.getStatisticsData().getCpuCoreStatistics().addAll(cpuStatsData);
     }
 
     /**
@@ -1469,6 +1538,62 @@
         return macAddress != null ? macAddress.replace('-', ':') : null;
     }
 
+    /**
+     * Build through the received NUMA nodes information
+     * @param vds
+     * @param xmlRpcStruct
+     */
+    private static void updateNumaNodesData(VDS vds, Map<String, Object> 
xmlRpcStruct) {
+        
vds.getDynamicData().setAutoNumaBalancing(AutoNumaBalanceStatus.forValue(
+                AssignIntValue(xmlRpcStruct, VdsProperties.AUTO_NUMA)));
+
+        if (xmlRpcStruct.containsKey(VdsProperties.NUMA_NODES)){
+            Map<String, Map<String, Object>> numaNodeMap =
+                    (Map<String, Map<String, Object>>) 
xmlRpcStruct.get(VdsProperties.NUMA_NODES);
+            Map<String, Object> numaNodeDistanceMap =
+                    (Map<String, Object>) 
xmlRpcStruct.get(VdsProperties.NUMA_NODE_DISTANCE);
+
+            List<VdsNumaNode> newNumaNodeList = new 
ArrayList<>(numaNodeMap.size());
+
+            for (Map.Entry<String, Map<String, Object>> item : 
numaNodeMap.entrySet()) {
+                int index = Integer.valueOf(item.getKey());
+                Map<String, Object> itemMap = item.getValue();
+                List<Integer> cpuIds = (List<Integer>) 
itemMap.get(VdsProperties.NUMA_NODE_CPU_LIST);
+                long memTotal = (long) 
itemMap.get(VdsProperties.NUMA_NODE_TOTAL_MEM);
+                VdsNumaNode numaNode = new VdsNumaNode();
+                numaNode.setIndex(index);
+                numaNode.setCpuIds(cpuIds);
+                numaNode.setMemTotal(memTotal);
+                newNumaNodeList.add(numaNode);
+            }
+
+            for (Map.Entry<String, Object> item : 
numaNodeDistanceMap.entrySet()) {
+                int index = Integer.valueOf(item.getKey());
+                List<Integer> distances = (List<Integer>) item.getValue();
+                Map<Integer, Integer> distanceMap = new 
HashMap<>(distances.size());
+                for (int i = 0; i < distances.size(); i++) {
+                    distanceMap.put(i, distances.get(i));
+                }
+                VdsNumaNode newNumaNode = 
getVdsNumaNodeByIndex(newNumaNodeList, index);
+                if (newNumaNode != null) {
+                    newNumaNode.setNumaNodeDistances(distanceMap);
+                }
+            }
+
+            vds.getDynamicData().setNumaNodeList(newNumaNodeList);
+        }
+
+    }
+
+    private static VdsNumaNode getVdsNumaNodeByIndex(List<VdsNumaNode> 
numaNodes, int index) {
+        for (VdsNumaNode numaNode : numaNodes) {
+            if (index == numaNode.getIndex()) {
+                return numaNode;
+            }
+        }
+        return null;
+    }
+
     private static List<String> extracStringtList(Map<String, Object> 
xmlRpcStruct, String propertyName) {
         if (!xmlRpcStruct.containsKey(propertyName)){
             return null;
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java
index c1f9fa2..a73e520 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java
@@ -80,6 +80,26 @@
 
     public static final String INTERFACE = "iface";
 
+    // NUMA related properties
+    public static final String NUMA_NODES = "numaNodes";
+    public static final String NUMA_NODE_DISTANCE = "numaDistances";
+    public static final String AUTO_NUMA = "autoNumaBalancing";
+    public static final String NUMA_NODE_CPU_LIST = "cpus";
+    public static final String NUMA_NODE_TOTAL_MEM = "totalMemory";
+    public static final String NUMA_NODE_FREE_MEM_STAT = "numaNodeMemFree";
+    public static final String CPU_STATS = "cpuStatistics";
+    public static final String NUMA_NODE_FREE_MEM = "memFree";
+    public static final String NUMA_NODE_MEM_PERCENT = "memPercent";
+    public static final String NUMA_NODE_INDEX = "nodeNodeIndex";
+    public static final String NUMA_CPU_SYS = "cpuSys";
+    public static final String NUMA_CPU_USER = "cpuUser";
+    public static final String NUMA_CPU_IDLE = "cpuIdle";
+    public static final String NUMA_TUNE_MODE = "mode";
+    public static final String NUMA_TUNE_NODESET = "nodeset";
+    public static final String VM_NUMA_NODE_MEM = "memory";
+    public static final String NUMA_TUNE = "numaTune";
+    public static final String VM_NUMA_NODES = "guestNumaNodes";
+
     // Network related properties
     public static final String NETWORK = "network";
     public static final String LINK_ACTIVE = "linkActive";
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilderBase.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilderBase.java
index 2183d42..b5af225 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilderBase.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilderBase.java
@@ -2,12 +2,15 @@
 
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 
 import org.apache.commons.lang.StringUtils;
@@ -15,10 +18,13 @@
 import org.ovirt.engine.core.common.FeatureSupported;
 import org.ovirt.engine.core.common.businessentities.Disk;
 import org.ovirt.engine.core.common.businessentities.DisplayType;
+import org.ovirt.engine.core.common.businessentities.NumaTuneMode;
 import org.ovirt.engine.core.common.businessentities.VDSGroup;
 import org.ovirt.engine.core.common.businessentities.VM;
+import org.ovirt.engine.core.common.businessentities.VdsNumaNode;
 import org.ovirt.engine.core.common.businessentities.VmDevice;
 import org.ovirt.engine.core.common.businessentities.VmDeviceId;
+import org.ovirt.engine.core.common.businessentities.VmNumaNode;
 import 
org.ovirt.engine.core.common.businessentities.comparators.DiskImageByDiskAliasComparator;
 import org.ovirt.engine.core.common.businessentities.network.Network;
 import org.ovirt.engine.core.common.businessentities.network.NetworkCluster;
@@ -140,6 +146,7 @@
         }
         createInfo.put(VdsProperties.transparent_huge_pages,
                 vm.isTransparentHugePages() ? "true" : "false");
+        addNumaSetting(compatibilityVersion);
     }
 
     private void addCpuPinning(final String compatibilityVersion) {
@@ -156,6 +163,105 @@
         }
     }
 
+    /**
+     * Numa will use the same compatibilityVersion as cpu pinning since
+     * numa may also add cpu pinning configuration and the two features
+     * have almost the same libvirt version support
+     *
+     * @param compatibilityVersion
+     */
+    private void addNumaSetting(final String compatibilityVersion) {
+        if (Boolean.TRUE.equals(Config.<Boolean> 
getValue(ConfigValues.CpuPinningEnabled,
+                        compatibilityVersion))) {
+            NumaTuneMode numaTune = vm.getNumaTuneMode();
+            List<VmNumaNode> vmNumaNodes = 
DbFacade.getInstance().getVmNumaNodeDAO().getAllVmNumaNodeByVmId(vm.getId());
+            List<VdsNumaNode> totalVdsNumaNodes = 
DbFacade.getInstance().getVdsNumaNodeDAO()
+                    .getAllVdsNumaNodeByVdsId(vm.getRunOnVds());
+            List<Integer> totalVdsNumaNodesIndexes = 
getNodeIndexList(totalVdsNumaNodes);
+            Map<String, Object> createNumaTune = new HashMap<>(2);
+            createNumaTune.put(VdsProperties.NUMA_TUNE_MODE, 
numaTune.getValue());
+            boolean useAllVdsNodesMem = false;
+            Set<Integer> vmNumaNodePinInfo = new HashSet<>();
+            if (!vmNumaNodes.isEmpty()) {
+                List<Map<String, Object>> createVmNumaNodes = new 
ArrayList<>();
+                for (VmNumaNode node : vmNumaNodes) {
+                    Map<String, Object> createVmNumaNode = new HashMap<>();
+                    createVmNumaNode.put(VdsProperties.NUMA_NODE_CPU_LIST, 
buildStringFromListForNuma(node.getCpuIds()));
+                    createVmNumaNode.put(VdsProperties.VM_NUMA_NODE_MEM, 
String.valueOf(node.getMemTotal()));
+                    createVmNumaNodes.add(createVmNumaNode);
+                    if (node.getPinnedVdsNumaNodeList().isEmpty()) {
+                        useAllVdsNodesMem = true;
+                    }
+                    else {
+                        
vmNumaNodePinInfo.addAll(node.getPinnedVdsNumaNodeList());
+                    }
+                }
+                createInfo.put(VdsProperties.VM_NUMA_NODES, createVmNumaNodes);
+            }
+            else {
+                useAllVdsNodesMem = true;
+            }
+            if (useAllVdsNodesMem) {
+                createNumaTune.put(VdsProperties.NUMA_TUNE_NODESET, 
buildStringFromListForNuma(totalVdsNumaNodesIndexes));
+            }
+            else {
+                createNumaTune.put(VdsProperties.NUMA_TUNE_NODESET, 
buildStringFromListForNuma(vmNumaNodePinInfo));
+            }
+            createInfo.put(VdsProperties.NUMA_TUNE, createNumaTune);
+            if (StringUtils.isEmpty(vm.getCpuPinning())) {
+                Map<String, Object> cpuPinDict = 
addCpuPinningForNumaSetting(vmNumaNodes, totalVdsNumaNodes);
+                if (!cpuPinDict.isEmpty()) {
+                    createInfo.put(VdsProperties.cpuPinning, cpuPinDict);
+                }
+            }
+        }
+    }
+
+    private Map<String, Object> addCpuPinningForNumaSetting(List<VmNumaNode> 
vmNodes, List<VdsNumaNode> vdsNodes) {
+        Map<Integer, List<Integer>> vdsNumaNodeCpus = new HashMap<>();
+        Map<String, Object> cpuPinDict = new HashMap<>();
+        for (VdsNumaNode node : vdsNodes) {
+            vdsNumaNodeCpus.put(node.getIndex(), node.getCpuIds());
+        }
+        for (VmNumaNode node : vmNodes) {
+            if (!node.getPinnedVdsNumaNodeList().isEmpty()) {
+                List <Integer> totalPinnedVdsCpus = new ArrayList<>();
+                for (Integer vCpu : node.getCpuIds()) {
+                    for (Integer pinnedVdsNode : 
node.getPinnedVdsNumaNodeList()) {
+                        if (vdsNumaNodeCpus.containsKey(pinnedVdsNode)) {
+                            
totalPinnedVdsCpus.addAll(vdsNumaNodeCpus.get(pinnedVdsNode));
+                        }
+                    }
+                    cpuPinDict.put(String.valueOf(vCpu), 
buildStringFromListForNuma(totalPinnedVdsCpus));
+                }
+            }
+        }
+        return cpuPinDict;
+    }
+
+    private String buildStringFromListForNuma(Collection<Integer> list) {
+        if (!list.isEmpty()) {
+            StringBuilder sb = new StringBuilder();
+            for (Integer item : list) {
+                sb.append(item);
+                sb.append(",");
+            }
+            return sb.deleteCharAt(sb.length() - 1).toString();
+        }
+        return "";
+    }
+
+    private List<Integer> getNodeIndexList(List<VdsNumaNode> nodeList) {
+        if (!nodeList.isEmpty()) {
+            List<Integer> nodeIndexes = new ArrayList<>(nodeList.size());
+            for (VdsNumaNode item : nodeList) {
+                nodeIndexes.add(item.getIndex());
+            }
+            return nodeIndexes;
+        }
+        return new ArrayList<Integer>();
+    }
+
     protected void buildVmNetworkCluster() {
         // set Display network
         List<NetworkCluster> all = DbFacade.getInstance()


-- 
To view, visit http://gerrit.ovirt.org/27083
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I050bc9d80a90ac73b5642ccd7630dd352eba236e
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Xiaolei Shi <xiao-lei....@hp.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to