package org.ovirt.engine.ui.uicommonweb.models.userportal; import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import org.ovirt.engine.core.common.businessentities.Nameable; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmPool; import org.ovirt.engine.core.common.businessentities.comparators.NameableComparator; import org.ovirt.engine.core.common.queries.IdQueryParameters; import org.ovirt.engine.core.common.queries.VdcQueryParametersBase; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.ui.frontend.Frontend; import org.ovirt.engine.ui.uicommonweb.ConsoleOptionsFrontendPersister.ConsoleContext; import org.ovirt.engine.ui.uicommonweb.IconUtils; import org.ovirt.engine.ui.uicommonweb.UICommand; import org.ovirt.engine.ui.uicommonweb.help.HelpTag; import org.ovirt.engine.ui.uicommonweb.models.ConsolePopupModel; import org.ovirt.engine.ui.uicommonweb.models.ConsolesFactory; import org.ovirt.engine.ui.uicommonweb.models.ListWithDetailsModel; import org.ovirt.engine.ui.uicommonweb.models.Model; import org.ovirt.engine.ui.uicommonweb.models.VmConsoles; import org.ovirt.engine.ui.uicompat.Event; import org.ovirt.engine.ui.uicompat.EventArgs; import org.ovirt.engine.ui.uicompat.ICancelable; public abstract class AbstractUserPortalListModel extends ListWithDetailsModel<Void, /* VmOrPool */ Object, UserPortalItemModel> implements ICancelable { private UICommand editConsoleCommand; protected ConsolesFactory consolesFactory; public AbstractUserPortalListModel() { setEditConsoleCommand(new UICommand("NewServer", this)); //$NON-NLS-1$ } public List<VmConsoles> getAutoConnectableConsoles() { List<VmConsoles> autoConnectableConsoles = new LinkedList<>(); if (items != null) { for (UserPortalItemModel upItem : items) { if (!upItem.isPool() && upItem.getVmConsoles().canConnectToConsole()) { autoConnectableConsoles.add(upItem.getVmConsoles()); } } } return autoConnectableConsoles; } public boolean getCanConnectAutomatically() { return getAutoConnectableConsoles().size() == 1; } public UICommand getEditConsoleCommand() { return editConsoleCommand; } private void setEditConsoleCommand(UICommand editConsoleCommand) { this.editConsoleCommand = editConsoleCommand; } @Override protected Object provideDetailModelEntity(UserPortalItemModel selectedItem) { // Each item in this list model is not a business entity, // therefore select an Entity property to provide it to // the detail models. if (selectedItem == null) { return null; } return selectedItem.getEntity(); } @Override public void executeCommand(UICommand command) { super.executeCommand(command); if (command == getEditConsoleCommand()) { editConsole(); } else if ("OnEditConsoleSave".equals(command.getName())) { //$NON-NLS-1$ onEditConsoleSave(); } else if (Model.CANCEL_COMMAND.equals(command.getName())) { cancel(); } } private void onEditConsoleSave() { cancel(); } private void editConsole() { if (getWindow() != null || getSelectedItem().getVmConsoles() == null) { return; } ConsolePopupModel model = new ConsolePopupModel(); model.setVmConsoles(getSelectedItem().getVmConsoles()); model.setHelpTag(HelpTag.editConsole); model.setHashName("editConsole"); //$NON-NLS-1$ setWindow(model); UICommand saveCommand = UICommand.createDefaultOkUiCommand("OnEditConsoleSave", this); //$NON-NLS-1$ model.getCommands().add(saveCommand); UICommand cancelCommand = UICommand.createCancelUiCommand("Cancel", this); //$NON-NLS-1$ model.getCommands().add(cancelCommand); } protected abstract ConsoleContext getConsoleContext(); protected abstract boolean fetchLargeIcons(); protected abstract Event<EventArgs> getSearchCompletedEvent(); public void onVmAndPoolLoad(final List<VM> vms, List<VmPool> pools) { if (vms == null || pools == null) { return; } // Count how many VMs were provided by each pool Map<Guid, Long> vmsPerPool = vms.stream() .filter(vm -> vm.getVmPoolId() != null) .collect(Collectors.groupingBy(VM::getVmPoolId, Collectors.counting())); // Remove pools that has provided VMs. final List<VmPool> filteredPools = pools.stream() .filter(p -> p.getMaxAssignedVmsPerUser() < vmsPerPool.getOrDefault(p.getVmPoolId(), 0L)) .collect(Collectors.toList()); final List<Pair<Nameable, VM>> vmPairs = vms.stream().map(v -> new Pair<Nameable, VM>(v, null)).collect(Collectors.toList()); if (filteredPools.isEmpty()) { IconUtils.prefetchIcons(vms, true, fetchLargeIcons(), idToIconMap -> finishSearch(vmPairs)); } else { // if we have pools we have to update their console cache and THEN finish search List<VdcQueryType> poolQueryList = new ArrayList<>(); List<VdcQueryParametersBase> poolParamList = new ArrayList<>(); for (VmPool p : filteredPools) { poolQueryList.add(VdcQueryType.GetVmDataByPoolId); poolParamList.add(new IdQueryParameters(p.getVmPoolId())); } Frontend.getInstance().runMultipleQueries( poolQueryList, poolParamList, result -> { final List<Pair<Nameable, VM>> all = Stream.concat(vmPairs.stream(), IntStream.range(0, filteredPools.size()) .filter(i -> result.getReturnValues().get(i).getReturnValue() != null) .mapToObj(i -> new Pair<Nameable, VM>( filteredPools.get(i), result.getReturnValues().get(i).getReturnValue()) ) ).collect(Collectors.toList()); final List<VM> vmsAndPoolRepresentants = extractVms(all); IconUtils.prefetchIcons(vmsAndPoolRepresentants, true, fetchLargeIcons(), idToIconMap -> finishSearch(all)); }); } } /** * @param vmsAndPools List of pairs of these types: (VM, null) or (VmPool, VM representative) * @return all VMs from the input */ private List<VM> extractVms(List<Pair<Nameable, VM>> vmsAndPools) { final ArrayList<VM> result = new ArrayList<>(); for (Pair<Nameable, VM> vmOrPool : vmsAndPools) { if (vmOrPool.getFirst() instanceof VM) { result.add((VM) vmOrPool.getFirst()); continue; } if (vmOrPool.getSecond() != null) { result.add(vmOrPool.getSecond()); } } return result; } private void finishSearch(List<Pair<Nameable, VM>> vmOrPoolAndPoolRepresentants) { setItems(vmOrPoolAndPoolRepresentants.stream() .sorted(Comparator.comparing(Pair::getFirst, new NameableComparator())) .map(item -> new UserPortalItemModel(item.getFirst(), item.getSecond(), consolesFactory)) .collect(Collectors.toList())); getSearchCompletedEvent().raise(this, EventArgs.EMPTY); } public void cancel() { setWindow(null); setConfirmWindow(null); } }