package org.ovirt.engine.ui.uicommonweb.models.hosts; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.ServerCpu; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.compat.StringHelper; import org.ovirt.engine.core.compat.Version; import org.ovirt.engine.ui.uicommonweb.Linq; import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; 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.TabName; import org.ovirt.engine.ui.uicommonweb.models.ValidationCompleteEvent; import org.ovirt.engine.ui.uicommonweb.models.clusters.ClusterModel; import org.ovirt.engine.ui.uicommonweb.models.datacenters.DataCenterModel; import org.ovirt.engine.ui.uicommonweb.models.storage.LocalStorageModel; import org.ovirt.engine.ui.uicommonweb.validation.IValidation; import org.ovirt.engine.ui.uicommonweb.validation.RegexValidation; import org.ovirt.engine.ui.uicompat.ConstantsManager; import org.ovirt.engine.ui.uicompat.Event; import org.ovirt.engine.ui.uicompat.EventArgs; public class ConfigureLocalStorageModel extends Model implements HasValidatedTabs { private LocalStorageModel privateStorage; public LocalStorageModel getStorage() { return privateStorage; } private void setStorage(LocalStorageModel value) { privateStorage = value; } private DataCenterModel privateDataCenter; public DataCenterModel getDataCenter() { return privateDataCenter; } private void setDataCenter(DataCenterModel value) { privateDataCenter = value; } private ClusterModel privateCluster; public ClusterModel getCluster() { return privateCluster; } private void setCluster(ClusterModel value) { privateCluster = value; } private EntityModel<String> privateFormattedStorageName; public EntityModel<String> getFormattedStorageName() { return privateFormattedStorageName; } private void setFormattedStorageName(EntityModel<String> value) { privateFormattedStorageName = value; } private StoragePool candidateDataCenter; public StoragePool getCandidateDataCenter() { return candidateDataCenter; } public void setCandidateDataCenter(StoragePool value) { candidateDataCenter = value; } private Cluster candidateCluster; public Cluster getCandidateCluster() { return candidateCluster; } public void setCandidateCluster(Cluster value) { candidateCluster = value; } private String privateCommonName; private String getCommonName() { return privateCommonName; } private void setCommonName(String value) { privateCommonName = value; } public ConfigureLocalStorageModel() { setStorage(new LocalStorageModel()); setDataCenter(new DataCenterModel()); getDataCenter().getVersion().getSelectedItemChangedEvent().addListener(this); setCluster(new ClusterModel()); getCluster().init(false); getCluster().setIsNew(true); setFormattedStorageName(new EntityModel<String>()); // Set the storage type to be Local. for (Boolean bool : getDataCenter().getStoragePoolType().getItems()) { if (bool) { getDataCenter().getStoragePoolType().setSelectedItem(bool); break; } } setValidTab(TabName.GENERAL_TAB, true); } @Override public void eventRaised(Event<? extends EventArgs> ev, Object sender, EventArgs args) { super.eventRaised(ev, sender, args); if (ev.matchesDefinition(ListModel.selectedItemChangedEventDefinition) && sender == getDataCenter().getVersion()) { dataCenterVersion_SelectedItemChanged(); } } private void dataCenterVersion_SelectedItemChanged() { Version version = getDataCenter().getVersion().getSelectedItem(); // Keep in sync version for data center and cluster. getCluster().getVersion().setSelectedItem(version); } public boolean validate() { RegexValidation validation = new RegexValidation(); validation.setExpression("^[A-Za-z0-9_-]+$"); //$NON-NLS-1$ validation.setMessage(ConstantsManager.getInstance().getConstants().asciiNameValidationMsg()); getFormattedStorageName().validateEntity(new IValidation[] { validation }); if (getFormattedStorageName().getEntity() != null && Linq.firstOrNull(context.storageList, new Linq.NamePredicate(getFormattedStorageName().getEntity())) != null) { getFormattedStorageName().setIsValid(false); getFormattedStorageName().getInvalidityReasons().add(ConstantsManager.getInstance() .getConstants() .nameMustBeUniqueInvalidReason()); } boolean isStorageValid = getStorage().validate() && getFormattedStorageName().getIsValid(); boolean isDataCenterValid = true; if (getCandidateDataCenter() == null) { isDataCenterValid = getDataCenter().validate(); } boolean isClusterValid = true; if (getCandidateCluster() == null) { getCluster().validateName(); getCluster().validateCPU(); isClusterValid = getCluster().getName().getIsValid() && getCluster().getCPU().getIsValid(); } setValidTab(TabName.GENERAL_TAB, isStorageValid && isDataCenterValid && isClusterValid); ValidationCompleteEvent.fire(getEventBus(), this); return isStorageValid && isDataCenterValid && isClusterValid; } private void setDefaultNames8() { VDS host = context.host; List<StoragePool> dataCenters = context.dataCenterList; List<Cluster> clusters = context.clusterList; setCommonName(host.getName().replace('.', '-') + "-Local"); //$NON-NLS-1$ StoragePool candidate = null; // Check if current settings suitable for local setup (in case just SD creation failed - re-using the same // setup) boolean useCurrentSettings = false; if (host.getStoragePoolId() != null) { StoragePool tempCandidate = context.hostDataCenter; if (isLocalDataCenterEmpty(tempCandidate)) { candidate = tempCandidate; useCurrentSettings = true; } else { if (tempCandidate != null && tempCandidate.isLocal()) { setMessage(ConstantsManager.getInstance() .getConstants() .noteLocalStorageAlreadyConfiguredForThisHostMsg() + " " + host.getStoragePoolName() + " " + ConstantsManager.getInstance().getConstants().withLocalStorageDomainMsg()); //$NON-NLS-1$ //$NON-NLS-2$ } } } // Check if there is other DC suitable for re-use if (candidate == null) { for (StoragePool dataCenter : dataCenters) { // Need to check if the new DC is without host. if (isLocalDataCenterEmpty(dataCenter) && context.localStorageHostByDataCenterMap.get(dataCenter) == null) { candidate = dataCenter; break; } } } ArrayList<String> names; // In case we found a suitable candidate for re-use: if (candidate != null) { getDataCenter().setDataCenterId(candidate.getId()); getDataCenter().getName().setEntity(candidate.getName()); getDataCenter().getDescription().setEntity(candidate.getdescription()); Version version = candidate.getCompatibilityVersion(); getDataCenter().getVersion().setSelectedItem(version); getCluster().getVersion().setSelectedItem(version); setCandidateDataCenter(candidate); // If we use current settings there is no need to create cluster. if (useCurrentSettings) { getCluster().setClusterId(host.getClusterId()); getCluster().getName().setEntity(host.getClusterName()); Cluster cluster = context.hostCluster; if (cluster != null) { getCluster().getDescription().setEntity(cluster.getDescription()); ServerCpu cpu = new ServerCpu(); cpu.setCpuName(cluster.getCpuName()); getCluster().getCPU().setSelectedItem(cpu); } setCandidateCluster(cluster); } // Use different cluster else { // Check the DC cluster list (for re-use) clusters = context.clusterListByDataCenterMap.get(candidate); // No clusters available - pick up new name. if (clusters == null || clusters.isEmpty()) { names = new ArrayList<>(); List<Cluster> listClusters = context.clusterList; for (Cluster cluster : listClusters) { names.add(cluster.getName()); } getCluster().getName().setEntity(availableName(names)); } else { // Use the DC cluster. Cluster cluster = Linq.firstOrNull(clusters); getCluster().setClusterId(cluster.getId()); getCluster().getName().setEntity(cluster.getName()); getCluster().getDescription().setEntity(cluster.getDescription()); cluster = Linq.firstOrNull(context.clusterList, new Linq.IdPredicate<>(getCluster().getClusterId())); if (cluster != null) { ServerCpu cpu = new ServerCpu(); cpu.setCpuName(cluster.getCpuName()); getCluster().getCPU().setSelectedItem(cpu); } setCandidateCluster(cluster); } } } else { // Didn't found DC to re-use, so we select new names. names = new ArrayList<>(); for (StoragePool dataCenter : dataCenters) { names.add(dataCenter.getName()); } getDataCenter().getName().setEntity(availableName(names)); // Choose a Data Center version corresponding to the host. if (!StringHelper.isNullOrEmpty(host.getSupportedClusterLevels())) { // The supported_cluster_levels are sorted. String[] array = host.getSupportedClusterLevels().split("[,]", -1); //$NON-NLS-1$ Version maxVersion = null; for (int i = 0; i < array.length; i++) { Version vdsVersion = new Version(array[i]); for (Version version : getDataCenter().getVersion().getItems()) { if (version.equals(vdsVersion) && version.compareTo(maxVersion) > 0) { maxVersion = version; } } } if (maxVersion != null) { getDataCenter().getVersion().setSelectedItem(maxVersion); getCluster().getVersion().setSelectedItem(maxVersion); } } names = new ArrayList<>(); if (clusters != null) { for (Cluster cluster : clusters) { names.add(cluster.getName()); } } getCluster().getName().setEntity(availableName(names)); } // Choose default CPU name to match host. List<ServerCpu> serverCpus = (List<ServerCpu>) getCluster().getCPU().getItems(); if (host.getCpuName() != null) { getCluster().getCPU().setSelectedItem(Linq.firstOrNull( serverCpus, new Linq.ServerCpuPredicate(host.getCpuName().getCpuName()))); } else { getCluster().getCPU().setSelectedItem(serverCpus.isEmpty() ? null : serverCpus.get(0)); } // Always choose a available storage name. List<StorageDomain> storages = context.storageList; names = new ArrayList<>(); for (StorageDomain storageDomain : storages) { names.add(storageDomain.getStorageName()); } getFormattedStorageName().setEntity(availableName(names)); } private void setDefaultNames7() { // Get all clusters. AsyncDataProvider.getInstance().getStorageDomainList(new AsyncQuery<>( returnValue -> { context.storageList = returnValue; setDefaultNames8(); })); } public void setDefaultNames6() { // Fill map of local storage host by data center. context.clusterListByDataCenterMap = new HashMap<>(); AsyncIterator<StoragePool> iterator = new AsyncIterator<>(context.dataCenterList); iterator.setComplete( (item, value) -> setDefaultNames7()); iterator.iterate( (item, callback) -> AsyncDataProvider.getInstance().getClusterList(callback.getAsyncQuery(), item.getId()), (item, value) -> { context.clusterListByDataCenterMap.put(item, (ArrayList<Cluster>) value); return false; }); } public void setDefaultNames5() { // Fill map of local storage host by data center. context.localStorageHostByDataCenterMap = new HashMap<>(); AsyncIterator<StoragePool> iterator = new AsyncIterator<>(context.dataCenterList); iterator.setComplete( (item, value) -> setDefaultNames6()); iterator.iterate( (item, callback) -> AsyncDataProvider.getInstance().getLocalStorageHost(callback.getAsyncQuery(), item.getName()), (item, value) -> { context.localStorageHostByDataCenterMap.put(item, (VDS) value); return false; }); } public void setDefaultNames4() { // Get data centers containing 'local' in name. AsyncDataProvider.getInstance().getDataCenterListByName(new AsyncQuery<>( returnValue -> { context.dataCenterList = returnValue; setDefaultNames5(); }), getCommonName() + "*"); //$NON-NLS-1$ } public void setDefaultNames3() { // Get all clusters. AsyncDataProvider.getInstance().getClusterList(new AsyncQuery<>( returnValue -> { context.clusterList = returnValue; setDefaultNames4(); })); } public void setDefaultNames2() { VDS host = context.host; // Get cluster of the host. if (host.getClusterId() != null) { AsyncDataProvider.getInstance().getClusterById(new AsyncQuery<>( returnValue -> { context.hostCluster = returnValue; setDefaultNames3(); }), host.getClusterId()); } else { setDefaultNames3(); } } public void setDefaultNames1() { VDS host = context.host; // Get data center of the host. if (host.getStoragePoolId() != null) { AsyncDataProvider.getInstance().getDataCenterById(new AsyncQuery<>( returnValue -> { context.hostDataCenter = returnValue; setDefaultNames2(); }), host.getStoragePoolId()); } else { setDefaultNames2(); } } public void setDefaultNames(VDS host) { context.host = host; setCommonName(host.getName().replace('.', '-') + "-Local"); //$NON-NLS-1$ setDefaultNames1(); } private boolean isLocalDataCenterEmpty(StoragePool dataCenter) { if (dataCenter != null && dataCenter.isLocal() && dataCenter.getStatus() == StoragePoolStatus.Uninitialized) { return true; } return false; } private String availableName(ArrayList<String> list) { String commonName = getCommonName(); ArrayList<Integer> notAvailableNumberList = new ArrayList<>(); String temp; for (String str : list) { temp = str.replace(getCommonName(), ""); //$NON-NLS-1$ if (StringHelper.isNullOrEmpty(temp)) { temp = "0"; //$NON-NLS-1$ } try { Integer i = Integer.valueOf(temp); notAvailableNumberList.add(i); } catch (NumberFormatException ignore) { // do nothing, this is not a number } } Collections.sort(notAvailableNumberList); int i; for (i = 0; i < notAvailableNumberList.size(); i++) { if (notAvailableNumberList.get(i) == i) { continue; } break; } if (i > 0) { commonName = getCommonName() + String.valueOf(i); } return commonName; } private final Context context = new Context(); public static final class Context { public VDS host; public StoragePool hostDataCenter; public Cluster hostCluster; public List<StoragePool> dataCenterList; public List<Cluster> clusterList; public List<StorageDomain> storageList; public HashMap<StoragePool, VDS> localStorageHostByDataCenterMap; public HashMap<StoragePool, ArrayList<Cluster>> clusterListByDataCenterMap; } }