package org.ovirt.engine.ui.uicommonweb.models.vms.hostdev; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.ovirt.engine.core.common.businessentities.HostDeviceView; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmHostDevice; import org.ovirt.engine.core.common.queries.ConfigurationValues; 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.EntityModel; import org.ovirt.engine.ui.uicommonweb.models.ListModel; import org.ovirt.engine.ui.uicommonweb.models.SortedListModel; import org.ovirt.engine.ui.uicommonweb.validation.IValidation; import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation; import org.ovirt.engine.ui.uicompat.ConstantsManager; public class AddVmHostDevicesModel extends ModelWithPinnedHost { private ListModel<String> capability; private SortedListModel<EntityModel<HostDeviceView>> allAvailableHostDevices; private SortedListModel<EntityModel<HostDeviceView>> availableHostDevices; private SortedListModel<EntityModel<HostDeviceView>> selectedHostDevices; private UICommand addDeviceCommand = new UICommand(null, this); private UICommand removeDeviceCommand = new UICommand(null, this); private Set<String> alreadyAttachedDevices = new HashSet<>(); public AddVmHostDevicesModel() { setCapability(new ListModel<String>()); setAllAvailableHostDevices(new SortedListModel<EntityModel<HostDeviceView>>()); setAvailableHostDevices(new SortedListModel<EntityModel<HostDeviceView>>()); setSelectedHostDevices(new SortedListModel<EntityModel<HostDeviceView>>()); setTitle(ConstantsManager.getInstance().getConstants().addVmHostDevicesTitle()); setHelpTag(HelpTag.add_host_device); setHashName("add_host_device"); //$NON-NLS-1$ getPinnedHost().getSelectedItemChangedEvent().addListener((ev, sender, args) -> updateAvailableHostDevices()); getCapability().getSelectedItemChangedEvent().addListener((ev, sender, args) -> updateSelectedCapability()); getAllAvailableHostDevices().getItemsChangedEvent().addListener((ev, sender, args) -> updateSelectedCapability()); } @Override public void init(VM vm) { super.init(vm); initCapabilities(); fetchExistingDevices(); } private void fetchExistingDevices() { startProgress(); AsyncDataProvider.getInstance().getConfiguredVmHostDevices(new AsyncQuery<>(devices -> { for (VmHostDevice device : devices) { if (!device.isIommuPlaceholder()) { alreadyAttachedDevices.add(device.getDevice()); } } // initHosts must be called after alreadyAttachedDevices are initialized initHosts(); }), getVm().getId()); } @SuppressWarnings("unchecked") private void initCapabilities() { List<String> capabilities = (List<String>) AsyncDataProvider.getInstance() .getConfigValuePreConverted(ConfigurationValues.HostDevicePassthroughCapabilities); getCapability().setItems(capabilities); } private void updateAvailableHostDevices() { if (getPinnedHost().getSelectedItem() == null) { return; } availableHostDevices.setItems(new ArrayList<EntityModel<HostDeviceView>>()); selectedHostDevices.setItems(new ArrayList<EntityModel<HostDeviceView>>()); startProgress(); AsyncDataProvider.getInstance().getHostDevicesByHostId(new AsyncQuery<>(fetchedDevices -> { stopProgress(); List<EntityModel<HostDeviceView>> models = new ArrayList<>(); for (HostDeviceView hostDevice : fetchedDevices) { // show only devices that support assignment and are not yet attached if (hostDevice.isAssignable() && !alreadyAttachedDevices.contains(hostDevice.getDeviceName())) { models.add(new EntityModel<>(hostDevice)); } } allAvailableHostDevices.setItems(models); }), getPinnedHost().getSelectedItem().getId()); } private void updateSelectedCapability() { if (getAllAvailableHostDevices().getItems() == null) { return; } final String selectedCapability = getCapability().getSelectedItem(); availableHostDevices.setItems(Linq.where(allAvailableHostDevices.getItems(), hostDevice -> hostDevice.getEntity().getCapability().equals(selectedCapability) && !getSelectedHostDevices().getItems().contains(hostDevice))); } public ListModel<String> getCapability() { return capability; } public void setCapability(ListModel<String> capability) { this.capability = capability; } public SortedListModel<EntityModel<HostDeviceView>> getAllAvailableHostDevices() { return allAvailableHostDevices; } public void setAllAvailableHostDevices(SortedListModel<EntityModel<HostDeviceView>> allAvailableHostDevices) { this.allAvailableHostDevices = allAvailableHostDevices; } public SortedListModel<EntityModel<HostDeviceView>> getAvailableHostDevices() { return availableHostDevices; } public void setAvailableHostDevices(SortedListModel<EntityModel<HostDeviceView>> availableHostDevices) { this.availableHostDevices = availableHostDevices; } public SortedListModel<EntityModel<HostDeviceView>> getSelectedHostDevices() { return selectedHostDevices; } public void setSelectedHostDevices(SortedListModel<EntityModel<HostDeviceView>> selectedHostDevices) { this.selectedHostDevices = selectedHostDevices; } public UICommand getAddDeviceCommand() { return addDeviceCommand; } public void setAddDeviceCommand(UICommand addDeviceCommand) { this.addDeviceCommand = addDeviceCommand; } public UICommand getRemoveDeviceCommand() { return removeDeviceCommand; } public void setRemoveDeviceCommand(UICommand removeDeviceCommand) { this.removeDeviceCommand = removeDeviceCommand; } public boolean validate() { getPinnedHost().validateSelectedItem(new IValidation[]{new NotEmptyValidation()}); return getPinnedHost().getIsValid(); } @Override public void executeCommand(UICommand command) { super.executeCommand(command); if (getAddDeviceCommand().equals(command)) { addDevice(); } else if (getRemoveDeviceCommand().equals(command)) { removeDevice(); } else { super.executeCommand(command); } } private void addDevice() { // TODO: add all devices from given IOMMU group and notify user } private void removeDevice() { // TODO: remove all devices from given IOMMU group and notify user } }