Kanagaraj M has uploaded a new change for review.

Change subject: webadmin: importing newly added gluster hosts
......................................................................

webadmin: importing newly added gluster hosts

An alert will be shown in the Cluster General tab
when there new hosts which were added to the cluster through
gluster cli(gluster peer probe) and they are not available in the ovirt engine.

On clicking of the alert, a dialog will be shown with the new hosts
along with their fingerprints. User will provide the passwords for them
and save.

Change-Id: I7afc2823d59c510d6e6aabd78e9be1d3c2ed082e
Signed-off-by: Kanagaraj M <[email protected]>
---
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/clusters/ClusterGeneralModel.java
M 
frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/Constants.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationMessages.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/ClusterModule.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/cluster/SubTabClusterGeneralPresenter.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.ui.xml
8 files changed, 469 insertions(+), 40 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/87/8187/1

diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
index be28ccb..a678de8 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
@@ -92,6 +92,7 @@
 import org.ovirt.engine.core.common.queries.VdcQueryType;
 import org.ovirt.engine.core.common.queries.VdsGroupQueryParamenters;
 import org.ovirt.engine.core.common.queries.VdsIdParametersBase;
+import 
org.ovirt.engine.core.common.queries.gluster.AddedGlusterServersParameters;
 import org.ovirt.engine.core.common.queries.gluster.GlusterParameters;
 import 
org.ovirt.engine.core.common.queries.gluster.GlusterServersQueryParameters;
 import org.ovirt.engine.core.compat.Guid;
@@ -1079,6 +1080,19 @@
                 aQuery);
     }
 
+    public static void GetGlusterHostsNewlyAdded(AsyncQuery aQuery, Guid 
clusterId, boolean isFingerprintRequired) {
+        aQuery.converterCallback = new IAsyncConverter() {
+            @Override
+            public Object Convert(Object source, AsyncQuery _asyncQuery)
+            {
+                return source;
+            }
+        };
+        Frontend.RunQuery(VdcQueryType.GetAddedGlusterServers,
+                new AddedGlusterServersParameters(clusterId, 
isFingerprintRequired),
+                aQuery);
+    }
+
     public static void GetRpmVersionViaPublic(AsyncQuery aQuery) {
         aQuery.converterCallback = new IAsyncConverter() {
             @Override
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/clusters/ClusterGeneralModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/clusters/ClusterGeneralModel.java
index c692664..146d722 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/clusters/ClusterGeneralModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/clusters/ClusterGeneralModel.java
@@ -1,12 +1,18 @@
 package org.ovirt.engine.ui.uicommonweb.models.clusters;
 
 import java.util.ArrayList;
+import java.util.Map;
 
+import org.ovirt.engine.core.common.action.AddVdsActionParameters;
+import org.ovirt.engine.core.common.action.VdcActionParametersBase;
 import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.action.VdcReturnValueBase;
 import org.ovirt.engine.core.common.action.VdsGroupOperationParameters;
+import org.ovirt.engine.core.common.businessentities.VDS;
 import org.ovirt.engine.core.common.businessentities.VDSGroup;
 import org.ovirt.engine.core.common.businessentities.gluster.GlusterStatus;
 import 
org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
+import org.ovirt.engine.core.compat.PropertyChangedEventArgs;
 import org.ovirt.engine.core.compat.StringHelper;
 import org.ovirt.engine.ui.frontend.AsyncQuery;
 import org.ovirt.engine.ui.frontend.Frontend;
@@ -15,7 +21,11 @@
 import org.ovirt.engine.ui.uicommonweb.UICommand;
 import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
 import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
+import org.ovirt.engine.ui.uicommonweb.models.hosts.HostDetailModel;
+import org.ovirt.engine.ui.uicommonweb.models.hosts.MultipleHostsModel;
 import org.ovirt.engine.ui.uicompat.ConstantsManager;
+import org.ovirt.engine.ui.uicompat.FrontendMultipleActionAsyncResult;
+import org.ovirt.engine.ui.uicompat.IFrontendMultipleActionAsyncCallback;
 
 public class ClusterGeneralModel extends EntityModel {
 
@@ -63,6 +73,50 @@
         privateEditPolicyCommand = value;
     }
 
+    private boolean hasAnyAlert;
+
+    public boolean getHasAnyAlert()
+    {
+        return hasAnyAlert;
+    }
+
+    public void setHasAnyAlert(boolean value)
+    {
+        if (hasAnyAlert != value)
+        {
+            hasAnyAlert = value;
+            OnPropertyChanged(new PropertyChangedEventArgs("HasAnyAlert")); 
//$NON-NLS-1$
+        }
+    }
+
+    private boolean hasGlusterHostsAlert;
+
+    public boolean getHasNewGlusterHostsAlert()
+    {
+        return hasGlusterHostsAlert;
+    }
+
+    public void setHasNewGlusterHostsAlert(boolean value)
+    {
+        if (hasGlusterHostsAlert != value)
+        {
+            hasGlusterHostsAlert = value;
+            OnPropertyChanged(new 
PropertyChangedEventArgs("HasNewGlusterHostsAlert")); //$NON-NLS-1$
+        }
+    }
+
+    private UICommand importNewGlusterHostsCommand;
+
+    public UICommand getImportNewGlusterHostsCommand()
+    {
+        return importNewGlusterHostsCommand;
+    }
+
+    private void setImportNewGlusterHostsCommand(UICommand value)
+    {
+        importNewGlusterHostsCommand = value;
+    }
+
     @Override
     public VDSGroup getEntity()
     {
@@ -84,6 +138,7 @@
         setNoOfVolumesDown(0);
 
         setEditPolicyCommand(new UICommand("EditPolicy", this)); //$NON-NLS-1$
+        setImportNewGlusterHostsCommand(new UICommand("ImportGlusterHosts", 
this)); //$NON-NLS-1$
 
         AsyncQuery _asyncQuery = new AsyncQuery();
         _asyncQuery.setModel(this);
@@ -135,6 +190,7 @@
         if (getEntity() != null)
         {
             UpdateVolumeDetails();
+            updateAlerts();
         }
 
         UpdateActionAvailability();
@@ -202,6 +258,121 @@
         Cancel();
     }
 
+    public void fetchAndImportNewGlusterHosts() {
+        if (getWindow() != null)
+        {
+            return;
+        }
+
+        final MultipleHostsModel hostsModel = new MultipleHostsModel();
+        setWindow(hostsModel);
+        
hostsModel.setTitle(ConstantsManager.getInstance().getConstants().addMultipleHostsTitle());
+        hostsModel.setHashName("add_hosts"); //$NON-NLS-1$
+
+        UICommand command = new UICommand("OnSaveHosts", this); //$NON-NLS-1$
+        command.setTitle(ConstantsManager.getInstance().getConstants().ok());
+        hostsModel.getCommands().add(command);
+        hostsModel.getHosts().setItems(new ArrayList<EntityModel>());
+
+        command = new UICommand("Cancel", this); //$NON-NLS-1$
+        
command.setTitle(ConstantsManager.getInstance().getConstants().cancel());
+        command.setIsCancel(true);
+        hostsModel.getCommands().add(command);
+
+        hostsModel.StartProgress(null);
+
+        AsyncQuery _asyncQuery = new AsyncQuery();
+        _asyncQuery.setModel(this);
+        _asyncQuery.asyncCallback = new INewAsyncCallback() {
+            @Override
+            public void OnSuccess(Object model, Object result)
+            {
+                Map<String, String> hostMap = (Map<String, String>) result;
+
+                if (hostMap == null || hostMap.isEmpty())
+                {
+                    
hostsModel.setMessage(ConstantsManager.getInstance().getConstants().emptyNewGlusterHosts());
+                }
+                else
+                {
+                    ArrayList<EntityModel> list = new ArrayList<EntityModel>();
+                    for (Map.Entry<String, String> host : hostMap.entrySet())
+                    {
+                        HostDetailModel hostModel = new 
HostDetailModel(host.getKey(), host.getValue());
+                        hostModel.setName(host.getKey());
+                        hostModel.setPassword("");//$NON-NLS-1$
+                        EntityModel entityModel = new EntityModel(hostModel);
+                        list.add(entityModel);
+                    }
+                    hostsModel.getHosts().setItems(list);
+                }
+                hostsModel.StopProgress();
+            }
+        };
+        AsyncDataProvider.GetGlusterHostsNewlyAdded(_asyncQuery, 
getEntity().getId(), true);
+
+    }
+
+    public void onSaveHosts() {
+        final MultipleHostsModel hostsModel = (MultipleHostsModel) getWindow();
+        if (hostsModel == null)
+        {
+            return;
+        }
+        if (!hostsModel.validate())
+        {
+            return;
+        }
+
+        hostsModel.StartProgress(null);
+        ArrayList<VdcActionParametersBase> parametersList = new 
ArrayList<VdcActionParametersBase>();
+        for (Object object : hostsModel.getHosts().getItems()) {
+            HostDetailModel hostDetailModel = (HostDetailModel) ((EntityModel) 
object).getEntity();
+
+            VDS host = new VDS();
+            host.setvds_name(hostDetailModel.getName());
+            host.sethost_name(hostDetailModel.getAddress());
+            host.setSSHKeyFingerprint(hostDetailModel.getFingerprint());
+            host.setport(54321);
+
+            host.setvds_group_id(getEntity().getId());
+            host.setpm_enabled(false);
+
+            AddVdsActionParameters parameters = new AddVdsActionParameters();
+            parameters.setVdsId(host.getId());
+            parameters.setvds(host);
+            parameters.setRootPassword(hostDetailModel.getPassword());
+            parameters.setOverrideFirewall(false);
+
+            parametersList.add(parameters);
+        }
+
+        Frontend.RunMultipleAction(VdcActionType.AddVds,
+                parametersList,
+                true,
+                new IFrontendMultipleActionAsyncCallback() {
+
+                    @Override
+                    public void Executed(FrontendMultipleActionAsyncResult 
result) {
+                        hostsModel.StopProgress();
+                        boolean isAllCanDoPassed = true;
+                        for (VdcReturnValueBase returnValueBase : 
result.getReturnValue())
+                        {
+                            isAllCanDoPassed = isAllCanDoPassed && 
returnValueBase.getCanDoAction();
+                            if (!isAllCanDoPassed)
+                            {
+                                break;
+                            }
+                        }
+                        if (isAllCanDoPassed)
+                        {
+                            updateAlerts();
+                            Cancel();
+                        }
+                    }
+                }, null);
+    }
+
     public void Cancel()
     {
         setWindow(null);
@@ -243,6 +414,39 @@
         AsyncDataProvider.GetVolumeList(_asyncQuery, getEntity().getname());
     }
 
+    private void updateAlerts()
+    {
+        if (getEntity().supportsGlusterService())
+        {
+            AsyncQuery _asyncQuery = new AsyncQuery();
+            _asyncQuery.setModel(this);
+            _asyncQuery.asyncCallback = new INewAsyncCallback() {
+                @Override
+                public void OnSuccess(Object model, Object result)
+                {
+                    ClusterGeneralModel innerGeneralModel = 
(ClusterGeneralModel) model;
+                    Map<String, String> serverMap = (Map<String, String>) 
result;
+                    if (!serverMap.isEmpty())
+                    {
+                        innerGeneralModel.setHasNewGlusterHostsAlert(true);
+                        innerGeneralModel.setHasAnyAlert(true);
+                    }
+                    else
+                    {
+                        setHasNewGlusterHostsAlert(false);
+                        setHasAnyAlert(false);
+                    }
+                }
+            };
+            AsyncDataProvider.GetGlusterHostsNewlyAdded(_asyncQuery, 
getEntity().getId(), false);
+        }
+        else
+        {
+            setHasNewGlusterHostsAlert(false);
+            setHasAnyAlert(false);
+        }
+    }
+
     @Override
     public void ExecuteCommand(UICommand command)
     {
@@ -256,6 +460,14 @@
         {
             OnSavePolicy();
         }
+        if (command == getImportNewGlusterHostsCommand())
+        {
+            fetchAndImportNewGlusterHosts();
+        }
+        else if (StringHelper.stringsEqual(command.getName(), "OnSaveHosts")) 
//$NON-NLS-1$
+        {
+            onSaveHosts();
+        }
         else if (StringHelper.stringsEqual(command.getName(), "Cancel")) 
//$NON-NLS-1$
         {
             Cancel();
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/Constants.java
 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/Constants.java
index b78d4c6..6896c64 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/Constants.java
+++ 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/Constants.java
@@ -1542,4 +1542,7 @@
 
     @DefaultStringValue("Unable to fetch the gluster hosts. Please verify the 
host IP Address and password")
     String emptyGlusterHosts();
+
+    @DefaultStringValue("There are no new hosts in the cluster to import")
+    String emptyNewGlusterHosts();
 }
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationMessages.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationMessages.java
index 910dc2e..2e9675e 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationMessages.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationMessages.java
@@ -59,4 +59,7 @@
 
     @DefaultMessage("{0} (VLAN {1})")
     String vlanNetwork(String name, String vlanId);
+
+    @DefaultMessage("Some new hosts are added to the cluster. <a>Click 
here</a> to import them.")
+    String clusterHasNewGlusterHosts();
 }
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/ClusterModule.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/ClusterModule.java
index 7af4d72..666a4c6 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/ClusterModule.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/ClusterModule.java
@@ -92,8 +92,9 @@
 
     @Provides
     @Singleton
-    public DetailModelProvider<ClusterListModel, ClusterGeneralModel> 
getClusterPolicyProvider(ClientGinjector ginjector,
-            final Provider<ClusterPolicyPopupPresenterWidget> popupProvider) {
+    public DetailModelProvider<ClusterListModel, ClusterGeneralModel> 
getClusterGeneralProvider(ClientGinjector ginjector,
+            final Provider<ClusterPolicyPopupPresenterWidget> 
policyPopupProvider,
+            final Provider<MultipleHostsPopupPresenterWidget> 
multipleHostsProvider) {
         return new DetailTabModelProvider<ClusterListModel, 
ClusterGeneralModel>(ginjector,
                 ClusterListModel.class,
                 ClusterGeneralModel.class) {
@@ -101,8 +102,11 @@
             public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> 
getModelPopup(ClusterGeneralModel source,
                     UICommand lastExecutedCommand, Model windowModel) {
                 if (lastExecutedCommand == getModel().getEditPolicyCommand()) {
-                    return popupProvider.get();
-                } else {
+                    return policyPopupProvider.get();
+                } else if (lastExecutedCommand == 
getModel().getImportNewGlusterHostsCommand()) {
+                    return multipleHostsProvider.get();
+                }
+                else {
                     return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
                 }
             }
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/cluster/SubTabClusterGeneralPresenter.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/cluster/SubTabClusterGeneralPresenter.java
index 130db41..df93501 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/cluster/SubTabClusterGeneralPresenter.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/tab/cluster/SubTabClusterGeneralPresenter.java
@@ -1,16 +1,30 @@
 package org.ovirt.engine.ui.webadmin.section.main.presenter.tab.cluster;
 
 import org.ovirt.engine.core.common.businessentities.VDSGroup;
+import org.ovirt.engine.core.compat.Event;
+import org.ovirt.engine.core.compat.EventArgs;
+import org.ovirt.engine.core.compat.IEventListener;
+import org.ovirt.engine.core.compat.PropertyChangedEventArgs;
 import org.ovirt.engine.ui.common.presenter.AbstractSubTabPresenter;
 import org.ovirt.engine.ui.common.uicommon.model.DetailModelProvider;
+import org.ovirt.engine.ui.common.uicommon.model.UiCommonInitEvent;
 import org.ovirt.engine.ui.common.widget.tab.ModelBoundTabData;
+import org.ovirt.engine.ui.uicommonweb.UICommand;
 import org.ovirt.engine.ui.uicommonweb.models.clusters.ClusterGeneralModel;
 import org.ovirt.engine.ui.uicommonweb.models.clusters.ClusterListModel;
+import org.ovirt.engine.ui.webadmin.ApplicationMessages;
 import org.ovirt.engine.ui.webadmin.gin.ClientGinjector;
+import org.ovirt.engine.ui.webadmin.gin.ClientGinjectorProvider;
 import org.ovirt.engine.ui.webadmin.place.ApplicationPlaces;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.ClusterSelectionChangeEvent;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.user.client.ui.Anchor;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Widget;
 import com.google.inject.Inject;
 import com.gwtplatform.mvp.client.TabData;
 import com.gwtplatform.mvp.client.annotations.NameToken;
@@ -30,7 +44,22 @@
     }
 
     public interface ViewDef extends AbstractSubTabPresenter.ViewDef<VDSGroup> 
{
+        /**
+         * Clear all the alerts currently displayed in the alerts panel of the 
cluster.
+         */
+        void clearAlerts();
+
+        /**
+         * Displays a new alert in the alerts panel of the host.
+         *
+         * @param widget
+         *            the widget used to display the alert, usually just a 
text label, but can also be a text label with
+         *            a link to an action embedded
+         */
+        void addAlert(Widget widget);
     }
+
+    private final ApplicationMessages messages;
 
     @TabInfo(container = ClusterSubTabPanelPresenter.class)
     static TabData getTabData(ClientGinjector ginjector) {
@@ -42,6 +71,105 @@
     public SubTabClusterGeneralPresenter(EventBus eventBus, ViewDef view, 
ProxyDef proxy,
             PlaceManager placeManager, DetailModelProvider<ClusterListModel, 
ClusterGeneralModel> modelProvider) {
         super(eventBus, view, proxy, placeManager, modelProvider);
+        // Inject a reference to the messages:
+        messages = ClientGinjectorProvider.instance().getApplicationMessages();
+    }
+
+    @Override
+    public void onUiCommonInit(UiCommonInitEvent event) {
+        super.onUiCommonInit(event);
+
+        // Initialize the list of alerts:
+        final ClusterGeneralModel model = getModelProvider().getModel();
+        updateAlerts(getView(), model);
+
+        // Listen for changes in the properties of the model in order
+        // to update the alerts panel:
+        model.getPropertyChangedEvent().addListener(new IEventListener() {
+            @Override
+            public void eventRaised(Event ev, Object sender, EventArgs args) {
+                if (args instanceof PropertyChangedEventArgs) {
+                    PropertyChangedEventArgs changedArgs = 
(PropertyChangedEventArgs) args;
+                    if (changedArgs.PropertyName.contains("Alert")) { 
//$NON-NLS-1$
+                        updateAlerts(getView(), model);
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Review the model and if there are alerts add them to the view.
+     *
+     * @param view
+     *            the view where alerts should be added
+     * @param model
+     *            the model to review
+     */
+    private void updateAlerts(final ViewDef view, final ClusterGeneralModel 
model) {
+        // Clear all the alerts:
+        view.clearAlerts();
+
+        // Review the alerts and add those that are active:
+        if (model.getHasNewGlusterHostsAlert()) {
+            addTextAndLinkAlert(view, messages.clusterHasNewGlusterHosts(), 
model.getImportNewGlusterHostsCommand());
+        }
+    }
+
+    /**
+     * Create a widget containing text and a link that triggers the execution 
of a command.
+     *
+     * @param view
+     *            the view where the alert should be added
+     * @param text
+     *            the text content of the alert
+     * @param command
+     *            the command that should be executed when the link is clicked
+     */
+    private void addTextAndLinkAlert(final ViewDef view, final String text, 
final UICommand command) {
+        // Find the open and close positions of the link within the message:
+        final int openIndex = text.indexOf("<a>"); //$NON-NLS-1$
+        final int closeIndex = text.indexOf("</a>"); //$NON-NLS-1$
+        if (openIndex == -1 || closeIndex == -1 || closeIndex < openIndex) {
+            return;
+        }
+
+        // Extract the text before, inside and after the tags:
+        final String beforeText = text.substring(0, openIndex);
+        final String betweenText = text.substring(openIndex + 3, closeIndex);
+        final String afterText = text.substring(closeIndex + 4);
+
+        // Create a flow panel containing the text and the link:
+        final FlowPanel alertPanel = new FlowPanel();
+
+        // Create the label for the text before the tag:
+        final Label beforeLabel = new Label(beforeText);
+        beforeLabel.getElement().getStyle().setProperty("display", "inline"); 
//$NON-NLS-1$ //$NON-NLS-2$
+        alertPanel.add(beforeLabel);
+
+        // Create the anchor:
+        final Anchor betweenAnchor = new Anchor(betweenText);
+        betweenAnchor.getElement().getStyle().setProperty("display", 
"inline"); //$NON-NLS-1$ //$NON-NLS-2$
+        alertPanel.add(betweenAnchor);
+
+        // Add a listener to the anchor so that the command is executed when
+        // it is clicked:
+        betweenAnchor.addClickHandler(
+                new ClickHandler() {
+                    @Override
+                    public void onClick(ClickEvent event) {
+                        command.Execute();
+                    }
+                }
+                );
+
+        // Create the label for the text after the tag:
+        final Label afterLabel = new Label(afterText);
+        afterLabel.getElement().getStyle().setProperty("display", "inline"); 
//$NON-NLS-1$ //$NON-NLS-2$
+        alertPanel.add(afterLabel);
+
+        // Add the alert to the view:
+        view.addAlert(alertPanel);
     }
 
     @Override
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.java
index 42844a9..9de1acf 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.java
@@ -18,6 +18,7 @@
 import org.ovirt.engine.ui.uicommonweb.models.clusters.ClusterGeneralModel;
 import org.ovirt.engine.ui.uicommonweb.models.clusters.ClusterListModel;
 import org.ovirt.engine.ui.webadmin.ApplicationConstants;
+import org.ovirt.engine.ui.webadmin.ApplicationResources;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.tab.cluster.SubTabClusterGeneralPresenter;
 
 import com.google.gwt.core.client.GWT;
@@ -28,7 +29,10 @@
 import com.google.gwt.uibinder.client.UiBinder;
 import com.google.gwt.uibinder.client.UiField;
 import com.google.gwt.user.client.ui.AbsolutePanel;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTMLPanel;
 import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.SimplePanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
@@ -47,6 +51,9 @@
     interface ViewUiBinder extends UiBinder<Widget, SubTabClusterGeneralView> {
         ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
     }
+
+    // to find the icon for alert messages:
+    private final ApplicationResources resources;
 
     @UiField
     HorizontalPanel policyPanel;
@@ -104,13 +111,24 @@
     TextBoxLabel noOfVolumesUp = new TextBoxLabel();
     TextBoxLabel noOfVolumesDown = new TextBoxLabel();
 
+    @UiField
+    HTMLPanel alertsPanel;
+
+    // This is the list of action items inside the panel, so that we
+    // can clear and add elements inside without affecting the panel:
+    @UiField
+    FlowPanel alertsList;
+
     private final ApplicationConstants constants;
 
     @Inject
     public SubTabClusterGeneralView(final 
DetailModelProvider<ClusterListModel, ClusterGeneralModel> modelProvider,
-            ApplicationConstants constants) {
+            ApplicationResources resources, ApplicationConstants constants) {
         super(modelProvider);
         this.constants = constants;
+
+        // Inject a reference to the resources:
+        this.resources = resources;
 
         initSliders();
         initLabels();
@@ -218,4 +236,30 @@
         volumeSummaryPanel.setVisible(selectedItem.supportsGlusterService());
     }
 
+    @Override
+    public void clearAlerts() {
+        // Remove all the alert widgets and make the panel invisible:
+        alertsList.clear();
+        alertsPanel.setVisible(false);
+    }
+
+    @Override
+    public void addAlert(Widget alertWidget) {
+        // Create a composite panel that contains the alert icon and the 
widget provided
+        // by the caller, both rendered horizontally:
+        FlowPanel alertPanel = new FlowPanel();
+        Image alertIcon = new Image(resources.alertImage());
+        alertIcon.getElement().getStyle().setProperty("display", "inline"); 
//$NON-NLS-1$ //$NON-NLS-2$
+        alertWidget.getElement().getStyle().setProperty("display", "inline"); 
//$NON-NLS-1$ //$NON-NLS-2$
+        alertPanel.add(alertIcon);
+        alertPanel.add(alertWidget);
+
+        // Add the composite panel to the alerts panel:
+        alertsList.add(alertPanel);
+
+        // Make the panel visible if it wasn't:
+        if (!alertsPanel.isVisible()) {
+            alertsPanel.setVisible(true);
+        }
+    }
 }
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.ui.xml
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.ui.xml
index 69fc179..6fb4439 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.ui.xml
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/cluster/SubTabClusterGeneralView.ui.xml
@@ -3,6 +3,9 @@
 <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" 
xmlns:g="urn:import:com.google.gwt.user.client.ui"
        xmlns:f="urn:import:org.ovirt.engine.ui.common.widget.form"
        xmlns:w="urn:import:org.ovirt.engine.ui.common.widget">
+
+       <ui:with field='constants' 
type='org.ovirt.engine.ui.webadmin.ApplicationConstants' />
+
        <ui:style>
                .button {
                        width: 100px;
@@ -53,43 +56,61 @@
                        font-weight: bold;
                        padding-left: 5px;
                }
+               @external alertsPanel;
+               .alertsPanel {
+                       padding-top: 5px;
+                       padding-right: 16px;
+                       padding-left: 16px;
+               }
+               .alertsPanel a {
+                       color: black;
+                       text-decoration: underline;
+               }
        </ui:style>
-       <g:HorizontalPanel spacing="5">
-               <g:HorizontalPanel ui:field="policyPanel" 
addStyleNames="{style.marginLeft}">
-                       <g:FlowPanel width="400px">
-                               <w:UiCommandButton ui:field="editPolicyButton" 
addStyleNames="{style.button}" />
-                               <g:HorizontalPanel>
-                                       <g:Label ui:field="policyLabel" 
addStyleNames="{style.rightMarginStyle}"/>
-                                       <g:Label ui:field="policyFieldLabel"/>
-                               </g:HorizontalPanel>
-                               <g:AbsolutePanel ui:field="sliderPanel" 
addStyleNames="{style.topMarginPanel}">
-                                       <g:HorizontalPanel 
addStyleNames="{style.absolutePanel}">
-                                               <g:SimplePanel 
ui:field="leftDummySlider" addStyleNames="{style.geryPanel}"/>
-                                               <f:Slider 
ui:field="leftSlider"/>
-                                               <g:SimplePanel 
addStyleNames="{style.gerySplitPanel}"/>
-                                               <f:Slider 
ui:field="rightSlider"/>
+       <g:FlowPanel>
+               <g:HorizontalPanel spacing="5">
+                       <g:HorizontalPanel ui:field="policyPanel" 
addStyleNames="{style.marginLeft}">
+                               <g:FlowPanel width="400px">
+                                       <w:UiCommandButton 
ui:field="editPolicyButton" addStyleNames="{style.button}" />
+                                       <g:HorizontalPanel>
+                                               <g:Label ui:field="policyLabel" 
addStyleNames="{style.rightMarginStyle}"/>
+                                               <g:Label 
ui:field="policyFieldLabel"/>
                                        </g:HorizontalPanel>
-                                       <g:SimplePanel 
addStyleNames="{style.transparent}"/>
-                               </g:AbsolutePanel>
-                               <g:Label ui:field="policyTimeLabel"/>
-                       </g:FlowPanel>
-                       <g:FlowPanel addStyleNames="{style.minMaxPanel}">
-                               <g:HorizontalPanel >
-                                       <g:SimplePanel 
addStyleNames="{style.maxLabel}"/>
-                                       <g:Label 
ui:field="maxServiceLevelLabel"/>
-                               </g:HorizontalPanel>
-                               <g:HorizontalPanel>
-                                       <g:SimplePanel 
addStyleNames="{style.minLabel}"/>
-                                       <g:Label 
ui:field="minServiceLevelLabel"/>
-                               </g:HorizontalPanel>
-                       </g:FlowPanel>
-               </g:HorizontalPanel>
+                                       <g:AbsolutePanel ui:field="sliderPanel" 
addStyleNames="{style.topMarginPanel}">
+                                               <g:HorizontalPanel 
addStyleNames="{style.absolutePanel}">
+                                                       <g:SimplePanel 
ui:field="leftDummySlider" addStyleNames="{style.geryPanel}"/>
+                                                       <f:Slider 
ui:field="leftSlider"/>
+                                                       <g:SimplePanel 
addStyleNames="{style.gerySplitPanel}"/>
+                                                       <f:Slider 
ui:field="rightSlider"/>
+                                               </g:HorizontalPanel>
+                                               <g:SimplePanel 
addStyleNames="{style.transparent}"/>
+                                       </g:AbsolutePanel>
+                                       <g:Label ui:field="policyTimeLabel"/>
+                               </g:FlowPanel>
+                               <g:FlowPanel 
addStyleNames="{style.minMaxPanel}">
+                                       <g:HorizontalPanel >
+                                               <g:SimplePanel 
addStyleNames="{style.maxLabel}"/>
+                                               <g:Label 
ui:field="maxServiceLevelLabel"/>
+                                       </g:HorizontalPanel>
+                                       <g:HorizontalPanel>
+                                               <g:SimplePanel 
addStyleNames="{style.minLabel}"/>
+                                               <g:Label 
ui:field="minServiceLevelLabel"/>
+                                       </g:HorizontalPanel>
+                               </g:FlowPanel>
+                       </g:HorizontalPanel>
 
-               <g:VerticalPanel ui:field="volumeSummaryPanel">
-                       <g:Label ui:field="volumeHeaderLabel" 
addStyleNames="{style.headerLabel}"/>
-                       <f:GeneralFormPanel  ui:field="volumeFormPanel">
-                       </f:GeneralFormPanel>
-               </g:VerticalPanel>
-       </g:HorizontalPanel>
+                       <g:VerticalPanel ui:field="volumeSummaryPanel">
+                               <g:Label ui:field="volumeHeaderLabel" 
addStyleNames="{style.headerLabel}"/>
+                               <f:GeneralFormPanel  ui:field="volumeFormPanel">
+                               </f:GeneralFormPanel>
+                       </g:VerticalPanel>
+               </g:HorizontalPanel>
+               <g:HTMLPanel ui:field="alertsPanel" 
addStyleNames="{style.alertsPanel}">
+                       <div>
+                               <b><g:Label 
text="{constants.actionItemsHostGeneral}"></g:Label></b>
+                       </div>
+                       <g:FlowPanel ui:field="alertsList"/>
+               </g:HTMLPanel>
+       </g:FlowPanel>
 </ui:UiBinder>
        
\ No newline at end of file


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

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

Reply via email to