/** * Find an UnManagedVolume for the given WWN by first checking in the UnManagedVolumesToUpdate * collection (in case we've already fetched it and updated it elsewhere), and then check the * database. * * @param wwn the WWN to find an UnManagedVolume for * @param dbClient a reference to the database client * @param cachedStorageNativeIds see comments, cached list of storage native GUIDs * @return an UnManagedVolume object for the given WWN */ private UnManagedVolume findUnManagedVolumeForWwn( String wwn, DbClient dbClient, List<String> cachedStorageNativeIds) { UnManagedVolume unManagedVolume = unManagedVolumesToUpdateByWwn.get(wwn); if (null == unManagedVolume) { unManagedVolume = DiscoveryUtils.checkUnManagedVolumeExistsInDBByWwn(dbClient, wwn); } // Special for RP. XIO unmanaged volumes store a WWN in the "wwn" field that will not match // the WWN returned by RP, however the proper 128-but WWN is in two places: // 1. The volume information "NATIVE_ID" field. (not indexable, so hard to run a query to find) // 2. Locked in the native guid of the volume // XTREMIO+APM00144755987+UNMANAGEDVOLUME+616a8770e89749a7908d48a3dd9cf0fd // The goal of this section of code is to loop through XIO arrays and search for the native guid // based on that XIO native guid and wwn to see if we find the unmanaged volume. // // Someday RP will return the short WWN in the CG information and this inefficient code can be // removed. if (null == unManagedVolume && cachedStorageNativeIds != null) { for (String storageNativeIdPrefix : cachedStorageNativeIds) { // Search for the unmanaged volume based on the native GUID String searchCriteria = storageNativeIdPrefix + "+UNMANAGEDVOLUME+" + wwn.toLowerCase(); List<UnManagedVolume> volumes = CustomQueryUtility.getUnManagedVolumeByNativeGuid(dbClient, searchCriteria); if (volumes != null && !volumes.isEmpty()) { log.info("Found XIO unmanaged volume: " + volumes.get(0).getLabel()); return volumes.get(0); } } } return unManagedVolume; }
private List<CifsShareACL> queryDBShareACLs() { try { ContainmentConstraint containmentConstraint = null; if (this.fs != null) { _log.info( "Querying DB for Share ACLs of share {} of filesystemId {} ", this.shareName, fs.getId()); containmentConstraint = ContainmentConstraint.Factory.getFileCifsShareAclsConstraint(this.fs.getId()); } else { // Snapshot _log.info( "Querying DB for Share ACLs of share {} of snapshotId {} ", this.shareName, this.snapshot.getId()); containmentConstraint = ContainmentConstraint.Factory.getSnapshotCifsShareAclsConstraint(this.snapshot.getId()); } List<CifsShareACL> shareAclList = CustomQueryUtility.queryActiveResourcesByConstraint( this.dbClient, CifsShareACL.class, containmentConstraint); return shareAclList; } catch (Exception e) { _log.error("Error while querying DB for ACL of a share {}", e); } return null; }
/** * If any endpoint is used in an active File Export, throws an exception * * @param endpoints endpoints being added * @param varrays endpoints belong to * <p>Assumes endpoint formats have been validated. */ public static void checkNotUsedByActiveFileExport(String endpoint, DbClient dbClient) { Network network = NetworkUtil.getEndpointNetwork(endpoint, dbClient); if (network != null) { Set<String> netVArrayIds = network.getConnectedVirtualArrays(); if ((netVArrayIds != null) && (!netVArrayIds.isEmpty())) { Iterator<String> netVArrayIdsIter = netVArrayIds.iterator(); while (netVArrayIdsIter.hasNext()) { String varrayId = netVArrayIdsIter.next(); List<FileShare> fileShares = CustomQueryUtility.queryActiveResourcesByConstraint( dbClient, FileShare.class, AlternateIdConstraint.Factory.getConstraint(FileShare.class, "varray", varrayId)); for (FileShare fileShare : fileShares) { FSExportMap fsExports = fileShare.getFsExports(); if (fsExports != null) { Iterator<FileExport> it = fsExports.values().iterator(); while (it.hasNext()) { FileExport fileExport = it.next(); if (fileExport.getClients().contains(endpoint) || fileExport.getStoragePort().contains(endpoint)) { throw APIException.badRequests.endpointsCannotBeUpdatedActiveExport(endpoint); } } } } } } } }
/** * check Storage Volume exists in DB * * @param dbClient * @param nativeGuid * @return * @throws IOException */ public static Volume checkStorageVolumeExistsInDB(DbClient dbClient, String nativeGuid) throws IOException { List<Volume> volumes = CustomQueryUtility.getActiveVolumeByNativeGuid(dbClient, nativeGuid); Iterator<Volume> volumesItr = volumes.iterator(); if (volumesItr.hasNext()) { return volumesItr.next(); } return null; }
/** * check Storage Volume exists in DB * * @param dbClient * @param nativeGuid * @return * @throws IOException */ public static BlockSnapshot checkBlockSnapshotExistsInDB(DbClient dbClient, String nativeGuid) throws IOException { List<BlockSnapshot> snapshots = CustomQueryUtility.getActiveBlockSnapshotByNativeGuid(dbClient, nativeGuid); Iterator<BlockSnapshot> snapshotItr = snapshots.iterator(); if (snapshotItr.hasNext()) { return snapshotItr.next(); } return null; }
/** * Cleans up instances of {@link BlockSnapshot} that failed to be created. Also, any stale entries * in {@link BlockSnapshotSession#getLinkedTargets()} will be cleaned up. * * @param volume Volume URI to process. * @param itemsToUpdate Items to be updated. * @param itemsToDelete Items to be deleted. */ @Override public void process( URI volume, Collection<DataObject> itemsToUpdate, Collection<DataObject> itemsToDelete) { List<BlockSnapshot> snapshots = CustomQueryUtility.queryActiveResourcesByConstraint( getDbClient(), BlockSnapshot.class, ContainmentConstraint.Factory.getVolumeSnapshotConstraint(volume)); List<BlockSnapshot> failedSnapshots = new ArrayList<>(); List<BlockSnapshotSession> updateSessions = new ArrayList<>(); failedSnapshots.addAll( Collections2.filter( snapshots, new Predicate<BlockSnapshot>() { @Override public boolean apply(BlockSnapshot snapshot) { return Strings.isNullOrEmpty(snapshot.getNativeId()); } })); // Removed failed snapshots from any existing sessions for (BlockSnapshot failedSnapshot : failedSnapshots) { log.info("Removing failed snapshot: {}", failedSnapshot.getLabel()); List<BlockSnapshotSession> sessions = CustomQueryUtility.queryActiveResourcesByConstraint( getDbClient(), BlockSnapshotSession.class, ContainmentConstraint.Factory.getLinkedTargetSnapshotSessionConstraint( failedSnapshot.getId())); for (BlockSnapshotSession session : sessions) { log.info("Updating existing session: {}", session.getSessionLabel()); StringSet linkedTargets = session.getLinkedTargets(); linkedTargets.remove(failedSnapshot.getId().toString()); updateSessions.add(session); } } itemsToUpdate.addAll(updateSessions); itemsToDelete.addAll(failedSnapshots); }
/** * Checks if an port in use by an export masks * * @param portId the port URI being checked * @param dbClient * @return true if the port in use by export masks */ public static boolean isBlockStoragePortInUse(URI portId, DbClient dbClient) { if (portId != null) { List<ExportMask> exportMasks = CustomQueryUtility.queryActiveResourcesByConstraint( dbClient, ExportMask.class, AlternateIdConstraint.Factory.getConstraint( ExportMask.class, "storagePorts", portId.toString())); return (exportMasks != null && !exportMasks.isEmpty()); } return false; }
/** * Allows the user to remove a storage system from the list of decommisioned resources After that * corresponding provider should be able to be rescanned and add this system back to the list of * managed systems. * * @param id id the URN of a ViPR Storage provider * @param param The storage system details. * @brief removes the storage system from the list of decommissioned systems and rescans the * provider. * @return An asynchronous task corresponding to the scan job scheduled for the provider. * @throws BadRequestException When the system type is not valid or a storage system with the same * native guid already exists. * @throws com.emc.storageos.db.exceptions.DatabaseException When an error occurs querying the * database. * @throws ControllerException When an error occurs discovering the storage system. */ @PUT @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @CheckPermission(roles = {Role.SYSTEM_ADMIN}) @Path("/{id}/storage-systems") public TaskResourceRep addStorageSystem( @PathParam("id") URI id, StorageSystemProviderRequestParam param) throws ControllerException { TaskResourceRep taskRep; URIQueryResultList list = new URIQueryResultList(); ArgValidator.checkFieldNotEmpty(param.getSystemType(), "system_type"); if (!StorageSystem.Type.isProviderStorageSystem( DiscoveredDataObject.Type.valueOf(param.getSystemType()))) { throw APIException.badRequests.cannotAddStorageSystemTypeToStorageProvider( param.getSystemType()); } StorageProvider provider = _dbClient.queryObject(StorageProvider.class, id); ArgValidator.checkEntityNotNull(provider, id, isIdEmbeddedInURL(id)); ArgValidator.checkFieldNotEmpty(param.getSerialNumber(), "serialNumber"); String nativeGuid = NativeGUIDGenerator.generateNativeGuid(param.getSystemType(), param.getSerialNumber()); // check for duplicate StorageSystem. List<StorageSystem> systems = CustomQueryUtility.getActiveStorageSystemByNativeGuid(_dbClient, nativeGuid); if (systems != null && !systems.isEmpty()) { throw APIException.badRequests.invalidParameterProviderStorageSystemAlreadyExists( "nativeGuid", nativeGuid); } int cleared = DecommissionedResource.removeDecommissionedFlag(_dbClient, nativeGuid, StorageSystem.class); if (cleared == 0) { log.info("Cleared {} decommissioned systems", cleared); } else { log.info("Did not find any decommissioned systems to clear. Continue to scan."); } ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1); String taskId = UUID.randomUUID().toString(); tasks.add(new AsyncTask(StorageProvider.class, provider.getId(), taskId)); BlockController controller = getController(BlockController.class, provider.getInterfaceType()); DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new ScanJobExec(controller)); TaskList taskList = scheduler.scheduleAsyncTasks(tasks); return taskList.getTaskList().listIterator().next(); }
/** * Checks if an initiator in use by an export groups * * @param initId the initiator URI being checked * @param dbClient * @return true if the initiator in use by export groups */ public static boolean isInitiatorInUse(URI initId, DbClient dbClient) { if (initId != null) { List<ExportGroup> exportGroups = CustomQueryUtility.queryActiveResourcesByConstraint( dbClient, ExportGroup.class, AlternateIdConstraint.Factory.getConstraint( ExportGroup.class, "initiators", initId.toString())); return (exportGroups != null && !exportGroups.isEmpty()); } return false; }
private List<QuotaDirectory> queryDBQuotaDirectories(FileShare fs) { _log.info("Querying all quota directories Using FsId {}", fs.getId()); try { ContainmentConstraint containmentConstraint = ContainmentConstraint.Factory.getQuotaDirectoryConstraint(fs.getId()); List<QuotaDirectory> fsQuotaDirs = CustomQueryUtility.queryActiveResourcesByConstraint( _dbClient, QuotaDirectory.class, containmentConstraint); return fsQuotaDirs; } catch (Exception e) { _log.error("Error while querying {}", e); } return null; }
/** * get the volume to be updated after application add and remove operations could be the volume * passed in if it's a simple block volume or the vplex virtual volume if it's a backing volume * * @param voluri uri of volume operated on during add or remove volume from application operation * @param dbClient * @return the volume to update */ private Volume getVolume(URI voluri, DbClient dbClient) { // if this is a vplex volume, update the parent virtual volume List<Volume> vplexVolumes = CustomQueryUtility.queryActiveResourcesByConstraint( dbClient, Volume.class, getVolumesByAssociatedId(voluri.toString())); Volume volume = null; for (Volume vplexVolume : vplexVolumes) { URI storageURI = vplexVolume.getStorageController(); StorageSystem storage = dbClient.queryObject(StorageSystem.class, storageURI); if (DiscoveredDataObject.Type.vplex.name().equals(storage.getSystemType())) { volume = vplexVolume; } } if (volume == null) { volume = dbClient.queryObject(Volume.class, voluri); } return volume; }
/** * Update the Storage Provider. This is useful when we move arrays to some other provider. * * @param id the URN of a ViPR Storage Provider * @brief Update Storage provider * @return Updated Storage Provider information. */ @PUT @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("/{id}") @CheckPermission(roles = {Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN}) public StorageProviderRestRep updateStorageProvider( @PathParam("id") URI id, StorageProviderUpdateParam param) { StorageProvider storageProvider = _dbClient.queryObject(StorageProvider.class, id); if (null == storageProvider || storageProvider.getInactive()) { throw APIException.notFound.unableToFindEntityInURL(id); } else { /* Usecase is not to remove the provider instead we can update the old storage provider with new provider details. */ if (param.getName() != null && !param.getName().equals("") && !param.getName().equalsIgnoreCase(storageProvider.getLabel())) { checkForDuplicateName(param.getName(), StorageProvider.class); storageProvider.setLabel(param.getName()); } // if the ip or port passed are different from the existing one // check to ensure a provider does not exist with the new ip + port combo String existingIPAddress = storageProvider.getIPAddress(); Integer existingPortNumber = storageProvider.getPortNumber(); if ((param.getIpAddress() != null && !param.getIpAddress().equals(existingIPAddress)) || (param.getPortNumber() != null && !param.getPortNumber().equals(existingPortNumber))) { String ipAddress = (param.getIpAddress() != null) ? param.getIpAddress() : existingIPAddress; Integer portNumber = (param.getPortNumber() != null) ? param.getPortNumber() : existingPortNumber; ArgValidator.checkFieldRange(portNumber, 1, 65535, "port_number"); String providerKey = ipAddress + "-" + portNumber; List<StorageProvider> providers = CustomQueryUtility.getActiveStorageProvidersByProviderId(_dbClient, providerKey); if (providers != null && !providers.isEmpty()) { throw APIException.badRequests.invalidParameterStorageProviderAlreadyRegistered( providerKey); } // User can update IP address for an existing Provider object // if and only if the connection with old IP is not alive. if (!existingIPAddress.equals(param.getIpAddress()) && isOldConnectionAlive( existingIPAddress, existingPortNumber, storageProvider.getInterfaceType()) && (storageProvider.getStorageSystems() != null && !storageProvider.getStorageSystems().isEmpty())) { throw APIException.badRequests.cannotUpdateProviderIP( existingIPAddress + "-" + existingPortNumber); } storageProvider.setIPAddress(ipAddress); storageProvider.setPortNumber(portNumber); } if (param.getUserName() != null && StringUtils.isNotBlank(param.getUserName())) { storageProvider.setUserName(param.getUserName()); } if (param.getPassword() != null && StringUtils.isNotBlank(param.getPassword())) { storageProvider.setPassword(param.getPassword()); } if (param.getUseSSL() != null) { storageProvider.setUseSSL(param.getUseSSL()); } if (param.getInterfaceType() != null) { ArgValidator.checkFieldValueFromEnum( param.getInterfaceType(), "interface_type", EnumSet.of( StorageProvider.InterfaceType.hicommand, StorageProvider.InterfaceType.smis, StorageProvider.InterfaceType.scaleio, StorageProvider.InterfaceType.ibmxiv)); storageProvider.setInterfaceType(param.getInterfaceType()); } if (param.getSecondaryUsername() != null) { storageProvider.setSecondaryUsername(param.getSecondaryUsername()); } if (param.getSecondaryPassword() != null) { storageProvider.setSecondaryPassword(param.getSecondaryPassword()); } if (param.getElementManagerURL() != null) { storageProvider.setElementManagerURL(param.getElementManagerURL()); } _dbClient.persistObject(storageProvider); } auditOp( OperationTypeEnum.UPDATE_STORAGEPROVIDER, true, null, storageProvider.getId().toString(), storageProvider.getLabel(), storageProvider.getIPAddress(), storageProvider.getPortNumber(), storageProvider.getUserName(), storageProvider.getInterfaceType()); return map(storageProvider); }
@POST @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @CheckPermission(roles = {Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN}) public TaskResourceRep registerStorageProvider(StorageProviderCreateParam param) throws ControllerException { ArgValidator.checkFieldNotEmpty(param.getName(), "name"); checkForDuplicateName(param.getName(), StorageProvider.class); ArgValidator.checkFieldNotEmpty(param.getIpAddress(), "ip_address"); ArgValidator.checkFieldNotNull(param.getPortNumber(), "port_number"); ArgValidator.checkFieldNotEmpty(param.getUserName(), "user_name"); ArgValidator.checkFieldNotEmpty(param.getPassword(), "password"); ArgValidator.checkFieldRange(param.getPortNumber(), 1, 65535, "port_number"); ArgValidator.checkFieldValueFromEnum( param.getInterfaceType(), "interface_type", StorageProvider.InterfaceType.class); String providerKey = param.getIpAddress() + "-" + param.getPortNumber(); List<StorageProvider> providers = CustomQueryUtility.getActiveStorageProvidersByProviderId(_dbClient, providerKey); if (providers != null && !providers.isEmpty()) { throw APIException.badRequests.invalidParameterStorageProviderAlreadyRegistered(providerKey); } // Set the SSL parameter Boolean useSSL = param.getUseSSL(); if (useSSL == null) { useSSL = StorageProviderCreateParam.USE_SSL_DEFAULT; } StorageProvider provider = new StorageProvider(); provider.setId(URIUtil.createId(StorageProvider.class)); provider.setLabel(param.getName()); provider.setIPAddress(param.getIpAddress()); provider.setPortNumber(param.getPortNumber()); provider.setUserName(param.getUserName()); provider.setPassword(param.getPassword()); provider.setUseSSL(useSSL); provider.setInterfaceType(param.getInterfaceType()); provider.setRegistrationStatus(RegistrationStatus.REGISTERED.toString()); provider.setConnectionStatus(ConnectionStatus.INITIALIZING.name()); provider.setSecondaryUsername(param.getSecondaryUsername()); provider.setSecondaryPassword(param.getSecondaryPassword()); provider.setElementManagerURL(param.getElementManagerURL()); if (param.getSioCLI() != null) { // TODO: Validate the input? provider.addKey(StorageProvider.GlobalKeys.SIO_CLI.name(), param.getSioCLI()); } if (StorageProvider.InterfaceType.ibmxiv.name().equalsIgnoreCase(provider.getInterfaceType())) { provider.setManufacturer("IBM"); } _dbClient.createObject(provider); auditOp( OperationTypeEnum.REGISTER_STORAGEPROVIDER, true, null, provider.getLabel(), provider.getId().toString(), provider.getIPAddress(), provider.getPortNumber(), provider.getUserName(), provider.getInterfaceType()); ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1); String taskId = UUID.randomUUID().toString(); tasks.add(new AsyncTask(StorageProvider.class, provider.getId(), taskId)); BlockController controller = getController(BlockController.class, provider.getInterfaceType()); log.debug("controller.getClass().getName() :{}", controller.getClass().getName()); log.debug("controller.getClass().getSimpleName() :{}", controller.getClass().getSimpleName()); /** * Creates MonitoringJob token for vnxblock/vmax, hds, cinder and IBM XIV device on zooKeeper * queue */ // TODO : If all interface types have monitoring impl class added (scaleIO is missing), // this check can be removed. String interfaceType = provider.getInterfaceType(); if (StorageProvider.InterfaceType.hicommand.name().equalsIgnoreCase(interfaceType) || StorageProvider.InterfaceType.smis.name().equalsIgnoreCase(interfaceType) || StorageProvider.InterfaceType.cinder.name().equalsIgnoreCase(interfaceType) || StorageProvider.InterfaceType.ibmxiv.name().equalsIgnoreCase(interfaceType)) { controller.startMonitoring( new AsyncTask(StorageProvider.class, provider.getId(), taskId), getSystemTypeByInterface(interfaceType)); } DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new ScanJobExec(controller)); TaskList taskList = scheduler.scheduleAsyncTasks(tasks); return taskList.getTaskList().listIterator().next(); }