Sahina Bose has uploaded a new change for review. Change subject: engine: Clean up orphan gluster task references ......................................................................
engine: Clean up orphan gluster task references Gluster tasks sync job periodically updates status of gluster tasks in engine. However, if for some reason (for instance, if engine was offline for a period of time) gluster does not return a task's information, engine should mark the job ended with task status UNKNOWN Change-Id: I61f921109fb710dfb3f7255b54595c882c6a076c Bug-Url: https://bugzilla.redhat.com/1022996 Signed-off-by: Sahina Bose <sab...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJob.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/tasks/GlusterTasksService.java M backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJobTest.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDao.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDaoDbFacadeImpl.java M backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/StepDaoTest.java M packaging/dbscripts/job_sp.sql 7 files changed, 116 insertions(+), 8 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/54/20954/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJob.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJob.java index bc0d382..0cabb80 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJob.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJob.java @@ -2,9 +2,11 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.ovirt.engine.core.bll.Backend; import org.ovirt.engine.core.bll.gluster.tasks.GlusterTasksService; @@ -22,6 +24,7 @@ import org.ovirt.engine.core.common.businessentities.VDSGroup; import org.ovirt.engine.core.common.businessentities.VdsStatic; import org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity; +import org.ovirt.engine.core.common.businessentities.gluster.GlusterStatus; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity; import org.ovirt.engine.core.common.constants.gluster.GlusterConstants; import org.ovirt.engine.core.common.errors.VdcBLLException; @@ -76,10 +79,16 @@ log.debug("Refreshing gluster tasks list"); List<VDSGroup> clusters = getClusterDao().getAll(); + List<Guid> tasksFromClusters = new ArrayList<>(); for (VDSGroup cluster : clusters) { - updateTasksInCluster(cluster); + Map<Guid, GlusterAsyncTask> runningTasks = updateTasksInCluster(cluster); + if (runningTasks != null) { + tasksFromClusters.addAll(runningTasks.keySet()); + } } + + cleanUpOrphanTasks(tasksFromClusters); } @@ -345,4 +354,34 @@ private boolean supportsGlusterAsyncTasksFeature(VDSGroup cluster) { return cluster.supportsGlusterService() && GlusterFeatureSupported.glusterAsyncTasks(cluster.getcompatibility_version()); } + + private void cleanUpOrphanTasks(List<Guid> runningTasksinCluster) { + //Populate the list of tasks that need to be monitored from database + List<Guid> taskListInDB = getProvider().getMonitoredTaskIDsInDB(); + if (taskListInDB == null) { + taskListInDB = new ArrayList<Guid>(); + } + + //if task is in DB but not in running task list + final Set<Guid> tasksNotRunning = new HashSet<Guid>(taskListInDB); + tasksNotRunning.removeAll(runningTasksinCluster); + + for (Guid taskId: tasksNotRunning) { + GlusterVolumeEntity vol= getVolumeDao().getVolumeByGlusterTask(taskId); + if (vol != null && vol.getStatus() != GlusterStatus.UP) { + //the volume is not UP. Hence gluster may not have been able to return tasks for the volume + continue; + } + + //Volume is up, but gluster does not know of task + //will mark job ended with status unknown. + List<Step> steps = getStepDao().getStepsByExternalId(taskId); + for (Step step: steps) { + step.markStepEnded(JobExecutionStatus.UNKNOWN); + endStepJob(step); + } + releaseVolumeLock(taskId); + } + + } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/tasks/GlusterTasksService.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/tasks/GlusterTasksService.java index 3c5b2b0..ba5fde5 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/tasks/GlusterTasksService.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/tasks/GlusterTasksService.java @@ -8,11 +8,13 @@ import org.ovirt.engine.core.bll.utils.ClusterUtils; import org.ovirt.engine.core.common.asynctasks.gluster.GlusterAsyncTask; import org.ovirt.engine.core.common.businessentities.VDS; +import org.ovirt.engine.core.common.job.ExternalSystemType; 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.common.vdscommands.VdsIdVDSCommandParametersBase; import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.log.Log; import org.ovirt.engine.core.utils.log.LogFactory; @@ -51,9 +53,9 @@ * @return */ public List<Guid> getMonitoredTaskIDsInDB() { - // List<Guid> externalIds = DbFacade.getInstance().getStepDao(). - // getExternalIdsForRunningSteps(ExternalSystemType.GLUSTER); - return null; + List<Guid> externalIds = DbFacade.getInstance().getStepDao(). + getExternalIdsForRunningSteps(ExternalSystemType.GLUSTER); + return externalIds; } private VDSReturnValue runVdsCommand(VDSCommandType commandType, VDSParametersBase params) { diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJobTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJobTest.java index f56b97f..ec385b5 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJobTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterTasksSyncJobTest.java @@ -7,6 +7,7 @@ import static org.ovirt.engine.core.utils.MockConfigRule.mockConfig; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,7 @@ import org.ovirt.engine.core.common.asynctasks.gluster.GlusterTaskParameters; import org.ovirt.engine.core.common.asynctasks.gluster.GlusterTaskType; import org.ovirt.engine.core.common.businessentities.VDSGroup; +import org.ovirt.engine.core.common.businessentities.gluster.GlusterStatus; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.job.JobExecutionStatus; @@ -51,10 +53,12 @@ new Guid("CC222222-2222-2222-2222-222222222222")}; private static final Guid[] TASK_GUIDS = {new Guid("EE111111-1111-1111-1111-111111111111"), - new Guid("EE222222-2222-2222-2222-222222222222")}; + new Guid("EE222222-2222-2222-2222-222222222222"), + new Guid("EE333333-3333-3333-3333-333333333333")}; private static final Guid[] VOL_GUIDS = {new Guid("AA111111-1111-1111-1111-111111111111"), - new Guid("AA222222-2222-2222-2222-222222222222")}; + new Guid("AA222222-2222-2222-2222-222222222222"), + new Guid("AA333333-3333-3333-3333-333333333333")}; @ClassRule public static MockEJBStrategyRule ejbRule = new MockEJBStrategyRule(); @@ -105,7 +109,7 @@ doReturn(backend).when(tasksSyncJob).getBackend(); doNothing().when(tasksSyncJob).releaseLock(any(Guid.class)); doNothing().when(tasksSyncJob).endStepJob(any(Step.class)); - + doReturn(null).when(provider).getMonitoredTaskIDsInDB(); } @Test @@ -115,6 +119,28 @@ tasksSyncJob.updateGlusterAsyncTasks(); Mockito.verify(jobRepository, times(1)).updateStep(any(Step.class)); + Mockito.verify(tasksSyncJob, times(1)).endStepJob(any(Step.class)); + } + + @Test + public void cleanOrphanTasks() { + doReturn(getTasks()).when(provider).getTaskListForCluster(CLUSTER_GUIDS[1]); + doReturn(Arrays.asList(TASK_GUIDS[2])).when(provider).getMonitoredTaskIDsInDB(); + prepareMocks(); + + tasksSyncJob.updateGlusterAsyncTasks(); + Mockito.verify(jobRepository, times(1)).updateStep(any(Step.class)); + Mockito.verify(tasksSyncJob, times(2)).endStepJob(any(Step.class)); + } + + @Test + public void cleanOrphanTasksWhenNoVolume() { + doReturn(null).when(provider).getTaskListForCluster(CLUSTER_GUIDS[1]); + doReturn(Arrays.asList(TASK_GUIDS[2])).when(provider).getMonitoredTaskIDsInDB(); + doReturn(null).when(volumeDao).getVolumeByGlusterTask(TASK_GUIDS[2]); + doReturn(getSteps()).when(stepDao).getStepsByExternalId(TASK_GUIDS[2]); + + tasksSyncJob.updateGlusterAsyncTasks(); Mockito.verify(tasksSyncJob, times(1)).endStepJob(any(Step.class)); } @@ -176,9 +202,11 @@ private void prepareMocks() { doReturn(getVolume(0)).when(volumeDao).getVolumeByGlusterTask(TASK_GUIDS[0]); doReturn(getVolume(1)).when(volumeDao).getVolumeByGlusterTask(TASK_GUIDS[1]); + doReturn(getVolume(1)).when(volumeDao).getVolumeByGlusterTask(TASK_GUIDS[2]); doReturn(getSteps()).when(stepDao).getStepsByExternalId(TASK_GUIDS[0]); doReturn(getSteps()).when(stepDao).getStepsByExternalId(TASK_GUIDS[1]); - } + doReturn(getSteps()).when(stepDao).getStepsByExternalId(TASK_GUIDS[2]); + } private void prepareMocksForTasksFromCLI() { doReturn(getVolume(0)).when(volumeDao).getVolumeByGlusterTask(TASK_GUIDS[0]); @@ -202,6 +230,7 @@ private GlusterVolumeEntity getVolume(int i) { GlusterVolumeEntity vol = new GlusterVolumeEntity(); + vol.setStatus(GlusterStatus.UP); vol.setId(VOL_GUIDS[i]); return vol; } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDao.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDao.java index c388efb..46e1fb8 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDao.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDao.java @@ -3,6 +3,7 @@ import java.util.Date; import java.util.List; +import org.ovirt.engine.core.common.job.ExternalSystemType; import org.ovirt.engine.core.common.job.JobExecutionStatus; import org.ovirt.engine.core.common.job.Step; import org.ovirt.engine.core.compat.Guid; @@ -51,5 +52,10 @@ * @return */ List<Step> getStepsByExternalId(Guid externalId); + + /** + * Retrieve all external ids for steps that are not yet completed + */ + List<Guid> getExternalIdsForRunningSteps(ExternalSystemType systemType); } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDaoDbFacadeImpl.java index 5851e55..8c52eb0 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDaoDbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/StepDaoDbFacadeImpl.java @@ -107,4 +107,11 @@ return getCallsHandler().executeReadList("GetStepsByExternalTaskId", createEntityRowMapper(), parameterSource); } + @Override + public List<Guid> getExternalIdsForRunningSteps(ExternalSystemType systemType) { + MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource().addValue("external_system_type", systemType.name()) + .addValue("status", JobExecutionStatus.STARTED.name()); + return getCallsHandler().executeReadList("GetExternalIdsFromSteps", createGuidMapper(), parameterSource); + } + } diff --git a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/StepDaoTest.java b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/StepDaoTest.java index 43cf4c8..9b81996 100644 --- a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/StepDaoTest.java +++ b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/StepDaoTest.java @@ -10,6 +10,7 @@ import org.junit.Before; import org.junit.Test; +import org.ovirt.engine.core.common.job.ExternalSystemType; import org.ovirt.engine.core.common.job.JobExecutionStatus; import org.ovirt.engine.core.common.job.Step; import org.ovirt.engine.core.common.job.StepEnum; @@ -116,4 +117,11 @@ assertTrue("Verify the Step status", JobExecutionStatus.STARTED == step.getStatus()); assertEquals("Invalid Step", REBALANCING_GLUSTER_VOLUME_STEP_ID, step.getId()); } + + @Test + public void getExternalIdsForRunningSteps(){ + List<Guid> externalIds = dao.getExternalIdsForRunningSteps(ExternalSystemType.GLUSTER); + assertEquals("Verify external ids present", 1, externalIds.size()); + assertEquals("Invalid TaskId", IN_PROGRESS_REBALANCING_GLUSTER_VOLUME_TASK_ID, externalIds.get(0)); + } } diff --git a/packaging/dbscripts/job_sp.sql b/packaging/dbscripts/job_sp.sql index 2f13bb3..d151e55 100644 --- a/packaging/dbscripts/job_sp.sql +++ b/packaging/dbscripts/job_sp.sql @@ -518,3 +518,20 @@ ORDER BY parent_step_id nulls first, step_number; END; $procedure$ LANGUAGE plpgsql; + +---------------------------------------------------- +-- Gets list of external task UUIDs from Step table +-- for steps based on external system type and job status +---------------------------------------------------- +Create or replace FUNCTION GetExternalIdsFromSteps(v_status VARCHAR(32), + v_external_system_type VARCHAR(32)) +RETURNS SETOF UUID STABLE +AS $procedure$ +BEGIN + RETURN QUERY SELECT step.external_id + FROM step + INNER JOIN job ON step.job_id = job.job_id + WHERE job.status = v_status + AND step.external_system_type = v_external_system_type; +END; $procedure$ +LANGUAGE plpgsql; -- To view, visit http://gerrit.ovirt.org/20954 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I61f921109fb710dfb3f7255b54595c882c6a076c Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Sahina Bose <sab...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches