package org.ovirt.engine.ui.uicommonweb.models.vms; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.ovirt.engine.core.common.TimeZoneType; import org.ovirt.engine.core.common.businessentities.ActionGroup; import org.ovirt.engine.core.common.businessentities.ArchitectureType; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.GraphicsType; import org.ovirt.engine.core.common.businessentities.InstanceType; import org.ovirt.engine.core.common.businessentities.MigrationSupport; import org.ovirt.engine.core.common.businessentities.Quota; import org.ovirt.engine.core.common.businessentities.QuotaEnforcementTypeEnum; import org.ovirt.engine.core.common.businessentities.ServerCpu; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmBase; import org.ovirt.engine.core.common.businessentities.VmDevice; import org.ovirt.engine.core.common.businessentities.VmNumaNode; import org.ovirt.engine.core.common.businessentities.VmRngDevice; import org.ovirt.engine.core.common.businessentities.VmTemplate; import org.ovirt.engine.core.common.businessentities.VmType; import org.ovirt.engine.core.common.businessentities.comparators.DiskByDiskAliasComparator; import org.ovirt.engine.core.common.businessentities.comparators.NameableComparator; import org.ovirt.engine.core.common.businessentities.profiles.CpuProfile; import org.ovirt.engine.core.common.businessentities.storage.CinderDisk; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType; import org.ovirt.engine.core.common.businessentities.storage.StorageType; import org.ovirt.engine.core.common.businessentities.storage.VolumeType; import org.ovirt.engine.core.common.queries.ConfigurationValues; import org.ovirt.engine.core.common.queries.IdQueryParameters; import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.common.utils.VmCommonUtils; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.StringHelper; import org.ovirt.engine.core.compat.Version; import org.ovirt.engine.ui.frontend.AsyncCallback; import org.ovirt.engine.ui.frontend.AsyncQuery; import org.ovirt.engine.ui.frontend.Frontend; import org.ovirt.engine.ui.uicommonweb.Linq; import org.ovirt.engine.ui.uicommonweb.builders.BuilderExecutor; import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; import org.ovirt.engine.ui.uicommonweb.models.ListModel; import org.ovirt.engine.ui.uicommonweb.models.SystemTreeItemModel; import org.ovirt.engine.ui.uicommonweb.models.SystemTreeItemType; import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.NumaSupportModel; import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VmNumaSupportModel; import org.ovirt.engine.ui.uicommonweb.models.templates.ExistingBlankTemplateModelBehavior; import org.ovirt.engine.ui.uicommonweb.models.templates.LatestVmTemplate; import org.ovirt.engine.ui.uicommonweb.models.templates.TemplateWithVersion; import org.ovirt.engine.ui.uicommonweb.models.vms.instancetypes.InstanceTypeManager; import org.ovirt.engine.ui.uicommonweb.validation.I18NNameValidation; import org.ovirt.engine.ui.uicommonweb.validation.IValidation; 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.UIConstants; import org.ovirt.engine.ui.uicompat.UIMessages; public abstract class VmModelBehaviorBase<TModel extends UnitVmModel> { // no need to have this configurable public static final int DEFAULT_NUM_OF_IOTHREADS = 1; private final UIConstants constants = ConstantsManager.getInstance().getConstants(); private final UIMessages messages = ConstantsManager.getInstance().getMessages(); private TModel privateModel; protected List<String> dedicatedHostsNames; private SystemTreeItemModel privateSystemTreeSelectedItem; private PriorityUtil priorityUtil; private VirtioScsiUtil virtioScsiUtil; public int maxCpus = 0; protected int maxCpusPerSocket = 0; protected int maxNumOfSockets = 0; protected int maxThreadsPerCore = 0; private int maxVmsInPool = 1000; protected boolean isCustomCompatibilityVersionChangeInProgress = false; protected Version savedCurrentCustomCompatibilityVersion = null; public List<String> getDedicatedHostsNames() { return dedicatedHostsNames; } public void setDedicatedHostsNames(List<String> dedicatedHostsNames) { this.dedicatedHostsNames = dedicatedHostsNames; } public TModel getModel() { return privateModel; } public void setModel(TModel value) { privateModel = value; } public SystemTreeItemModel getSystemTreeSelectedItem() { return privateSystemTreeSelectedItem; } public void setSystemTreeSelectedItem(SystemTreeItemModel value) { privateSystemTreeSelectedItem = value; } public void initialize(SystemTreeItemModel systemTreeSelectedItem) { this.setSystemTreeSelectedItem(systemTreeSelectedItem); commonInitialize(); } /** * If someone overrides the initialize not calling the super, at least this has to be called */ protected void commonInitialize() { priorityUtil = new PriorityUtil(getModel()); virtioScsiUtil = new VirtioScsiUtil(getModel()); getModel().getVmId().setIsAvailable(false); getModel().getLease().setIsChangeable(false); getModel().getIsHighlyAvailable().getEntityChangedEvent().addListener((ev, sender, args) -> { boolean ha = getModel().getIsHighlyAvailable().getEntity(); getModel().getLease().setIsChangeable(ha); if (!ha) { getModel().getLease().setSelectedItem(null); } }); getModel().getMigrationPolicies() .setItems(AsyncDataProvider.getInstance().getMigrationPolicies(Version.getLast())); } public void dataCenterWithClusterSelectedItemChanged() { DataCenterWithCluster dataCenterWithCluster = getModel().getDataCenterWithClustersList().getSelectedItem(); if (dataCenterWithCluster == null) { return; } StoragePool dataCenter = dataCenterWithCluster.getDataCenter(); if (dataCenter == null) { return; } if (dataCenter.getQuotaEnforcementType() != QuotaEnforcementTypeEnum.DISABLED) { getModel().getQuota().setIsAvailable(true); } else { getModel().getQuota().setIsAvailable(false); } getModel().getIsRngEnabled().setIsChangeable(true); setRngAvailability(); postDataCenterWithClusterSelectedItemChanged(); } private void setVmLeasesAvailability() { TModel model = getModel(); Version compVer = model.getSelectedCluster().getCompatibilityVersion(); if (model.getCustomCompatibilityVersion().getSelectedItem() != null) { compVer = model.getCustomCompatibilityVersion().getSelectedItem(); } model.getLease().setIsChangeable( AsyncDataProvider.getInstance().isVmLeasesFeatureSupported(compVer), constants.vmLeasesSupported()); } private void setRngAvailability() { TModel model = getModel(); Set<VmRngDevice.Source> requiredRngSources = model.getSelectedCluster().getRequiredRngSources(); boolean requiredRngSourcesEmpty = requiredRngSources.isEmpty(); boolean urandomSourceAvailable = requiredRngSources.contains(VmRngDevice.Source.URANDOM) || requiredRngSources.contains(VmRngDevice.Source.RANDOM); boolean hwrngSourceAvailable = requiredRngSources.contains(VmRngDevice.Source.HWRNG); model.getIsRngEnabled().setIsChangeable(!requiredRngSourcesEmpty); model.getRngPeriod().setIsChangeable(!requiredRngSourcesEmpty); model.getRngBytes().setIsChangeable(!requiredRngSourcesEmpty); if (requiredRngSourcesEmpty) { model.getIsRngEnabled().setChangeProhibitionReason(constants.rngNotSupportedByCluster()); model.getRngPeriod().setChangeProhibitionReason(constants.rngNotSupportedByCluster()); model.getRngBytes().setChangeProhibitionReason(constants.rngNotSupportedByCluster()); } model.getRngSourceUrandom().setIsChangeable(urandomSourceAvailable); if (!urandomSourceAvailable) { model.getRngSourceUrandom().setChangeProhibitionReason(messages.rngSourceNotSupportedByCluster( VmRngDevice.Source.getUrandomOrRandomFor(getModel().getSelectedCluster().getCompatibilityVersion()) .toString().toLowerCase())); } model.getRngSourceHwrng().setIsChangeable(hwrngSourceAvailable); if (!hwrngSourceAvailable) { model.getRngSourceHwrng().setChangeProhibitionReason(messages.rngSourceNotSupportedByCluster( VmRngDevice.Source.HWRNG.toString().toLowerCase())); } } protected void updateMigrationForLocalSD() { boolean isLocalSD = getModel().getSelectedDataCenter() != null && getModel().getSelectedDataCenter().isLocal(); if(isLocalSD) { getModel().getIsAutoAssign().setEntity(false); getModel().getMigrationMode().setSelectedItem(MigrationSupport.PINNED_TO_HOST); } getModel().getIsAutoAssign().setIsChangeable(!isLocalSD); getModel().getMigrationMode().setIsChangeable(!isLocalSD); getModel().getDefaultHost().setIsChangeable(!isLocalSD); } protected void buildModel(VmBase vmBase, BuilderExecutor.BuilderExecutionFinished<VmBase, UnitVmModel> callback) { } public void templateWithVersion_SelectedItemChanged() {} public abstract void postDataCenterWithClusterSelectedItemChanged(); public abstract void defaultHost_SelectedItemChanged(); public abstract void provisioning_SelectedItemChanged(); public void oSType_SelectedItemChanged() { } public void updateMinAllocatedMemory() { } public void deactivateInstanceTypeManager(InstanceTypeManager.ActivatedListener activatedListener) { if (getInstanceTypeManager() != null) { getInstanceTypeManager().deactivate(activatedListener); } } public void deactivateInstanceTypeManager() { if (getInstanceTypeManager() != null) { getInstanceTypeManager().deactivate(); } } public void activateInstanceTypeManager() { if (getInstanceTypeManager() != null) { getInstanceTypeManager().activate(); } } public boolean instanceTypeActive() { return getInstanceTypeManager() != null ? getInstanceTypeManager().isActive() : false; } protected InstanceTypeManager getInstanceTypeManager() { return null; } protected void postOsItemChanged() { } protected void baseTemplateSelectedItemChanged() { } protected void initTemplateWithVersion(List<VmTemplate> templates, Guid previousTemplateId, boolean useLatest) { initTemplateWithVersion(templates, previousTemplateId, useLatest, true); } /** * * @param templates empty list is allowed * @param previousTemplateId template ID to select, if null -> autodetect based on the model (ignored if latest is set) * @param useLatest if true, explicitly selects the latest template * @param addLatest if add to all templates also the "latest" or not */ protected void initTemplateWithVersion(List<VmTemplate> templates, Guid previousTemplateId, boolean useLatest, boolean addLatest) { List<TemplateWithVersion> templatesWithVersion = createTemplateWithVersionsAddLatest(templates, addLatest); if (previousTemplateId == null && !useLatest) { TemplateWithVersion previouslySelectedTemplate = getModel().getTemplateWithVersion().getSelectedItem(); if (previouslySelectedTemplate != null && previouslySelectedTemplate.getTemplateVersion() != null) { previousTemplateId = previouslySelectedTemplate.getTemplateVersion().getId(); useLatest = previouslySelectedTemplate.getTemplateVersion() instanceof LatestVmTemplate; } } TemplateWithVersion templateToSelect = computeTemplateWithVersionToSelect(templatesWithVersion, previousTemplateId, useLatest, addLatest); getModel().getTemplateWithVersion().setItems(templatesWithVersion, templateToSelect); } protected TemplateWithVersion computeTemplateWithVersionToSelect( List<TemplateWithVersion> newItems, Guid previousTemplateId, boolean useLatest, boolean addLatest) { if (previousTemplateId == null) { return computeNewTemplateWithVersionToSelect(newItems, addLatest); } TemplateWithVersion oldTemplateToSelect = Linq.firstOrNull( newItems, new Linq.TemplateWithVersionPredicate(previousTemplateId, useLatest)); return oldTemplateToSelect != null ? oldTemplateToSelect : computeNewTemplateWithVersionToSelect(newItems, addLatest); } /** * It prefers to select second element (usually [Blank-1]) to the first one (usually [Blank-latest]). * If the latest has not been added, just return the first one */ protected static TemplateWithVersion computeNewTemplateWithVersionToSelect(List<TemplateWithVersion> newItems, boolean addLatest) { if (newItems.isEmpty()) { return null; } if (addLatest) { return newItems.size() >= 2 ? newItems.get(1) : newItems.get(0); } return newItems.get(0); } /** * * @param templates raw templates from backend, latest not included * @return model ready for 'Template' comobox, including latest */ private static List<TemplateWithVersion> createTemplateWithVersionsAddLatest(List<VmTemplate> templates, boolean addLatest) { final Map<Guid, VmTemplate> baseIdToBaseTemplateMap = new HashMap<>(); final Map<Guid, VmTemplate> baseIdToLastVersionMap = new HashMap<>(); for (VmTemplate template : templates) { if (template.isBaseTemplate()) { baseIdToBaseTemplateMap.put(template.getId(), template); baseIdToLastVersionMap.put(template.getId(), template); } } final List<TemplateWithVersion> result = new ArrayList<>(); for (VmTemplate template : templates) { // update last version map if (baseIdToLastVersionMap.get(template.getBaseTemplateId()).getTemplateVersionNumber() < template.getTemplateVersionNumber()) { baseIdToLastVersionMap.put(template.getBaseTemplateId(), template); } final VmTemplate baseTemplate = baseIdToBaseTemplateMap.get(template.getBaseTemplateId()); result.add(new TemplateWithVersion(baseTemplate, template)); } // add latest if (addLatest) { for (Map.Entry<Guid, VmTemplate> pair : baseIdToLastVersionMap.entrySet()) { VmTemplate baseTemplate = baseIdToBaseTemplateMap.get(pair.getKey()); VmTemplate latestTemplate = new LatestVmTemplate(pair.getValue()); result.add(new TemplateWithVersion(baseTemplate, latestTemplate)); } } Collections.sort(result); return result; } protected static List<VmTemplate> keepBaseTemplates(List<VmTemplate> templates) { List<VmTemplate> baseTemplates = new ArrayList<>(); for (VmTemplate template : templates) { if (template.isBaseTemplate()) { baseTemplates.add(template); } } return baseTemplates; } protected void isSubTemplateEntityChanged() { } public boolean validate() { return true; } public int getMaxVmsInPool() { return maxVmsInPool; } public void setMaxVmsInPool(int maxVmsInPool) { this.maxVmsInPool = maxVmsInPool; } protected void updateUserCdImage(Guid storagePoolId) { AsyncDataProvider.getInstance().getIrsImageList(new AsyncQuery<>(images -> setImagesToModel(getModel(), images)), storagePoolId ); } protected void setImagesToModel(UnitVmModel model, List<String> images) { String oldCdImage = model.getCdImage().getSelectedItem(); model.getCdImage().setItems(images); model.getCdImage().setSelectedItem((oldCdImage != null) ? oldCdImage : Linq.firstOrNull(images)); } public void refreshCdImages() { updateCdImage(true); } protected void updateCdImage() { updateCdImage(false); } protected void updateCdImage(boolean forceRefresh) { StoragePool dataCenter = getModel().getSelectedDataCenter(); if (dataCenter == null) { return; } AsyncDataProvider.getInstance().getIrsImageList(asyncQuery( images -> setImagesToModel(getModel(), images)), dataCenter.getId(), forceRefresh); } protected void updateTimeZone(final String selectedTimeZone) { if (StringHelper.isNullOrEmpty(selectedTimeZone)) { updateDefaultTimeZone(); } else { doUpdateTimeZone(selectedTimeZone); } } protected void updateDefaultTimeZone() { doUpdateTimeZone(null); } private void doUpdateTimeZone(final String selectedTimeZone) { final Collection<TimeZoneModel> timeZones = TimeZoneModel.getTimeZones(getTimeZoneType()); getModel().getTimeZone().setItems(timeZones); getModel().getTimeZone().setSelectedItem(Linq.firstOrNull(timeZones, new Linq.TimeZonePredicate(selectedTimeZone))); } protected void initPriority(int priority) { priorityUtil.initPriority(priority, new PriorityUtil.PriorityUpdatingCallbacks() { @Override public void beforeUpdates() { if (getInstanceTypeManager() != null) { getInstanceTypeManager().deactivate(); } } @Override public void afterUpdates() { if (getInstanceTypeManager() != null) { getInstanceTypeManager().activate(); } } }); } public TimeZoneType getTimeZoneType() { // can be null as a consequence of setItems on ListModel Integer vmOsType = getModel().getOSType().getSelectedItem(); return AsyncDataProvider.getInstance().isWindowsOsType(vmOsType) ? TimeZoneType.WINDOWS_TIMEZONE : TimeZoneType.GENERAL_TIMEZONE; } protected void changeDefaultHost() { } protected void doChangeDefaultHost(List<Guid> dedicatedHostIds) { getModel().getIsAutoAssign().setEntity(true); if (dedicatedHostIds == null) { return; } if (getModel().getDefaultHost().getItems() != null) { List<VDS> selectedHosts = new ArrayList<>(); for (VDS host: getModel().getDefaultHost().getItems()) { if (dedicatedHostIds.contains(host.getId())) { selectedHosts.add(host); } } if (!selectedHosts.isEmpty()) { getModel().getDefaultHost().setSelectedItems(selectedHosts); getModel().getIsAutoAssign().setEntity(false); } } } protected void updateDefaultHost() { Cluster cluster = getModel().getSelectedCluster(); final UIConstants constants = ConstantsManager.getInstance().getConstants(); if (cluster == null) { getModel().getDefaultHost().setItems(new ArrayList<VDS>()); getModel().getDefaultHost().setSelectedItems(new ArrayList<VDS>()); return; } getHostListByCluster(cluster, asyncQuery(returnValue -> { List<VDS> hosts = null; if (returnValue instanceof List) { hosts = (List<VDS>) returnValue; } else if (returnValue instanceof VdcQueryReturnValue && ((VdcQueryReturnValue) returnValue).getReturnValue() instanceof List) { hosts = ((VdcQueryReturnValue) returnValue).getReturnValue(); } else { throw new IllegalArgumentException("The return value should be List<VDS> or VdcQueryReturnValue with return value List<VDS>"); //$NON-NLS-1$ } List<VDS> oldDefaultHosts = getModel().getDefaultHost().getSelectedItems(); if (getModel().getBehavior().getSystemTreeSelectedItem() != null && getModel().getBehavior().getSystemTreeSelectedItem().getType() == SystemTreeItemType.Host) { VDS host = (VDS) getModel().getBehavior().getSystemTreeSelectedItem().getEntity(); for (VDS vds : hosts) { if (host.getId().equals(vds.getId())) { getModel().getDefaultHost() .setItems(new ArrayList<>(Collections.singletonList(vds))); getModel().getDefaultHost().setSelectedItems(Collections.singletonList(vds)); getModel().getDefaultHost().setIsChangeable(false); getModel().getDefaultHost().setChangeProhibitionReason(constants.cannotChangeHostInTreeContext()); break; } } } else { getModel().getDefaultHost().setItems(hosts); // attempt to preserve selection as much as possible if (oldDefaultHosts != null && !oldDefaultHosts.isEmpty()) { Set<VDS> oldSelectedIntersectionNewHosts = new HashSet<>(oldDefaultHosts); oldSelectedIntersectionNewHosts.retainAll(hosts); oldDefaultHosts = new ArrayList<>(oldSelectedIntersectionNewHosts); } List<VDS> hostsToSelect = oldDefaultHosts != null && !oldDefaultHosts.isEmpty() ? oldDefaultHosts : !hosts.isEmpty() ? Collections.singletonList(hosts.get(0)) : Collections.<VDS>emptyList(); getModel().getDefaultHost().setSelectedItems(hostsToSelect); } changeDefaultHost(); })); } /** * By default admin query is fired, UserPortal overrides it to fire user query */ protected void getHostListByCluster(Cluster cluster, AsyncQuery<List<VDS>> query) { AsyncDataProvider.getInstance().getHostListByCluster(query, cluster.getName()); } protected void updateCustomPropertySheet() { if (getModel().getCompatibilityVersion() != null) { updateCustomPropertySheet(getModel().getCompatibilityVersion()); } } protected void updateCustomPropertySheet(Version clusterVersion) { getModel().getCustomPropertySheet().setKeyValueMap( getModel().getCustomPropertiesKeysList().get(clusterVersion) ); } public void updataMaxVmsInPool() { AsyncDataProvider.getInstance().getMaxVmsInPool(asyncQuery( returnValue -> { setMaxVmsInPool(returnValue); updateMaxNumOfVmCpus(); } )); } public void updateMaxNumOfVmCpus() { String version = getCompatibilityVersion().toString(); AsyncDataProvider.getInstance().getMaxNumOfVmCpus(asyncQuery( returnValue -> { maxCpus = returnValue; postUpdateNumOfSockets2(); }), version); } public void postUpdateNumOfSockets2() { String version = getCompatibilityVersion().toString(); AsyncDataProvider.getInstance().getMaxNumOfCPUsPerSocket(asyncQuery( returnValue -> { maxCpusPerSocket = returnValue; postUpdateNumOfSockets3(); }), version); } public void postUpdateNumOfSockets3() { String version = getCompatibilityVersion().toString(); AsyncDataProvider.getInstance().getMaxNumOfThreadsPerCpu(asyncQuery( returnValue -> { maxThreadsPerCore = returnValue; totalCpuCoresChanged(); }), version); } public void initDisks() { VmTemplate template = getModel().getTemplateWithVersion().getSelectedItem().getTemplateVersion(); AsyncDataProvider.getInstance().getTemplateDiskList(asyncQuery( returnValue -> initTemplateDisks(returnValue)), template.getId()); } protected void initTemplateDisks(List<DiskImage> disks) { Collections.sort(disks, new DiskByDiskAliasComparator()); ArrayList<DiskModel> list = new ArrayList<>(); for (DiskImage disk : disks) { DiskModel diskModel = new DiskModel(); diskModel.getAlias().setEntity(disk.getDiskAlias()); diskModel.getVolumeType().setIsAvailable(false); switch (disk.getDiskStorageType()) { case IMAGE: diskModel.setSize(new EntityModel<>((int) disk.getSizeInGigabytes())); ListModel volumes = new ListModel(); volumes.setItems(disk.getVolumeType() == VolumeType.Preallocated ? new ArrayList<>(Arrays.asList(new VolumeType[]{VolumeType.Preallocated})) : AsyncDataProvider.getInstance().getVolumeTypeList(), disk.getVolumeType()); diskModel.setVolumeType(volumes); break; case CINDER: CinderDisk cinderDisk = (CinderDisk) disk; diskModel.setSize(new EntityModel<>((int) cinderDisk.getSizeInGigabytes())); ListModel volumeTypes = new ListModel(); volumeTypes.setItems(new ArrayList<>(Arrays.asList(cinderDisk.getVolumeType())), cinderDisk.getVolumeType()); diskModel.setVolumeType(volumeTypes); ListModel volumeFormats = new ListModel(); volumeFormats.setItems(new ArrayList<>(Arrays.asList(cinderDisk.getVolumeFormat())), cinderDisk.getVolumeFormat()); diskModel.setVolumeFormat(volumeFormats); break; } diskModel.setDisk(disk); list.add(diskModel); } getModel().setDisks(list); updateIsDisksAvailable(); initStorageDomains(); } public void updateIsDisksAvailable() { } public void initStorageDomains() { if (getModel().getDisks() == null) { return; } TemplateWithVersion templateWithVersion = getModel().getTemplateWithVersion().getSelectedItem(); if (templateWithVersion != null && !templateWithVersion.getTemplateVersion().getId().equals(Guid.Empty)) { postInitStorageDomains(); } else { getModel().getStorageDomain().setItems(new ArrayList<StorageDomain>()); getModel().getStorageDomain().setSelectedItem(null); getModel().getStorageDomain().setIsChangeable(false); } } protected void postInitStorageDomains() { if (getModel().getDisks() == null) { return; } ActionGroup actionGroup = getModel().isCreateInstanceOnly() ? ActionGroup.CREATE_INSTANCE : ActionGroup.CREATE_VM; StoragePool dataCenter = getModel().getSelectedDataCenter(); AsyncDataProvider.getInstance().getPermittedStorageDomainsByStoragePoolId(new AsyncQuery<>(storageDomains -> { ArrayList<StorageDomain> activeStorageDomains = filterStorageDomains(storageDomains); boolean provisioning = getModel().getProvisioning().getEntity(); ArrayList<DiskModel> disks = (ArrayList<DiskModel>) getModel().getDisks(); Collections.sort(activeStorageDomains, new NameableComparator()); List<DiskModel> diskImages = Linq.filterDisksByType(disks, DiskStorageType.IMAGE); for (DiskModel diskModel : diskImages) { List<StorageDomain> availableDiskStorageDomains; diskModel.getQuota().setItems(getModel().getQuota().getItems()); ArrayList<Guid> storageIds = ((DiskImage) diskModel.getDisk()).getStorageIds(); // Active storage domains that the disk resides on List<StorageDomain> activeDiskStorageDomains = Linq.getStorageDomainsByIds(storageIds, activeStorageDomains); // Set target storage domains availableDiskStorageDomains = provisioning ? activeStorageDomains : activeDiskStorageDomains; Collections.sort(availableDiskStorageDomains, new NameableComparator()); diskModel.getStorageDomain().setItems(availableDiskStorageDomains); diskModel.getStorageDomain().setChangeProhibitionReason( constants.noActiveTargetStorageDomainAvailableMsg()); diskModel.getStorageDomain().setIsChangeable(!availableDiskStorageDomains.isEmpty()); } List<DiskModel> cinderDisks = Linq.filterDisksByType(disks, DiskStorageType.CINDER); Collection<StorageDomain> cinderStorageDomains = Linq.filterStorageDomainsByStorageType(storageDomains, StorageType.CINDER); initStorageDomainsForCinderDisks(cinderDisks, cinderStorageDomains); }), dataCenter.getId(), actionGroup); } private void initStorageDomainsForCinderDisks(List<DiskModel> cinderDisks, Collection<StorageDomain> cinderStorageDomains) { for (DiskModel diskModel : cinderDisks) { CinderDisk cinderDisk = (CinderDisk) diskModel.getDisk(); diskModel.getStorageDomain().setItems(Linq.filterStorageDomainById( cinderStorageDomains, cinderDisk.getStorageIds().get(0))); diskModel.getStorageDomain().setIsChangeable(false); diskModel.getDiskProfile().setIsChangeable(false); diskModel.getDiskProfile().setChangeProhibitionReason( ConstantsManager.getInstance().getConstants().notSupportedForCinderDisks()); } } public ArrayList<StorageDomain> filterStorageDomains(List<StorageDomain> storageDomains) { // filter only the Active storage domains (Active regarding the relevant storage pool). ArrayList<StorageDomain> list = new ArrayList<>(); for (StorageDomain a : storageDomains) { if (Linq.isDataActiveStorageDomain(a)) { list.add(a); } } // Filter according to system tree selection. if (getSystemTreeSelectedItem() != null && getSystemTreeSelectedItem().getType() == SystemTreeItemType.Storage) { StorageDomain selectStorage = (StorageDomain) getSystemTreeSelectedItem().getEntity(); StorageDomain sd = Linq.firstOrNull(list, new Linq.IdPredicate<>(selectStorage.getId())); list = new ArrayList<>(Arrays.asList(new StorageDomain[]{sd})); } return list; } protected void updateQuotaByCluster(final Guid defaultQuota, final String quotaName) { if (getModel().getQuota().getIsAvailable()) { Cluster cluster = getModel().getSelectedCluster(); if (cluster == null) { return; } AsyncDataProvider.getInstance().getAllRelevantQuotasForClusterSorted(new AsyncQuery<>( quotaList -> { UnitVmModel vmModel = getModel(); if (quotaList == null) { return; } if (!quotaList.isEmpty()) { vmModel.getQuota().setItems(quotaList); } if (defaultQuota != null && !Guid.Empty.equals(defaultQuota)) { boolean hasQuotaInList = false; if (!quotaList.isEmpty()) { hasQuotaInList = defaultQuota.equals(quotaList.get(0).getId()); } // Add the quota to the list only in edit mode if (!hasQuotaInList && !getModel().getIsNew()) { Quota quota = new Quota(); quota.setId(defaultQuota); quota.setQuotaName(quotaName); quotaList.add(0, quota); vmModel.getQuota().setItems(quotaList); vmModel.getQuota().setSelectedItem(quota); } } }), cluster.getId(), defaultQuota); } } protected void updateMemoryBalloon() { Cluster cluster = getModel().getSelectedCluster(); Integer osType = getModel().getOSType().getSelectedItem(); if (cluster != null && osType != null) { updateMemoryBalloon(getModel().getCompatibilityVersion(), osType); } } protected void updateMemoryBalloon(Version clusterVersion, int osType) { boolean isBalloonEnabled = AsyncDataProvider.getInstance().isBalloonEnabled(osType, clusterVersion); if (!isBalloonEnabled) { getModel().getMemoryBalloonDeviceEnabled().setEntity(false); } getModel().getMemoryBalloonDeviceEnabled().setIsAvailable(isBalloonEnabled); } protected void updateCpuSharesAvailability() { if (getModel().getSelectedCluster() != null) { getModel().getCpuSharesAmountSelection().setIsAvailable(true); getModel().getCpuSharesAmount().setIsAvailable(true); } } protected void updateVirtioScsiAvailability() { getModel().getIsVirtioScsiEnabled().setIsAvailable(true); } protected void setupTemplateWithVersion(final Guid templateId, final boolean useLatest, final boolean isVersionChangeable) { AsyncDataProvider.getInstance().getTemplateById(new AsyncQuery<>( rawTemplate -> { if (isVersionChangeable) { // only used by pools therefore query is limited to admin-portal permissions. AsyncDataProvider.getInstance().getVmTemplatesByBaseTemplateId( new AsyncQuery<>(templatesChain -> initTemplateWithVersion(templatesChain, templateId, useLatest)), rawTemplate.getBaseTemplateId()); } else { final VmTemplate template = useLatest ? new LatestVmTemplate(rawTemplate) : rawTemplate; if (template.isBaseTemplate()) { TemplateWithVersion templateCouple = new TemplateWithVersion(template, template); setReadOnlyTemplateWithVersion(templateCouple); } else { AsyncDataProvider.getInstance().getTemplateById(new AsyncQuery<>( baseTemplate -> { TemplateWithVersion templateCouple = new TemplateWithVersion(baseTemplate, template); setReadOnlyTemplateWithVersion(templateCouple); }), template.getBaseTemplateId()); } } }), templateId ); } protected void setReadOnlyTemplateWithVersion(TemplateWithVersion templateCouple) { getModel().getTemplateWithVersion().setItems(Collections.singleton(templateCouple)); getModel().getTemplateWithVersion().setSelectedItem(templateCouple); getModel().getTemplateWithVersion().setIsChangeable(false); } protected void updateCpuPinningVisibility() { if (getModel().getSelectedCluster() != null) { boolean isLocalSD = getModel().getSelectedDataCenter() != null && getModel().getSelectedDataCenter().isLocal(); // cpu pinning is available on Local SD with no consideration for auto assign value boolean hasCpuPinning = Boolean.FALSE.equals(getModel().getIsAutoAssign().getEntity()) || isLocalSD; if (Boolean.FALSE.equals(AsyncDataProvider.getInstance().getConfigValuePreConverted(ConfigurationValues.CpuPinMigrationEnabled, AsyncDataProvider.getInstance().getDefaultConfigurationVersion())) && isVmMigratable() && !isLocalSD) { hasCpuPinning = false; } if (!hasCpuPinning) { getModel().getCpuPinning().setChangeProhibitionReason(constants.cpuPinningUnavailable()); } getModel().getCpuPinning().setIsChangeable(hasCpuPinning); } } public void updateUseHostCpuAvailability() { boolean clusterSupportsHostCpu = getCompatibilityVersion() != null; boolean vmIsNonMigratable = MigrationSupport.PINNED_TO_HOST == getModel().getMigrationMode().getSelectedItem(); if (clusterSupportsHostCpu && !clusterHasPpcArchitecture() && vmIsNonMigratable) { getModel().getHostCpu().setIsChangeable(true); } else { getModel().getHostCpu().setEntity(false); getModel().getHostCpu().setChangeProhibitionReason(constants.hosCPUUnavailable()); getModel().getHostCpu().setIsChangeable(false); } } private boolean clusterHasPpcArchitecture() { Cluster cluster = getModel().getSelectedCluster(); return cluster != null && cluster.getArchitecture() != null && ArchitectureType.ppc == cluster.getArchitecture().getFamily(); } public void updateHaAvailability() { boolean automaticMigrationAllowed = getModel().getMigrationMode().getSelectedItem() == MigrationSupport.MIGRATABLE; final Collection<VDS> allowedHosts = getModel().getDefaultHost().getSelectedItems(); Collection<VDS> presentHosts = getModel().getDefaultHost().getItems(); int pinToHostSize = allowedHosts == null ? 0 : allowedHosts.size(); boolean isHighlyAvailable = getModel().getIsHighlyAvailable().getEntity(); Boolean isAutoAssign = getModel().getIsAutoAssign().getEntity(); // This is needed for the unittests to not crash.. if (presentHosts == null) { presentHosts = new ArrayList<>(); } if (!automaticMigrationAllowed && (pinToHostSize == 1 || (pinToHostSize == 0 && presentHosts.size() < 2)) && (!isAutoAssign || presentHosts.size() < 2) && !isHighlyAvailable) { getModel().getIsHighlyAvailable().setChangeProhibitionReason(constants.hostNonMigratable()); getModel().getIsHighlyAvailable().setEntity(false); isHighlyAvailable = false; } getModel().getIsHighlyAvailable().setIsChangeable(isHighlyAvailable || automaticMigrationAllowed || (isAutoAssign && presentHosts.size() >= 2) || pinToHostSize >= 2 || (pinToHostSize == 0 && presentHosts.size() >= 2)); } public void updateMigrationAvailability() { if (getModel().getIsHighlyAvailable().getEntity() == null || getModel().getDefaultHost().getItems() == null || getModel().getIsAutoAssign().getEntity() == null) { return; } final boolean haHost = getModel().getIsHighlyAvailable().getEntity(); final Collection<VDS> allowedHosts = getModel().getDefaultHost().getSelectedItems(); Collection<VDS> presentHosts = getModel().getDefaultHost().getItems(); int pinToHostSize = allowedHosts == null ? 0 : allowedHosts.size(); final boolean isAutoAssign = getModel().getIsAutoAssign().getEntity(); // This is needed for the unittests to not crash.. if (presentHosts == null) { presentHosts = new ArrayList<>(); } if (haHost && (pinToHostSize == 1 || (pinToHostSize == 0 && presentHosts.size() < 2)) && (!isAutoAssign || presentHosts.size() < 2)) { getModel().getMigrationMode().setChangeProhibitionReason(constants.hostIsHa()); getModel().getMigrationMode().setSelectedItem(MigrationSupport.MIGRATABLE); } getModel().getMigrationMode().setIsChangeable(!haHost || (isAutoAssign && presentHosts.size() >= 2) || pinToHostSize >= 2 || (pinToHostSize == 0 && presentHosts.size() >= 2)); } public void updateCpuSharesAmountChangeability() { boolean changeable = getModel().getCpuSharesAmountSelection().getSelectedItem() == UnitVmModel.CpuSharesAmount.CUSTOM; boolean none = getModel().getCpuSharesAmountSelection().getSelectedItem() == UnitVmModel.CpuSharesAmount.DISABLED; getModel().getCpuSharesAmount() .setEntity(changeable || none ? null //$NON-NLS-1$ : getModel().getCpuSharesAmountSelection().getSelectedItem().getValue()); getModel().getCpuSharesAmount().setIsChangeable(changeable); } public void updateCpuSharesSelection() { boolean foundEnum = false; for (UnitVmModel.CpuSharesAmount cpuSharesAmount : UnitVmModel.CpuSharesAmount.values()) { // this has to be done explicitly otherwise it fails on NPE on unboxing since the cpuSharesAmount.getValue() is a small int int cpuShares = getModel().getCpuSharesAmount().getEntity() != null ? getModel().getCpuSharesAmount().getEntity() : 0; if (cpuSharesAmount.getValue() == cpuShares) { getModel().getCpuSharesAmountSelection().setSelectedItem(cpuSharesAmount); foundEnum = true; break; } } if (!foundEnum) { // saving the value - because when Custom is selected the value automatically clears. Integer currentVal = getModel().getCpuSharesAmount().getEntity(); getModel().getCpuSharesAmountSelection().setSelectedItem(UnitVmModel.CpuSharesAmount.CUSTOM); getModel().getCpuSharesAmount().setEntity(currentVal); } } private boolean isVmMigratable() { return getModel().getMigrationMode().getSelectedItem() != MigrationSupport.PINNED_TO_HOST; } public void numOfSocketChanged() { final int numOfSockets = extractIntFromListModel(getModel().getNumOfSockets()); final int totalCpuCores = getTotalCpuCores(); if (numOfSockets == 0 || totalCpuCores == 0) { return; } // preselect the first threads/core option getModel().getThreadsPerCore().setSelectedItem(1); // and compute corresponding coresPerSocket getModel().getCoresPerSocket().setSelectedItem(totalCpuCores / numOfSockets); setCpuChangeability(); } public void coresPerSocketChanged() { final int coresPerSocket = extractIntFromListModel(getModel().getCoresPerSocket()); int numOfSockets = extractIntFromListModel(getModel().getNumOfSockets()); final int totalCpuCores = getTotalCpuCores(); if (coresPerSocket == 0 || numOfSockets == 0 || totalCpuCores == 0) { return; } if (numOfSockets * coresPerSocket > totalCpuCores) {// decrease the number of sockets, threads can be 1 numOfSockets = totalCpuCores / coresPerSocket; getModel().getNumOfSockets().setSelectedItem(numOfSockets); } int threadsPerCore = totalCpuCores / (coresPerSocket * numOfSockets); getModel().getThreadsPerCore().setSelectedItem(threadsPerCore); } public void threadsPerCoreChanged() { final int threadsPerCore = extractIntFromListModel(getModel().getThreadsPerCore()); final int totalCpuCores = getTotalCpuCores(); Collection<Integer> possCoresPerSocket = getModel().getCoresPerSocket().getItems(); if (threadsPerCore == 0 || totalCpuCores == 0 || possCoresPerSocket == null || possCoresPerSocket.isEmpty()) { return; } // maximize the number of sockets int coresPerSocket = 1; int numOfSockets = totalCpuCores / (threadsPerCore * coresPerSocket); getModel().getCoresPerSocket().setSelectedItem(coresPerSocket); getModel().getNumOfSockets().setSelectedItem(numOfSockets); } protected void setCpuChangeability() { getModel().getThreadsPerCore().setIsChangeable(true); getModel().getCoresPerSocket().setIsChangeable(true); getModel().getNumOfSockets().setIsChangeable(true); } public void totalCpuCoresChanged() { setCpuChangeability(); final int totalCpuCores = getTotalCpuCores(); if (totalCpuCores == 0) { return; } int threadsPerCore = extractIntFromListModel(getModel().getThreadsPerCore()); int coresPerSocket = extractIntFromListModel(getModel().getCoresPerSocket()); int numOfSockets = extractIntFromListModel(getModel().getNumOfSockets()); // if has not been yet inited, init to 1 if (numOfSockets == 0 || coresPerSocket == 0 || threadsPerCore == 0) { initListToOne(getModel().getThreadsPerCore()); initListToOne(getModel().getCoresPerSocket()); initListToOne(getModel().getNumOfSockets()); } List<Integer> possThreadsPerCore = findIndependentPossibleValues(maxThreadsPerCore); List<Integer> possCoresPerSocket = findIndependentPossibleValues(maxCpusPerSocket); List<Integer> possSockets = findIndependentPossibleValues(maxNumOfSockets); getModel().getThreadsPerCore().setItems( filterPossibleValues(possThreadsPerCore, possCoresPerSocket, possSockets)); getModel().getCoresPerSocket().setItems( filterPossibleValues(possCoresPerSocket, possSockets, possThreadsPerCore)); getModel().getNumOfSockets().setItems( filterPossibleValues(possSockets, possCoresPerSocket, possThreadsPerCore)); // ignore the value already selected in the coresPerSocket/threadsPerCore // and always try to set the max possible totalCpuCores if (totalCpuCores <= maxNumOfSockets) { getModel().getThreadsPerCore().setSelectedItem(1); threadsPerCoreChanged(); } else { // we need to compose it from more cores on the available sockets composeCoresAndSocketsWhenDontFitInto(totalCpuCores); } setCpuChangeability(); } public boolean isNumOfSocketsCorrect(int totalCpuCores) { int numOfSockets = extractIntFromListModel(getModel().getNumOfSockets()); int coresPerSocket = extractIntFromListModel(getModel().getCoresPerSocket()); int threadsPerCore = extractIntFromListModel(getModel().getThreadsPerCore()); return totalCpuCores == (coresPerSocket * numOfSockets * threadsPerCore); } /** * The hard way of finding, what the correct combination of the sockets, cores/socket and threads/socket should be * (e.g. checking all possible combinations) */ protected void composeCoresAndSocketsWhenDontFitInto(int totalCpuCores) { List<Integer> possibleSockets = findIndependentPossibleValues(maxNumOfSockets); List<Integer> possibleCoresPerSocket = findIndependentPossibleValues(maxCpusPerSocket); List<Integer> possibleThreadsPerCore = findIndependentPossibleValues(maxThreadsPerCore); // the more sockets I can use, the better Collections.reverse(possibleSockets); for (int socket : possibleSockets) { for (int threadsPerSocket : possibleThreadsPerCore) { for (int coresPerSocket : possibleCoresPerSocket) { if (socket * coresPerSocket * threadsPerSocket == totalCpuCores) { getModel().getThreadsPerCore().setSelectedItem(threadsPerSocket); getModel().getCoresPerSocket().setSelectedItem(coresPerSocket); getModel().getNumOfSockets().setSelectedItem(socket); return; } } } } } protected int getTotalCpuCores() { try { return getModel().getTotalCPUCores().getEntity() != null ? Integer.parseInt(getModel().getTotalCPUCores() .getEntity()) : 0; } catch (NumberFormatException e) { return 0; } } protected int extractIntFromListModel(ListModel model) { return model.getSelectedItem() != null ? Integer.parseInt(model .getSelectedItem() .toString()) : 0; } private void initListToOne(ListModel list) { list.setItems(Arrays.asList(1)); list.setSelectedItem(1); } protected void updateNumOfSockets() { Version version = getCompatibilityVersion(); if (version == null) { return; } AsyncDataProvider.getInstance().getMaxNumOfVmSockets(asyncQuery( returnValue -> { maxNumOfSockets = returnValue; updataMaxVmsInPool(); }), version.toString()); } /** * Returns a list of integers which can divide the param */ protected List<Integer> findIndependentPossibleValues(int max) { List<Integer> res = new ArrayList<>(); int totalCPUCores = getTotalCpuCores(); for (int i = 1; i <= Math.min(totalCPUCores, max); i++) { if (totalCPUCores % i == 0) { res.add(i); } } return res; } /** * Filters out the values, which can not be used in conjuction with the others to reach the total CPUs * i.e. first ~ num of sockets, second ~ cores per socket, thirds ~ threads per core */ protected List<Integer> filterPossibleValues(List<Integer> candidates, List<Integer> second, List<Integer> third) { List<Integer> res = new ArrayList<>(); int currentCpusCores = getTotalCpuCores(); for (Integer candidate : candidates) { for (Integer b : second) { for (Integer c : third) { if (candidate * b * c == currentCpusCores) { if (!res.contains(candidate)) { res.add(candidate); } break; } } } } return res; } protected void updateOSValues() { List<Integer> vmOsValues; Cluster cluster = getModel().getSelectedCluster(); if (cluster != null) { vmOsValues = AsyncDataProvider.getInstance().getOsIds(cluster.getArchitecture()); Integer selectedOsId = getModel().getOSType().getSelectedItem(); getModel().getOSType().setItems(vmOsValues); if (selectedOsId != null && vmOsValues.contains(selectedOsId)) { getModel().getOSType().setSelectedItem(selectedOsId); } postOsItemChanged(); } } protected void updateLeaseStorageDomains(final Guid selectedStorageDomainId) { setVmLeasesAvailability(); AsyncDataProvider.getInstance().getStorageDomainList(new AsyncQuery<>( returnValue -> { List<StorageDomain> domains = new ArrayList<>(); domains.add(null); for (StorageDomain domain : returnValue) { if (domain.getStorageDomainType().isDataDomain() && domain.getStatus() == StorageDomainStatus.Active) { domains.add(domain); } } getModel().getLease().setItems(domains); if (!getModel().getLease().getIsChangable() || selectedStorageDomainId == null) { getModel().getLease().setSelectedItem(null); } else { for (StorageDomain domain : domains) { if (domain != null && selectedStorageDomainId.equals(domain.getId())) { getModel().getLease().setSelectedItem(domain); break; } } } }), getModel().getSelectedDataCenter().getId()); } /* * Updates the emulated machine combobox after a cluster change occurs */ protected void updateEmulatedMachines() { Cluster cluster = getModel().getSelectedCluster(); if (cluster == null) { return; } AsyncDataProvider.getInstance().getEmulatedMachinesByClusterID(new AsyncQuery<>( returnValue -> { if (returnValue != null) { Set<String> emulatedSet = new TreeSet<>(returnValue); emulatedSet.add(""); //$NON-NLS-1$ String oldVal = getModel().getEmulatedMachine().getSelectedItem(); getModel().getEmulatedMachine().setItems(emulatedSet); getModel().getEmulatedMachine().setSelectedItem(oldVal); } }), cluster.getId()); } /* * Updates the cpu model combobox after a cluster change occurs */ protected void updateCustomCpu() { Cluster cluster = getModel().getSelectedCluster(); if (cluster == null || cluster.getCpuName() == null) { return; } AsyncDataProvider.getInstance().getSupportedCpuList(new AsyncQuery<>( returnValue -> { if (returnValue != null) { List<String> cpuList = new ArrayList<>(); cpuList.add(""); //$NON-NLS-1$ for (ServerCpu cpu : returnValue) { cpuList.add(cpu.getVdsVerbData()); } String oldVal = getModel().getCustomCpu().getSelectedItem(); getModel().getCustomCpu().setItems(cpuList); getModel().getCustomCpu().setSelectedItem(oldVal); } }), cluster.getCpuName()); } protected void updateSelectedCdImage(VmBase vmBase) { getModel().getCdImage().setSelectedItem(vmBase.getIsoPath()); boolean hasCd = !StringHelper.isNullOrEmpty(vmBase.getIsoPath()); getModel().getCdImage().setIsChangeable(hasCd); getModel().getCdAttached().setEntity(hasCd); } protected void updateConsoleDevice(Guid vmId) { Frontend.getInstance().runQuery( VdcQueryType.GetConsoleDevices, new IdQueryParameters(vmId), new AsyncQuery<VdcQueryReturnValue>(returnValue -> { List<String> consoleDevices = returnValue.getReturnValue(); getModel().getIsConsoleDeviceEnabled().setEntity(!consoleDevices.isEmpty()); })); } protected void updateVirtioScsiEnabledWithoutDetach(final Guid vmId, int osId) { virtioScsiUtil.updateVirtioScsiEnabled(vmId, osId, new VirtioScsiUtil.VirtioScasiEnablingFinished() { @Override public void beforeUpdates() { getInstanceTypeManager().deactivate(); } @Override public void afterUpdates() { getInstanceTypeManager().activate(); } }); } public void vmTypeChanged(VmType vmType) { if (basedOnCustomInstanceType()) { // this field is normally taken from instance type. If the "custom" is selected, then it is supposed to use the default // determined by vm type getModel().getIsSoundcardEnabled().setEntity(vmType == VmType.Desktop); } getModel().getAllowConsoleReconnect().setEntity(vmType == VmType.Server); } public void enableSinglePCI(boolean enabled) { getModel().getIsSingleQxlEnabled().setIsChangeable(enabled); if (!enabled) { getModel().getIsSingleQxlEnabled().setEntity(false); } } protected void updateRngDevice(Guid templateId) { if (!getModel().getIsRngEnabled().getIsChangable()) { return; } Frontend.getInstance().runQuery( VdcQueryType.GetRngDevice, new IdQueryParameters(templateId), new AsyncQuery<VdcQueryReturnValue>(returnValue -> { List<VmRngDevice> devs = returnValue.getReturnValue(); getModel().getIsRngEnabled().setEntity(!devs.isEmpty()); final VmRngDevice rngDevice = devs.isEmpty() ? new VmRngDevice() : devs.get(0); rngDevice.updateSourceByVersion(getModel().getCompatibilityVersion()); getModel().setRngDevice(rngDevice); } )); } /* * Updates the custom compatibility version combo box options on init/DC-change */ protected void updateCompatibilityVersion() { DataCenterWithCluster dataCenterWithCluster = getModel().getDataCenterWithClustersList().getSelectedItem(); if (dataCenterWithCluster == null) { return; } final StoragePool dataCenter = dataCenterWithCluster.getDataCenter(); if (dataCenter == null) { return; } AsyncDataProvider.getInstance().getDataCenterVersions(new AsyncQuery<>(versions -> { versions.add(0, null); Version selectedVersion; selectedVersion = getModel().getCustomCompatibilityVersion().getSelectedItem(); if (selectedVersion != null && versions.contains(selectedVersion)) { getModel().getCustomCompatibilityVersion().setItems(versions, selectedVersion); } else { getModel().getCustomCompatibilityVersion().setItems(versions); } }), dataCenter.getId()); } /** * In case of a blank template, use the proper value for the default OS. */ protected void setSelectedOSType(VmBase vmBase, ArchitectureType architectureType) { if (vmBase.getId().equals(Guid.Empty)) { Integer osId = AsyncDataProvider.getInstance().getDefaultOs(architectureType); if (osId != null) { setSelectedOSTypeById(osId.intValue()); } } else { setSelectedOSTypeById(vmBase.getOsId()); } } private void setSelectedOSTypeById(int osId) { for (Integer osIdList : getModel().getOSType().getItems()) { if (osIdList.intValue() == osId) { getModel().getOSType().setSelectedItem(osIdList); break; } } } public void updateNumOfIoThreads() { getModel().getIoThreadsEnabled().setIsChangeable(true); getModel().getNumOfIoThreads().setIsChangeable(true); getModel().getNumOfIoThreads().setIsAvailable(getModel().getIoThreadsEnabled().getEntity()); if (getModel().getIoThreadsEnabled().getEntity() && getModel().getNumOfIoThreads().getEntity() == 0) { getModel().getNumOfIoThreads().setEntity(DEFAULT_NUM_OF_IOTHREADS); } } protected Version getCompatibilityVersion() { return getModel().getCompatibilityVersion(); } protected Version latestCluster() { // instance type and blank template always exposes all the features of the latest cluster and if some is not applicable // than that particular feature will not be applicable on the instance creation return Version.getLast(); } protected boolean basedOnCustomInstanceType() { InstanceType selectedInstanceType = getModel().getInstanceTypes().getSelectedItem(); return selectedInstanceType == null || selectedInstanceType instanceof CustomInstanceType; } protected void updateCpuProfile(Guid clusterId, Guid cpuProfileId) { getModel().getCpuProfiles().setIsAvailable(true); fetchCpuProfiles(clusterId, cpuProfileId); } private void fetchCpuProfiles(Guid clusterId, final Guid cpuProfileId) { if (clusterId == null) { return; } Frontend.getInstance().runQuery(VdcQueryType.GetCpuProfilesByClusterId, new IdQueryParameters(clusterId), new AsyncQuery<VdcQueryReturnValue>(returnValue -> { List<CpuProfile> cpuProfiles = returnValue.getReturnValue(); getModel().getCpuProfiles().setItems(cpuProfiles); if (cpuProfiles != null) { for (CpuProfile cpuProfile : cpuProfiles) { if (cpuProfile.getId().equals(cpuProfileId)) { getModel().getCpuProfiles().setSelectedItem(cpuProfile); break; } } } })); } public void numaSupport() { if (getModel().getWindow() != null) { return; } VM vm = getVmWithNuma(); final VDS host = getModel().getDefaultHost().getSelectedItems().get(0); NumaSupportModel model = new VmNumaSupportModel((List<VDS>) getModel().getDefaultHost().getItems(), host , getModel(), vm); getModel().setWindow(model); } protected VM getVmWithNuma() { VM vm = new VM(); String vmName = getModel().getName().getEntity(); if (vmName == null || vmName.isEmpty()) { vmName = "new_vm"; //$NON-NLS-1$ } vm.setName(vmName); Integer nodeCount = getModel().getNumaNodeCount().getEntity(); vm.setvNumaNodeList(new ArrayList<VmNumaNode>()); for (int i = 0; i < nodeCount; i++) { VmNumaNode vmNumaNode = new VmNumaNode(); vmNumaNode.setIndex(i); vm.getvNumaNodeList().add(vmNumaNode); } return vm; } protected void updateGraphics(Guid id) { Frontend.getInstance().runQuery(VdcQueryType.GetGraphicsDevices, new IdQueryParameters(id), new AsyncQuery<VdcQueryReturnValue>(returnValue -> { List<VmDevice> graphicsVmDevs = returnValue.getReturnValue(); List<GraphicsType> graphicsTypes = new ArrayList<>(); for (VmDevice graphicsVmDev : graphicsVmDevs) { graphicsTypes.add(GraphicsType.fromString(graphicsVmDev.getDevice())); } boolean hasSpiceAndVnc = graphicsTypes.size() == 2 && graphicsTypes.containsAll(Arrays.asList(GraphicsType.SPICE, GraphicsType.VNC)); boolean canBeSelected = getModel().getGraphicsType().getItems().contains(UnitVmModel.GraphicsTypes.SPICE_AND_VNC); if (hasSpiceAndVnc && canBeSelected) { getModel().getGraphicsType().setSelectedItem(UnitVmModel.GraphicsTypes.SPICE_AND_VNC); } else if (graphicsVmDevs.size() == 1) { GraphicsType type = GraphicsType.fromString(graphicsVmDevs.get(0).getDevice()); getModel().getGraphicsType().setSelectedItem(UnitVmModel.GraphicsTypes.fromGraphicsType(type)); } })); } /** * allows to enable numa models in all derived behaviors * use updateNumaEnabledHelper in each behavior that requires numa */ protected void updateNumaEnabled() { } protected final void updateNumaEnabledHelper() { boolean enabled = true; if (getModel().getMigrationMode().getSelectedItem() != MigrationSupport.PINNED_TO_HOST || getModel().getIsAutoAssign().getEntity() || getModel().getDefaultHost().getSelectedItem() == null || !getModel().getDefaultHost().getSelectedItem().isNumaSupport()) { enabled = false; } if (enabled) { getModel().getNumaEnabled().setMessage(constants.numaInfoMessage()); } else { getModel().getNumaEnabled().setMessage(constants.numaDisabledInfoMessage()); getModel().getNumaNodeCount().setEntity(0); } getModel().getNumaEnabled().setEntity(enabled); } public boolean isBlankTemplateBehavior() { return this instanceof ExistingBlankTemplateModelBehavior; } public boolean isExistingTemplateBehavior() { return this instanceof TemplateVmModelBehavior; } public boolean isNewTemplateBehavior() { return this instanceof NewTemplateVmModelBehavior; } public boolean isAnyTemplateBehavior() { return this instanceof TemplateVmModelBehavior || this instanceof ExistingBlankTemplateModelBehavior; } public int getMaxNameLength() { return AsyncDataProvider.getInstance().getMaxVmNameLength(); } public IValidation getNameAllowedCharactersIValidation() { return new I18NNameValidation(); } public VmRngDevice.Source getUrandomOrRandomRngSource() { return VmRngDevice.Source.getUrandomOrRandomFor(getModel().getCompatibilityVersion()); } public void updateMaxMemory() { final Integer memoryMb = getModel().getMemSize().getEntity(); if (memoryMb != null) { getModel().getMaxMemorySize().setEntity( VmCommonUtils.getMaxMemorySizeDefault(memoryMb)); } } protected abstract class UpdateTemplateWithVersionListener implements IEventListener<EventArgs> { @Override public void eventRaised(Event<? extends EventArgs> ev, Object sender, EventArgs args) { if (getModel().getTemplateWithVersion() == null || getModel().getTemplateWithVersion().getItems() == null || getModel().getTemplateWithVersion().getSelectedItem() == null) { return; } List<VmTemplate> baseTemplates = new ArrayList<>(); for (TemplateWithVersion templateWithVersion : getModel().getTemplateWithVersion().getItems()) { if (templateWithVersion.isLatest() || templateWithVersion.getTemplateVersion() == null) { continue; } baseTemplates.add(templateWithVersion.getTemplateVersion()); } TemplateWithVersion selectedItemTemplateWithVersion = getModel().getTemplateWithVersion().getSelectedItem(); VmTemplate selectedTemplateWithVersion = selectedItemTemplateWithVersion.getTemplateVersion(); if (selectedTemplateWithVersion == null) { return; } Guid selectedId = selectedTemplateWithVersion.getId(); beforeUpdate(); initTemplateWithVersion(baseTemplates, selectedId, selectedItemTemplateWithVersion.isLatest(), isAddLatestVersion()); } protected void beforeUpdate() { } protected abstract boolean isAddLatestVersion(); } protected <T> AsyncQuery<T> asyncQuery(AsyncCallback<T> callback) { return getModel().asyncQuery(callback); } public boolean isCustomCompatibilityVersionChangeInProgress() { return isCustomCompatibilityVersionChangeInProgress; } public void setCustomCompatibilityVersionChangeInProgress(boolean isCustomCompatibilityVersionChangeInProgress) { } public void setSavedCurrentCustomCompatibilityVersion(Version savedCurrentCustomCompatibilityVersion) { this.savedCurrentCustomCompatibilityVersion = savedCurrentCustomCompatibilityVersion; } public Version getSavedCurrentCustomCompatibilityVersion() { return savedCurrentCustomCompatibilityVersion; } public VirtioScsiUtil getVirtioScsiUtil() { return virtioScsiUtil; } }