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