package org.ovirt.engine.ui.uicommonweb.models.hosts; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.ovirt.engine.core.common.action.VdsOperationActionParameters.AuthenticationMethod; import org.ovirt.engine.core.common.businessentities.ArchitectureType; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.ExternalEntityBase; import org.ovirt.engine.core.common.businessentities.HostedEngineDeployConfiguration; import org.ovirt.engine.core.common.businessentities.Label; import org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties; import org.ovirt.engine.core.common.businessentities.Provider; import org.ovirt.engine.core.common.businessentities.ProviderType; import org.ovirt.engine.core.common.businessentities.ServerCpu; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VdsStatic; import org.ovirt.engine.core.common.businessentities.pm.FenceAgent; import org.ovirt.engine.core.common.businessentities.pm.FenceProxySourceType; import org.ovirt.engine.core.common.mode.ApplicationMode; import org.ovirt.engine.core.common.utils.CpuVendor; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.common.utils.pm.PowerManagementUtils; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.Version; import org.ovirt.engine.ui.uicommonweb.ICommandTarget; import org.ovirt.engine.ui.uicommonweb.Linq; import org.ovirt.engine.ui.uicommonweb.UICommand; import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider; import org.ovirt.engine.ui.uicommonweb.models.ApplicationModeHelper; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; import org.ovirt.engine.ui.uicommonweb.models.HasEntity; import org.ovirt.engine.ui.uicommonweb.models.HasValidatedTabs; import org.ovirt.engine.ui.uicommonweb.models.ListModel; import org.ovirt.engine.ui.uicommonweb.models.Model; import org.ovirt.engine.ui.uicommonweb.models.SystemTreeItemModel; import org.ovirt.engine.ui.uicommonweb.models.TabName; import org.ovirt.engine.ui.uicommonweb.models.ValidationCompleteEvent; import org.ovirt.engine.ui.uicommonweb.models.providers.HostNetworkProviderModel; import org.ovirt.engine.ui.uicommonweb.validation.HostAddressValidation; import org.ovirt.engine.ui.uicommonweb.validation.HostnameValidation; import org.ovirt.engine.ui.uicommonweb.validation.IValidation; import org.ovirt.engine.ui.uicommonweb.validation.IntegerValidation; import org.ovirt.engine.ui.uicommonweb.validation.LengthValidation; import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation; import org.ovirt.engine.ui.uicommonweb.validation.SpecialAsciiI18NOrNoneValidation; 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.IEventListener; import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs; import org.ovirt.engine.ui.uicompat.UIConstants; import org.ovirt.engine.ui.uicompat.external.StringUtils; public abstract class HostModel extends Model implements HasValidatedTabs { public static final int HostNameMaxLength = 255; public static final String BeginTestStage = "BeginTest"; //$NON-NLS-1$ public static final String EndTestStage = "EndTest"; //$NON-NLS-1$ public static final String RootUserName = "root"; //$NON-NLS-1$ UIConstants constants = ConstantsManager.getInstance().getConstants(); private EntityModel<String> currentKernelCmdLine; public EntityModel<String> getCurrentKernelCmdLine() { return currentKernelCmdLine; } public void setCurrentKernelCmdLine(EntityModel<String> currentKernelCmdLine) { this.currentKernelCmdLine = currentKernelCmdLine; } private CpuVendor lastNonNullCpuVendor; private EnableableEventListener<EventArgs> kernelCmdlineListener; private UICommand privateUpdateHostsCommand; public UICommand getUpdateHostsCommand() { return privateUpdateHostsCommand; } private void setUpdateHostsCommand(UICommand value) { privateUpdateHostsCommand = value; } public boolean getIsNew() { return getHostId() == null; } private Guid privateHostId; public Guid getHostId() { return privateHostId; } public void setHostId(Guid value) { privateHostId = value; } private String privateOriginalName; public String getOriginalName() { return privateOriginalName; } public void setOriginalName(String value) { privateOriginalName = value; } private EntityModel<String> privateName; public EntityModel<String> getName() { return privateName; } private void setName(EntityModel<String> value) { privateName = value; } private EntityModel<String> privateUserName; public EntityModel<String> getUserName() { return privateUserName; } private void setUserName(EntityModel<String> value) { privateUserName = value; } private EntityModel<Void> privatePkSection; public EntityModel<Void> getPkSection() { return privatePkSection; } private void setPkSection(EntityModel<Void> value) { privatePkSection = value; } private EntityModel<String> privateFetchSshFingerprint; public EntityModel<String> getFetchSshFingerprint() { return privateFetchSshFingerprint; } private void setFetchSshFingerprint(EntityModel<String> value) { privateFetchSshFingerprint = value; } private EntityModel<Integer> privateAuthSshPort; public EntityModel<Integer> getAuthSshPort() { return privateAuthSshPort; } private void setAuthSshPort(EntityModel<Integer> value) { privateAuthSshPort = value; } private EntityModel<String> privateUserPassword; public EntityModel<String> getUserPassword() { return privateUserPassword; } private void setUserPassword(EntityModel<String> value) { privateUserPassword = value; } private EntityModel<String> privatePublicKey; public EntityModel<String> getPublicKey() { return privatePublicKey; } private void setPublicKey(EntityModel<String> value) { privatePublicKey = value; } private EntityModel<String> privateProviderSearchFilterLabel; public EntityModel<String> getProviderSearchFilterLabel() { return privateProviderSearchFilterLabel; } private void setProviderSearchFilterLabel(EntityModel<String> value) { privateProviderSearchFilterLabel = value; } private EntityModel<String> privateProviderSearchFilter; public EntityModel<String> getProviderSearchFilter() { return privateProviderSearchFilter; } private void setProviderSearchFilter(EntityModel<String> value) { privateProviderSearchFilter = value; } private EntityModel<String> privateHost; public EntityModel<String> getHost() { return privateHost; } private void setHost(EntityModel<String> value) { privateHost = value; } private ListModel<StoragePool> privateDataCenter; public ListModel<StoragePool> getDataCenter() { return privateDataCenter; } private void setDataCenter(ListModel<StoragePool> value) { privateDataCenter = value; } private ListModel<Cluster> privateCluster; public ListModel<Cluster> getCluster() { return privateCluster; } private void setCluster(ListModel<Cluster> value) { privateCluster = value; } private EntityModel<Integer> privatePort; public EntityModel<Integer> getPort() { return privatePort; } private void setPort(EntityModel<Integer> value) { privatePort = value; } private AuthenticationMethod hostAuthenticationMethod; public void setAuthenticationMethod(AuthenticationMethod value) { hostAuthenticationMethod = value; } public AuthenticationMethod getAuthenticationMethod() { return hostAuthenticationMethod; } private EntityModel<String> privateFetchResult; public EntityModel<String> getFetchResult() { return privateFetchResult; } private void setFetchResult(EntityModel<String> value) { privateFetchResult = value; } private EntityModel<Boolean> privateOverrideIpTables; public EntityModel<Boolean> getOverrideIpTables() { return privateOverrideIpTables; } private void setOverrideIpTables(EntityModel<Boolean> value) { privateOverrideIpTables = value; } private EntityModel<Boolean> privateIsPm; public EntityModel<Boolean> getIsPm() { return privateIsPm; } private void setIsPm(EntityModel<Boolean> value) { privateIsPm = value; } private EntityModel<String> consoleAddress; public void setConsoleAddress(EntityModel<String> consoleAddress) { this.consoleAddress = consoleAddress; } public EntityModel<String> getConsoleAddress() { return consoleAddress; } private EntityModel<Boolean> consoleAddressEnabled; public EntityModel<Boolean> getConsoleAddressEnabled() { return consoleAddressEnabled; } public void setConsoleAddressEnabled(EntityModel<Boolean> consoleAddressEnabled) { this.consoleAddressEnabled = consoleAddressEnabled; } private EntityModel<Boolean> pmKdumpDetection; public EntityModel<Boolean> getPmKdumpDetection() { return pmKdumpDetection; } private void setPmKdumpDetection(EntityModel<Boolean> value) { pmKdumpDetection = value; } private EntityModel<Boolean> fencingEnabled; public EntityModel<Boolean> getFencingEnabled() { return fencingEnabled; } private void setFencingEnabled(EntityModel<Boolean> value) { fencingEnabled = value; } private EntityModel<Boolean> disableAutomaticPowerManagement; public EntityModel<Boolean> getDisableAutomaticPowerManagement() { return disableAutomaticPowerManagement; } private void setDisableAutomaticPowerManagement(EntityModel<Boolean> value) { disableAutomaticPowerManagement = value; } private boolean isPowerManagementTabSelected; public boolean getIsPowerManagementTabSelected() { return isPowerManagementTabSelected; } public void setIsPowerManagementTabSelected(boolean value) { if (isPowerManagementTabSelected != value) { isPowerManagementTabSelected = value; onPropertyChanged(new PropertyChangedEventArgs("IsPowerManagementTabSelected")); //$NON-NLS-1$ } } private EntityModel<String> kernelCmdline; public EntityModel<String> getKernelCmdline() { return kernelCmdline; } public void setKernelCmdline(EntityModel<String> kernelCmdline) { this.kernelCmdline = kernelCmdline; } private boolean kernelCmdlineParsable; public boolean isKernelCmdlineParsable() { return kernelCmdlineParsable; } public void setKernelCmdlineParsable(boolean kernelCmdlineParsable) { this.kernelCmdlineParsable = kernelCmdlineParsable; } private EntityModel<Boolean> kernelCmdlineIommu; public EntityModel<Boolean> getKernelCmdlineIommu() { return kernelCmdlineIommu; } public void setKernelCmdlineIommu(EntityModel<Boolean> kernelCmdlineIommu) { this.kernelCmdlineIommu = kernelCmdlineIommu; } private EntityModel<Boolean> kernelCmdlineKvmNested; public EntityModel<Boolean> getKernelCmdlineKvmNested() { return kernelCmdlineKvmNested; } public void setKernelCmdlineKvmNested(EntityModel<Boolean> kernelCmdlineKvmNested) { this.kernelCmdlineKvmNested = kernelCmdlineKvmNested; } private EntityModel<Boolean> kernelCmdlineUnsafeInterrupts; public EntityModel<Boolean> getKernelCmdlineUnsafeInterrupts() { return kernelCmdlineUnsafeInterrupts; } public void setKernelCmdlineUnsafeInterrupts(EntityModel<Boolean> kernelCmdlineUnsafeInterrupts) { this.kernelCmdlineUnsafeInterrupts = kernelCmdlineUnsafeInterrupts; } private EntityModel<Boolean> kernelCmdlinePciRealloc; public EntityModel<Boolean> getKernelCmdlinePciRealloc() { return kernelCmdlinePciRealloc; } public void setKernelCmdlinePciRealloc(EntityModel<Boolean> kernelCmdlinePciRealloc) { this.kernelCmdlinePciRealloc = kernelCmdlinePciRealloc; } public String getPmProxyPreferences() { // Return null if power management is not enabled. if (!getIsPm().getEntity()) { return null; } //Translate the preferences back into a comma separated string. StringBuilder builder = new StringBuilder(); if (getPmProxyPreferencesList().getItems() != null) { Collection<FenceProxyModel> items = getPmProxyPreferencesList().getItems(); for (FenceProxyModel item : items) { if (builder.length() > 0) { builder.append(","); //$NON-NLS-1$ } builder.append(item.getEntity().getValue()); } } return builder.toString(); } public void setPmProxyPreferences(String value) { // Create list from the provided comma delimited string. String[] array = value.split(","); //$NON-NLS-1$ List<FenceProxyModel> list = new ArrayList<>(); for (String item : array) { FenceProxyModel model = new FenceProxyModel(); model.setEntity(FenceProxySourceType.forValue(item)); list.add(model); } getPmProxyPreferencesList().setItems(list); } private ListModel<FenceProxyModel> pmProxyPreferencesList; public ListModel<FenceProxyModel> getPmProxyPreferencesList() { return pmProxyPreferencesList; } private void setPmProxyPreferencesList(ListModel<FenceProxyModel> value) { pmProxyPreferencesList = value; } private FenceAgentListModel fenceAgents; public void setFenceAgents(FenceAgentListModel fenceAgentListModel) { fenceAgents = fenceAgentListModel; } public FenceAgentListModel getFenceAgentListModel() { return fenceAgents; } private UICommand proxySSHFingerPrintCommand; public UICommand getSSHFingerPrint() { return proxySSHFingerPrintCommand; } public void setSSHFingerPrint(UICommand value) { proxySSHFingerPrintCommand = value; } private Integer postponedSpmPriority; public void setSpmPriorityValue(Integer value) { if (spmInitialized) { updateSpmPriority(value); } else { postponedSpmPriority = value; } } public int getSpmPriorityValue() { EntityModel<Integer> selectedItem = getSpmPriority().getSelectedItem(); if (selectedItem != null) { return selectedItem.getEntity(); } return 0; } private ListModel<EntityModel<Integer>> spmPriority; public ListModel<EntityModel<Integer>> getSpmPriority() { return spmPriority; } private void setSpmPriority(ListModel<EntityModel<Integer>> value) { spmPriority = value; } private ListModel<VDS> privateExternalHostName; public ListModel<VDS> getExternalHostName() { return privateExternalHostName; } protected void setExternalHostName(ListModel<VDS> value) { privateExternalHostName = value; } private ListModel<ExternalEntityBase> privateExternalDiscoveredHosts; public ListModel<ExternalEntityBase> getExternalDiscoveredHosts() { return privateExternalDiscoveredHosts; } protected void setExternalDiscoveredHosts(ListModel<ExternalEntityBase> value) { privateExternalDiscoveredHosts = value; } private ListModel<ExternalEntityBase> privateExternalHostGroups; public ListModel<ExternalEntityBase> getExternalHostGroups() { return privateExternalHostGroups; } protected void setExternalHostGroups(ListModel<ExternalEntityBase> value) { privateExternalHostGroups = value; } private ListModel<ExternalEntityBase> privateExternalComputeResource; public ListModel<ExternalEntityBase> getExternalComputeResource() { return privateExternalComputeResource; } protected void setExternalComputeResource(ListModel<ExternalEntityBase> value) { privateExternalComputeResource = value; } private EntityModel<String> privateComment; public EntityModel<String> getComment() { return privateComment; } protected void setComment(EntityModel<String> value) { privateComment = value; } private EntityModel<Boolean> externalHostProviderEnabled; public EntityModel<Boolean> getExternalHostProviderEnabled() { return externalHostProviderEnabled; } public void setExternalHostProviderEnabled(EntityModel<Boolean> externalHostProviderEnabled) { this.externalHostProviderEnabled = externalHostProviderEnabled; } private ListModel<Provider<OpenstackNetworkProviderProperties>> privateProviders; public ListModel<Provider<OpenstackNetworkProviderProperties>> getProviders() { return privateProviders; } protected void setProviders(ListModel<Provider<OpenstackNetworkProviderProperties>> value) { privateProviders = value; } private HostNetworkProviderModel networkProviderModel; public HostNetworkProviderModel getNetworkProviderModel() { return networkProviderModel; } private void setNetworkProviderModel(HostNetworkProviderModel value) { networkProviderModel = value; } private EntityModel<Boolean> isDiscoveredHosts; public EntityModel<Boolean> getIsDiscoveredHosts() { return isDiscoveredHosts; } public void setIsDiscoveredHosts(EntityModel<Boolean> value) { isDiscoveredHosts = value; } public ListModel<Provider<org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties>> getNetworkProviders() { return getNetworkProviderModel().getNetworkProviders(); } public EntityModel<String> getInterfaceMappings() { return getNetworkProviderModel().getInterfaceMappings(); } private HostedEngineHostModel hostedEngineHostModel; private ListModel<Label> labelList; public void setLabelList(ListModel<Label> labelList) { this.labelList = labelList; } public ListModel<Label> getLabelList() { return labelList; } private boolean isHeSystem; public void setIsHeSystem(boolean isHeSystem) { this.isHeSystem = isHeSystem; } public boolean getIsHeSystem() { return isHeSystem; } private boolean isHostedEngineDeployed; public void setIsHostedEngineDeployed(boolean isHeDeployed) { isHostedEngineDeployed = isHeDeployed; } public boolean getIsHostedEngineDeployed() { return isHostedEngineDeployed; } private List<Guid> hostsWithHeDeployed; public void setHostsWithHeDeployed(List<Guid> hostsWithHeDeployed) { this.hostsWithHeDeployed = hostsWithHeDeployed; } public List<Guid> getHostsWithHeDeployed() { return hostsWithHeDeployed; } public boolean isLastHostWithHeDeployed() { return hostsWithHeDeployed.size() == 1 && hostsWithHeDeployed.get(0).equals(getHostId()); } private EntityModel<String> hostedEngineWarning; public EntityModel<String> getHostedEngineWarning() { return hostedEngineWarning; } public void setHostedEngineWarning(EntityModel<String> hostedEngineWarning) { this.hostedEngineWarning = hostedEngineWarning; } public HostModel() { setUpdateHostsCommand(new UICommand("", new ICommandTarget() { //$NON-NLS-1$ @Override public void executeCommand(UICommand command) { updateProvisionedHosts(); } @Override public void executeCommand(UICommand uiCommand, Object... parameters) { updateProvisionedHosts(); } })); setSSHFingerPrint(new UICommand("fetch", new ICommandTarget() { //$NON-NLS-1$ @Override public void executeCommand(UICommand command) { fetchSSHFingerprint(); } @Override public void executeCommand(UICommand uiCommand, Object... parameters) { fetchSSHFingerprint(); } })); setName(new EntityModel<String>()); setComment(new EntityModel<String>()); setHost(new EntityModel<String>()); setPkSection(new EntityModel<Void>()); setAuthSshPort(new EntityModel<Integer>()); getAuthSshPort().setEntity(VdsStatic.DEFAULT_SSH_PORT); setUserName(new EntityModel<String>()); getUserName().setEntity(RootUserName); // TODO: remove setIsChangeable when configured ssh username is enabled getUserName().setIsChangeable(false); setFetchSshFingerprint(new EntityModel<String>()); getFetchSshFingerprint().setEntity(""); //$NON-NLS-1$ setUserPassword(new EntityModel<String>()); getUserPassword().setEntity(""); //$NON-NLS-1$ setPublicKey(new EntityModel<String>()); getPublicKey().setEntity(""); //$NON-NLS-1$ setDataCenter(new ListModel<StoragePool>()); getDataCenter().getSelectedItemChangedEvent().addListener(this); getDataCenter().setIsAvailable(ApplicationModeHelper.getUiMode() != ApplicationMode.GlusterOnly); setCluster(new ListModel<Cluster>()); getCluster().getSelectedItemChangedEvent().addListener(this); setPort(new EntityModel<Integer>()); setFetchResult(new EntityModel<String>()); setOverrideIpTables(new EntityModel<Boolean>()); getOverrideIpTables().setEntity(false); setFenceAgents(new FenceAgentListModel()); IEventListener<EventArgs> pmListener = (ev, sender, args) -> updatePmModels(); setExternalHostName(new ListModel<VDS>()); getExternalHostName().setIsAvailable(false); setExternalHostProviderEnabled(new EntityModel<>(false)); getExternalHostProviderEnabled().setIsAvailable(false); setProviders(new ListModel<Provider<OpenstackNetworkProviderProperties>>()); getProviders().setIsAvailable(false); setProviderSearchFilter(new EntityModel<String>()); getProviderSearchFilter().setIsAvailable(false); setProviderSearchFilterLabel(new EntityModel<String>()); getProviderSearchFilterLabel().setIsAvailable(false); setExternalDiscoveredHosts(new ListModel<ExternalEntityBase>()); setExternalHostGroups(new ListModel<ExternalEntityBase>()); getExternalHostGroups().setIsChangeable(true); setExternalComputeResource(new ListModel<ExternalEntityBase>()); getExternalComputeResource().setIsChangeable(true); getUpdateHostsCommand().setIsExecutionAllowed(false); setDisableAutomaticPowerManagement(new EntityModel<Boolean>()); getDisableAutomaticPowerManagement().setEntity(false); setPmKdumpDetection(new EntityModel<Boolean>()); setFencingEnabled(new EntityModel<Boolean>()); getPmKdumpDetection().setEntity(true); setPmProxyPreferencesList(new ListModel<FenceProxyModel>()); getPmProxyPreferencesList().getSelectedItemChangedEvent().addListener((ev, sender, args) -> updatePmModels()); setConsoleAddress(new EntityModel<String>()); getConsoleAddress().setEntity(null); setConsoleAddressEnabled(new EntityModel<Boolean>()); getConsoleAddressEnabled().setEntity(false); getConsoleAddressEnabled().getEntityChangedEvent().addListener(this); setIsPm(new EntityModel<Boolean>()); getIsPm().getEntityChangedEvent().addListener(pmListener); getIsPm().setEntity(false); setValidTab(TabName.POWER_MANAGEMENT_TAB, true); setValidTab(TabName.GENERAL_TAB, true); setSpmPriority(new ListModel<EntityModel<Integer>>()); initSpmPriorities(); fetchEngineSshPublicKey(); setNetworkProviderModel(new HostNetworkProviderModel()); setIsDiscoveredHosts(new EntityModel<Boolean>()); setKernelCmdline(new EntityModel<String>()); setKernelCmdlineIommu(new EntityModel<>(false)); setKernelCmdlineKvmNested(new EntityModel<>(false)); setKernelCmdlineUnsafeInterrupts(new EntityModel<>(false)); setKernelCmdlinePciRealloc(new EntityModel<>(false)); kernelCmdlineListener = new EnableableEventListener<>(null); setCurrentKernelCmdLine(new EntityModel<>("")); setHostedEngineHostModel(new HostedEngineHostModel()); setLabelList(new ListModel<Label>()); updateLabelList(); setHostedEngineWarning(new EntityModel<String>(constants.hostedEngineDeploymentCompatibilityWarning())); } private void updatePmModels() { boolean isPm = getIsPm().getEntity(); getPmProxyPreferencesList().setIsChangeable(getIsPm().getEntity()); getDisableAutomaticPowerManagement().setIsValid(true); getDisableAutomaticPowerManagement().setIsChangeable(isPm); getFenceAgentListModel().setIsChangeable(isPm); // Update other PM fields. getPmKdumpDetection().setIsChangeable(isPm); getFenceAgentListModel().setIsChangeable(isPm); getFenceAgentListModel().setHost(this); } public void fetchEngineSshPublicKey() { AsyncDataProvider.getInstance().getEngineSshPublicKey(new AsyncQuery<>(pk -> { if (pk != null && pk.length() > 0) { getPublicKey().setEntity(pk); } })); } private void fetchSSHFingerprint() { // Cleaning up fields for initialization getFetchSshFingerprint().setEntity(""); //$NON-NLS-1$ getFetchResult().setEntity(""); //$NON-NLS-1$ AsyncQuery<String> aQuery = new AsyncQuery<>(fingerprint -> { if (fingerprint != null && fingerprint.length() > 0) { getFetchSshFingerprint().setEntity(fingerprint); getFetchResult().setEntity(ConstantsManager.getInstance().getConstants().successLoadingFingerprint()); } else { getFetchResult().setEntity(ConstantsManager.getInstance().getConstants().errorLoadingFingerprint()); } }); getHost().validateEntity(new IValidation[] { new NotEmptyValidation(), new LengthValidation(255), new HostAddressValidation() }); if (!getHost().getIsValid()) { getFetchResult().setEntity(ConstantsManager.getInstance().getConstants().fingerprintAddressError() + getHost().getInvalidityReasons().get(0)); } else { getFetchResult().setEntity(ConstantsManager.getInstance().getConstants().loadingFingerprint()); AsyncDataProvider.getInstance().getHostFingerprint( aQuery, getHost().getEntity(), getAuthSshPort().getEntity()); } } boolean spmInitialized; int maxSpmPriority; int defaultSpmPriority; private void initSpmPriorities() { AsyncDataProvider.getInstance().getMaxSpmPriority(new AsyncQuery<>(returnValue -> { maxSpmPriority = returnValue; initSpmPriorities1(); })); } private void initSpmPriorities1() { AsyncDataProvider.getInstance().getDefaultSpmPriority(new AsyncQuery<>(returnValue -> { defaultSpmPriority = returnValue; if (postponedSpmPriority != null) { updateSpmPriority(postponedSpmPriority); } spmInitialized = true; })); } private void updateSpmPriority(Integer value) { List<EntityModel<Integer>> items = new ArrayList<>(); if (value == null) { value = defaultSpmPriority; } int neverValue = -1; EntityModel<Integer> neverItem = new EntityModel<>(constants.neverTitle(), neverValue); items.add(neverItem); int lowValue = defaultSpmPriority / 2; items.add(new EntityModel<>(constants.lowTitle(), lowValue)); items.add(new EntityModel<>(constants.normalTitle(), defaultSpmPriority)); int highValue = defaultSpmPriority + (maxSpmPriority - defaultSpmPriority) / 2; items.add(new EntityModel<>(constants.highTitle(), highValue)); // Determine whether to set custom SPM priority, and where. EntityModel<Integer> selectedItem = null; int[] values = new int[] { neverValue, lowValue, defaultSpmPriority, highValue, maxSpmPriority + 1 }; Integer prevValue = null; for (int i = 0; i < values.length; i++) { int currentValue = values[i]; if (value == currentValue) { selectedItem = items.get(i); break; } else if (prevValue != null && value > prevValue && value < currentValue) { EntityModel<Integer> customItem = new EntityModel<>("Custom (" + value + ")", value);//$NON-NLS-1$ //$NON-NLS-2$ items.add(i, customItem); selectedItem = customItem; break; } prevValue = currentValue; } getSpmPriority().setItems(items); getSpmPriority().setSelectedItem(selectedItem); } @Override public void eventRaised(Event<? extends EventArgs> ev, Object sender, EventArgs args) { super.eventRaised(ev, sender, args); if (ev.matchesDefinition(ListModel.selectedItemChangedEventDefinition) && sender == getDataCenter()) { dataCenter_SelectedItemChanged(); } else if (ev.matchesDefinition(ListModel.selectedItemChangedEventDefinition) && sender == getCluster()) { cluster_SelectedItemChanged(); } else if (sender == getConsoleAddressEnabled()) { consoleAddressChanged(); } else if (ev.matchesDefinition(HasEntity.entityChangedEventDefinition) && (sender == getKernelCmdlineIommu() || sender == getKernelCmdlineKvmNested() || sender == getKernelCmdlineUnsafeInterrupts() || sender == getKernelCmdlinePciRealloc())) { if (isKernelCmdlineParsable()) { updateKernelCmdlineAccordingToCheckboxes(); } } } private void consoleAddressChanged() { boolean enabled = getConsoleAddressEnabled().getEntity(); getConsoleAddress().setIsChangeable(enabled); } private void dataCenter_SelectedItemChanged() { StoragePool dataCenter = getDataCenter().getSelectedItem(); if (dataCenter != null) { AsyncDataProvider.getInstance().getClusterList(new AsyncQuery<>(clusters -> { if (getIsNew()) { updateClusterList(HostModel.this, clusters); } else { AsyncDataProvider.getInstance().getHostArchitecture(new AsyncQuery<>(architecture -> { ArrayList<Cluster> filteredClusters = new ArrayList<>(); for (Cluster cluster : clusters) { if (architecture == ArchitectureType.undefined || cluster.getArchitecture() == ArchitectureType.undefined || cluster.getArchitecture() == architecture) { filteredClusters.add(cluster); } } updateClusterList(HostModel.this, filteredClusters); }), getHostId()); } updatePmModels(); })); } } private void updateClusterList(HostModel hostModel, List<Cluster> clusters) { Cluster oldCluster = hostModel.getCluster().getSelectedItem(); List<Cluster> filteredClusters = filterClusters(clusters, hostModel.getDataCenter().getItems()); hostModel.getCluster().setItems(filteredClusters); if (oldCluster != null) { Cluster newSelectedItem = Linq.firstOrNull(filteredClusters, new Linq.IdPredicate<>(oldCluster.getId())); if (newSelectedItem != null) { hostModel.getCluster().setSelectedItem(newSelectedItem); } } if (hostModel.getCluster().getSelectedItem() == null) { hostModel.getCluster().setSelectedItem(Linq.firstOrNull(filteredClusters)); } } private List<Cluster> filterClusters(List<Cluster> clusters, Collection<StoragePool> dataCenters) { List<Cluster> result = new ArrayList<>(); Set<Guid> dataCenterIds = new HashSet<>(); for (StoragePool dataCenter: dataCenters) { dataCenterIds.add(dataCenter.getId()); } for (Cluster cluster: clusters) { if (dataCenterIds.contains(cluster.getStoragePoolId())) { result.add(cluster); } } return result; } protected void cluster_SelectedItemChanged() { Cluster cluster = getCluster().getSelectedItem(); if (cluster == null) { return; } getFencingEnabled().setEntity(cluster.getFencingPolicy().isFencingEnabled()); AsyncDataProvider.getInstance().getPmTypeList(new AsyncQuery<>(pmTypes -> updatePmTypeList(pmTypes)), cluster.getCompatibilityVersion()); //Match the appropriate selected data center to the selected cluster, don't fire update events. if (getDataCenter() != null && getDataCenter().getItems() != null) { for (StoragePool datacenter : getDataCenter().getItems()) { if (datacenter.getId().equals(cluster.getStoragePoolId())) { getDataCenter().setSelectedItem(datacenter, false); break; } } } final CpuVendor newCpuVendor = getCurrentCpuVendor(); if (newCpuVendor != null && !newCpuVendor.equals(lastNonNullCpuVendor)) { lastNonNullCpuVendor = newCpuVendor; cpuVendorChanged(); } getHostedEngineWarning().setIsAvailable(cluster.getCompatibilityVersion().less(Version.v4_0)); } protected abstract void cpuVendorChanged(); private void updatePmTypeList(List<String> pmTypes) { getFenceAgentListModel().setPmTypes(pmTypes); } public boolean validate() { getName().validateEntity(new IValidation[] { new HostnameValidation() }); getComment().validateEntity(new IValidation[] { new SpecialAsciiI18NOrNoneValidation() }); getHost().validateEntity(new IValidation[] { new NotEmptyValidation(), new LengthValidation(255), new HostAddressValidation() }); if (Boolean.TRUE.equals(getIsDiscoveredHosts().getEntity())) { getUserPassword().validateEntity(new IValidation[] { new NotEmptyValidation(), new LengthValidation(255) }); getExternalComputeResource().setIsValid(getExternalComputeResource().getSelectedItem() != null); getExternalHostGroups().setIsValid(getExternalHostGroups().getSelectedItem() != null); } else { getExternalComputeResource().setIsValid(true); getExternalHostGroups().setIsValid(true); } if (getExternalHostProviderEnabled().getEntity() && getProviders().getSelectedItem() == null) { getProviders().getInvalidityReasons().add(constants.validateSelectExternalProvider()); getProviders().setIsValid(false); } getAuthSshPort().validateEntity(new IValidation[] {new NotEmptyValidation(), new IntegerValidation(1, 65535)}); if (getConsoleAddressEnabled().getEntity()) { getConsoleAddress().validateEntity(new IValidation[] {new NotEmptyValidation(), new HostAddressValidation()}); } else { // the console address is ignored so can not be invalid getConsoleAddress().setIsValid(true); } setValidTab(TabName.CONSOLE_TAB, getConsoleAddress().getIsValid()); getDataCenter().validateSelectedItem(new IValidation[] { new NotEmptyValidation() }); getCluster().validateSelectedItem(new IValidation[] { new NotEmptyValidation() }); boolean fenceAgentsValid = true; if (getIsPm().getEntity()) { fenceAgentsValid = getFenceAgentListModel().validate(); } setValidTab(TabName.GENERAL_TAB, getName().getIsValid() && getComment().getIsValid() && getHost().getIsValid() && getAuthSshPort().getIsValid() && getCluster().getIsValid() && getExternalHostGroups().getIsValid() && getExternalComputeResource().getIsValid() && getUserPassword().getIsValid() && getProviders().getIsValid() ); setValidTab(TabName.POWER_MANAGEMENT_TAB, fenceAgentsValid); getNetworkProviderModel().validate(); ValidationCompleteEvent.fire(getEventBus(), this); return isValidTab(TabName.GENERAL_TAB) && isValidTab(TabName.POWER_MANAGEMENT_TAB) && getConsoleAddress().getIsValid() && getNetworkProviderModel().getIsValid(); } public void updateModelFromVds(VDS vds, List<StoragePool> dataCenters, boolean isEditWithPMemphasis, SystemTreeItemModel selectedSystemTreeItem) { setHostId(vds.getId()); setIsHostedEngineDeployed(vds.isHostedEngineDeployed()); updateExternalHostModels(vds.getHostProviderId()); getOverrideIpTables().setIsAvailable(showInstallationProperties()); setSpmPriorityValue(vds.getVdsSpmPriority()); setOriginalName(vds.getName()); getName().setEntity(vds.getName()); getComment().setEntity(vds.getComment()); getHost().setEntity(vds.getHostName()); getFetchSshFingerprint().setEntity(vds.getSshKeyFingerprint()); getUserName().setEntity(vds.getSshUsername()); getAuthSshPort().setEntity(vds.getSshPort()); if (StringUtils.isNotEmpty(vds.getKernelArgs())) { getCurrentKernelCmdLine().setEntity(constants.currentKernelCmdLine() + vds.getKernelArgs()); } setPort(vds); boolean consoleAddressEnabled = vds.getConsoleAddress() != null; getConsoleAddressEnabled().setEntity(consoleAddressEnabled); getConsoleAddress().setEntity(vds.getConsoleAddress()); getConsoleAddress().setIsChangeable(consoleAddressEnabled); if (!showInstallationProperties()) { getPkSection().setIsChangeable(false); getPkSection().setIsAvailable(false); // Use public key when edit or approve host setAuthenticationMethod(AuthenticationMethod.PublicKey); } setAllowChangeHost(vds); if (vds.isFenceAgentsExist()) { orderAgents(vds.getFenceAgents()); List<FenceAgentModel> agents = new ArrayList<>(); //Keep a list of examined agents to prevent duplicate management IPs from showing up in the UI. Set<Pair<String, String>> examinedAgents = new HashSet<>(); for (FenceAgent agent: vds.getFenceAgents()) { FenceAgentModel model = new FenceAgentModel(); model.setHost(this); // Set primary PM parameters. model.getManagementIp().setEntity(agent.getIp()); model.getPmUserName().setEntity(agent.getUser()); model.getPmPassword().setEntity(agent.getPassword()); model.getPmType().setSelectedItem(agent.getType()); if (agent.getPort() != null) { model.getPmPort().setEntity(agent.getPort()); } model.getPmEncryptOptions().setEntity(agent.getEncryptOptions()); model.setPmOptionsMap(PowerManagementUtils.pmOptionsStringToMap(agent.getOptions())); model.setOrder(agent.getOrder()); if (!examinedAgents.contains(new Pair<>(model.getManagementIp().getEntity(), model.getPmType().getSelectedItem()))) { boolean added = false; for (FenceAgentModel concurrentModel: agents) { if (model.getOrder().getEntity() != null && model.getOrder().getEntity().equals(concurrentModel.getOrder().getEntity())) { concurrentModel.getConcurrentList().add(model); added = true; break; } } if (!added) { agents.add(model); } } examinedAgents.add(new Pair<>(model.getManagementIp().getEntity(), model.getPmType().getSelectedItem())); } getFenceAgentListModel().setItems(agents); } getDisableAutomaticPowerManagement().setEntity(vds.isDisablePowerManagementPolicy()); getPmKdumpDetection().setEntity(vds.isPmKdumpDetection()); getFencingEnabled().setEntity(vds.isFencingEnabled()); // Set other PM parameters. if (isEditWithPMemphasis) { setIsPowerManagementTabSelected(true); getIsPm().setEntity(true); getIsPm().setIsChangeable(false); } else { getIsPm().setEntity(vds.isPmEnabled()); } updateModelDataCenterFromVds(dataCenters, vds); if (vds.getStatus() != VDSStatus.Maintenance && vds.getStatus() != VDSStatus.PendingApproval && vds.getStatus() != VDSStatus.InstallingOS) { setAllowChangeHostPlacementPropertiesWhenNotInMaintenance(); } else if (selectedSystemTreeItem != null) { final UIConstants constants = ConstantsManager.getInstance().getConstants(); switch (selectedSystemTreeItem.getType()) { case Host: getName().setIsChangeable(false); getName().setChangeProhibitionReason(constants.cannotEditNameInTreeContext()); break; case Hosts: case Cluster: case Cluster_Gluster: getCluster().setIsChangeable(false); getCluster().setChangeProhibitionReason(constants.cannotChangeClusterInTreeContext()); getDataCenter().setIsChangeable(false); break; case DataCenter: StoragePool selectDataCenter = (StoragePool) selectedSystemTreeItem.getEntity(); getDataCenter() .setItems(new ArrayList<>(Arrays.asList(new StoragePool[]{selectDataCenter}))); getDataCenter().setSelectedItem(selectDataCenter); getDataCenter().setIsChangeable(false); break; default: break; } } getKernelCmdline().setEntity(vds.getCurrentKernelCmdline()); setKernelCmdlineParsable(vds.isKernelCmdlineParsable()); getKernelCmdlineIommu().setEntity(vds.isKernelCmdlineIommu()); getKernelCmdlineKvmNested().setEntity(vds.isKernelCmdlineKvmNested()); getKernelCmdlineUnsafeInterrupts().setEntity(vds.isKernelCmdlineUnsafeInterrupts()); getKernelCmdlinePciRealloc().setEntity(vds.isKernelCmdlinePciRealloc()); } public void cleanHostParametersFields() { getName().setEntity(""); //$NON-NLS-1$ getHost().setEntity(""); //$NON-NLS-1$ } public static void orderAgents(List<FenceAgent> fenceAgents) { synchronized (fenceAgents) { Collections.sort(fenceAgents, new FenceAgent.FenceAgentOrderComparator()); } } private void updateExternalHostModels(final Guid selected) { AsyncDataProvider.getInstance().getAllProvidersByType(new AsyncQuery<>(result -> { List<Provider<OpenstackNetworkProviderProperties>> providers = (List) result; ListModel<Provider<OpenstackNetworkProviderProperties>> providersListModel = getProviders(); if (selected != null) { for (Provider<OpenstackNetworkProviderProperties> provider: providers) { if (provider.getId().equals(selected)) { providersListModel.setItems(providers, provider); getExternalHostProviderEnabled().setEntity(true); break; } } } if (providersListModel.getItems() == null || providersListModel.getItems().isEmpty() || providersListModel.getSelectedItem() == null) { providersListModel.setItems(providers, Linq.firstOrNull(providers)); } providersListModel.setIsChangeable(true); if (!externalProvisionEnabled()) { getIsDiscoveredHosts().setEntity(null); } }), ProviderType.FOREMAN); } /** * This should be called when model is synchronously filled by data from business entity * (async model updates may follow). */ public void onDataInitialized() { addKernelCmdlineCheckboxesListeners(); addKernelCmdlineListener(); updateKernelCmdlineCheckboxesChangeability(); } private void addKernelCmdlineListener() { kernelCmdlineListener = new EnableableEventListener<>((ev, sender, args) -> { setKernelCmdlineParsable(false); resetKernelCmdlineCheckboxes(); }); getKernelCmdline().getEntityChangedEvent().addListener(kernelCmdlineListener); } public void resetKernelCmdlineCheckboxes() { final CpuVendor cpuVendor = getCurrentCpuVendor(); if (cpuVendor == null) { return; } switch (cpuVendor) { case INTEL: case AMD: setKernelCmdlineCheckboxesValue(false); break; case IBM: setKernelCmdlineCheckboxesValue(true); break; default: throw new RuntimeException("Unknown CpuVendor type: " + cpuVendor); //$NON-NLS-1$ } updateKernelCmdlineCheckboxesChangeability(); } protected void updateKernelCmdlineCheckboxesChangeability() { final CpuVendor cpuVendor = getCurrentCpuVendor(); if (cpuVendor == null) { return; } switch (cpuVendor) { case INTEL: case AMD: setKernelCmdlineCheckboxesChangeability( isKernelCmdlineParsable(), constants.kernelCmdlineCheckboxesAndDirectCustomizationNotAllowed()); break; case IBM: setKernelCmdlineCheckboxesChangeability( false, constants.kernelCmdlineNotAvailableInClusterWithIbmCpu()); break; default: throw new RuntimeException("Unknown CpuVendor type: " + cpuVendor); //$NON-NLS-1$ } } private void setKernelCmdlineCheckboxesChangeability(boolean changeable, String reason) { getKernelCmdlineIommu().setIsChangeable(changeable, reason); getKernelCmdlineKvmNested().setIsChangeable(changeable, reason); getKernelCmdlineUnsafeInterrupts().setIsChangeable(changeable, reason); getKernelCmdlinePciRealloc().setIsChangeable(changeable, reason); } private void setKernelCmdlineCheckboxesValue(boolean checked) { getKernelCmdlineIommu().setEntity(checked); getKernelCmdlineKvmNested().setEntity(checked); getKernelCmdlineUnsafeInterrupts().setEntity(checked); getKernelCmdlinePciRealloc().setEntity(checked); } /** * @return it may return `null` */ private CpuVendor getCurrentCpuVendor() { if (getCluster().getSelectedItem() == null) { return null; } final Cluster selectedCluster = getCluster().getSelectedItem(); final ServerCpu clustersCpu = AsyncDataProvider.getInstance() .getCpuByName(selectedCluster.getCpuName(), selectedCluster.getCompatibilityVersion()); if (clustersCpu == null) { // in case CPU of cluster was not yet set return null; } return clustersCpu.getVendor(); } private void addKernelCmdlineCheckboxesListeners() { getKernelCmdlineIommu().getEntityChangedEvent().addListener(this); getKernelCmdlineKvmNested().getEntityChangedEvent().addListener(this); getKernelCmdlineUnsafeInterrupts().getEntityChangedEvent().addListener(this); getKernelCmdlinePciRealloc().getEntityChangedEvent().addListener(this); } private void updateKernelCmdlineAccordingToCheckboxes() { final CpuVendor cpuVendor = getCurrentCpuVendor(); if (cpuVendor == null || getKernelCmdlineIommu().getEntity() == null || getKernelCmdlineKvmNested().getEntity() == null || getKernelCmdlineUnsafeInterrupts().getEntity() == null || getKernelCmdlinePciRealloc().getEntity() == null) { return; } final String kernelCmdline = KernelCmdlineUtil.create( cpuVendor, getKernelCmdlineIommu().getEntity(), getKernelCmdlineKvmNested().getEntity(), getKernelCmdlineUnsafeInterrupts().getEntity(), getKernelCmdlinePciRealloc().getEntity()); kernelCmdlineListener.whilePaused(() -> getKernelCmdline().setEntity(kernelCmdline)); } public void resetKernelCmdline() { setKernelCmdlineParsable(true); kernelCmdlineListener.whilePaused(() -> getKernelCmdline().setEntity("")); resetKernelCmdlineCheckboxes(); } private void updateLabelList() { AsyncDataProvider.getInstance().getLabelList(new AsyncQuery<>(allLabels -> { if (getIsNew()) { labelList.setItems(allLabels); labelList.setSelectedItems(new ArrayList<Label>()); } else { AsyncDataProvider.getInstance().getLabelListByEntityId(new AsyncQuery<>(hostLabelsList -> { labelList.setItems(allLabels); labelList.setSelectedItems(hostLabelsList); }), getHostId()); } // This is phase 1 of this feature. Phase 2 will introduce the ability to make // changes to the selected labels via the UI. Until then, labels can be set through // the REST API. labelList.setIsChangeable(false); })); } protected abstract boolean showInstallationProperties(); protected abstract boolean editTransportProperties(VDS vds); public abstract boolean showExternalProviderPanel(); protected abstract void updateModelDataCenterFromVds(List<StoragePool> dataCenters, VDS vds); protected abstract void updateModelClusterFromVds(ArrayList<Cluster> clusters, VDS vds); protected abstract void setAllowChangeHost(VDS vds); protected abstract void setAllowChangeHostPlacementPropertiesWhenNotInMaintenance(); public void updateHosts() { updateExternalHostModels(null); } protected abstract void updateProvisionedHosts(); public boolean externalProvisionEnabled() { return true; } protected abstract void setPort(VDS vds); public abstract boolean showNetworkProviderTab(); /** * {@code EntityModel.setEntity(..., false);} can't be used because this prevents * view form update */ private static class EnableableEventListener<T extends EventArgs> implements IEventListener<T> { private boolean enabled = true; private final IEventListener<T> delegate; public EnableableEventListener(IEventListener<T> delegate) { this.delegate = delegate; } public void whilePaused(Runnable action) { final boolean originalEnabled = this.enabled; enabled = false; action.run(); enabled = originalEnabled; } @Override public void eventRaised(Event<? extends T> ev, Object sender, T args) { if (enabled && delegate != null) { delegate.eventRaised(ev, sender, args); } } } public HostedEngineHostModel getHostedEngineHostModel() { return hostedEngineHostModel; } public void setHostedEngineHostModel(final HostedEngineHostModel hostedEngineHostModel) { this.hostedEngineHostModel = hostedEngineHostModel; if (!isHostedEngineDeployed || getIsNew()) { hostedEngineHostModel.removeActionFromList(HostedEngineDeployConfiguration.Action.UNDEPLOY); } else if (isLastHostWithHeDeployed()) { hostedEngineHostModel.setIsChangeable(false); hostedEngineHostModel.setChangeProhibitionReason(constants.cannotUndeployHeFromLastHostWithHeDeployed()); } else { hostedEngineHostModel.removeActionFromList(HostedEngineDeployConfiguration.Action.DEPLOY); } } }