Sahina Bose has uploaded a new change for review. Change subject: engine: Monitoring of geo-rep status and statistics ......................................................................
engine: Monitoring of geo-rep status and statistics Created a scheduler job to poll for status and statistics of each session. Exposed the methods of GlusterGeoRepSyncJob to refresh status and discover geo-rep sessions for a volume, so that these can be triggered via UI and API Change-Id: I67e857ab2ce993cded966fb60b361f6962b9a665 Bug-Url: https://bugzilla.redhat.com/1138116 Signed-off-by: Sahina Bose <[email protected]> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJob.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java M backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJobTest.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllErrors.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterGeoRepDaoDbFacadeImpl.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeGeoRepStatusDetailVDSCommand.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusDetailForXmlRpc.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusForXmlRpc.java M packaging/dbscripts/create_views.sql M packaging/dbscripts/gluster_georep_sp.sql M packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql M packaging/etc/engine-config/engine-config.properties 14 files changed, 308 insertions(+), 67 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/83/39583/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJob.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJob.java index 362fb3f..bf478c2 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJob.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJob.java @@ -5,7 +5,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.ArrayUtils; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.businessentities.VDS; @@ -15,11 +17,15 @@ import org.ovirt.engine.core.common.businessentities.gluster.GlusterGeoRepSessionDetails; 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; +import org.ovirt.engine.core.common.errors.VdcBllErrors; import org.ovirt.engine.core.common.gluster.GlusterFeatureSupported; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.common.vdscommands.gluster.GlusterVolumeGeoRepSessionVDSParameters; import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.utils.lock.EngineLock; +import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil; import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,27 +48,104 @@ } @OnTimerMethodAnnotation("gluster_georep_poll_event") - public void refreshGeoRepData() { + public void discoverGeoRepData() { // get all clusters List<VDSGroup> clusters = getClusterDao().getAll(); // for every cluster that supports geo-rep monitoring for (VDSGroup cluster : clusters) { - refreshGeoRepDataInCluster(cluster); + discoverGeoRepDataInCluster(cluster); } } - public void refreshGeoRepDataInCluster(VDSGroup cluster) { + @OnTimerMethodAnnotation("gluster_georepstatus_poll_event") + public void refreshGeoRepSessionStatus() { + // get all clusters + List<VDSGroup> clusters = getClusterDao().getAll(); + // for every cluster that supports geo-rep monitoring + for (VDSGroup cluster : clusters) { + refreshGeoRepSessionStatusInCluster(cluster); + } + } + + private void refreshGeoRepSessionStatusInCluster(final VDSGroup cluster) { + if (!supportsGlusterGeoRepFeature(cluster)) { + return; + } + List<GlusterGeoRepSession> geoRepSessions = getGeoRepDao().getGeoRepSessionsInCluster(cluster.getId()); + refreshGeoRepSessionStatusForSessions(cluster, geoRepSessions); + } + + /** + * Exposing this to be called via BLL command in case of force sync of geo-replication session data for volume + * @param volume + */ + public void refreshGeoRepDataForVolume(final GlusterVolumeEntity volume) { + if (volume == null) { + throw new VdcBLLException(VdcBllErrors.GlusterVolumeGeoRepSyncFailed, "No volume information"); + } + VDSGroup cluster = getClusterDao().get(volume.getClusterId()); + discoverGeoRepDataInCluster(cluster, volume.getName()); + List<GlusterGeoRepSession> geoRepSessions = getGeoRepDao().getGeoRepSessions(volume.getId()); + refreshGeoRepSessionStatusForSessions(cluster, geoRepSessions); + } + + private void refreshGeoRepSessionStatusForSessions(final VDSGroup cluster, List<GlusterGeoRepSession> geoRepSessions) { + if (CollectionUtils.isEmpty(geoRepSessions)) { + return; + } + List<Callable<GlusterGeoRepSession>> geoRepSessionCalls = new ArrayList<>(); + for (final GlusterGeoRepSession geoRepSession: geoRepSessions) { + geoRepSessionCalls.add(new Callable<GlusterGeoRepSession>() { + + @Override + public GlusterGeoRepSession call() throws Exception { + geoRepSession.setSessionDetails((ArrayList) getSessionDetailFromCLI(cluster, geoRepSession)); + return geoRepSession; + } + + }); + } + + List<GlusterGeoRepSession> updatedSessions = ThreadPoolUtil.invokeAll(geoRepSessionCalls); + for (GlusterGeoRepSession updatedSession : updatedSessions) { + if (updatedSession.getSessionDetails() == null) { + log.info("Geo-replication session details not updated for session '{}' as there was error returning data from VDS", + updatedSession.getSessionKey()); + continue; + } + try (EngineLock lock = acquireGeoRepSessionLock(updatedSession.getId())) { + GlusterVolumeEntity masterVolume = getVolumeDao().getById(updatedSession.getMasterVolumeId()); + updateGeoRepStatus(masterVolume, updatedSession); + getGeoRepDao().updateSession(updatedSession); + updateSessionDetailsInDB(updatedSession); + } catch (Exception e) { + log.error("Error updating session details '{}' : '{}'", updatedSession.getSessionKey(), e.getMessage()); + log.debug("Exception", e); + } + } + } + + private void discoverGeoRepDataInCluster(VDSGroup cluster) { + discoverGeoRepDataInCluster(cluster, null); + } + + private void discoverGeoRepDataInCluster(VDSGroup cluster, String volumeName) { if (!supportsGlusterGeoRepFeature(cluster)) { return; } - Map<String, GlusterGeoRepSession> sessionsMap = getSessionsForCluster(cluster); + Map<String, GlusterGeoRepSession> sessionsMap = getSessionsFromCLI(cluster, volumeName); if (sessionsMap == null) { - log.debug("Error in retrieving sessions for cluster '{}' from CLI, nothing to do", cluster.getName()); + log.debug("No sessions retrieved for cluster: {} from CLI, nothing to do", cluster.getName()); return; } + updateDiscoveredSessions(cluster, sessionsMap); + } + + + private void updateDiscoveredSessions(VDSGroup cluster, Map<String, GlusterGeoRepSession> sessionsMap) { removeDeletedSessions(cluster.getId(), sessionsMap); // for each geo-rep session, find session in database and update details. @@ -88,24 +171,48 @@ if (Guid.isNullOrEmpty(session.getId())) { session.setId(Guid.newGuid()); } + if (session.getSlaveNodeUuid() == null && session.getSlaveVolumeId() == null) { + updateSlaveNodeAndVolumeId(session); + } getGeoRepDao().save(session); logGeoRepMessage(AuditLogType.GLUSTER_GEOREP_SESSION_DETECTED_FROM_CLI, cluster.getId(), session); } else { + if (sessionInDb.getSlaveNodeUuid() == null && sessionInDb.getSlaveVolumeId() == null + && session.getSlaveNodeUuid() == null && session.getSlaveVolumeId() == null) { + updateSlaveNodeAndVolumeId(session); + } session.setId(sessionInDb.getId()); getGeoRepDao().updateSession(session); } - //update the session details object with session id. - for (GlusterGeoRepSessionDetails sessDetails : session.getSessionDetails()) { - sessDetails.setSessionId(session.getId()); - } - getGeoRepDao().saveOrUpdateDetailsInBatch(session.getSessionDetails()); + updateSessionDetailsInDB(session); } + } + private void updateSlaveNodeAndVolumeId(GlusterGeoRepSession session) { + // populate ids from the ones that exist in engine + List<VDS> slaveHosts = getVdsDao().getAllForHostname(session.getSlaveHostName()); + if (!CollectionUtils.isEmpty(slaveHosts)) { + session.setSlaveNodeUuid(slaveHosts.get(0).getId()); + GlusterVolumeEntity slaveVol = + getVolumeDao().getByName(slaveHosts.get(0).getVdsGroupId(), + session.getSlaveVolumeName()); + if (slaveVol != null) { + session.setSlaveVolumeId(slaveVol.getId()); + } + } + } + + private void updateSessionDetailsInDB(GlusterGeoRepSession session) { + // update the session details object with session id. + for (GlusterGeoRepSessionDetails sessDetails : session.getSessionDetails()) { + sessDetails.setSessionId(session.getId()); + } + getGeoRepDao().saveOrUpdateDetailsInBatch(session.getSessionDetails()); } private void removeDeletedSessions(Guid clusterId, final Map<String, GlusterGeoRepSession> sessionsMap) { List<GlusterGeoRepSession> sessionsInDb = getGeoRepDao().getGeoRepSessionsInCluster(clusterId); - if (sessionsInDb == null || sessionsInDb.isEmpty()) { + if (CollectionUtils.isEmpty(sessionsInDb)) { return; } List<GlusterGeoRepSession> sessionsToDelete = new ArrayList<>(); @@ -116,7 +223,7 @@ } for (final GlusterGeoRepSession session : sessionsToDelete) { - log.debug("geo-rep session '{}' detected removed for volume '{}'", + log.info("geo-rep session '{}' detected removed for volume '{}'", session.getSessionKey(), session.getMasterVolumeName()); getGeoRepDao().remove(session.getId()); @@ -194,7 +301,7 @@ return GeoRepSessionStatus.UNKNOWN; } - private Map<String, GlusterGeoRepSession> getSessionsForCluster(VDSGroup cluster) { + private Map<String, GlusterGeoRepSession> getSessionsFromCLI(VDSGroup cluster, String volumeName) { VDS upServer = getClusterUtils().getRandomUpServer(cluster.getId()); if (upServer == null) { log.debug("No UP server found in cluster '{}' for geo-rep monitoring", cluster.getName()); @@ -202,7 +309,7 @@ } // get details of geo-rep sessions in cluster VDSReturnValue returnValue = runVdsCommand(VDSCommandType.GetGlusterVolumeGeoRepStatus, - new GlusterVolumeGeoRepSessionVDSParameters(upServer.getId(), null)); + new GlusterVolumeGeoRepSessionVDSParameters(upServer.getId(), volumeName)); if (returnValue.getSucceeded()) { List<GlusterGeoRepSession> sessions = (List<GlusterGeoRepSession>) returnValue.getReturnValue(); HashMap<String, GlusterGeoRepSession> sessionsMap = new HashMap<>(); @@ -221,6 +328,30 @@ } + private List<GlusterGeoRepSessionDetails> getSessionDetailFromCLI(VDSGroup cluster, GlusterGeoRepSession session) { + VDS upServer = getClusterUtils().getRandomUpServer(cluster.getId()); + if (upServer == null) { + log.debug("No UP server found in cluster: {} for geo-rep monitoring", cluster.getName()); + return null; + } + try { + VDSReturnValue returnValue = runVdsCommand(VDSCommandType.GetGlusterVolumeGeoRepStatusDetail, + new GlusterVolumeGeoRepSessionVDSParameters(upServer.getId(), + session.getMasterVolumeName(), session.getSlaveHostName(), session.getSlaveVolumeName())); + if (returnValue.getSucceeded()) { + return (List<GlusterGeoRepSessionDetails>) returnValue.getReturnValue(); + } else { + log.error("VDS error {}", returnValue.getVdsError().getMessage()); + log.debug("VDS error", returnValue.getVdsError()); + return null; + } + } catch (Exception e) { + log.error("Exception getting geo-rep status from vds {}", e.getMessage()); + log.debug("Exception", e); + return null; + } + } + private GlusterVolumeEntity getVolume(VDSGroup cluster, String masterVolumeName) { return getVolumeDao().getByName(cluster.getId(), masterVolumeName); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java index 57beb7b..dce1120 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java @@ -166,6 +166,14 @@ LockMessagesMatchUtil.makeLockingPair(LockingGroup.GLUSTER, VdcBllMessages.ACTION_TYPE_FAILED_GLUSTER_OPERATION_INPROGRESS)), null); } + protected EngineLock acquireGeoRepSessionLock(Guid id) { + EngineLock lock = new EngineLock(Collections.singletonMap(id.toString(), + LockMessagesMatchUtil.makeLockingPair(LockingGroup.GLUSTER_GEOREP, + VdcBllMessages.ACTION_TYPE_FAILED_GEOREP_SESSION_LOCKED)), null); + LockManagerFactory.getLockManager().acquireLockWait(lock); + return lock; + } + protected GlusterUtil getGlusterUtil() { return GlusterUtil.getInstance(); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java index 96e19aa..1e615e1 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java @@ -68,10 +68,17 @@ "gluster_georep_poll_event", new Class[0] , new Class [0], - getRefreshRate(ConfigValues.GlusterRefreshRateGeoRepDiscovery), - getRefreshRate(ConfigValues.GlusterRefreshRateGeoRepDiscovery), + getRefreshRate(ConfigValues.GlusterRefreshRateGeoRepDiscoveryInSecs), + getRefreshRate(ConfigValues.GlusterRefreshRateGeoRepDiscoveryInSecs), TimeUnit.SECONDS); + scheduler.scheduleAFixedDelayJob(GlusterGeoRepSyncJob.getInstance(), + "gluster_georepstatus_poll_event", + new Class[0], + new Class[0], + getRefreshRate(ConfigValues.GlusterRefreshRateGeoRepStatusInSecs), + getRefreshRate(ConfigValues.GlusterRefreshRateGeoRepStatusInSecs), + TimeUnit.SECONDS); } private static boolean glusterModeSupported() { diff --git a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJobTest.java b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJobTest.java index 3f4de6d..ee80831 100644 --- a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJobTest.java +++ b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterGeoRepSyncJobTest.java @@ -33,13 +33,17 @@ import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.Version; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.gluster.GlusterAuditLogUtil; +import org.ovirt.engine.core.dao.VdsDAO; import org.ovirt.engine.core.dao.VdsGroupDAO; import org.ovirt.engine.core.dao.gluster.GlusterGeoRepDao; import org.ovirt.engine.core.dao.gluster.GlusterVolumeDao; import org.ovirt.engine.core.utils.MockConfigRule; +import org.ovirt.engine.core.utils.lock.EngineLock; @RunWith(MockitoJUnitRunner.class) public class GlusterGeoRepSyncJobTest { + private static final Guid[] CLUSTER_GUIDS = { new Guid("CC111111-1111-1111-1111-111111111111"), + new Guid("CC222222-2222-2222-2222-222222222222") }; @Mock private GlusterGeoRepDao geoRepDao; @@ -49,6 +53,9 @@ @Mock private VdsGroupDAO clusterDao; + + @Mock + private VdsDAO vdsDao; @Mock private GlusterVolumeDao volumeDao; @@ -61,65 +68,115 @@ @ClassRule public static MockConfigRule mcr = new MockConfigRule( mockConfig(ConfigValues.GlusterGeoReplicationEnabled, Version.v3_5.toString(), true), - mockConfig(ConfigValues.GlusterGeoReplicationEnabled, Version.v3_4.toString(), false) + mockConfig(ConfigValues.GlusterGeoReplicationEnabled, Version.v3_4.toString(), false), + mockConfig(ConfigValues.DefaultMinThreadPoolSize, 10), + mockConfig(ConfigValues.DefaultMaxThreadPoolSize, 20), + mockConfig(ConfigValues.DefaultMaxThreadWaitQueueSize, 10) ); @Before public void init() { syncJob = Mockito.spy(GlusterGeoRepSyncJob.getInstance()); MockitoAnnotations.initMocks(this); + syncJob.setLogUtil(logUtil); doReturn(clusterDao).when(syncJob).getClusterDao(); + doReturn(vdsDao).when(syncJob).getVdsDao(); doReturn(geoRepDao).when(syncJob).getGeoRepDao(); doReturn(volumeDao).when(syncJob).getVolumeDao(); doReturn(clusterUtils).when(syncJob).getClusterUtils(); - syncJob.setLogUtil(logUtil); doReturn(getClusters()).when(clusterDao).getAll(); doReturn(getVolume()).when(volumeDao).getByName(any(Guid.class), any(String.class)); + doReturn(getVolume()).when(volumeDao).getById(any(Guid.class)); doReturn(getServer()).when(clusterUtils).getRandomUpServer(any(Guid.class)); + doReturn(getMockLock()).when(syncJob).acquireGeoRepSessionLock(any(Guid.class)); + doReturn(getSessions(2, true)).when(geoRepDao).getGeoRepSessionsInCluster(CLUSTER_GUIDS[1]); } @Test - public void testSync() { + public void testDiscoverGeoRepData() { doReturn(getSessionsVDSReturnVal(true, 2)).when(syncJob) .runVdsCommand(eq(VDSCommandType.GetGlusterVolumeGeoRepStatus), any(GlusterVolumeGeoRepSessionVDSParameters.class)); - syncJob.refreshGeoRepData(); + syncJob.discoverGeoRepData(); Mockito.verify(geoRepDao, times(2)).save(any(GlusterGeoRepSession.class)); } @Test - public void testSyncWhenNoSessions() { + public void testDiscoverGeoRepDataWhenNoSessions() { doReturn(getSessionsVDSReturnVal(true, 0)).when(syncJob) .runVdsCommand(eq(VDSCommandType.GetGlusterVolumeGeoRepStatus), any(GlusterVolumeGeoRepSessionVDSParameters.class)); - syncJob.refreshGeoRepData(); + syncJob.discoverGeoRepData(); Mockito.verify(geoRepDao, times(0)).save(any(GlusterGeoRepSession.class)); + } + + @Test + public void testRefreshStatus() { + doReturn(getSessionDetailsVDSReturnVal(true)).when(syncJob) + .runVdsCommand(eq(VDSCommandType.GetGlusterVolumeGeoRepStatusDetail), + any(GlusterVolumeGeoRepSessionVDSParameters.class)); + syncJob.refreshGeoRepSessionStatus(); + Mockito.verify(geoRepDao, times(2)).saveOrUpdateDetailsInBatch(any(List.class)); + } + + @Test + public void testRefreshStatusNoSessions() { + doReturn(getSessionDetailsVDSReturnVal(false)).when(syncJob) + .runVdsCommand(eq(VDSCommandType.GetGlusterVolumeGeoRepStatusDetail), + any(GlusterVolumeGeoRepSessionVDSParameters.class)); + syncJob.refreshGeoRepSessionStatus(); + Mockito.verify(geoRepDao, times(0)).saveOrUpdateDetailsInBatch(any(List.class)); + } + + private EngineLock getMockLock() { + return new EngineLock() { + + @Override + public void close() { + + } + + }; } private Object getSessionsVDSReturnVal(boolean ret, int count) { VDSReturnValue vdsRetValue = new VDSReturnValue(); vdsRetValue.setSucceeded(ret); if (ret) { - vdsRetValue.setReturnValue(getSessions(count)); + vdsRetValue.setReturnValue(getSessions(count, false)); } else { vdsRetValue.setReturnValue(null); } return vdsRetValue; } - private List<GlusterGeoRepSession> getSessions(int count) { + private Object getSessionDetailsVDSReturnVal(boolean ret) { + VDSReturnValue vdsRetValue = new VDSReturnValue(); + vdsRetValue.setSucceeded(ret); + if (ret) { + vdsRetValue.setReturnValue(getSessionDetailsList()); + } else { + vdsRetValue.setReturnValue(null); + } + return vdsRetValue; + } + + private List<GlusterGeoRepSession> getSessions(int count, boolean populateVoId) { List<GlusterGeoRepSession> sessions = new ArrayList<GlusterGeoRepSession>(); for (int i = 0; i < count; i++) { - sessions.add(getSession()); + sessions.add(getSession(populateVoId)); } return sessions; } - private GlusterGeoRepSession getSession() { + private GlusterGeoRepSession getSession(boolean populateVoId) { GlusterGeoRepSession session = new GlusterGeoRepSession(); session.setMasterVolumeName("VOL1"); + if (populateVoId) { + session.setMasterVolumeId(Guid.newGuid()); + } session.setId(Guid.newGuid()); session.setSessionKey(session.getId() + session.getMasterVolumeName()); session.setStatus(GeoRepSessionStatus.ACTIVE); @@ -137,14 +194,14 @@ private List<VDSGroup> getClusters() { List<VDSGroup> list = new ArrayList<>(); - list.add(createCluster(Version.v3_4)); - list.add(createCluster(Version.v3_5)); + list.add(createCluster(0, Version.v3_4)); + list.add(createCluster(1, Version.v3_5)); return list; } - private VDSGroup createCluster(Version v) { + private VDSGroup createCluster(int index, Version v) { VDSGroup cluster = new VDSGroup(); - cluster.setId(Guid.newGuid()); + cluster.setId(CLUSTER_GUIDS[index]); cluster.setName("cluster"); cluster.setGlusterService(true); cluster.setVirtService(false); diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java index 4c97df3..27cef6c 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java @@ -1463,7 +1463,11 @@ @TypeConverterAttribute(Integer.class) @DefaultValueAttribute("3600") - GlusterRefreshRateGeoRepDiscovery, + GlusterRefreshRateGeoRepDiscoveryInSecs, + + @TypeConverterAttribute(Integer.class) + @DefaultValueAttribute("300") + GlusterRefreshRateGeoRepStatusInSecs, @TypeConverterAttribute(String.class) @DefaultValueAttribute("AttestationService/resources/PollHosts") diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllErrors.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllErrors.java index bd1fbe4..4b97678 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllErrors.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllErrors.java @@ -403,6 +403,7 @@ GlusterVolumeGeoRepStopFailedException(4596), GlusterVolumeGeoRepStatusFailed(4599), GlusterVolumeGeoRepStatusDetailFailed(4600), + GlusterVolumeGeoRepSyncFailed(4601), UnicodeArgumentException(4900), diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterGeoRepDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterGeoRepDaoDbFacadeImpl.java index b838f96..245c593 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterGeoRepDaoDbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterGeoRepDaoDbFacadeImpl.java @@ -39,6 +39,7 @@ GlusterGeoRepSession entity = new GlusterGeoRepSession(); entity.setId(getGuidDefaultEmpty(rs, "session_id")); entity.setMasterVolumeId(getGuidDefaultEmpty(rs, "master_volume_id")); + entity.setMasterVolumeName(rs.getString("master_volume_name")); entity.setSessionKey(rs.getString("session_key")); entity.setSlaveHostName(rs.getString("slave_host_name")); entity.setSlaveNodeUuid(getGuid(rs, "slave_host_uuid")); @@ -189,6 +190,14 @@ @Override public void updateSession(GlusterGeoRepSession geoRepSession) { + getCallsHandler().executeModification("UpdateGlusterGeoRepSession", + createIdParameterMapper(geoRepSession.getId()) + .addValue("status", EnumUtils.nameOrNull(geoRepSession.getStatus())) + .addValue("slave_host_uuid", geoRepSession.getSlaveNodeUuid()) + .addValue("slave_volume_id", geoRepSession.getSlaveVolumeId())); + } + + public void updateSessionStatus(GlusterGeoRepSession geoRepSession) { getCallsHandler().executeModification("UpdateGlusterGeoRepSessionStatus", createIdParameterMapper(geoRepSession.getId()) .addValue("status", EnumUtils.nameOrNull(geoRepSession.getStatus()))); diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeGeoRepStatusDetailVDSCommand.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeGeoRepStatusDetailVDSCommand.java index a770d6a..5357ba7 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeGeoRepStatusDetailVDSCommand.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeGeoRepStatusDetailVDSCommand.java @@ -21,7 +21,7 @@ result = getBroker().glusterVolumeGeoRepStatusDetail(parameter.getVolumeName(), parameter.getSlaveHost(), parameter.getSlaveVolume()); proceedProxyReturnValue(); if (getVDSReturnValue().getSucceeded()) { - setReturnValue(result.getGeoRepSessions()); + setReturnValue(result.getGeoRepDetails()); } } diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusDetailForXmlRpc.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusDetailForXmlRpc.java index 757937a..77cbf88 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusDetailForXmlRpc.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusDetailForXmlRpc.java @@ -18,8 +18,8 @@ private final ArrayList<GlusterGeoRepSessionDetails> geoRepDetails = new ArrayList<GlusterGeoRepSessionDetails>(); private final List<GlusterGeoRepSession> geoRepSessions = new ArrayList<GlusterGeoRepSession>(); - private GlusterGeoRepSessionDetails populatePairDetails(Map<String, Object> innerMap, GlusterGeoRepSession session) { - GlusterGeoRepSessionDetails details = getSessionDetails(innerMap, session); + private GlusterGeoRepSessionDetails populatePairDetails(Map<String, Object> innerMap) { + GlusterGeoRepSessionDetails details = getSessionDetails(innerMap); if (details != null) { Long filesSynced = innerMap.containsKey(FILES_SYNCED) ? Long.parseLong(innerMap.get(FILES_SYNCED).toString()) : null; @@ -49,7 +49,7 @@ if (innerMap.containsKey(GEO_REP_PAIRS)) { for (Object sessionPair : (Object[]) innerMap.get(GEO_REP_PAIRS)) { - geoRepDetails.add(populatePairDetails((Map<String, Object>) sessionPair, session)); + geoRepDetails.add(populatePairDetails((Map<String, Object>) sessionPair)); } } session.setSessionDetails(geoRepDetails); @@ -58,7 +58,7 @@ } public GlusterVolumeGeoRepStatusDetailForXmlRpc(Map<String, Object> innerMap) { - super(innerMap); + super(innerMap, false); if (innerMap.containsKey(GEO_REP)) { populateSessionDetails((Map<String, Object>) innerMap.get(GEO_REP)); } @@ -72,5 +72,4 @@ public List<GlusterGeoRepSession> getGeoRepSessions() { return geoRepSessions; } - } diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusForXmlRpc.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusForXmlRpc.java index 5bc5a70..0c659b4 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusForXmlRpc.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeGeoRepStatusForXmlRpc.java @@ -31,9 +31,9 @@ private final List<GlusterGeoRepSession> geoRepSessions = new ArrayList<GlusterGeoRepSession>(); - private static final Log log = LogFactory.getLog(GlusterVolumesListReturnForXmlRpc.class); + private static final Log log = LogFactory.getLog(GlusterVolumeGeoRepStatusForXmlRpc.class); - protected GlusterGeoRepSessionDetails getSessionDetails(Map<String, Object> innerMap, GlusterGeoRepSession session) { + protected GlusterGeoRepSessionDetails getSessionDetails(Map<String, Object> innerMap) { GlusterGeoRepSessionDetails details = new GlusterGeoRepSessionDetails(); Guid masterNodeGlusterId; if (innerMap.containsKey(MASTER_NODE_UUID)) { @@ -107,7 +107,7 @@ ArrayList<GlusterGeoRepSessionDetails> geoRepSessionDetails = new ArrayList<GlusterGeoRepSessionDetails>(); if (innerMap.containsKey(GEO_REP_PAIRS)) { for (Object sessionPair : (Object[]) innerMap.get(GEO_REP_PAIRS)) { - geoRepSessionDetails.add(getSessionDetails((Map<String, Object>) sessionPair, geoRepSession)); + geoRepSessionDetails.add(getSessionDetails((Map<String, Object>) sessionPair)); } } geoRepSession.setSessionDetails(geoRepSessionDetails); @@ -115,8 +115,12 @@ } public GlusterVolumeGeoRepStatusForXmlRpc(Map<String, Object> innerMap) { + this(innerMap, true); + } + + public GlusterVolumeGeoRepStatusForXmlRpc(Map<String, Object> innerMap, boolean includeSessions) { super(innerMap); - if (innerMap.containsKey(GEO_REP)) { + if (includeSessions && innerMap.containsKey(GEO_REP)) { populateSessions((Object[]) innerMap.get(GEO_REP)); } } diff --git a/packaging/dbscripts/create_views.sql b/packaging/dbscripts/create_views.sql index a96c845..2b68ebc 100644 --- a/packaging/dbscripts/create_views.sql +++ b/packaging/dbscripts/create_views.sql @@ -1773,6 +1773,16 @@ FROM gluster_server_hooks INNER JOIN vds_static ON gluster_server_hooks.server_id = vds_static.vds_id; +CREATE OR REPLACE VIEW gluster_georep_sessions_view +AS +SELECT session_id, master_volume_id, session_key, slave_host_uuid, + slave_host_name, slave_volume_id, slave_volume_name, georep.status, + georep._create_date, georep._update_date, + gluster_volumes.vol_name AS master_volume_name, + gluster_volumes.cluster_id AS cluster_id +FROM gluster_georep_session georep +INNER JOIN gluster_volumes ON gluster_volumes.id = georep.master_volume_id; + -- Affinity Groups view, including members CREATE OR REPLACE VIEW affinity_groups_view AS diff --git a/packaging/dbscripts/gluster_georep_sp.sql b/packaging/dbscripts/gluster_georep_sp.sql index a3b921c..72e2713 100644 --- a/packaging/dbscripts/gluster_georep_sp.sql +++ b/packaging/dbscripts/gluster_georep_sp.sql @@ -105,50 +105,42 @@ Create or replace FUNCTION GetGlusterGeoRepSessionById(v_session_id UUID) -RETURNS SETOF gluster_georep_session STABLE +RETURNS SETOF gluster_georep_sessions_view STABLE AS $procedure$ BEGIN - RETURN QUERY SELECT session_id, master_volume_id, session_key, slave_host_uuid, - slave_host_name, slave_volume_id, slave_volume_name, status, - _create_date, _update_date - FROM gluster_georep_session + RETURN QUERY SELECT * + FROM gluster_georep_sessions_view WHERE session_id = v_session_id; END; $procedure$ LANGUAGE plpgsql; Create or replace FUNCTION GetGlusterGeoRepSessionsByVolumeId(v_master_volume_id UUID) -RETURNS SETOF gluster_georep_session STABLE +RETURNS SETOF gluster_georep_sessions_view STABLE AS $procedure$ BEGIN - RETURN QUERY SELECT session_id, master_volume_id, session_key, slave_host_uuid, - slave_host_name, slave_volume_id, slave_volume_name, status, - _create_date, _update_date - FROM gluster_georep_session + RETURN QUERY SELECT * + FROM gluster_georep_sessions_view WHERE master_volume_id = v_master_volume_id order by slave_volume_name asc; END; $procedure$ LANGUAGE plpgsql; Create or replace FUNCTION GetGlusterGeoRepSessionsByClusterId(v_cluster_id UUID) -RETURNS SETOF gluster_georep_session STABLE +RETURNS SETOF gluster_georep_sessions_view STABLE AS $procedure$ BEGIN - RETURN QUERY SELECT session_id, master_volume_id, session_key, slave_host_uuid, - slave_host_name, slave_volume_id, slave_volume_name, georep.status, - georep._create_date, georep._update_date - FROM gluster_georep_session georep JOIN gluster_volumes ON master_volume_id = id + RETURN QUERY SELECT * + FROM gluster_georep_sessions_view WHERE cluster_id = v_cluster_id order by slave_volume_name asc; END; $procedure$ LANGUAGE plpgsql; Create or replace FUNCTION GetGlusterGeoRepSessionByKey(v_session_key VARCHAR(150)) -RETURNS SETOF gluster_georep_session STABLE +RETURNS SETOF gluster_georep_sessions_view STABLE AS $procedure$ BEGIN - RETURN QUERY SELECT session_id, master_volume_id, session_key, slave_host_uuid, - slave_host_name, slave_volume_id, slave_volume_name, status, - _create_date, _update_date - FROM gluster_georep_session + RETURN QUERY SELECT * + FROM gluster_georep_sessions_view WHERE session_key = v_session_key; END; $procedure$ LANGUAGE plpgsql; @@ -165,6 +157,22 @@ END; $procedure$ LANGUAGE plpgsql; +Create or replace FUNCTION UpdateGlusterGeoRepSession(v_session_id UUID, + v_status VARCHAR(50), + v_slave_host_uuid UUID, + v_slave_volume_id UUID) +RETURNS VOID +AS $procedure$ +BEGIN + UPDATE gluster_georep_session + SET status = v_status, + slave_host_uuid = v_slave_host_uuid, + slave_volume_id = v_slave_volume_id, + _update_date = LOCALTIMESTAMP + WHERE session_id = v_session_id; +END; $procedure$ +LANGUAGE plpgsql; + Create or replace FUNCTION GetGlusterGeoRepSessionDetails(v_session_id UUID) RETURNS SETOF gluster_georep_session_details STABLE AS $procedure$ diff --git a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql index 3150905..1907c10 100644 --- a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql +++ b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql @@ -198,8 +198,9 @@ select fn_db_add_config_value('GlusterGeoReplicationEnabled', 'false', '3.3'); select fn_db_add_config_value('GlusterGeoReplicationEnabled', 'false', '3.4'); select fn_db_add_config_value('GlusterGeoReplicationEnabled', 'false', '3.5'); -select fn_db_add_config_value('GlusterRefreshRateGeoRepStatus', '300', 'general'); -select fn_db_add_config_value('GlusterRefreshRateGeoRepDiscovery', '3600', 'general'); +select fn_db_add_config_value('GlusterRefreshRateGeoRepDiscoveryInSecs', '3600', 'general'); +select fn_db_add_config_value('GlusterRefreshRateGeoRepStatusInSecs', '300', 'general'); + -- OpenStack related select fn_db_add_config_value('KeystoneAuthUrl', '', 'general'); @@ -1077,6 +1078,8 @@ select fn_db_delete_config_value('ENMailUseDefaultCredentials','general'); select fn_db_delete_config_value('ENMailUser','general'); select fn_db_delete_config_value('FreeSpaceCriticalLow','general'); +select fn_db_delete_config_value('GlusterRefreshRateGeoRepStatus', 'general'); +select fn_db_delete_config_value('GlusterRefreshRateGeoRepDiscovery', 'general'); select fn_db_delete_config_value('HotPlugUnsupportedOsList','general'); select fn_db_delete_config_value('HotPlugSupportedOsList','general'); select fn_db_delete_config_value('ImagesSyncronizationTimeout','general'); diff --git a/packaging/etc/engine-config/engine-config.properties b/packaging/etc/engine-config/engine-config.properties index c9d5455..7f67e61 100644 --- a/packaging/etc/engine-config/engine-config.properties +++ b/packaging/etc/engine-config/engine-config.properties @@ -448,7 +448,7 @@ UnsupportedLocalesFilterOverrides.type=String DefaultMTU.description="Default MTU value" DefaultMTU.type=Mtu -GlusterRefreshRateGeoRepStatus.description=Refresh rate (in seconds) of the geo-replication session status and statistics -GlusterRefreshRateGeoRepStatus.type=Integer -GlusterRefreshRateGeoRepDiscovery.description=Refresh rate (in seconds) for discovery of geo-replication sessions -GlusterRefreshRateGeoRepDiscovery.type=Integer +GlusterRefreshRateGeoRepStatusInSecs.description=Refresh rate (in seconds) of the geo-replication session status and statistics +GlusterRefreshRateGeoRepStatusInSecs.type=Integer +GlusterRefreshRateGeoRepDiscoveryInSecs.description=Refresh rate (in seconds) for discovery of geo-replication sessions +GlusterRefreshRateGeoRepDiscoveryInSecs.type=Integer -- To view, visit https://gerrit.ovirt.org/39583 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I67e857ab2ce993cded966fb60b361f6962b9a665 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5-gluster Gerrit-Owner: Sahina Bose <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
