CLOUDSTACK-8423: [Xenserver] Improved the performance for processing of ClusterVMMetaDataSync command which can cause slowness in DB if there are huge number of VMs this closes #204
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/866cc411 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/866cc411 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/866cc411 Branch: refs/heads/master Commit: 866cc41145bd8ccbf5f883a24ec3ef4763ebdb22 Parents: f46ed59 Author: Anshul Gangwar <anshul.gang...@citrix.com> Authored: Tue Apr 28 13:37:56 2015 +0530 Committer: Rajesh Battala <rajesh.batt...@citrix.com> Committed: Thu Apr 30 14:44:36 2015 +0530 ---------------------------------------------------------------------- .../com/cloud/vm/VirtualMachineManagerImpl.java | 62 +++++++++++++------- .../schema/src/com/cloud/vm/dao/UserVmDao.java | 4 ++ .../src/com/cloud/vm/dao/UserVmDaoImpl.java | 42 +++++++++++++ .../xenserver/resource/CitrixResourceBase.java | 4 ++ 4 files changed, 90 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java ---------------------------------------------------------------------- diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index 527b623..a48db61 100644 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -2558,40 +2558,58 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (vmMetadatum == null || vmMetadatum.isEmpty()) { return; } + List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> vmDetails = _userVmDao.getVmsDetailByNames(vmMetadatum.keySet(), "platform"); for (final Map.Entry<String, String> entry : vmMetadatum.entrySet()) { final String name = entry.getKey(); final String platform = entry.getValue(); if (platform == null || platform.isEmpty()) { continue; } - final VMInstanceVO vm = _vmDao.findVMByInstanceName(name); - if (vm != null && vm.getType() == VirtualMachine.Type.User) { - boolean changed = false; - final UserVmVO userVm = _userVmDao.findById(vm.getId()); - _userVmDao.loadDetails(userVm); - if ( userVm.details.containsKey("timeoffset")) { - userVm.details.remove("timeoffset"); - changed = true; - } - if (!userVm.details.containsKey("platform") || !userVm.details.get("platform").equals(platform)) { - userVm.setDetail("platform", platform); - changed = true; - } - String pvdriver = "xenserver56"; - if ( platform.contains("device_id")) { - pvdriver = "xenserver61"; - } - if (!userVm.details.containsKey("hypervisortoolsversion") || !userVm.details.get("hypervisortoolsversion").equals(pvdriver)) { - userVm.setDetail("hypervisortoolsversion", pvdriver); - changed = true; + + boolean found = false; + for(Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>> vmDetail : vmDetails ) { + Pair<String, VirtualMachine.Type> vmNameTypePair = vmDetail.first(); + if(vmNameTypePair.first().equals(name)) { + found = true; + if(vmNameTypePair.second() == VirtualMachine.Type.User) { + Pair<Long, String> detailPair = vmDetail.second(); + String platformDetail = detailPair.second(); + + if (platformDetail != null && platformDetail.equals(platform)) { + break; + } + updateVmMetaData(detailPair.first(), platform); + } + break; } - if ( changed ) { - _userVmDao.saveDetails(userVm); + } + + if(!found) { + VMInstanceVO vm = _vmDao.findVMByInstanceName(name); + if(vm.getType() == VirtualMachine.Type.User) { + updateVmMetaData(vm.getId(), platform); } } } } + // this is XenServer specific + private void updateVmMetaData(Long vmId, String platform) { + UserVmVO userVm = _userVmDao.findById(vmId); + _userVmDao.loadDetails(userVm); + if ( userVm.details.containsKey("timeoffset")) { + userVm.details.remove("timeoffset"); + } + userVm.setDetail("platform", platform); + String pvdriver = "xenserver56"; + if ( platform.contains("device_id")) { + pvdriver = "xenserver61"; + } + if (!userVm.details.containsKey("hypervisortoolsversion") || !userVm.details.get("hypervisortoolsversion").equals(pvdriver)) { + userVm.setDetail("hypervisortoolsversion", pvdriver); + } + _userVmDao.saveDetails(userVm); + } private void ensureVmRunningContext(final long hostId, VMInstanceVO vm, final Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException, InsufficientAddressCapacityException { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/engine/schema/src/com/cloud/vm/dao/UserVmDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDao.java b/engine/schema/src/com/cloud/vm/dao/UserVmDao.java index dfafdeb..dfcc7f7 100644 --- a/engine/schema/src/com/cloud/vm/dao/UserVmDao.java +++ b/engine/schema/src/com/cloud/vm/dao/UserVmDao.java @@ -19,9 +19,12 @@ package com.cloud.vm.dao; import java.util.Date; import java.util.Hashtable; import java.util.List; +import java.util.Set; +import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; import com.cloud.vm.UserVmVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; public interface UserVmDao extends GenericDao<UserVmVO, Long> { @@ -80,4 +83,5 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> { List<UserVmVO> listByIsoId(Long isoId); + List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> getVmsDetailByNames(Set<String> vmNames, String detail); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java index ef762e1..5fa3b06 100644 --- a/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java +++ b/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java @@ -24,11 +24,13 @@ import java.util.Date; import java.util.Hashtable; import java.util.List; import java.util.Map; +import java.util.Set; import javax.annotation.PostConstruct; import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.utils.Pair; import org.apache.log4j.Logger; import com.cloud.server.ResourceTag.ResourceObjectType; @@ -102,6 +104,11 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use + "left join security_group on security_group_vm_map.security_group_id=security_group.id " + "left join nics on vm_instance.id=nics.instance_id " + "left join networks on nics.network_id=networks.id " + "left join user_ip_address on user_ip_address.vm_id=vm_instance.id " + "where vm_instance.id in ("; + private static final String VMS_DETAIL_BY_NAME = "select vm_instance.instance_name, vm_instance.vm_type, vm_instance.id , user_vm_details.value, user_vm_details.name from vm_instance " + + "left join user_vm_details on vm_instance.id = user_vm_details.vm_id where (user_vm_details.name is null or user_vm_details.name = '"; + + private static final String VMS_DETAIL_BY_NAME2 = "') and vm_instance.instance_name in ("; + private static final int VM_DETAILS_BATCH_SIZE = 100; @Inject @@ -631,4 +638,39 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use return result; } + @Override + public List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> getVmsDetailByNames(Set<String> vmNames, String detail) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + List<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>> vmsDetailByNames = new ArrayList<Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>>(); + + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareStatement(VMS_DETAIL_BY_NAME + detail + VMS_DETAIL_BY_NAME2 + getQueryBatchAppender(vmNames.size())); + int i = 1; + for(String name : vmNames) { + pstmt.setString(i, name); + i++; + } + try { + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + vmsDetailByNames.add(new Pair<Pair<String, VirtualMachine.Type>, Pair<Long, String>>(new Pair<String, VirtualMachine.Type>( + rs.getString("vm_instance.instance_name"), VirtualMachine.Type.valueOf(rs.getString("vm_type"))), + new Pair<Long, String>(rs.getLong("vm_instance.id"), rs.getString("user_vm_details.value")))); + } + rs.close(); + } catch (Exception e) { + s_logger.error("GetVmsDetailsByNames: Exception: " + e.getMessage()); + throw new CloudRuntimeException("GetVmsDetailsByNames: Exception: " + e.getMessage()); + } + if(pstmt != null) { + pstmt.close(); + } + } catch (Exception e) { + s_logger.error("GetVmsDetailsByNames: Exception in sql: " + e.getMessage()); + throw new CloudRuntimeException("GetVmsDetailsByNames: Exception: " + e.getMessage()); + } + + return vmsDetailByNames; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/866cc411/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index ff9f61d..2b3035c 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -717,6 +717,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe if (record.isControlDomain || record.isASnapshot || record.isATemplate) { continue; // Skip DOM0 } + String platform = StringUtils.mapToString(record.platform); + if (platform.isEmpty()) { + continue; //Skip if platform is null + } vmMetaDatum.put(record.nameLabel, StringUtils.mapToString(record.platform)); } }