diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index a7e34f90e0e..2d82814119d 100755 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -18,12 +18,16 @@ package com.cloud.vm; import java.net.URI; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TimeZone; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -3412,11 +3416,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if(vm != null) { switch(vm.getPowerState()) { case PowerOn : - HandlePowerOnReportWithNoPendingJobsOnVM(vm); + handlePowerOnReportWithNoPendingJobsOnVM(vm); break; case PowerOff : - HandlePowerOffReportWithNoPendingJobsOnVM(vm); + handlePowerOffReportWithNoPendingJobsOnVM(vm); break; // PowerUnknown shouldn't be reported, it is a derived @@ -3434,7 +3438,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - private void HandlePowerOnReportWithNoPendingJobsOnVM(VMInstanceVO vm) { + private void handlePowerOnReportWithNoPendingJobsOnVM(VMInstanceVO vm) { // // 1) handle left-over transitional VM states // 2) handle out of band VM live migration @@ -3493,7 +3497,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - private void HandlePowerOffReportWithNoPendingJobsOnVM(VMInstanceVO vm) { + private void handlePowerOffReportWithNoPendingJobsOnVM(VMInstanceVO vm) { // TODO : // 1) handle left-over transitional VM states @@ -3527,15 +3531,69 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac private void scanStalledVMInTransitionState(long hostId) { // - // TODO check VM that is stuck in Starting, Stopping, Migrating states, we won't check + // Check VM that is stuck in Starting, Stopping, Migrating states, we won't check // VMs in expunging state (this need to be handled specially) // // checking condition // 1) no pending VmWork job - // 2) no power state update for some time - // 3) on hostId host - + // 2) on hostId host and host is UP + // + // When host is UP, soon or later we will get a report from the host about the VM, + // however, if VM is missing from the host report (it may happen in out of band changes + // or from designed behave of XS/KVM) + // } + + // TODO, use sql query directly for quick prototype, need to refactor to use joins and search builders + // if it supports + @DB + private List listStalledVMInTransitionStateOnUpHost(long hostId, Date cutTime) { + String sql = "SELECT i.* FROM vm_instance as i, host as h WHERE h.status = 'UP' " + + "AND h.id = ? AND i.power_state_update_time < ? AND i.host_id = h.id " + + "AND (i.state ='Starting' OR i.state='Stopping' OR i.state='Migrating') " + + "AND i.id NOT IN (SELECT vm_instance_id FROM vm_work_job)"; + + List l = new ArrayList(); + Transaction txn = Transaction.currentTxn();; + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareAutoCloseStatement(sql); + + pstmt.setLong(1, hostId); + pstmt.setString(2, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutTime)); + ResultSet rs = pstmt.executeQuery(); + while(rs.next()) { + l.add(rs.getLong(1)); + } + } catch (SQLException e) { + } catch (Throwable e) { + } + return l; + } + + @DB + private List listStalledVMInTransitionStateOnDisconnectedHosts(Date cutTime) { + String sql = "SELECT i.* FROM vm_instance as i, host as h WHERE h.status != 'UP' " + + "AND i.power_state_update_time < ? AND i.host_id = h.id " + + "AND (i.state ='Starting' OR i.state='Stopping' OR i.state='Migrating') " + + "AND i.id NOT IN (SELECT vm_instance_id FROM vm_work_job)"; + + List l = new ArrayList(); + Transaction txn = Transaction.currentTxn();; + PreparedStatement pstmt = null; + try { + pstmt = txn.prepareAutoCloseStatement(sql); + + pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutTime)); + ResultSet rs = pstmt.executeQuery(); + while(rs.next()) { + l.add(rs.getLong(1)); + } + } catch (SQLException e) { + } catch (Throwable e) { + } + return l; + } } diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java index e76781c357e..9c47727ed51 100644 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java @@ -66,7 +66,6 @@ public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStat private void processReport(long hostId, Map translatedInfo) { - for(Map.Entry entry : translatedInfo.entrySet()) { if(s_logger.isDebugEnabled()) @@ -80,11 +79,6 @@ public class VirtualMachinePowerStateSyncImpl implements VirtualMachinePowerStat _messageBus.publish(null, VirtualMachineManager.Topics.VM_POWER_STATE, PublishScope.GLOBAL, entry.getKey()); } } - - // - // TODO - // 1) publish missing report (if VM is missing from host report) for KVM/XenServer - // } private Map convertHostPingInfos(Map states) {