Gilad Chaplik has uploaded a new change for review.

Change subject: webadmin: introduce storage qos
......................................................................

webadmin: introduce storage qos

* storage qos subtab under datacenters.
* create/update/remove dialog storage qos.
* backend integration in GUI.

For more information see http://www.ovirt.org/Features/blkio-support

Change-Id: I4d5c14409be9e1fad1df3487cf3615f4b4955930
Signed-off-by: Gilad Chaplik <[email protected]>
---
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/help/HelpTag.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterQosListModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterStorageQosListModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditQosModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditStorageQosModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewQosModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewStorageQosModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosParametersModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveQosModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveStorageQosModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosMetricParametersModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosParametersModel.java
M 
frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
M 
frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
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/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/DataCenterModule.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/place/ApplicationPlaces.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/StorageQosPopupPresenterWidget.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/datacenter/SubTabDataCenterStorageQosPresenter.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.ui.xml
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.ui.xml
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/datacenter/SubTabDataCenterStorageQosView.java
30 files changed, 1,677 insertions(+), 6 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/31/31831/1

diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
index d8bc5e4..2011905 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
@@ -103,7 +103,7 @@
     SshSoftFencingCommand,
     MemorySnapshotSupported(ConfigAuthType.User),
     HostNetworkQosSupported,
-    StorageQosSupported,
+    StorageQosSupported(ConfigAuthType.User),
     CpuQosSupported,
     MaxAverageNetworkQoSValue,
     MaxPeakNetworkQoSValue,
@@ -140,7 +140,13 @@
     DefaultMtu,
     LiveMergeSupported(ConfigAuthType.User),
     SkipFencingIfSDActiveSupported,
-    JsonProtocolSupported(ConfigAuthType.User);
+    JsonProtocolSupported(ConfigAuthType.User),
+    MaxThroughputUpperBoundQosValue,
+    MaxReadThroughputUpperBoundQosValue,
+    MaxWriteThroughputUpperBoundQosValue,
+    MaxIopsUpperBoundQosValue,
+    MaxReadIopsUpperBoundQosValue,
+    MaxWriteIopsUpperBoundQosValue;
 
     public static enum ConfigAuthType {
         Admin,
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
index 99fb311..5ad8b24 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
@@ -1709,6 +1709,9 @@
     @DefaultStringValue("Unlimited")
     String UnlimitedNetworkQoS();
 
+    @DefaultStringValue("Unlimited")
+    String UnlimitedStorageQos();
+
     @DefaultStringValue("Password")
     String hostPasswordLabel();
 
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 9857a1c..22f1e02 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
@@ -146,6 +146,8 @@
 
     edit_network_qos("edit_network_qos", HelpTagType.WEBADMIN, "'Data Centers' 
main tab -> 'Network QoS' sub-tab -> 'Edit Network QoS' dialog"), //$NON-NLS-1$ 
//$NON-NLS-2$
 
+    edit_storage_qos("edit_storage_qos", HelpTagType.WEBADMIN, "'Data Centers' 
main tab -> 'Storage QoS' sub-tab -> 'Edit Storage QoS' dialog"), //$NON-NLS-1$ 
//$NON-NLS-2$
+
     edit_pool("edit_pool", HelpTagType.COMMON, "Pools Tab > Edit Pool"), 
//$NON-NLS-1$ //$NON-NLS-2$
 
     edit_provider("edit_provider", HelpTagType.WEBADMIN, "[Neutron 
integration] 'Providers' main tab -> 'Edit Provider' dialog"), //$NON-NLS-1$ 
//$NON-NLS-2$
@@ -286,6 +288,8 @@
 
     new_network_qos("new_network_qos", HelpTagType.WEBADMIN, "'Data Centers' 
main tab -> 'Network QoS' sub-tab -> 'New Network QoS' dialog"), //$NON-NLS-1$ 
//$NON-NLS-2$
 
+    new_storage_qos("new_storage_qos", HelpTagType.WEBADMIN, "'Data Centers' 
main tab -> 'Storage QoS' sub-tab -> 'New Storage QoS' dialog"), //$NON-NLS-1$ 
//$NON-NLS-2$
+
     new_pool("new_pool", HelpTagType.WEBADMIN, "Pools Tab > New Pool"), 
//$NON-NLS-1$ //$NON-NLS-2$
 
     new_quota("new_quota", HelpTagType.WEBADMIN, "Quota Tab > New Quota"), 
//$NON-NLS-1$ //$NON-NLS-2$
@@ -351,6 +355,8 @@
     remove_network_interface_vms("remove_network_interface_vms", 
HelpTagType.COMMON, "VMs Tab > Logical Network Sub-Tab > Remove Network 
Interface(s)"), //$NON-NLS-1$ //$NON-NLS-2$
 
     remove_network_qos("remove_network_qos", HelpTagType.WEBADMIN, "'Data 
Centers' main tab -> 'Network QoS' sub-tab -> 'Remove Network QoS' confirmation 
dialog."), //$NON-NLS-1$ //$NON-NLS-2$
+
+    remove_storage_qos("remove_storage_qos", HelpTagType.WEBADMIN, "'Data 
Centers' main tab -> 'Storage QoS' sub-tab -> 'Remove Storage QoS' confirmation 
dialog."), //$NON-NLS-1$ //$NON-NLS-2$
 
     remove_permission("remove_permission", HelpTagType.COMMON, "Each Main Tab 
> Permissions Sub-Tab > Remove Permission"), //$NON-NLS-1$ //$NON-NLS-2$
 
@@ -478,7 +484,9 @@
 
     reboot_virtual_machine("reboot_virtual_machine", HelpTagType.WEBADMIN, 
"VMs main tab -> Reboot confirmation dialog"), //$NON-NLS-1$ //$NON-NLS-2$
 
-    remove_disk_snapshot("remove_disk_snapshot", HelpTagType.WEBADMIN, 
"Storage Tab > Snapshots Sub-Tab > Remove Disk Snapshot(s)"); //$NON-NLS-1$ 
//$NON-NLS-2$
+    remove_disk_snapshot("remove_disk_snapshot", HelpTagType.WEBADMIN, 
"Storage Tab > Snapshots Sub-Tab > Remove Disk Snapshot(s)"), //$NON-NLS-1$ 
//$NON-NLS-2$
+
+    storage_qos("storage_qos", HelpTagType.UNKNOWN); //$NON-NLS-1$
 
     public final String name;
 
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
index 0ca1a00..3c0a218 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
@@ -48,6 +48,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.datacenters.qos.DataCenterStorageQosListModel;
 import org.ovirt.engine.ui.uicompat.ConstantsManager;
 import org.ovirt.engine.ui.uicompat.FrontendActionAsyncResult;
 import org.ovirt.engine.ui.uicompat.FrontendMultipleActionAsyncResult;
@@ -235,6 +236,7 @@
         quotaListModel.setIsAvailable(false);
         list.add(quotaListModel);
         list.add(new DataCenterNetworkQoSListModel());
+        list.add(new DataCenterStorageQosListModel());
         list.add(new PermissionListModel());
         list.add(new DataCenterEventListModel());
         setDetailModels(list);
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterQosListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterQosListModel.java
new file mode 100644
index 0000000..070af8a
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterQosListModel.java
@@ -0,0 +1,167 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.core.common.businessentities.qos.QosType;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.QosQueryParameterBase;
+import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.ui.frontend.AsyncQuery;
+import org.ovirt.engine.ui.frontend.Frontend;
+import org.ovirt.engine.ui.frontend.INewAsyncCallback;
+import org.ovirt.engine.ui.uicommonweb.UICommand;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
+
+public abstract class DataCenterQosListModel<T extends QosBase, P extends 
QosParametersModel<T>> extends SearchableListModel {
+
+    private UICommand newCommand;
+    private UICommand editCommand;
+    private UICommand removeCommand;
+
+    public DataCenterQosListModel() {
+        setTitle(getQosTitle());
+        setHelpTag(getQosHelpTag());
+        setHashName(getQosHashName());
+
+        setNewCommand(new UICommand("New", this)); //$NON-NLS-1$
+        setEditCommand(new UICommand("Edit", this)); //$NON-NLS-1$
+        setRemoveCommand(new UICommand("Remove", this)); //$NON-NLS-1$
+    }
+
+    protected abstract String getQosTitle();
+
+    protected abstract String getQosHashName();
+
+    protected abstract HelpTag getQosHelpTag();
+
+    protected abstract QosType getQosType();
+
+    protected abstract NewQosModel<T, P> getNewQosModel();
+
+    protected abstract EditQosModel<T, P> getEditQosModel(final T qoS);
+
+    protected abstract RemoveQosModel<T> getRemoveQosModel();
+
+    @Override
+    public StoragePool getEntity() {
+        return (StoragePool) super.getEntity();
+    }
+
+    public void setEntity(StoragePool value) {
+        super.setEntity(value);
+    }
+
+    @Override
+    protected void onEntityChanged() {
+        super.onEntityChanged();
+        getSearchCommand().execute();
+    }
+
+    @Override
+    protected void syncSearch() {
+        if (getEntity() == null) {
+            return;
+        }
+        AsyncQuery asyncQuery = new AsyncQuery();
+        asyncQuery.model = this;
+        asyncQuery.asyncCallback = new INewAsyncCallback() {
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public void onSuccess(Object model, Object returnValue) {
+                DataCenterQosListModel<T, P> qosListModel = 
(DataCenterQosListModel) model;
+                qosListModel.setItems((ArrayList<T>) ((VdcQueryReturnValue) 
returnValue).getReturnValue());
+
+            }
+        };
+        IdQueryParameters parameters = new 
QosQueryParameterBase(getEntity().getId(), getQosType());
+        parameters.setRefresh(getIsQueryFirstTime());
+        
Frontend.getInstance().runQuery(VdcQueryType.GetAllQosByStoragePoolIdAndType,
+                parameters,
+                asyncQuery);
+    }
+
+    public UICommand getNewCommand() {
+        return newCommand;
+    }
+
+    public void setNewCommand(UICommand newCommand) {
+        this.newCommand = newCommand;
+    }
+
+    @Override
+    public UICommand getEditCommand() {
+        return editCommand;
+    }
+
+    public void setEditCommand(UICommand editCommand) {
+        this.editCommand = editCommand;
+    }
+
+    public UICommand getRemoveCommand() {
+        return removeCommand;
+    }
+
+    public void setRemoveCommand(UICommand removeCommand) {
+        this.removeCommand = removeCommand;
+    }
+
+    @Override
+    public void executeCommand(UICommand command) {
+        super.executeCommand(command);
+
+        if (command == getNewCommand()) {
+            newQos();
+        } else if (command == getEditCommand()) {
+            edit();
+        } else if (command == getRemoveCommand()) {
+            remove();
+        }
+    }
+
+    public void remove() {
+        if (getConfirmWindow() != null) {
+            return;
+        }
+
+        setConfirmWindow(getRemoveQosModel());
+    }
+
+    public void edit() {
+        T qos = (T) getSelectedItem();
+
+        if (getWindow() != null) {
+            return;
+        }
+
+        final EditQosModel<T, P> qosModel = getEditQosModel(qos);
+        setWindow(qosModel);
+
+        qosModel.getDataCenters().setItems(Arrays.asList(getEntity()), 
getEntity());
+    }
+
+    private void updateActionAvailability() {
+        List selectedItems = getSelectedItems();
+
+        getEditCommand().setIsExecutionAllowed(selectedItems != null && 
selectedItems.size() == 1);
+        getRemoveCommand().setIsExecutionAllowed(selectedItems != null && 
selectedItems.size() > 0);
+    }
+
+    public void newQos() {
+        if (getWindow() != null) {
+            return;
+        }
+
+        final NewQosModel<T, P> newQosModel = getNewQosModel();
+        setWindow(newQosModel);
+
+        newQosModel.getDataCenters().setItems(Arrays.asList(getEntity()), 
getEntity());
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterStorageQosListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterStorageQosListModel.java
new file mode 100644
index 0000000..142296a
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/DataCenterStorageQosListModel.java
@@ -0,0 +1,49 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.businessentities.qos.QosType;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+
+public class DataCenterStorageQosListModel extends 
DataCenterQosListModel<StorageQos, StorageQosParametersModel> {
+    @Override
+    protected String getQosTitle() {
+        return ConstantsManager.getInstance().getConstants().storageQosTitle();
+    }
+
+    @Override
+    protected String getQosHashName() {
+        return "storage_qos"; //$NON-NLS-1$
+    }
+
+    @Override
+    protected HelpTag getQosHelpTag() {
+        return HelpTag.storage_qos;
+    }
+
+    @Override
+    protected QosType getQosType() {
+        return QosType.STORAGE;
+    }
+
+    @Override
+    protected NewQosModel<StorageQos, StorageQosParametersModel> 
getNewQosModel() {
+        return new NewStorageQosModel(this, getEntity());
+    }
+
+    @Override
+    protected EditQosModel<StorageQos, StorageQosParametersModel> 
getEditQosModel(StorageQos qoS) {
+        return new EditStorageQosModel((StorageQos) getSelectedItem(), this, 
getEntity());
+    }
+
+    @Override
+    protected RemoveQosModel<StorageQos> getRemoveQosModel() {
+        return new RemoveStorageQosModel(this);
+    }
+
+    @Override
+    protected String getListName() {
+        return "DataCenterStorageQosModel"; //$NON-NLS-1$
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditQosModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditQosModel.java
new file mode 100644
index 0000000..3a25d8c
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditQosModel.java
@@ -0,0 +1,21 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+
+public abstract class EditQosModel<T extends QosBase, P extends 
QosParametersModel<T>> extends NewQosModel<T, P> {
+
+    public EditQosModel(T qos, Model sourceModel, StoragePool dataCenter) {
+        super(sourceModel, dataCenter);
+        init(qos);
+    }
+
+    @Override
+    public void init(T qos) {
+        setQos(qos);
+        getName().setEntity(qos.getName());
+        getDescription().setEntity(qos.getDescription());
+    }
+}
+
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditStorageQosModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditStorageQosModel.java
new file mode 100644
index 0000000..9747ad1
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/EditStorageQosModel.java
@@ -0,0 +1,54 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.action.QosParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+
+public class EditStorageQosModel extends EditQosModel<StorageQos, 
StorageQosParametersModel> {
+
+    public EditStorageQosModel(StorageQos qos, Model sourceModel, StoragePool 
dataCenter) {
+        super(qos, sourceModel, dataCenter);
+    }
+
+    @Override
+    protected VdcActionType getVdcAction() {
+        return VdcActionType.UpdateStorageQos;
+    }
+
+    @Override
+    protected QosParametersBase<StorageQos> getParameters() {
+        QosParametersBase<StorageQos> qosParametersBase = new 
QosParametersBase<StorageQos>();
+        qosParametersBase.setQos(getQos());
+        qosParametersBase.setQosId(getQos().getId());
+        return qosParametersBase;
+    }
+
+    @Override
+    public void init(StorageQos qos) {
+        super.init(qos);
+
+        setQosParametersModel(new StorageQosParametersModel());
+        getQosParametersModel().init(qos);
+    }
+
+    @Override
+    public String getTitle() {
+        return 
ConstantsManager.getInstance().getConstants().editStorageQoSTitle();
+    }
+
+    @Override
+    public HelpTag getHelpTag() {
+        return HelpTag.edit_storage_qos;
+    }
+
+    @Override
+    public String getHashName() {
+        return "edit_storage_qos"; //$NON-NLS-1$
+    }
+
+}
+
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewQosModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewQosModel.java
new file mode 100644
index 0000000..3d4aaf8
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewQosModel.java
@@ -0,0 +1,40 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.action.QosParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.action.VdcReturnValueBase;
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.ui.frontend.Frontend;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+import org.ovirt.engine.ui.uicompat.FrontendActionAsyncResult;
+import org.ovirt.engine.ui.uicompat.IFrontendActionAsyncCallback;
+
+public abstract class NewQosModel<T extends QosBase, P extends 
QosParametersModel<T>> extends QosModel<T, P> {
+    public NewQosModel(Model sourceModel, StoragePool dataCenter) {
+        super(sourceModel, dataCenter);
+    }
+
+    @Override
+    protected void executeSave() {
+        final QosParametersBase<T> parameters = getParameters();
+        parameters.setQos(getQos());
+        Frontend.getInstance().runAction(getVdcAction(), parameters, new 
IFrontendActionAsyncCallback() {
+            @Override
+            public void executed(FrontendActionAsyncResult result1) {
+                VdcReturnValueBase retVal = result1.getReturnValue();
+                boolean succeeded = false;
+                if (retVal != null && retVal.getSucceeded()) {
+                    succeeded = true;
+                    getQos().setId((Guid) retVal.getActionReturnValue());
+                }
+                postSaveAction(succeeded);
+            }
+        });
+    }
+
+    protected abstract VdcActionType getVdcAction();
+
+    protected abstract QosParametersBase<T> getParameters();
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewStorageQosModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewStorageQosModel.java
new file mode 100644
index 0000000..2c223b1
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/NewStorageQosModel.java
@@ -0,0 +1,52 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.action.QosParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+
+public class NewStorageQosModel extends NewQosModel<StorageQos, 
StorageQosParametersModel> {
+
+    public NewStorageQosModel(Model sourceModel, StoragePool dataCenter) {
+        super(sourceModel, dataCenter);
+        init(new StorageQos());
+    }
+
+    @Override
+    protected VdcActionType getVdcAction() {
+        return VdcActionType.AddStorageQos;
+    }
+
+    @Override
+    protected QosParametersBase<StorageQos> getParameters() {
+        QosParametersBase<StorageQos> qosParametersBase = new 
QosParametersBase<StorageQos>();
+        qosParametersBase.setQos(getQos());
+        return qosParametersBase;
+    }
+
+    @Override
+    public void init(StorageQos qos) {
+        setQos(qos);
+        setQosParametersModel(new StorageQosParametersModel());
+        getQosParametersModel().init(qos);
+    }
+
+    @Override
+    public String getTitle() {
+        return 
ConstantsManager.getInstance().getConstants().newStorageQoSTitle();
+    }
+
+    @Override
+    public HelpTag getHelpTag() {
+        return HelpTag.new_storage_qos;
+    }
+
+    @Override
+    public String getHashName() {
+        return "new_storage_qos"; //$NON-NLS-1$;
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosModel.java
new file mode 100644
index 0000000..858a095
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosModel.java
@@ -0,0 +1,152 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.ui.uicommonweb.UICommand;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
+import org.ovirt.engine.ui.uicommonweb.models.ListModel;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+import org.ovirt.engine.ui.uicommonweb.validation.AsciiNameValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.AsciiOrNoneValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.IValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+
+public abstract class QosModel<T extends QosBase, P extends 
QosParametersModel<T>> extends Model {
+    private T qos;
+    private P qosParametersModel;
+    private final Model sourceModel;
+    private ListModel<StoragePool> dataCenters;
+    private EntityModel<String> name;
+    private EntityModel<String> description;
+
+    public QosModel(Model sourceModel, StoragePool dataCenter) {
+        this.sourceModel = sourceModel;
+
+        setName(new EntityModel<String>());
+        setDescription(new EntityModel<String>());
+        setDataCenters(new ListModel<StoragePool>());
+        getDataCenters().setSelectedItem(dataCenter);
+        getDataCenters().setIsChangable(false);
+
+        setTitle(getTitle());
+        setHelpTag(getHelpTag());
+        setHashName(getHashName());
+
+        addCommands();
+    }
+
+    public boolean validate() {
+        getName().validateEntity(new IValidation[] { new NotEmptyValidation(), 
new AsciiNameValidation() });
+        getDescription().validateEntity(new IValidation[] { new 
AsciiOrNoneValidation() });
+        setIsValid(getIsValid() && getName().getIsValid() && 
getDescription().getIsValid());
+        return getIsValid();
+    }
+
+    protected void addCommands() {
+        getCommands().add(new UICommand("OnSave", 
this).setTitle(ConstantsManager.getInstance().getConstants().ok()) //$NON-NLS-1$
+                .setIsDefault(true));
+        getCommands().add(new UICommand("Cancel", 
this).setTitle(ConstantsManager.getInstance().getConstants().cancel()) 
//$NON-NLS-1$
+                .setIsCancel(true));
+    }
+
+    public StoragePool getSelectedDc() {
+        return getDataCenters().getSelectedItem();
+    }
+
+    public T flush() {
+        getQos().setName(getName().getEntity());
+        getQos().setDescription(getDescription().getEntity());
+        getQos().setStoragePoolId(getDataCenters().getSelectedItem().getId());
+        getQosParametersModel().flush(getQos());
+        return getQos();
+    }
+
+    protected abstract void executeSave();
+
+    public abstract void init(T qos);
+
+    @Override
+    public abstract String getTitle();
+
+    public abstract HelpTag getHelpTag();
+
+    @Override
+    public abstract String getHashName();
+
+    protected void cancel() {
+        sourceModel.setWindow(null);
+        sourceModel.setConfirmWindow(null);
+    }
+
+    public void onSave() {
+        if (!validate()) {
+            return;
+        }
+
+        // Save changes.
+        flush();
+
+        // Execute all the required commands (detach, attach, update) to save 
the updates
+        executeSave();
+    }
+
+    @Override
+    public void executeCommand(UICommand command) {
+        super.executeCommand(command);
+
+        if ("OnSave".equals(command.getName())) { //$NON-NLS-1$
+            onSave();
+        } else if ("Cancel".equals(command.getName())) { //$NON-NLS-1$
+            cancel();
+        }
+    }
+
+    protected void postSaveAction(boolean succeeded) {
+        if (succeeded) {
+            cancel();
+        }
+        stopProgress();
+    }
+
+    public T getQos() {
+        return qos;
+    }
+
+    public void setQos(T qos) {
+        this.qos = qos;
+    }
+
+    public ListModel<StoragePool> getDataCenters() {
+        return dataCenters;
+    }
+
+    public void setDataCenters(ListModel<StoragePool> dataCenters) {
+        this.dataCenters = dataCenters;
+    }
+
+    public EntityModel<String> getName() {
+        return name;
+    }
+
+    public void setName(EntityModel<String> name) {
+        this.name = name;
+    }
+
+    public EntityModel<String> getDescription() {
+        return description;
+    }
+
+    public void setDescription(EntityModel<String> description) {
+        this.description = description;
+    }
+
+    public P getQosParametersModel() {
+        return qosParametersModel;
+    }
+
+    public void setQosParametersModel(P qosParametersModel) {
+        this.qosParametersModel = qosParametersModel;
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosParametersModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosParametersModel.java
new file mode 100644
index 0000000..71bcfc7
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/QosParametersModel.java
@@ -0,0 +1,12 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+
+public abstract class QosParametersModel<T extends QosBase> extends Model {
+
+    public abstract void init(T qos);
+
+    public abstract void flush(T qos);
+
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveQosModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveQosModel.java
new file mode 100644
index 0000000..14fe24e
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveQosModel.java
@@ -0,0 +1,123 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.ovirt.engine.core.common.action.QosParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.profiles.ProfileBase;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryParametersBase;
+import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.ui.frontend.Frontend;
+import org.ovirt.engine.ui.uicommonweb.UICommand;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicommonweb.models.ConfirmationModel;
+import org.ovirt.engine.ui.uicommonweb.models.ListModel;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+import org.ovirt.engine.ui.uicompat.FrontendMultipleQueryAsyncResult;
+import org.ovirt.engine.ui.uicompat.IFrontendMultipleQueryAsyncCallback;
+
+public abstract class RemoveQosModel<T extends QosBase> extends 
ConfirmationModel {
+
+    private final ListModel<T> sourceListModel;
+
+    public RemoveQosModel(ListModel<T> sourceListModel) {
+        this.sourceListModel = sourceListModel;
+
+        setTitle(getTitle());
+        setMessage();
+        addCommands();
+    }
+
+    private void addCommands() {
+        getCommands().add(new UICommand("onRemove", 
this).setTitle(ConstantsManager.getInstance().getConstants().ok()) //$NON-NLS-1$
+                .setIsDefault(true));
+
+        getCommands().add(new UICommand("cancel", 
this).setTitle(ConstantsManager.getInstance().getConstants().cancel()) 
//$NON-NLS-1$
+                .setIsCancel(true));
+    }
+
+    @Override
+    public abstract String getTitle();
+
+    protected abstract VdcQueryType getProfilesByQosIdQueryType();
+
+    protected abstract String getRemoveQosMessage(int size);
+
+    protected abstract String getRemoveQosHashName();
+
+    protected abstract HelpTag getRemoveQosHelpTag();
+
+    protected abstract VdcActionType getRemoveActionType();
+
+    private void setMessage() {
+        ArrayList<VdcQueryParametersBase> parameters = new 
ArrayList<VdcQueryParametersBase>();
+        ArrayList<VdcQueryType> queryTypes = new ArrayList<VdcQueryType>();
+        for (T qos : sourceListModel.getSelectedItems()) {
+            VdcQueryParametersBase parameter = new 
IdQueryParameters(qos.getId());
+            parameters.add(parameter);
+            queryTypes.add(getProfilesByQosIdQueryType());
+        }
+        Frontend.getInstance().runMultipleQueries(queryTypes, parameters, new 
IFrontendMultipleQueryAsyncCallback() {
+
+            @Override
+            public void executed(FrontendMultipleQueryAsyncResult result) {
+                List<ProfileBase> profiles = new ArrayList<ProfileBase>();
+
+                setHelpTag(getRemoveQosHelpTag());
+                setHashName(getRemoveQosHashName());
+
+                for (VdcQueryReturnValue returnValue : 
result.getReturnValues()) {
+                    profiles.addAll((List<ProfileBase>) 
returnValue.getReturnValue());
+                }
+                if (profiles.isEmpty()) {
+                    ArrayList<String> list = new ArrayList<String>();
+                    for (T item : sourceListModel.getSelectedItems()) {
+                        list.add(item.getName());
+                    }
+                    setItems(list);
+                } else {
+                    setMessage(getRemoveQosMessage(profiles.size()));
+
+                    ArrayList<String> list = new ArrayList<String>();
+                    for (ProfileBase item : profiles) {
+                        list.add(item.getName());
+                    }
+                    setItems(list);
+                }
+            }
+        });
+    }
+
+    public void onRemove() {
+        ArrayList<VdcActionParametersBase> parameters = new 
ArrayList<VdcActionParametersBase>();
+
+        for (T qos : sourceListModel.getSelectedItems()) {
+            QosParametersBase<T> parameter = new QosParametersBase<T>();
+            parameter.setQosId(qos.getId());
+            parameters.add(parameter);
+        }
+
+        Frontend.getInstance().runMultipleAction(getRemoveActionType(), 
parameters);
+
+        cancel();
+    }
+
+    private void cancel() {
+        sourceListModel.setConfirmWindow(null);
+    }
+
+    @Override
+    public void executeCommand(UICommand command) {
+        super.executeCommand(command);
+        if ("onRemove".equals(command.getName())) { //$NON-NLS-1$
+            onRemove();
+        } else if ("cancel".equals(command.getName())) { //$NON-NLS-1$
+            cancel();
+        }
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveStorageQosModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveStorageQosModel.java
new file mode 100644
index 0000000..0fc5444
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/RemoveStorageQosModel.java
@@ -0,0 +1,47 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.ui.uicommonweb.help.HelpTag;
+import org.ovirt.engine.ui.uicommonweb.models.ListModel;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+
+public class RemoveStorageQosModel extends RemoveQosModel<StorageQos> {
+
+    public RemoveStorageQosModel(ListModel<StorageQos> sourceListModel) {
+        super(sourceListModel);
+    }
+
+    @Override
+    public String getTitle() {
+        return 
ConstantsManager.getInstance().getConstants().removeStorageQoSTitle();
+    }
+
+    @Override
+    protected VdcQueryType getProfilesByQosIdQueryType() {
+        return VdcQueryType.GetDiskProfilesByStorageQosId;
+    }
+
+    @Override
+    protected String getRemoveQosMessage(int size) {
+        return 
ConstantsManager.getInstance().getMessages().removeStorageQoSMessage(size);
+    }
+
+    @Override
+    protected String getRemoveQosHashName() {
+        return "remove_storage_qos"; //$NON-NLS-1$
+    }
+
+    @Override
+    protected HelpTag getRemoveQosHelpTag() {
+        return HelpTag.remove_storage_qos;
+    }
+
+    @Override
+    protected VdcActionType getRemoveActionType() {
+        return VdcActionType.RemoveStorageQos;
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosMetricParametersModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosMetricParametersModel.java
new file mode 100644
index 0000000..715c756
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosMetricParametersModel.java
@@ -0,0 +1,104 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.queries.ConfigurationValues;
+import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
+import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+import org.ovirt.engine.ui.uicommonweb.validation.IValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.IntegerValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation;
+import org.ovirt.engine.ui.uicompat.Event;
+import org.ovirt.engine.ui.uicompat.EventArgs;
+
+public class StorageQosMetricParametersModel extends Model {
+    private EntityModel<Integer> total;
+    private EntityModel<Integer> read;
+    private EntityModel<Integer> write;
+    private EntityModel<Boolean> enabled;
+    private final ConfigurationValues maxTotal;
+    private final ConfigurationValues maxRead;
+    private final ConfigurationValues maxWrite;
+
+    public StorageQosMetricParametersModel(ConfigurationValues maxTotal,
+            ConfigurationValues maxRead,
+            ConfigurationValues maxWrite) {
+        this.maxTotal = maxTotal;
+        this.maxRead = maxRead;
+        this.maxWrite = maxWrite;
+        setTotal(new EntityModel<Integer>());
+        setRead(new EntityModel<Integer>());
+        setWrite(new EntityModel<Integer>());
+        setEnabled(new EntityModel<Boolean>());
+        getEnabled().getPropertyChangedEvent().addListener(this);
+        getPropertyChangedEvent().addListener(this);
+    }
+
+    public EntityModel<Integer> getTotal() {
+        return total;
+    }
+
+    public void setTotal(EntityModel<Integer> total) {
+        this.total = total;
+    }
+
+    public EntityModel<Integer> getRead() {
+        return read;
+    }
+
+    public void setRead(EntityModel<Integer> read) {
+        this.read = read;
+    }
+
+    public EntityModel<Integer> getWrite() {
+        return write;
+    }
+
+    public void setWrite(EntityModel<Integer> write) {
+        this.write = write;
+    }
+
+    public EntityModel<Boolean> getEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(EntityModel<Boolean> enabled) {
+        this.enabled = enabled;
+    }
+
+    public boolean validate() {
+        if (!getEnabled().getEntity()) {
+            return true;
+        }
+
+        validateValue(getTotal(), (Integer) 
AsyncDataProvider.getConfigValuePreConverted(maxTotal));
+        validateValue(getRead(), (Integer) 
AsyncDataProvider.getConfigValuePreConverted(maxRead));
+        validateValue(getWrite(), (Integer) 
AsyncDataProvider.getConfigValuePreConverted(maxWrite));
+
+        setIsValid(getTotal().getIsValid() && getRead().getIsValid() && 
getWrite().getIsValid());
+        return getIsValid();
+    }
+
+    private void validateValue(EntityModel<Integer> entity, Integer maxValue) {
+        entity.validateEntity(new IValidation[] {
+                new NotEmptyValidation(),
+                new IntegerValidation(0, maxValue) });
+    }
+
+    @Override
+    public void eventRaised(Event ev, Object sender, EventArgs args) {
+        super.eventRaised(ev, sender, args);
+
+        if (getEnabled().equals(sender)) {
+            updateChangeability();
+        } else if (this.equals(sender)) {
+            getEnabled().setIsChangable(getIsChangable());
+        }
+    }
+
+    private void updateChangeability() {
+        boolean enabled = getIsChangable() && getEnabled().getEntity();
+        getTotal().setIsChangable(enabled);
+        getRead().setIsChangable(enabled);
+        getWrite().setIsChangable(enabled);
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosParametersModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosParametersModel.java
new file mode 100644
index 0000000..2d2c879
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/qos/StorageQosParametersModel.java
@@ -0,0 +1,111 @@
+package org.ovirt.engine.ui.uicommonweb.models.datacenters.qos;
+
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import org.ovirt.engine.core.common.queries.ConfigurationValues;
+import org.ovirt.engine.ui.uicompat.Event;
+import org.ovirt.engine.ui.uicompat.EventArgs;
+import org.ovirt.engine.ui.uicompat.IEventListener;
+import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
+
+
+public class StorageQosParametersModel extends QosParametersModel<StorageQos> {
+    private StorageQosMetricParametersModel throughput;
+    private StorageQosMetricParametersModel iops;
+
+    public StorageQosParametersModel() {
+        setThroughput(new 
StorageQosMetricParametersModel(ConfigurationValues.MaxThroughputUpperBoundQosValue,
+                ConfigurationValues.MaxReadThroughputUpperBoundQosValue,
+                ConfigurationValues.MaxWriteThroughputUpperBoundQosValue));
+        setIops(new 
StorageQosMetricParametersModel(ConfigurationValues.MaxIopsUpperBoundQosValue,
+                ConfigurationValues.MaxReadIopsUpperBoundQosValue,
+                ConfigurationValues.MaxWriteIopsUpperBoundQosValue));
+
+        getPropertyChangedEvent().addListener(new IEventListener() {
+
+            @Override
+            public void eventRaised(Event ev, Object sender, EventArgs args) {
+                if ("IsChangable".equals(((PropertyChangedEventArgs) 
args).propertyName)) { //$NON-NLS-1$
+                    boolean value = getIsChangable();
+                    getThroughput().setIsChangable(value);
+                    getIops().setIsChangable(value);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void init(StorageQos qos) {
+        if (qos.getMaxThroughput() == null
+                && qos.getMaxReadThroughput() == null
+                && qos.getMaxWriteThroughput() == null) {
+            getThroughput().getEnabled().setEntity(false);
+        } else {
+            getThroughput().getTotal().setEntity(qos.getMaxThroughput());
+            getThroughput().getRead().setEntity(qos.getMaxReadThroughput());
+            getThroughput().getWrite().setEntity(qos.getMaxWriteThroughput());
+            getThroughput().getEnabled().setEntity(true);
+        }
+
+        if (qos.getMaxIops() == null
+                && qos.getMaxReadIops() == null
+                && qos.getMaxWriteIops() == null) {
+            getIops().getEnabled().setEntity(false);
+        } else {
+            getIops().getTotal().setEntity(qos.getMaxIops());
+            getIops().getRead().setEntity(qos.getMaxReadIops());
+            getIops().getWrite().setEntity(qos.getMaxWriteIops());
+            getIops().getEnabled().setEntity(true);
+        }
+    }
+
+    @Override
+    public void flush(StorageQos storageQos) {
+        if (getThroughput().getEnabled().getEntity()) {
+            
storageQos.setMaxThroughput(getThroughput().getTotal().getEntity());
+            
storageQos.setMaxReadThroughput(getThroughput().getRead().getEntity());
+            
storageQos.setMaxWriteThroughput(getThroughput().getWrite().getEntity());
+        } else {
+            storageQos.setMaxThroughput(null);
+            storageQos.setMaxReadThroughput(null);
+            storageQos.setMaxWriteThroughput(null);
+        }
+
+        if (getIops().getEnabled().getEntity()) {
+            storageQos.setMaxIops(getIops().getTotal().getEntity());
+            storageQos.setMaxReadIops(getIops().getRead().getEntity());
+            storageQos.setMaxWriteIops(getIops().getWrite().getEntity());
+        } else {
+            storageQos.setMaxIops(null);
+            storageQos.setMaxReadIops(null);
+            storageQos.setMaxWriteIops(null);
+        }
+    }
+
+    public boolean validate() {
+        if (!getIsAvailable()) {
+            return true;
+        }
+
+        getThroughput().validate();
+        getIops().validate();
+
+        setIsValid(getThroughput().getIsValid() && getIops().getIsValid());
+        return getIsValid();
+    }
+
+    public StorageQosMetricParametersModel getThroughput() {
+        return throughput;
+    }
+
+    public void setThroughput(StorageQosMetricParametersModel throughput) {
+        this.throughput = throughput;
+    }
+
+    public StorageQosMetricParametersModel getIops() {
+        return iops;
+    }
+
+    public void setIops(StorageQosMetricParametersModel iops) {
+        this.iops = iops;
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
index 9af7011..0083cb1 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
+++ 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
@@ -252,6 +252,9 @@
     @DefaultStringValue("Network QoS")
     String networkQoSTitle();
 
+    @DefaultStringValue("Storage QoS")
+    String storageQosTitle();
+
     @DefaultStringValue("Volumes")
     String volumesTitle();
 
@@ -2105,12 +2108,21 @@
     @DefaultStringValue("Remove Network QoS")
     String removeNetworkQoSTitle();
 
+    @DefaultStringValue("Remove Storage QoS")
+    String removeStorageQoSTitle();
+
     @DefaultStringValue("Edit Network QoS")
     String editNetworkQoSTitle();
 
+    @DefaultStringValue("Edit Storage QoS")
+    String editStorageQoSTitle();
+
     @DefaultStringValue("New Network QoS")
     String newNetworkQoSTitle();
 
+    @DefaultStringValue("New Storage QoS")
+    String newStorageQoSTitle();
+
     @DefaultStringValue("Are you sure you want to remove this Network QoS")
     String removeNetworkQoSMessage();
 
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
index 0c4ce1c..f1951e2 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
+++ 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
@@ -304,6 +304,9 @@
     @DefaultMessage("This Network QoS is used by {0} Vnic Profiles.\nAre you 
sure you want to remove this Network QoS?\n\n Profiles using this QoS:\n")
     String removeNetworkQoSMessage(int numOfProfiles);
 
+    @DefaultMessage("This Storage QoS is used by {0} Disk Profiles.\nAre you 
sure you want to remove this Storage QoS?\n\n Profiles using this QoS:\n")
+    String removeStorageQoSMessage(int numOfProfiles);
+
     @DefaultMessage("{0} ({1} Socket(s), {2} Core(s) per Socket)")
     String cpuInfoMessage(int numOfCpus, int sockets, int coresPerSocket);
 
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 f3bd70f..f7868e4 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
@@ -181,6 +181,9 @@
     @DefaultStringValue("Network QoS")
     String dataCenterNetworkQoSSubTabLabel();
 
+    @DefaultStringValue("Storage QoS")
+    String dataCenterStorageQosSubTabLabel();
+
     @DefaultStringValue("Permissions")
     String dataCenterPermissionSubTabLabel();
 
@@ -3296,6 +3299,9 @@
     @DefaultStringValue("Name")
     String networkQoSName();
 
+    @DefaultStringValue("Name")
+    String storageQosName();
+
     @DefaultStringValue("In Average")
     String networkQoSInboundAverage();
 
@@ -3767,4 +3773,58 @@
 
     @DefaultStringValue("This will skip fencing if the percentage of Cluster 
Hosts with connectivity issues is greater than or equal to the defined 
threshold")
     String skipFencingWhenConnectivityBrokenInfo();
+
+    @DefaultStringValue("Total Throughput")
+    String storageQosThroughputTotal();
+
+    @DefaultStringValue("Read Throughput")
+    String storageQosThroughputRead();
+
+    @DefaultStringValue("Write Throughput")
+    String storageQosThroughputWrite();
+
+    @DefaultStringValue("Total IOps")
+    String storageQosIopsTotal();
+
+    @DefaultStringValue("Read IOps")
+    String storageQosIopsRead();
+
+    @DefaultStringValue("Read IOps")
+    String storageQosIopsWrite();
+
+    @DefaultStringValue("New")
+    String newStorageQos();
+
+    @DefaultStringValue("Edit")
+    String editStorageQos();
+
+    @DefaultStringValue("Remove")
+    String removeStorageQos();
+
+    @DefaultStringValue("Data Center")
+    String dataCenterStorageQosPopup();
+
+    @DefaultStringValue("Description")
+    String storageQosDescription();
+
+    @DefaultStringValue("Throughput")
+    String throughputLabelQosPopup();
+
+    @DefaultStringValue("IOps")
+    String iopsLabelQosPopup();
+
+    @DefaultStringValue("Read")
+    String readStorageQosPopup();
+
+    @DefaultStringValue("Total")
+    String totalStorageQosPopup();
+
+    @DefaultStringValue("Write")
+    String writeStorageQosPopup();
+
+    @DefaultStringValue("Mbps")
+    String mbpsLabelStorageQosPopup();
+
+    @DefaultStringValue("Count")
+    String iopsCountLabelQosPopup();
 }
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 6362a52..3bdf4c5 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
@@ -33,6 +33,7 @@
 import 
org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface;
 import 
org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface;
 import org.ovirt.engine.core.common.businessentities.network.VnicProfileView;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
 import org.ovirt.engine.core.common.scheduling.AffinityGroup;
 import org.ovirt.engine.core.common.utils.PairQueryable;
 import org.ovirt.engine.ui.common.auth.LoggedInGatekeeper;
@@ -57,6 +58,7 @@
 import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterNetworkQoSListModel;
 import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterQuotaListModel;
 import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterStorageListModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.DataCenterStorageQosListModel;
 import org.ovirt.engine.ui.uicommonweb.models.disks.DiskGeneralModel;
 import org.ovirt.engine.ui.uicommonweb.models.disks.DiskListModel;
 import org.ovirt.engine.ui.uicommonweb.models.disks.DiskStorageListModel;
@@ -209,6 +211,8 @@
 
     SearchableDetailModelProvider<NetworkQoS, DataCenterListModel, 
DataCenterNetworkQoSListModel> getSubTabDataCenterNetworkQoSModelProvider();
 
+    SearchableDetailModelProvider<StorageQos, DataCenterListModel, 
DataCenterStorageQosListModel> getSubTabDataCenterStorageQosModelProvider();
+
     SearchableDetailModelProvider<Permissions, DataCenterListModel, 
PermissionListModel> getSubTabDataCenterPermissionModelProvider();
 
     SearchableDetailModelProvider<AuditLog, DataCenterListModel, 
DataCenterEventListModel> getSubTabDataCenterEventModelProvider();
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 1e85680..4cff6d7 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
@@ -16,6 +16,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.DetachConfirmationPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.NetworkQoSPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.PermissionsPopupPresenterWidget;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.StorageQosPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.SystemPermissionsRemoveConfirmationPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.bookmark.BookmarkPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.cluster.ClusterManageNetworkPopupPresenterWidget;
@@ -25,7 +26,6 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.cluster.ManageGlusterSwiftPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.cluster.NewClusterNetworkPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.configure.ConfigurePopupPresenterWidget;
-import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.instancetypes.InstanceTypesPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.configure.RolePopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.datacenter.DataCenterForceRemovePopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.datacenter.DataCenterPopupPresenterWidget;
@@ -64,6 +64,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.host.SetupNetworksBondPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.host.SetupNetworksInterfacePopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.host.SetupNetworksManagementPopupPresenterWidget;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.instancetypes.InstanceTypesPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.pool.PoolEditPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.pool.PoolNewPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.profile.VnicProfilePopupPresenterWidget;
@@ -144,6 +145,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.datacenter.SubTabDataCenterPermissionPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.datacenter.SubTabDataCenterQuotaPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.datacenter.SubTabDataCenterStoragePresenter;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.datacenter.SubTabDataCenterStorageQosPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.disk.DiskSubTabPanelPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.disk.SubTabDiskGeneralPresenter;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.disk.SubTabDiskPermissionPresenter;
@@ -253,7 +255,6 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.cluster.ManageGlusterSwiftPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.cluster.NewClusterNetworkPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.configure.ConfigurePopupView;
-import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.instancetypes.InstanceTypesPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.configure.RolePopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.datacenter.DataCenterForceRemovePopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.datacenter.DataCenterPopupView;
@@ -291,6 +292,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.host.SetupNetworksBondPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.host.SetupNetworksInterfacePopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.host.SetupNetworksManagementPopupView;
+import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.instancetypes.InstanceTypesPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.networkQoS.NetworkQoSPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.pool.PoolEditPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.pool.PoolNewPopupView;
@@ -298,6 +300,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.provider.ExternalSubnetPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.provider.ImportNetworksPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.provider.ProviderPopupView;
+import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.qos.StorageQosPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.quota.ChangeQuotaPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.quota.EditQuotaClusterPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.quota.EditQuotaStoragePopupView;
@@ -373,6 +376,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.datacenter.SubTabDataCenterNetworkView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.datacenter.SubTabDataCenterPermissionView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.datacenter.SubTabDataCenterQuotaView;
+import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.datacenter.SubTabDataCenterStorageQosView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.datacenter.SubTabDataCenterStorageView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.disk.DiskSubTabPanelView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.tab.disk.SubTabDiskGeneralView;
@@ -610,6 +614,10 @@
                 SubTabDataCenterNetworkQoSPresenter.ViewDef.class,
                 SubTabDataCenterNetworkQoSView.class,
                 SubTabDataCenterNetworkQoSPresenter.ProxyDef.class);
+        bindPresenter(SubTabDataCenterStorageQosPresenter.class,
+                SubTabDataCenterStorageQosPresenter.ViewDef.class,
+                SubTabDataCenterStorageQosView.class,
+                SubTabDataCenterStorageQosPresenter.ProxyDef.class);
         bindPresenter(SubTabDataCenterClusterPresenter.class,
                 SubTabDataCenterClusterPresenter.ViewDef.class,
                 SubTabDataCenterClusterView.class,
@@ -1338,6 +1346,11 @@
                 NetworkQoSPopupPresenterWidget.ViewDef.class,
                 NetworkQoSPopupView.class);
 
+        // Storage QoS
+        bindPresenterWidget(StorageQosPopupPresenterWidget.class,
+                StorageQosPopupPresenterWidget.ViewDef.class,
+                StorageQosPopupView.class);
+
         bindPresenterWidget(EditQuotaClusterPopupPresenterWidget.class,
                 EditQuotaClusterPopupPresenterWidget.ViewDef.class,
                 EditQuotaClusterPopupView.class);
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/DataCenterModule.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/DataCenterModule.java
index 5b5c3d3..854bf9b 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/DataCenterModule.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/DataCenterModule.java
@@ -2,13 +2,14 @@
 
 import org.ovirt.engine.core.common.businessentities.AuditLog;
 import org.ovirt.engine.core.common.businessentities.IscsiBond;
+import org.ovirt.engine.core.common.businessentities.Permissions;
 import org.ovirt.engine.core.common.businessentities.Quota;
 import org.ovirt.engine.core.common.businessentities.StorageDomain;
 import org.ovirt.engine.core.common.businessentities.StoragePool;
 import org.ovirt.engine.core.common.businessentities.VDSGroup;
-import org.ovirt.engine.core.common.businessentities.Permissions;
 import org.ovirt.engine.core.common.businessentities.network.Network;
 import org.ovirt.engine.core.common.businessentities.network.NetworkQoS;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
 import 
org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget;
 import org.ovirt.engine.ui.common.presenter.ModelBoundPresenterWidget;
 import 
org.ovirt.engine.ui.common.presenter.popup.DefaultConfirmationPopupPresenterWidget;
@@ -31,9 +32,11 @@
 import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterNetworkQoSListModel;
 import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterQuotaListModel;
 import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterStorageListModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.DataCenterStorageQosListModel;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.ReportPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.NetworkQoSPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.PermissionsPopupPresenterWidget;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.StorageQosPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.datacenter.DataCenterForceRemovePopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.datacenter.DataCenterPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.datacenter.EditDataCenterNetworkPopupPresenterWidget;
@@ -264,6 +267,40 @@
 
     @Provides
     @Singleton
+    public SearchableDetailModelProvider<StorageQos, DataCenterListModel, 
DataCenterStorageQosListModel> getDataCenterStorageQosListProvider(EventBus 
eventBus,
+            Provider<DefaultConfirmationPopupPresenterWidget> 
defaultConfirmPopupProvider,
+            final Provider<StorageQosPopupPresenterWidget> 
storageQosPopupProvider,
+            final Provider<RemoveConfirmationPopupPresenterWidget> 
removeConfirmPopupProvider) {
+        return new SearchableDetailTabModelProvider<StorageQos, 
DataCenterListModel, DataCenterStorageQosListModel>(
+                eventBus, defaultConfirmPopupProvider,
+                DataCenterListModel.class,
+                DataCenterStorageQosListModel.class) {
+            @Override
+            public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> 
getModelPopup(DataCenterStorageQosListModel source,
+                    UICommand lastExecutedCommand,
+                    Model windowModel) {
+                if (lastExecutedCommand.equals(getModel().getNewCommand())
+                        || 
lastExecutedCommand.equals(getModel().getEditCommand())) {
+                    return storageQosPopupProvider.get();
+                } else {
+                    return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
+                }
+            }
+
+            @Override
+            public AbstractModelBoundPopupPresenterWidget<? extends 
ConfirmationModel, ?> getConfirmModelPopup(DataCenterStorageQosListModel source,
+                    UICommand lastExecutedCommand) {
+                if (lastExecutedCommand.equals(getModel().getRemoveCommand())) 
{
+                    return removeConfirmPopupProvider.get();
+                } else {
+                    return super.getConfirmModelPopup(source, 
lastExecutedCommand);
+                }
+            }
+        };
+    }
+
+    @Provides
+    @Singleton
     public SearchableDetailModelProvider<Permissions, DataCenterListModel, 
PermissionListModel> getPermissionListProvider(EventBus eventBus,
             Provider<DefaultConfirmationPopupPresenterWidget> 
defaultConfirmPopupProvider,
             final Provider<PermissionsPopupPresenterWidget> popupProvider,
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/place/ApplicationPlaces.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/place/ApplicationPlaces.java
index 10bde3a..03947c5 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/place/ApplicationPlaces.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/place/ApplicationPlaces.java
@@ -69,6 +69,9 @@
     public static final String dataCenterNetworkQoSSubTabPlace = 
dataCenterMainTabPlace + SUB_TAB_PREFIX
             + "network_qos"; //$NON-NLS-1$
 
+    public static final String dataCenterStorageQosSubTabPlace = 
dataCenterMainTabPlace + SUB_TAB_PREFIX
+            + "storage_qos"; //$NON-NLS-1$
+
     public static final String dataCenterPermissionSubTabPlace = 
dataCenterMainTabPlace + SUB_TAB_PREFIX
             + "permissions"; //$NON-NLS-1$
 
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/StorageQosPopupPresenterWidget.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/StorageQosPopupPresenterWidget.java
new file mode 100644
index 0000000..32d84b4
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/StorageQosPopupPresenterWidget.java
@@ -0,0 +1,22 @@
+package org.ovirt.engine.ui.webadmin.section.main.presenter.popup;
+
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import 
org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget;
+import org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.QosModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.StorageQosParametersModel;
+
+import com.google.gwt.event.shared.EventBus;
+import com.google.inject.Inject;
+
+
+public class StorageQosPopupPresenterWidget extends 
AbstractModelBoundPopupPresenterWidget<QosModel<StorageQos, 
StorageQosParametersModel>, StorageQosPopupPresenterWidget.ViewDef> {
+
+    public interface ViewDef extends 
AbstractModelBoundPopupPresenterWidget.ViewDef<QosModel<StorageQos, 
StorageQosParametersModel>> {
+    }
+
+    @Inject
+    public StorageQosPopupPresenterWidget(EventBus eventBus, ViewDef view) {
+        super(eventBus, view);
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/datacenter/SubTabDataCenterStorageQosPresenter.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/datacenter/SubTabDataCenterStorageQosPresenter.java
new file mode 100644
index 0000000..563fb7a
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/datacenter/SubTabDataCenterStorageQosPresenter.java
@@ -0,0 +1,62 @@
+package org.ovirt.engine.ui.webadmin.section.main.presenter.tab.datacenter;
+
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+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.datacenters.DataCenterListModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.DataCenterStorageQosListModel;
+import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+import org.ovirt.engine.ui.webadmin.place.ApplicationPlaces;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.DataCenterSelectionChangeEvent;
+
+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.PlaceRequest;
+import com.gwtplatform.mvp.client.proxy.TabContentProxyPlace;
+
+public class SubTabDataCenterStorageQosPresenter extends 
AbstractSubTabPresenter<StoragePool, DataCenterListModel,
+        DataCenterStorageQosListModel, 
SubTabDataCenterStorageQosPresenter.ViewDef,
+        SubTabDataCenterStorageQosPresenter.ProxyDef> {
+
+    @ProxyCodeSplit
+    @NameToken(ApplicationPlaces.dataCenterStorageQosSubTabPlace)
+    public interface ProxyDef extends 
TabContentProxyPlace<SubTabDataCenterStorageQosPresenter> {
+    }
+
+    public interface ViewDef extends 
AbstractSubTabPresenter.ViewDef<StoragePool> {
+    }
+
+    @TabInfo(container = DataCenterSubTabPanelPresenter.class)
+    static TabData getTabData(ApplicationConstants applicationConstants,
+            SearchableDetailModelProvider<StorageQos, DataCenterListModel, 
DataCenterStorageQosListModel> modelProvider) {
+        return new 
ModelBoundTabData(applicationConstants.dataCenterStorageQosSubTabLabel(), 10, 
modelProvider);
+    }
+
+    @Inject
+    public SubTabDataCenterStorageQosPresenter(EventBus eventBus, ViewDef 
view, ProxyDef proxy,
+            PlaceManager placeManager,
+            SearchableDetailModelProvider<StorageQos, DataCenterListModel, 
DataCenterStorageQosListModel> modelProvider) {
+        super(eventBus, view, proxy, placeManager, modelProvider,
+                DataCenterSubTabPanelPresenter.TYPE_SetTabContent);
+    }
+
+    @Override
+    protected PlaceRequest getMainTabRequest() {
+        return 
PlaceRequestFactory.get(ApplicationPlaces.dataCenterMainTabPlace);
+    }
+
+    @ProxyEvent
+    public void onDataCenterSelectionChange(DataCenterSelectionChangeEvent 
event) {
+        updateMainTabSelection(event.getSelectedItems());
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.java
new file mode 100644
index 0000000..8268776
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.java
@@ -0,0 +1,100 @@
+package org.ovirt.engine.ui.webadmin.section.main.view.popup.qos;
+
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import org.ovirt.engine.ui.common.idhandler.ElementIdHandler;
+import org.ovirt.engine.ui.common.idhandler.WithElementId;
+import org.ovirt.engine.ui.common.view.popup.AbstractModelBoundPopupView;
+import org.ovirt.engine.ui.common.widget.dialog.SimpleDialogPanel;
+import org.ovirt.engine.ui.common.widget.editor.ListModelListBoxEditor;
+import 
org.ovirt.engine.ui.common.widget.editor.generic.StringEntityModelTextBoxEditor;
+import org.ovirt.engine.ui.common.widget.renderer.NullSafeRenderer;
+import org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.QosModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.StorageQosParametersModel;
+import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+import org.ovirt.engine.ui.webadmin.ApplicationResources;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.StorageQosPopupPresenterWidget;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.editor.client.SimpleBeanEditorDriver;
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.inject.Inject;
+
+public class StorageQosPopupView extends 
AbstractModelBoundPopupView<QosModel<StorageQos, StorageQosParametersModel>>
+        implements StorageQosPopupPresenterWidget.ViewDef {
+
+    @UiField(provided = true)
+    @Path(value = "dataCenters.selectedItem")
+    @WithElementId
+    ListModelListBoxEditor<StoragePool> dataCenterEditor;
+
+    @UiField
+    @Path(value = "name.entity")
+    @WithElementId
+    StringEntityModelTextBoxEditor nameEditor;
+
+    @UiField
+    @Path(value = "description.entity")
+    @WithElementId
+    StringEntityModelTextBoxEditor descriptionEditor;
+
+    @UiField(provided = true)
+    @Ignore
+    @WithElementId
+    StorageQosWidget qosWidget;
+
+    interface Driver extends SimpleBeanEditorDriver<QosModel<StorageQos, 
StorageQosParametersModel>, StorageQosPopupView> {
+    }
+
+    interface ViewUiBinder extends UiBinder<SimpleDialogPanel, 
StorageQosPopupView> {
+        ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
+    }
+
+    interface ViewIdHandler extends ElementIdHandler<StorageQosPopupView> {
+        ViewIdHandler idHandler = GWT.create(ViewIdHandler.class);
+    }
+
+    private final Driver driver = GWT.create(Driver.class);
+
+    @Inject
+    public StorageQosPopupView(EventBus eventBus, ApplicationResources 
resources, ApplicationConstants constants) {
+        super(eventBus, resources);
+        initListBoxEditors();
+        qosWidget = new StorageQosWidget(constants);
+        initWidget(ViewUiBinder.uiBinder.createAndBindUi(this));
+        ViewIdHandler.idHandler.generateAndSetIds(this);
+
+        localize(constants);
+        driver.initialize(this);
+    }
+
+    private void initListBoxEditors() {
+        dataCenterEditor = new ListModelListBoxEditor<StoragePool>(new 
NullSafeRenderer<StoragePool>() {
+            @Override
+            public String renderNullSafe(StoragePool dataCenter) {
+                return dataCenter.getName();
+            }
+        });
+    }
+
+    private void localize(ApplicationConstants constants) {
+        nameEditor.setLabel(constants.storageQosName());
+        descriptionEditor.setLabel(constants.storageQosDescription());
+        dataCenterEditor.setLabel(constants.dataCenterStorageQosPopup());
+    }
+
+    @Override
+    public void edit(QosModel<StorageQos, StorageQosParametersModel> object) {
+        driver.edit(object);
+        qosWidget.edit(object.getQosParametersModel());
+    }
+
+    @Override
+    public QosModel<StorageQos, StorageQosParametersModel> flush() {
+        qosWidget.flush();
+        return driver.flush();
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.ui.xml
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.ui.xml
new file mode 100644
index 0000000..e71cdd8
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosPopupView.ui.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent";>
+<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
+       xmlns:g="urn:import:com.google.gwt.user.client.ui" 
xmlns:d="urn:import:org.ovirt.engine.ui.common.widget.dialog"
+       xmlns:e="urn:import:org.ovirt.engine.ui.common.widget.editor" 
xmlns:ge="urn:import:org.ovirt.engine.ui.common.widget.editor.generic"
+       
xmlns:q="urn:import:org.ovirt.engine.ui.webadmin.section.main.view.popup.qos">
+
+       <ui:style>
+               .topDecorator {
+                       background-color: #D3D3D3;
+                       margin: 5px;
+               }
+       </ui:style>
+
+       <d:SimpleDialogPanel width="400px" height="400px">
+               <d:content>
+                       <g:FlowPanel>
+                               <g:FlowPanel 
addStyleNames="{style.topDecorator}">
+                                       <e:ListModelListBoxEditor 
ui:field="dataCenterEditor" />
+                                       <ge:StringEntityModelTextBoxEditor 
ui:field="nameEditor" />
+                                       <ge:StringEntityModelTextBoxEditor 
ui:field="descriptionEditor" />
+                               </g:FlowPanel>
+                               <q:StorageQosWidget ui:field="qosWidget" />
+                       </g:FlowPanel>
+               </d:content>
+       </d:SimpleDialogPanel>
+
+</ui:UiBinder>
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.java
new file mode 100644
index 0000000..d132c65
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.java
@@ -0,0 +1,153 @@
+package org.ovirt.engine.ui.webadmin.section.main.view.popup.qos;
+
+import org.ovirt.engine.ui.common.idhandler.ElementIdHandler;
+import org.ovirt.engine.ui.common.idhandler.WithElementId;
+import org.ovirt.engine.ui.common.widget.Align;
+import 
org.ovirt.engine.ui.common.widget.editor.generic.EntityModelCheckBoxEditor;
+import 
org.ovirt.engine.ui.common.widget.editor.generic.IntegerEntityModelTextBoxOnlyEditor;
+import 
org.ovirt.engine.ui.common.widget.uicommon.popup.AbstractModelBoundPopupWidget;
+import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.StorageQosParametersModel;
+import org.ovirt.engine.ui.uicompat.Event;
+import org.ovirt.engine.ui.uicompat.EventArgs;
+import org.ovirt.engine.ui.uicompat.IEventListener;
+import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
+import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.editor.client.SimpleBeanEditorDriver;
+import com.google.gwt.resources.client.CssResource;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.ui.FlowPanel;
+
+public class StorageQosWidget extends 
AbstractModelBoundPopupWidget<StorageQosParametersModel> {
+
+    interface Driver extends SimpleBeanEditorDriver<StorageQosParametersModel, 
StorageQosWidget> {
+    }
+
+    private final Driver driver = GWT.create(Driver.class);
+
+    interface ViewUiBinder extends UiBinder<FlowPanel, StorageQosWidget> {
+        ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
+    }
+
+    interface ViewIdHandler extends ElementIdHandler<StorageQosWidget> {
+        ViewIdHandler idHandler = GWT.create(ViewIdHandler.class);
+    }
+
+    interface WidgetStyle extends CssResource {
+        String valueWidth();
+    }
+
+    @UiField
+    WidgetStyle style;
+
+    @UiField
+    FlowPanel mainPanel;
+
+    @UiField(provided = true)
+    @Path(value = "throughput.enabled.entity")
+    @WithElementId
+    EntityModelCheckBoxEditor throughputEnabled;
+
+    @UiField(provided = true)
+    @Path(value = "iops.enabled.entity")
+    @WithElementId
+    EntityModelCheckBoxEditor iopsEnabled;
+
+    @UiField
+    @Path(value = "throughput.total.entity")
+    @WithElementId
+    IntegerEntityModelTextBoxOnlyEditor throughputTotalEditor;
+
+    @UiField
+    @Path(value = "throughput.read.entity")
+    @WithElementId
+    IntegerEntityModelTextBoxOnlyEditor throughputReadEditor;
+
+    @UiField
+    @Path(value = "throughput.write.entity")
+    @WithElementId
+    IntegerEntityModelTextBoxOnlyEditor throughputWriteEditor;
+
+    @UiField
+    @Path(value = "iops.total.entity")
+    @WithElementId
+    IntegerEntityModelTextBoxOnlyEditor iopsTotalEditor;
+
+    @UiField
+    @Path(value = "iops.read.entity")
+    @WithElementId
+    IntegerEntityModelTextBoxOnlyEditor iopsReadEditor;
+
+    @UiField
+    @Path(value = "iops.write.entity")
+    @WithElementId
+    IntegerEntityModelTextBoxOnlyEditor iopsWriteEditor;
+
+    private StorageQosParametersModel model;
+    private final IEventListener availabilityListener;
+
+    public StorageQosWidget(ApplicationConstants constants) {
+        throughputEnabled = new EntityModelCheckBoxEditor(Align.RIGHT);
+        iopsEnabled = new EntityModelCheckBoxEditor(Align.RIGHT);
+        initWidget(ViewUiBinder.uiBinder.createAndBindUi(this));
+        ViewIdHandler.idHandler.generateAndSetIds(this);
+
+        setStyle();
+        localize(constants);
+        driver.initialize(this);
+
+        availabilityListener = new IEventListener() {
+
+            @Override
+            public void eventRaised(Event ev, Object sender, EventArgs args) {
+                if ("IsAvailable".equals(((PropertyChangedEventArgs) 
args).propertyName)) { //$NON-NLS-1$
+                    toggleVisibility();
+                }
+            }
+        };
+    }
+
+    private void setStyle() {
+        throughputTotalEditor.setContentWidgetStyleName(style.valueWidth());
+        throughputReadEditor.setContentWidgetStyleName(style.valueWidth());
+        throughputWriteEditor.setContentWidgetStyleName(style.valueWidth());
+        iopsTotalEditor.setContentWidgetStyleName(style.valueWidth());
+        iopsReadEditor.setContentWidgetStyleName(style.valueWidth());
+        iopsWriteEditor.setContentWidgetStyleName(style.valueWidth());
+    }
+
+    private void localize(ApplicationConstants constants) {
+        throughputEnabled.setLabel(constants.throughputLabelQosPopup());
+        iopsEnabled.setLabel(constants.iopsLabelQosPopup());
+        throughputTotalEditor.setTitle(constants.totalStorageQosPopup() + 
constants.mbpsLabelStorageQosPopup());
+        throughputReadEditor.setTitle(constants.readStorageQosPopup() + 
constants.mbpsLabelStorageQosPopup());
+        throughputWriteEditor.setTitle(constants.writeStorageQosPopup() + 
constants.mbpsLabelStorageQosPopup());
+        iopsTotalEditor.setTitle(constants.totalStorageQosPopup() + 
constants.iopsCountLabelQosPopup());
+        iopsReadEditor.setTitle(constants.readStorageQosPopup() + 
constants.iopsCountLabelQosPopup());
+        iopsWriteEditor.setTitle(constants.writeStorageQosPopup() + 
constants.iopsCountLabelQosPopup());
+    }
+
+    private void toggleVisibility() {
+        mainPanel.setVisible(model.getIsAvailable());
+    }
+
+    @Override
+    public void edit(StorageQosParametersModel model) {
+        driver.edit(model);
+
+        if (this.model != null) {
+            
this.model.getPropertyChangedEvent().removeListener(availabilityListener);
+        }
+        this.model = model;
+        model.getPropertyChangedEvent().addListener(availabilityListener);
+        toggleVisibility();
+    }
+
+    @Override
+    public StorageQosParametersModel flush() {
+        return driver.flush();
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.ui.xml
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.ui.xml
new file mode 100644
index 0000000..67b574e
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/qos/StorageQosWidget.ui.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent";>
+<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
+       xmlns:g="urn:import:com.google.gwt.user.client.ui" 
xmlns:d="urn:import:org.ovirt.engine.ui.common.widget.dialog"
+       xmlns:e="urn:import:org.ovirt.engine.ui.common.widget.editor.generic">
+       <ui:with field='constants' 
type='org.ovirt.engine.ui.webadmin.ApplicationConstants' />
+
+       <ui:style 
type="org.ovirt.engine.ui.webadmin.section.main.view.popup.qos.StorageQosWidget.WidgetStyle">
+               .labelStyle {
+                       font-weight: bold;
+                       width: 90%;
+                       padding-left: 5px;
+               }
+               .mbpsLabel {
+                       text-align: right;
+                       font-size: smaller;
+                       color: gray;
+               }
+               .valueWidth {
+                       width: 60px;
+                       padding-left: 5px;
+               }
+               .valuePanelStyle {
+                       padding-left: 30px;
+                       width: 120px;
+               }
+               .textBoxLabelStyle {
+                       padding-left: 5px;
+               }
+       </ui:style>
+
+       <g:FlowPanel ui:field="mainPanel" >
+               <e:EntityModelCheckBoxEditor addStyleNames="{style.labelStyle}" 
ui:field="throughputEnabled"/>
+               <g:HorizontalPanel>
+                       <g:VerticalPanel 
addStyleNames="{style.valuePanelStyle}">
+                               <g:Label 
addStyleNames="{style.textBoxLabelStyle}" 
text="{constants.totalStorageQosPopup}"/>
+                               <g:VerticalPanel>
+                                       <e:IntegerEntityModelTextBoxOnlyEditor 
ui:field="throughputTotalEditor" />
+                                       <g:Label 
addStyleNames="{style.mbpsLabel}" text="{constants.mbpsLabelStorageQosPopup}"/>
+                               </g:VerticalPanel>
+                       </g:VerticalPanel>
+                       <g:VerticalPanel 
addStyleNames="{style.valuePanelStyle}">
+                               <g:Label 
addStyleNames="{style.textBoxLabelStyle}" 
text="{constants.readStorageQosPopup}"/>
+                               <g:VerticalPanel>
+                                       <e:IntegerEntityModelTextBoxOnlyEditor 
ui:field="throughputReadEditor" />
+                                       <g:Label 
addStyleNames="{style.mbpsLabel}" text="{constants.mbpsLabelStorageQosPopup}"/>
+                               </g:VerticalPanel>
+                       </g:VerticalPanel>
+                       <g:VerticalPanel 
addStyleNames="{style.valuePanelStyle}">
+                               <g:Label 
addStyleNames="{style.textBoxLabelStyle}" 
text="{constants.writeStorageQosPopup}"/>
+                               <g:VerticalPanel>
+                                       <e:IntegerEntityModelTextBoxOnlyEditor 
ui:field="throughputWriteEditor" />
+                                       <g:Label 
addStyleNames="{style.mbpsLabel}" text="{constants.mbpsLabelStorageQosPopup}"/>
+                               </g:VerticalPanel>
+                       </g:VerticalPanel>
+               </g:HorizontalPanel>
+               <e:EntityModelCheckBoxEditor addStyleNames="{style.labelStyle}" 
ui:field="iopsEnabled"/>
+               <g:HorizontalPanel>
+                       <g:VerticalPanel 
addStyleNames="{style.valuePanelStyle}">
+                               <g:Label 
addStyleNames="{style.textBoxLabelStyle}" 
text="{constants.totalStorageQosPopup}"/>
+                               <g:VerticalPanel>
+                                       <e:IntegerEntityModelTextBoxOnlyEditor 
ui:field="iopsTotalEditor" />
+                                       <g:Label 
addStyleNames="{style.mbpsLabel}" text="{constants.iopsCountLabelQosPopup}"/>
+                               </g:VerticalPanel>
+                       </g:VerticalPanel>
+                       <g:VerticalPanel 
addStyleNames="{style.valuePanelStyle}">
+                               <g:Label 
addStyleNames="{style.textBoxLabelStyle}" 
text="{constants.readStorageQosPopup}"/>
+                               <g:VerticalPanel>
+                                       <e:IntegerEntityModelTextBoxOnlyEditor 
ui:field="iopsReadEditor" />
+                                       <g:Label 
addStyleNames="{style.mbpsLabel}" text="{constants.iopsCountLabelQosPopup}"/>
+                               </g:VerticalPanel>
+                       </g:VerticalPanel>
+                       <g:VerticalPanel 
addStyleNames="{style.valuePanelStyle}">
+                               <g:Label 
addStyleNames="{style.textBoxLabelStyle}" 
text="{constants.writeStorageQosPopup}"/>
+                               <g:VerticalPanel>
+                                       <e:IntegerEntityModelTextBoxOnlyEditor 
ui:field="iopsWriteEditor" />
+                                       <g:Label 
addStyleNames="{style.mbpsLabel}" text="{constants.iopsCountLabelQosPopup}"/>
+                               </g:VerticalPanel>
+                       </g:VerticalPanel>
+               </g:HorizontalPanel>
+       </g:FlowPanel>
+
+</ui:UiBinder>
\ No newline at end of file
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/datacenter/SubTabDataCenterStorageQosView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/datacenter/SubTabDataCenterStorageQosView.java
new file mode 100644
index 0000000..87ace1b
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/datacenter/SubTabDataCenterStorageQosView.java
@@ -0,0 +1,140 @@
+package org.ovirt.engine.ui.webadmin.section.main.view.tab.datacenter;
+
+import javax.inject.Inject;
+
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+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.UICommand;
+import org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterListModel;
+import 
org.ovirt.engine.ui.uicommonweb.models.datacenters.qos.DataCenterStorageQosListModel;
+import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.datacenter.SubTabDataCenterStorageQosPresenter;
+import org.ovirt.engine.ui.webadmin.section.main.view.AbstractSubTabTableView;
+import org.ovirt.engine.ui.webadmin.widget.action.WebAdminButtonDefinition;
+
+import com.google.gwt.core.client.GWT;
+
+public class SubTabDataCenterStorageQosView extends 
AbstractSubTabTableView<StoragePool,
+        StorageQos, DataCenterListModel, DataCenterStorageQosListModel>
+        implements SubTabDataCenterStorageQosPresenter.ViewDef {
+
+    interface ViewIdHandler extends 
ElementIdHandler<SubTabDataCenterStorageQosView> {
+        ViewIdHandler idHandler = GWT.create(ViewIdHandler.class);
+    }
+
+    @Inject
+    public 
SubTabDataCenterStorageQosView(SearchableDetailModelProvider<StorageQos,
+            DataCenterListModel, DataCenterStorageQosListModel> modelProvider,
+            ApplicationConstants constants) {
+        super(modelProvider);
+        ViewIdHandler.idHandler.generateAndSetIds(this);
+        initTable(constants);
+        initWidget(getTable());
+    }
+
+    void initTable(final ApplicationConstants constants) {
+        getTable().enableColumnResizing();
+
+        TextColumnWithTooltip<StorageQos> nameColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getName() == null ? "" : object.getName(); 
//$NON-NLS-1$
+            }
+        };
+        nameColumn.makeSortable();
+        getTable().addColumn(nameColumn, constants.storageQosName(), "200px"); 
//$NON-NLS-1$
+
+        TextColumnWithTooltip<StorageQos> descColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getDescription() == null ? "" : 
object.getDescription(); //$NON-NLS-1$
+            }
+        };
+        descColumn.makeSortable();
+        getTable().addColumn(descColumn, constants.storageQosDescription(), 
"150px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<StorageQos> throughputColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getMaxThroughput() == null ? 
constants.UnlimitedStorageQos()
+                        : object.getMaxThroughput().toString();
+            }
+        };
+        throughputColumn.makeSortable();
+        getTable().addColumn(throughputColumn, 
constants.storageQosThroughputTotal(), "105px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<StorageQos> readThroughputColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getMaxReadThroughput() == null ? 
constants.UnlimitedStorageQos()
+                        : object.getMaxReadThroughput().toString();
+            }
+        };
+        readThroughputColumn.makeSortable();
+        getTable().addColumn(readThroughputColumn, 
constants.storageQosThroughputRead(), "105px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<StorageQos> writeThroughputColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getMaxWriteThroughput() == null ? 
constants.UnlimitedStorageQos()
+                        : object.getMaxWriteThroughput().toString();
+            }
+        };
+        writeThroughputColumn.makeSortable();
+        getTable().addColumn(writeThroughputColumn, 
constants.storageQosThroughputWrite(), "105px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<StorageQos> iopsColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getMaxIops() == null ? 
constants.UnlimitedStorageQos()
+                        : object.getMaxIops().toString();
+            }
+        };
+        iopsColumn.makeSortable();
+        getTable().addColumn(iopsColumn, constants.storageQosIopsTotal(), 
"105px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<StorageQos> readIopsColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getMaxReadIops() == null ? 
constants.UnlimitedStorageQos()
+                        : object.getMaxReadIops().toString();
+            }
+        };
+        readIopsColumn.makeSortable();
+        getTable().addColumn(readIopsColumn, constants.storageQosIopsRead(), 
"105px"); //$NON-NLS-1$
+
+        TextColumnWithTooltip<StorageQos> writeIopsColumn = new 
TextColumnWithTooltip<StorageQos>() {
+            @Override
+            public String getValue(StorageQos object) {
+                return object.getMaxWriteIops() == null ? 
constants.UnlimitedStorageQos()
+                        : object.getMaxWriteIops().toString();
+            }
+        };
+        writeIopsColumn.makeSortable();
+        getTable().addColumn(writeIopsColumn, constants.storageQosIopsWrite(), 
"105px"); //$NON-NLS-1$
+
+        getTable().addActionButton(new 
WebAdminButtonDefinition<StorageQos>(constants.newStorageQos()) {
+            @Override
+            protected UICommand resolveCommand() {
+                return getDetailModel().getNewCommand();
+            }
+        });
+
+        getTable().addActionButton(new 
WebAdminButtonDefinition<StorageQos>(constants.editStorageQos()) {
+            @Override
+            protected UICommand resolveCommand() {
+                return getDetailModel().getEditCommand();
+            }
+        });
+
+        getTable().addActionButton(new 
WebAdminButtonDefinition<StorageQos>(constants.removeStorageQos()) {
+            @Override
+            protected UICommand resolveCommand() {
+                return getDetailModel().getRemoveCommand();
+            }
+        });
+    }
+}


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

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

Reply via email to