package org.ovirt.engine.ui.uicommonweb.models.gluster; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeType; import org.ovirt.engine.core.common.mode.ApplicationMode; import org.ovirt.engine.core.compat.Version; 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.ApplicationModeHelper; import org.ovirt.engine.ui.uicommonweb.models.ConfirmationModel; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; import org.ovirt.engine.ui.uicommonweb.models.ListModel; import org.ovirt.engine.ui.uicommonweb.models.Model; import org.ovirt.engine.ui.uicommonweb.models.volumes.VolumeListModel; import org.ovirt.engine.ui.uicommonweb.validation.AsciiNameValidation; import org.ovirt.engine.ui.uicommonweb.validation.IValidation; import org.ovirt.engine.ui.uicommonweb.validation.LengthValidation; import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation; import org.ovirt.engine.ui.uicompat.ConstantsManager; import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs; public class VolumeModel extends Model { EntityModel<String> name; ListModel<GlusterVolumeType> typeList; EntityModel<Integer> replicaCount; EntityModel<Integer> stripeCount; EntityModel<Boolean> tcpTransportType; EntityModel<Boolean> rdmaTransportType; ListModel<StoragePool> dataCenter; ListModel<Cluster> cluster; ListModel<EntityModel<GlusterBrickEntity>> bricks; EntityModel<Boolean> gluster_accecssProtocol; EntityModel<Boolean> nfs_accecssProtocol; EntityModel<Boolean> cifs_accecssProtocol; EntityModel<String> allowAccess; EntityModel<Boolean> optimizeForVirtStore; EntityModel<Boolean> arbiterVolume; private boolean forceAddBricks; private UICommand addBricksCommand; public UICommand getAddBricksCommand() { return addBricksCommand; } private void setAddBricksCommand(UICommand value) { addBricksCommand = value; } public ListModel<StoragePool> getDataCenter() { return dataCenter; } public void setDataCenter(ListModel<StoragePool> dataCenter) { this.dataCenter = dataCenter; } public ListModel<Cluster> getCluster() { return cluster; } public void setCluster(ListModel<Cluster> cluster) { this.cluster = cluster; } private boolean isHCMode() { if (getCluster() == null || getCluster().getSelectedItem() == null) { return false; } if (getCluster().getSelectedItem().supportsGlusterService() && getCluster().getSelectedItem().supportsVirtService()) { return true; } return false; } public VolumeModel() { setAddBricksCommand(new UICommand("AddBricks", this)); //$NON-NLS-1$ getAddBricksCommand().setIsExecutionAllowed(false); getAddBricksCommand().setTitle(ConstantsManager.getInstance().getConstants().addBricksVolume()); setDataCenter(new ListModel<StoragePool>()); getDataCenter().getSelectedItemChangedEvent().addListener((ev, sender, args) -> dataCenter_SelectedItemChanged()); getDataCenter().setIsAvailable(ApplicationModeHelper.getUiMode() != ApplicationMode.GlusterOnly); setCluster(new ListModel<Cluster>()); getCluster().getSelectedItemChangedEvent().addListener((ev, sender, args) -> clusterSelectedItemChanged()); setName(new EntityModel<String>()); setTypeList(new ListModel<GlusterVolumeType>()); ArrayList<GlusterVolumeType> list = new ArrayList<>(); //do not show Distribute for HC if (!isHCMode()) { list.add(GlusterVolumeType.DISTRIBUTE); } list.add(GlusterVolumeType.REPLICATE); list.add(GlusterVolumeType.DISTRIBUTED_REPLICATE); getTypeList().setItems(list); setReplicaCount(new EntityModel<Integer>()); getReplicaCount().setEntity(VolumeListModel.REPLICATE_COUNT_DEFAULT); getReplicaCount().setIsChangeable(false); setStripeCount(new EntityModel<Integer>()); getStripeCount().setEntity(VolumeListModel.STRIPE_COUNT_DEFAULT); getStripeCount().setIsChangeable(false); setTcpTransportType(new EntityModel<Boolean>()); getTcpTransportType().setEntity(true); setRdmaTransportType(new EntityModel<Boolean>()); getRdmaTransportType().setEntity(false); getTypeList().setSelectedItem(GlusterVolumeType.REPLICATE); getReplicaCount().setIsAvailable(true); getStripeCount().setIsAvailable(false); setBricks(new ListModel<EntityModel<GlusterBrickEntity>>()); getTypeList().getSelectedItemChangedEvent().addListener((ev, sender, args) -> { getReplicaCount().setIsAvailable(getTypeList().getSelectedItem().isReplicatedType()); getStripeCount().setIsAvailable(getTypeList().getSelectedItem().isStripedType()); if (getBricks().getItems() != null && ((List) getBricks().getItems()).size() > 0 && !validateBrickCount() && getAddBricksCommand().getIsExecutionAllowed()) { getAddBricksCommand().execute(); } updateArbiterAvailability(); }); setGluster_accecssProtocol(new EntityModel<Boolean>()); getGluster_accecssProtocol().setEntity(true); getGluster_accecssProtocol().setIsChangeable(false); setNfs_accecssProtocol(new EntityModel<Boolean>()); getNfs_accecssProtocol().setEntity(false); setCifs_accecssProtocol(new EntityModel<Boolean>()); getCifs_accecssProtocol().setEntity(false); setAllowAccess(new EntityModel<String>()); getAllowAccess().setEntity("*"); //$NON-NLS-1$ setOptimizeForVirtStore(new EntityModel<Boolean>()); getOptimizeForVirtStore().setEntity(false); setArbiterVolume(new EntityModel<Boolean>()); getArbiterVolume().setEntity(false); getArbiterVolume().setIsAvailable(false); } public EntityModel<String> getName() { return name; } public void setName(EntityModel<String> name) { this.name = name; } public ListModel<GlusterVolumeType> getTypeList() { return typeList; } public void setTypeList(ListModel<GlusterVolumeType> typeList) { this.typeList = typeList; } public EntityModel<Integer> getReplicaCount() { return replicaCount; } public Integer getReplicaCountValue() { return replicaCount.getEntity(); } public void setReplicaCount(EntityModel<Integer> replicaCount) { this.replicaCount = replicaCount; } public EntityModel<Integer> getStripeCount() { return stripeCount; } public Integer getStripeCountValue() { return stripeCount.getEntity(); } public void setStripeCount(EntityModel<Integer> stripeCount) { this.stripeCount = stripeCount; } public EntityModel<Boolean> getTcpTransportType() { return tcpTransportType; } public void setTcpTransportType(EntityModel<Boolean> tcpTransportType) { this.tcpTransportType = tcpTransportType; } public EntityModel<Boolean> getRdmaTransportType() { return rdmaTransportType; } public void setRdmaTransportType(EntityModel<Boolean> rdmaTransportType) { this.rdmaTransportType = rdmaTransportType; } public ListModel<EntityModel<GlusterBrickEntity>> getBricks() { return bricks; } public void setBricks(ListModel<EntityModel<GlusterBrickEntity>> bricks) { this.bricks = bricks; onPropertyChanged(new PropertyChangedEventArgs("Bricks")); //$NON-NLS-1$ } public EntityModel<Boolean> getGluster_accecssProtocol() { return gluster_accecssProtocol; } public void setGluster_accecssProtocol(EntityModel<Boolean> gluster_accecssProtocol) { this.gluster_accecssProtocol = gluster_accecssProtocol; } public EntityModel<Boolean> getNfs_accecssProtocol() { return nfs_accecssProtocol; } public void setNfs_accecssProtocol(EntityModel<Boolean> nfs_accecssProtocol) { this.nfs_accecssProtocol = nfs_accecssProtocol; } public EntityModel<Boolean> getCifs_accecssProtocol() { return cifs_accecssProtocol; } public void setCifs_accecssProtocol(EntityModel<Boolean> cifs_accecssProtocol) { this.cifs_accecssProtocol = cifs_accecssProtocol; } public EntityModel<String> getAllowAccess() { return allowAccess; } public void setAllowAccess(EntityModel<String> allowAccess) { this.allowAccess = allowAccess; } public EntityModel<Boolean> getOptimizeForVirtStore() { return optimizeForVirtStore; } public void setOptimizeForVirtStore(EntityModel<Boolean> optimizeForVirtStore) { this.optimizeForVirtStore = optimizeForVirtStore; } public boolean isForceAddBricks() { return this.forceAddBricks; } public void setForceAddBricks(boolean forceAddBricks) { this.forceAddBricks = forceAddBricks; } public EntityModel<Boolean> getArbiterVolume() { return arbiterVolume; } public void setArbiterVolume(EntityModel<Boolean> arbiterVolume) { this.arbiterVolume = arbiterVolume; } private void updateArbiterAvailability() { getArbiterVolume().setIsAvailable(getTypeList().getSelectedItem().isReplicatedType() && getCluster().getSelectedItem() != null && Version.v4_1.compareTo(getCluster().getSelectedItem().getCompatibilityVersion()) >= 0); } private void updateDefaults() { getCifs_accecssProtocol().setEntity(!isHCMode()); getNfs_accecssProtocol().setEntity(!isHCMode()); getOptimizeForVirtStore().setEntity(isHCMode()); } public void addBricks(){ if (getWindow() != null || getCluster().getSelectedItem() == null) { return; } final VolumeBrickModel volumeBrickModel = new VolumeBrickModel(); volumeBrickModel.getVolumeType().setEntity(getTypeList().getSelectedItem()); volumeBrickModel.getReplicaCount().setEntity(getReplicaCount().getEntity()); volumeBrickModel.getReplicaCount().setIsChangeable(true); volumeBrickModel.getReplicaCount().setIsAvailable(getReplicaCount().getIsAvailable()); volumeBrickModel.getStripeCount().setEntity(getStripeCount().getEntity()); volumeBrickModel.getStripeCount().setIsChangeable(true); volumeBrickModel.getStripeCount().setIsAvailable(getStripeCount().getIsAvailable()); Cluster cluster = getCluster().getSelectedItem(); if (cluster != null) { volumeBrickModel.getForce().setIsAvailable(true); volumeBrickModel.getForce().setEntity(isForceAddBricks()); volumeBrickModel.setIsBrickProvisioningSupported(); } setWindow(volumeBrickModel); volumeBrickModel.setTitle(ConstantsManager.getInstance().getConstants().addBricksTitle()); volumeBrickModel.setHelpTag(HelpTag.add_bricks); volumeBrickModel.setHashName("add_bricks"); //$NON-NLS-1$ AsyncDataProvider.getInstance().getHostListByCluster(volumeBrickModel.asyncQuery(hostList -> { Iterator<VDS> iterator = hostList.iterator(); while (iterator.hasNext()) { if (iterator.next().getStatus() != VDSStatus.Up) { iterator.remove(); } } volumeBrickModel.setHostList(hostList); }), getCluster().getSelectedItem().getName()); // TODO: fetch the mount points to display if (getBricks().getItems() != null) { volumeBrickModel.getBricks().setItems(getBricks().getItems()); } else { volumeBrickModel.getBricks().setItems(new ArrayList<EntityModel<GlusterBrickEntity>>()); } UICommand command = UICommand.createDefaultOkUiCommand("OnAddBricks", this); //$NON-NLS-1$ volumeBrickModel.getCommands().add(command); volumeBrickModel.getCommands().add(UICommand.createCancelUiCommand("Cancel", this)); //$NON-NLS-1$ } private void onAddBricks() { VolumeBrickModel volumeBrickModel = (VolumeBrickModel) getWindow(); if (!volumeBrickModel.validate()) { return; } GlusterVolumeType volumeType = getTypeList().getSelectedItem(); if (!volumeBrickModel.validateBrickCount(volumeType, true)) { String validationMsg = volumeBrickModel.getValidationFailedMsg(getTypeList().getSelectedItem(), true); if (validationMsg != null) { volumeBrickModel.setMessage(validationMsg); } return; } if (!validateArbiterVolume()) { volumeBrickModel.setMessage(ConstantsManager.getInstance().getConstants().arbiterVolumeShouldBeReplica3()); return; } if ((volumeType == GlusterVolumeType.REPLICATE || volumeType == GlusterVolumeType.DISTRIBUTED_REPLICATE) && !volumeBrickModel.validateReplicateBricks()) { ConfirmationModel confirmModel = new ConfirmationModel(); setConfirmWindow(confirmModel); confirmModel.setTitle(ConstantsManager.getInstance() .getConstants() .addBricksReplicateConfirmationTitle()); confirmModel.setHelpTag(HelpTag.add_bricks_confirmation); confirmModel.setHashName("add_bricks_confirmation"); //$NON-NLS-1$ confirmModel.setMessage(ConstantsManager.getInstance() .getConstants() .addBricksToReplicateVolumeFromSameServerMsg()); UICommand okCommand = new UICommand("OnAddBricksInternal", this); //$NON-NLS-1$ okCommand.setTitle(ConstantsManager.getInstance().getConstants().yes()); okCommand.setIsDefault(true); getConfirmWindow().getCommands().add(okCommand); UICommand cancelCommand = new UICommand("CancelConfirmation", this); //$NON-NLS-1$ cancelCommand.setTitle(ConstantsManager.getInstance().getConstants().no()); cancelCommand.setIsCancel(true); getConfirmWindow().getCommands().add(cancelCommand); } else { onAddBricksInternal(); } } public boolean validateArbiterVolume() { if (getArbiterVolume().getIsAvailable() && getArbiterVolume().getEntity()) { return getReplicaCount().getEntity() == 3; } return true; } private void onAddBricksInternal() { VolumeBrickModel volumeBrickModel = (VolumeBrickModel) getWindow(); cancelConfirmation(); if (!volumeBrickModel.validate()) { return; } GlusterVolumeType selectedVolumeType = getTypeList().getSelectedItem(); if (selectedVolumeType.isReplicatedType()) { getReplicaCount().setEntity(volumeBrickModel.getReplicaCount().getEntity()); } if (selectedVolumeType.isStripedType()) { getStripeCount().setEntity(volumeBrickModel.getStripeCount().getEntity()); } ArrayList<EntityModel<GlusterBrickEntity>> brickList = new ArrayList<>(); brickList.addAll(volumeBrickModel.getBricks().getItems()); volumeBrickModel.getBricks().setItems(null); ListModel<EntityModel<GlusterBrickEntity>> brickListModel = new ListModel<>(); brickListModel.setItems(brickList); brickListModel.setSelectedItems(brickList); setBricks(brickListModel); setForceAddBricks(volumeBrickModel.getForce().getEntity()); setWindow(null); } private void cancelConfirmation() { setConfirmWindow(null); } public boolean validateBrickCount() { return VolumeBrickModel.validateBrickCount(getTypeList().getSelectedItem(), getBricks(), getReplicaCountValue(), getStripeCountValue(), true); } public boolean validate() { if (!validateBrickCount()) { setMessage(VolumeBrickModel.getValidationFailedMsg(getTypeList().getSelectedItem(), true)); return false; } getName().validateEntity(new IValidation[] { new NotEmptyValidation(), new LengthValidation(50), new AsciiNameValidation() }); setMessage(null); boolean validTransportTypes = true; if (!getTcpTransportType().getEntity() && !getRdmaTransportType().getEntity()) { validTransportTypes = false; setMessage(ConstantsManager.getInstance().getConstants().volumeTransportTypesValidationMsg()); } return getName().getIsValid() && validTransportTypes; } private void clusterSelectedItemChanged() { setBricks(new ListModel<EntityModel<GlusterBrickEntity>>()); if (getCluster().getSelectedItem() != null) { final Cluster cluster = getCluster().getSelectedItem(); updateArbiterAvailability(); updateDefaults(); AsyncDataProvider.getInstance().isAnyHostUpInCluster(new AsyncQuery<>(returnValue -> { // In case the result of previous call is returned after selecting some other cluster if (!getCluster().getSelectedItem().getId().equals(cluster.getId())) { return; } if (returnValue) { getAddBricksCommand().setIsExecutionAllowed(true); setMessage(null); } else { getAddBricksCommand().setIsExecutionAllowed(false); setMessage(ConstantsManager.getInstance().getConstants().volumeEmptyClusterValidationMsg()); } }), cluster.getName()); } else { getAddBricksCommand().setIsExecutionAllowed(false); setMessage(null); } } private void dataCenter_SelectedItemChanged() { StoragePool dataCenter = getDataCenter().getSelectedItem(); if (dataCenter != null) { // load clusters of Gluster type AsyncDataProvider.getInstance().getClusterByServiceList(new AsyncQuery<>(clusters -> { Cluster oldCluster = getCluster().getSelectedItem(); StoragePool selectedDataCenter = getDataCenter().getSelectedItem(); Iterator<Cluster> iterator = clusters.iterator(); while(iterator.hasNext()) { if (!iterator.next().supportsGlusterService()) { iterator.remove(); } } // Update selected cluster only if the returned cluster list is indeed the selected datacenter's // clusters if (clusters.isEmpty() || clusters.size() > 0 && clusters.get(0) .getStoragePoolId() .equals(selectedDataCenter.getId())) { getCluster().setItems(clusters); if (oldCluster != null) { Cluster newSelectedItem = Linq.firstOrNull(clusters, new Linq.IdPredicate<>(oldCluster.getId())); if (newSelectedItem != null) { getCluster().setSelectedItem(newSelectedItem); } } if (getCluster().getSelectedItem() == null) { getCluster().setSelectedItem(Linq.firstOrNull(clusters)); } } }), dataCenter.getId(), false, true); } } @Override public void executeCommand(UICommand command) { super.executeCommand(command); if (command == getAddBricksCommand()) { addBricks(); } else if (command.getName().equals("OnAddBricks")) { //$NON-NLS-1$ onAddBricks(); } else if (command.getName().equals("Cancel")) { //$NON-NLS-1$ setWindow(null); } else if (command.getName().equals("OnAddBricksInternal")) { //$NON-NLS-1$ onAddBricksInternal(); } else if (command.getName().equals("CancelConfirmation")) { //$NON-NLS-1$ cancelConfirmation(); } } }