Gilad Chaplik has uploaded a new change for review. Change subject: frontend: NUMA support ......................................................................
frontend: NUMA support For more information see: http://www.ovirt.org/Features/NUMA_and_Virtual_NUMA Change-Id: I0712ea82b87d4fe9fc25f196183136485c0c4381 Bug-Url: https://bugzilla.redhat.com/1134880 Signed-off-by: Gilad Chaplik <gchap...@redhat.com> --- M frontend/webadmin/modules/gwt-common/exclude-filters.xml M frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java M frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationMessages.java M frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationResources.java M frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/BasePresenterModule.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/WidgetModule.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/CollapsiblePanelPresenterWidget.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaSupportPopupPresenterWidget.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaVmSelected.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UnassignedVNumaNodesPanelPresenterWidget.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UpdatedVnuma.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaTitleTemplate.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VNumaTitleTemplate.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.java A frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.ui.xml A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/collapsed_header_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/expanded_header_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/drag_handle.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_dark_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_light_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_dark_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_light_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_dark_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_light_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_dark_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_icon.png A frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_light_icon.png M frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java M frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/help/HelpTag.java M frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostListModel.java A frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/NumaSupportModel.java A frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/VNodeModel.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/ApplicationMessages.java M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationResources.java M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/HostModule.java M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabHostView.java 62 files changed, 2,701 insertions(+), 6 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/93/33193/1 diff --git a/frontend/webadmin/modules/gwt-common/exclude-filters.xml b/frontend/webadmin/modules/gwt-common/exclude-filters.xml index 7e489bf..70331bf 100644 --- a/frontend/webadmin/modules/gwt-common/exclude-filters.xml +++ b/frontend/webadmin/modules/gwt-common/exclude-filters.xml @@ -196,4 +196,55 @@ <Match> <Bug pattern="SIC_INNER_SHOULD_BE_STATIC" /> </Match> + + <!-- + findbugs complain of unused field in class. + This is a GWT class and use to generate code + + findbugs reason: + UuF: Unused field (UUF_UNUSED_FIELD) + --> + <Match> + <Class name="org.ovirt.engine.ui.common.presenter.popup.numa.NumaVmSelected" /> + <Bug code="UuF"/> + </Match> + + <!-- + findbugs complain of unused field in class. + This is a GWT class and use to generate code + + findbugs reason: + UuF: Unused field (UUF_UNUSED_FIELD) + --> + <Match> + <Class name="org.ovirt.engine.ui.common.presenter.popup.numa.UpdatedVnuma" /> + <Bug code="UuF"/> + </Match> + + <!-- + findbugs complain of using Integer constructor instead of Integer.valueOf + This class is GWT generated code + + findbugs reason: + Dm: Method invokes inefficient Integer constructor; use Integer.valueOf(...) instead (DM_NUMBER_CTOR) + --> + <Match> + <Class name="org.ovirt.engine.ui.common.presenter.popup.numa.UpdatedVnumaEvent" /> + <Method name="hashCode"/> + <Bug code="Bx"/> + </Match> + + <!-- + findbugs complain of using Boolean constructor instead of Boolean.valueOf + This calss is GWT generated code + + findbugs reason: + Dm: Method invokes inefficient Boolean constructor; use Boolean.valueOf(...) instead (DM_BOOLEAN_CTOR) + --> + <Match> + <Class name="org.ovirt.engine.ui.common.presenter.popup.numa.UpdatedVnumaEvent" /> + <Method name="hashCode"/> + <Bug pattern="DM_BOOLEAN_CTOR"/> + </Match> + </FindBugsFilter> 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 21e5899..1fe592f 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 @@ -1917,4 +1917,20 @@ @DefaultStringValue("CPU Profile") String cpuProfileLabel(); + //Numa + @DefaultStringValue("Drag a vNUMA onto a NUMA node to pin the vNUMA to that node.") + String numaUnassignedInstructions(); + + @DefaultStringValue("Unassigned virtual nodes") + String unassignedVNumaNodesLabel(); + + @DefaultStringValue("Totals:") + String numaSummaryTotals(); + + @DefaultStringValue("Pin to NUMA node") + String pinToNumaNode(); + + @DefaultStringValue("Un pin virtual node") + String unPinNode(); + } diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationMessages.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationMessages.java index bacfa8b..bcf766c 100644 --- a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationMessages.java +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationMessages.java @@ -153,4 +153,27 @@ @DefaultMessage("{0} (Previewing: {1})") String snapshotPreviewing(String snapshotDescription, String diskAliases); + + //Numa messages + @DefaultMessage("{0}_NUMA{1}") + String vNumaName(String name, int index); + + @DefaultMessage("{0} CPUs") + String numaTotalCpus(int totalCpu); + + @DefaultMessage("{0}% Used") + String numaPercentUsed(int percentage); + + @DefaultMessage("{0} MB") + String numaMemory(long totalMemory); + + @DefaultMessage("{0} MB used") + String numaMemoryUsed(long totalMemoryUsed); + + @DefaultMessage("Socket {0}") + SafeHtml numaSocketNumber(int nodeIndex); + + @DefaultMessage("NUMA {0}") + String numaNode(int index); + } diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationResources.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationResources.java index 5caf7da..bc07283 100644 --- a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationResources.java +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationResources.java @@ -280,4 +280,42 @@ @Source("images/separated.png") ImageResource separatedIcon(); + + //Collapsible panel + @Source("images/collapsed_header_icon.png") + ImageResource collapsedHeaderArrow(); + + @Source("images/expanded_header_icon.png") + ImageResource expandedHeaderArrow(); + + //Numa popup + @Source("images/numa/vnuma_icon.png") + ImageResource vNumaTitleIcon(); + + @Source("images/numa/partial_vnuma_light_icon.png") + ImageResource partialVNumaIcon(); + + @Source("images/numa/pinned_partial_vnuma_light_icon.png") + ImageResource pinnedPartialVNumaIcon(); + + @Source("images/numa/vnuma_light_icon.png") + ImageResource vNumaIcon(); + + @Source("images/numa/pinned_vnuma_light_icon.png") + ImageResource pinnedVNumaIcon(); + + @Source("images/numa/drag_handle.png") + ImageResource dragHandleIcon(); + + @Source("images/numa/pinned_partial_vnuma_dark_icon.png") + ImageResource darkPinnedPartialVNumaIcon(); + + @Source("images/numa/pinned_vnuma_dark_icon.png") + ImageResource darkPinnedVNumaIcon(); + + @Source("images/numa/partial_vnuma_dark_icon.png") + ImageResource darkPartialVNumaIcon(); + + @Source("images/numa/vnuma_dark_icon.png") + ImageResource darkVNumaIcon(); } diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/BasePresenterModule.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/BasePresenterModule.java index 07629db..616e992 100644 --- a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/BasePresenterModule.java +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/BasePresenterModule.java @@ -1,17 +1,23 @@ package org.ovirt.engine.ui.common.gin; +import org.ovirt.engine.ui.common.presenter.CollapsiblePanelPresenterWidget; import org.ovirt.engine.ui.common.presenter.ScrollableTabBarPresenterWidget; import org.ovirt.engine.ui.common.presenter.popup.ConsolePopupPresenterWidget; import org.ovirt.engine.ui.common.presenter.popup.DefaultConfirmationPopupPresenterWidget; import org.ovirt.engine.ui.common.presenter.popup.ErrorPopupPresenterWidget; import org.ovirt.engine.ui.common.presenter.popup.RemoveConfirmationPopupPresenterWidget; import org.ovirt.engine.ui.common.presenter.popup.RolePermissionsRemoveConfirmationPopupPresenterWidget; +import org.ovirt.engine.ui.common.presenter.popup.numa.NumaSupportPopupPresenterWidget; +import org.ovirt.engine.ui.common.presenter.popup.numa.UnassignedVNumaNodesPanelPresenterWidget; +import org.ovirt.engine.ui.common.view.CollapsiblePanelView; import org.ovirt.engine.ui.common.view.ScrollableTabBarView; import org.ovirt.engine.ui.common.view.popup.ConsolePopupView; import org.ovirt.engine.ui.common.view.popup.DefaultConfirmationPopupView; import org.ovirt.engine.ui.common.view.popup.ErrorPopupView; import org.ovirt.engine.ui.common.view.popup.RemoveConfirmationPopupView; import org.ovirt.engine.ui.common.view.popup.RolePermissionsRemoveConfirmationPopupView; +import org.ovirt.engine.ui.common.view.popup.numa.NumaSupportPopupView; +import org.ovirt.engine.ui.common.view.popup.numa.UnassignedVNumaNodesPanelView; import com.gwtplatform.mvp.client.gin.AbstractPresenterModule; @@ -46,7 +52,17 @@ bindPresenterWidget(ScrollableTabBarPresenterWidget.class, ScrollableTabBarPresenterWidget.ViewDef.class, ScrollableTabBarView.class); + bindPresenterWidget(CollapsiblePanelPresenterWidget.class, + CollapsiblePanelPresenterWidget.ViewDef.class, + CollapsiblePanelView.class); + // Numa popup. + bindPresenterWidget(UnassignedVNumaNodesPanelPresenterWidget.class, + UnassignedVNumaNodesPanelPresenterWidget.ViewDef.class, + UnassignedVNumaNodesPanelView.class); + bindPresenterWidget(NumaSupportPopupPresenterWidget.class, + NumaSupportPopupPresenterWidget.ViewDef.class, + NumaSupportPopupView.class); } } diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/WidgetModule.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/WidgetModule.java new file mode 100644 index 0000000..086e1a2 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/gin/WidgetModule.java @@ -0,0 +1,33 @@ +package org.ovirt.engine.ui.common.gin; + +import org.ovirt.engine.ui.common.view.popup.numa.AssignedVNumaNodesPanel; +import org.ovirt.engine.ui.common.view.popup.numa.CpuSummaryPanel; +import org.ovirt.engine.ui.common.view.popup.numa.DragTargetScrollPanel; +import org.ovirt.engine.ui.common.view.popup.numa.DraggableVirtualNumaPanel; +import org.ovirt.engine.ui.common.view.popup.numa.HostSummaryContentPanel; +import org.ovirt.engine.ui.common.view.popup.numa.MemorySummaryPanel; +import org.ovirt.engine.ui.common.view.popup.numa.NumaPanel; +import org.ovirt.engine.ui.common.view.popup.numa.SocketPanel; +import org.ovirt.engine.ui.common.view.popup.numa.VirtualNumaPanel; +import org.ovirt.engine.ui.common.view.popup.numa.VmTitlePanel; + +import com.google.gwt.inject.client.AbstractGinModule; + +public class WidgetModule extends AbstractGinModule { + + @Override + protected void configure() { + //NUMA popup widgets. + bind(CpuSummaryPanel.class); + bind(MemorySummaryPanel.class); + bind(NumaPanel.class); + bind(SocketPanel.class); + bind(AssignedVNumaNodesPanel.class); + bind(DraggableVirtualNumaPanel.class); + bind(DragTargetScrollPanel.class); + bind(VmTitlePanel.class); + bind(HostSummaryContentPanel.class); + bind(VirtualNumaPanel.class); + } + +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/CollapsiblePanelPresenterWidget.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/CollapsiblePanelPresenterWidget.java new file mode 100644 index 0000000..57eb9b6 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/CollapsiblePanelPresenterWidget.java @@ -0,0 +1,44 @@ +package org.ovirt.engine.ui.common.presenter; + +import com.google.gwt.user.client.ui.IsWidget; +import com.google.inject.Inject; +import com.google.web.bindery.event.shared.EventBus; +import com.gwtplatform.mvp.client.PresenterWidget; +import com.gwtplatform.mvp.client.View; + +public class CollapsiblePanelPresenterWidget extends + PresenterWidget<CollapsiblePanelPresenterWidget.ViewDef> { + + public interface ViewDef extends View { + /** + * Add the content to the panel + * @param widget The widget to add. + */ + void addContentWidget(IsWidget widget); + /** + * Add the header widget, could be a label, or something more complex. + * @param widget The widget to add. + */ + void setTitleWidget(IsWidget widget); + + /** + * Remove the content from the panel. + */ + void clearContent(); + + /** + * Collapse the panel; + */ + void collapsePanel(); + } + + @Inject + public CollapsiblePanelPresenterWidget(EventBus eventBus, ViewDef view) { + super(eventBus, view); + } + + public void collapsePanel() { + getView().collapsePanel(); + } + +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaSupportPopupPresenterWidget.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaSupportPopupPresenterWidget.java new file mode 100644 index 0000000..0529e5f --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaSupportPopupPresenterWidget.java @@ -0,0 +1,141 @@ +package org.ovirt.engine.ui.common.presenter.popup.numa; + +import java.util.List; +import java.util.Set; + +import org.ovirt.engine.core.common.businessentities.VDS; +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget; +import org.ovirt.engine.ui.common.presenter.CollapsiblePanelPresenterWidget; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.NumaSupportModel; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; +import org.ovirt.engine.ui.uicompat.Event; +import org.ovirt.engine.ui.uicompat.EventArgs; +import org.ovirt.engine.ui.uicompat.IEventListener; + +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.event.shared.GwtEvent.Type; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.gwtplatform.mvp.client.View; +import com.gwtplatform.mvp.client.annotations.ContentSlot; +import com.gwtplatform.mvp.client.proxy.RevealContentHandler; + +public class NumaSupportPopupPresenterWidget extends AbstractModelBoundPopupPresenterWidget<NumaSupportModel, NumaSupportPopupPresenterWidget.ViewDef> { + + public interface ViewDef extends AbstractModelBoundPopupPresenterWidget.ViewDef<NumaSupportModel> { + public void setUnassignedGroupPanel(View view); + + public void setHostSummaryPanel(IsWidget widget); + + public IsWidget getHostSummaryTitle(int totalCpus, int usedCpus, int totalMemory, int usedMemory, + int totalNumaNodes, int totalVNumaNodes); + + public void addVNumaInfoPanel(Set<VdsNumaNode> numaNodes, int nodeIndex, NumaSupportModel supportModel); + + public IsWidget getHostSummaryContent(VDS selectedItem, NumaSupportModel supportModel); + + public void displayVmDetails(VNodeModel vNodeModel); + + void clear(); + } + + @ContentSlot + public static final Type<RevealContentHandler<?>> TYPE_SetUnassignedPanel = new Type<RevealContentHandler<?>>(); + + private final UnassignedVNumaNodesPanelPresenterWidget unassignedVNumaNodesPanelPresenterWidget; + + private final Provider<CollapsiblePanelPresenterWidget> collapsiblePanelProvider; + + private NumaSupportModel supportModel; + + public static final Object TYPE_revealHostSummary = new Object(); + + public static final Object TYPE_revealSocketInfo = new Object(); + + @Inject + public NumaSupportPopupPresenterWidget(EventBus eventBus, ViewDef view, + UnassignedVNumaNodesPanelPresenterWidget unassignedVNumaNodesPanelPresenterWidget, + Provider<CollapsiblePanelPresenterWidget> collapsiblePanelProvider) { + super(eventBus, view); + this.collapsiblePanelProvider = collapsiblePanelProvider; + this.unassignedVNumaNodesPanelPresenterWidget = unassignedVNumaNodesPanelPresenterWidget; + } + + @SuppressWarnings("unchecked") + @Override + public void init(final NumaSupportModel model) { + super.init(model); + supportModel = model; + this.unassignedVNumaNodesPanelPresenterWidget.setModel(model); + supportModel.getModelReady().addListener(new IEventListener() { + @Override + public void eventRaised(Event ev, Object sender, EventArgs args) { + modelReady(); + } + }); + } + + @Override + protected void onBind() { + registerHandler(getEventBus().addHandler(UpdatedVnumaEvent.getType(), + new UpdatedVnumaEvent.UpdatedVnumaHandler() { + + @Override + public void onUpdatedVnuma(UpdatedVnumaEvent event) { + supportModel.pinVNodeToNumaNode(event.getSourceVmGuid(), event.isPinned(), + event.getSourceVNumaNodeIndex(), event.getTargetNumaNodeIndex()); + } + })); + + registerHandler(getEventBus().addHandler(NumaVmSelectedEvent.getType(), + new NumaVmSelectedEvent.NumaVmSelectedHandler() { + + @Override + public void onNumaVmSelected(NumaVmSelectedEvent event) { + getView().displayVmDetails(event.getVNodeModel()); + } + })); + } + + @Override + protected void onReveal() { + super.onReveal(); + setInSlot(TYPE_SetUnassignedPanel, unassignedVNumaNodesPanelPresenterWidget); + getView().setUnassignedGroupPanel(unassignedVNumaNodesPanelPresenterWidget.getView()); + } + + private void modelReady() { + unassignedVNumaNodesPanelPresenterWidget.populateView(); + getView().clear(); + populateHostSummary(); + populateSockets(); + } + + private void populateSockets() { + for (int i = 0; i < supportModel.getFirstLevelDistanceSetList().size(); i++) { + getView().addVNumaInfoPanel(supportModel.getFirstLevelDistanceSetList().get(i).getSecond(), i, supportModel); + } + } + + private void populateHostSummary() { + CollapsiblePanelPresenterWidget hostSummaryPanel = collapsiblePanelProvider.get(); + setInSlot(TYPE_revealHostSummary, hostSummaryPanel); + List<VM> vmsWithVNuma = supportModel.getVmsWithvNumaNodeList(); + int totalVNuma = 0; + for (VM vm: vmsWithVNuma) { + totalVNuma += vm.getvNumaNodeList().size(); + } + hostSummaryPanel.getView().setTitleWidget(getView().getHostSummaryTitle( + supportModel.getHosts().getSelectedItem().getCpuCores(), + supportModel.getHosts().getSelectedItem().getUsageCpuPercent(), + supportModel.getHosts().getSelectedItem().getPhysicalMemMb(), + supportModel.getHosts().getSelectedItem().getMemFree().intValue(), + supportModel.getNumaNodeList().size(), totalVNuma)); + hostSummaryPanel.getView().addContentWidget(getView().getHostSummaryContent( + supportModel.getHosts().getSelectedItem(), supportModel)); + getView().setHostSummaryPanel(hostSummaryPanel); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaVmSelected.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaVmSelected.java new file mode 100644 index 0000000..b9ea1fa --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/NumaVmSelected.java @@ -0,0 +1,10 @@ +package org.ovirt.engine.ui.common.presenter.popup.numa; + +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.gwtplatform.dispatch.annotation.GenEvent; + +@GenEvent +public class NumaVmSelected { + VNodeModel vNodeModel; +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UnassignedVNumaNodesPanelPresenterWidget.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UnassignedVNumaNodesPanelPresenterWidget.java new file mode 100644 index 0000000..0f21884 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UnassignedVNumaNodesPanelPresenterWidget.java @@ -0,0 +1,80 @@ +package org.ovirt.engine.ui.common.presenter.popup.numa; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.ui.common.presenter.CollapsiblePanelPresenterWidget; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.NumaSupportModel; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.google.gwt.user.client.ui.IsWidget; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.web.bindery.event.shared.EventBus; +import com.gwtplatform.mvp.client.PresenterWidget; +import com.gwtplatform.mvp.client.View; + +public class UnassignedVNumaNodesPanelPresenterWidget extends + PresenterWidget<UnassignedVNumaNodesPanelPresenterWidget.ViewDef> { + + public interface ViewDef extends View { + public void addToUnassignedPanel(View view); + + public IsWidget getNodePanelTitle(VM vm, List<VNodeModel> list); + + public IsWidget getNodePanelContent(VM vm, List<VNodeModel> list, List<VdsNumaNode> numaNodeList); + + public void addEmptyUnassignPanel(); + + void clear(); + } + + public static final Object TYPE_RevealUnassignedPanels = new Object(); + + private final Provider<CollapsiblePanelPresenterWidget> collapisblePanelProvider; + + private NumaSupportModel model; + + @Inject + public UnassignedVNumaNodesPanelPresenterWidget(EventBus eventBus, ViewDef view, + Provider<CollapsiblePanelPresenterWidget> collapsiblePanelProvider) { + super(eventBus, view); + this.collapisblePanelProvider = collapsiblePanelProvider; + } + + public void setModel(NumaSupportModel model) { + this.model = model; + } + + public void populateView() { + getView().clear(); + List<VNodeModel> unassignedNodeList = model.getUnassignedVNodeModelList(); + Map<VM, List<VNodeModel>> vmToNodeMap = new HashMap<VM, List<VNodeModel>>(); + for(VM currentVM: this.model.getVmsWithvNumaNodeList()) { + List<VNodeModel> nodeModelList = new ArrayList<VNodeModel>(); + vmToNodeMap.put(currentVM, nodeModelList); + } + for (VNodeModel vNodeModel: unassignedNodeList) { + VM currentVM = vNodeModel.getVm(); + List<VNodeModel> nodeModels = vmToNodeMap.get(currentVM); + nodeModels.add(vNodeModel); + } + for(Map.Entry<VM, List<VNodeModel>> entry: vmToNodeMap.entrySet()) { + CollapsiblePanelPresenterWidget nodePanelPresenter = collapisblePanelProvider.get(); + addToSlot(TYPE_RevealUnassignedPanels, nodePanelPresenter); + nodePanelPresenter.getView().setTitleWidget(getView().getNodePanelTitle(entry.getKey(), entry.getValue())); + nodePanelPresenter.getView().addContentWidget(getView().getNodePanelContent(entry.getKey(), + entry.getValue(), model.getNumaNodeList())); + if (entry.getValue().isEmpty()) { + nodePanelPresenter.collapsePanel(); + } + getView().addToUnassignedPanel(nodePanelPresenter.getView()); + } + getView().addEmptyUnassignPanel(); + } + +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UpdatedVnuma.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UpdatedVnuma.java new file mode 100644 index 0000000..27b3fa8 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/numa/UpdatedVnuma.java @@ -0,0 +1,28 @@ +package org.ovirt.engine.ui.common.presenter.popup.numa; + +import org.ovirt.engine.core.compat.Guid; + +import com.gwtplatform.dispatch.annotation.GenEvent; + +@GenEvent +public class UpdatedVnuma { + /** + * The {@cod Guid} of the VM that contains the virtual NUMA node. + */ + Guid sourceVmGuid; + + /** + * Is the VM pinned. + */ + boolean pinned; + + /** + * The index of the virtual NUMA node on the VM. + */ + int sourceVNumaNodeIndex; + + /** + * The target physical NUMA node, -1 means unassigned. + */ + int targetNumaNodeIndex; +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.java new file mode 100644 index 0000000..95814e5 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.java @@ -0,0 +1,68 @@ +package org.ovirt.engine.ui.common.view; + +import org.ovirt.engine.ui.common.presenter.CollapsiblePanelPresenterWidget; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.gwt.user.client.ui.ToggleButton; +import com.google.gwt.user.client.ui.Widget; + +public class CollapsiblePanelView extends AbstractView implements CollapsiblePanelPresenterWidget.ViewDef { + + public interface ViewUiBinder extends UiBinder<Widget, CollapsiblePanelView> { + ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class); + } + + private static final String INDEX = "index"; //$NON-NLS-1$ + + @UiField + FlowPanel headerPanel; + + @UiField + ToggleButton collapseButton; + + @UiField + FlowPanel contentPanel; + + int dragIndex; + + /** + * Constructor. + */ + public CollapsiblePanelView() { + initWidget(ViewUiBinder.uiBinder.createAndBindUi(this)); + } + + @Override + public void addContentWidget(IsWidget widget) { + contentPanel.add(widget); + } + + @Override + public void clearContent() { + contentPanel.clear(); + } + + @Override + public void setTitleWidget(IsWidget widget) { + headerPanel.insert(widget, headerPanel.getWidgetCount() - 1); + } + + @UiHandler("collapseButton") + void handleCollapseClick(ClickEvent event) { + contentPanel.setVisible(!contentPanel.isVisible()); + } + + @Override + public void collapsePanel() { + if (contentPanel.isVisible()) { + collapseButton.setValue(true); + contentPanel.setVisible(false); + } + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.ui.xml new file mode 100644 index 0000000..67c62bb --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/CollapsiblePanelView.ui.xml @@ -0,0 +1,40 @@ +<?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:ge="urn:import:org.ovirt.engine.ui.common.widget.editor.generic" + xmlns:e="urn:import:org.ovirt.engine.ui.common.widget.editor"> + + <ui:with field='resources' type='org.ovirt.engine.ui.common.CommonApplicationResources' /> + + <ui:style> + .headerPanel { + background-color: #EDEDED; + color: #75797D; + } + + .collapseButton { + width: 24px; + background: transparent; + float:left; + border: none; + padding: 0px 2px 2px 6px; + } + + .endFloat { + clear: both; + } + </ui:style> + + <g:FlowPanel> + <g:FlowPanel ui:field="headerPanel" addStyleNames="{style.headerPanel}"> + <g:ToggleButton ui:field="collapseButton" addStyleNames="{style.collapseButton}" > + <g:upFace image="{resources.expandedHeaderArrow}" /> + <g:downFace image="{resources.collapsedHeaderArrow}"/> + </g:ToggleButton> + <g:SimplePanel addStyleNames="{style.endFloat}" /> + </g:FlowPanel> + <g:FlowPanel ui:field="contentPanel" /> + </g:FlowPanel> +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.java new file mode 100644 index 0000000..f7421d1 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.java @@ -0,0 +1,81 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import java.util.ArrayList; +import java.util.List; + +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.ui.common.CommonApplicationResources; +import org.ovirt.engine.ui.common.view.CollapsiblePanelView; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.CssResource; +import com.google.gwt.safehtml.shared.OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; +import com.google.inject.Provider; + +public class AssignedVNumaNodesPanel extends Composite { + + interface WidgetUiBinder extends UiBinder<Widget, AssignedVNumaNodesPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + interface Style extends CssResource { + String numaTitle(); + } + + private final VNumaTitleTemplate titleTemplate; + + @UiField + FlowPanel container; + + @UiField + Style style; + + private final Provider<DraggableVirtualNumaPanel> virtualNumaPanelProvider; + + private final CollapsiblePanelView collapsiblePanel; + + private final DragTargetScrollPanel scrollPanel; + + private final CommonApplicationResources resources; + + @Inject + public AssignedVNumaNodesPanel(CollapsiblePanelView collapsiblePanel, + Provider<DraggableVirtualNumaPanel> virtualNumaPanelProvider, DragTargetScrollPanel scrollPanel, + CommonApplicationResources resources, VNumaTitleTemplate vNumaTitleTemplate) { + this.collapsiblePanel = collapsiblePanel; + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + container.add(collapsiblePanel); + this.resources = resources; + this.virtualNumaPanelProvider = virtualNumaPanelProvider; + this.scrollPanel = scrollPanel; + this.titleTemplate = vNumaTitleTemplate; + collapsiblePanel.addContentWidget(scrollPanel); + } + + public void setNodes(List<VNodeModel> virtualNodes, int numaNodeIndex, List<VdsNumaNode> numaNodeList) { + String myImageHtml = AbstractImagePrototype.create(resources.vNumaTitleIcon()).getHTML(); + SafeHtml mySafeImageHtml = new OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml(myImageHtml); + if (virtualNodes == null) { + virtualNodes = new ArrayList<VNodeModel>(); + } + SafeHtml title = titleTemplate.title(virtualNodes.size(), mySafeImageHtml, style.numaTitle()); + collapsiblePanel.setTitleWidget(new HTML(title)); + scrollPanel.setIndex(numaNodeIndex); + scrollPanel.clear(); + for (VNodeModel nodeModel: virtualNodes) { + DraggableVirtualNumaPanel numaNodePanel = virtualNumaPanelProvider.get(); + numaNodePanel.setModel(nodeModel, numaNodeList); + scrollPanel.add(numaNodePanel); + } + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.ui.xml new file mode 100644 index 0000000..5004e3d --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/AssignedVNumaNodesPanel.ui.xml @@ -0,0 +1,12 @@ +<?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" > + + <ui:style type="org.ovirt.engine.ui.common.view.popup.numa.AssignedVNumaNodesPanel.Style"> + .numaTitle { + padding-left: 5px; + } + </ui:style> + + <g:FlowPanel ui:field="container" /> +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.java new file mode 100644 index 0000000..11c4989 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.java @@ -0,0 +1,51 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import org.ovirt.engine.ui.common.CommonApplicationMessages; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +public class CpuSummaryPanel extends Composite { + + interface WidgetUiBinder extends UiBinder<Widget, CpuSummaryPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + private final CommonApplicationMessages messages; + + @UiField + Label nameLabel; + + @UiField + Label totalLabel; + + @UiField + Label percentageLabel; + + @Inject + public CpuSummaryPanel(CommonApplicationMessages messages) { + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + this.messages = messages; + } + + public void setName(String name) { + nameLabel.setTitle(name); + nameLabel.setText(name); + } + + public void setCpus(int totalCpus, int usedPercentage) { + String totalCpusString = messages.numaTotalCpus(totalCpus); + + totalLabel.setTitle(totalCpusString); + totalLabel.setText(totalCpusString); + + String percentageUsed = messages.numaPercentUsed(usedPercentage); + percentageLabel.setTitle(percentageUsed); + percentageLabel.setText(percentageUsed); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.ui.xml new file mode 100644 index 0000000..f000281 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/CpuSummaryPanel.ui.xml @@ -0,0 +1,46 @@ +<?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"> + + <ui:style> + .cpuPanel { + float: left; + padding: 5px; + } + + .nameLabelContainer { + float: left; + padding-right: 5px; + } + + .cpuLabelContainer { + float: left; + } + + .mainText { + font-size: medium; + color: black; + } + + .subText { + font-size: smaller; + color: #AEAEAE; + } + + .clearFloat { + clear: both; + } + </ui:style> + + <g:FlowPanel addStyleNames="{style.cpuPanel}"> + <g:SimplePanel addStyleNames="{style.nameLabelContainer}"> + <g:Label ui:field="nameLabel" addStyleNames="{style.mainText}"/> + </g:SimplePanel> + <g:FlowPanel addStyleNames="{style.cpuLabelContainer}"> + <g:Label ui:field="totalLabel" addStyleNames="{style.mainText}" /> + <g:Label ui:field="percentageLabel" addStyleNames="{style.subText}" /> + </g:FlowPanel> + <g:SimplePanel addStyleNames="{style.clearFloat}" /> + </g:FlowPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.java new file mode 100644 index 0000000..1151f66 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.java @@ -0,0 +1,98 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.ui.common.presenter.popup.numa.UpdatedVnumaEvent; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.DragLeaveEvent; +import com.google.gwt.event.dom.client.DragOverEvent; +import com.google.gwt.event.dom.client.DropEvent; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.event.shared.GwtEvent; +import com.google.gwt.event.shared.HasHandlers; +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.uibinder.client.UiHandler; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.FocusPanel; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +public class DragTargetScrollPanel extends Composite implements HasHandlers { + + interface WidgetUiBinder extends UiBinder<Widget, DragTargetScrollPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + interface Style extends CssResource { + String dragOver(); + } + + private final EventBus eventBus; + + @UiField + FocusPanel container; + + @UiField + FlowPanel dragTargetPanel; + + @UiField + Style style; + + private int pNumaNodeIndex; + + @Inject + public DragTargetScrollPanel(EventBus gwtEventBus) { + this.eventBus = gwtEventBus; + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + } + + public void clear() { + dragTargetPanel.clear(); + } + + public void add(IsWidget widget) { + dragTargetPanel.add(widget); + } + + @Override + public void fireEvent(GwtEvent<?> event) { + eventBus.fireEvent(event); + } + + @UiHandler("container") + void onPanelDragOver(DragOverEvent event) { + container.addStyleName(style.dragOver()); + } + + @UiHandler("container") + void onPanelDragLeave(DragLeaveEvent event) { + container.removeStyleName(style.dragOver()); + } + + @UiHandler("container") + void onPanelDragDrop(DropEvent event) { + Guid vmGuid = Guid.createGuidFromString(event.getData("VM_GID")); //$NON-NLS-1$ + boolean pinned = Boolean.valueOf(event.getData("PINNED")); //$NON-NLS-1$ + int vNumaNodeIndex = Integer.valueOf(event.getData("INDEX")); //$NON-NLS-1$ + container.removeStyleName(style.dragOver()); + event.preventDefault(); + UpdatedVnumaEvent.fire(this, vmGuid, pinned, vNumaNodeIndex, pNumaNodeIndex); + } + + private Pair<Guid, Pair<Boolean, Integer>> parseDropString(String dropString) { + Pair<Boolean, Integer> pinnedIndexPair = new Pair<Boolean, Integer>(); + String[] splitString = dropString.split("_"); //$NON-NLS-1$ + pinnedIndexPair.setFirst(Boolean.valueOf(splitString[1])); + pinnedIndexPair.setSecond(Integer.valueOf(splitString[2])); + return new Pair<Guid, Pair<Boolean, Integer>>(Guid.createGuidFromString(splitString[0]), pinnedIndexPair); + } + + public void setIndex(int numaNodeIndex) { + this.pNumaNodeIndex = numaNodeIndex; + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.ui.xml new file mode 100644 index 0000000..74bb005 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DragTargetScrollPanel.ui.xml @@ -0,0 +1,22 @@ +<?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"> + + <ui:style type="org.ovirt.engine.ui.common.view.popup.numa.DragTargetScrollPanel.Style"> + .scrollPanel { + overflow-y: scroll; + overflow-x: hidden; + max-height: 100px; + height: 100px; + background-color: #EDEDED; + } + + .dragOver { + border: 1px dotted green; + } + </ui:style> + + <g:FocusPanel ui:field="container" addStyleNames="{style.scrollPanel}"> + <g:FlowPanel ui:field="dragTargetPanel" /> + </g:FocusPanel> +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.java new file mode 100644 index 0000000..a4fc50e --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.java @@ -0,0 +1,203 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import java.util.List; + +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.ui.common.CommonApplicationConstants; +import org.ovirt.engine.ui.common.CommonApplicationMessages; +import org.ovirt.engine.ui.common.CommonApplicationResources; +import org.ovirt.engine.ui.common.presenter.popup.numa.NumaVmSelectedEvent; +import org.ovirt.engine.ui.common.presenter.popup.numa.UpdatedVnumaEvent; +import org.ovirt.engine.ui.common.widget.MenuBar; +import org.ovirt.engine.ui.common.widget.PopupPanel; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.event.dom.client.ContextMenuEvent; +import com.google.gwt.event.dom.client.ContextMenuHandler; +import com.google.gwt.event.dom.client.DragStartEvent; +import com.google.gwt.event.dom.client.FocusEvent; +import com.google.gwt.event.dom.client.MouseOutEvent; +import com.google.gwt.event.dom.client.MouseOverEvent; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.event.shared.GwtEvent; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.event.shared.HasHandlers; +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.uibinder.client.UiHandler; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FocusPanel; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +public class DraggableVirtualNumaPanel extends Composite implements HasHandlers { + + interface WidgetUiBinder extends UiBinder<Widget, DraggableVirtualNumaPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + interface Style extends CssResource { + String panelOver(); + } + + static final PopupPanel menuPopup = new PopupPanel(true); + + @UiField + FocusPanel container; + + @UiField(provided=true) + VirtualNumaPanel numaPanel; + + @UiField + Image dragHandle; + + @UiField + Style style; + + private VNodeModel nodeModel; + + private final EventBus eventBus; + + private final CommonApplicationConstants commonConstants; + private final CommonApplicationMessages commonMessages; + + private HandlerRegistration contextMenuHandlerRegistration; + private MenuBar menuBar; + + @Inject + public DraggableVirtualNumaPanel(EventBus gwtEventBus, CommonApplicationResources commonResources, + CommonApplicationMessages messages, CommonApplicationConstants commonConstants, + VirtualNumaPanel virtualNumaPanel) { + numaPanel = virtualNumaPanel; + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + initializeResouceIcons(commonResources); + this.eventBus = gwtEventBus; + this.commonConstants = commonConstants; + this.commonMessages = messages; + enableDrag(true); + } + + @Override + public void onLoad() { + super.onLoad(); + contextMenuHandlerRegistration = numaPanel.addDomHandler(new ContextMenuHandler() { + @Override + public void onContextMenu(ContextMenuEvent event) { + NativeEvent nativeEvent = event.getNativeEvent(); + showContextMenu(nativeEvent.getClientX(), nativeEvent.getClientY()); + event.stopPropagation(); + event.preventDefault(); + } + }, ContextMenuEvent.getType()); + } + + @Override + public void onUnload() { + super.onUnload(); + contextMenuHandlerRegistration.removeHandler(); + } + + private void initializeResouceIcons(CommonApplicationResources resources) { + numaPanel.setPinnedPartialVNumaIcon(resources.pinnedPartialVNumaIcon()); + numaPanel.setPinnedVNumaIcon(resources.pinnedVNumaIcon()); + numaPanel.setPartialVNumaIcon(resources.partialVNumaIcon()); + numaPanel.setvNumaIcon(resources.vNumaIcon()); + } + + @UiHandler("container") + void handleMouseOver(MouseOverEvent event) { + container.addStyleName(style.panelOver()); + dragHandle.setVisible(true); + } + + @UiHandler("container") + void handleMouseOut(MouseOutEvent event) { + container.removeStyleName(style.panelOver()); + dragHandle.setVisible(false); + } + + @UiHandler("container") + void onDragStart(DragStartEvent event) { + event.setData("VM_GID", nodeModel.getVm().getId().toString()); //$NON-NLS-1$ + event.setData("PINNED", String.valueOf(nodeModel.isPinned())); //$NON-NLS-1$ + event.setData("INDEX", String.valueOf(nodeModel.getVmNumaNode().getIndex())); //$NON-NLS-1$ + // show a ghost of the widget under cursor. + NativeEvent nativeEvent = event.getNativeEvent(); + int x = nativeEvent.getClientX() - getAbsoluteLeft(); + int y = nativeEvent.getClientY() - getAbsoluteTop(); + event.getDataTransfer().setDragImage(getElement(), x, y); + } + + @UiHandler("container") + void onFocus(FocusEvent event) { + NumaVmSelectedEvent.fire(this, this.nodeModel); + } + + protected void showContextMenu(int clientX, int clientY) { + menuPopup.setWidget(menuBar); + menuPopup.setPopupPosition(clientX, clientY); + menuPopup.show(); + } + + /** + * Dragging is enabled by default, if you want to alter that behavior, call this method with false. + * @param enable Enabled or disable dragging of this panel. + */ + public void enableDrag(boolean enable) { + if (enable) { + getElement().setDraggable(Element.DRAGGABLE_TRUE); + } else { + getElement().setDraggable(Element.DRAGGABLE_FALSE); + } + } + + @Override + public void setStyleName(String className) { + container.setStyleName(className); + } + + public void setModel(VNodeModel nodeModel, List<VdsNumaNode> numaNodeList) { + numaPanel.setModel(nodeModel); + this.nodeModel = nodeModel; + createMenu(numaNodeList, nodeModel.getVmNumaNode().getIndex()); + } + + private void createMenu(final List<VdsNumaNode> numaNodeList, int indexToSkip) { + menuBar = new MenuBar(true); + for (final VdsNumaNode numaNode : numaNodeList) { + final int nodeIndex = numaNode.getIndex(); + menuBar.addItem(commonMessages.numaNode(nodeIndex), new Command() { + + @Override + public void execute() { + UpdatedVnumaEvent.fire(DraggableVirtualNumaPanel.this, nodeModel.getVm().getId(), + nodeModel.isPinned(), nodeModel.getVmNumaNode().getIndex(), nodeIndex); + menuPopup.hide(); + } + }); + } + if (nodeModel.isPinned()) { + menuBar.addSeparator(); + menuBar.addItem(commonConstants.unPinNode(), new Command() { + + @Override + public void execute() { + UpdatedVnumaEvent.fire(DraggableVirtualNumaPanel.this, nodeModel.getVm().getId(), + nodeModel.isPinned(), nodeModel.getVmNumaNode().getIndex(), -1); + menuPopup.hide(); + } + }); + } + } + + @Override + public void fireEvent(GwtEvent<?> event) { + eventBus.fireEvent(event); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.ui.xml new file mode 100644 index 0000000..640cf76 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/DraggableVirtualNumaPanel.ui.xml @@ -0,0 +1,33 @@ +<?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:onu="urn:import:org.ovirt.engine.ui.common.view.popup.numa"> + + <ui:with field="commonResources" type="org.ovirt.engine.ui.common.CommonApplicationResources" /> + + <ui:style type="org.ovirt.engine.ui.common.view.popup.numa.DraggableVirtualNumaPanel.Style"> + .panel { + background-color: #969696; + color: white; + margin: 1px 15px 1px 15px; + width: 213px; + } + + .imageStyle { + float: left; + padding-left: 5px; + } + + .panelOver { + background-color: #0099d2; + cursor: pointer; + } + </ui:style> + + <g:FocusPanel ui:field="container" addStyleNames="{style.panel}"> + <onu:VirtualNumaPanel ui:field="numaPanel"> + <g:Image ui:field="dragHandle" resource="{commonResources.dragHandleIcon}" addStyleNames="{style.imageStyle}" visible="false"/> + </onu:VirtualNumaPanel> + </g:FocusPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.java new file mode 100644 index 0000000..02ebb76 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.java @@ -0,0 +1,59 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import java.util.List; + +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.ui.common.CommonApplicationMessages; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.FocusPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; +import com.google.inject.Provider; + +public class HostSummaryContentPanel extends Composite { + + interface WidgetUiBinder extends UiBinder<Widget, HostSummaryContentPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + @UiField + FocusPanel numaContainer; + + @UiField + FlowPanel numaPanel; + + @UiField + FocusPanel vNumaContainer; + + @UiField + FlowPanel vNumaPanel; + + @Inject + Provider<VirtualNumaPanel> virtualNumaPanelProvider; + + private final CommonApplicationMessages messages; + + @Inject + public HostSummaryContentPanel(CommonApplicationMessages messages) { + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + this.messages = messages; + } + + public void setModel(List<VdsNumaNode> numaNodes, List<VNodeModel> vNodeModels) { + for(VNodeModel vNodeModel: vNodeModels) { + VirtualNumaPanel panel = virtualNumaPanelProvider.get(); + panel.setModel(vNodeModel); + vNumaPanel.add(panel); + } + for(VdsNumaNode numaNode: numaNodes) { + numaPanel.add(new HTML(messages.numaNode(numaNode.getIndex()))); + } + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.ui.xml new file mode 100644 index 0000000..871816c --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/HostSummaryContentPanel.ui.xml @@ -0,0 +1,50 @@ +<?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:onu="urn:import:org.ovirt.engine.ui.common.view.popup.numa"> + + <ui:style> + .container { + background-color: white; + border: 1px solid #EDEDED; + } + + .fancyBarsContainer { + width: 200px; + min-height: 1px; + float: left; + } + + .scrollPanel { + overflow-y: scroll; + overflow-x: hidden; + max-height: 100px; + height: 100px; + width: 180px; + padding: 5px; + float: left; + border-left: 1px solid #EDEDED; + margin-top: 1px; + } + + .vNumaScrollPanel { + background-color: #EDEDED; + } + + .clearFloat { + clear: both; + } + </ui:style> + + <g:FlowPanel addStyleNames="{style.container}"> + <g:FlowPanel addStyleNames="{style.fancyBarsContainer}" /> + <g:FocusPanel ui:field="numaContainer" addStyleNames="{style.scrollPanel}"> + <g:FlowPanel ui:field="numaPanel" /> + </g:FocusPanel> + <g:FocusPanel ui:field="vNumaContainer" addStyleNames="{style.scrollPanel} {style.vNumaScrollPanel}"> + <g:FlowPanel ui:field="vNumaPanel" /> + </g:FocusPanel> + <g:SimplePanel addStyleNames="{style.clearFloat}" /> + </g:FlowPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.java new file mode 100644 index 0000000..59366a9 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.java @@ -0,0 +1,41 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import org.ovirt.engine.ui.common.CommonApplicationMessages; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +public class MemorySummaryPanel extends Composite { + interface WidgetUiBinder extends UiBinder<Widget, MemorySummaryPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + private final CommonApplicationMessages messages; + + @UiField + Label totalLabel; + + @UiField + Label usedLabel; + + @Inject + public MemorySummaryPanel(CommonApplicationMessages messages) { + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + this.messages = messages; + } + + public void setMemoryStats(long totalMemory, long usedMemory) { + String totalMemoryString = messages.numaMemory(totalMemory); + totalLabel.setTitle(totalMemoryString); + totalLabel.setText(totalMemoryString); + + String usedMemoryString = messages.numaMemoryUsed(usedMemory); + usedLabel.setTitle(usedMemoryString); + usedLabel.setText(usedMemoryString); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.ui.xml new file mode 100644 index 0000000..8c647c4 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/MemorySummaryPanel.ui.xml @@ -0,0 +1,38 @@ +<?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"> + + <ui:style> + .memoryPanel { + float: left; + padding: 5px; + } + + .memoryLabelContainer { + float:left; + } + + .mainText { + font-size: medium; + color: black; + } + + .subText { + font-size: smaller; + color: #555; + } + + .clearFloat { + clear: both; + } + </ui:style> + + <g:FlowPanel addStyleNames="{style.memoryPanel}"> + <g:FlowPanel addStyleNames="{style.memoryLabelContainer}"> + <g:Label ui:field="totalLabel" addStyleNames="{style.mainText}" /> + <g:Label ui:field="usedLabel" addStyleNames="{style.subText}" /> + </g:FlowPanel> + <g:SimplePanel addStyleNames="{style.clearFloat}" /> + </g:FlowPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.java new file mode 100644 index 0000000..7f9a286 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.java @@ -0,0 +1,35 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +public class NumaPanel extends Composite { + interface WidgetUiBinder extends UiBinder<Widget, NumaPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + @UiField(provided=true) + CpuSummaryPanel cpuSummaryPanel; + + @UiField(provided=true) + MemorySummaryPanel memorySummaryPanel; + + @Inject + public NumaPanel(CpuSummaryPanel cpuSummary, MemorySummaryPanel memorySummary) { + this.cpuSummaryPanel = cpuSummary; + this.memorySummaryPanel = memorySummary; + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + } + + public CpuSummaryPanel getCpuSummaryPanel() { + return this.cpuSummaryPanel; + } + + public MemorySummaryPanel getMemorySummaryPanel() { + return this.memorySummaryPanel; + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.ui.xml new file mode 100644 index 0000000..1987187 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaPanel.ui.xml @@ -0,0 +1,23 @@ +<?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:onu="urn:import:org.ovirt.engine.ui.common.view.popup.numa"> + + <ui:style> + .numaPanel { + background-color: white; + color: #eee; + } + + .clearFloat { + clear: both; + } + </ui:style> + + <g:FlowPanel addStyleNames="{style.numaPanel}"> + <onu:CpuSummaryPanel ui:field="cpuSummaryPanel" /> + <onu:MemorySummaryPanel ui:field="memorySummaryPanel" /> + <g:SimplePanel addStyleNames="{style.clearFloat}" /> + </g:FlowPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.java new file mode 100644 index 0000000..52793b0 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.java @@ -0,0 +1,213 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.ovirt.engine.core.common.businessentities.VDS; +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.core.common.businessentities.VmNumaNode; +import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.ui.common.CommonApplicationConstants; +import org.ovirt.engine.ui.common.CommonApplicationMessages; +import org.ovirt.engine.ui.common.CommonApplicationResources; +import org.ovirt.engine.ui.common.idhandler.ElementIdHandler; +import org.ovirt.engine.ui.common.presenter.popup.numa.NumaSupportPopupPresenterWidget; +import org.ovirt.engine.ui.common.system.ClientStorage; +import org.ovirt.engine.ui.common.view.popup.AbstractModelBoundPopupView; +import org.ovirt.engine.ui.common.widget.dialog.SimpleDialogPanel; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.NumaSupportModel; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.resources.client.CssResource; +import com.google.gwt.safehtml.shared.OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.gwt.user.client.ui.SplitLayoutPanel; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.gwtplatform.mvp.client.View; + +public class NumaSupportPopupView extends AbstractModelBoundPopupView<NumaSupportModel> + implements NumaSupportPopupPresenterWidget.ViewDef { + + interface ViewUiBinder extends UiBinder<SimpleDialogPanel, NumaSupportPopupView> { + + ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class); + } + + interface ViewIdHandler extends ElementIdHandler<NumaSupportPopupView> { + + ViewIdHandler idHandler = GWT.create(ViewIdHandler.class); + } + + interface Style extends CssResource { + String hostSummaryNumaTitle(); + } + + static final String DELIMITER = ", "; //$NON-NLS-1$ + private static final int SPLITTER_THICKNESS = 1; + + @Inject + Provider<CpuSummaryPanel> cpuSummaryPanelProvider; + + @Inject + Provider<MemorySummaryPanel> memorySummaryPanelProvider; + + @Inject + Provider<SocketPanel> socketPanelProvider; + + @Inject + Provider<NumaPanel> numaPanelProvider; + + @Inject + Provider<AssignedVNumaNodesPanel> assignedVNumaPanelProvider; + + @Inject + Provider<HostSummaryContentPanel> hostSummaryContentProvider; + + + private final CommonApplicationConstants constants; + private final CommonApplicationMessages messages; + private final CommonApplicationResources resources; + + @UiField + FlowPanel groupPanel; + + @UiField + FlowPanel hostSummaryPanel; + + @UiField + FlowPanel unassignedvNumaNodesContainer; + + @UiField + FlowPanel socketListPanel; + + @UiField(provided = true) + SplitLayoutPanel horizontalSplitLayoutPanel; + + @UiField + Style style; + + final VNumaTitleTemplate vNumaTitleTemplate; + final NumaTitleTemplate numaTitleTemplate; + + @Inject + public NumaSupportPopupView(EventBus eventBus, ClientStorage clientStorage, VNumaTitleTemplate vNumaTitleTemplate, + NumaTitleTemplate numaTitleTemplate, CommonApplicationMessages messages, + CommonApplicationConstants constants, CommonApplicationResources resources) { + super(eventBus, resources); + this.constants = constants; + this.messages = messages; + this.resources = resources; + this.numaTitleTemplate = numaTitleTemplate; + this.vNumaTitleTemplate = vNumaTitleTemplate; + horizontalSplitLayoutPanel = new SplitLayoutPanel(SPLITTER_THICKNESS); + initWidget(ViewUiBinder.uiBinder.createAndBindUi(this)); + ViewIdHandler.idHandler.generateAndSetIds(this); + horizontalSplitLayoutPanel.setWidgetToggleDisplayAllowed(unassignedvNumaNodesContainer, true); + } + + @Override + public void edit(NumaSupportModel object) { + } + + @Override + public NumaSupportModel flush() { + return null; + } + + @Override + public void setUnassignedGroupPanel(View view) { + unassignedvNumaNodesContainer.insert(view, 1); + } + + @Override + public IsWidget getHostSummaryTitle(int totalCpus, int usedCpuPercentage, int totalMemory, int usedMemory, + int totalNumaNodes, int totalVNumaNodes) { + FlowPanel summaryPanel = new FlowPanel(); + CpuSummaryPanel cpuSummaryPanel = this.cpuSummaryPanelProvider.get(); + cpuSummaryPanel.setName(constants.numaSummaryTotals()); + cpuSummaryPanel.setCpus(totalCpus, usedCpuPercentage); + summaryPanel.add(cpuSummaryPanel); + + MemorySummaryPanel memorySummaryPanel = this.memorySummaryPanelProvider.get(); + memorySummaryPanel.setMemoryStats(totalMemory, usedMemory); + summaryPanel.add(memorySummaryPanel); + + summaryPanel.add(new HTML(numaTitleTemplate.title(totalNumaNodes, style.hostSummaryNumaTitle()))); + + String myImageHtml = AbstractImagePrototype.create(resources.vNumaTitleIcon()).getHTML(); + SafeHtml mySafeImageHtml = new OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml(myImageHtml); + summaryPanel.add(new HTML(vNumaTitleTemplate.title(totalVNumaNodes, mySafeImageHtml, + style.hostSummaryNumaTitle()))); + return summaryPanel; + } + + @Override + public IsWidget getHostSummaryContent(VDS selectedItem, NumaSupportModel supportModel) { + HostSummaryContentPanel contentPanel = hostSummaryContentProvider.get(); + + List<VM> vmsWithVNuma = supportModel.getVmsWithvNumaNodeList(); + List<VNodeModel> numaNodes = new ArrayList<VNodeModel>(); + for (VM vm: vmsWithVNuma) { + for(VmNumaNode vmNumaNode: vm.getvNumaNodeList()) { + VNodeModel vNodeModel = new VNodeModel(supportModel, vm, vmNumaNode, false); + if (vmNumaNode.getVdsNumaNodeList() != null && !vmNumaNode.getVdsNumaNodeList().isEmpty()) { + for (Pair<Guid, Pair<Boolean, Integer>> pair : vmNumaNode.getVdsNumaNodeList()) { + if (pair.getSecond().getFirst()) { + vNodeModel.setPinned(true); + } + } + } + numaNodes.add(vNodeModel); + } + } + contentPanel.setModel(supportModel.getNumaNodeList(), numaNodes); + return contentPanel; + } + + @Override + public void setHostSummaryPanel(IsWidget widget) { + this.hostSummaryPanel.add(widget); + } + + @Override + public void addVNumaInfoPanel(Set<VdsNumaNode> numaNodes, int socketIndex, NumaSupportModel supportModel) { + SocketPanel socketPanel = socketPanelProvider.get(); + socketPanel.setHeaderText(messages.numaSocketNumber(socketIndex)); + for (VdsNumaNode numaNode: numaNodes) { + NumaPanel numaPanel = numaPanelProvider.get(); + numaPanel.getCpuSummaryPanel().setName(messages.numaNode(numaNode.getIndex())); + numaPanel.getCpuSummaryPanel().setCpus(numaNode.getCpuIds().size(), + numaNode.getNumaNodeStatistics().getCpuUsagePercent()); + numaPanel.getMemorySummaryPanel().setMemoryStats(numaNode.getMemTotal(), + numaNode.getMemTotal() - numaNode.getNumaNodeStatistics().getMemFree()); + socketPanel.addWidget(numaPanel); + AssignedVNumaNodesPanel assignedPanel = assignedVNumaPanelProvider.get(); + assignedPanel.setNodes(supportModel.getVNumaNodeByNodeId(numaNode.getId()), numaNode.getIndex(), + supportModel.getNumaNodeList()); + socketPanel.addWidget(assignedPanel); + } + this.socketListPanel.add(socketPanel); + } + + @Override + public void displayVmDetails(VNodeModel vNodeModel) { + } + + @Override + public void clear() { + this.socketListPanel.clear(); + this.hostSummaryPanel.clear(); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.ui.xml new file mode 100644 index 0000000..9a38b90 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaSupportPopupView.ui.xml @@ -0,0 +1,78 @@ +<?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:ge="urn:import:org.ovirt.engine.ui.common.widget.editor.generic" + xmlns:e="urn:import:org.ovirt.engine.ui.common.widget.editor" + xmlns:n="urn:import:org.ovirt.engine.ui.common.view.popup.numa"> + + <ui:style type="org.ovirt.engine.ui.common.view.popup.numa.NumaSupportPopupView.Style"> + .header { + background-color: #EFEFEF; + } + + .headerLabel { + float: left; + font-weight: bolder; + font-size: large; + line-height: 35px; + padding-left: 15px; + } + + .hostInfoPanel { + margin: 15px 15px 0px 15px; + border: 1px solid EFEFEF; + } + + .socketScrollPanel { + overflow-y: auto; + } + + .socketListPanel { + float: left; + } + + .endFloat { + clear: both; + } + + .unassignedPanel { + background-color: #EDEDED; + } + + .hostSummaryNumaTitle { + float: left; + padding-left: 5px; + width: 180px; + font-size: medium; + color: black; + padding: 5px; + } + </ui:style> + + <d:SimpleDialogPanel width="1200px" height="700px"> + <d:content> + <g:SplitLayoutPanel ui:field="horizontalSplitLayoutPanel"> + <g:center> + <g:FlowPanel ui:field="groupPanel"> + <g:FlowPanel ui:field="hostSummaryPanel" addStyleNames="{style.hostInfoPanel}"> + </g:FlowPanel> + <g:FlowPanel addStyleNames="{style.socketScrollPanel}"> + <g:FlowPanel ui:field="socketListPanel" addStyleNames="{style.socketListPanel}"/> + </g:FlowPanel> + <g:SimplePanel addStyleNames="{style.endFloat}" /> + </g:FlowPanel> + </g:center> + <g:east size="300"> + <g:FlowPanel ui:field="unassignedvNumaNodesContainer" addStyleNames="{style.unassignedPanel}"> + <g:HTMLPanel> + <g:Label ui:field="unassignedvNumaNodesLabel" /> + </g:HTMLPanel> + </g:FlowPanel> + </g:east> + </g:SplitLayoutPanel> + </d:content> + </d:SimpleDialogPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaTitleTemplate.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaTitleTemplate.java new file mode 100644 index 0000000..de9d89f --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/NumaTitleTemplate.java @@ -0,0 +1,9 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import com.google.gwt.safehtml.client.SafeHtmlTemplates; +import com.google.gwt.safehtml.shared.SafeHtml; + +public interface NumaTitleTemplate extends SafeHtmlTemplates { + @Template("<div class=\"{1}\">{0} NUMA</div>") + SafeHtml title(int count, String className); +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.java new file mode 100644 index 0000000..a33fa69 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.java @@ -0,0 +1,35 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; + +public class SocketPanel extends Composite { + interface WidgetUiBinder extends UiBinder<Widget, SocketPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + @UiField + FlowPanel container; + + @UiField + Label headerLabel; + + public SocketPanel() { + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + } + + public void setHeaderText(SafeHtml text) { + headerLabel.setText(text.asString()); + } + + public void addWidget(IsWidget widget) { + container.add(widget); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.ui.xml new file mode 100644 index 0000000..09f653a --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/SocketPanel.ui.xml @@ -0,0 +1,29 @@ +<?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"> + + <ui:style> + .header { + width: 100%; + background-color: #EDEDED; + padding-left: 15px; + font-weight: bold; + } + + .socketPanel { + border: 1px #EDEDED solid; + width: 260px; + float: left; + margin-left: 15px; + margin-top: 15px; + } + </ui:style> + + <g:FocusPanel addStyleNames="{style.socketPanel}"> + <g:FlowPanel> + <g:Label ui:field="headerLabel" addStyleNames="{style.header}"/> + <g:FlowPanel ui:field="container" /> + </g:FlowPanel> + </g:FocusPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.java new file mode 100644 index 0000000..e2bae18 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.java @@ -0,0 +1,129 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import java.util.List; + +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.ui.common.CommonApplicationConstants; +import org.ovirt.engine.ui.common.presenter.popup.numa.UnassignedVNumaNodesPanelPresenterWidget; +import org.ovirt.engine.ui.common.view.AbstractView; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.CssResource; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.gwtplatform.mvp.client.View; + +public class UnassignedVNumaNodesPanelView extends AbstractView implements + UnassignedVNumaNodesPanelPresenterWidget.ViewDef { + + interface ViewUiBinder extends UiBinder<Widget, UnassignedVNumaNodesPanelView> { + ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class); + } + + interface Style extends CssResource { + String scrollPanel(); + + String unassignPanel(); + + String emptyPanel(); + } + + private static final int UNASSIGNED = -1; //-1 means unassigned NUMA NODE. + + @UiField + Label unassignedHeaderLabel; + + @UiField + Label instructionsLabel; + + @UiField + FlowPanel unassignedNodesPanel; + + @UiField + FlowPanel nodeDetailPanel; + + @UiField + Style style; + + @UiField(provided=true) + final CommonApplicationConstants commonConstants; + + private final Provider<VmTitlePanel> vmTitlePanelProvider; + private final Provider<DraggableVirtualNumaPanel> virtualNumaPanelProvider; + private final Provider<DragTargetScrollPanel> scrollPanelProvider; + + /** + * Constructor. + */ + @Inject + public UnassignedVNumaNodesPanelView(final Provider<VmTitlePanel> vmTitlePanelProvider, + final Provider<DraggableVirtualNumaPanel> virtualNumaPanelProvider, + Provider<DragTargetScrollPanel> scrollPanelProvider, final CommonApplicationConstants commonConstants) { + this.commonConstants = commonConstants; + this.vmTitlePanelProvider = vmTitlePanelProvider; + this.virtualNumaPanelProvider = virtualNumaPanelProvider; + this.scrollPanelProvider = scrollPanelProvider; + initWidget(ViewUiBinder.uiBinder.createAndBindUi(this)); + } + + private void addVNumaNode(IsWidget widget) { + unassignedNodesPanel.add(widget); + } + + @Override + public void addToUnassignedPanel(View view) { + addVNumaNode(view); + } + + @Override + public IsWidget getNodePanelTitle(VM vm, List<VNodeModel> list) { + VmTitlePanel titlePanel = vmTitlePanelProvider.get(); + SafeHtmlBuilder builder = new SafeHtmlBuilder(); + builder.appendEscaped(vm.getName()); + titlePanel.initWidget(builder.toSafeHtml(), list.size(), vm.getStatus()); + return titlePanel; + } + + @Override + public IsWidget getNodePanelContent(VM vm, List<VNodeModel> virtualNodes, List<VdsNumaNode> numaNodeList) { + DragTargetScrollPanel scrollPanel = getScrollPanel(); + scrollPanel.clear(); + for (VNodeModel nodeModel: virtualNodes) { + DraggableVirtualNumaPanel numaNodePanel = virtualNumaPanelProvider.get(); + numaNodePanel.setModel(nodeModel, numaNodeList); + scrollPanel.add(numaNodePanel); + } + if (virtualNodes.isEmpty()) { + scrollPanel.addStyleName(style.emptyPanel()); + } + return scrollPanel; + } + + @Override + public void addEmptyUnassignPanel() { + DragTargetScrollPanel scrollPanel = getScrollPanel(); + scrollPanel.addStyleName(style.unassignPanel()); + addVNumaNode(scrollPanel); + } + + private DragTargetScrollPanel getScrollPanel() { + DragTargetScrollPanel scrollPanel = scrollPanelProvider.get(); + scrollPanel.setStyleName(style.scrollPanel()); + scrollPanel.setIndex(UNASSIGNED); + return scrollPanel; + } + + @Override + public void clear() { + unassignedNodesPanel.clear(); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.ui.xml new file mode 100644 index 0000000..3e1fd99 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/UnassignedVNumaNodesPanelView.ui.xml @@ -0,0 +1,64 @@ +<?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"> + + <ui:with field="commonConstants" type="org.ovirt.engine.ui.common.CommonApplicationConstants" /> + + <ui:style type="org.ovirt.engine.ui.common.view.popup.numa.UnassignedVNumaNodesPanelView.Style"> + .unassignedPanelContainer { + height: 380px; + } + + .unassignedNodesPanel { + overflow-y: scroll; + background-color: white; + border: 1px solid #DADADA; + margin: 15px; + padding: 5px; + height: 260px; + } + + .headerLabel { + font-size: medium; + color: #75797D; + } + + .instructionLabel { + font-size: smaller; + color: #AEAEAE; + } + + .labelContainer { + padding: 15px; + } + + .scrollPanel { + background-color: white; + overflow-y: auto; + height: auto; + } + + .unassignPanel { + min-height: 75px; + margin: 15px; + border: 1px dashed #DADADA; + } + + .emptyPanel { + min-height: 35px; + margin-left: 15px; + margin-right: 15px; + border: 1px dashed #DADADA; + } + </ui:style> + + <g:FlowPanel addStyleNames="{style.unassignedPanelContainer}"> + <g:FlowPanel addStyleNames="{style.labelContainer}"> + <g:Label ui:field="unassignedHeaderLabel" addStyleNames="{style.headerLabel}" text="{commonConstants.numaUnassignedInstructions}" /> + <g:Label ui:field="instructionsLabel" addStyleNames="{style.instructionLabel}" text="{commonConstants.unassignedVNumaNodesLabel}"/> + </g:FlowPanel> + <g:FlowPanel ui:field="unassignedNodesPanel" addStyleNames="{style.unassignedNodesPanel}"/> + <g:FlowPanel ui:field="nodeDetailPanel" /> + </g:FlowPanel> +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VNumaTitleTemplate.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VNumaTitleTemplate.java new file mode 100644 index 0000000..b6f9aa1 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VNumaTitleTemplate.java @@ -0,0 +1,9 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import com.google.gwt.safehtml.client.SafeHtmlTemplates; +import com.google.gwt.safehtml.shared.SafeHtml; + +public interface VNumaTitleTemplate extends SafeHtmlTemplates { + @Template("<div class=\"{2}\">{0} {1} vNuma</div>") + SafeHtml title(int count, SafeHtml image, String className); +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.java new file mode 100644 index 0000000..82b4c07 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.java @@ -0,0 +1,154 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import java.util.Iterator; + +import org.ovirt.engine.core.common.businessentities.VMStatus; +import org.ovirt.engine.ui.common.CommonApplicationMessages; +import org.ovirt.engine.ui.common.CommonApplicationResources; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HasWidgets; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +public class VirtualNumaPanel extends Composite implements HasWidgets { + interface WidgetUiBinder extends UiBinder<Widget, VirtualNumaPanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + @UiField(provided=true) + final CommonApplicationResources commonResources; + + protected final CommonApplicationMessages messages; + + @UiField + FlowPanel container; + + @UiField + Image virtualNodeStatus; + + @UiField + Image numaState; + + @UiField + Label virtualNodeName; + + ImageResource vNumaIcon; + ImageResource partialVNumaIcon; + ImageResource pinnedVNumaIcon; + ImageResource pinnedPartialVNumaIcon; + + @Inject + public VirtualNumaPanel(CommonApplicationResources commonResources, CommonApplicationMessages messages) { + this.commonResources = commonResources; + this.messages = messages; + initializeResouceIcons(commonResources); + + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + } + + private void initializeResouceIcons(CommonApplicationResources resources) { + pinnedPartialVNumaIcon = resources.darkPinnedPartialVNumaIcon(); + pinnedVNumaIcon = resources.darkPinnedVNumaIcon(); + partialVNumaIcon = resources.darkPartialVNumaIcon(); + vNumaIcon = resources.darkVNumaIcon(); + } + + @Override + public void setStyleName(String className) { + container.setStyleName(className); + } + + public void setModel(VNodeModel nodeModel) { + virtualNodeName.setText(messages.vNumaName(nodeModel.getVm().getName(), nodeModel.getVmNumaNode().getIndex())); + setStatusIcon(nodeModel); + setTypeIcon(nodeModel); + } + + protected void setStatusIcon(VNodeModel nodeModel) { + if (VMStatus.Up.equals(nodeModel.getVm().getStatus())) { + virtualNodeStatus.setResource(commonResources.upImage()); + } else if (VMStatus.Down.equals(nodeModel.getVm().getStatus())) { + virtualNodeStatus.setResource(commonResources.downImage()); + } else { + //Unknown status + virtualNodeStatus.setResource(commonResources.questionMarkImage()); + } + } + + protected void setTypeIcon(VNodeModel nodeModel) { + if (nodeModel.isPinned()) { + if (nodeModel.isSplitted()) { + numaState.setResource(pinnedPartialVNumaIcon); + } else { + numaState.setResource(pinnedVNumaIcon); + } + } else { + if (nodeModel.isSplitted()) { + numaState.setResource(partialVNumaIcon); + } else { + numaState.setResource(vNumaIcon); + } + } + } + + public ImageResource getvNumaIcon() { + return vNumaIcon; + } + + public void setvNumaIcon(ImageResource vNumaIcon) { + this.vNumaIcon = vNumaIcon; + } + + public ImageResource getPartialVNumaIcon() { + return partialVNumaIcon; + } + + public void setPartialVNumaIcon(ImageResource partialVNumaIcon) { + this.partialVNumaIcon = partialVNumaIcon; + } + + public ImageResource getPinnedVNumaIcon() { + return pinnedVNumaIcon; + } + + public void setPinnedVNumaIcon(ImageResource pinnedVNumaIcon) { + this.pinnedVNumaIcon = pinnedVNumaIcon; + } + + public ImageResource getPinnedPartialVNumaIcon() { + return pinnedPartialVNumaIcon; + } + + public void setPinnedPartialVNumaIcon(ImageResource pinnedPartialVNumaIcon) { + this.pinnedPartialVNumaIcon = pinnedPartialVNumaIcon; + } + + @Override + public void add(Widget w) { + container.insert(w, 0); + } + + @Override + public void clear() { + throw new RuntimeException("Can't clear this widget"); //$NON-NLS-1$ + } + + @Override + public Iterator<Widget> iterator() { + return container.iterator(); + } + + @Override + public boolean remove(Widget w) { + return container.remove(w); + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.ui.xml new file mode 100644 index 0000000..d33c838 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VirtualNumaPanel.ui.xml @@ -0,0 +1,30 @@ +<?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:onu="urn:import:org.ovirt.engine.ui.common.view.popup.numa"> + + <ui:with field="commonResources" type="org.ovirt.engine.ui.common.CommonApplicationResources" /> + + <ui:style> + .imageStyle { + float: left; + padding-left: 5px; + } + + .vmStatusIcon { + margin-top: 4px; + } + + .clearFloat { + clear: both; + } + </ui:style> + + <g:FlowPanel ui:field="container"> + <g:Image ui:field="virtualNodeStatus" resource="{commonResources.downImage}" addStyleNames="{style.imageStyle} {style.vmStatusIcon}" /> + <g:Image ui:field="numaState" resource="{commonResources.vNumaIcon}" addStyleNames="{style.imageStyle}" /> + <g:Label ui:field="virtualNodeName" addStyleNames="{style.imageStyle}" /> + <g:SimplePanel addStyleNames="{style.clearFloat}" /> + </g:FlowPanel> + +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.java new file mode 100644 index 0000000..16a9510 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.java @@ -0,0 +1,56 @@ +package org.ovirt.engine.ui.common.view.popup.numa; + +import org.ovirt.engine.core.common.businessentities.VMStatus; +import org.ovirt.engine.ui.common.CommonApplicationResources; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +public class VmTitlePanel extends Composite { + + interface WidgetUiBinder extends UiBinder<Widget, VmTitlePanel> { + WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class); + } + + @UiField(provided=true) + final CommonApplicationResources commonResources; + + @UiField + Image vmStatus; + + @UiField + Label vmName; + + @UiField + Label nodeCountLabel; + + @Inject + public VmTitlePanel(CommonApplicationResources commonResources) { + this.commonResources = commonResources; + initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this)); + } + + public void initWidget(SafeHtml vmNameString, int nodeCount, VMStatus status) { + vmName.setText(vmNameString.asString()); + nodeCountLabel.setText(String.valueOf(nodeCount)); + setStatusIcon(status); + } + + private void setStatusIcon(VMStatus status) { + if (VMStatus.Up.equals(status)) { + vmStatus.setResource(commonResources.upImage()); + } else if (VMStatus.Down.equals(status)) { + vmStatus.setResource(commonResources.downImage()); + } else { + //Unknown status + vmStatus.setResource(commonResources.questionMarkImage()); + } + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.ui.xml b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.ui.xml new file mode 100644 index 0000000..93b1956 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/numa/VmTitlePanel.ui.xml @@ -0,0 +1,44 @@ +<?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"> + + <ui:with field="commonResources" type="org.ovirt.engine.ui.common.CommonApplicationResources" /> + + <ui:style> + .container { + background-color: white; + width: 100%; + } + + .itemStyle { + float: left; + padding-left: 5px; + } + + .vmStatusIcon { + margin-top: 4px; + } + + .nodeCountLabel { + float: right; + background-color: #B7B7B7; + margin: 3px; + color: white; + min-width: 20px; + text-align: center; + } + + .clearFloat { + clear: both; + } + </ui:style> + + <g:FlowPanel addStyleNames="{style.container}"> + <g:Image ui:field="vmStatus" resource="{commonResources.downImage}" addStyleNames="{style.itemStyle} {style.vmStatusIcon}" /> + <g:Label ui:field="vmName" addStyleNames="{style.itemStyle}" /> + <g:SimplePanel addStyleNames="{style.nodeCountLabel}"> + <g:Label ui:field="nodeCountLabel" /> + </g:SimplePanel> + <g:SimplePanel addStyleNames="{style.clearFloat}" /> + </g:FlowPanel> +</ui:UiBinder> diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/collapsed_header_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/collapsed_header_icon.png new file mode 100644 index 0000000..94ca3bc --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/collapsed_header_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/expanded_header_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/expanded_header_icon.png new file mode 100644 index 0000000..3a8dc18 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/expanded_header_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/drag_handle.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/drag_handle.png new file mode 100644 index 0000000..25f3a39 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/drag_handle.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_dark_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_dark_icon.png new file mode 100644 index 0000000..fdf9a77 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_dark_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_light_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_light_icon.png new file mode 100644 index 0000000..f9b1eb5 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/partial_vnuma_light_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_dark_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_dark_icon.png new file mode 100644 index 0000000..8eb1624 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_dark_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_light_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_light_icon.png new file mode 100644 index 0000000..ce3efdc --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_partial_vnuma_light_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_dark_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_dark_icon.png new file mode 100644 index 0000000..775b6e8 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_dark_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_light_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_light_icon.png new file mode 100644 index 0000000..0850b18 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/pinned_vnuma_light_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_dark_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_dark_icon.png new file mode 100644 index 0000000..b743e18 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_dark_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_icon.png new file mode 100644 index 0000000..233ded6 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_icon.png Binary files differ diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_light_icon.png b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_light_icon.png new file mode 100644 index 0000000..e740cf0 --- /dev/null +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/ui/common/images/numa/vnuma_light_icon.png Binary files differ 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 4bd10b5..2f80c4d 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 @@ -37,6 +37,7 @@ import org.ovirt.engine.core.common.businessentities.IVdcQueryable; import org.ovirt.engine.core.common.businessentities.ImageFileType; import org.ovirt.engine.core.common.businessentities.LUNs; +import org.ovirt.engine.core.common.businessentities.NumaTuneMode; import org.ovirt.engine.core.common.businessentities.Permissions; import org.ovirt.engine.core.common.businessentities.Provider; import org.ovirt.engine.core.common.businessentities.ProviderType; @@ -57,6 +58,7 @@ import org.ovirt.engine.core.common.businessentities.VDSGroup; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; import org.ovirt.engine.core.common.businessentities.VmGuestAgentInterface; import org.ovirt.engine.core.common.businessentities.VmPool; import org.ovirt.engine.core.common.businessentities.VmTemplate; @@ -84,8 +86,8 @@ import org.ovirt.engine.core.common.businessentities.profiles.DiskProfile; import org.ovirt.engine.core.common.interfaces.SearchType; import org.ovirt.engine.core.common.mode.ApplicationMode; -import org.ovirt.engine.core.common.queries.ArchCapabilitiesParameters.ArchCapabilitiesVerb; import org.ovirt.engine.core.common.queries.ArchCapabilitiesParameters; +import org.ovirt.engine.core.common.queries.ArchCapabilitiesParameters.ArchCapabilitiesVerb; import org.ovirt.engine.core.common.queries.CommandVersionsInfo; import org.ovirt.engine.core.common.queries.ConfigurationValues; import org.ovirt.engine.core.common.queries.GetAgentFenceOptionsQueryParameters; @@ -115,8 +117,8 @@ import org.ovirt.engine.core.common.queries.InterfaceAndIdQueryParameters; import org.ovirt.engine.core.common.queries.MultilevelAdministrationsQueriesParameters; import org.ovirt.engine.core.common.queries.NameQueryParameters; -import org.ovirt.engine.core.common.queries.OsQueryParameters.OsRepositoryVerb; import org.ovirt.engine.core.common.queries.OsQueryParameters; +import org.ovirt.engine.core.common.queries.OsQueryParameters.OsRepositoryVerb; import org.ovirt.engine.core.common.queries.ProviderQueryParameters; import org.ovirt.engine.core.common.queries.SearchParameters; import org.ovirt.engine.core.common.queries.ServerParameters; @@ -3806,4 +3808,43 @@ }; } + public static void getHostNumaTopologyByHostId(AsyncQuery asyncQuery, Guid hostId) { + asyncQuery.converterCallback = new IAsyncConverter() { + + @Override + public Object Convert(Object source, AsyncQuery asyncQuery) { + if (source == null) { + return new ArrayList<VdsNumaNode>(); + } + return source; + } + }; + Frontend.getInstance().runQuery(VdcQueryType.GetVdsNumaNodesByVdsId, + new IdQueryParameters(hostId), + asyncQuery); + } + + public static void getVMsWithVNumaNodesByClusterId(AsyncQuery asyncQuery, Guid clusterId) { + asyncQuery.converterCallback = new IAsyncConverter() { + + @Override + public Object Convert(Object source, AsyncQuery asyncQuery) { + if (source == null) { + return new ArrayList<VM>(); + } + return source; + } + }; + Frontend.getInstance().runQuery(VdcQueryType.GetAllVmsWithNumaByVdsGroupId, + new IdQueryParameters(clusterId), + asyncQuery); + } + + public static ArrayList<NumaTuneMode> getNumaTuneModeList() { + return new ArrayList<NumaTuneMode>(Arrays.asList(new NumaTuneMode[] { + NumaTuneMode.STRICT, + NumaTuneMode.PREFERRED, + NumaTuneMode.INTERLEAVE + })); + } } 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 05ebc6d..626f0fa 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 @@ -510,7 +510,9 @@ edit_cpu_profile("edit_cpu_profile", HelpTagType.WEBADMIN, "Cluster Tab > Cpu Profiles sub-tab -> Edit Cpu Profile dialog"), //$NON-NLS-1$ //$NON-NLS-2$ - remove_cpu_profile("remove_cpu_profile", HelpTagType.WEBADMIN, "Clsuter Tab > Cpu Profiles sub-tab -> Remove Cpu Profile dialog"); //$NON-NLS-1$ //$NON-NLS-2$ + remove_cpu_profile("remove_cpu_profile", HelpTagType.WEBADMIN, "Clsuter Tab > Cpu Profiles sub-tab -> Remove Cpu Profile dialog"), //$NON-NLS-1$ //$NON-NLS-2$ + + numa_support("numa_support", HelpTagType.WEBADMIN, "Hosts maint tab -> NUMA Support"); //$NON-NLS-1$ //$NON-NLS-2$ public final String name; diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostListModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostListModel.java index 430664d..6dd6870 100644 --- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostListModel.java +++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostListModel.java @@ -40,8 +40,10 @@ import org.ovirt.engine.core.common.businessentities.VDSGroup; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VDSType; +import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VdsProtocol; import org.ovirt.engine.core.common.businessentities.VdsSpmStatus; +import org.ovirt.engine.core.common.businessentities.VmNumaNode; import org.ovirt.engine.core.common.businessentities.aaa.DbUser; import org.ovirt.engine.core.common.interfaces.SearchType; import org.ovirt.engine.core.common.mode.ApplicationMode; @@ -76,6 +78,7 @@ import org.ovirt.engine.ui.uicommonweb.models.events.TaskListModel; import org.ovirt.engine.ui.uicommonweb.models.gluster.GlusterFeaturesUtil; import org.ovirt.engine.ui.uicommonweb.models.gluster.HostGlusterSwiftListModel; +import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.NumaSupportModel; import org.ovirt.engine.ui.uicommonweb.models.tags.TagListModel; import org.ovirt.engine.ui.uicommonweb.models.tags.TagModel; import org.ovirt.engine.ui.uicompat.ConstantsManager; @@ -303,6 +306,16 @@ refreshCapabilitiesCommand = value; } + private UICommand numaSupportCommand; + + public UICommand getNumaSupportCommand() { + return numaSupportCommand; + } + + public void setNumaSupportCommand(UICommand numaSupportCommand) { + this.numaSupportCommand = numaSupportCommand; + } + private HostEventListModel privateHostEventListModel; private HostEventListModel getHostEventListModel() @@ -405,7 +418,7 @@ setAssignTagsCommand(new UICommand("AssignTags", this)); //$NON-NLS-1$ setConfigureLocalStorageCommand(new UICommand("ConfigureLocalStorage", this)); //$NON-NLS-1$ setRefreshCapabilitiesCommand(new UICommand("GetCapabilities", this)); //$NON-NLS-1$ - + setNumaSupportCommand(new UICommand("NumaSupport", this)); //$NON-NLS-1$ getConfigureLocalStorageCommand().setAvailableInModes(ApplicationMode.VirtOnly); getSelectAsSpmCommand().setAvailableInModes(ApplicationMode.VirtOnly); updateActionAvailability(); @@ -2076,6 +2089,13 @@ getRefreshCapabilitiesCommand().setIsExecutionAllowed(items.size() > 0 && VdcActionUtils.canExecute(items, VDS.class, VdcActionType.RefreshHostCapabilities)); + + boolean numaVisible = false; + if (getSelectedItem() != null) { + numaVisible = ((VDS) getSelectedItem()).isNumaSupport(); + } + getNumaSupportCommand().setIsVisible(numaVisible); + } private Boolean hasAdminSystemPermission = null; @@ -2213,6 +2233,9 @@ { refreshCapabilities(); } + else if (command == getNumaSupportCommand()) { + numaSupport(); + } else if ("OnAssignTags".equals(command.getName())) //$NON-NLS-1$ { onAssignTags(); @@ -2277,6 +2300,43 @@ { onConfigureLocalStorage(); } + else if (NumaSupportModel.SUBMIT_NUMA_SUPPORT.equals(command.getName())) { + onNumaSupport(); + } + } + + private void numaSupport() { + if (getWindow() != null) { + return; + } + + VDS host = (VDS) getSelectedItem(); + List<VDS> hosts = getSelectedItems(); + + NumaSupportModel model = new NumaSupportModel(hosts, host, this); + setWindow(model); + } + + private void onNumaSupport() { + if (getWindow() == null) { + return; + } + NumaSupportModel model = (NumaSupportModel) getWindow(); + ArrayList<VdcActionParametersBase> updateParamsList = model.getUpdateParameters(); + if (!updateParamsList.isEmpty()) { + Frontend.getInstance().runMultipleAction(VdcActionType.UpdateVmNumaNodes, updateParamsList); + } + setWindow(null); + } + + private void updateVNodesMap(VM vm, Map<Guid, VmNumaNode> map) { + List<VmNumaNode> list = new ArrayList<VmNumaNode>(); + for (VmNumaNode node : vm.getvNumaNodeList()) { + list.add(node); + } + for (VmNumaNode node : list) { + map.put(node.getId(), node); + } } private void selectAsSPM() { diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/NumaSupportModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/NumaSupportModel.java new file mode 100644 index 0000000..c5d3a57 --- /dev/null +++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/NumaSupportModel.java @@ -0,0 +1,302 @@ +package org.ovirt.engine.ui.uicommonweb.models.hosts.numa; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.ovirt.engine.core.common.action.VdcActionParametersBase; +import org.ovirt.engine.core.common.action.VmNumaNodeOperationParameters; +import org.ovirt.engine.core.common.businessentities.VDS; +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VdsNumaNode; +import org.ovirt.engine.core.common.businessentities.VmNumaNode; +import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.ui.frontend.AsyncQuery; +import org.ovirt.engine.ui.frontend.INewAsyncCallback; +import org.ovirt.engine.ui.uicommonweb.UICommand; +import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider; +import org.ovirt.engine.ui.uicommonweb.help.HelpTag; +import org.ovirt.engine.ui.uicommonweb.models.ListModel; +import org.ovirt.engine.ui.uicommonweb.models.Model; +import org.ovirt.engine.ui.uicompat.ConstantsManager; +import org.ovirt.engine.ui.uicompat.Event; +import org.ovirt.engine.ui.uicompat.EventArgs; +import org.ovirt.engine.ui.uicompat.EventDefinition; +import org.ovirt.engine.ui.uicompat.IEventListener; + +public class NumaSupportModel extends Model { + + public static final String SUBMIT_NUMA_SUPPORT = "SubmitNumaSupport"; //$NON-NLS-1$ + private final Model parentModel; + private ListModel<VDS> hosts; + private List<VdsNumaNode> numaNodeList; + private List<VM> vmsWithvNumaNodeList; + private List<VNodeModel> unassignedVNodeModelList; + private Map<Guid, List<VNodeModel>> p2vNumaNodesMap; + private List<Pair<Integer, Set<VdsNumaNode>>> firstLevelDistanceSetList; + private final Event modelReady = new Event(new EventDefinition("ModelReady", NumaSupportModel.class)); //$NON-NLS-1$ + private Map<Integer, VdsNumaNode> indexNodeMap; + private final Map<Guid, VdcActionParametersBase> updateParametersMap = new HashMap<Guid, VdcActionParametersBase>(); + + public NumaSupportModel(List<VDS> hosts, VDS host, Model parentModel) { + this.parentModel = parentModel; + setHosts(new ListModel<VDS>()); + setNumaNodeList(new ArrayList<VdsNumaNode>()); + setTitle(ConstantsManager.getInstance().getMessages().numaTopologyTitle(host.getName())); + setHelpTag(HelpTag.numa_support); + setHashName("numa_support"); //$NON-NLS-1$ + initCommands(); + initHosts(hosts, host); + } + + private void initHosts(List<VDS> hosts, VDS host) { + getHosts().setItems(hosts); + if (host == null) { + host = hosts.get(0); + } + if (getHosts().getItems().size() <= 1) { + getHosts().setIsChangable(false); + } + getHosts().getSelectedItemChangedEvent().addListener(new IEventListener() { + + @Override + public void eventRaised(Event ev, Object sender, EventArgs args) { + initHostNUMATopology(); + } + }); + getHosts().setSelectedItem(host); + } + + protected void initCommands() { + UICommand command = new UICommand(SUBMIT_NUMA_SUPPORT, this); + command.setTitle(ConstantsManager.getInstance().getConstants().ok()); + getCommands().add(command); + + command = new UICommand("Cancel", this); //$NON-NLS-1$ + command.setTitle(ConstantsManager.getInstance().getConstants().cancel()); + command.setIsCancel(true); + command.setIsDefault(true); + getCommands().add(command); + } + + protected void initHostNUMATopology() { + startProgress(null); + AsyncDataProvider.getHostNumaTopologyByHostId(new AsyncQuery(new INewAsyncCallback() { + + @SuppressWarnings("unchecked") + @Override + public void onSuccess(Object model, Object returnValue) { + // TODO: host query can be skipped in case it was already fetched. + NumaSupportModel.this.getNumaNodeList().addAll((List<VdsNumaNode>) returnValue); + NumaSupportModel.this.initFirstLevelDistanceSetList(); + AsyncDataProvider.getVMsWithVNumaNodesByClusterId(new AsyncQuery(new INewAsyncCallback() { + + @Override + public void onSuccess(Object model, Object returnValue) { + NumaSupportModel.this.setVmsWithvNumaNodeList((List<VM>) returnValue); + NumaSupportModel.this.modelReady(); + } + + }), NumaSupportModel.this.hosts.getSelectedItem().getVdsGroupId()); + } + + }), hosts.getSelectedItem().getId()); + } + + private void initVNumaNodes() { + unassignedVNodeModelList = new ArrayList<VNodeModel>(); + p2vNumaNodesMap = new HashMap<Guid, List<VNodeModel>>(); + + for (VM vm : getVmsWithvNumaNodeList()) { + if (vm.getvNumaNodeList() != null) { + for (VmNumaNode vmNumaNode : vm.getvNumaNodeList()) { + VNodeModel vNodeModel = new VNodeModel(this, vm, vmNumaNode, false); + if (vmNumaNode.getVdsNumaNodeList() != null && !vmNumaNode.getVdsNumaNodeList().isEmpty()) { + for (Pair<Guid, Pair<Boolean, Integer>> pair : vmNumaNode.getVdsNumaNodeList()) { + if (!pair.getSecond().getFirst()) { + unassignedVNodeModelList.add(vNodeModel); + break; + } else { + vNodeModel.setPinned(true); + Guid nodeId = pair.getFirst(); + assignVNumaToPhysicalNuma(vNodeModel, nodeId); + } + } + } else { + unassignedVNodeModelList.add(vNodeModel); + } + } + } + } + } + + private void assignVNumaToPhysicalNuma(VNodeModel vNodeModel, Guid nodeId) { + if (!p2vNumaNodesMap.containsKey(nodeId)) { + p2vNumaNodesMap.put(nodeId, new ArrayList<VNodeModel>()); + } + p2vNumaNodesMap.get(nodeId) + .add(vNodeModel); + } + + private VdsNumaNode getNodeByIndex(Integer index) { + if (indexNodeMap == null) { + indexNodeMap = new HashMap<Integer, VdsNumaNode>(); + for (VdsNumaNode node : getNumaNodeList()) { + indexNodeMap.put(node.getIndex(), node); + } + } + return indexNodeMap.get(index); + } + + public List<VNodeModel> getVNumaNodeByNodeId(Guid nodeId) { + return p2vNumaNodesMap.get(nodeId); + } + + private void initFirstLevelDistanceSetList() { + firstLevelDistanceSetList = new ArrayList<Pair<Integer, Set<VdsNumaNode>>>(); + for (VdsNumaNode node : getNumaNodeList()) { + Map<Integer, Set<VdsNumaNode>> distances = new HashMap<Integer, Set<VdsNumaNode>>(); + for (Entry<Integer, Integer> entry : node.getNumaNodeDistances().entrySet()) { + Set<VdsNumaNode> sameDistanceNodes = distances.get(entry.getValue()); + if (sameDistanceNodes == null) { + sameDistanceNodes = new HashSet<VdsNumaNode>(); + sameDistanceNodes.add(getNodeByIndex(entry.getKey())); + distances.put(entry.getValue(), sameDistanceNodes); + } + sameDistanceNodes.add(node); + } + + Entry<Integer, Set<VdsNumaNode>> minDistance = null; + for (Entry<Integer, Set<VdsNumaNode>> entry : distances.entrySet()) { + if (minDistance == null || entry.getKey() < minDistance.getKey()) { + minDistance = entry; + } + } + + boolean found = false; + for (Pair<Integer, Set<VdsNumaNode>> group : firstLevelDistanceSetList) { + // 'true' if the two specified collections have no elements in common + boolean isDisjoint = Collections.disjoint(group.getSecond(), minDistance.getValue()); + if (group.getFirst().equals(minDistance.getKey()) && !isDisjoint) { + group.getSecond().addAll(minDistance.getValue()); + found = true; + break; + } + } + if (!found && minDistance != null) { + firstLevelDistanceSetList.add(new Pair<Integer, Set<VdsNumaNode>>(minDistance.getKey(), + minDistance.getValue())); + } + } + } + + private void modelReady() { + initVNumaNodes(); + getModelReady().raise(this, EventArgs.EMPTY); + stopProgress(); + } + + public void cancel() { + parentModel.setWindow(null); + } + + public List<VdsNumaNode> getNumaNodeList() { + return numaNodeList; + } + + public void setNumaNodeList(List<VdsNumaNode> numaNodeList) { + this.numaNodeList = numaNodeList; + } + + public List<VM> getVmsWithvNumaNodeList() { + return vmsWithvNumaNodeList; + } + + public void setVmsWithvNumaNodeList(List<VM> vmsWithvNumaNodeList) { + this.vmsWithvNumaNodeList = vmsWithvNumaNodeList; + } + + public List<VNodeModel> getUnassignedVNodeModelList() { + return unassignedVNodeModelList; + } + + public List<Pair<Integer, Set<VdsNumaNode>>> getFirstLevelDistanceSetList() { + return firstLevelDistanceSetList; + } + + public void setFirstLevelDistanceSetList(List<Pair<Integer, Set<VdsNumaNode>>> firstLevelDistanceSetList) { + this.firstLevelDistanceSetList = firstLevelDistanceSetList; + } + + public Event getModelReady() { + return modelReady; + } + + public ListModel<VDS> getHosts() { + return hosts; + } + + public void setHosts(ListModel<VDS> hosts) { + this.hosts = hosts; + } + + @Override + public void executeCommand(UICommand command) { + super.executeCommand(command); + if (SUBMIT_NUMA_SUPPORT.equals(command.getName())) { + parentModel.executeCommand(command); + parentModel.setWindow(null); + } else if ("Cancel".equals(command.getName())) { //$NON-NLS-1$ + cancel(); + } + } + + public void pinVNodeToNumaNode(Guid sourceVMGuid, boolean isPinned, int sourceVNumaIndex, int targetPNumaNodeIndex) { + boolean breakFlag = false; + for (VM vm : getVmsWithvNumaNodeList()) { + if (vm.getId().equals(sourceVMGuid)) { + for (VmNumaNode vmNumaNode : vm.getvNumaNodeList()) { + if (vmNumaNode.getIndex() == sourceVNumaIndex) { + breakFlag = true; + if (vmNumaNode.getVdsNumaNodeList().isEmpty()) { + Pair<Guid, Pair<Boolean, Integer>> pair = new Pair<Guid, Pair<Boolean, Integer>>(); + pair.setFirst(getNodeByIndex(targetPNumaNodeIndex).getId()); + pair.setSecond(new Pair<Boolean, Integer>()); + pair.getSecond().setFirst(true); + pair.getSecond().setSecond(targetPNumaNodeIndex); + vmNumaNode.getVdsNumaNodeList().add(pair); + } else { + for (Pair<Guid, Pair<Boolean, Integer>> pair : vmNumaNode.getVdsNumaNodeList()) { + if (targetPNumaNodeIndex == -1) { + pair.setFirst(null); + pair.getSecond().setFirst(false); + } else { + pair.setFirst(getNodeByIndex(targetPNumaNodeIndex).getId()); + pair.getSecond().setFirst(true); + pair.getSecond().setSecond(targetPNumaNodeIndex); + } + } + } + break; + } + } + updateParametersMap.put(vm.getId(), + new VmNumaNodeOperationParameters(vm.getId(), vm.getvNumaNodeList())); + } + if (breakFlag) { + break; + } + } + modelReady(); + } + + public ArrayList<VdcActionParametersBase> getUpdateParameters() { + return new ArrayList<VdcActionParametersBase>(updateParametersMap.values()); + } +} diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/VNodeModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/VNodeModel.java new file mode 100644 index 0000000..dbf3909 --- /dev/null +++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/numa/VNodeModel.java @@ -0,0 +1,43 @@ +package org.ovirt.engine.ui.uicommonweb.models.hosts.numa; + +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VmNumaNode; +import org.ovirt.engine.ui.uicommonweb.models.Model; + +public class VNodeModel extends Model { + private final NumaSupportModel numaSupportModel; + private final VM vm; + private final VmNumaNode vmNumaNode; + private boolean pinned; + + public VNodeModel(NumaSupportModel numaSupportModel, VM vm, VmNumaNode vmNumaNode, boolean pinned) { + this.numaSupportModel = numaSupportModel; + this.vm = vm; + this.vmNumaNode = vmNumaNode; + this.pinned = pinned; + } + + public NumaSupportModel getNumaSupportModel() { + return numaSupportModel; + } + + public VM getVm() { + return vm; + } + + public VmNumaNode getVmNumaNode() { + return vmNumaNode; + } + + public boolean isPinned() { + return pinned; + } + + public void setPinned(boolean pinned) { + this.pinned = pinned; + } + + public boolean isSplitted() { + return getVmNumaNode().getVdsNumaNodeList() != null && getVmNumaNode().getVdsNumaNodeList().size() > 1; + } +} 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 42c154f..51cb0e8 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 @@ -313,6 +313,9 @@ @DefaultMessage("{0} ({1} Socket(s), {2} Core(s) per Socket)") String cpuInfoMessage(int numOfCpus, int sockets, int coresPerSocket); + @DefaultMessage("NUMA Topology - {0}") + String numaTopologyTitle(String hostName); + @DefaultMessage("Could not fetch rebalance status of volume : {0}") String rebalanceStatusFailed(String name); 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 5831272..cbe22cf 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 @@ -3707,6 +3707,7 @@ @DefaultStringValue("Disk Snapshots") String snapshotsLabel(); + @DefaultStringValue("Attached by label") String attachedByLabel(); @@ -3857,4 +3858,7 @@ @DefaultStringValue("QoS") String cpuProfileQosLabel(); + + @DefaultStringValue("NUMA Support") + String numaSupport(); } 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 99dbb60..3963747 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 @@ -106,4 +106,5 @@ @DefaultMessage("Default ({0})") String defaultMtu(int mtu); + } diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationResources.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationResources.java index 4d67455..848d8cd 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationResources.java +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/ApplicationResources.java @@ -426,5 +426,4 @@ @Source("images/glusterAsyncTasks/remove_brick_commit_required.png") ImageResource removeBrickCommitRequired(); - } diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/HostModule.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/HostModule.java index df8c076..9e1565d 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/HostModule.java +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/HostModule.java @@ -14,6 +14,7 @@ import org.ovirt.engine.ui.common.presenter.popup.DefaultConfirmationPopupPresenterWidget; import org.ovirt.engine.ui.common.presenter.popup.RemoveConfirmationPopupPresenterWidget; import org.ovirt.engine.ui.common.presenter.popup.RolePermissionsRemoveConfirmationPopupPresenterWidget; +import org.ovirt.engine.ui.common.presenter.popup.numa.NumaSupportPopupPresenterWidget; import org.ovirt.engine.ui.common.uicommon.model.DetailModelProvider; import org.ovirt.engine.ui.common.uicommon.model.DetailTabModelProvider; import org.ovirt.engine.ui.common.uicommon.model.MainModelProvider; @@ -80,7 +81,8 @@ final Provider<AssignTagsPopupPresenterWidget> assignTagsPopupProvider, final Provider<ReportPresenterWidget> reportWindowProvider, final Provider<ConfigureLocalStoragePopupPresenterWidget> configureLocalStoragePopupProvider, - final Provider<HostInstallPopupPresenterWidget> installPopupProvider) { + final Provider<HostInstallPopupPresenterWidget> installPopupProvider, + final Provider<NumaSupportPopupPresenterWidget> numaSupportPopupProvider) { return new MainTabModelProvider<VDS, HostListModel>(eventBus, defaultConfirmPopupProvider, HostListModel.class) { @Override public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> getModelPopup(HostListModel source, @@ -97,6 +99,8 @@ return assignTagsPopupProvider.get(); } else if (lastExecutedCommand == getModel().getConfigureLocalStorageCommand()) { return configureLocalStoragePopupProvider.get(); + } else if (lastExecutedCommand == getModel().getNumaSupportCommand()) { + return numaSupportPopupProvider.get(); } return super.getModelPopup(source, lastExecutedCommand, windowModel); } diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabHostView.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabHostView.java index cebae83..cda3b0e 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabHostView.java +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabHostView.java @@ -245,6 +245,12 @@ } }); if (ApplicationModeHelper.getUiMode() != ApplicationMode.GlusterOnly) { + getTable().addActionButton(new WebAdminButtonDefinition<VDS>(constants.numaSupport()) { + @Override + protected UICommand resolveCommand() { + return getMainModel().getNumaSupportCommand(); + } + }); getTable().addActionButton(new WebAdminButtonDefinition<VDS>(constants.confirmRebootedHost(), CommandLocation.OnlyFromContext) { @Override -- To view, visit http://gerrit.ovirt.org/33193 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0712ea82b87d4fe9fc25f196183136485c0c4381 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5 Gerrit-Owner: Gilad Chaplik <gchap...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches