package org.ovirt.engine.ui.uicommonweb.models.templates; import java.util.ArrayList; import java.util.List; import org.ovirt.engine.core.common.action.AddVmParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.action.VmManagementParametersBase; import org.ovirt.engine.core.common.businessentities.DisplayType; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StorageDomainType; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmType; import org.ovirt.engine.core.common.businessentities.VmWatchdog; import org.ovirt.engine.core.common.businessentities.VmWatchdogType; import org.ovirt.engine.core.common.queries.GetAllFromExportDomainQueryParameters; import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.StringHelper; import org.ovirt.engine.ui.frontend.AsyncCallback; import org.ovirt.engine.ui.frontend.Frontend; import org.ovirt.engine.ui.uicommonweb.IconUtils; import org.ovirt.engine.ui.uicommonweb.Linq; import org.ovirt.engine.ui.uicommonweb.UICommand; import org.ovirt.engine.ui.uicommonweb.builders.BuilderExecutor; import org.ovirt.engine.ui.uicommonweb.builders.vm.FullUnitToVmBaseBuilder; import org.ovirt.engine.ui.uicommonweb.builders.vm.UnitToGraphicsDeviceParamsBuilder; import org.ovirt.engine.ui.uicommonweb.builders.vm.VmSpecificUnitToVmBuilder; import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider; import org.ovirt.engine.ui.uicommonweb.help.HelpTag; import org.ovirt.engine.ui.uicommonweb.models.ListWithSimpleDetailsModel; 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.vms.BalloonEnabled; import org.ovirt.engine.ui.uicommonweb.models.vms.ExportVmModel; import org.ovirt.engine.ui.uicommonweb.models.vms.HasDiskWindow; import org.ovirt.engine.ui.uicommonweb.models.vms.UnitVmModel; import org.ovirt.engine.ui.uicommonweb.models.vms.UnitVmModelNetworkAsyncCallback; import org.ovirt.engine.ui.uicommonweb.models.vms.VmBasedWidgetSwitchModeCommand; import org.ovirt.engine.ui.uicommonweb.models.vms.VmInterfaceCreatingManager; import org.ovirt.engine.ui.uicompat.ConstantsManager; import org.ovirt.engine.ui.uicompat.FrontendActionAsyncResult; import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs; import org.ovirt.engine.ui.uicompat.external.StringUtils; public abstract class VmBaseListModel<E, T> extends ListWithSimpleDetailsModel<E, T> implements HasDiskWindow { public static final String DISK_WINDOW = "DiskWindow"; //$NON-NLS-1$ private VM privatecurrentVm; public VM getcurrentVm() { return privatecurrentVm; } public void setcurrentVm(VM value) { privatecurrentVm = value; } VmInterfaceCreatingManager addVmFromBlankTemplateNetworkManager = new VmInterfaceCreatingManager(new VmInterfaceCreatingManager.PostVnicCreatedCallback() { @Override public void vnicCreated(Guid vmId, UnitVmModel unitVmModel) { executeDiskModifications(vmId, unitVmModel); } @Override public void queryFailed() { // do nothing } }); protected VmInterfaceCreatingManager defaultNetworkCreatingManager = new VmInterfaceCreatingManager(new VmInterfaceCreatingManager.PostVnicCreatedCallback() { @Override public void vnicCreated(Guid vmId, UnitVmModel unitVmModel) { getWindow().stopProgress(); cancel(); updateActionsAvailability(); executeDiskModifications(vmId, unitVmModel); } @Override public void queryFailed() { getWindow().stopProgress(); cancel(); } }); protected void executeDiskModifications(Guid vmId, UnitVmModel model) { // this is done on the background - the window is not visible anymore getcurrentVm().setId(vmId); model.getInstanceImages().executeDiskModifications(getcurrentVm()); } protected void export() { T selectedEntity = getSelectedItem(); if (selectedEntity == null) { return; } if (getWindow() != null) { return; } ExportVmModel model = new ExportVmModel(); setWindow(model); model.startProgress(); setupExportModel(model); AsyncDataProvider.getInstance().getStorageDomainList(new AsyncQuery<>( storageDomains -> { List<StorageDomain> filteredStorageDomains = new ArrayList<>(); for (StorageDomain a : storageDomains) { if (a.getStorageDomainType() == StorageDomainType.ImportExport) { filteredStorageDomains.add(a); } } postExportGetStorageDomainList(filteredStorageDomains); }), extractStoragePoolIdNullSafe(selectedEntity)); // check, if the VM has a disk which doesn't allow snapshot sendWarningForNonExportableDisks(selectedEntity); } private void postExportGetStorageDomainList(List<StorageDomain> storageDomains) { ExportVmModel model = (ExportVmModel) getWindow(); model.getStorage().setItems(storageDomains); model.getStorage().setSelectedItem(Linq.firstOrNull(storageDomains)); boolean noActiveStorage = true; for (StorageDomain a : storageDomains) { if (a.getStatus() == StorageDomainStatus.Active) { noActiveStorage = false; break; } } if (entitiesSelectedOnDifferentDataCenters()) { model.getCollapseSnapshots().setIsChangeable(false); model.getForceOverride().setIsChangeable(false); model.setMessage(entityResideOnSeveralDCsMakeSureTheExportedVMResideOnSameDcMsg()); UICommand tempVar = new UICommand("Cancel", this); //$NON-NLS-1$ tempVar.setTitle(ConstantsManager.getInstance().getConstants().close()); tempVar.setIsDefault(true); tempVar.setIsCancel(true); model.getCommands().add(tempVar); model.stopProgress(); } else if (storageDomains.isEmpty()) { model.getCollapseSnapshots().setIsChangeable(false); model.getForceOverride().setIsChangeable(false); model.setMessage(thereIsNoExportDomainBackupEntityAttachExportDomainToVmsDcMsg()); UICommand tempVar2 = new UICommand("Cancel", this); //$NON-NLS-1$ tempVar2.setTitle(ConstantsManager.getInstance().getConstants().close()); tempVar2.setIsDefault(true); tempVar2.setIsCancel(true); model.getCommands().add(tempVar2); model.stopProgress(); } else if (noActiveStorage) { model.getCollapseSnapshots().setIsChangeable(false); model.getForceOverride().setIsChangeable(false); model.setMessage(ConstantsManager.getInstance() .getConstants() .theRelevantExportDomainIsNotActivePleaseActivateItMsg()); UICommand tempVar3 = new UICommand("Cancel", this); //$NON-NLS-1$ tempVar3.setTitle(ConstantsManager.getInstance().getConstants().close()); tempVar3.setIsDefault(true); tempVar3.setIsCancel(true); model.getCommands().add(tempVar3); model.stopProgress(); } else { showWarningOnExistingEntities(model, getEntityExportDomain()); UICommand tempVar4 = UICommand.createDefaultOkUiCommand("OnExport", this); //$NON-NLS-1$ model.getCommands().add(tempVar4); UICommand tempVar5 = UICommand.createCancelUiCommand("Cancel", this); //$NON-NLS-1$ model.getCommands().add(tempVar5); } } protected void showWarningOnExistingEntities(final ExportVmModel model, final VdcQueryType getVmOrTemplateQuery) { Guid storageDomainId = model.getStorage().getSelectedItem().getId(); AsyncDataProvider.getInstance().getDataCentersByStorageDomain(new AsyncQuery<>( storagePools -> postShowWarningOnExistingVms(model, storagePools, getVmOrTemplateQuery)), storageDomainId); } private void postShowWarningOnExistingVms(final ExportVmModel exportModel, List<StoragePool> storagePools, VdcQueryType getVmOrTemplateQuery) { StoragePool storagePool = storagePools.size() > 0 ? storagePools.get(0) : null; if (storagePool != null) { Guid storageDomainId = exportModel.getStorage().getSelectedItem().getId(); GetAllFromExportDomainQueryParameters tempVar = new GetAllFromExportDomainQueryParameters(storagePool.getId(), storageDomainId); Frontend.getInstance().runQuery(getVmOrTemplateQuery, tempVar, new AsyncQuery<>((AsyncCallback<VdcQueryReturnValue>) returnValue -> { ExportVmModel windowModel = (ExportVmModel) getWindow(); List<T> foundVms = new ArrayList<>(); if (returnValue != null) { Iterable<T> iterableReturnValue = asIterableReturnValue(returnValue.getReturnValue()); for (T selectedItem1 : getSelectedItems()) { for (T returnValueItem : iterableReturnValue) { if (entititesEqualsNullSafe(returnValueItem, selectedItem1)) { foundVms.add(selectedItem1); break; } } } } if (foundVms.size() != 0) { windowModel.setMessage(composeEntityOnStorage(composeExistingVmsWarningMessage(foundVms))); } exportModel.stopProgress(); })); } else { exportModel.stopProgress(); } } private String composeExistingVmsWarningMessage(List<T> existingVms) { final List<String> list = new ArrayList<>(); for (T t : existingVms) { list.add(extractNameFromEntity(t)); } return StringUtils.join(list, ", "); //$NON-NLS-1$ } protected void setupExportModel(ExportVmModel model) { // no-op by default. Override if needed. } protected void setupNewVmModel(UnitVmModel model, VmType vmtype, SystemTreeItemModel systemTreeItemModel, List<UICommand> uiCommands) { model.setTitle(ConstantsManager.getInstance().getConstants().newVmTitle()); model.setHelpTag(HelpTag.new_vm); model.setHashName("new_vm"); //$NON-NLS-1$ model.setIsNew(true); model.getVmType().setSelectedItem(vmtype); model.setCustomPropertiesKeysList(AsyncDataProvider.getInstance().getCustomPropertiesList()); model.setIsAdvancedModeLocalStorageKey("wa_vm_dialog"); //$NON-NLS-1$ setWindow(model); model.initialize(systemTreeItemModel); VmBasedWidgetSwitchModeCommand switchModeCommand = new VmBasedWidgetSwitchModeCommand(); switchModeCommand.init(model); model.getCommands().add(switchModeCommand); model.getProvisioning().setEntity(true); for (UICommand uicommand : uiCommands) { model.getCommands().add(uicommand); } model.initForemanProviders(null); } protected void validateVm(final UnitVmModel model, final String vmName) { if (!model.validate()) { return; } AsyncDataProvider.getInstance(). isVmNameUnique(new AsyncQuery<>(returnValue -> { if (!returnValue && vmName.compareToIgnoreCase(getcurrentVm().getName()) != 0) { model.getName() .getInvalidityReasons() .add(ConstantsManager.getInstance().getConstants().nameMustBeUniqueInvalidReason()); model.getName().setIsValid(false); model.setValidTab(TabName.GENERAL_TAB, false); model.fireValidationCompleteEvent(); } else { model.getName() .getInvalidityReasons().clear(); model.getName().setIsValid(true); model.setValidTab(TabName.GENERAL_TAB, true); onSaveVM(model); } } ), vmName, model.getSelectedDataCenter() == null ? null : model.getSelectedDataCenter().getId()); } protected void onSaveVM(UnitVmModel model) { // Save changes. buildVmOnSave(model, getcurrentVm()); getcurrentVm().setCpuPinning(model.getCpuPinning().getEntity()); getcurrentVm().setUseHostCpuFlags(model.getHostCpu().getEntity()); getcurrentVm().setVmInit(model.getVmInitModel().buildCloudInitParameters(model)); if (!model.getProviders().getItems().iterator().next().equals(model.getProviders().getSelectedItem())) { getcurrentVm().setProviderId(model.getProviders().getSelectedItem().getId()); } if (model.getIsNew()) { saveNewVm(model); } else { updateVM(model); } } private void saveNewVm(final UnitVmModel model) { if (model.getProgress() != null) { return; } model.startProgress(); VM vm = getcurrentVm(); if (!StringHelper.isNullOrEmpty(model.getVmId().getEntity())) { vm.setId(new Guid(model.getVmId().getEntity())); } vm.setUseLatestVersion(model.getTemplateWithVersion().getSelectedItem().isLatest()); AddVmParameters parameters = new AddVmParameters(vm); parameters.setDiskInfoDestinationMap(model.getDisksAllocationModel().getImageToDestinationDomainMap()); parameters.setConsoleEnabled(model.getIsConsoleDeviceEnabled().getEntity()); parameters.setBalloonEnabled(balloonEnabled(model)); parameters.setCopyTemplatePermissions(model.getCopyPermissions().getEntity()); parameters.setSoundDeviceEnabled(model.getIsSoundcardEnabled().getEntity()); parameters.setVirtioScsiEnabled(model.getIsVirtioScsiEnabled().getEntity()); parameters.setVmLargeIcon(IconUtils.filterPredefinedIcons(model.getIcon().getEntity().getIcon())); setVmWatchdogToParams(model, parameters); setRngDeviceToParams(model, parameters); if (model.getIsHeadlessModeEnabled().getEntity()) { parameters.getVmStaticData().setDefaultDisplayType(DisplayType.none); } BuilderExecutor.build(model, parameters, new UnitToGraphicsDeviceParamsBuilder()); if (!StringHelper.isNullOrEmpty(model.getVmId().getEntity())) { parameters.setVmId(new Guid(model.getVmId().getEntity())); } Frontend.getInstance().runAction( model.getProvisioning().getEntity() ? VdcActionType.AddVmFromTemplate : VdcActionType.AddVm, parameters, createUnitVmModelNetworkAsyncCallback(vm, model), this); } protected void updateVM(UnitVmModel model){ // no-op by default. Override if needed. } protected void cancel() { // no-op by default. Override if needed. } protected void updateActionsAvailability() { // no-op by default. Override if needed. } protected UnitVmModelNetworkAsyncCallback createUnitVmModelNetworkAsyncCallback(VM vm, UnitVmModel model) { if (vm.getVmtGuid().equals(Guid.Empty)) { return new UnitVmModelNetworkAsyncCallback(model, addVmFromBlankTemplateNetworkManager) { @Override public void executed(FrontendActionAsyncResult result) { getWindow().stopProgress(); VdcReturnValueBase returnValue = result.getReturnValue(); if (returnValue != null && returnValue.getSucceeded()) { setWindow(null); updateActionsAvailability(); } else { cancel(); } super.executed(result); } }; } return new UnitVmModelNetworkAsyncCallback(model, defaultNetworkCreatingManager); } public static void buildVmOnSave(UnitVmModel model, VM vm) { BuilderExecutor.build(model, vm.getStaticData(), new FullUnitToVmBaseBuilder()); BuilderExecutor.build(model, vm, new VmSpecificUnitToVmBuilder()); } protected boolean balloonEnabled(UnitVmModel model) { return BalloonEnabled.balloonEnabled(model); } protected void setVmWatchdogToParams(final UnitVmModel model, VmManagementParametersBase updateVmParams) { VmWatchdogType wdModel = model.getWatchdogModel().getSelectedItem(); updateVmParams.setUpdateWatchdog(true); if (wdModel != null) { VmWatchdog vmWatchdog = new VmWatchdog(); vmWatchdog.setAction(model.getWatchdogAction().getSelectedItem()); vmWatchdog.setModel(wdModel); updateVmParams.setWatchdog(vmWatchdog); } } protected void setRngDeviceToParams(UnitVmModel model, VmManagementParametersBase parameters) { parameters.setUpdateRngDevice(true); parameters.setRngDevice(model.getIsRngEnabled().getEntity() ? model.generateRngDevice() : null); } protected abstract String composeEntityOnStorage(String entities); protected abstract Iterable<T> asIterableReturnValue(Object returnValue); protected abstract boolean entititesEqualsNullSafe(T e1, T e2); protected abstract String extractNameFromEntity(T entity); protected abstract Guid extractStoragePoolIdNullSafe(T entity); protected abstract boolean entitiesSelectedOnDifferentDataCenters(); protected abstract String entityResideOnSeveralDCsMakeSureTheExportedVMResideOnSameDcMsg(); protected abstract String thereIsNoExportDomainBackupEntityAttachExportDomainToVmsDcMsg(); protected abstract VdcQueryType getEntityExportDomain(); protected abstract void sendWarningForNonExportableDisks(T entity); private Model diskModel; public void setDiskWindow(Model value) { if (diskModel != value) { diskModel = value; onPropertyChanged(new PropertyChangedEventArgs(DISK_WINDOW)); } } public Model getDiskWindow() { return diskModel; } }