From a3e6974a94fa2af921a1b25542a2f1b637eec05e Mon Sep 17 00:00:00 2001 From: Anshul Gangwar Date: Tue, 28 Apr 2015 13:37:56 +0530 Subject: [PATCH] CLOUDSTACK-8423: [Xenserver] Improved the performance for processing of ClusterVMMetaDataSync command which can cause slowness in DB if there are huge number of VMs --- .../cloud/vm/VirtualMachineManagerImpl.java | 62 ++++++++++++------- .../src/com/cloud/vm/dao/UserVmDao.java | 4 ++ .../src/com/cloud/vm/dao/UserVmDaoImpl.java | 42 +++++++++++++ .../resource/CitrixResourceBase.java | 4 ++ 4 files changed, 90 insertions(+), 22 deletions(-) diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index 527b623d04dd..a48db6119e09 100644 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -2558,40 +2558,58 @@ public void syncVMMetaData(final Map vmMetadatum) { if (vmMetadatum == null || vmMetadatum.isEmpty()) { return; } + List, Pair>> vmDetails = _userVmDao.getVmsDetailByNames(vmMetadatum.keySet(), "platform"); for (final Map.Entry 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> vmDetail : vmDetails ) { + Pair vmNameTypePair = vmDetail.first(); + if(vmNameTypePair.first().equals(name)) { + found = true; + if(vmNameTypePair.second() == VirtualMachine.Type.User) { + Pair 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 { diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDao.java b/engine/schema/src/com/cloud/vm/dao/UserVmDao.java index dfafdeb966b2..dfcc7f7fc333 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 @@ 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 { @@ -80,4 +83,5 @@ public interface UserVmDao extends GenericDao { List listByIsoId(Long isoId); + List, Pair>> getVmsDetailByNames(Set vmNames, String detail); } diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java index ef762e1aef2f..5fa3b06f239e 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.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 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 boolean remove(Long id) { return result; } + @Override + public List, Pair>> getVmsDetailByNames(Set vmNames, String detail) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + List, Pair>> vmsDetailByNames = new ArrayList, Pair>>(); + + 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>(new Pair( + rs.getString("vm_instance.instance_name"), VirtualMachine.Type.valueOf(rs.getString("vm_type"))), + new Pair(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; + } } 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 bc812e80e99c..f9fc483c8d2f 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 @@ -719,6 +719,10 @@ public HashMap clusterVMMetaDataSync(final Connection conn) { 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)); } }