package org.ovirt.engine.ui.uicommonweb.models.storage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import org.ovirt.engine.core.common.action.StorageServerConnectionParametersBase;
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.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StorageDomainType;
import org.ovirt.engine.core.common.businessentities.StorageServerConnections;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.storage.LUNs;
import org.ovirt.engine.core.common.businessentities.storage.LunStatus;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.queries.DiscoverSendTargetsQueryParameters;
import org.ovirt.engine.core.common.queries.GetDeviceListQueryParameters;
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.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.EntityModel;
import org.ovirt.engine.ui.uicommonweb.models.Model;
import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
import org.ovirt.engine.ui.uicommonweb.models.hosts.ValueEventArgs;
import org.ovirt.engine.ui.uicommonweb.validation.IValidation;
import org.ovirt.engine.ui.uicommonweb.validation.IntegerValidation;
import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation;
import org.ovirt.engine.ui.uicompat.ConstantsManager;
import org.ovirt.engine.ui.uicompat.Event;
import org.ovirt.engine.ui.uicompat.EventArgs;
import org.ovirt.engine.ui.uicompat.EventDefinition;
import org.ovirt.engine.ui.uicompat.IEventListener;
import org.ovirt.engine.ui.uicompat.IFrontendActionAsyncCallback;
import org.ovirt.engine.ui.uicompat.ObservableCollection;
import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
import org.ovirt.engine.ui.uicompat.UIConstants;
import org.ovirt.engine.ui.uicompat.UIMessages;
public abstract class SanStorageModelBase extends SearchableListModel implements IStorageModel {
private static final UIConstants constants = ConstantsManager.getInstance().getConstants();
private boolean isGrouppedByTarget;
private VDS previousGetLunsByVGIdHost;
private final List<LunModel> includedLUNs;
private final ArrayList<SanTargetModel> lastDiscoveredTargets;
private boolean isTargetModelList;
private UICommand updateCommand;
@Override
public UICommand getUpdateCommand() {
return updateCommand;
}
private void setUpdateCommand(UICommand value) {
updateCommand = value;
}
private UICommand loginCommand;
public UICommand getLoginCommand() {
return loginCommand;
}
private void setLoginCommand(UICommand value) {
loginCommand = value;
}
private UICommand discoverTargetsCommand;
public UICommand getDiscoverTargetsCommand() {
return discoverTargetsCommand;
}
private void setDiscoverTargetsCommand(UICommand value) {
discoverTargetsCommand = value;
}
private StorageModel container;
@Override
public StorageModel getContainer() {
return container;
}
@Override
public void setContainer(StorageModel value) {
container = value;
}
private StorageDomainType role = StorageDomainType.values()[0];
@Override
public StorageDomainType getRole() {
return role;
}
@Override
public void setRole(StorageDomainType value) {
role = value;
}
@Override
public abstract StorageType getType();
private EntityModel<String> address;
public EntityModel<String> getAddress() {
return address;
}
private void setAddress(EntityModel<String> value) {
address = value;
}
private EntityModel<String> port;
public EntityModel<String> getPort() {
return port;
}
private void setPort(EntityModel<String> value) {
port = value;
}
private EntityModel<String> userName;
public EntityModel<String> getUserName() {
return userName;
}
private void setUserName(EntityModel<String> value) {
userName = value;
}
private EntityModel<String> password;
public EntityModel<String> getPassword() {
return password;
}
private void setPassword(EntityModel<String> value) {
password = value;
}
private EntityModel<Boolean> useUserAuth;
public EntityModel<Boolean> getUseUserAuth() {
return useUserAuth;
}
private void setUseUserAuth(EntityModel<Boolean> value) {
useUserAuth = value;
}
private boolean proposeDiscoverTargets;
public boolean getProposeDiscoverTargets() {
return proposeDiscoverTargets;
}
public void setProposeDiscoverTargets(boolean value) {
if (proposeDiscoverTargets != value) {
proposeDiscoverTargets = value;
onPropertyChanged(new PropertyChangedEventArgs("ProposeDiscoverTargets")); //$NON-NLS-1$
}
}
private boolean isAllLunsSelected;
public boolean getIsAllLunsSelected() {
return isAllLunsSelected;
}
public void setIsAllLunsSelected(boolean value) {
if (isAllLunsSelected != value) {
isAllLunsSelected = value;
isAllLunsSelectedChanged();
onPropertyChanged(new PropertyChangedEventArgs("IsAllLunsSelected")); //$NON-NLS-1$
}
}
private boolean ignoreGrayedOut;
public boolean isIgnoreGrayedOut() {
return ignoreGrayedOut;
}
public void setIgnoreGrayedOut(boolean value) {
if (ignoreGrayedOut != value) {
ignoreGrayedOut = value;
onPropertyChanged(new PropertyChangedEventArgs("IgnoreGrayedOut")); //$NON-NLS-1$
}
}
private boolean multiSelection;
public boolean isMultiSelection() {
return multiSelection;
}
public void setMultiSelection(boolean value) {
if (multiSelection != value) {
multiSelection = value;
onPropertyChanged(new PropertyChangedEventArgs("MultiSelection")); //$NON-NLS-1$
}
}
private String selectedLunWarning;
public String getSelectedLunWarning() {
return selectedLunWarning;
}
public void setSelectedLunWarning(String value) {
if (!Objects.equals(selectedLunWarning, value)) {
selectedLunWarning = value;
onPropertyChanged(new PropertyChangedEventArgs("SelectedLunWarning")); //$NON-NLS-1$
}
}
private ArrayList<SanTargetModel> targetsToConnect;
protected SanStorageModelBase() {
setHelpTag(HelpTag.SanStorageModelBase);
setHashName("SanStorageModelBase"); //$NON-NLS-1$
setUpdateCommand(new UICommand("Update", this)); //$NON-NLS-1$
UICommand tempVar = new UICommand("Login", this); //$NON-NLS-1$
tempVar.setIsExecutionAllowed(false);
setLoginCommand(tempVar);
setDiscoverTargetsCommand(new UICommand("DiscoverTargets", this)); //$NON-NLS-1$
setAddress(new EntityModel<String>());
EntityModel<String> tempVar2 = new EntityModel<>();
tempVar2.setEntity("3260"); //$NON-NLS-1$
setPort(tempVar2);
setUserName(new EntityModel<String>());
setPassword(new EntityModel<String>());
EntityModel<Boolean> tempVar3 = new EntityModel<>();
tempVar3.setEntity(false);
setUseUserAuth(tempVar3);
getUseUserAuth().getEntityChangedEvent().addListener(this);
updateUserAuthFields();
includedLUNs = new ArrayList<>();
lastDiscoveredTargets = new ArrayList<>();
initializeItems(null, null);
}
@Override
public void eventRaised(Event ev, Object sender, EventArgs args) {
super.eventRaised(ev, sender, args);
if (ev.matchesDefinition(SanTargetModel.loggedInEventDefinition)) {
sanTargetModel_LoggedIn(sender, args);
}
else if (ev.matchesDefinition(entityChangedEventDefinition)) {
useUserAuth_EntityChanged(sender, args);
}
}
public void updateLunWarningForDiscardAfterDelete() {
if (getContainer().getDiscardAfterDelete().getEntity()) {
for (LunModel lunModel : getSelectedLuns()) {
if (!lunModel.getEntity().supportsDiscard()) {
setSelectedLunWarning(constants.discardIsNotSupportedByUnderlyingStorage());
return;
}
}
}
setSelectedLunWarning(constants.emptyString());
}
private void postLogin( VdcReturnValueBase returnValue, SanStorageModelBase sanStorageModel) {
SanTargetModel sanTargetModel = sanStorageModel.targetsToConnect.remove(0);
boolean success = returnValue != null && returnValue.getSucceeded();
if (success) {
sanTargetModel.setIsLoggedIn(true);
sanTargetModel.getLoginCommand().setIsExecutionAllowed(false);
}
if (sanStorageModel.targetsToConnect.isEmpty()) {
sanStorageModel.updateInternal();
}
}
private void connectTargets() {
VDS host = getContainer().getHost().getSelectedItem();
if (host == null) {
return;
}
ArrayList<VdcActionType> actionTypes = new ArrayList<>();
ArrayList<VdcActionParametersBase> parameters = new ArrayList<>();
ArrayList<IFrontendActionAsyncCallback> callbacks = new ArrayList<>();
final SanStorageModelBase sanStorageModel = this;
IFrontendActionAsyncCallback loginCallback =
result -> sanStorageModel.postLogin(result.getReturnValue(), sanStorageModel);
for (int i = 0; i < targetsToConnect.size(); i++) {
SanTargetModel model = targetsToConnect.get(i);
StorageServerConnections connection = new StorageServerConnections();
connection.setStorageType(StorageType.ISCSI);
connection.setUserName(getUseUserAuth().getEntity() ? getUserName().getEntity() : ""); //$NON-NLS-1$
connection.setPassword(getUseUserAuth().getEntity() ? getPassword().getEntity() : ""); //$NON-NLS-1$
connection.setIqn(model.getName());
connection.setConnection(model.getAddress());
connection.setPort(String.valueOf(model.getPort()));
actionTypes.add(VdcActionType.ConnectStorageToVds);
parameters.add(new StorageServerConnectionParametersBase(connection, host.getId(), false));
callbacks.add(loginCallback);
}
Object target = getWidgetModel() != null ? getWidgetModel() : getContainer();
Frontend.getInstance().runMultipleActions(actionTypes, parameters, callbacks, null, target);
}
private void sanTargetModel_LoggedIn(Object sender, EventArgs args) {
SanTargetModel model = (SanTargetModel) sender;
targetsToConnect = new ArrayList<>();
targetsToConnect.add(model);
connectTargets();
}
protected void login() {
loginAll();
}
private void loginAll() {
// Cast to list of SanTargetModel because we get call
// to this method only from target/LUNs mode.
List<SanTargetModel> items = (List<SanTargetModel>) getItems();
targetsToConnect = new ArrayList<>();
for (SanTargetModel item : items) {
if (!item.getIsLoggedIn()) {
targetsToConnect.add(item);
}
}
connectTargets();
}
private void discoverTargets() {
if (!validateDiscoverTargetFields()) {
return;
}
VDS host = getContainer().getHost().getSelectedItem();
StorageServerConnections tempVar = new StorageServerConnections();
tempVar.setConnection(getAddress().getEntity().trim());
tempVar.setPort(getPort().getEntity().trim());
tempVar.setStorageType(StorageType.ISCSI);
tempVar.setUserName(getUseUserAuth().getEntity() ? getUserName().getEntity() : ""); //$NON-NLS-1$
tempVar.setPassword(getUseUserAuth().getEntity() ? getPassword().getEntity() : ""); //$NON-NLS-1$
DiscoverSendTargetsQueryParameters parameters =
new DiscoverSendTargetsQueryParameters(host.getId(), tempVar);
setMessage(null);
final SanStorageModelBase model = this;
AsyncQuery<VdcQueryReturnValue> asyncQuery = new AsyncQuery<>(returnValue -> {
Object result = returnValue.getReturnValue();
model.postDiscoverTargetsInternal(result != null ? (ArrayList<StorageServerConnections>) result
: new ArrayList<StorageServerConnections>());
}, true);
Frontend.getInstance().runQuery(VdcQueryType.DiscoverSendTargets, parameters, asyncQuery);
}
protected void postDiscoverTargetsInternal(ArrayList<StorageServerConnections> items) {
ArrayList<SanTargetModel> newItems = new ArrayList<>();
for (StorageServerConnections a : items) {
SanTargetModel model = new SanTargetModel();
model.setAddress(a.getConnection());
model.setPort(a.getPort());
model.setName(a.getIqn());
model.setLuns(new ObservableCollection<LunModel>());
model.getLoggedInEvent().addListener(this);
newItems.add(model);
}
if (items.isEmpty()) {
setMessage(ConstantsManager.getInstance().getConstants().noNewDevicesWereFoundMsg());
}
postDiscoverTargets(newItems);
}
private boolean validateDiscoverTargetFields() {
getContainer().getHost().validateSelectedItem(new NotEmptyValidation[] { new NotEmptyValidation() });
getAddress().validateEntity(new IValidation[] { new NotEmptyValidation() });
IntegerValidation tempVar = new IntegerValidation();
tempVar.setMinimum(0);
tempVar.setMaximum(65535);
getPort().validateEntity(new IValidation[] { new NotEmptyValidation(), tempVar });
if (getUseUserAuth().getEntity()) {
getUserName().validateEntity(new IValidation[] { new NotEmptyValidation() });
getPassword().validateEntity(new IValidation[] { new NotEmptyValidation() });
}
return getContainer().getHost().getIsValid() && getAddress().getIsValid() && getPort().getIsValid()
&& getUserName().getIsValid() && getPassword().getIsValid();
}
@Override
public boolean validate() {
boolean isValid = getAddedLuns().size() > 0 || includedLUNs.size() > 0;
if (!isValid) {
getInvalidityReasons().add(ConstantsManager.getInstance().getConstants().noLUNsSelectedInvalidReason());
}
setIsValid(isValid);
return getIsValid();
}
private void useUserAuth_EntityChanged(Object sender, EventArgs args) {
updateUserAuthFields();
}
private void updateUserAuthFields() {
getUserName().setIsValid(true);
getUserName().setIsChangeable(getUseUserAuth().getEntity());
getPassword().setIsValid(true);
getPassword().setIsChangeable(getUseUserAuth().getEntity());
}
@Override
public void executeCommand(UICommand command) {
super.executeCommand(command);
if (command == getUpdateCommand()) {
update();
}
else if (command == getLoginCommand()) {
login();
}
else if (command == getDiscoverTargetsCommand()) {
discoverTargets();
}
}
protected void update() {
lastDiscoveredTargets.clear();
updateInternal();
setIsValid(true);
}
protected void updateInternal() {
if (!(getContainer().isNewStorage() || getContainer().isStorageActive())) {
return;
}
VDS host = getContainer().getHost().getSelectedItem();
if (host == null) {
proposeDiscover();
return;
}
final Collection<EntityModel<?>> prevSelected = Linq.findSelectedItems((Collection<EntityModel<?>>) getSelectedItem());
clearItems();
initializeItems(null, null);
final SanStorageModelBase model = this;
AsyncQuery<VdcQueryReturnValue> asyncQuery = new AsyncQuery<>(response -> {
if (response.getSucceeded()) {
model.applyData((ArrayList<LUNs>) response.getReturnValue(), false, prevSelected);
model.setGetLUNsFailure(""); //$NON-NLS-1$
}
else {
model.setGetLUNsFailure(
ConstantsManager.getInstance().getConstants().couldNotRetrieveLUNsLunsFailure());
}
}, true);
Frontend.getInstance().runQuery(VdcQueryType.GetDeviceList,
new GetDeviceListQueryParameters(host.getId(), getType(), false, null),
asyncQuery);
}
protected void updateLoginAvailability() {
List<SanTargetModel> items = (List<SanTargetModel>) getItems();
// Allow login all command when there at least one target that may be logged in.
boolean allow = false;
for (SanTargetModel item : items) {
if (!item.getIsLoggedIn()) {
allow = true;
break;
}
}
getLoginCommand().setIsExecutionAllowed(allow);
}
public String getLoginButtonLabel() {
return ""; //$NON-NLS-1$
}
/**
* Gets or sets the value determining whether the items containing target/LUNs or LUN/targets.
*/
public boolean getIsGrouppedByTarget() {
return isGrouppedByTarget;
}
public void setIsGrouppedByTarget(boolean value) {
if (isGrouppedByTarget != value) {
isGrouppedByTarget = value;
isGrouppedByTargetChanged();
onPropertyChanged(new PropertyChangedEventArgs("IsGrouppedByTarget")); //$NON-NLS-1$
}
}
private String getLUNsFailure;
public String getGetLUNsFailure() {
return getLUNsFailure;
}
public void setGetLUNsFailure(String value) {
if (!Objects.equals(getLUNsFailure, value)) {
getLUNsFailure = value;
onPropertyChanged(new PropertyChangedEventArgs("GetLUNsFailure")); //$NON-NLS-1$
}
}
private StorageDomain storageDomain;
public StorageDomain getStorageDomain() {
return storageDomain;
}
public void setStorageDomain(StorageDomain storageDomain) {
this.storageDomain = storageDomain;
}
private boolean force;
public boolean isForce() {
return force;
}
public void setForce(boolean force) {
this.force = force;
}
protected void postDiscoverTargets(ArrayList<SanTargetModel> newItems) {
initializeItems(null, newItems);
// Remember all discovered targets.
lastDiscoveredTargets.clear();
lastDiscoveredTargets.addAll(newItems);
}
private void clearItems() {
if (getItems() == null) {
return;
}
if (getIsGrouppedByTarget()) {
List<SanTargetModel> items = (List<SanTargetModel>) getItems();
items.removeIf(target -> {
boolean found = false;
// Ensure remove targets that are not in last discovered targets list.
if (Linq.firstOrNull(lastDiscoveredTargets, new Linq.TargetPredicate(target)) != null) {
found = true;
}
else {
// Ensure remove targets that are not contain already included LUNs.
for (LunModel lun : target.getLuns()) {
LunModel foundItem = Linq.firstOrNull(includedLUNs, new Linq.LunPredicate(lun));
if (foundItem == null) {
found = true;
break;
}
}
}
return !found;
});
}
else {
List<LunModel> items = (List<LunModel>) getItems();
items.removeIf(lun -> Linq.firstOrNull(includedLUNs, new Linq.LunPredicate(lun)) == null);
}
}
/**
* Creates model items from the provided list of business entities.
*/
public void applyData(List<LUNs> source, boolean isIncluded, Collection<EntityModel<?>> selectedItems) {
ArrayList<LunModel> newItems = new ArrayList<>();
for (LUNs a : source) {
if (a.getLunType() == getType() || a.getLunType() == StorageType.UNKNOWN) {
ArrayList<SanTargetModel> targets = createTargetModelList(a);
LunModel lunModel = new LunModel();
lunModel.setLunId(a.getLUNId());
lunModel.setVendorId(a.getVendorId());
lunModel.setProductId(a.getProductId());
lunModel.setSerial(a.getSerial());
lunModel.setMultipathing(a.getPathCount());
lunModel.setTargets(targets);
lunModel.setSize(a.getDeviceSize());
lunModel.setAdditionalAvailableSize(getAdditionalAvailableSize(a));
lunModel.setAdditionalAvailableSizeSelected(false);
lunModel.setIsAccessible(a.getAccessible());
lunModel.setStatus(a.getStatus());
lunModel.setIsIncluded(isIncluded);
lunModel.setIsSelected(containsLun(lunModel, selectedItems, isIncluded));
lunModel.setEntity(a);
// Add LunModel
newItems.add(lunModel);
// Update isGrayedOut and grayedOutReason properties
updateGrayedOut(lunModel);
// Remember included LUNs to prevent their removal while updating items.
if (isIncluded) {
includedLUNs.add(lunModel);
}
}
}
initializeItems(newItems, null);
proposeDiscover();
}
private int getAdditionalAvailableSize(LUNs lun) {
int pvSize = lun.getPvSize();
if (pvSize == 0) {
return 0;
}
// The PV size is always smaller by 1 GB from the device due to LVM metadata
int additionalAvailableSize = lun.getDeviceSize() - pvSize - 1;
if (additionalAvailableSize < 0) {
additionalAvailableSize = 0;
}
return additionalAvailableSize;
}
private boolean containsLun(LunModel lunModel, Collection<EntityModel<?>> models, boolean isIncluded) {
if (models == null) {
return isIncluded;
}
for (EntityModel<?> model : models) {
if (model instanceof LunModel) {
if (((LunModel) model).getLunId().equals(lunModel.getLunId())) {
return true;
}
}
}
return false;
}
private ArrayList<SanTargetModel> createTargetModelList(LUNs a) {
ArrayList<SanTargetModel> targetModelList = new ArrayList<>();
if (a.getLunConnections() != null) {
for (StorageServerConnections b : a.getLunConnections()) {
SanTargetModel model = new SanTargetModel();
model.setAddress(b.getConnection());
model.setPort(b.getPort());
model.setName(b.getIqn());
model.setIsSelected(true);
model.setIsLoggedIn(true);
model.setLuns(new ObservableCollection<LunModel>());
model.getLoginCommand().setIsExecutionAllowed(false);
targetModelList.add(model);
}
}
return targetModelList;
}
private void updateGrayedOut(LunModel lunModel) {
UIConstants constants = ConstantsManager.getInstance().getConstants();
UIMessages messages = ConstantsManager.getInstance().getMessages();
LUNs lun = lunModel.getEntity();
boolean nonEmpty = lun.getStorageDomainId() != null || lun.getDiskId() != null ||
lun.getStatus() == LunStatus.Unusable;
// Graying out LUNs
lunModel.setIsGrayedOut(isIgnoreGrayedOut() ? lun.getDiskId() != null : nonEmpty);
// Adding 'GrayedOutReasons'
if (lun.getDiskId() != null) {
lunModel.getGrayedOutReasons().add(
messages.lunUsedByDiskWarning(lun.getDiskAlias()));
}
else if (lun.getStorageDomainId() != null) {
lunModel.getGrayedOutReasons().add(
messages.lunAlreadyPartOfStorageDomainWarning(lun.getStorageDomainName()));
}
else if (lun.getStatus() == LunStatus.Unusable) {
lunModel.getGrayedOutReasons().add(
constants.lunUnusable());
}
}
private void isGrouppedByTargetChanged() {
initializeItems(null, null);
}
/**
* Organizes items according to the current groupping flag. When new items provided takes them in account and add to
* the Items collection.
*/
protected void initializeItems(List<LunModel> newLuns, List<SanTargetModel> newTargets) {
if (getIsGrouppedByTarget()) {
if (getItems() == null) {
setItems(new ObservableCollection<SanTargetModel>());
isTargetModelList = true;
}
else {
// Convert to list of another type as neccessary.
if (!isTargetModelList) {
setItems(toTargetModelList((List<LunModel>) getItems()));
}
}
ArrayList<SanTargetModel> items = new ArrayList<>();
items.addAll((List<SanTargetModel>) getItems());
// Add new targets.
if (newTargets != null) {
for (SanTargetModel newItem : newTargets) {
if (Linq.firstOrNull(items, new Linq.TargetPredicate(newItem)) == null) {
items.add(newItem);
}
}
}
// Merge luns into targets.
if (newLuns != null) {
mergeLunsToTargets(newLuns, items);
}
setItems(items);
updateLoginAvailability();
}
else {
if (getItems() == null) {
setItems(new ObservableCollection<LunModel>());
isTargetModelList = false;
}
else {
// Convert to list of another type as neccessary.
if (isTargetModelList) {
setItems(toLunModelList((List<SanTargetModel>) getItems()));
}
}
ArrayList<LunModel> items = new ArrayList<>();
items.addAll((List<LunModel>) getItems());
// Add new LUNs.
if (newLuns != null) {
for (LunModel newItem : newLuns) {
LunModel existingItem = Linq.firstOrNull(items, new Linq.LunPredicate(newItem));
if (existingItem == null) {
items.add(newItem);
}
else {
existingItem.setIsIncluded(existingItem.getIsIncluded() || newItem.getIsIncluded());
}
}
}
setItems(items);
}
if (!isMultiSelection() && newLuns != null) {
addLunModelSelectionEventListeners(newLuns);
}
}
private void addLunModelSelectionEventListeners(List<LunModel> luns) {
for (LunModel lun : luns) {
// Adding PropertyEventListener to LunModel if needed
if (!lun.getPropertyChangedEvent().getListeners().contains(lunModelEventListener)) {
lun.getPropertyChangedEvent().addListener(lunModelEventListener);
}
}
}
private void mergeLunsToTargets(List<LunModel> newLuns, List<SanTargetModel> targets) {
for (LunModel lun : newLuns) {
for (SanTargetModel target : lun.getTargets()) {
SanTargetModel item = Linq.firstOrNull(targets, new Linq.TargetPredicate(target));
if (item == null) {
item = target;
targets.add(item);
}
LunModel currLun = Linq.firstOrNull(item.getLuns(), new Linq.LunPredicate(lun));
if (currLun == null) {
item.getLuns().add(lun);
} else {
currLun.setLunId(lun.getLunId());
currLun.setVendorId(lun.getVendorId());
currLun.setProductId(lun.getProductId());
currLun.setSerial(lun.getSerial());
currLun.setMultipathing(lun.getMultipathing());
currLun.setTargets(createTargetModelList(lun.getEntity()));
currLun.setSize(lun.getSize());
currLun.setAdditionalAvailableSize(lun.getAdditionalAvailableSize());
currLun.setAdditionalAvailableSizeSelected(lun.isAdditionalAvailableSizeSelected());
currLun.setIsAccessible(lun.getIsAccessible());
currLun.setStatus(lun.getStatus());
currLun.setIsIncluded(lun.getIsIncluded());
currLun.setIsSelected(lun.getIsSelected());
currLun.setEntity(lun.getEntity());
}
}
}
}
private EventDefinition
lunSelectionChangedEventDefinition = new EventDefinition("lunSelectionChanged", SanStorageModelBase.class); //$NON-NLS-1$
private Event lunSelectionChangedEvent = new Event(lunSelectionChangedEventDefinition);
public Event getLunSelectionChangedEvent() {
return lunSelectionChangedEvent;
}
final IEventListener<PropertyChangedEventArgs> lunModelEventListener = new IEventListener<PropertyChangedEventArgs>() {
@Override
public void eventRaised(Event<? extends PropertyChangedEventArgs> ev, Object sender, PropertyChangedEventArgs args) {
String propName = args.propertyName;
if (propName.equals("IsSelected")) { //$NON-NLS-1$
LunModel selectedLunModel = (LunModel) sender;
if (!selectedLunModel.getIsSelected() || !getItems().iterator().hasNext()) {
return;
}
// Clear LUNs selection
for (Model model : (List<Model>) getItems()) {
if (model instanceof LunModel) {
LunModel lunModel = (LunModel) model;
if (!lunModel.equals(selectedLunModel)) {
lunModel.setIsSelected(false);
}
}
else {
SanTargetModel sanTargetModel = (SanTargetModel) model;
boolean isIncludeSelected = false;
for (LunModel lunModel : sanTargetModel.getLuns()) {
if (!lunModel.equals(selectedLunModel)) {
lunModel.setIsSelected(false);
}
else {
isIncludeSelected = true;
}
}
if (!isIncludeSelected && sanTargetModel.getLunsList().getSelectedItem() != null) {
sanTargetModel.getLunsList().setSelectedItem(null);
}
}
}
lunSelectionChangedEvent.raise(this, new ValueEventArgs<>(selectedLunModel));
}
}
};
private List<SanTargetModel> toTargetModelList(List<LunModel> source) {
ObservableCollection<SanTargetModel> list = new ObservableCollection<>();
for (LunModel lun : source) {
for (SanTargetModel target : lun.getTargets()) {
SanTargetModel item = Linq.firstOrNull(list, new Linq.TargetPredicate(target));
if (item == null) {
item = target;
list.add(item);
}
if (Linq.firstOrNull(item.getLuns(), new Linq.LunPredicate(lun)) == null) {
item.getLuns().add(lun);
}
}
}
// Merge with last discovered targets list.
for (SanTargetModel target : lastDiscoveredTargets) {
if (Linq.firstOrNull(list, new Linq.TargetPredicate(target)) == null) {
list.add(target);
}
}
isTargetModelList = true;
return list;
}
private List<LunModel> toLunModelList(List<SanTargetModel> source) {
ObservableCollection<LunModel> list = new ObservableCollection<>();
for (SanTargetModel target : source) {
for (LunModel lun : target.getLuns()) {
LunModel item = Linq.firstOrNull(list, new Linq.LunPredicate(lun));
if (item == null) {
item = lun;
list.add(item);
}
if (Linq.firstOrNull(item.getTargets(), new Linq.TargetPredicate(target)) == null) {
item.getTargets().add(target);
}
}
}
isTargetModelList = false;
return list;
}
protected void proposeDiscover() {
setProposeDiscoverTargets(getItems() == null || getItems().isEmpty());
}
protected void isAllLunsSelectedChanged() {
if (!getIsGrouppedByTarget()) {
List<LunModel> items = (List<LunModel>) getItems();
for (LunModel lun : items) {
if (!lun.getIsIncluded() && lun.getIsAccessible()) {
lun.setIsSelected(getIsAllLunsSelected());
}
}
}
}
/**
* @return the new selected and the preselected luns.
*/
public ArrayList<LunModel> getSelectedLuns() {
return getLuns(true, true);
}
/**
* @return the new selected luns.
*/
public ArrayList<LunModel> getAddedLuns() {
return getLuns(true, false);
}
private ArrayList<LunModel> getLuns(boolean selectedLuns, boolean includedLuns) {
ArrayList<LunModel> luns = new ArrayList<>();
if (getIsGrouppedByTarget()) {
List<SanTargetModel> items = (List<SanTargetModel>) getItems();
for (SanTargetModel item : items) {
luns.addAll(getAddedLuns(item.getLuns(), selectedLuns, includedLuns));
}
} else {
List<LunModel> items = (List<LunModel>) getItems();
luns.addAll(getAddedLuns(items, selectedLuns, includedLuns));
}
return luns;
}
private Collection<LunModel> getAddedLuns(List<LunModel> lunModels, boolean selectedLuns, boolean includedLuns) {
Collection<LunModel> luns = new LinkedList<>();
for (LunModel lun : lunModels) {
if (((selectedLuns && lun.getIsSelected() && !lun.getIsIncluded()) ||
(includedLuns && lun.getIsIncluded() && !lun.getIsSelected())) &&
Linq.firstOrNull(luns, new Linq.LunPredicate(lun)) == null) {
luns.add(lun);
}
}
return luns;
}
public ArrayList<LunModel> getLunsToRefresh() {
ArrayList<LunModel> luns = new ArrayList<>();
if (!getIsGrouppedByTarget()) {
List<LunModel> items = (List<LunModel>) getItems();
for (LunModel lun : items) {
if (lun.getIsIncluded()) {
if (lun.isAdditionalAvailableSizeSelected()
&& Linq.firstOrNull(luns, new Linq.LunPredicate(lun)) == null) {
luns.add(lun);
}
}
}
}
return luns;
}
public ArrayList<String> getUsedLunsMessages(List<LUNs> luns) {
ArrayList<String> usedLunsMessages = new ArrayList<>();
UIMessages messages = ConstantsManager.getInstance().getMessages();
for (LUNs lun : luns) {
if (lun.getStatus() == LunStatus.Used) {
String reason = null;
if (lun.getVolumeGroupId() != null && !lun.getVolumeGroupId().isEmpty()) {
reason = messages.lunUsedByVG(lun.getVolumeGroupId());
}
usedLunsMessages.add(reason == null ? lun.getLUNId() :
messages.usedLunIdReason(lun.getLUNId(), reason));
}
}
return usedLunsMessages;
}
public ArrayList<String> getPartOfSdLunsMessages() {
ArrayList<String> partOfSdLunsMessages = new ArrayList<>();
UIMessages messages = ConstantsManager.getInstance().getMessages();
for (LunModel lunModel : getAddedLuns()) {
LUNs lun = lunModel.getEntity();
if (lun.getStorageDomainId() != null) {
String reason = messages.lunAlreadyPartOfStorageDomainWarning(lun.getStorageDomainName());
partOfSdLunsMessages.add(lunModel.getLunId() + " (" + reason + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return partOfSdLunsMessages;
}
public boolean isEditable(StorageDomain storage) {
return getContainer().isStorageActive() || getContainer().isNewStorage();
}
public void prepareForEdit(final StorageDomain storage) {
if (isEditable(storage)) {
final SanStorageModelBase thisModel = this;
getContainer().getHost().getSelectedItemChangedEvent().addListener((ev, sender, args) -> postPrepareSanStorageForEdit(thisModel, true, storage));
}
else {
postPrepareSanStorageForEdit(this, false, storage);
}
}
private void postPrepareSanStorageForEdit(final SanStorageModelBase model, boolean isStorageActive, StorageDomain storage) {
model.setStorageDomain(storage);
VDS host = getContainer().getHost().getSelectedItem();
if (Objects.equals(previousGetLunsByVGIdHost, host) && isStorageActive) {
return;
}
previousGetLunsByVGIdHost = host;
Guid hostId = host != null && isStorageActive ? host.getId() : null;
AsyncDataProvider.getInstance().getLunsByVgId(new AsyncQuery<>(lunList -> model.applyData(lunList, true, Linq.findSelectedItems((Collection<EntityModel<?>>) getSelectedItem()))), storage.getStorage(), hostId);
}
}