package org.ovirt.engine.ui.uicommonweb.models.networks; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.ovirt.engine.core.common.action.AddNetworkStoragePoolParameters; import org.ovirt.engine.core.common.action.AddVnicProfileParameters; import org.ovirt.engine.core.common.action.ManageNetworkClustersParameters; import org.ovirt.engine.core.common.action.VdcActionParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.Provider; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.comparators.NameableComparator; import org.ovirt.engine.core.common.businessentities.network.Network; import org.ovirt.engine.core.common.businessentities.network.NetworkCluster; import org.ovirt.engine.core.common.businessentities.network.VnicProfile; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.ui.frontend.Frontend; 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.help.HelpTag; import org.ovirt.engine.ui.uicommonweb.models.CommonModel; import org.ovirt.engine.ui.uicommonweb.models.ListModel; import org.ovirt.engine.ui.uicommonweb.models.Model; import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel; import org.ovirt.engine.ui.uicommonweb.models.SystemTreeItemModel; import org.ovirt.engine.ui.uicommonweb.models.SystemTreeItemType; import org.ovirt.engine.ui.uicommonweb.models.providers.ExternalNetwork; import org.ovirt.engine.ui.uicompat.ConstantsManager; import org.ovirt.engine.ui.uicompat.IFrontendActionAsyncCallback; public class BaseImportNetworksModel extends Model { private static final String CMD_IMPORT = "OnImport"; //$NON-NLS-1$ private static final String CMD_CANCEL = "Cancel"; //$NON-NLS-1$ private final SearchableListModel sourceListModel; private final StoragePool treeSelectedDc; private final ListModel<Provider<?>> providers = new ListModel<>(); private final ListModel<ExternalNetwork> providerNetworks = new ListModel<>(); private final ListModel<ExternalNetwork> importedNetworks = new ListModel<>(); private final ListModel<String> errors = new ListModel<>(); private final UICommand addImportCommand = new UICommand(null, this); private final UICommand cancelImportCommand = new UICommand(null, this); private Map<Guid, Collection<Cluster>> dcClusters; private final com.google.inject.Provider<CommonModel> commonModelProvider; public ListModel<ExternalNetwork> getProviderNetworks() { return providerNetworks; } public ListModel<ExternalNetwork> getImportedNetworks() { return importedNetworks; } public ListModel<Provider<?>> getProviders() { return providers; } public ListModel<String> getErrors() { return errors; } public UICommand getAddImportCommand() { return addImportCommand; } public UICommand getCancelImportCommand() { return cancelImportCommand; } public BaseImportNetworksModel(SearchableListModel sourceListModel, final com.google.inject.Provider<CommonModel> commonModelProvider) { this.commonModelProvider = commonModelProvider; this.sourceListModel = sourceListModel; setTitle(ConstantsManager.getInstance().getConstants().importNetworksTitle()); setHelpTag(HelpTag.import_networks); setHashName("import_networks"); //$NON-NLS-1$ UICommand importCommand = new UICommand(CMD_IMPORT, this); importCommand.setIsExecutionAllowed(false); importCommand.setTitle(ConstantsManager.getInstance().getConstants().importNetworksButton()); importCommand.setIsDefault(true); getCommands().add(importCommand); UICommand cancelCommand = UICommand.createCancelUiCommand(CMD_CANCEL, this); //$NON-NLS-1$ getCommands().add(cancelCommand); SystemTreeItemModel treeSelectedDcItem = SystemTreeItemModel.findAncestor(SystemTreeItemType.DataCenter, commonModelProvider.get().getSystemTree().getSelectedItem()); treeSelectedDc = (treeSelectedDcItem == null) ? null : (StoragePool) treeSelectedDcItem.getEntity(); providers.getSelectedItemChangedEvent().addListener((ev, sender, args) -> onProviderChosen()); initProviderList(); } protected void initProviderList() { startProgress(); AsyncDataProvider.getInstance().getAllNetworkProviders(new AsyncQuery<>(providers -> { stopProgress(); providers.add(0, null); getProviders().setItems(providers); })); } private void onProviderChosen() { final Provider<?> provider = providers.getSelectedItem(); if (provider == null) { return; } final List<StoragePool> dataCenters = new LinkedList<>(); startProgress(); AsyncDataProvider.getInstance().getDataCenterList(new AsyncQuery<>(returnValue -> { dataCenters.addAll(returnValue); Collections.sort(dataCenters, new NameableComparator()); AsyncDataProvider.getInstance().getExternalNetworkMap(new AsyncQuery<>(externalNetworkToDataCenters -> { List<ExternalNetwork> items = new LinkedList<>(); for (Map.Entry<Network, Set<Guid>> entry : externalNetworkToDataCenters.entrySet()) { Network network = entry.getKey(); Set<Guid> attachedDataCenters = entry.getValue(); ExternalNetwork externalNetwork = new ExternalNetwork(); externalNetwork.setNetwork(network); externalNetwork.setDisplayName(network.getName()); externalNetwork.setPublicUse(true); List<StoragePool> availableDataCenters = new LinkedList<>(); for (StoragePool dc : dataCenters) { if (!attachedDataCenters.contains(dc.getId())) { availableDataCenters.add(dc); } } externalNetwork.getDataCenters().setItems(availableDataCenters); externalNetwork.getDataCenters().setSelectedItem(treeSelectedDc != null && availableDataCenters.contains(treeSelectedDc) ? treeSelectedDc : Linq.firstOrNull(availableDataCenters)); items.add(externalNetwork); } Collections.sort(items, Comparator.comparing(ExternalNetwork::getNetwork, new NameableComparator())); providerNetworks.setItems(items); importedNetworks.setItems(new LinkedList<ExternalNetwork>()); stopProgress(); }), provider.getId()); })); } private boolean validate() { String errorDuplicate = ConstantsManager.getInstance().getConstants().importDuplicateName(); boolean valid = true; Collection<ExternalNetwork> networks = importedNetworks.getItems(); List<String> errors = new ArrayList<>(networks.size()); Map<String, Integer> nameToIndex = new HashMap<>(); int i = 0; for (ExternalNetwork network : networks) { String networkName = network.getDisplayName(); Integer encounteredIndex = nameToIndex.get(networkName); // if this name has been encountered, invalidate that entry; else store it for future invalidation if (encounteredIndex != null) { errors.set(encounteredIndex, errorDuplicate); valid = false; } else { nameToIndex.put(networkName, i); } // invalidate current entry errors.add(encounteredIndex == null ? null : errorDuplicate); ++i; } getErrors().setItems(errors); return valid; } public void cancel() { sourceListModel.setWindow(null); } public void onImport() { if (!validate()) { return; } List<VdcActionParametersBase> multipleActionParameters = new LinkedList<>(); List<IFrontendActionAsyncCallback> callbacks = new LinkedList<>(); dcClusters = new HashMap<>(); for (final ExternalNetwork externalNetwork : importedNetworks.getItems()) { final Network network = externalNetwork.getNetwork(); final Guid dcId = externalNetwork.getDataCenters().getSelectedItem().getId(); network.setName(externalNetwork.getDisplayName()); network.setDataCenterId(dcId); AddNetworkStoragePoolParameters params = new AddNetworkStoragePoolParameters(dcId, network); params.setVnicProfileRequired(false); multipleActionParameters.add(params); callbacks.add(result -> { VdcReturnValueBase returnValue = result.getReturnValue(); if (returnValue != null && returnValue.getSucceeded()) { network.setId((Guid) returnValue.getActionReturnValue()); // Perform sequentially: first fetch clusters, then attach network, then create VNIC profile fetchDcClusters(dcId, network, externalNetwork.isPublicUse()); } }); } Frontend.getInstance().runMultipleActions(VdcActionType.AddNetwork, multipleActionParameters, callbacks); cancel(); } private void fetchDcClusters(final Guid dcId, final Network network, final boolean publicUse) { if (dcClusters.containsKey(dcId)) { attachNetworkToClusters(network, dcClusters.get(dcId), publicUse); } else { AsyncDataProvider.getInstance().getClusterList(new AsyncQuery<>(clusters -> { dcClusters.put(dcId, clusters); attachNetworkToClusters(network, clusters, publicUse); }), dcId); } } private void attachNetworkToClusters(final Network network, Collection<Cluster> clusters, final boolean publicUse) { List<NetworkCluster> networkAttachments = new LinkedList<>(); for (Cluster cluster : clusters) { final NetworkCluster networkCluster = new NetworkCluster(); networkCluster.setClusterId(cluster.getId()); networkCluster.setNetworkId(network.getId()); networkCluster.setRequired(false); networkAttachments.add(networkCluster); } Frontend.getInstance().runAction( VdcActionType.ManageNetworkClusters, new ManageNetworkClustersParameters(networkAttachments), result -> addVnicProfile(network, publicUse)); } private void addVnicProfile(Network network, boolean publicUse) { VnicProfile vnicProfile = new VnicProfile(); vnicProfile.setName(network.getName()); vnicProfile.setNetworkId(network.getId()); AddVnicProfileParameters parameters = new AddVnicProfileParameters(vnicProfile, true); parameters.setPublicUse(publicUse); Frontend.getInstance().runAction(VdcActionType.AddVnicProfile, parameters, result -> sourceListModel.getSearchCommand().execute()); } private void addImport() { getDefaultCommand().setIsExecutionAllowed(true); } private void cancelImport() { Collection<ExternalNetwork> selectedNetworks = getImportedNetworks().getSelectedItems(); Collection<ExternalNetwork> importedNetworks = getImportedNetworks().getItems(); getDefaultCommand().setIsExecutionAllowed(selectedNetworks.size() < importedNetworks.size()); for (ExternalNetwork externalNetwork : selectedNetworks) { externalNetwork.setDisplayName(externalNetwork.getNetwork().getName()); } } @Override public void executeCommand(UICommand command) { super.executeCommand(command); if (CMD_IMPORT.equals(command.getName())) { onImport(); } else if (CMD_CANCEL.equals(command.getName())) { cancel(); } else if (getAddImportCommand().equals(command)) { addImport(); } else if (getCancelImportCommand().equals(command)) { cancelImport(); } } }