package org.ovirt.engine.core.bll.storage; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import org.ovirt.engine.core.bll.Backend; import org.ovirt.engine.core.bll.context.CompensationContext; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.SetNonOperationalVdsParameters; import org.ovirt.engine.core.common.action.StorageDomainParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.businessentities.LUN_storage_server_connection_map; import org.ovirt.engine.core.common.businessentities.LUN_storage_server_connection_map_id; import org.ovirt.engine.core.common.businessentities.LUNs; import org.ovirt.engine.core.common.businessentities.NonOperationalReason; import org.ovirt.engine.core.common.businessentities.StorageDomainStatus; import org.ovirt.engine.core.common.businessentities.StorageDomainType; import org.ovirt.engine.core.common.businessentities.StoragePoolIsoMapId; import org.ovirt.engine.core.common.businessentities.StorageType; import org.ovirt.engine.core.common.businessentities.storage_domains; import org.ovirt.engine.core.common.businessentities.storage_pool; import org.ovirt.engine.core.common.businessentities.storage_pool_iso_map; import org.ovirt.engine.core.common.businessentities.storage_server_connections; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.NGuid; import org.ovirt.engine.core.compat.TransactionScopeOption; import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.linq.LinqUtils; import org.ovirt.engine.core.utils.linq.Predicate; import org.ovirt.engine.core.utils.transaction.TransactionMethod; import org.ovirt.engine.core.utils.transaction.TransactionSupport; import org.ovirt.engine.core.vdsbroker.ResourceManager; public abstract class StorageDomainCommandBase<T extends StorageDomainParametersBase> extends StorageHandlingCommandBase<T> { private storage_pool _storagePool; public StorageDomainCommandBase(T parameters) { super(parameters); } /** * Constructor for command creation when compensation is applied on startup * * @param commandId */ protected StorageDomainCommandBase(Guid commandId) { super(commandId); } @Override public NGuid getStorageDomainId() { return getParameters() != null ? !getParameters().getStorageDomainId().equals(Guid.Empty) ? getParameters() .getStorageDomainId() : super.getStorageDomainId() : super.getStorageDomainId(); } public boolean IsDomainActive(Guid domainId, NGuid storagePoolId) { return IsDomainActive(domainId, storagePoolId, getReturnValue().getCanDoActionMessages()); } public static boolean IsDomainActive(Guid domainId, NGuid storagePoolId, java.util.ArrayList<String> messages) { storage_domains storage = DbFacade.getInstance().getStorageDomainDAO().getForStoragePool(domainId, storagePoolId); if (storage == null) { messages.add(VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_EXIST.toString()); return false; } if (storage.getstatus() == null || storage.getstatus() != StorageDomainStatus.Active) { messages.add(VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_DOMAIN_STATUS_ILLEGAL.toString()); return false; } return true; } protected boolean canDetachDomain(boolean isDestroyStoragePool, boolean isRemoveLast, boolean isInternal) { return CheckStoragePool() && CheckStorageDomain() && checkStorageDomainStatus(StorageDomainStatus.InActive, StorageDomainStatus.Maintenance) && (isMaster() || isDestroyStoragePool || CheckMasterDomainIsUp()) && isNotLocalData(isInternal) && isDetachAllowed(isRemoveLast); } protected boolean isDetachAllowed(final boolean isRemoveLast) { boolean returnValue = true; if (getStoragePoolIsoMap() == null) { returnValue = false; addCanDoActionMessage(VdcBllMessages.STORAGE_DOMAIN_NOT_ATTACHED_TO_STORAGE_POOL); } else if (hasImages()) { returnValue = false; addCanDoActionMessage(VdcBllMessages.ERROR_CANNOT_DETACH_STORAGE_DOMAIN_WITH_IMAGES); } else if (!isRemoveLast && isMaster()) { storage_domains storage_domains = LinqUtils.firstOrNull(DbFacade.getInstance() .getStorageDomainDAO() .getAllForStoragePool(getStorageDomain().getstorage_pool_id().getValue()), new Predicate<storage_domains>() { @Override public boolean eval(storage_domains a) { return a.getid().equals(getStorageDomain().getid()) && a.getstatus() == StorageDomainStatus.Active; } }); if (storage_domains == null) { returnValue = false; addCanDoActionMessage(VdcBllMessages.ERROR_CANNOT_DETACH_LAST_STORAGE_DOMAIN); } } return returnValue; } protected boolean isNotLocalData(final boolean isInternal) { boolean returnValue = true; if (this.getStoragePool().getstorage_pool_type() == StorageType.LOCALFS && getStorageDomain().getstorage_domain_type() == StorageDomainType.Data && !isInternal) { returnValue = false; addCanDoActionMessage(VdcBllMessages.VDS_GROUP_CANNOT_DETACH_DATA_DOMAIN_FROM_LOCAL_STORAGE); } return returnValue; } private boolean hasImages() { return DbFacade.getInstance() .getDiskImageDAO() .getAllSnapshotsForStorageDomain(getStorageDomain().getid()) .size() != 0 || DbFacade.getInstance() .getStorageDomainDAO() .getAllImageGroupStorageDomainMapsForStorageDomain(getStorageDomain().getid()) .size() != 0; } private storage_pool_iso_map getStoragePoolIsoMap() { return DbFacade.getInstance() .getStoragePoolIsoMapDAO() .get(new StoragePoolIsoMapId(getStorageDomain().getid(), getStoragePoolId())); } private boolean isMaster() { return getStorageDomain().getstorage_domain_type() == StorageDomainType.Master; } @Override public storage_pool getStoragePool() { if (_storagePool == null) { if (getStoragePoolId() != null && !getStoragePoolId().equals(Guid.Empty)) { _storagePool = getStoragePoolDAO().get(getStoragePoolId().getValue()); } } return _storagePool; } @Override protected boolean canDoAction() { addCanDoActionMessage(VdcBllMessages.VAR__TYPE__STORAGE__DOMAIN); return super.canDoAction(); } protected boolean CheckStorageDomainNameLengthValid() { boolean result = true; if (getStorageDomain().getstorage_name().length() > Config .<Integer> GetValue(ConfigValues.StorageDomainNameSizeLimit)) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_NAME_LENGTH_IS_TOO_LONG); result = false; } return result; } protected boolean CheckStorageDomain() { return isStorageDomainNotNull(getStorageDomain()); } protected boolean checkStorageDomainInDb() { boolean returnValue; returnValue = DbFacade.getInstance().getStorageDomainStaticDAO().get(getStorageDomain().getid()) != null; return returnValue; } protected boolean checkStorageDomainStatus(final StorageDomainStatus... statuses) { boolean valid = false; if(getStorageDomainStatus() != null) { valid = Arrays.asList(statuses).contains(getStorageDomainStatus()); } if(!valid) { addStorageDomainStatusIllegalMessage(); } return valid; } protected boolean CheckStorageDomainStatusNotEqual(StorageDomainStatus status) { boolean returnValue = false; if (getStorageDomain() != null && getStorageDomain().getstatus() != null) { returnValue = (getStorageDomain().getstatus() != status); if (!returnValue) { getReturnValue().getCanDoActionMessages().add( VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_DOMAIN_STATUS_ILLEGAL2.toString()); } } return returnValue; } protected boolean CheckStorageDomainNotInPool() { return isStorageDomainNotInPool(getStorageDomain()); } protected boolean CheckStorageConnection(String storageDomainConnection) { boolean returnValue = true; if (DbFacade.getInstance().getStorageServerConnectionDAO().get(storageDomainConnection) == null) { returnValue = false; addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_CONNECTION_NOT_EXIST); } return returnValue; } protected boolean CheckMasterDomainIsUp() { boolean returnValue = true; List<storage_domains> storageDomains = DbFacade.getInstance().getStorageDomainDAO().getAllForStoragePool( getStoragePool().getId()); storageDomains = LinqUtils.filter(storageDomains, new Predicate<storage_domains>() { @Override public boolean eval(storage_domains a) { return a.getstorage_domain_type() == StorageDomainType.Master && a.getstatus() == StorageDomainStatus.Active; } }); if (storageDomains.isEmpty()) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_MASTER_STORAGE_DOMAIN_NOT_ACTIVE); returnValue = false; } return returnValue; } protected void SetStorageDomainStatus(StorageDomainStatus status) { if (getStorageDomain() != null && getStorageDomain().getstorage_pool_id() != null) { storage_pool_iso_map map = getStorageDomain().getStoragePoolIsoMapData(); getStorageDomain().setstatus(status); DbFacade.getInstance() .getStoragePoolIsoMapDAO() .updateStatus(map.getId(), map.getstatus()); } } protected void RefreshAllVdssInPool(boolean connect) { java.util.ArrayList<Guid> vdsIdsToSetNonOperational = new java.util.ArrayList<Guid>(); runSynchronizeOperation(new RefreshPoolSingleAsyncOperationFactory(), vdsIdsToSetNonOperational); for (Guid vdsId : vdsIdsToSetNonOperational) { SetNonOperationalVdsParameters tempVar = new SetNonOperationalVdsParameters(vdsId, NonOperationalReason.STORAGE_DOMAIN_UNREACHABLE); tempVar.setSaveToDb(true); tempVar.setStorageDomainId(getStorageDomain().getid()); tempVar.setTransactionScopeOption(TransactionScopeOption.RequiresNew); Backend.getInstance().runInternalAction(VdcActionType.SetNonOperationalVds, tempVar); } } protected void ProceedLUNInDb(final LUNs lun) { DbFacade.getInstance().getLunDAO().save(lun); for (storage_server_connections connection : lun.getLunConnections()) { List<storage_server_connections> connections = DbFacade.getInstance() .getStorageServerConnectionDAO().getAllForConnection(connection); if (connections.isEmpty()) { connection.setid(Guid.NewGuid().toString()); connection.setstorage_type(getStorageDomain().getstorage_type()); DbFacade.getInstance().getStorageServerConnectionDAO().save(connection); } else { connection.setid(connections.get(0).getid()); } if (DbFacade.getInstance() .getStorageServerConnectionLunMapDAO() .get(new LUN_storage_server_connection_map_id(lun.getLUN_id(), connection.getid())) == null) { DbFacade.getInstance().getStorageServerConnectionLunMapDAO().save( new LUN_storage_server_connection_map(lun.getLUN_id(), connection.getid())); } } } protected void ConnectAllHostsToPool() { runSynchronizeOperation(new ConnectSingleAsyncOperationFactory()); } protected void DiconnectAllHostsInPool() { runSynchronizeOperation(new RefreshStoragePoolAndDisconnectAsyncOperationFactory()); } /** * The new master must be a data domain which is in Active status and not * reported by any vdsm as problematic. In case that all domains reported as problematic a first Active data domain * will be returned * @return an elected master domain or null */ protected storage_domains electNewMaster() { storage_domains newMaster = null; if (getStoragePool() != null) { List<storage_domains> storageDomains = DbFacade.getInstance() .getStorageDomainDAO().getAllForStoragePool(getStoragePool().getId()); if (storageDomains.size() > 0) { storage_domains storageDomain = getStorageDomain(); for (storage_domains dbStorageDomain : storageDomains) { if ((storageDomain == null || !dbStorageDomain.getid().equals(storageDomain.getid())) && (dbStorageDomain.getstatus() == StorageDomainStatus.Active || dbStorageDomain.getstatus() == StorageDomainStatus.Unknown) && dbStorageDomain.getstorage_domain_type() == StorageDomainType.Data) { if (!ResourceManager.getInstance().isDomainReportedInProblem(getStoragePool().getId(), dbStorageDomain.getid())) { newMaster = dbStorageDomain; break; } else if (newMaster == null) { newMaster = dbStorageDomain; } } } } } return newMaster; } @Override public Map<Guid, VdcObjectType> getPermissionCheckSubjects() { return Collections.singletonMap(getParameters().getStorageDomainId(), VdcObjectType.Storage); } protected void changeStorageDomainStatusInTransaction(final storage_pool_iso_map map, final StorageDomainStatus status) { TransactionSupport.executeInNewTransaction(new TransactionMethod<storage_pool_iso_map>() { @Override public storage_pool_iso_map runInTransaction() { CompensationContext context = getCompensationContext(); context.snapshotEntityStatus(map, map.getstatus()); map.setstatus(status); DbFacade.getInstance().getStoragePoolIsoMapDAO().updateStatus(map.getId(), map.getstatus()); getCompensationContext().stateChanged(); return null; } }); } private StorageDomainStatus getStorageDomainStatus() { StorageDomainStatus status = null; if (getStorageDomain() != null) { status = getStorageDomain().getstatus(); } return status; } private void addStorageDomainStatusIllegalMessage() { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_DOMAIN_STATUS_ILLEGAL); } }