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
This commit is contained in:
Anshul Gangwar 2015-04-28 13:37:56 +05:30 committed by Rajesh Battala
parent f46ed59290
commit 866cc41145
4 changed files with 90 additions and 22 deletions

View File

@ -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;
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 (!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;
}
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 {

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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));
}
}