Roy Golan has uploaded a new change for review.

Change subject: core: VURTI - fix handle expection in GetVmStats
......................................................................

core: VURTI - fix handle expection in GetVmStats

after getting all vms with List command, VURTI loops through them
to update internal structure data. BUT if the call fails, VURTI removes
the VM from the internal running map - this leads to a split-brains
for VURTI assumes the Vm is DOWN and if it HA, its runs it.

the fix is to move the VM to UKNOWN so it would be ignored in this
cycle.

UNIT TEST
added a unit test to make sure the VM is kept in the map
although the call to GetVmStats didn't made it

Bug-Url: https://bugzilla.redhat.com/1072282
Change-Id: I415804d9fa1f1288423241b8547f4cab5540914a
Signed-off-by: Roy Golan <rgo...@redhat.com>
---
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/ResourceManager.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/test/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfoTest.java
4 files changed, 136 insertions(+), 18 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/48/25548/1

diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/ResourceManager.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/ResourceManager.java
index f695f60..0169187 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/ResourceManager.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/ResourceManager.java
@@ -53,7 +53,6 @@
             Collections.newSetFromMap(new ConcurrentHashMap<Guid, Boolean>());
 
     private static final String VDSCommandPrefix = "VDSCommand";
-
     private static Log log = LogFactory.getLog(ResourceManager.class);
 
     private ResourceManager() {
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 109c2f8..b7cddbb 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
@@ -65,7 +65,7 @@
         return (_refreshIteration == _numberRefreshesBeforeSave);
     }
 
-    private static final int VDS_REFRESH_RATE = Config.<Integer> 
getValue(ConfigValues.VdsRefreshRate) * 1000;
+    private int VDS_REFRESH_RATE = Config.<Integer> 
getValue(ConfigValues.VdsRefreshRate) * 1000;
 
     private String onTimerJobId;
 
@@ -97,7 +97,7 @@
     private final AtomicInteger mUnrespondedAttempts;
     private final AtomicBoolean sshSoftFencingExecuted;
 
-    private static final int VDS_DURING_FAILURE_TIMEOUT_IN_MINUTES = Config
+    private  int VDS_DURING_FAILURE_TIMEOUT_IN_MINUTES = Config
             .<Integer> 
getValue(ConfigValues.TimeToReduceFailedRunOnVdsInMinutes);
     private String duringFailureJobId;
     private boolean privateInitialized;
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 6dda8bf..5da02c1 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
@@ -934,7 +934,7 @@
         }
     }
 
-    private void refreshVmStats() {
+    protected void refreshVmStats() {
         if (Config.<Boolean> getValue(ConfigValues.DebugTimerLogging)) {
             log.debug("vds::refreshVmList entered");
         }
@@ -1295,7 +1295,7 @@
     }
 
     // if not statistics check if status changed and add to running list
-    private List<VM> checkVmsStatusChanged() {
+    protected List<VM> checkVmsStatusChanged() {
         List<VM> running = new ArrayList<VM>();
         if (!_vdsManager.getRefreshStatistics()) {
             List<VmDynamic> tempRunningList = new ArrayList<VmDynamic>();
@@ -1618,7 +1618,7 @@
         }
     }
 
-    private void processExternallyManagedVms() {
+    protected void processExternallyManagedVms() {
         List<String> vmsToQuery = new ArrayList<String>();
         // Searching for External VMs that run on the host
         for (VmInternalData vmInternalData : _runningVms.values()) {
diff --git 
a/backend/manager/modules/vdsbroker/src/test/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfoTest.java
 
b/backend/manager/modules/vdsbroker/src/test/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfoTest.java
index a4b0f4e..cb09d62 100644
--- 
a/backend/manager/modules/vdsbroker/src/test/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfoTest.java
+++ 
b/backend/manager/modules/vdsbroker/src/test/java/org/ovirt/engine/core/vdsbroker/VdsUpdateRunTimeInfoTest.java
@@ -4,6 +4,7 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -12,11 +13,13 @@
 import java.util.List;
 import java.util.Map;
 
+import junit.framework.Assert;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.ovirt.engine.core.common.AuditLogType;
 import org.ovirt.engine.core.common.businessentities.AuditLog;
@@ -26,10 +29,16 @@
 import org.ovirt.engine.core.common.businessentities.VDS;
 import org.ovirt.engine.core.common.businessentities.VDSGroup;
 import org.ovirt.engine.core.common.businessentities.VM;
+import org.ovirt.engine.core.common.businessentities.VMStatus;
 import org.ovirt.engine.core.common.businessentities.VmDevice;
 import org.ovirt.engine.core.common.businessentities.VmDynamic;
 import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType;
+import org.ovirt.engine.core.common.config.ConfigValues;
+import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
+import org.ovirt.engine.core.common.vdscommands.VDSParametersBase;
+import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
 import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.compat.Version;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
 import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
 import org.ovirt.engine.core.dao.AuditLogDAO;
@@ -37,6 +46,8 @@
 import org.ovirt.engine.core.dao.VdsGroupDAO;
 import org.ovirt.engine.core.dao.VmDAO;
 import org.ovirt.engine.core.dao.VmDeviceDAO;
+import org.ovirt.engine.core.dao.VmDynamicDAO;
+import org.ovirt.engine.core.utils.MockConfigRule;
 import org.ovirt.engine.core.utils.MockEJBStrategyRule;
 import org.ovirt.engine.core.vdsbroker.vdsbroker.VdsProperties;
 import org.ovirt.engine.core.vdsbroker.vdsbroker.entities.VmInternalData;
@@ -44,13 +55,27 @@
 @RunWith(MockitoJUnitRunner.class)
 public class VdsUpdateRunTimeInfoTest {
 
+    private static final Guid VM_1 = 
Guid.createGuidFromString("7eeabc50-325f-49bb-acb6-15e786599423");
+
     @ClassRule
     public static MockEJBStrategyRule mockEjbRule = new MockEJBStrategyRule();
+
+    @ClassRule
+    public static MockConfigRule mcr = new MockConfigRule(
+            MockConfigRule.mockConfig(
+                    ConfigValues.DebugTimerLogging,
+                    true),
+            MockConfigRule.mockConfig(
+                    ConfigValues.VdsRefreshRate,
+                    3),
+            MockConfigRule.mockConfig(
+                    ConfigValues.TimeToReduceFailedRunOnVdsInMinutes,
+                    3)
+    );
 
     private VDS vds;
     HashMap[] vmInfo;
     List<VmDynamic> poweringUpVms;
-    Map<Guid, VmInternalData> runningVms;
 
     VdsUpdateRunTimeInfo updater;
 
@@ -72,13 +97,28 @@
     @Mock
     VmDeviceDAO vmDeviceDAO;
 
+    @Mock
+    VmDynamicDAO vmDynamicDao;
+
     AuditLogDAO mockAuditLogDao = new AuditLogDaoMocker();
+
+    VM vm_1_db;
+    VM vm_1_vdsm;
+
+    @Mock
+    ResourceManager resourceManager;
+
+    @Mock
+    private VdsManager vdsManager;
+
 
     @Before
     public void setup() {
         initVds();
         initConditions();
-        updater = new VdsUpdateRunTimeInfo(null, vds, 
mock(MonitoringStrategy.class)) {
+        when(vdsManager.getRefreshStatistics()).thenReturn(false);
+        updater = Mockito.spy(
+                    new VdsUpdateRunTimeInfo(vdsManager, vds, 
mock(MonitoringStrategy.class)) {
 
             @Override
             public DbFacade getDbFacade() {
@@ -101,13 +141,7 @@
             protected List<VmDynamic> getPoweringUpVms() {
                 return poweringUpVms;
             }
-
-            @Override
-            protected Map<Guid, VmInternalData> getRunningVms() {
-                return runningVms;
-            }
-
-        };
+        });
     }
 
     @Test
@@ -183,9 +217,8 @@
         VmInternalData vmInternalData = new VmInternalData(vmDynamic, null, 
null, lunsMapFromVmStats);
 
         when(diskDAO.getAllForVm(any(Guid.class), 
any(Boolean.class))).thenReturn(vmLunDisksFromDb);
-
+        
when(updater.getRunningVms()).thenReturn(Collections.singletonMap(vmId, 
vmInternalData));
         poweringUpVms = Collections.singletonList(vmDynamic);
-        runningVms = Collections.singletonMap(vmId, vmInternalData);
 
         updater.updateLunDisks();
     }
@@ -195,15 +228,18 @@
         when(dbFacade.getVmDao()).thenReturn(vmDAO);
         when(dbFacade.getAuditLogDao()).thenReturn(mockAuditLogDao);
         when(dbFacade.getVmDeviceDao()).thenReturn(vmDeviceDAO);
+        when(dbFacade.getVmDynamicDao()).thenReturn(vmDynamicDao);
         when(dbFacade.getDiskDao()).thenReturn(diskDAO);
         when(groupDAO.get((Guid) any())).thenReturn(cluster);
         Map<Guid, VM> emptyMap = Collections.emptyMap();
-        when(vmDAO.getAllRunningByVds(vds.getId())).thenReturn(emptyMap);
+        initVm();
+        
when(vmDAO.getAllRunningByVds(vds.getId())).thenReturn(Collections.singletonMap(VM_1,
 vm_1_db));
     }
 
     private void initVds() {
         vds = new VDS();
         vds.setId(new Guid("00000000-0000-0000-0000-000000000012"));
+        vds.setVdsGroupCompatibilityVersion(Version.v3_4);
     }
 
     @Test
@@ -221,4 +257,87 @@
         dynamic.setLastWatchdogEvent(null);
         assertFalse(VdsUpdateRunTimeInfo.isNewWatchdogEvent(dynamic, vm));
     }
+
+    /**
+     * Test that when we succeed in retriving a VM stats, we insert it into 
the internal runningVms structure
+     */
+    @Test
+    public void verifyListOfRunningVmsIsSameWithSuccessFromVdsmResponse() {
+        prepareForRefreshVmStatsCall();
+        mockGetVmStatsCommand(true);
+        // start refreshing vm data... VURTI now fetches Vms list from 
ResourceManager and loop through it
+        updater.refreshVmStats();
+        Assert.assertTrue("expecting the VM in running VMs map", 
updater.getRunningVms().containsKey(VM_1));
+        Assert.assertTrue(
+                String.format("expecting the VM to be in status %s and got 
%s", VMStatus.Up, vm_1_db.getStatus()),
+                updater.getRunningVms().get(VM_1).getVmDynamic().getStatus() 
== VMStatus.Up);
+    }
+
+    /**
+     * Test that when we fail in getting a response for GetVmStats we still 
insert the VM to the runningVms structure,<br>
+     * but with status UNKNOWN
+     */
+    @Test
+    public void verifyListOfRunningVmsIsSameWithFailureOnGetVmStats() {
+        prepareForRefreshVmStatsCall();
+        mockGetVmStatsCommand(false);
+        // start refreshing vm data... VURTI now fetches Vms list from 
ResourceManager and loop through it
+        updater.refreshVmStats();
+        Assert.assertTrue("expecting the VM in running VMs map", 
updater.getRunningVms().containsKey(VM_1));
+        Assert.assertTrue(
+                String.format("expecting the VM to be in status %s and got 
%s", VMStatus.Unknown, vm_1_db.getStatus()),
+                updater.getRunningVms().get(VM_1).getVmDynamic().getStatus() 
== VMStatus.Unknown);
+    }
+
+    private void prepareForRefreshVmStatsCall() {
+        initVm();
+        mockUpdater();
+        mockListCommand();
+        muteNonRelatedMethods();
+    }
+
+    private void mockUpdater() {
+        when(updater.getResourceManager()).thenReturn(resourceManager);
+    }
+
+    private void initVm() {
+        vm_1_vdsm = new VM();
+        vm_1_db = new VM();
+        vm_1_db.setId(VM_1);
+        vm_1_vdsm.setId(VM_1);
+        vm_1_db.setStatus(VMStatus.WaitForLaunch);
+        vm_1_vdsm.setStatus(VMStatus.Up);
+        vm_1_db.setName("vm-prod-mailserver");
+        vm_1_vdsm.setName("vm-prod-mailserver");
+        when(vmDynamicDao.get(VM_1)).thenReturn(vm_1_db.getDynamicData());
+    }
+
+    private void mockGetVmStatsCommand(boolean mockSuccess) {
+        VDSReturnValue vdsReturnValue = new VDSReturnValue();
+        if (mockSuccess) {
+            vdsReturnValue.setSucceeded(true);
+            vdsReturnValue.setReturnValue(createRunningVms().get(VM_1));
+        }
+        
when(resourceManager.runVdsCommand(Mockito.eq(VDSCommandType.GetVmStats), 
(VDSParametersBase) Mockito.anyObject())).thenReturn(vdsReturnValue);
+    }
+
+    private void mockListCommand() {
+        VDSReturnValue vdsReturnValue = new VDSReturnValue();
+        vdsReturnValue.setSucceeded(true);
+        vdsReturnValue.setReturnValue(createRunningVms());
+        when(resourceManager.runVdsCommand(Mockito.eq(VDSCommandType.List), 
(VDSParametersBase) Mockito.anyObject())).thenReturn(vdsReturnValue);
+        
when(resourceManager.runVdsCommand(Mockito.eq(VDSCommandType.GetVmStats), 
(VDSParametersBase) Mockito.anyObject())).thenReturn(vdsReturnValue);
+        when(updater.getResourceManager()).thenReturn(resourceManager);
+    }
+
+    private void muteNonRelatedMethods() {
+        doNothing().when(updater).processExternallyManagedVms();
+        
when(updater.getPoweringUpVms()).thenReturn(Collections.<VmDynamic>emptyList());
+    }
+
+    private Map<Guid, VmInternalData> createRunningVms() {
+        HashMap<Guid, VmInternalData> vms = new HashMap<>();
+        vms.put(VM_1, new VmInternalData(vm_1_vdsm.getDynamicData(), null, 
null, null));
+        return vms;
+    }
 }


-- 
To view, visit http://gerrit.ovirt.org/25548
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I415804d9fa1f1288423241b8547f4cab5540914a
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Roy Golan <rgo...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to