Shubhendu Tripathi has uploaded a new change for review.

Change subject: webadmin: Listing gluster volume snapshots
......................................................................

webadmin: Listing gluster volume snapshots

Introduced sub tab for listing gluster volume snapshots under Volumes
main tab.
Also added a column for no of snapshots under volumes list and added a
field to display the maximum no of allowed snapshots for a volume under
General sub tab.

Change-Id: Ic1953aad3d013d386719a43b4bfdda82896cc3af
Signed-off-by: Shubhendu Tripathi <shtri...@redhat.com>
---
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterVolumeSnapshotEntity.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/help/HelpTag.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/VolumeGeneralModel.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/volumes/VolumeListModel.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/place/WebAdminApplicationPlaces.java
M 
frontend/webadmin/modules/uicompat/src/main/resources/org/ovirt/engine/ui/uicompat/LocalizedEnums.properties
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationConstants.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationTemplates.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/ClientGinjectorExtension.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VolumeModule.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/gluster/SubTabGlusterVolumeSnapshotPresenter.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVolumeView.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabGlusterVolumeSnapshotView.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabVolumeGeneralView.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusCell.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusColumn.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountCell.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountColumn.java
22 files changed, 677 insertions(+), 179 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/28/36628/1

diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterVolumeSnapshotEntity.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterVolumeSnapshotEntity.java
index edc3907..bde66d4 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterVolumeSnapshotEntity.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/gluster/GlusterVolumeSnapshotEntity.java
@@ -133,4 +133,9 @@
 
         return true;
     }
+
+    @Override
+    public Object getQueryableId() {
+        return this.snapshotId;
+    }
 }
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
index 07cf87f..e9e7f1a 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Linq.java
@@ -41,6 +41,7 @@
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterGeoRepSession;
 import org.ovirt.engine.core.common.businessentities.network.HostNetworkQos;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
 import org.ovirt.engine.core.common.businessentities.network.Network;
 import org.ovirt.engine.core.common.businessentities.network.NetworkInterface;
 import org.ovirt.engine.core.common.businessentities.network.NetworkQoS;
@@ -139,6 +140,15 @@
         }
     }
 
+    public static class GlusterVolumeSnapshotComparer implements 
Comparator<GlusterVolumeSnapshotEntity>, Serializable {
+        private static final long serialVersionUID = -6085272225112945249L;
+
+        @Override
+        public int compare(GlusterVolumeSnapshotEntity snapshot0, 
GlusterVolumeSnapshotEntity snapshot1) {
+            return 
snapshot0.getSnapshotName().compareTo(snapshot1.getSnapshotName());
+        }
+    }
+
     public static class DiskImageByLastModifiedComparer implements 
Comparator<DiskImage>, Serializable
     {
 
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
index 01bd2dd..c6186a7 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
@@ -78,6 +78,7 @@
 import org.ovirt.engine.core.common.businessentities.gluster.GlusterHookEntity;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterServerService;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
 import org.ovirt.engine.core.common.businessentities.gluster.ServiceType;
 import org.ovirt.engine.core.common.businessentities.network.HostNetworkQos;
 import org.ovirt.engine.core.common.businessentities.network.Network;
@@ -1624,6 +1625,16 @@
         
Frontend.getInstance().runQuery(VdcQueryType.GetGlusterVolumeGeoRepSessions, 
new IdQueryParameters(masterVolumeId), aQuery);
     }
 
+    public void getGlusterVolumeSnapshotsForVolume(AsyncQuery aQuery, Guid 
volumeId) {
+        aQuery.converterCallback = new IAsyncConverter() {
+            @Override
+            public Object Convert(Object source, AsyncQuery asyncQuery) {
+                return source != null ? source : new 
ArrayList<GlusterVolumeSnapshotEntity>();
+            }
+        };
+        
Frontend.getInstance().runQuery(VdcQueryType.GetGlusterVolumeSnapshotsByVolumeId,
 new IdQueryParameters(volumeId), aQuery);
+    }
+
     public void getGlusterHook(AsyncQuery aQuery, Guid hookId, boolean 
includeServerHooks) {
         aQuery.converterCallback = new IAsyncConverter() {
             @Override
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/help/HelpTag.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/help/HelpTag.java
index f018dc1..07bf103 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/help/HelpTag.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/help/HelpTag.java
@@ -486,6 +486,8 @@
 
     volume_stop("volume_stop", HelpTagType.WEBADMIN, "Volumes Tab > Stop 
Volume"), //$NON-NLS-1$ //$NON-NLS-2$
 
+    volume_snapshots("volume_snapshots", HelpTagType.WEBADMIN), //$NON-NLS-1$
+
     new_role("new_role", HelpTagType.WEBADMIN), //$NON-NLS-1$
 
     edit_role("edit_role", HelpTagType.WEBADMIN), //$NON-NLS-1$
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java
new file mode 100644
index 0000000..7421c4d
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java
@@ -0,0 +1,79 @@
+package org.ovirt.engine.ui.uicommonweb.models.gluster;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+import org.ovirt.engine.ui.frontend.AsyncQuery;
+import org.ovirt.engine.ui.frontend.INewAsyncCallback;
+import org.ovirt.engine.ui.uicommonweb.Linq;
+import org.ovirt.engine.ui.uicommonweb.UICommand;
+import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+
+public class GlusterVolumeSnapshotListModel extends SearchableListModel {
+    @Override
+    public String getListName() {
+        return "GlusterVolumeSnapshotListModel"; //$NON-NLS-1$
+    }
+
+    public GlusterVolumeSnapshotListModel() {
+        
setTitle(ConstantsManager.getInstance().getConstants().snapshotsTitle());
+        setHelpTag(HelpTag.volume_snapshots);
+        setHashName("volume_snapshots");//$NON-NLS-1$
+    }
+
+    @Override
+    protected void onEntityChanged() {
+        super.onEntityChanged();
+        getSearchCommand().execute();
+    }
+
+    @Override
+    protected void onSelectedItemChanged() {
+        super.onSelectedItemChanged();
+    }
+
+    @Override
+    protected void selectedItemsChanged()
+    {
+        super.selectedItemsChanged();
+    }
+
+    @Override
+    protected void syncSearch() {
+        if (getEntity() == null) {
+            return;
+        }
+
+        AsyncDataProvider.getInstance().getGlusterVolumeSnapshotsForVolume(new 
AsyncQuery(this,
+                new INewAsyncCallback() {
+
+                    @Override
+                    public void onSuccess(Object model, Object returnValue) {
+                        List<GlusterVolumeSnapshotEntity> snapshots =
+                                (ArrayList<GlusterVolumeSnapshotEntity>) 
returnValue;
+                        Collections.sort(snapshots, new 
Linq.GlusterVolumeSnapshotComparer());
+                        setItems(snapshots);
+                    }
+                }), getEntity().getId());
+    }
+
+    @Override
+    public void executeCommand(UICommand command) {
+        super.executeCommand(command);
+    }
+
+    @Override
+    public GlusterVolumeEntity getEntity() {
+        return (GlusterVolumeEntity) super.getEntity();
+    }
+
+    public void setEntity(GlusterVolumeEntity value) {
+        super.setEntity(value);
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/VolumeGeneralModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/VolumeGeneralModel.java
index d341419..02ca742 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/VolumeGeneralModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/VolumeGeneralModel.java
@@ -19,6 +19,7 @@
     private String glusterMountPoint;
     private String nfsMountPoint;
     private Set<TransportType> transportTypes;
+    private String snapMaxLimit;
 
     public String getName() {
         return name;
@@ -89,6 +90,14 @@
         this.nfsMountPoint = nfsMountPoint;
     }
 
+    public String getSnapMaxLimit() {
+        return this.snapMaxLimit;
+    }
+
+    public void setSnapMaxLimit(String noOfSnaps) {
+        this.snapMaxLimit = noOfSnaps;
+    }
+
     public VolumeGeneralModel() {
         setTitle(ConstantsManager.getInstance().getConstants().generalTitle());
         setHelpTag(HelpTag.general);
@@ -113,6 +122,7 @@
         setStripeCount(entity.getStripeCount() != null ? 
Integer.toString(entity.getStripeCount()) : null);
         setNumOfBricks(entity.getBricks() != null ? 
Integer.toString(entity.getBricks().size()) : null);
         setTransportTypes(entity.getTransportTypes());
+        setSnapMaxLimit(entity.getSnapMaxLimit() != null ? 
entity.getSnapMaxLimit().toString() : null);
     }
 
     public Set<TransportType> getTransportTypes() {
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/volumes/VolumeListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/volumes/VolumeListModel.java
index db5b5cb..40b8b58 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/volumes/VolumeListModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/volumes/VolumeListModel.java
@@ -51,6 +51,7 @@
 import org.ovirt.engine.ui.uicommonweb.models.SystemTreeItemModel;
 import org.ovirt.engine.ui.uicommonweb.models.SystemTreeItemType;
 import org.ovirt.engine.ui.uicommonweb.models.configure.PermissionListModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.gluster.GlusterVolumeSnapshotListModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeBrickListModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeEventListModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeGeneralModel;
@@ -122,6 +123,7 @@
     public void setStopRebalanceCommand(UICommand stopRebalanceCommand) {
         this.stopRebalanceCommand = stopRebalanceCommand;
     }
+
     private UICommand statusRebalanceCommand;
 
     public UICommand getStatusRebalanceCommand() {
@@ -168,6 +170,12 @@
         return geoRepListModel;
     }
 
+    private final GlusterVolumeSnapshotListModel snapshotListModel;
+
+    public GlusterVolumeSnapshotListModel getSnapshotListModel() {
+        return snapshotListModel;
+    }
+
     public UICommand getStartVolumeProfilingCommand() {
         return startVolumeProfilingCommand;
     }
@@ -193,19 +201,24 @@
     }
 
     @Inject
-    public VolumeListModel(final VolumeBrickListModel volumeBrickListModel, 
final VolumeGeneralModel volumeGeneralModel,
+    public VolumeListModel(final VolumeBrickListModel volumeBrickListModel,
+            final VolumeGeneralModel volumeGeneralModel,
             final VolumeParameterListModel volumeParameterListModel,
-            final PermissionListModel<VolumeListModel> permissionListModel,
-            final VolumeEventListModel volumeEventListModel, final 
VolumeGeoRepListModel geoRepListModel) {
+            final PermissionListModel permissionListModel,
+            final VolumeEventListModel volumeEventListModel,
+            final VolumeGeoRepListModel geoRepListModel,
+            final GlusterVolumeSnapshotListModel snapshotListModel) {
         this.brickListModel = volumeBrickListModel;
         this.geoRepListModel = geoRepListModel;
+        this.snapshotListModel = snapshotListModel;
         setDetailList(volumeGeneralModel, volumeParameterListModel, 
permissionListModel, volumeEventListModel);
         setTitle(ConstantsManager.getInstance().getConstants().volumesTitle());
         setApplicationPlace(WebAdminApplicationPlaces.volumeMainTabPlace);
 
         setDefaultSearchString("Volumes:"); //$NON-NLS-1$
         setSearchString(getDefaultSearchString());
-        setSearchObjects(new String[] { SearchObjects.GLUSTER_VOLUME_OBJ_NAME, 
SearchObjects.GLUSTER_VOLUME_PLU_OBJ_NAME });
+        setSearchObjects(new String[] { SearchObjects.GLUSTER_VOLUME_OBJ_NAME,
+                SearchObjects.GLUSTER_VOLUME_PLU_OBJ_NAME });
         setAvailableInModes(ApplicationMode.GlusterOnly);
 
         setNewVolumeCommand(new UICommand("Create Volume", this)); 
//$NON-NLS-1$
@@ -245,6 +258,7 @@
         list.add(getGeoRepListModel());
         list.add(permissionListModel);
         list.add(volumeEventListModel);
+        list.add(getSnapshotListModel());
         setDetailModels(list);
     }
 
@@ -282,7 +296,7 @@
                             if (dc.getId().equals(cluster.getStoragePoolId()))
                             {
                                 innerVolumeModel.getDataCenter()
-                                        .setItems(new 
ArrayList<StoragePool>(Arrays.asList(new StoragePool[] {dc})));
+                                        .setItems(new 
ArrayList<StoragePool>(Arrays.asList(new StoragePool[] { dc })));
                                 
innerVolumeModel.getDataCenter().setSelectedItem(dc);
                                 break;
                             }
@@ -323,7 +337,7 @@
                 
command.setTitle(ConstantsManager.getInstance().getConstants().ok());
                 command.setIsDefault(true);
                 innerVolumeModel.getCommands().add(command);
-                command = new UICommand("Cancel", volumeListModel);  
//$NON-NLS-1$
+                command = new UICommand("Cancel", volumeListModel); 
//$NON-NLS-1$
                 
command.setTitle(ConstantsManager.getInstance().getConstants().cancel());
                 command.setIsCancel(true);
                 innerVolumeModel.getCommands().add(command);
@@ -408,7 +422,8 @@
 
     @Override
     protected void syncSearch() {
-        SearchParameters tempVar = new SearchParameters(getSearchString(), 
SearchType.GlusterVolume, isCaseSensitiveSearch());
+        SearchParameters tempVar =
+                new SearchParameters(getSearchString(), 
SearchType.GlusterVolume, isCaseSensitiveSearch());
         tempVar.setMaxCount(getSearchPageSize());
         super.syncSearch(VdcQueryType.Search, tempVar);
     }
@@ -417,9 +432,10 @@
     protected void onSelectedItemChanged() {
         super.onSelectedItemChanged();
         updateActionAvailability();
-        GlusterVolumeEntity selectedVolume = 
(GlusterVolumeEntity)provideDetailModelEntity(getSelectedItem());
+        GlusterVolumeEntity selectedVolume = (GlusterVolumeEntity) 
provideDetailModelEntity(getSelectedItem());
         getBrickListModel().setVolumeEntity(selectedVolume);
         getGeoRepListModel().setEntity(selectedVolume);
+        getSnapshotListModel().setEntity(selectedVolume);
     }
 
     @Override
@@ -514,7 +530,7 @@
                 if (volumeEntity.getStatus() == GlusterStatus.DOWN) {
                     return false;
                 }
-                if 
((volumeEntity.getOptionValue("diagnostics.latency-measurement") == null)|| 
(!(volumeEntity.getOptionValue("diagnostics.latency-measurement").equals("on"))))
 {//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+                if 
((volumeEntity.getOptionValue("diagnostics.latency-measurement") == null) || 
(!(volumeEntity.getOptionValue("diagnostics.latency-measurement").equals("on"))))
 {//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
                     return false;
                 }
             }
@@ -550,9 +566,9 @@
     }
 
     private boolean getProfileStatisticsAvailability(List<GlusterVolumeEntity> 
selectedVolumes) {
-        if(selectedVolumes.size() == 1) {
+        if (selectedVolumes.size() == 1) {
             GlusterVolumeEntity selectedVolume = selectedVolumes.get(0);
-            if(selectedVolume.getStatus() == GlusterStatus.UP) {
+            if (selectedVolume.getStatus() == GlusterStatus.UP) {
                 return true;
             }
         }
@@ -571,7 +587,7 @@
         }
         else if (command.equals(getRemoveVolumeCommand())) {
             removeVolume();
-        } else if(command.getName().equals("rebalanceNotStarted")) 
{//$NON-NLS-1$
+        } else if (command.getName().equals("rebalanceNotStarted")) 
{//$NON-NLS-1$
             closeConfirmationWindow();
         }
         else if (command.getName().equals("Cancel")) { //$NON-NLS-1$
@@ -594,27 +610,28 @@
             setConfirmWindow(null);
         } else if (command.getName().equals("CancelRebalanceStatus")) 
{//$NON-NLS-1$
             cancelRebalanceStatus();
-        }else if (command.equals(getOptimizeForVirtStoreCommand())) {
+        } else if (command.equals(getOptimizeForVirtStoreCommand())) {
             optimizeForVirtStore();
         } else if (command.getName().equals("onStop")) {//$NON-NLS-1$
             onStop();
         } else if (command.getName().equals("OnRemove")) { //$NON-NLS-1$
             onRemoveVolume();
-        } else if(command.getName().equals("stop_rebalance_from_status")) 
{//$NON-NLS-1$
+        } else if (command.getName().equals("stop_rebalance_from_status")) 
{//$NON-NLS-1$
             stopRebalance();
-        } else if(command.equals(getStartVolumeProfilingCommand()) || 
command.getName().equals("startProfiling")) {//$NON-NLS-1$
+        } else if (command.equals(getStartVolumeProfilingCommand()) || 
command.getName().equals("startProfiling")) {//$NON-NLS-1$
             startVolumeProfiling();
-        } else if(command.equals(getStopVolumeProfilingCommand()) || 
command.getName().equals("stopProfiling")) {//$NON-NLS-1$
+        } else if (command.equals(getStopVolumeProfilingCommand()) || 
command.getName().equals("stopProfiling")) {//$NON-NLS-1$
             stopVolumeProfiling();
-        } else if(command.equals(getShowVolumeProfileDetailsCommand()) || 
command.getName().equals("showProfileDetails")) {//$NON-NLS-1$
+        } else if (command.equals(getShowVolumeProfileDetailsCommand())
+                || command.getName().equals("showProfileDetails")) 
{//$NON-NLS-1$
             showVolumeProfiling();
-        }else if(command.getName().equalsIgnoreCase("closeProfileStats")) 
{//$NON-NLS-1$
+        } else if (command.getName().equalsIgnoreCase("closeProfileStats")) 
{//$NON-NLS-1$
             setWindow(null);
-        } else 
if(command.getName().equalsIgnoreCase("CancelOptimizeForVirtStore")) 
{//$NON-NLS-1$
+        } else if 
(command.getName().equalsIgnoreCase("CancelOptimizeForVirtStore")) 
{//$NON-NLS-1$
             setConfirmWindow(null);
         } else if 
(command.getName().equalsIgnoreCase("ConfirmOptimiseForVirtStore")) 
{//$NON-NLS-1$
             List<GlusterVolumeEntity> selectedVolumes = new 
ArrayList<GlusterVolumeEntity>();
-            for(Object selectedVolume : getSelectedItems()) {
+            for (Object selectedVolume : getSelectedItems()) {
                 selectedVolumes.add((GlusterVolumeEntity) selectedVolume);
             }
             optimizeVolumesForVirtStore(selectedVolumes);
@@ -648,7 +665,7 @@
     }
 
     private void closeConfirmationWindow() {
-        if(getConfirmWindow() == null) {
+        if (getConfirmWindow() == null) {
             return;
         }
         getConfirmWindow().stopProgress();
@@ -707,20 +724,23 @@
         model.startProgress(null);
 
         final GlusterVolumeEntity volumeEntity = (GlusterVolumeEntity) 
getSelectedItem();
-        GlusterVolumeRebalanceParameters param = new 
GlusterVolumeRebalanceParameters(volumeEntity.getId(), false, false);
+        GlusterVolumeRebalanceParameters param =
+                new GlusterVolumeRebalanceParameters(volumeEntity.getId(), 
false, false);
 
-        
Frontend.getInstance().runAction(VdcActionType.StopRebalanceGlusterVolume, 
param, new IFrontendActionAsyncCallback() {
+        
Frontend.getInstance().runAction(VdcActionType.StopRebalanceGlusterVolume,
+                param,
+                new IFrontendActionAsyncCallback() {
 
-            @Override
-            public void executed(FrontendActionAsyncResult result) {
-                ConfirmationModel localModel = (ConfirmationModel) 
getConfirmWindow();
-                localModel.stopProgress();
-                setConfirmWindow(null);
-                if (result.getReturnValue().getSucceeded()) {
-                    showRebalanceStatus();
-                }
-            }
-        });
+                    @Override
+                    public void executed(FrontendActionAsyncResult result) {
+                        ConfirmationModel localModel = (ConfirmationModel) 
getConfirmWindow();
+                        localModel.stopProgress();
+                        setConfirmWindow(null);
+                        if (result.getReturnValue().getSucceeded()) {
+                            showRebalanceStatus();
+                        }
+                    }
+                });
     }
 
     private void showRebalanceStatus() {
@@ -745,9 +765,11 @@
             public void onSuccess(Object model, Object returnValue) {
                 cModel.stopProgress();
                 VdcQueryReturnValue vdcValue = (VdcQueryReturnValue) 
returnValue;
-                GlusterVolumeTaskStatusEntity rebalanceStatusEntity 
=vdcValue.getReturnValue();
+                GlusterVolumeTaskStatusEntity rebalanceStatusEntity = 
vdcValue.getReturnValue();
                 if ((rebalanceStatusEntity == null) || 
!(vdcValue.getSucceeded())) {
-                    
cModel.setMessage(ConstantsManager.getInstance().getMessages().rebalanceStatusFailed(volumeEntity.getName()));
+                    cModel.setMessage(ConstantsManager.getInstance()
+                            .getMessages()
+                            .rebalanceStatusFailed(volumeEntity.getName()));
                 } else {
                     setConfirmWindow(null);
                     if (getWindow() == null) {
@@ -762,7 +784,8 @@
                         
rebalanceStatusModel.getVolume().setEntity(volumeEntity.getName());
                         
rebalanceStatusModel.getCluster().setEntity(volumeEntity.getVdsGroupName());
 
-                        UICommand stopRebalanceFromStatus = new 
UICommand("stop_rebalance_from_status", VolumeListModel.this);//$NON-NLS-1$
+                        UICommand stopRebalanceFromStatus =
+                                new UICommand("stop_rebalance_from_status", 
VolumeListModel.this);//$NON-NLS-1$
                         
stopRebalanceFromStatus.setTitle(ConstantsManager.getInstance().getConstants().stopRebalance());
                         
rebalanceStatusModel.getCommands().add(stopRebalanceFromStatus);
                         
rebalanceStatusModel.setStopReblanceFromStatus(stopRebalanceFromStatus);
@@ -773,7 +796,7 @@
                         
rebalanceStatusModel.getCommands().add(cancelRebalance);
 
                         rebalanceStatusModel.showStatus(rebalanceStatusEntity);
-                    }else {
+                    } else {
                         VolumeRebalanceStatusModel statusModel = 
(VolumeRebalanceStatusModel) getWindow();
                         
statusModel.getCommands().get(0).setIsExecutionAllowed(false);
                         statusModel.showStatus(rebalanceStatusEntity);
@@ -787,11 +810,14 @@
     }
 
     private void showVolumeProfiling() {
-        if(getSelectedItem() == null || getWindow()!= null) {
+        if (getSelectedItem() == null || getWindow() != null) {
             return;
         }
-        GlusterVolumeEntity selectedVolume = 
(GlusterVolumeEntity)getSelectedItem();
-        VolumeProfileStatisticsModel profileStatsModel = new 
VolumeProfileStatisticsModel(selectedVolume.getClusterId(), 
selectedVolume.getId(), selectedVolume.getName());
+        GlusterVolumeEntity selectedVolume = (GlusterVolumeEntity) 
getSelectedItem();
+        VolumeProfileStatisticsModel profileStatsModel =
+                new VolumeProfileStatisticsModel(selectedVolume.getClusterId(),
+                        selectedVolume.getId(),
+                        selectedVolume.getName());
 
         setWindow(profileStatsModel);
         setHelpTag(HelpTag.volume_profile_statistics);
@@ -813,7 +839,7 @@
         {
             return;
         }
-        ((VolumeRebalanceStatusModel)getWindow()).cancelRefresh();
+        ((VolumeRebalanceStatusModel) getWindow()).cancelRefresh();
         cancel();
     }
 
@@ -829,14 +855,14 @@
         for (Object item : getSelectedItems()) {
             GlusterVolumeEntity volume = (GlusterVolumeEntity) item;
             volumesForOptimiseForVirtStore.add(volume);
-            if(volume.getReplicaCount() != 3) {
+            if (volume.getReplicaCount() != 3) {
                 discouragedConfigVolumeNamesBuilder.append(volume.getName() + 
"\n");//$NON-NLS-1$
                 isDiscouragedVolumePresent = true;
             }
         }
         
discouragedConfigVolumeNamesBuilder.append(constants.optimiseForVirtStoreContinueMessage());
 
-        if(isDiscouragedVolumePresent) {
+        if (isDiscouragedVolumePresent) {
             ConfirmationModel cModel = new ConfirmationModel();
 
             cModel.setMessage(discouragedConfigVolumeNamesBuilder.toString());
@@ -857,7 +883,7 @@
     }
 
     private void optimizeVolumesForVirtStore(final List<GlusterVolumeEntity> 
volumeList) {
-        if(getConfirmWindow() != null) {
+        if (getConfirmWindow() != null) {
             setConfirmWindow(null);
         }
         AsyncQuery aQuery = new AsyncQuery();
@@ -888,20 +914,25 @@
                                 {
                                     Guid volumeId = volume.getId();
 
-                                    list.add(new 
GlusterVolumeOptionParameters(getOption(volumeId, "group", 
optionGroupVirt)));//$NON-NLS-1$
+                                    list.add(new 
GlusterVolumeOptionParameters(getOption(volumeId,
+                                            "group", 
optionGroupVirt)));//$NON-NLS-1$
 
-                                    list.add(new 
GlusterVolumeOptionParameters(getOption(volumeId, "storage.owner-uid", 
optionOwnerUserVirt)));//$NON-NLS-1$
+                                    list.add(new 
GlusterVolumeOptionParameters(getOption(volumeId,
+                                            "storage.owner-uid", 
optionOwnerUserVirt)));//$NON-NLS-1$
 
-                                    list.add(new 
GlusterVolumeOptionParameters(getOption(volumeId, "storage.owner-gid", 
optionOwnerGroupVirt)));//$NON-NLS-1$
+                                    list.add(new 
GlusterVolumeOptionParameters(getOption(volumeId,
+                                            "storage.owner-gid", 
optionOwnerGroupVirt)));//$NON-NLS-1$
 
-                                    final GlusterVolumeOptionEntity 
checkOption = getOption(volumeId, "network.ping-timeout", 
"10");//$NON-NLS-1$//$NON-NLS-2$
-                                    
List<PredicateFilter<GlusterVolumeOptionEntity>> predicaetFilters = 
Collections.singletonList(new PredicateFilter<GlusterVolumeOptionEntity>(new 
Predicate<GlusterVolumeOptionEntity>() {
-                                        @Override
-                                        public boolean 
evaluate(GlusterVolumeOptionEntity obj) {
-                                            return 
obj.getKey().equalsIgnoreCase(checkOption.getKey());
-                                        }
-                                    }));
-                                    if(!isOptionEnabledOnVolume(volume, 
predicaetFilters)) {
+                                    final GlusterVolumeOptionEntity 
checkOption =
+                                            getOption(volumeId, 
"network.ping-timeout", "10");//$NON-NLS-1$//$NON-NLS-2$
+                                    
List<PredicateFilter<GlusterVolumeOptionEntity>> predicaetFilters =
+                                            Collections.singletonList(new 
PredicateFilter<GlusterVolumeOptionEntity>(new 
Predicate<GlusterVolumeOptionEntity>() {
+                                                @Override
+                                                public boolean 
evaluate(GlusterVolumeOptionEntity obj) {
+                                                    return 
obj.getKey().equalsIgnoreCase(checkOption.getKey());
+                                                }
+                                            }));
+                                    if (!isOptionEnabledOnVolume(volume, 
predicaetFilters)) {
                                         list.add(new 
GlusterVolumeOptionParameters(checkOption));//$NON-NLS-1$
                                     }
                                 }
@@ -909,28 +940,33 @@
                             }
                         };
 
-                        AsyncDataProvider.getInstance().getConfigFromCache(new 
GetConfigurationValueParameters(ConfigurationValues.GlusterVolumeOptionOwnerGroupVirtValue,
-                                                                               
                  
AsyncDataProvider.getInstance().getDefaultConfigurationVersion()),
-                                aQueryInner1);
+                        AsyncDataProvider.getInstance()
+                                .getConfigFromCache(new 
GetConfigurationValueParameters(ConfigurationValues.GlusterVolumeOptionOwnerGroupVirtValue,
+                                        
AsyncDataProvider.getInstance().getDefaultConfigurationVersion()),
+                                        aQueryInner1);
                     }
                 };
-                AsyncDataProvider.getInstance().getConfigFromCache(new 
GetConfigurationValueParameters(ConfigurationValues.GlusterVolumeOptionOwnerUserVirtValue,
-                                                                               
          AsyncDataProvider.getInstance().getDefaultConfigurationVersion()),
-                        aQueryInner);
+                AsyncDataProvider.getInstance()
+                        .getConfigFromCache(new 
GetConfigurationValueParameters(ConfigurationValues.GlusterVolumeOptionOwnerUserVirtValue,
+                                
AsyncDataProvider.getInstance().getDefaultConfigurationVersion()),
+                                aQueryInner);
             }
         };
-        AsyncDataProvider.getInstance().getConfigFromCache(new 
GetConfigurationValueParameters(ConfigurationValues.GlusterVolumeOptionGroupVirtValue,
-                                                                               
  AsyncDataProvider.getInstance().getDefaultConfigurationVersion()),
-                aQuery);
+        AsyncDataProvider.getInstance()
+                .getConfigFromCache(new 
GetConfigurationValueParameters(ConfigurationValues.GlusterVolumeOptionGroupVirtValue,
+                        
AsyncDataProvider.getInstance().getDefaultConfigurationVersion()),
+                        aQuery);
     }
 
-    private boolean isOptionEnabledOnVolume(GlusterVolumeEntity volume, 
List<PredicateFilter<GlusterVolumeOptionEntity>> predicates) {
-        List<GlusterVolumeOptionEntity> volumeOptionsEnabled = new 
ArrayList<GlusterVolumeOptionEntity>(volume.getOptions());
+    private boolean isOptionEnabledOnVolume(GlusterVolumeEntity volume,
+            List<PredicateFilter<GlusterVolumeOptionEntity>> predicates) {
+        List<GlusterVolumeOptionEntity> volumeOptionsEnabled =
+                new ArrayList<GlusterVolumeOptionEntity>(volume.getOptions());
         List<GlusterVolumeOptionEntity> filteredOptions = volumeOptionsEnabled;
-        for(PredicateFilter<GlusterVolumeOptionEntity> predicate  : 
predicates) {
-             filteredOptions = ListUtils.filter(filteredOptions, predicate);
+        for (PredicateFilter<GlusterVolumeOptionEntity> predicate : 
predicates) {
+            filteredOptions = ListUtils.filter(filteredOptions, predicate);
         }
-        if(filteredOptions.size() > 0) {
+        if (filteredOptions.size() > 0) {
             return true;
         }
         return false;
@@ -1027,7 +1063,6 @@
         
Frontend.getInstance().runMultipleAction(VdcActionType.StartGlusterVolume, 
list);
     }
 
-
     private void onCreateVolume() {
         VolumeModel volumeModel = (VolumeModel) getWindow();
 
@@ -1088,14 +1123,17 @@
         CreateGlusterVolumeParameters parameter =
                 new CreateGlusterVolumeParameters(volume, 
volumeModel.isForceAddBricks());
 
-        Frontend.getInstance().runAction(VdcActionType.CreateGlusterVolume, 
parameter, new IFrontendActionAsyncCallback() {
+        Frontend.getInstance().runAction(VdcActionType.CreateGlusterVolume,
+                parameter,
+                new IFrontendActionAsyncCallback() {
 
-            @Override
-            public void executed(FrontendActionAsyncResult result) {
-                VolumeListModel localModel = (VolumeListModel) 
result.getState();
-                localModel.postOnCreateVolume(result.getReturnValue(), volume);
-            }
-        }, this);
+                    @Override
+                    public void executed(FrontendActionAsyncResult result) {
+                        VolumeListModel localModel = (VolumeListModel) 
result.getState();
+                        localModel.postOnCreateVolume(result.getReturnValue(), 
volume);
+                    }
+                },
+                this);
     }
 
     public void postOnCreateVolume(VdcReturnValueBase returnValue, 
GlusterVolumeEntity volume)
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/place/WebAdminApplicationPlaces.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/place/WebAdminApplicationPlaces.java
index 776698c..459b9cb 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/place/WebAdminApplicationPlaces.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/place/WebAdminApplicationPlaces.java
@@ -311,6 +311,8 @@
 
     public static final String volumeGeoRepSubTabPlace = volumeMainTabPlace + 
SUB_TAB_PREFIX + "geo_rep"; //$NON-NLS-1$
 
+    public static final String volumeSnapshotSubTabPlace = volumeMainTabPlace 
+ SUB_TAB_PREFIX + "volume_snapshots"; //$NON-NLS-1$
+
     // Disk
 
     public static final String diskGeneralSubTabPlace = diskMainTabPlace + 
SUB_TAB_PREFIX + "general"; //$NON-NLS-1$
@@ -322,7 +324,6 @@
     public static final String diskStorageSubTabPlace = diskMainTabPlace + 
SUB_TAB_PREFIX + "storage"; //$NON-NLS-1$
 
     public static final String diskPermissionSubTabPlace = diskMainTabPlace + 
SUB_TAB_PREFIX + "permissions"; //$NON-NLS-1$
-
 
     // Network
     public static final String networkGeneralSubTabPlace = networkMainTabPlace 
+ SUB_TAB_PREFIX + "general"; //$NON-NLS-1$
@@ -347,7 +348,6 @@
 
     public static final String networkPermissionSubTabPlace = 
networkMainTabPlace + SUB_TAB_PREFIX
             + "permissions"; //$NON-NLS-1$
-
 
     // Provider
     public static final String providerGeneralSubTabPlace = 
providerMainTabPlace + SUB_TAB_PREFIX + "general"; //$NON-NLS-1$
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/resources/org/ovirt/engine/ui/uicompat/LocalizedEnums.properties
 
b/frontend/webadmin/modules/uicompat/src/main/resources/org/ovirt/engine/ui/uicompat/LocalizedEnums.properties
index f50b0f9..091004c 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/resources/org/ovirt/engine/ui/uicompat/LocalizedEnums.properties
+++ 
b/frontend/webadmin/modules/uicompat/src/main/resources/org/ovirt/engine/ui/uicompat/LocalizedEnums.properties
@@ -217,6 +217,8 @@
 AuditLogType___GLUSTER_BRICK_STATUS_CHANGED=Detected change in status of brick
 AuditLogType___GLUSTER_VOLUME_REBALANCE_NOT_FOUND_FROM_CLI=Could not find 
information for rebalance on volume from CLI. Marking it as unknown.
 AuditLogType___REMOVE_GLUSTER_VOLUME_BRICKS_NOT_FOUND_FROM_CLI=Could not find 
information for remove brick on volume from CLI. Marking it as unknown.
+AuditLogType___GLUSTER_VOLUME_SNAPSHOT_CREATED=Snapshot created for the volume
+AuditLogType___GLUSTER_VOLUME_SNAPSHOT_CREATE_FAILED=Failed create snapshot 
for the volume
 
 
 VdcActionType___ActivateVds=Activate Host
@@ -335,6 +337,7 @@
 VdcActionType___GlusterVolumeRemoveBricks=Remove Gluster Volume Bricks
 VdcActionType___AddBricksToGlusterVolume=Add Brick To Gluster Volume
 VdcActionType___StartRebalanceGlusterVolume=Start Rebalance Gluster Volume
+VdcActionType___CreateGlusterVolumeSnapshot=Create Gluster Volume Snapshot
 VdcActionType___ReplaceGlusterVolumeBrick=Start Gluster Volume Replace Brick
 VdcActionType___GlusterHostAdd=Add Gluster server
 vdcActionType___StartGlusterVolumeProfile=Start Gluster Volume Profile
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationConstants.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationConstants.java
index 09f06f1..b60f04a 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationConstants.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationConstants.java
@@ -106,6 +106,9 @@
     @DefaultStringValue("Geo-Replication")
     String volumeGeoRepSubTabLabel();
 
+    @DefaultStringValue("Snapshots")
+    String volumeSnapshotSubTabLabel();
+
     @DefaultStringValue("Destination Host")
     String volumeSubTabGeoRepSlaveClusterHostColumn();
 
@@ -822,7 +825,8 @@
     @DefaultStringValue("CPU Threads")
     String clusterPopupCpuThreadsPanelTitle();
 
-    @DefaultStringValue("Allow guests to use host threads as virtual CPU 
cores, utilizing AMD Clustered MultiThreading or Intel" +
+    @DefaultStringValue("Allow guests to use host threads as virtual CPU 
cores, utilizing AMD Clustered MultiThreading or Intel"
+            +
             " Hyper-Threading technology on the virtualization host. Enabling 
this option may be useful for less" +
             " CPU-intensive workloads, or to run guests with CPU 
configurations that would otherwise be restricted.")
     String clusterPopupCpuThreadsInfo();
@@ -2810,6 +2814,9 @@
     @DefaultStringValue("Transport Types")
     String transportTypesVolume();
 
+    @DefaultStringValue("Maximum no of snapshots")
+    String maxNumberOfSnapshotsVolume();
+
     @DefaultStringValue("Activities")
     String activitiesOnVolume();
 
@@ -3652,7 +3659,7 @@
     @DefaultStringValue("Remove brick in progress but status unknown. Unable 
to fetch the status at the moment.")
     String removeBrickStatusUnknown();
 
-    //Volume Rebalance Status Table Columns
+    // Volume Rebalance Status Table Columns
     @DefaultStringValue("Host")
     String rebalanceSessionHost();
 
@@ -3816,11 +3823,10 @@
     @DefaultStringValue("Disk Snapshots")
     String snapshotsLabel();
 
-
     @DefaultStringValue("Attached by label")
     String attachedByLabel();
 
-    //Gluster Volume Profiling
+    // Gluster Volume Profiling
     @DefaultStringValue("File operation")
     String fileOperation();
 
@@ -3973,4 +3979,17 @@
 
     @DefaultStringValue("NUMA Support")
     String numaSupport();
+
+    // Volume snapshots
+    @DefaultStringValue("Name")
+    String volumeSnapshotName();
+
+    @DefaultStringValue("Description")
+    String volumeSnapshotDescription();
+
+    @DefaultStringValue("Creation Time")
+    String volumeSnapshotCreationTime();
+
+    @DefaultStringValue("No of snapshots")
+    String noOfSnapshotsLabel();
 }
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationTemplates.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationTemplates.java
index 0dd4ebd..c8bf4d3 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationTemplates.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationTemplates.java
@@ -153,6 +153,9 @@
             "</tr> </table>")
     SafeHtml volumeBrickStatusTemplate(SafeHtml upImage, int upCount, SafeHtml 
downImage, int downCount);
 
+    @Template("<div style='line-height: 100%; text-align: center; 
vertical-align: middle;'>{0}</div>")
+    SafeHtml volumeSnapshotsStatusTemplate(int snapshotCount);
+
     @Template("<div style='line-height: 100%; text-align: center; 
vertical-align: middle; border: solid 1px transparent; '>{0}</div>")
     SafeHtml volumeActivityMenu(SafeHtml statusImage);
 
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/ClientGinjectorExtension.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/ClientGinjectorExtension.java
index cb8f9cd..7b505cf 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/ClientGinjectorExtension.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/ClientGinjectorExtension.java
@@ -26,6 +26,7 @@
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterServerService;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeOptionEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
 import org.ovirt.engine.core.common.businessentities.network.ExternalSubnet;
 import org.ovirt.engine.core.common.businessentities.network.HostNetworkQos;
 import org.ovirt.engine.core.common.businessentities.network.Network;
@@ -78,6 +79,7 @@
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeGeneralModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeGeoRepListModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeParameterListModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.gluster.GlusterVolumeSnapshotListModel;
 import org.ovirt.engine.ui.uicommonweb.models.hosts.HostBricksListModel;
 import org.ovirt.engine.ui.uicommonweb.models.hosts.HostEventListModel;
 import org.ovirt.engine.ui.uicommonweb.models.hosts.HostGeneralModel;
@@ -389,6 +391,8 @@
 
     SearchableDetailModelProvider<GlusterGeoRepSession, VolumeListModel, 
VolumeGeoRepListModel> getSubTabVolumeGeoRepModelProvider();
 
+    SearchableDetailModelProvider<GlusterVolumeSnapshotEntity, 
VolumeListModel, GlusterVolumeSnapshotListModel> 
getSubTabVolumeSnapshotModelProvider();
+
     // Disk
 
     DetailModelProvider<DiskListModel, DiskGeneralModel> 
getSubTabDiskGeneralModelProvider();
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
index 5284304..b8d2cf6 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
@@ -169,6 +169,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.gluster.SubTabVolumeGeoRepPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.gluster.SubTabVolumeParameterPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.gluster.SubTabVolumePermissionPresenter;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.gluster.SubTabGlusterVolumeSnapshotPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.gluster.VolumeSubTabPanelPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.host.HostSubTabPanelPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.host.SubTabHostBrickPresenter;
@@ -414,6 +415,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.gluster.SubTabVolumeGeoRepView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.gluster.SubTabVolumeParameterView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.gluster.SubTabVolumePermissionView;
+import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.gluster.SubTabGlusterVolumeSnapshotView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.gluster.VolumeSubTabPanelView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.host.HostSubTabPanelView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.host.SubTabHostBrickView;
@@ -866,7 +868,6 @@
                 SubTabVirtualMachineEventPresenter.ViewDef.class,
                 SubTabVirtualMachineEventView.class,
                 SubTabVirtualMachineEventPresenter.ProxyDef.class);
-
 
         // Pool
         bindPresenter(PoolSubTabPanelPresenter.class,
@@ -1395,7 +1396,7 @@
                 QuotaPopupPresenterWidget.ViewDef.class,
                 QuotaPopupView.class);
 
-        //Network QoS
+        // Network QoS
         bindPresenterWidget(NetworkQoSPopupPresenterWidget.class,
                 NetworkQoSPopupPresenterWidget.ViewDef.class,
                 NetworkQoSPopupView.class);
@@ -1462,6 +1463,11 @@
                 SubTabVolumeEventView.class,
                 SubTabVolumeEventPresenter.ProxyDef.class);
 
+        bindPresenter(SubTabGlusterVolumeSnapshotPresenter.class,
+                SubTabGlusterVolumeSnapshotPresenter.ViewDef.class,
+                SubTabGlusterVolumeSnapshotView.class,
+                SubTabGlusterVolumeSnapshotPresenter.ProxyDef.class);
+
         bindPresenterWidget(AddBrickPopupPresenterWidget.class,
                 AddBrickPopupPresenterWidget.ViewDef.class,
                 AddBrickPopupView.class);
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VolumeModule.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VolumeModule.java
index 87f7789..70b8507 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VolumeModule.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VolumeModule.java
@@ -6,6 +6,7 @@
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterGeoRepSession;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeOptionEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
 import 
org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget;
 import 
org.ovirt.engine.ui.common.presenter.popup.DefaultConfirmationPopupPresenterWidget;
 import 
org.ovirt.engine.ui.common.presenter.popup.RemoveConfirmationPopupPresenterWidget;
@@ -20,6 +21,7 @@
 import org.ovirt.engine.ui.uicommonweb.models.ConfirmationModel;
 import org.ovirt.engine.ui.uicommonweb.models.Model;
 import org.ovirt.engine.ui.uicommonweb.models.configure.PermissionListModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.gluster.GlusterVolumeSnapshotListModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeBrickListModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeEventListModel;
 import org.ovirt.engine.ui.uicommonweb.models.gluster.VolumeGeneralModel;
@@ -60,36 +62,40 @@
             final Provider<VolumeListModel> modelProvider,
             final Provider<CommonModel> commonModelProvider) {
         MainTabModelProvider<GlusterVolumeEntity, VolumeListModel> result =
-                new MainTabModelProvider<GlusterVolumeEntity, 
VolumeListModel>(eventBus, defaultConfirmPopupProvider,
+                new MainTabModelProvider<GlusterVolumeEntity, 
VolumeListModel>(eventBus,
+                        defaultConfirmPopupProvider,
                         commonModelProvider) {
-            @Override
-            public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> 
getModelPopup(VolumeListModel source,
-                    UICommand lastExecutedCommand, Model windowModel) {
-                if (lastExecutedCommand == getModel().getNewVolumeCommand()) {
-                    return popupProvider.get();
-                }
-                else if (lastExecutedCommand == 
getModel().getStatusRebalanceCommand() || 
lastExecutedCommand.getName().equals("onStopRebalance")) {//$NON-NLS-1$
-                    return rebalanceStatusPopupProvider.get();
-                }
-                else if(lastExecutedCommand == 
getModel().getShowVolumeProfileDetailsCommand() || 
lastExecutedCommand.getName().equals("showProfileDetails")) {//$NON-NLS-1$
-                    return volumeProfileStatsPopupProvider.get();
-                }
-                else {
-                    return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
-                }
-            }
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
Model, ?> getModelPopup(VolumeListModel source,
+                            UICommand lastExecutedCommand,
+                            Model windowModel) {
+                        if (lastExecutedCommand == 
getModel().getNewVolumeCommand()) {
+                            return popupProvider.get();
+                        }
+                        else if (lastExecutedCommand == 
getModel().getStatusRebalanceCommand()
+                                || 
lastExecutedCommand.getName().equals("onStopRebalance")) {//$NON-NLS-1$
+                            return rebalanceStatusPopupProvider.get();
+                        }
+                        else if (lastExecutedCommand == 
getModel().getShowVolumeProfileDetailsCommand()
+                                || 
lastExecutedCommand.getName().equals("showProfileDetails")) {//$NON-NLS-1$
+                            return volumeProfileStatsPopupProvider.get();
+                        }
+                        else {
+                            return super.getModelPopup(source, 
lastExecutedCommand, windowModel);
+                        }
+                    }
 
-            @Override
-            public AbstractModelBoundPopupPresenterWidget<? extends 
ConfirmationModel, ?> getConfirmModelPopup(VolumeListModel source,
-                    UICommand lastExecutedCommand) {
-                if (lastExecutedCommand == getModel().getStopCommand()
-                        || lastExecutedCommand == 
getModel().getRemoveVolumeCommand()) {
-                    return removeConfirmPopupProvider.get();
-                } else {
-                    return super.getConfirmModelPopup(source, 
lastExecutedCommand);
-                }
-            }
-        };
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
ConfirmationModel, ?> getConfirmModelPopup(VolumeListModel source,
+                            UICommand lastExecutedCommand) {
+                        if (lastExecutedCommand == getModel().getStopCommand()
+                                || lastExecutedCommand == 
getModel().getRemoveVolumeCommand()) {
+                            return removeConfirmPopupProvider.get();
+                        } else {
+                            return super.getConfirmModelPopup(source, 
lastExecutedCommand);
+                        }
+                    }
+                };
         result.setModelProvider(modelProvider);
         return result;
     }
@@ -108,39 +114,67 @@
             final Provider<VolumeBrickListModel> modelProvider) {
         SearchableDetailTabModelProvider<GlusterBrickEntity, VolumeListModel, 
VolumeBrickListModel> result =
                 new SearchableDetailTabModelProvider<GlusterBrickEntity, 
VolumeListModel, VolumeBrickListModel>(
-                eventBus, defaultConfirmPopupProvider) {
-            @Override
-            public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> 
getModelPopup(VolumeBrickListModel source,
-                    UICommand lastExecutedCommand,
-                    Model windowModel) {
-                if (lastExecutedCommand == getModel().getAddBricksCommand()) {
-                    return addBrickPopupProvider.get();
-                } else if (lastExecutedCommand == 
getModel().getRemoveBricksCommand()) {
-                    return removeBrickPopupProvider.get();
-                } else if (lastExecutedCommand == 
getModel().getStatusRemoveBricksCommand()) {
-                    return removeBricksStatusPopupProvider.get();
-                }else if 
(lastExecutedCommand.getName().equals("OnStopRemoveBricks")) {  //$NON-NLS-1$
-                    return removeBricksStatusPopupProvider.get();
-                } else if (lastExecutedCommand == 
getModel().getReplaceBrickCommand()) {
-                    return replaceBrickPopupProvider.get();
-                } else if (lastExecutedCommand == 
getModel().getBrickAdvancedDetailsCommand()) {
-                    return brickDetailsPopupProvider.get();
-                } else {
-                    return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
-                }
-            }
+                        eventBus, defaultConfirmPopupProvider) {
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
Model, ?> getModelPopup(VolumeBrickListModel source,
+                            UICommand lastExecutedCommand,
+                            Model windowModel) {
+                        if (lastExecutedCommand == 
getModel().getAddBricksCommand()) {
+                            return addBrickPopupProvider.get();
+                        } else if (lastExecutedCommand == 
getModel().getRemoveBricksCommand()) {
+                            return removeBrickPopupProvider.get();
+                        } else if (lastExecutedCommand == 
getModel().getStatusRemoveBricksCommand()) {
+                            return removeBricksStatusPopupProvider.get();
+                        } else if 
(lastExecutedCommand.getName().equals("OnStopRemoveBricks")) { //$NON-NLS-1$
+                            return removeBricksStatusPopupProvider.get();
+                        } else if (lastExecutedCommand == 
getModel().getReplaceBrickCommand()) {
+                            return replaceBrickPopupProvider.get();
+                        } else if (lastExecutedCommand == 
getModel().getBrickAdvancedDetailsCommand()) {
+                            return brickDetailsPopupProvider.get();
+                        } else {
+                            return super.getModelPopup(source, 
lastExecutedCommand, windowModel);
+                        }
+                    }
 
-            @Override
-            public AbstractModelBoundPopupPresenterWidget<? extends 
ConfirmationModel, ?> getConfirmModelPopup(VolumeBrickListModel source,
-                    UICommand lastExecutedCommand) {
-                if (lastExecutedCommand == 
getModel().getRemoveBricksCommand()) {
-                    return removeConfirmPopupProvider.get();
-                } else {
-                    return super.getConfirmModelPopup(source, 
lastExecutedCommand);
-                }
-            }
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
ConfirmationModel, ?> getConfirmModelPopup(VolumeBrickListModel source,
+                            UICommand lastExecutedCommand) {
+                        if (lastExecutedCommand == 
getModel().getRemoveBricksCommand()) {
+                            return removeConfirmPopupProvider.get();
+                        } else {
+                            return super.getConfirmModelPopup(source, 
lastExecutedCommand);
+                        }
+                    }
 
-        };
+                };
+        result.setMainModelProvider(mainModelProvider);
+        result.setModelProvider(modelProvider);
+        return result;
+    }
+
+    @Provides
+    @Singleton
+    public SearchableDetailModelProvider<GlusterVolumeSnapshotEntity, 
VolumeListModel, GlusterVolumeSnapshotListModel> 
getVolumeSnapshotListProvider(EventBus eventBus,
+            Provider<DefaultConfirmationPopupPresenterWidget> 
defaultConfirmPopupProvider,
+            final Provider<VolumeListModel> mainModelProvider,
+            final Provider<GlusterVolumeSnapshotListModel> modelProvider) {
+        SearchableDetailTabModelProvider<GlusterVolumeSnapshotEntity, 
VolumeListModel, GlusterVolumeSnapshotListModel> result =
+                new 
SearchableDetailTabModelProvider<GlusterVolumeSnapshotEntity, VolumeListModel, 
GlusterVolumeSnapshotListModel>(
+                        eventBus, defaultConfirmPopupProvider) {
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
Model, ?> getModelPopup(GlusterVolumeSnapshotListModel source,
+                            UICommand lastExecutedCommand,
+                            Model windowModel) {
+                        return super.getModelPopup(source, 
lastExecutedCommand, windowModel);
+                    }
+
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
ConfirmationModel, ?> getConfirmModelPopup(GlusterVolumeSnapshotListModel 
source,
+                            UICommand lastExecutedCommand) {
+                        return super.getConfirmModelPopup(source, 
lastExecutedCommand);
+                    }
+
+                };
         result.setMainModelProvider(mainModelProvider);
         result.setModelProvider(modelProvider);
         return result;
@@ -156,20 +190,20 @@
             final Provider<VolumeParameterListModel> modelProvider) {
         SearchableDetailTabModelProvider<GlusterVolumeOptionEntity, 
VolumeListModel, VolumeParameterListModel> result =
                 new 
SearchableDetailTabModelProvider<GlusterVolumeOptionEntity, VolumeListModel, 
VolumeParameterListModel>(
-                eventBus, defaultConfirmPopupProvider) {
-            @Override
-            public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> 
getModelPopup(VolumeParameterListModel source,
-                    UICommand lastExecutedCommand,
-                    Model windowModel) {
-                if (lastExecutedCommand == 
getModel().getAddParameterCommand()) {
-                    return addParameterPopupProvider.get();
-                } else if (lastExecutedCommand == 
getModel().getEditParameterCommand()) {
-                    return editParameterPopupProvider.get();
-                } else {
-                    return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
-                }
-            }
-        };
+                        eventBus, defaultConfirmPopupProvider) {
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
Model, ?> getModelPopup(VolumeParameterListModel source,
+                            UICommand lastExecutedCommand,
+                            Model windowModel) {
+                        if (lastExecutedCommand == 
getModel().getAddParameterCommand()) {
+                            return addParameterPopupProvider.get();
+                        } else if (lastExecutedCommand == 
getModel().getEditParameterCommand()) {
+                            return editParameterPopupProvider.get();
+                        } else {
+                            return super.getModelPopup(source, 
lastExecutedCommand, windowModel);
+                        }
+                    }
+                };
         result.setMainModelProvider(mainModelProvider);
         result.setModelProvider(modelProvider);
         return result;
@@ -184,18 +218,18 @@
             final Provider<VolumeEventListModel> modelProvider) {
         SearchableDetailTabModelProvider<AuditLog, VolumeListModel, 
VolumeEventListModel> result =
                 new SearchableDetailTabModelProvider<AuditLog, 
VolumeListModel, VolumeEventListModel>(
-                eventBus, defaultConfirmPopupProvider) {
-            @Override
-            public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> 
getModelPopup(VolumeEventListModel source,
-                    UICommand lastExecutedCommand,
-                    Model windowModel) {
-                if 
(lastExecutedCommand.equals(getModel().getDetailsCommand())) {
-                    return eventPopupProvider.get();
-                } else {
-                    return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
-                }
-            }
-        };
+                        eventBus, defaultConfirmPopupProvider) {
+                    @Override
+                    public AbstractModelBoundPopupPresenterWidget<? extends 
Model, ?> getModelPopup(VolumeEventListModel source,
+                            UICommand lastExecutedCommand,
+                            Model windowModel) {
+                        if 
(lastExecutedCommand.equals(getModel().getDetailsCommand())) {
+                            return eventPopupProvider.get();
+                        } else {
+                            return super.getModelPopup(source, 
lastExecutedCommand, windowModel);
+                        }
+                    }
+                };
         result.setMainModelProvider(mainModelProvider);
         result.setModelProvider(modelProvider);
         return result;
@@ -208,18 +242,25 @@
         bind(VolumeBrickListModel.class).in(Singleton.class);
         bind(VolumeParameterListModel.class).in(Singleton.class);
         bind(VolumeEventListModel.class).in(Singleton.class);
-        bind(new 
TypeLiteral<PermissionListModel<VolumeListModel>>(){}).in(Singleton.class);
+        bind(new TypeLiteral<PermissionListModel<VolumeListModel>>() 
{}).in(Singleton.class);
+        bind(GlusterVolumeSnapshotListModel.class).in(Singleton.class);
 
         // Form Detail Models
-        bind(new TypeLiteral<DetailModelProvider<VolumeListModel, 
VolumeGeneralModel>>(){})
-            .to(new TypeLiteral<DetailTabModelProvider<VolumeListModel, 
VolumeGeneralModel>>(){}).in(Singleton.class);
+        bind(new TypeLiteral<DetailModelProvider<VolumeListModel, 
VolumeGeneralModel>>() {
+        })
+                .to(new TypeLiteral<DetailTabModelProvider<VolumeListModel, 
VolumeGeneralModel>>() {
+                }).in(Singleton.class);
         // Search-able Detail Models
-        bind(new 
TypeLiteral<SearchableDetailModelProvider<GlusterGeoRepSession, 
VolumeListModel, VolumeGeoRepListModel>>(){})
-           .to(new 
TypeLiteral<SearchableDetailTabModelProvider<GlusterGeoRepSession, 
VolumeListModel, VolumeGeoRepListModel>>(){})
-           .in(Singleton.class);
+        bind(new 
TypeLiteral<SearchableDetailModelProvider<GlusterGeoRepSession, 
VolumeListModel, VolumeGeoRepListModel>>() {
+        })
+                .to(new 
TypeLiteral<SearchableDetailTabModelProvider<GlusterGeoRepSession, 
VolumeListModel, VolumeGeoRepListModel>>() {
+                })
+                .in(Singleton.class);
         // Permission Detail Model
-        bind(new TypeLiteral<SearchableDetailModelProvider<Permissions, 
VolumeListModel, PermissionListModel<VolumeListModel>>>(){})
-           .to(new 
TypeLiteral<PermissionModelProvider<VolumeListModel>>(){}).in(Singleton.class);
+        bind(new TypeLiteral<SearchableDetailModelProvider<Permissions, 
VolumeListModel, PermissionListModel<VolumeListModel>>>() {
+        })
+                .to(new 
TypeLiteral<PermissionModelProvider<VolumeListModel>>() {
+                }).in(Singleton.class);
     }
 
 }
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/gluster/SubTabGlusterVolumeSnapshotPresenter.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/gluster/SubTabGlusterVolumeSnapshotPresenter.java
new file mode 100644
index 0000000..7220eda
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/gluster/SubTabGlusterVolumeSnapshotPresenter.java
@@ -0,0 +1,58 @@
+package org.ovirt.engine.ui.webadmin.section.main.presenter.tab.gluster;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+import org.ovirt.engine.ui.common.place.PlaceRequestFactory;
+import org.ovirt.engine.ui.common.presenter.AbstractSubTabPresenter;
+import org.ovirt.engine.ui.common.uicommon.model.SearchableDetailModelProvider;
+import org.ovirt.engine.ui.common.widget.tab.ModelBoundTabData;
+import 
org.ovirt.engine.ui.uicommonweb.models.gluster.GlusterVolumeSnapshotListModel;
+import org.ovirt.engine.ui.uicommonweb.models.volumes.VolumeListModel;
+import org.ovirt.engine.ui.uicommonweb.place.WebAdminApplicationPlaces;
+import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.VolumeSelectionChangeEvent;
+
+import com.google.gwt.event.shared.EventBus;
+import com.google.inject.Inject;
+import com.gwtplatform.mvp.client.TabData;
+import com.gwtplatform.mvp.client.annotations.NameToken;
+import com.gwtplatform.mvp.client.annotations.ProxyCodeSplit;
+import com.gwtplatform.mvp.client.annotations.ProxyEvent;
+import com.gwtplatform.mvp.client.annotations.TabInfo;
+import com.gwtplatform.mvp.client.proxy.PlaceManager;
+import com.gwtplatform.mvp.client.proxy.TabContentProxyPlace;
+import com.gwtplatform.mvp.shared.proxy.PlaceRequest;
+
+public class SubTabGlusterVolumeSnapshotPresenter extends 
AbstractSubTabPresenter<GlusterVolumeEntity, VolumeListModel, 
GlusterVolumeSnapshotListModel, SubTabGlusterVolumeSnapshotPresenter.ViewDef, 
SubTabGlusterVolumeSnapshotPresenter.ProxyDef> {
+    @TabInfo(container = VolumeSubTabPanelPresenter.class)
+    static TabData getTabData(ApplicationConstants applicationConstants,
+            SearchableDetailModelProvider<GlusterVolumeSnapshotEntity, 
VolumeListModel, GlusterVolumeSnapshotListModel> modelProvider) {
+        return new 
ModelBoundTabData(applicationConstants.volumeSnapshotSubTabLabel(), 5, 
modelProvider);
+    }
+
+    @Inject
+    public SubTabGlusterVolumeSnapshotPresenter(EventBus eventBus, ViewDef 
view, ProxyDef proxy,
+            PlaceManager placeManager,
+            SearchableDetailModelProvider<GlusterVolumeSnapshotEntity, 
VolumeListModel, GlusterVolumeSnapshotListModel> modelProvider) {
+        super(eventBus, view, proxy, placeManager, modelProvider,
+                VolumeSubTabPanelPresenter.TYPE_SetTabContent);
+    }
+
+    @ProxyCodeSplit
+    @NameToken(WebAdminApplicationPlaces.volumeSnapshotSubTabPlace)
+    public interface ProxyDef extends 
TabContentProxyPlace<SubTabGlusterVolumeSnapshotPresenter> {
+    }
+
+    public interface ViewDef extends 
AbstractSubTabPresenter.ViewDef<GlusterVolumeEntity> {
+    }
+
+    @Override
+    protected PlaceRequest getMainTabRequest() {
+        return 
PlaceRequestFactory.get(WebAdminApplicationPlaces.volumeMainTabPlace);
+    }
+
+    @ProxyEvent
+    public void onVolumeSelectionChange(VolumeSelectionChangeEvent event) {
+        updateMainTabSelection(event.getSelectedItems());
+    }
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVolumeView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVolumeView.java
index dd7087b..a95b7cb 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVolumeView.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVolumeView.java
@@ -30,6 +30,7 @@
 import 
org.ovirt.engine.ui.webadmin.widget.table.column.VolumeActivityStatusColumn;
 import 
org.ovirt.engine.ui.webadmin.widget.table.column.VolumeBrickStatusColumn;
 import org.ovirt.engine.ui.webadmin.widget.table.column.VolumeCapacityCell;
+import 
org.ovirt.engine.ui.webadmin.widget.table.column.GlusterVolumeSnapshotsCountColumn;
 import org.ovirt.engine.ui.webadmin.widget.table.column.VolumeStatusColumn;
 import org.ovirt.engine.ui.webadmin.widget.table.column.VolumeTaskWaitingCell;
 
@@ -150,6 +151,8 @@
                 constants.activitiesOnVolume(),
                 "100px"); //$NON-NLS-1$
 
+        getTable().addColumn(new GlusterVolumeSnapshotsCountColumn(), 
constants.noOfSnapshotsLabel(), "100px"); //$NON-NLS-1$
+
         getTable().addActionButton(new 
WebAdminButtonDefinition<GlusterVolumeEntity>(constants.newVolume()) {
             @Override
             protected UICommand resolveCommand() {
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabGlusterVolumeSnapshotView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabGlusterVolumeSnapshotView.java
new file mode 100644
index 0000000..79f20a5
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabGlusterVolumeSnapshotView.java
@@ -0,0 +1,76 @@
+package org.ovirt.engine.ui.webadmin.section.main.view.tab.gluster;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+import org.ovirt.engine.ui.common.idhandler.ElementIdHandler;
+import org.ovirt.engine.ui.common.uicommon.model.SearchableDetailModelProvider;
+import org.ovirt.engine.ui.common.widget.table.column.TextColumnWithTooltip;
+import 
org.ovirt.engine.ui.uicommonweb.models.gluster.GlusterVolumeSnapshotListModel;
+import org.ovirt.engine.ui.uicommonweb.models.volumes.VolumeListModel;
+import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.gluster.SubTabGlusterVolumeSnapshotPresenter;
+import org.ovirt.engine.ui.webadmin.section.main.view.AbstractSubTabTableView;
+import 
org.ovirt.engine.ui.webadmin.widget.table.column.GlusterVolumeSnapshotStatusColumn;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.inject.Inject;
+
+public class SubTabGlusterVolumeSnapshotView extends 
AbstractSubTabTableView<GlusterVolumeEntity, GlusterVolumeSnapshotEntity, 
VolumeListModel, GlusterVolumeSnapshotListModel> implements 
SubTabGlusterVolumeSnapshotPresenter.ViewDef {
+
+    interface ViewIdHandler extends 
ElementIdHandler<SubTabGlusterVolumeSnapshotView> {
+        ViewIdHandler idHandler = GWT.create(ViewIdHandler.class);
+    }
+
+    @Inject
+    public 
SubTabGlusterVolumeSnapshotView(SearchableDetailModelProvider<GlusterVolumeSnapshotEntity,
 VolumeListModel, GlusterVolumeSnapshotListModel> modelProvider,
+            ApplicationConstants constants) {
+        super(modelProvider);
+        initTable(constants);
+        initWidget(getTable());
+    }
+
+    @Override
+    protected void generateIds() {
+        ViewIdHandler.idHandler.generateAndSetIds(this);
+    }
+
+    void initTable(ApplicationConstants constants) {
+        getTable().enableColumnResizing();
+
+        GlusterVolumeSnapshotStatusColumn snapshotStatusColumn = new 
GlusterVolumeSnapshotStatusColumn();
+        snapshotStatusColumn.makeSortable();
+        getTable().addColumn(snapshotStatusColumn, constants.empty(), "30px"); 
//$NON-NLS-1$
+
+        TextColumnWithTooltip<GlusterVolumeSnapshotEntity> snapshotNameColumn =
+                new TextColumnWithTooltip<GlusterVolumeSnapshotEntity>() {
+                    @Override
+                    public String getValue(GlusterVolumeSnapshotEntity 
snapshot) {
+                        return snapshot.getSnapshotName();
+                    }
+                };
+        snapshotNameColumn.makeSortable();
+        getTable().addColumn(snapshotNameColumn, 
constants.volumeSnapshotName(), "300px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<GlusterVolumeSnapshotEntity> descriptionColumn =
+                new TextColumnWithTooltip<GlusterVolumeSnapshotEntity>() {
+                    @Override
+                    public String getValue(GlusterVolumeSnapshotEntity 
snapshot) {
+                        return snapshot.getDescription();
+                    }
+                };
+        descriptionColumn.makeSortable();
+        getTable().addColumn(descriptionColumn, 
constants.volumeSnapshotDescription(), "400px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<GlusterVolumeSnapshotEntity> creationTimeColumn =
+                new TextColumnWithTooltip<GlusterVolumeSnapshotEntity>() {
+                    @Override
+                    public String getValue(GlusterVolumeSnapshotEntity 
snapshot) {
+                        DateTimeFormat df = 
DateTimeFormat.getFormat("yyyy-MM-dd, HH:mm:ss"); //$NON-NLS-1$
+                        return df.format(snapshot.getCreatedAt());
+                    }
+                };
+        creationTimeColumn.makeSortable();
+        getTable().addColumn(creationTimeColumn, 
constants.volumeSnapshotCreationTime(), "400px"); //$NON-NLS-1$
+    }
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabVolumeGeneralView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabVolumeGeneralView.java
index ea2b846..7a8f481 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabVolumeGeneralView.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/gluster/SubTabVolumeGeneralView.java
@@ -47,6 +47,7 @@
     TextBoxLabel stripeCount = new TextBoxLabel();
     TextBoxLabel numOfBricks = new TextBoxLabel();
     VolumeTransportTypeLabel transportTypes = new VolumeTransportTypeLabel();
+    TextBoxLabel snapMaxLimit = new TextBoxLabel();
 
     FormBuilder formBuilder;
 
@@ -68,7 +69,7 @@
         generateIds();
 
         // Build a form using the FormBuilder
-        formBuilder = new FormBuilder(formPanel, 1, 7);
+        formBuilder = new FormBuilder(formPanel, 1, 8);
 
         formBuilder.addFormItem(new FormItem(constants.NameVolume(), name, 0, 
0));
         formBuilder.addFormItem(new FormItem(constants.volumeIdVolume(), 
volumeId, 1, 0));
@@ -83,6 +84,8 @@
         formBuilder.addFormItem(new FormItem(constants.numberOfBricksVolume(), 
numOfBricks, 5, 0));
         formBuilder.addFormItem(new FormItem(constants.transportTypesVolume(), 
transportTypes, 6, 0));
 
+        formBuilder.addFormItem(new 
FormItem(constants.maxNumberOfSnapshotsVolume(), snapMaxLimit, 7, 0));
+
         getDetailModel().getPropertyChangedEvent().addListener(new 
IEventListener<PropertyChangedEventArgs>() {
             @Override
             public void eventRaised(Event<? extends PropertyChangedEventArgs> 
ev, Object sender, PropertyChangedEventArgs args) {
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusCell.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusCell.java
new file mode 100644
index 0000000..1560a3c
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusCell.java
@@ -0,0 +1,60 @@
+package org.ovirt.engine.ui.webadmin.widget.table.column;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterSnapshotStatus;
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+import org.ovirt.engine.ui.webadmin.ApplicationResources;
+import org.ovirt.engine.ui.webadmin.ApplicationTemplates;
+import org.ovirt.engine.ui.webadmin.gin.ClientGinjectorProvider;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+
+public class GlusterVolumeSnapshotStatusCell extends 
AbstractCell<GlusterVolumeSnapshotEntity> {
+
+    private static final ApplicationResources resources = 
ClientGinjectorProvider.getApplicationResources();
+
+    private static final ApplicationConstants constants = 
ClientGinjectorProvider.getApplicationConstants();
+
+    private static final ApplicationTemplates applicationTemplates = 
ClientGinjectorProvider.getApplicationTemplates();
+
+    @Override
+    public void render(Context context, GlusterVolumeSnapshotEntity snapshot, 
SafeHtmlBuilder sb) {
+        // Nothing to render if no snapshot is provided:
+        if (snapshot == null) {
+            return;
+        }
+
+        // Find the image corresponding to the status of the brick:
+        GlusterSnapshotStatus status = snapshot.getStatus();
+        ImageResource statusImage = null;
+        String tooltip;
+
+        switch (status) {
+        case STARTED:
+            statusImage = resources.upImage();
+            tooltip = constants.up();
+            break;
+        case STOPPED:
+            statusImage = resources.downImage();
+            tooltip = constants.down();
+            break;
+        case UNKNOWN:
+            statusImage = resources.questionMarkImage();
+            tooltip = constants.unknown();
+            break;
+        default:
+            statusImage = resources.downImage();
+            tooltip = constants.down();
+        }
+
+        // Generate the HTML for the image:
+        SafeHtml statusImageHtml =
+                
SafeHtmlUtils.fromTrustedString(AbstractImagePrototype.create(statusImage).getHTML());
+        sb.append(applicationTemplates.statusTemplate(statusImageHtml, 
tooltip));
+    }
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusColumn.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusColumn.java
new file mode 100644
index 0000000..add4a7d
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotStatusColumn.java
@@ -0,0 +1,27 @@
+package org.ovirt.engine.ui.webadmin.widget.table.column;
+
+import java.util.Comparator;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotEntity;
+import org.ovirt.engine.ui.common.widget.table.column.SortableColumn;
+
+public class GlusterVolumeSnapshotStatusColumn extends 
SortableColumn<GlusterVolumeSnapshotEntity, GlusterVolumeSnapshotEntity> {
+
+    public GlusterVolumeSnapshotStatusColumn() {
+        super(new GlusterVolumeSnapshotStatusCell());
+    }
+
+    @Override
+    public GlusterVolumeSnapshotEntity getValue(GlusterVolumeSnapshotEntity 
object) {
+        return object;
+    }
+
+    public void makeSortable() {
+        makeSortable(new Comparator<GlusterVolumeSnapshotEntity>() {
+            @Override
+            public int compare(GlusterVolumeSnapshotEntity o1, 
GlusterVolumeSnapshotEntity o2) {
+                return o1.getStatus().ordinal() - o2.getStatus().ordinal();
+            }
+        });
+    }
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountCell.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountCell.java
new file mode 100644
index 0000000..7495b45
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountCell.java
@@ -0,0 +1,24 @@
+package org.ovirt.engine.ui.webadmin.widget.table.column;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import org.ovirt.engine.ui.webadmin.ApplicationTemplates;
+import org.ovirt.engine.ui.webadmin.gin.ClientGinjectorProvider;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+
+public class GlusterVolumeSnapshotsCountCell extends 
AbstractCell<GlusterVolumeEntity> {
+    ApplicationTemplates templates = 
ClientGinjectorProvider.getApplicationTemplates();
+
+    @Override
+    public void render(Context context, GlusterVolumeEntity volume, 
SafeHtmlBuilder sb) {
+        // Nothing to render if no volume provided
+        if (volume == null) {
+            return;
+        }
+
+        // Generate the HTML for the images
+        sb.append(templates.volumeSnapshotsStatusTemplate(
+                volume.getNoOfSnapshots() != null ? 
volume.getNoOfSnapshots().intValue() : 0));
+    }
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountColumn.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountColumn.java
new file mode 100644
index 0000000..2d2949c6
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/GlusterVolumeSnapshotsCountColumn.java
@@ -0,0 +1,16 @@
+package org.ovirt.engine.ui.webadmin.widget.table.column;
+
+import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+
+import com.google.gwt.user.cellview.client.Column;
+
+public class GlusterVolumeSnapshotsCountColumn extends 
Column<GlusterVolumeEntity, GlusterVolumeEntity> {
+    public GlusterVolumeSnapshotsCountColumn() {
+        super(new GlusterVolumeSnapshotsCountCell());
+    }
+
+    @Override
+    public GlusterVolumeEntity getValue(GlusterVolumeEntity object) {
+        return object;
+    }
+}


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

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

Reply via email to