package org.ovirt.engine.ui.webadmin.section.main.view.popup; import java.util.ArrayList; import java.util.Map.Entry; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSGroup; import org.ovirt.engine.core.common.businessentities.VmTemplate; import org.ovirt.engine.core.common.businessentities.VmType; import org.ovirt.engine.core.common.businessentities.storage_domains; import org.ovirt.engine.core.common.businessentities.storage_pool; import org.ovirt.engine.core.compat.Event; import org.ovirt.engine.core.compat.EventArgs; import org.ovirt.engine.core.compat.IEventListener; import org.ovirt.engine.core.compat.PropertyChangedEventArgs; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; import org.ovirt.engine.ui.uicommonweb.models.ListModel; import org.ovirt.engine.ui.uicommonweb.models.vms.UnitVmModel; import org.ovirt.engine.ui.webadmin.ApplicationConstants; import org.ovirt.engine.ui.webadmin.ApplicationResources; import org.ovirt.engine.ui.webadmin.widget.Align; import org.ovirt.engine.ui.webadmin.widget.dialog.SimpleDialogPanel; import org.ovirt.engine.ui.webadmin.widget.dialog.tab.DialogTab; import org.ovirt.engine.ui.webadmin.widget.editor.EntityModelCellTable; import org.ovirt.engine.ui.webadmin.widget.editor.EntityModelCheckBoxEditor; import org.ovirt.engine.ui.webadmin.widget.editor.EntityModelRadioButtonEditor; import org.ovirt.engine.ui.webadmin.widget.editor.EntityModelSliderWithTextBoxEditor; import org.ovirt.engine.ui.webadmin.widget.editor.EntityModelTextBoxEditor; import org.ovirt.engine.ui.webadmin.widget.editor.ListModelListBoxEditor; import org.ovirt.engine.ui.webadmin.widget.parser.MemorySizeParser; import org.ovirt.engine.ui.webadmin.widget.renderer.EnumRenderer; import org.ovirt.engine.ui.webadmin.widget.renderer.MemorySizeRenderer; import org.ovirt.engine.ui.webadmin.widget.renderer.NullSafeRenderer; import org.ovirt.engine.ui.webadmin.widget.table.column.EntityModelTextColumn; import com.google.gwt.core.client.GWT; import com.google.gwt.editor.client.SimpleBeanEditorDriver; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.EventBus; import com.google.gwt.resources.client.CssResource; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.CellTable.Resources; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.RadioButton; import com.google.inject.Inject; public class AbstractVmPopupView extends AbstractModelBoundPopupView<UnitVmModel> { interface Driver extends SimpleBeanEditorDriver<UnitVmModel, AbstractVmPopupView> { Driver driver = GWT.create(Driver.class); } interface ViewUiBinder extends UiBinder<SimpleDialogPanel, AbstractVmPopupView> { ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class); } interface Style extends CssResource { String longCheckboxContent(); } @UiField Style style; // ==General Tab== @UiField protected DialogTab generalTab; @UiField(provided = true) @Path(value = "dataCenter.selectedItem") ListModelListBoxEditor<Object> dataCenterEditor; @UiField(provided = true) @Path(value = "cluster.selectedItem") ListModelListBoxEditor<Object> clusterEditor; @UiField @Path(value = "name.entity") EntityModelTextBoxEditor nameEditor; @UiField @Path(value = "description.entity") EntityModelTextBoxEditor descriptionEditor; @UiField(provided = true) @Path(value = "template.selectedItem") protected ListModelListBoxEditor<Object> templateEditor; @UiField(provided = true) @Path(value = "memSize.entity") EntityModelTextBoxEditor memSizeEditor; @UiField(provided = true) @Path(value = "totalCPUCores.entity") EntityModelSliderWithTextBoxEditor totalCPUCoresEditor; @UiField(provided = true) @Path(value = "numOfSockets.entity") EntityModelSliderWithTextBoxEditor numOfSocketsEditor; @UiField(provided = true) @Path(value = "oSType.selectedItem") ListModelListBoxEditor<Object> oSTypeEditor; // ==Windows Prep Tab== @UiField protected DialogTab windowsSysPrepTab; @UiField(provided = true) @Path(value = "domain.selectedItem") ListModelListBoxEditor<Object> domainEditor; @UiField(provided = true) @Path(value = "timeZone.selectedItem") ListModelListBoxEditor<Object> timeZoneEditor; // ==Console Tab== @UiField DialogTab consoleTab; @UiField(provided = true) @Path(value = "displayProtocol.selectedItem") ListModelListBoxEditor<Object> displayProtocolEditor; @UiField(provided = true) @Path(value = "usbPolicy.selectedItem") ListModelListBoxEditor<Object> usbPolicyEditor; @UiField(provided = true) @Path(value = "numOfMonitors.selectedItem") protected ListModelListBoxEditor<Object> numOfMonitorsEditor; @UiField(provided = true) @Path(value = "isStateless.entity") protected EntityModelCheckBoxEditor isStatelessEditor; // ==Host Tab== @UiField protected DialogTab hostTab; @UiField(provided = true) @Path(value = "runVMOnSpecificHost.entity") EntityModelCheckBoxEditor runVMOnSpecificHostEditor; @UiField(provided = true) @Path(value = "dontMigrateVM.entity") EntityModelCheckBoxEditor dontMigrateVMEditor; @UiField(provided = true) @Ignore RadioButton specificHost; @UiField(provided = true) @Path(value = "defaultHost.selectedItem") ListModelListBoxEditor<Object> defaultHostEditor; @UiField(provided = true) @Path(value = "isAutoAssign.entity") EntityModelRadioButtonEditor isAutoAssignEditor; // ==High Availability Tab== @UiField protected DialogTab highAvailabilityTab; @UiField(provided = true) @Path(value = "isHighlyAvailable.entity") EntityModelCheckBoxEditor isHighlyAvailableEditor; // TODO: Priority is a ListModel which is rendered as RadioBox @UiField(provided = true) @Ignore EntityModelCellTable<ListModel> priorityEditor; // ==Resource Allocation Tab== @UiField protected DialogTab resourceAllocationTab; @UiField(provided = true) @Path(value = "storageDomain.selectedItem") ListModelListBoxEditor<Object> storageDomainEditor; @UiField(provided = true) @Path(value = "provisioning.selectedItem") ListModelListBoxEditor<Object> provisioningEditor; @UiField(provided = true) @Path(value = "minAllocatedMemory.entity") EntityModelTextBoxEditor minAllocatedMemoryEditor; // ==Boot Options Tab== @UiField DialogTab bootOptionsTab; @UiField(provided = true) @Path(value = "firstBootDevice.selectedItem") ListModelListBoxEditor<Object> firstBootDeviceEditor; @UiField(provided = true) @Path(value = "secondBootDevice.selectedItem") ListModelListBoxEditor<Object> secondBootDeviceEditor; @UiField(provided = true) @Path(value = "cdImage.selectedItem") ListModelListBoxEditor<Object> cdImageEditor; @UiField // EntityModelCheckBoxEditor cdImageIsChangable; // TODO: Should be handeled in a more generic way! // @Path(value = "cdImage.isChangable") @Ignore CheckBox cdImageIsChangable; @UiField protected FlowPanel linuxBootOptionsPanel; @UiField @Path(value = "kernel_path.entity") EntityModelTextBoxEditor kernel_pathEditor; @UiField @Path(value = "initrd_path.entity") EntityModelTextBoxEditor initrd_pathEditor; @UiField @Path(value = "kernel_parameters.entity") EntityModelTextBoxEditor kernel_parametersEditor; // @UiField // @Path(value = "isHighlyAvailable.entity") // EntityModelCheckBoxEditor ; // ==Custom Properties Tab== @UiField protected DialogTab customPropertiesTab; @UiField @Path(value = "customProperties.entity") EntityModelTextBoxEditor customPropertiesEditor; @Inject public AbstractVmPopupView(EventBus eventBus, ApplicationResources resources, ApplicationConstants constants) { super(eventBus, resources); initListBoxEditors(); // Contains a special parser/renderer memSizeEditor = new EntityModelTextBoxEditor(new MemorySizeRenderer(), new MemorySizeParser()); minAllocatedMemoryEditor = new EntityModelTextBoxEditor(new MemorySizeRenderer(), new MemorySizeParser()); totalCPUCoresEditor = new EntityModelSliderWithTextBoxEditor(1, 16); numOfSocketsEditor = new EntityModelSliderWithTextBoxEditor(1, 16); // TODO: How to align right without creating the widget manually? runVMOnSpecificHostEditor = new EntityModelCheckBoxEditor(Align.RIGHT); dontMigrateVMEditor = new EntityModelCheckBoxEditor(Align.RIGHT); isHighlyAvailableEditor = new EntityModelCheckBoxEditor(Align.RIGHT); isStatelessEditor = new EntityModelCheckBoxEditor(Align.RIGHT); priorityEditor = new EntityModelCellTable<ListModel>((Resources) GWT.create(ButtonCellTableResources.class)); priorityEditor.addEntityModelColumn(new EntityModelTextColumn<EntityModel>() { @Override public String getValue(EntityModel model) { return model.getTitle(); } }, ""); initWidget(ViewUiBinder.uiBinder.createAndBindUi(this)); applyStyles(); // Default is false windowsSysPrepTab.setVisible(false); localize(constants); Driver.driver.initialize(this); } private void initListBoxEditors() { // General tab dataCenterEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((storage_pool) object).getname(); } }); clusterEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((VDSGroup) object).getname(); } }); templateEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((VmTemplate) object).getname(); } }); oSTypeEditor = new ListModelListBoxEditor<Object>(new EnumRenderer()); // Windows Sysprep domainEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return object.toString(); } }); timeZoneEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((Entry<String, String>) object).getValue(); } }); // Console tab displayProtocolEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((EntityModel) object).getTitle(); } }); usbPolicyEditor = new ListModelListBoxEditor<Object>(new EnumRenderer()); numOfMonitorsEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return object.toString(); } }); // Host Tab specificHost = new RadioButton("runVmOnHostGroup"); isAutoAssignEditor = new EntityModelRadioButtonEditor("runVmOnHostGroup"); defaultHostEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((VDS) object).getvds_name(); } }); // Resource Allocation storageDomainEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((storage_domains) object).getstorage_name(); } }); provisioningEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((EntityModel) object).getTitle(); } }); // Boot Options Tab firstBootDeviceEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((EntityModel) object).getTitle(); } }); secondBootDeviceEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return ((EntityModel) object).getTitle(); } }); cdImageEditor = new ListModelListBoxEditor<Object>(new NullSafeRenderer<Object>() { @Override public String renderNullSafe(Object object) { return (String) object; } }); } // TODO: Localize private void localize(ApplicationConstants constants) { // Tabs highAvailabilityTab.setLabel("High Availability"); resourceAllocationTab.setLabel("Resource Allocation"); bootOptionsTab.setLabel("Boot Options"); customPropertiesTab.setLabel("Custom Properties"); // General Tab generalTab.setLabel("General"); dataCenterEditor.setLabel("Data Center"); clusterEditor.setLabel("Host Cluster"); nameEditor.setLabel("Name"); descriptionEditor.setLabel("Description"); templateEditor.setLabel("Based on Template"); memSizeEditor.setLabel("Memory Size"); totalCPUCoresEditor.setLabel("Total Cores"); numOfSocketsEditor.setLabel("CPU Sockets"); oSTypeEditor.setLabel("Operating System"); isStatelessEditor.setLabel("Stateless"); // Windows Sysprep Tab windowsSysPrepTab.setLabel("Windows Sysprep"); domainEditor.setLabel("Domain"); timeZoneEditor.setLabel("Time Zone"); // Console Tab consoleTab.setLabel("Console"); displayProtocolEditor.setLabel("Protocol"); usbPolicyEditor.setLabel("USB Policy"); numOfMonitorsEditor.setLabel("Monitors"); // Host Tab hostTab.setLabel("Host"); isAutoAssignEditor.setLabel("Any Host in Cluster"); // specificHostEditor.setLabel("Specific"); runVMOnSpecificHostEditor.setLabel("Run VM on the selected host (no migration allowed)"); dontMigrateVMEditor.setLabel("Allow VM migration only upon Administrator specific request (system will not trigger automatic migration of this VM)"); // High Availability Tab isHighlyAvailableEditor.setLabel("Highly Available"); // Resource Allocation Tab storageDomainEditor.setLabel("Storage Domain"); provisioningEditor.setLabel("Provisioning"); minAllocatedMemoryEditor.setLabel("Physical Memory Guaranteed"); // Boot Options firstBootDeviceEditor.setLabel("First Device"); secondBootDeviceEditor.setLabel("Second Device"); kernel_pathEditor.setLabel("kernel path"); initrd_pathEditor.setLabel("initrd path"); kernel_parametersEditor.setLabel("kernel parameters"); customPropertiesEditor.setLabel("Custom Properties"); } private void applyStyles() { runVMOnSpecificHostEditor.addContentWidgetStyleName(style.longCheckboxContent()); dontMigrateVMEditor.addContentWidgetStyleName(style.longCheckboxContent()); } @Override public void focusInput() { nameEditor.setFocus(true); } @Override public void edit(UnitVmModel object) { priorityEditor.setRowData(new ArrayList<EntityModel>()); priorityEditor.edit(object.getPriority()); Driver.driver.edit(object); initSliders(object); initTabAvailabilityListeners(object); } private void initSliders(final UnitVmModel object) { object.getTotalCPUCores().getPropertyChangedEvent() .addListener(new IEventListener() { @Override public void eventRaised(Event ev, Object sender, EventArgs args) { PropertyChangedEventArgs rangeArgs = (PropertyChangedEventArgs) args; if (rangeArgs.PropertyName.equalsIgnoreCase("Min")) { totalCPUCoresEditor.setMin(((Double) object .getTotalCPUCores().getMin()).intValue()); } else if (rangeArgs.PropertyName .equalsIgnoreCase("Max")) { totalCPUCoresEditor.setMax(((Double) object .getTotalCPUCores().getMax()).intValue()); } else if (rangeArgs.PropertyName .equalsIgnoreCase("Interval")) { totalCPUCoresEditor.setStepSize(((Double) object .getTotalCPUCores().getInterval()) .intValue()); } } }); } private void initTabAvailabilityListeners(final UnitVmModel vm) { // TODO should be handled by the core framework vm.getPropertyChangedEvent().addListener(new IEventListener() { @Override public void eventRaised(Event ev, Object sender, EventArgs args) { String propName = ((PropertyChangedEventArgs) args).PropertyName; if ("IsWindowsOS".equals(propName)) { if (vm.getIsWindowsOS()) { windowsSysPrepTab.setVisible(true); } else { windowsSysPrepTab.setVisible(false); } } else if ("IsGeneralTabValid".equals(propName)) { if (vm.getIsGeneralTabValid()) { generalTab.markAsValid(); } else { generalTab.markAsInvalid(null); } } else if ("IsDisplayTabValid".equals(propName)) { if (vm.getIsDisplayTabValid()) { consoleTab.markAsValid(); } else { consoleTab.markAsInvalid(null); } } else if ("IsAllocationTabValid".equals(propName)) { if (vm.getIsAllocationTabValid()) { resourceAllocationTab.markAsValid(); } else { resourceAllocationTab.markAsInvalid(null); } } else if ("IsHighlyAvailable".equals(propName)) { highAvailabilityTab.setVisible((Boolean) vm.getIsHighlyAvailable().getEntity()); } else if ("IsBootSequenceTabValid".equals(propName)) { if ((Boolean) vm.getIsHighlyAvailable().getEntity()) { bootOptionsTab.markAsValid(); } else { bootOptionsTab.markAsInvalid(null); } } else if ("IsCustomPropertiesAvailable".equals(propName)) { customPropertiesTab.setVisible(vm.getIsCustomPropertiesAvailable()); } else if ("IsCustomPropertiesTabValid".equals(propName)) { if (vm.getIsCustomPropertiesTabValid()) { customPropertiesTab.markAsValid(); } else { customPropertiesTab.markAsInvalid(null); } } } }); // High Availability only avail in server mode highAvailabilityTab.setVisible(vm.getVmType().equals(VmType.Server)); // TODO: Move to a more appropriate method vm.getPropertyChangedEvent().addListener(new IEventListener() { @Override public void eventRaised(Event ev, Object sender, EventArgs args) { String propName = ((PropertyChangedEventArgs) args).PropertyName; if ("IsLinux_Unassign_UnknownOS".equals(propName)) { linuxBootOptionsPanel.setVisible(vm.getIsLinux_Unassign_UnknownOS()); } } }); // only avail for desktop mode isStatelessEditor.setVisible(vm.getVmType().equals(VmType.Desktop)); numOfMonitorsEditor.setVisible(vm.getVmType().equals(VmType.Desktop)); // TODO: Should be handled in a more generic way! cdImageIsChangable.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { vm.getCdImage().setIsChangable(cdImageIsChangable.getValue()); } }); defaultHostEditor.setEnabled(false); specificHost.addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { defaultHostEditor.setEnabled(specificHost.getValue()); ValueChangeEvent.fire(isAutoAssignEditor.asRadioButton(), false); } }); // TODO: This is a hack and should be handled cleanly via model property availability isAutoAssignEditor.addDomHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { defaultHostEditor.setEnabled(false); } }, ClickEvent.getType()); vm.getIsAutoAssign().getEntityChangedEvent().addListener(new IEventListener() { @Override public void eventRaised(Event ev, Object sender, EventArgs args) { if (!isAutoAssignEditor.asRadioButton().getValue()) specificHost.setValue(true, true); } }); } @Override public UnitVmModel flush() { priorityEditor.flush(); return Driver.driver.flush(); } public interface ButtonCellTableResources extends CellTable.Resources { interface TableStyle extends CellTable.Style { } @Override @Source({ CellTable.Style.DEFAULT_CSS, "org/ovirt/engine/ui/webadmin/css/ButtonCellTable.css" }) TableStyle cellTableStyle(); } }