Shubhendu Tripathi has uploaded a new change for review.

Change subject: gluster: Sync job for gluster volume snapshots
......................................................................

gluster: Sync job for gluster volume snapshots

Sync job for gluster volume snapshots

Change-Id: I7b7bf79b72fc5680dab301b290e7aa860d5c714d
Signed-off-by: Shubhendu Tripathi <[email protected]>
---
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
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJob.java
A 
backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJobTest.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotConfigInfo.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotStatus.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllErrors.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/gluster/GlusterVolumeSnapshotVDSParameters.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterVolumeSnapshotDaoDbFacadeImpl.java
M backend/manager/modules/dal/src/main/resources/bundles/VdsmErrors.properties
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/AbstractGlusterBrokerCommand.java
A 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotConfigInfoVDSCommand.java
A 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotInfoVDSCommand.java
A 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotConfigReturnForXmlRpc.java
A 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotInfoReturnForXmlRpc.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerConnector.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java
M 
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/VdsmErrors.java
M 
frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/VdsmErrors.properties
M packaging/dbscripts/gluster_volume_snapshot_sp.sql
26 files changed, 1,070 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/80/39280/1

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 56242e2..b92ad3b 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
@@ -161,6 +161,14 @@
                 LockMessagesMatchUtil.makeLockingPair(LockingGroup.GLUSTER, 
VdcBllMessages.ACTION_TYPE_FAILED_GLUSTER_OPERATION_INPROGRESS)), null);
     }
 
+    protected EngineLock acquireVolumeSnapshotLock(Guid id) {
+        EngineLock lock = new 
EngineLock(Collections.singletonMap(id.toString(),
+                
LockMessagesMatchUtil.makeLockingPair(LockingGroup.GLUSTER_SNAPSHOT,
+                        
VdcBllMessages.ACTION_TYPE_FAILED_VOLUME_SNAPSHOT_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 c0f6a27..d97d92c 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
@@ -64,6 +64,14 @@
                 getRefreshRate(ConfigValues.GlusterRefreshRateTasks),
                 TimeUnit.SECONDS);
 
+        scheduler.scheduleAFixedDelayJob(GlusterSnapshotSyncJob.getInstance(),
+                "gluster_snapshot_poll_event",
+                new Class[0],
+                new Class[0],
+                
getRefreshRate(ConfigValues.GlusterRefreshRateSnapshotDiscovery),
+                
getRefreshRate(ConfigValues.GlusterRefreshRateSnapshotDiscovery),
+                TimeUnit.SECONDS);
+
     }
 
     private static boolean glusterModeSupported() {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJob.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJob.java
new file mode 100644
index 0000000..5b3c590b
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJob.java
@@ -0,0 +1,269 @@
+package org.ovirt.engine.core.bll.gluster;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.ovirt.engine.core.common.businessentities.VDS;
+import org.ovirt.engine.core.common.businessentities.VDSGroup;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterSnapshotConfigInfo;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotConfig;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+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.GlusterVolumeSnapshotVDSParameters;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.dao.gluster.GlusterVolumeDao;
+import org.ovirt.engine.core.dao.gluster.GlusterVolumeSnapshotConfigDao;
+import org.ovirt.engine.core.dao.gluster.GlusterVolumeSnapshotDao;
+import org.ovirt.engine.core.utils.lock.EngineLock;
+import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GlusterSnapshotSyncJob extends GlusterJob {
+    private static final Logger log = 
LoggerFactory.getLogger(GlusterSnapshotSyncJob.class);
+    private static final GlusterSnapshotSyncJob instance = new 
GlusterSnapshotSyncJob();
+
+    public void init() {
+        log.info("Gluster snapshot monitoring has been initialized");
+    }
+
+    public static GlusterSnapshotSyncJob getInstance() {
+        return instance;
+    }
+
+    @OnTimerMethodAnnotation("gluster_snapshot_poll_event")
+    public void refreshSnapshotData() {
+        refreshSnapshotList();
+        refreshSnapshotConfig();
+    }
+
+    public void refreshSnapshotList() {
+        // get all clusters
+        List<VDSGroup> clusters = getClusterDao().getAll();
+
+        for (VDSGroup cluster : clusters) {
+            refreshSnapshotsInCluster(cluster);
+        }
+    }
+
+    public void refreshSnapshotConfig() {
+        // get all clusters
+        List<VDSGroup> clusters = getClusterDao().getAll();
+
+        for (VDSGroup cluster : clusters) {
+            refreshSnapshotConfigInCluster(cluster);
+        }
+    }
+
+    private void refreshSnapshotsInCluster(VDSGroup cluster) {
+        if (!supportsGlusterSnapshotFeature(cluster)) {
+            return;
+        }
+
+        final VDS upServer = 
getClusterUtils().getRandomUpServer(cluster.getId());
+        if (upServer == null) {
+            log.info("No UP server found in cluster '{}' for snapshot 
monitoring", cluster.getName());
+            return;
+        }
+
+        VDSReturnValue returnValue = 
runVdsCommand(VDSCommandType.GetGlusterVolumeSnapshotInfo,
+                new GlusterVolumeSnapshotVDSParameters(upServer.getId(), 
cluster.getId(), null));
+        if (returnValue.getSucceeded()) {
+            addOrUpdateSnapshots(cluster.getId(), 
(ArrayList<GlusterVolumeSnapshotEntity>) returnValue.getReturnValue());
+        } else {
+            log.error("VDS Error {}", returnValue.getVdsError().getMessage());
+            log.debug("VDS Error {}", returnValue.getVdsError());
+        }
+    }
+
+    private void refreshSnapshotConfigInCluster(VDSGroup cluster) {
+        if (!supportsGlusterSnapshotFeature(cluster)) {
+            return;
+        }
+
+        final VDS upServer = 
getClusterUtils().getRandomUpServer(cluster.getId());
+        if (upServer == null) {
+            log.info("No UP server found in cluster '{}' for snapshot 
configurations monitoring", cluster.getName());
+            return;
+        }
+
+        VDSReturnValue returnValue =
+                
runVdsCommand(VDSCommandType.GetGlusterVolumeSnapshotConfigInfo,
+                        new 
GlusterVolumeSnapshotVDSParameters(upServer.getId(), cluster.getId(), null));
+        if (returnValue.getSucceeded()) {
+            addOrUpdateSnapshotsConfig(cluster.getId(), 
(GlusterSnapshotConfigInfo) returnValue.getReturnValue());
+        } else {
+            log.error("VDS Error {}", returnValue.getVdsError().getMessage());
+            log.debug("VDS Error {}", returnValue.getVdsError());
+        }
+    }
+
+    private void addOrUpdateSnapshots(Guid clusterId, 
List<GlusterVolumeSnapshotEntity> fetchedSnapshots) {
+        Map<Guid, GlusterVolumeSnapshotEntity> fetchedSnapshotsMap = new 
HashMap<>();
+        for (GlusterVolumeSnapshotEntity fetchedSnapshot : fetchedSnapshots) {
+            fetchedSnapshotsMap.put(fetchedSnapshot.getId(), fetchedSnapshot);
+        }
+
+        List<GlusterVolumeSnapshotEntity> existingSnapshots =
+                getGlusterVolumeSnapshotDao().getAllByClusterId(clusterId);
+        Map<Guid, GlusterVolumeSnapshotEntity> existingSnapshotsMap = new 
HashMap<>();
+        for (GlusterVolumeSnapshotEntity existingSnapshot : existingSnapshots) 
{
+            existingSnapshotsMap.put(existingSnapshot.getId(), 
existingSnapshot);
+        }
+
+        List<GlusterVolumeSnapshotEntity> updatedSnapshots = new ArrayList<>();
+        List<GlusterVolumeSnapshotEntity> newlyAddedSnapshots = new 
ArrayList<>();
+        List<GlusterVolumeSnapshotEntity> deletedSnapshots = new ArrayList<>();
+
+        for (GlusterVolumeSnapshotEntity fetchedSnapshot : fetchedSnapshots) {
+            GlusterVolumeSnapshotEntity correspondingExistingSnapshot =
+                    existingSnapshotsMap.get(fetchedSnapshot.getId());
+            if (correspondingExistingSnapshot == null) {
+                newlyAddedSnapshots.add(fetchedSnapshot);
+            } else if (correspondingExistingSnapshot.getStatus() != 
fetchedSnapshot.getStatus()) {
+                
correspondingExistingSnapshot.setStatus(fetchedSnapshot.getStatus());
+                updatedSnapshots.add(correspondingExistingSnapshot);
+            }
+        }
+
+        for (GlusterVolumeSnapshotEntity existingSnapshot : existingSnapshots) 
{
+            GlusterVolumeSnapshotEntity correspondingFetchedSnapshot =
+                    fetchedSnapshotsMap.get(existingSnapshot.getId());
+            if (correspondingFetchedSnapshot == null) {
+                deletedSnapshots.add(existingSnapshot);
+            }
+        }
+
+        // update snapshot details
+        try (EngineLock lock = acquireVolumeSnapshotLock(clusterId)) {
+            saveNewSnapshots(newlyAddedSnapshots);
+            updateSnapshots(updatedSnapshots);
+            deleteSnapshots(deletedSnapshots);
+        } catch (Exception e) {
+            log.error("Exception ocuured while adding/updating snapshots from 
CLI - '{}'", e.getMessage());
+            log.debug("Exception", e);
+            throw new 
VdcBLLException(VdcBllErrors.GlusterSnapshotInfoFailedException, 
e.getLocalizedMessage());
+        }
+    }
+
+    private void addOrUpdateSnapshotsConfig(Guid clusterId, 
GlusterSnapshotConfigInfo configInfo) {
+        try (EngineLock lock = acquireVolumeSnapshotLock(clusterId)) {
+            for (Map.Entry<String, String> entry : 
configInfo.getClusterConfigOptions().entrySet()) {
+                if (entry.getValue() != null) {
+                    addOrUpdateClusterConfig(clusterId, entry.getKey(), 
entry.getValue());
+                }
+            }
+        } catch (Exception e) {
+            log.error("Exception ocuured while adding/updating snapshots 
configurations from CLI - '{}'",
+                    e.getMessage());
+            log.debug("Exception", e);
+            throw new 
VdcBLLException(VdcBllErrors.GlusterSnapshotInfoFailedException, 
e.getLocalizedMessage());
+        }
+
+        Map<String, Map<String, String>> volumeConfigs = 
configInfo.getVolumeConfigOptions();
+        for (Map.Entry<String, Map<String, String>> entry : 
volumeConfigs.entrySet()) {
+            GlusterVolumeEntity volume = 
getGlusterVolumeDao().getByName(clusterId, entry.getKey());
+            if (volume == null) {
+                continue;
+            }
+
+            try (EngineLock lock = acquireVolumeSnapshotLock(volume.getId())) {
+                Map<String, String> volumeConfig = entry.getValue();
+                if (volumeConfig != null) {
+                    for (Map.Entry<String, String> entry1 : 
volumeConfig.entrySet()) {
+                        if (entry.getValue() != null) {
+                            addOrUpdateVolumeConfig(clusterId,
+                                    volume.getId(),
+                                    entry1.getKey(),
+                                    entry1.getValue());
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                log.error("Exception ocuured while adding/updating snapshots 
configurations from CLI - '{}'",
+                        e.getMessage());
+                log.debug("Exception", e);
+                throw new 
VdcBLLException(VdcBllErrors.GlusterSnapshotInfoFailedException, 
e.getLocalizedMessage());
+            }
+        }
+    }
+
+    private void addOrUpdateClusterConfig(Guid clusterId, String paramName, 
String paramValue) {
+        GlusterVolumeSnapshotConfig param = new GlusterVolumeSnapshotConfig();
+        param.setClusterId(clusterId);
+        param.setVolumeId(null);
+        param.setParamName(paramName);
+        param.setParamValue(paramValue);
+        GlusterVolumeSnapshotConfig existingParamDetail =
+                
getGlusterVolumeSnapshotConfigDao().getConfigByClusterIdAndName(clusterId,
+                        paramName);
+        if (existingParamDetail == null) {
+            getGlusterVolumeSnapshotConfigDao().save(param);
+        } else if (!(existingParamDetail.getParamValue().equals(paramValue))) {
+            
getGlusterVolumeSnapshotConfigDao().updateConfigByClusterIdAndName(clusterId,
+                    paramName,
+                    paramValue);
+        }
+    }
+
+    private void addOrUpdateVolumeConfig(Guid clusterId, Guid volumeId, String 
paramName, String paramValue) {
+        GlusterVolumeSnapshotConfig cfg = new GlusterVolumeSnapshotConfig();
+        cfg.setClusterId(clusterId);
+        cfg.setVolumeId(volumeId);
+        cfg.setParamName(paramName);
+        cfg.setParamValue(paramValue);
+        GlusterVolumeSnapshotConfig existingParamDetail =
+                
getGlusterVolumeSnapshotConfigDao().getConfigByVolumeIdAndName(clusterId,
+                        volumeId,
+                        paramName);
+        if (existingParamDetail == null) {
+            getGlusterVolumeSnapshotConfigDao().save(cfg);
+        } else if (!(existingParamDetail.getParamValue().equals(paramValue))) {
+            
getGlusterVolumeSnapshotConfigDao().updateConfigByVolumeIdAndName(clusterId,
+                    volumeId,
+                    paramName,
+                    paramValue);
+        }
+    }
+
+    private void saveNewSnapshots(List<GlusterVolumeSnapshotEntity> snapshots) 
{
+        getGlusterVolumeSnapshotDao().saveAll(snapshots);
+    }
+
+    private void updateSnapshots(List<GlusterVolumeSnapshotEntity> snapshots) {
+        getGlusterVolumeSnapshotDao().updateAllInBatch(snapshots);
+    }
+
+    private void deleteSnapshots(List<GlusterVolumeSnapshotEntity> snaphosts) {
+        List<Guid> deletedIds = new ArrayList<>();
+        for (GlusterVolumeSnapshotEntity snapshot : snaphosts) {
+            deletedIds.add(snapshot.getId());
+        }
+        getGlusterVolumeSnapshotDao().removeAll(deletedIds);
+    }
+
+    private boolean supportsGlusterSnapshotFeature(VDSGroup cluster) {
+        return cluster.supportsGlusterService()
+                && 
GlusterFeatureSupported.glusterSnapshot(cluster.getcompatibility_version());
+    }
+
+    protected GlusterVolumeDao getGlusterVolumeDao() {
+        return DbFacade.getInstance().getGlusterVolumeDao();
+    }
+
+    protected GlusterVolumeSnapshotDao getGlusterVolumeSnapshotDao() {
+        return DbFacade.getInstance().getGlusterVolumeSnapshotDao();
+    }
+
+    protected GlusterVolumeSnapshotConfigDao 
getGlusterVolumeSnapshotConfigDao() {
+        return DbFacade.getInstance().getGlusterVolumeSnapshotConfigDao();
+    }
+}
diff --git 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJobTest.java
 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJobTest.java
new file mode 100644
index 0000000..bcefc69
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/GlusterSnapshotSyncJobTest.java
@@ -0,0 +1,383 @@
+package org.ovirt.engine.core.bll.gluster;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.ovirt.engine.core.utils.MockConfigRule.mockConfig;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.ovirt.engine.core.bll.utils.ClusterUtils;
+import org.ovirt.engine.core.bll.utils.GlusterUtil;
+import org.ovirt.engine.core.common.businessentities.VDS;
+import org.ovirt.engine.core.common.businessentities.VDSGroup;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterSnapshotConfigInfo;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterSnapshotStatus;
+import org.ovirt.engine.core.common.businessentities.gluster.GlusterStatus;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotConfig;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+import org.ovirt.engine.core.common.config.ConfigValues;
+import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
+import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
+import 
org.ovirt.engine.core.common.vdscommands.gluster.GlusterVolumeSnapshotVDSParameters;
+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.VdsGroupDAO;
+import org.ovirt.engine.core.dao.gluster.GlusterVolumeDao;
+import org.ovirt.engine.core.dao.gluster.GlusterVolumeSnapshotConfigDao;
+import org.ovirt.engine.core.dao.gluster.GlusterVolumeSnapshotDao;
+import org.ovirt.engine.core.utils.MockConfigRule;
+import org.ovirt.engine.core.utils.lock.EngineLock;
+
+@RunWith(MockitoJUnitRunner.class)
+public class GlusterSnapshotSyncJobTest {
+    private static final Guid CLUSTER_ID_1 = Guid.newGuid();
+    private static final Guid CLUSTER_ID_2 = Guid.newGuid();
+    private static final Guid VOLUME_ID_1 = Guid.newGuid();
+    private static final String VOLUME_NAME_1 = "VOL1";
+    private static final Guid VOLUME_ID_2 = Guid.newGuid();
+    private static final String VOLUME_NAME_2 = "VOL2";
+    private static final Guid[] existingSnapshotIds = { Guid.newGuid(), 
Guid.newGuid() };
+    private static final String[] existingSnapshotNames = { "snap-1", "snap-2" 
};
+    private static final Date existingSnapsCreateDate = new Date();
+    private static final Guid newSnapshotId = Guid.newGuid();
+    private static final String newSnapshotName = "new-snap";
+    private static final String PARAM_SNAP_MAX_LIMIT = "snap-max-hard-limit";
+    private static final String PARAM_SNAP_MAX_SOFT_LIMIT = 
"snap-max-soft-limit";
+    private static final String PARAM_AUTO_DELETE = "auto-delete";
+
+    @Mock
+    private GlusterVolumeDao volumeDao;
+
+    @Mock
+    private ClusterUtils clusterUtils;
+
+    @Mock
+    private GlusterVolumeSnapshotDao snapshotDao;
+
+    @Mock
+    private GlusterVolumeSnapshotConfigDao snapshotConfigDao;
+
+    @Mock
+    private VdsGroupDAO clusterDao;
+
+    private GlusterSnapshotSyncJob syncJob;
+
+    @Mock
+    private GlusterAuditLogUtil logUtil;
+
+    @Mock
+    private GlusterUtil glusterUtil;
+
+    @Mock
+    private EngineLock engineLock;
+
+    @ClassRule
+    public static MockConfigRule mcr = new MockConfigRule(
+            mockConfig(ConfigValues.GlusterVolumeSnapshotSupported, 
Version.v3_5.toString(), true),
+            mockConfig(ConfigValues.GlusterVolumeSnapshotSupported, 
Version.v3_4.toString(), false),
+            mockConfig(ConfigValues.DefaultMinThreadPoolSize, 10),
+            mockConfig(ConfigValues.DefaultMaxThreadPoolSize, 20),
+            mockConfig(ConfigValues.DefaultMaxThreadWaitQueueSize, 10)
+            );
+
+    @Before
+    public void init() {
+        syncJob = Mockito.spy(GlusterSnapshotSyncJob.getInstance());
+        MockitoAnnotations.initMocks(this);
+        syncJob.setLogUtil(logUtil);
+
+        doReturn(clusterDao).when(syncJob).getClusterDao();
+        doReturn(volumeDao).when(syncJob).getGlusterVolumeDao();
+        doReturn(snapshotDao).when(syncJob).getGlusterVolumeSnapshotDao();
+        
doReturn(snapshotConfigDao).when(syncJob).getGlusterVolumeSnapshotConfigDao();
+        doReturn(clusterUtils).when(syncJob).getClusterUtils();
+
+        doReturn(getClusters()).when(clusterDao).getAll();
+        
doReturn(getVolumes()).when(volumeDao).getByClusterId(argThat(validClusterId()));
+        doReturn(getVolume(CLUSTER_ID_1, VOLUME_ID_1, 
VOLUME_NAME_1)).when(volumeDao)
+                .getByName(argThat(validClusterId()), 
argThat(validVolumeName()));
+        
doReturn(getServer()).when(clusterUtils).getRandomUpServer(any(Guid.class));
+
+        
doReturn(engineLock).when(syncJob).acquireVolumeSnapshotLock(any(Guid.class));
+    }
+
+    @Test
+    public void testSyncSnapshotsList() {
+        
doReturn(getExistingSnapshots()).when(snapshotDao).getAllByVolumeId(argThat(validVolumeId()));
+        doReturn(getSnapshotVDSReturnVal(true)).when(syncJob)
+                .runVdsCommand(eq(VDSCommandType.GetGlusterVolumeSnapshotInfo),
+                        argThat(snapshotInfoParam()));
+        syncJob.refreshSnapshotList();
+        Mockito.verify(snapshotDao, times(1)).saveAll(any(List.class));
+        Mockito.verify(snapshotDao, times(1)).removeAll(any(List.class));
+        Mockito.verify(snapshotDao, 
times(1)).updateAllInBatch(any(List.class));
+    }
+
+    @Test
+    public void testSyncSnapshotConfigs() {
+        doReturn(getClusterSnapMaxLimit()).when(snapshotConfigDao)
+                .getConfigByClusterIdAndName(CLUSTER_ID_1, 
PARAM_SNAP_MAX_LIMIT);
+        
doReturn(null).when(snapshotConfigDao).getConfigByClusterIdAndName(CLUSTER_ID_1,
+                PARAM_SNAP_MAX_SOFT_LIMIT);
+        
doReturn(null).when(snapshotConfigDao).getConfigByClusterIdAndName(CLUSTER_ID_1,
+                PARAM_AUTO_DELETE);
+        doReturn(getVolume(CLUSTER_ID_1, VOLUME_ID_1, 
VOLUME_NAME_1)).when(volumeDao).getByName(CLUSTER_ID_1,
+                VOLUME_NAME_1);
+        doReturn(getVolume(CLUSTER_ID_1, VOLUME_ID_2, 
VOLUME_NAME_2)).when(volumeDao).getByName(CLUSTER_ID_1,
+                VOLUME_NAME_2);
+        doReturn(getVolumeSnapMaxLimit()).when(snapshotConfigDao)
+                .getConfigByVolumeIdAndName(CLUSTER_ID_1, VOLUME_ID_1, 
PARAM_SNAP_MAX_LIMIT);
+        
doReturn(null).when(snapshotConfigDao).getConfigByVolumeIdAndName(CLUSTER_ID_1,
+                VOLUME_ID_2,
+                PARAM_SNAP_MAX_LIMIT);
+        doReturn(getSnapshotConfigVDSReturnValue()).when(syncJob)
+                
.runVdsCommand(eq(VDSCommandType.GetGlusterVolumeSnapshotConfigInfo),
+                        argThat(snapshotInfoParam()));
+        syncJob.refreshSnapshotConfig();
+        Mockito.verify(snapshotConfigDao, 
times(3)).save(any(GlusterVolumeSnapshotConfig.class));
+        Mockito.verify(snapshotConfigDao, 
times(1)).updateConfigByClusterIdAndName(any(Guid.class),
+                any(String.class),
+                any(String.class));
+        Mockito.verify(snapshotConfigDao, 
times(1)).updateConfigByVolumeIdAndName(any(Guid.class),
+                any(Guid.class),
+                any(String.class),
+                any(String.class));
+    }
+
+    private GlusterVolumeSnapshotConfig getClusterSnapMaxLimit() {
+        GlusterVolumeSnapshotConfig param = new GlusterVolumeSnapshotConfig();
+        param.setClusterId(CLUSTER_ID_1);
+        param.setVolumeId(null);
+        param.setParamName(PARAM_SNAP_MAX_LIMIT);
+        param.setParamValue("256");
+        return param;
+    }
+
+    private GlusterVolumeSnapshotConfig getVolumeSnapMaxLimit() {
+        GlusterVolumeSnapshotConfig param = new GlusterVolumeSnapshotConfig();
+        param.setClusterId(CLUSTER_ID_1);
+        param.setVolumeId(VOLUME_ID_1);
+        param.setParamName(PARAM_SNAP_MAX_LIMIT);
+        param.setParamValue("20");
+        return param;
+    }
+
+    private ArgumentMatcher<GlusterVolumeSnapshotVDSParameters> 
snapshotInfoParam() {
+        return new ArgumentMatcher<GlusterVolumeSnapshotVDSParameters>() {
+
+            @Override
+            public boolean matches(Object argument) {
+                if (!(argument instanceof GlusterVolumeSnapshotVDSParameters)) 
{
+                    return false;
+                }
+                return ((GlusterVolumeSnapshotVDSParameters) 
argument).getClusterId().equals(CLUSTER_ID_1);
+            }
+        };
+    }
+
+    private ArgumentMatcher<Guid> validClusterId() {
+        return new ArgumentMatcher<Guid>() {
+            @Override
+            public boolean matches(Object argument) {
+                if (!(argument instanceof Guid)) {
+                    return false;
+                }
+                return ((Guid) argument).equals(CLUSTER_ID_1);
+            }
+        };
+    }
+
+    private ArgumentMatcher<String> validVolumeName() {
+        return new ArgumentMatcher<String>() {
+            @Override
+            public boolean matches(Object argument) {
+                if (!(argument instanceof String)) {
+                    return false;
+                }
+                return ((String) argument).equals(VOLUME_NAME_1);
+            }
+        };
+    }
+
+    private ArgumentMatcher<Guid> validVolumeId() {
+        return new ArgumentMatcher<Guid>() {
+            @Override
+            public boolean matches(Object argument) {
+                if (!(argument instanceof Guid)) {
+                    return false;
+                }
+                return ((Guid) argument).equals(VOLUME_ID_1);
+            }
+        };
+    }
+
+    private List<GlusterVolumeSnapshotEntity> getExistingSnapshots() {
+        List<GlusterVolumeSnapshotEntity> snapsList = new 
ArrayList<GlusterVolumeSnapshotEntity>();
+
+        GlusterVolumeSnapshotEntity snap1 = new GlusterVolumeSnapshotEntity();
+        snap1.setId(existingSnapshotIds[0]);
+        snap1.setClusterId(CLUSTER_ID_1);
+        snap1.setCreatedAt(existingSnapsCreateDate);
+        snap1.setDescription("");
+        snap1.setSnapshotName(existingSnapshotNames[0]);
+        snap1.setStatus(GlusterSnapshotStatus.STARTED);
+        snap1.setVolumeId(VOLUME_ID_1);
+        snapsList.add(snap1);
+
+        GlusterVolumeSnapshotEntity snap2 = new GlusterVolumeSnapshotEntity();
+        snap2.setId(existingSnapshotIds[1]);
+        snap2.setClusterId(CLUSTER_ID_1);
+        snap2.setCreatedAt(existingSnapsCreateDate);
+        snap2.setDescription("");
+        snap2.setSnapshotName(existingSnapshotNames[1]);
+        snap2.setStatus(GlusterSnapshotStatus.STARTED);
+        snap2.setVolumeId(VOLUME_ID_1);
+        snapsList.add(snap2);
+
+        return snapsList;
+    }
+
+    private Object getSnapshotConfigVDSReturnValue() {
+        VDSReturnValue vdsRetValue = new VDSReturnValue();
+        vdsRetValue.setSucceeded(true);
+        vdsRetValue.setReturnValue(getSnapshotConfigInfo());
+        return vdsRetValue;
+    }
+
+    private GlusterSnapshotConfigInfo getSnapshotConfigInfo() {
+        GlusterSnapshotConfigInfo config = new GlusterSnapshotConfigInfo();
+        Map<String, String> clusterConfigs = new HashMap<String, String>();
+        clusterConfigs.put("snap-max-hard-limit", "200");
+        clusterConfigs.put("snap-max-soft-limit", "90%");
+        clusterConfigs.put("auto-delete", "enable");
+        config.setClusterConfigOptions(clusterConfigs);
+
+        Map<String, Map<String, String>> volumeConfigs = new HashMap<String, 
Map<String, String>>();
+
+        Map<String, String> volConf1 = new HashMap<String, String>();
+        volConf1.put("snap-max-hard-limit", "30");
+        volumeConfigs.put(VOLUME_NAME_1, volConf1);
+
+        Map<String, String> volConf2 = new HashMap<String, String>();
+        volConf2.put("snap-max-hard-limit", "50");
+        volumeConfigs.put(VOLUME_NAME_2, volConf2);
+
+        config.setVolumeConfigOptions(volumeConfigs);
+
+        return config;
+    }
+
+    private Object getSnapshotVDSReturnVal(boolean ret) {
+        VDSReturnValue vdsRetValue = new VDSReturnValue();
+        vdsRetValue.setSucceeded(ret);
+        if (ret) {
+            vdsRetValue.setReturnValue(getSnapshotDetails());
+        } else {
+            vdsRetValue.setReturnValue(null);
+        }
+        return vdsRetValue;
+    }
+
+    private List<GlusterVolumeSnapshotEntity> getSnapshotDetails() {
+        List<GlusterVolumeSnapshotEntity> snapshots = new 
ArrayList<GlusterVolumeSnapshotEntity>();
+
+        GlusterVolumeSnapshotEntity snap1 = new GlusterVolumeSnapshotEntity();
+        snap1.setClusterId(CLUSTER_ID_1);
+        snap1.setCreatedAt(existingSnapsCreateDate);
+        snap1.setDescription("");
+        snap1.setId(existingSnapshotIds[0]);
+        snap1.setSnapshotName(existingSnapshotNames[0]);
+        snap1.setStatus(GlusterSnapshotStatus.STOPPED);
+        snap1.setVolumeId(VOLUME_ID_1);
+        snapshots.add(snap1);
+
+        GlusterVolumeSnapshotEntity snap2 = new GlusterVolumeSnapshotEntity();
+        snap2.setClusterId(CLUSTER_ID_1);
+        snap2.setCreatedAt(new Date());
+        snap2.setDescription("");
+        snap2.setId(newSnapshotId);
+        snap2.setSnapshotName(newSnapshotName);
+        snap2.setStatus(GlusterSnapshotStatus.STARTED);
+        snap2.setVolumeId(VOLUME_ID_1);
+        snapshots.add(snap2);
+
+        return snapshots;
+    }
+
+    private List<VDSGroup> getClusters() {
+        List<VDSGroup> list = new ArrayList<>();
+
+        VDSGroup cluster = new VDSGroup();
+        cluster.setId(CLUSTER_ID_1);
+        cluster.setName("cluster");
+        cluster.setGlusterService(true);
+        cluster.setVirtService(false);
+        cluster.setcompatibility_version(Version.v3_5);
+        list.add(cluster);
+
+        VDSGroup cluster1 = new VDSGroup();
+        cluster1.setId(CLUSTER_ID_2);
+        cluster1.setName("cluster1");
+        cluster1.setGlusterService(true);
+        cluster1.setVirtService(false);
+        cluster1.setcompatibility_version(Version.v3_4);
+        list.add(cluster1);
+
+        return list;
+    }
+
+    private VDS getServer() {
+        VDS vds = new VDS();
+        vds.setId(Guid.newGuid());
+        return vds;
+    }
+
+    private List<GlusterVolumeEntity> getVolumes() {
+        List<GlusterVolumeEntity> volList = new 
ArrayList<GlusterVolumeEntity>();
+        volList.add(getVolume(CLUSTER_ID_1, VOLUME_ID_1, VOLUME_NAME_1));
+        return volList;
+    }
+
+    private GlusterVolumeEntity getVolume(Guid clusterId, Guid volumeId, 
String volumeName) {
+        GlusterVolumeEntity volume = new GlusterVolumeEntity();
+        volume.setName(volumeName);
+        volume.setClusterId(clusterId);
+        volume.setId(volumeId);
+        volume.setReplicaCount(2);
+
+        GlusterBrickEntity brick = new GlusterBrickEntity();
+        brick.setVolumeId(volume.getId());
+        brick.setBrickDirectory("/export/testvol1");
+        brick.setStatus(GlusterStatus.UP);
+        brick.setBrickOrder(0);
+        volume.addBrick(brick);
+
+        GlusterBrickEntity brick2 = new GlusterBrickEntity();
+        brick2.setVolumeId(volume.getId());
+        brick2.setBrickDirectory("/export/testvol1");
+        brick2.setStatus(GlusterStatus.UP);
+        brick2.setBrickOrder(1);
+        volume.addBrick(brick2);
+
+        return volume;
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotConfigInfo.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotConfigInfo.java
new file mode 100644
index 0000000..6941672
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotConfigInfo.java
@@ -0,0 +1,54 @@
+package org.ovirt.engine.core.common.businessentities.gluster;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.ovirt.engine.core.common.utils.ObjectUtils;
+
+public class GlusterSnapshotConfigInfo implements Serializable {
+    private static final long serialVersionUID = -768822766895441288L;
+
+    private Map<String, String> clusterConfigOptions;
+    private Map<String, Map<String, String>> volumeConfigOptions;
+
+    public Map<String, String> getClusterConfigOptions() {
+        return this.clusterConfigOptions;
+    }
+
+    public void setClusterConfigOptions(Map<String, String> options) {
+        this.clusterConfigOptions = options;
+    }
+
+    public Map<String, Map<String, String>> getVolumeConfigOptions() {
+        return this.volumeConfigOptions;
+    }
+
+    public void setVolumeConfigOptions(Map<String, Map<String, String>> 
options) {
+        this.volumeConfigOptions = options;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof GlusterSnapshotConfigInfo)) {
+            return false;
+        }
+        GlusterSnapshotConfigInfo configInfo = (GlusterSnapshotConfigInfo) obj;
+        if (!ObjectUtils.objectsEqual(getClusterConfigOptions(), 
configInfo.getClusterConfigOptions())) {
+            return false;
+        }
+        if (!ObjectUtils.objectsEqual(getVolumeConfigOptions(), 
configInfo.getVolumeConfigOptions())) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getClusterConfigOptions() == null) ? 0 : 
getClusterConfigOptions().hashCode());
+        result =
+                prime * result + ((getVolumeConfigOptions() == null) ? 0 : 
getVolumeConfigOptions().hashCode());
+        return result;
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotStatus.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotStatus.java
index 1912c1f..3a171dc 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotStatus.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterSnapshotStatus.java
@@ -7,7 +7,7 @@
 
     public static GlusterSnapshotStatus from(String status) {
         for (GlusterSnapshotStatus snapshotStatus : values()) {
-            if (snapshotStatus.name().equals(status)) {
+            if (snapshotStatus.name().equalsIgnoreCase(status)) {
                 return snapshotStatus;
             }
         }
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 72c5ef9..1a6790c 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
@@ -399,6 +399,8 @@
     GlfsStatvfsException(4571),
     GlfsInitException(4572),
     GlfsFiniException(4573),
+    GlusterSnapshotException(4700),
+    GlusterSnapshotInfoFailedException(4708),
 
     UnicodeArgumentException(4900),
 
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
index 12c8485..70e32d2 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
@@ -929,6 +929,8 @@
     ACTION_TYPE_FAILED_NO_SERVERS_FOR_CLUSTER(ErrorType.BAD_PARAMETERS),
     ACTION_TYPE_FAILED_VOLUME_OPERATION_IN_PROGRESS(ErrorType.CONFLICT),
     ACTION_TYPE_FAILED_GLUSTER_OPERATION_INPROGRESS(ErrorType.CONFLICT),
+    ACTION_TYPE_FAILED_VOLUME_SNAPSHOT_LOCKED(ErrorType.CONFLICT),
+
     // OpenStack Glance
     ACTION_TYPE_FAILED_IMAGE_DOWNLOAD_ERROR(ErrorType.BAD_PARAMETERS),
     ACTION_TYPE_FAILED_IMAGE_NOT_SUPPORTED(ErrorType.BAD_PARAMETERS),
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
index 564f731..2e72df9 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
@@ -80,4 +80,14 @@
             return false;
         }
     }
+
+  /**
+   * @param version
+   *            Compatibility version to check for.
+   * @return <code>true</code> if gluster snapshot management feature is 
enabled,
+   *         <code>false</code> if it's not.
+   */
+  public static boolean glusterSnapshot(Version version) {
+      return supportedInConfig(ConfigValues.GlusterVolumeSnapshotSupported, 
version);
+  }
 }
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java
index 83801a6..2b10a8c 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/locks/LockingGroup.java
@@ -17,6 +17,8 @@
     REGISTER_VDS,
     VM_SNAPSHOTS,
     GLUSTER,
+    /** this group is used for gluster volume snapshot purpose */
+    GLUSTER_SNAPSHOT,
     USER_VM_POOL,
     /** This group is used to lock template which is in export domain */
     REMOTE_TEMPLATE,
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java
index 5bb1b87..b2e62da 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/VDSCommandType.java
@@ -158,6 +158,8 @@
     GetDiskAlignment("org.ovirt.engine.core.vdsbroker.vdsbroker"),
     GlusterTasksList("org.ovirt.engine.core.vdsbroker.gluster"),
     
GetGlusterVolumeRemoveBricksStatus("org.ovirt.engine.core.vdsbroker.gluster"),
+    GetGlusterVolumeSnapshotInfo("org.ovirt.engine.core.vdsbroker.gluster"),
+    
GetGlusterVolumeSnapshotConfigInfo("org.ovirt.engine.core.vdsbroker.gluster"),
     SetNumberOfCpus("org.ovirt.engine.core.vdsbroker"),
     UpdateVmPolicy("org.ovirt.engine.core.vdsbroker"),
     List("org.ovirt.engine.core.vdsbroker.vdsbroker"),           // get a list 
of VMs with status only
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/gluster/GlusterVolumeSnapshotVDSParameters.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/gluster/GlusterVolumeSnapshotVDSParameters.java
new file mode 100644
index 0000000..99dfab7
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/gluster/GlusterVolumeSnapshotVDSParameters.java
@@ -0,0 +1,23 @@
+package org.ovirt.engine.core.common.vdscommands.gluster;
+
+import org.ovirt.engine.core.compat.Guid;
+
+public class GlusterVolumeSnapshotVDSParameters extends 
GlusterVolumeVDSParameters {
+    protected Guid clusterId;
+
+    public GlusterVolumeSnapshotVDSParameters() {
+    }
+
+    public GlusterVolumeSnapshotVDSParameters(Guid serverId, Guid clusterId, 
String volumeName) {
+        super(serverId, volumeName);
+        this.clusterId = clusterId;
+    }
+
+    public Guid getClusterId() {
+        return this.clusterId;
+    }
+
+    public void setClusterId(Guid clusterId) {
+        this.clusterId = clusterId;
+    }
+}
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterVolumeSnapshotDaoDbFacadeImpl.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterVolumeSnapshotDaoDbFacadeImpl.java
index bf3137b..1ef2690 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterVolumeSnapshotDaoDbFacadeImpl.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/gluster/GlusterVolumeSnapshotDaoDbFacadeImpl.java
@@ -130,7 +130,8 @@
                 .addValue("snapshot_name", snapshot.getSnapshotName())
                 .addValue("volume_id", snapshot.getVolumeId())
                 .addValue("description", snapshot.getDescription())
-                .addValue("status", 
EnumUtils.nameOrNull(snapshot.getStatus()));
+                .addValue("status", EnumUtils.nameOrNull(snapshot.getStatus()))
+                .addValue("_create_date", snapshot.getCreatedAt());
     }
 
     private MapSqlParameterSource createSnapshotIdParams(Guid id) {
diff --git 
a/backend/manager/modules/dal/src/main/resources/bundles/VdsmErrors.properties 
b/backend/manager/modules/dal/src/main/resources/bundles/VdsmErrors.properties
index f3b06a9..bc0953c 100644
--- 
a/backend/manager/modules/dal/src/main/resources/bundles/VdsmErrors.properties
+++ 
b/backend/manager/modules/dal/src/main/resources/bundles/VdsmErrors.properties
@@ -372,6 +372,8 @@
 GlfsStatvfsException=Failed to get gluster volume size info
 GlfsInitException=Command failed while mounting gluster volume
 GlfsFiniException=Command failed while unmounting gluster volume
+GlusterSnapshotException=Error in executing gluster snapshot command
+GlusterSnapshotInfoFailedException=Gluster snapshot info failed
 
 CANT_RECONSTRUCT_WHEN_A_DOMAIN_IN_POOL_IS_LOCKED=Can't reconstruct the Master 
Domain when the Data Center contains Domains in Locked state.\nPlease wait 
until the operation for these Domains ends before trying to reconstruct the 
Master Domain again.
 NO_IMPLEMENTATION=Not implemented
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/AbstractGlusterBrokerCommand.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/AbstractGlusterBrokerCommand.java
index 2b2d573..6578218 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/AbstractGlusterBrokerCommand.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/AbstractGlusterBrokerCommand.java
@@ -70,6 +70,9 @@
         case GlfsStatvfsException:
         case GlfsInitException:
         case GlfsFiniException:
+        case GlusterSnapshotException:
+        case GlusterSnapshotInfoFailedException:
+
             // Capture error from gluster command and record failure
             getVDSReturnValue().setVdsError(new VDSError(returnStatus, 
getReturnStatus().mMessage));
             getVDSReturnValue().setSucceeded(false);
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotConfigInfoVDSCommand.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotConfigInfoVDSCommand.java
new file mode 100644
index 0000000..fdcbf21
--- /dev/null
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotConfigInfoVDSCommand.java
@@ -0,0 +1,30 @@
+package org.ovirt.engine.core.vdsbroker.gluster;
+
+import 
org.ovirt.engine.core.common.vdscommands.gluster.GlusterVolumeSnapshotVDSParameters;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.vdsbroker.vdsbroker.StatusForXmlRpc;
+
+public class GetGlusterVolumeSnapshotConfigInfoVDSCommand<P extends 
GlusterVolumeSnapshotVDSParameters> extends AbstractGlusterBrokerCommand<P> {
+    private GlusterVolumeSnapshotConfigReturnForXmlRpc infoReturn;
+
+    public GetGlusterVolumeSnapshotConfigInfoVDSCommand(P parameters) {
+        super(parameters);
+    }
+
+    @Override
+    protected StatusForXmlRpc getReturnStatus() {
+        return this.infoReturn.mStatus;
+    }
+
+    @Override
+    protected void executeVdsBrokerCommand() {
+        Guid clusterId = getParameters().getClusterId();
+        String volumeName = getParameters().getVolumeName();
+        infoReturn = getBroker().glusterVolumeSnapshotConfigGet(clusterId, 
volumeName);
+        proceedProxyReturnValue();
+
+        if (getVDSReturnValue().getSucceeded()) {
+            setReturnValue(infoReturn.getGlusterSnapshotConfigInfo());
+        }
+    }
+}
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotInfoVDSCommand.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotInfoVDSCommand.java
new file mode 100644
index 0000000..d4567de
--- /dev/null
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GetGlusterVolumeSnapshotInfoVDSCommand.java
@@ -0,0 +1,30 @@
+package org.ovirt.engine.core.vdsbroker.gluster;
+
+import 
org.ovirt.engine.core.common.vdscommands.gluster.GlusterVolumeSnapshotVDSParameters;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.vdsbroker.vdsbroker.StatusForXmlRpc;
+
+public class GetGlusterVolumeSnapshotInfoVDSCommand<P extends 
GlusterVolumeSnapshotVDSParameters> extends AbstractGlusterBrokerCommand<P> {
+    private GlusterVolumeSnapshotInfoReturnForXmlRpc infoReturn;
+
+    public GetGlusterVolumeSnapshotInfoVDSCommand(P parameters) {
+        super(parameters);
+    }
+
+    @Override
+    protected StatusForXmlRpc getReturnStatus() {
+        return infoReturn.mStatus;
+    }
+
+    @Override
+    protected void executeVdsBrokerCommand() {
+        Guid clusterId = getParameters().getClusterId();
+        String volumeName = getParameters().getVolumeName();
+        infoReturn = getBroker().glusterSnapshotInfo(clusterId, volumeName);
+        proceedProxyReturnValue();
+
+        if (getVDSReturnValue().getSucceeded()) {
+            setReturnValue(infoReturn.getSnapshots());
+        }
+    }
+}
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotConfigReturnForXmlRpc.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotConfigReturnForXmlRpc.java
new file mode 100644
index 0000000..f632f77
--- /dev/null
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotConfigReturnForXmlRpc.java
@@ -0,0 +1,67 @@
+package org.ovirt.engine.core.vdsbroker.gluster;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterSnapshotConfigInfo;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.vdsbroker.irsbroker.StatusReturnForXmlRpc;
+import org.ovirt.engine.core.vdsbroker.vdsbroker.StatusForXmlRpc;
+
+public class GlusterVolumeSnapshotConfigReturnForXmlRpc extends 
StatusReturnForXmlRpc {
+    private static final String STATUS = "status";
+    private static final String SNAPSHOT_CONFIG = "snapshotConfig";
+    private static final String SYSTEM_CONFIG = "systemConfig";
+    private static final String VOLUME_CONFIG = "volumeConfig";
+
+    private StatusForXmlRpc status;
+    private GlusterSnapshotConfigInfo glusterSnapshotConfigInfo = new 
GlusterSnapshotConfigInfo();
+
+    public GlusterSnapshotConfigInfo getGlusterSnapshotConfigInfo() {
+        return this.glusterSnapshotConfigInfo;
+    }
+
+    public GlusterVolumeSnapshotConfigReturnForXmlRpc(Guid clusterId, 
Map<String, Object> innerMap) {
+        super(innerMap);
+        status = new StatusForXmlRpc((Map<String, Object>) 
innerMap.get(STATUS));
+
+        Map<String, Object> configInfo = (Map<String, Object>) 
innerMap.get(SNAPSHOT_CONFIG);
+
+        Map<String, Object> systemConfig = (Map<String, Object>) 
configInfo.get(SYSTEM_CONFIG);
+        Map<String, String> clusterConfigs = new HashMap<String, String>();
+        for (Map.Entry<String, Object> entry : systemConfig.entrySet()) {
+            String value = (String) entry.getValue();
+            clusterConfigs.put(entry.getKey(), value == null ? "" : value);
+        }
+        glusterSnapshotConfigInfo.setClusterConfigOptions(clusterConfigs);
+
+        
glusterSnapshotConfigInfo.setVolumeConfigOptions(parseVolumeConfigDetails((Map<String,
 Object>) configInfo.get(VOLUME_CONFIG)));
+    }
+
+    private Map<String, Map<String, String>> 
parseVolumeConfigDetails(Map<String, Object> configs) {
+        Map<String, Map<String, String>> volumeConfigs =
+                new HashMap<String, Map<String, String>>();
+
+        for (Map.Entry<String, Object> entry : configs.entrySet()) {
+            Map<String, Object> fetchedVolumeConfig = (Map<String, Object>) 
entry.getValue();
+            Map<String, String> volConfig = new HashMap<String, String>();
+
+            for (Map.Entry<String, Object> config : 
fetchedVolumeConfig.entrySet()) {
+                String value = (String) config.getValue();
+                volConfig.put(config.getKey(), value);
+            }
+
+            volumeConfigs.put(entry.getKey(), volConfig);
+        }
+
+        return volumeConfigs;
+    }
+
+    public StatusForXmlRpc getStatus() {
+        return status;
+    }
+
+    public void setStatus(StatusForXmlRpc status) {
+        this.status = status;
+    }
+}
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotInfoReturnForXmlRpc.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotInfoReturnForXmlRpc.java
new file mode 100644
index 0000000..ee6f3c9
--- /dev/null
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/gluster/GlusterVolumeSnapshotInfoReturnForXmlRpc.java
@@ -0,0 +1,98 @@
+package org.ovirt.engine.core.vdsbroker.gluster;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterSnapshotStatus;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.dao.gluster.GlusterVolumeDao;
+import org.ovirt.engine.core.vdsbroker.irsbroker.StatusReturnForXmlRpc;
+import org.ovirt.engine.core.vdsbroker.vdsbroker.StatusForXmlRpc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unchecked")
+public final class GlusterVolumeSnapshotInfoReturnForXmlRpc extends 
StatusReturnForXmlRpc {
+    private static final String STATUS = "status";
+    private static final String SNAPSHOT_LIST = "snapshotList";
+    private static final String SNAPSHOTS = "snapshots";
+    private static final String NAME = "name";
+    private static final String DESCRIPTION = "snapDescription";
+    private static final String CREATETIME = "createTime";
+    private static final String SNAPSHOT_UUID = "snapshotUuid";
+    private static final String SNAPSHOT_NAME = "snapshotName";
+    private static final String SNAP_VOLUME_STATUS = "snapVolumeStatus";
+
+    private StatusForXmlRpc status;
+    private static final Logger log = 
LoggerFactory.getLogger(GlusterVolumesListReturnForXmlRpc.class);
+    private List<GlusterVolumeSnapshotEntity> glusterVolumeSnapshots = new 
ArrayList<GlusterVolumeSnapshotEntity>();
+
+    public List<GlusterVolumeSnapshotEntity> getSnapshots() {
+        return glusterVolumeSnapshots;
+    }
+
+    public GlusterVolumeSnapshotInfoReturnForXmlRpc(Guid clusterId, 
Map<String, Object> innerMap) {
+        super(innerMap);
+        status = new StatusForXmlRpc((Map<String, Object>) 
innerMap.get(STATUS));
+
+        Map<String, Object> snapshots = (Map<String, Object>) 
innerMap.get(SNAPSHOT_LIST);
+
+        glusterVolumeSnapshots = prepareVolumeSnapshotsList(clusterId, 
snapshots);
+    }
+
+    private List<GlusterVolumeSnapshotEntity> prepareVolumeSnapshotsList(Guid 
clusterId, Map<String, Object> snapshots) {
+
+        List<GlusterVolumeSnapshotEntity> newSnapshotsList = new 
ArrayList<GlusterVolumeSnapshotEntity>();
+
+        for (Map.Entry<String, Object> entry : snapshots.entrySet()) {
+            String volumeName = entry.getKey();
+            Map<String, Object> snapshotInfo = (Map<String, Object>) 
entry.getValue();
+
+            Object[] volumeSnapshots = (Object[]) 
(snapshotInfo.get(SNAPSHOTS));
+            GlusterVolumeEntity volumeEntity = 
getGlusterVolumeDao().getByName(clusterId, volumeName);
+
+            for (Object snapshot : volumeSnapshots) {
+                Map<String, Object> individualSnapshot = (Map<String, Object>) 
snapshot;
+                GlusterVolumeSnapshotEntity newSnapshot = new 
GlusterVolumeSnapshotEntity();
+                newSnapshot.setClusterId(clusterId);
+                newSnapshot.setVolumeId(volumeEntity.getId());
+                newSnapshot.setSnapshotId(Guid.createGuidFromString((String) 
individualSnapshot.get(SNAPSHOT_UUID)));
+                newSnapshot.setSnapshotName((String) 
individualSnapshot.get(SNAPSHOT_NAME));
+                newSnapshot.setDescription((String) 
individualSnapshot.get(DESCRIPTION));
+                newSnapshot.setStatus(GlusterSnapshotStatus.from((String) 
individualSnapshot.get(SNAP_VOLUME_STATUS)));
+                try {
+                    DateFormat df = new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ss");
+                    newSnapshot.setCreatedAt(df.parse((String) 
individualSnapshot.get(CREATETIME)));
+                } catch (Exception e) {
+                    log.info("Could not populate creation time for snapshot 
'{}' of volume '{}' on cluster '{}': {}",
+                            (String) snapshotInfo.get(NAME),
+                            volumeEntity.getName(),
+                            clusterId,
+                            e.getMessage());
+                    log.debug("Exception", e);
+                }
+                newSnapshotsList.add(newSnapshot);
+            }
+        }
+
+        return newSnapshotsList;
+    }
+
+    private GlusterVolumeDao getGlusterVolumeDao() {
+        return DbFacade.getInstance().getGlusterVolumeDao();
+    }
+
+    public StatusForXmlRpc getStatus() {
+        return status;
+    }
+
+    public void setStatus(StatusForXmlRpc status) {
+        this.status = status;
+    }
+}
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java
index 732cf7a..a7806e0 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/jsonrpc/JsonRpcVdsServer.java
@@ -20,6 +20,8 @@
 import org.ovirt.engine.core.vdsbroker.gluster.GlusterTasksListReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeOptionsInfoReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeProfileInfoReturnForXmlRpc;
+import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeSnapshotConfigReturnForXmlRpc;
+import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeSnapshotInfoReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeStatusReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeTaskReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumesListReturnForXmlRpc;
@@ -1481,4 +1483,22 @@
                 new FutureMap(this.client, request);
         return new StatusOnlyReturnForXmlRpc(response);
     }
+
+    @Override
+    public GlusterVolumeSnapshotInfoReturnForXmlRpc glusterSnapshotInfo(Guid 
clusterId, String volumeName) {
+        JsonRpcRequest request =
+                new 
RequestBuilder("GlusterVolume.snapshotList").withOptionalParameter("volumeName",
 volumeName)
+                        .build();
+        Map<String, Object> response = new FutureMap(this.client, 
request).withIgnoreResponseKey();
+        return new GlusterVolumeSnapshotInfoReturnForXmlRpc(clusterId, 
response);
+    }
+
+    @Override
+    public GlusterVolumeSnapshotConfigReturnForXmlRpc 
glusterVolumeSnapshotConfigGet(Guid clusterId, String volumeName) {
+        JsonRpcRequest request =
+                new 
RequestBuilder("GlusterSnapshot.configList").withOptionalParameter("volumeName",
 volumeName)
+                        .build();
+        Map<String, Object> response = new FutureMap(this.client, 
request).withIgnoreResponseKey();
+        return new GlusterVolumeSnapshotConfigReturnForXmlRpc(clusterId, 
response);
+    }
 }
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java
index 89f3404..b7421a8 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/IVdsServer.java
@@ -15,6 +15,8 @@
 import org.ovirt.engine.core.vdsbroker.gluster.GlusterTasksListReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeOptionsInfoReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeProfileInfoReturnForXmlRpc;
+import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeSnapshotConfigReturnForXmlRpc;
+import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeSnapshotInfoReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeStatusReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeTaskReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumesListReturnForXmlRpc;
@@ -311,4 +313,8 @@
     StatusOnlyReturnForXmlRpc setNumberOfCpus(String vmId, String 
numberOfCpus);
 
     StatusOnlyReturnForXmlRpc updateVmPolicy(Map info);
+
+    GlusterVolumeSnapshotInfoReturnForXmlRpc glusterSnapshotInfo(Guid 
clusterId, String volumeName);
+
+    GlusterVolumeSnapshotConfigReturnForXmlRpc 
glusterVolumeSnapshotConfigGet(Guid clusterId, String volumeName);
 }
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerConnector.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerConnector.java
index cc778ae..29b661e 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerConnector.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerConnector.java
@@ -294,4 +294,8 @@
     public Map<String, Object> setNumberOfCpus(String vmId, String 
numberOfCpus);
 
     public Map<String, Object> updateVmPolicy(Map info);
+
+    public Map<String, Object> glusterSnapshotInfo(String snapshotName, String 
volumeName);
+
+    public Map<String, Object> glusterSnapshotConfigGet(String volumeName);
 }
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java
index 5f43faf..21b5035 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsServerWrapper.java
@@ -16,6 +16,8 @@
 import org.ovirt.engine.core.vdsbroker.gluster.GlusterTasksListReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeOptionsInfoReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeProfileInfoReturnForXmlRpc;
+import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeSnapshotConfigReturnForXmlRpc;
+import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeSnapshotInfoReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeStatusReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumeTaskReturnForXmlRpc;
 import 
org.ovirt.engine.core.vdsbroker.gluster.GlusterVolumesListReturnForXmlRpc;
@@ -1438,4 +1440,34 @@
         StoragePoolInfoReturnForXmlRpc wrapper = new 
StoragePoolInfoReturnForXmlRpc(xmlRpcReturnValue);
         return wrapper;
     }
+
+    public GlusterVolumeSnapshotInfoReturnForXmlRpc glusterSnapshotInfo(Guid 
clusterId,
+            String volumeName) {
+        try {
+            Map<String, Object> xmlRpcReturnValue = 
vdsServer.glusterSnapshotInfo("", volumeName);
+            GlusterVolumeSnapshotInfoReturnForXmlRpc wrapper =
+                    new GlusterVolumeSnapshotInfoReturnForXmlRpc(clusterId, 
xmlRpcReturnValue);
+            return wrapper;
+        } catch (UndeclaredThrowableException ute) {
+            throw new XmlRpcRunTimeException(ute);
+        }
+    }
+
+    @Override
+    public GlusterVolumeSnapshotConfigReturnForXmlRpc 
glusterVolumeSnapshotConfigGet(Guid clusterId, String volumeName) {
+        try {
+            Map<String, Object> xmlRpcReturnValue;
+            if (volumeName == null) {
+                xmlRpcReturnValue = vdsServer.glusterSnapshotConfigGet("");
+            } else {
+                xmlRpcReturnValue = 
vdsServer.glusterSnapshotConfigGet(volumeName);
+            }
+
+            GlusterVolumeSnapshotConfigReturnForXmlRpc wrapper =
+                    new GlusterVolumeSnapshotConfigReturnForXmlRpc(clusterId, 
xmlRpcReturnValue);
+            return wrapper;
+        } catch (UndeclaredThrowableException ute) {
+            throw new XmlRpcRunTimeException(ute);
+        }
+    }
 }
diff --git 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/VdsmErrors.java
 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/VdsmErrors.java
index b99a183..c2c3be3 100644
--- 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/VdsmErrors.java
+++ 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/VdsmErrors.java
@@ -821,4 +821,10 @@
     @DefaultStringValue("Cannot get list of images in ISO domain. " +
             "Please check that the storage domain status is Active")
     String GetIsoListError();
+
+    @DefaultStringValue("Error in executing gluster snapshot command")
+    String GlusterSnapshotException();
+
+    @DefaultStringValue("Gluster snapshot info failed")
+    String GlusterSnapshotInfoFailedException();
 }
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/VdsmErrors.properties
 
b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/VdsmErrors.properties
index 9315b0b..2645761 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/VdsmErrors.properties
+++ 
b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/VdsmErrors.properties
@@ -381,3 +381,5 @@
 GlusterHostIsNotPartOfCluster = Host is not part of the cluster
 GlusterVolumeRebalanceStatusFailedException=Failed to get gluster volume 
rebalance status
 GlusterVolumeRemoveBrickStatusFailed=Failed to get status of gluster volume 
remove bricks
+GlusterSnapshotException=Error in executing gluster snapshot command
+GlusterSnapshotInfoFailedException=Gluster snapshot info failed
diff --git a/packaging/dbscripts/gluster_volume_snapshot_sp.sql 
b/packaging/dbscripts/gluster_volume_snapshot_sp.sql
index 38ba5a2..969e37a 100644
--- a/packaging/dbscripts/gluster_volume_snapshot_sp.sql
+++ b/packaging/dbscripts/gluster_volume_snapshot_sp.sql
@@ -9,14 +9,15 @@
                                                 v_snapshot_name VARCHAR(1000),
                                                 v_volume_id UUID,
                                                 v_description VARCHAR(1024),
-                                                v_status VARCHAR(32))
+                                                v_status VARCHAR(32),
+                                                v__create_date TIMESTAMP WITH 
TIME ZONE)
     RETURNS VOID
     AS $procedure$
 BEGIN
     INSERT INTO gluster_volume_snapshots (snapshot_id, snapshot_name, 
volume_id,
-        description, status)
+        description, status, _create_date)
     VALUES (v_snapshot_id,  v_snapshot_name, v_volume_id,
-        v_description, v_status);
+        v_description, v_status, v__create_date);
 
     PERFORM UpdateSnapshotCountInc(v_volume_id, 1);
 END; $procedure$


-- 
To view, visit https://gerrit.ovirt.org/39280
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I7b7bf79b72fc5680dab301b290e7aa860d5c714d
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: ovirt-engine-3.5-gluster
Gerrit-Owner: Shubhendu Tripathi <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to