/** {@inheritDoc} */ @Override public void process() throws MigrationCallbackException { s_logger.info("Executing BlockSnapshotSession migration callback."); try { DbClient dbClient = getDbClient(); List<BlockSnapshotSession> snapshotSessions = new ArrayList<BlockSnapshotSession>(); Map<URI, Map<String, BlockSnapshotSession>> groupSessionMap = new HashMap<>(); List<URI> snapshotURIs = dbClient.queryByType(BlockSnapshot.class, true); Iterator<BlockSnapshot> snapshotsIter = dbClient.queryIterativeObjects(BlockSnapshot.class, snapshotURIs, true); while (snapshotsIter.hasNext()) { BlockSnapshot snapshot = snapshotsIter.next(); if (isSnapshotSessionSupported(snapshot)) { // Check if this is a group snapshot. URI cgURI = snapshot.getConsistencyGroup(); if (NullColumnValueGetter.isNullURI(cgURI)) { // The storage system for the single volume snapshot supports // snapshot sessions, then we need to prepare and create a // snapshot session for that snapshot and add the snapshot as // a linked target for the session. BlockSnapshotSession snapshotSession = prepareSnapshotSession(snapshot); snapshotSessions.add(snapshotSession); } else { // Create the group session if necessary and add the snapshot as a // linked target for that group session. String settingsInstance = snapshot.getSettingsInstance(); Map<String, BlockSnapshotSession> grpSnapshotSessions = groupSessionMap.get(cgURI); if (grpSnapshotSessions != null) { BlockSnapshotSession snapshotSession = grpSnapshotSessions.get(settingsInstance); if (snapshotSession == null) { snapshotSession = prepareSnapshotSession(snapshot); grpSnapshotSessions.put(settingsInstance, snapshotSession); snapshotSessions.add(snapshotSession); } else { StringSet linkedTargets = snapshotSession.getLinkedTargets(); linkedTargets.add(snapshot.getId().toString()); } } else { grpSnapshotSessions = new HashMap<String, BlockSnapshotSession>(); groupSessionMap.put(cgURI, grpSnapshotSessions); BlockSnapshotSession snapshotSession = prepareSnapshotSession(snapshot); grpSnapshotSessions.put(settingsInstance, snapshotSession); snapshotSessions.add(snapshotSession); } } } } if (!snapshotSessions.isEmpty()) { dbClient.createObject(snapshotSessions); } } catch (Exception e) { s_logger.error("Caught exception during BlockSnapshotSession migration", e); } }
/** * 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); }
/** * Prepare the ViPR BlockSnapshotSession instance for the pass BlockSnapshot instance. * * @param snapshot A reference to the snapshot. * @return A reference to the newly created snapshot session. */ private BlockSnapshotSession prepareSnapshotSession(BlockSnapshot snapshot) { s_logger.info("Prepare BlockSnapshotSession for snapshot {}", snapshot.getId()); BlockSnapshotSession snapshotSession = new BlockSnapshotSession(); URI snapSessionURI = URIUtil.createId(BlockSnapshotSession.class); snapshotSession.setId(snapSessionURI); snapshotSession.setSessionLabel(getSessionLabelFromSettingsInstance(snapshot)); URI cgURI = snapshot.getConsistencyGroup(); if (NullColumnValueGetter.isNullURI(cgURI)) { snapshotSession.setParent(snapshot.getParent()); snapshotSession.setLabel(snapshot.getLabel()); } else { snapshotSession.setConsistencyGroup(cgURI); snapshotSession.setLabel(snapshot.getSnapsetLabel()); Volume parent = getDbClient().queryObject(Volume.class, snapshot.getParent()); if (parent != null) { snapshotSession.setReplicationGroupInstance(parent.getReplicationGroupInstance()); snapshotSession.setSessionSetName(parent.getReplicationGroupInstance()); } } snapshotSession.setProject(snapshot.getProject()); snapshotSession.setStorageController(snapshot.getStorageController()); snapshotSession.setSessionInstance(snapshot.getSettingsInstance()); StringSet linkedTargets = new StringSet(); linkedTargets.add(snapshot.getId().toString()); snapshotSession.setLinkedTargets(linkedTargets); return snapshotSession; }
/** {@inheritDoc} */ @Override public void updateStatus(JobContext jobContext) throws Exception { JobStatus jobStatus = getJobStatus(); CloseableIterator<CIMObjectPath> volumeIter = null; try { DbClient dbClient = jobContext.getDbClient(); TaskCompleter completer = getTaskCompleter(); BlockSnapshot snapshot = dbClient.queryObject(BlockSnapshot.class, _snapshotURI); if (jobStatus == JobStatus.IN_PROGRESS) { return; } if (jobStatus == JobStatus.SUCCESS) { s_logger.info( "Post-processing successful link snapshot session target {} for task {}", snapshot.getId(), completer.getOpId()); // Get the snapshot session to which the target is being linked. BlockSnapshotSession snapSession = dbClient.queryObject(BlockSnapshotSession.class, completer.getId()); // Get the snapshot device ID and set it against the BlockSnapshot object. BlockObject sourceObj = BlockObject.fetch(dbClient, snapshot.getParent().getURI()); CIMConnectionFactory cimConnectionFactory = jobContext.getCimConnectionFactory(); WBEMClient client = getWBEMClient(dbClient, cimConnectionFactory); volumeIter = client.associatorNames(getCimJob(), null, SmisConstants.CIM_STORAGE_VOLUME, null, null); while (volumeIter.hasNext()) { // Get the sync volume native device id CIMObjectPath volumePath = volumeIter.next(); s_logger.info("volumePath: {}", volumePath.toString()); CIMInstance volume = client.getInstance(volumePath, false, false, null); String volumeDeviceId = volumePath.getKey(SmisConstants.CP_DEVICE_ID).getValue().toString(); s_logger.info("volumeDeviceId: {}", volumeDeviceId); if (volumeDeviceId.equals(sourceObj.getNativeId())) { // Don't want the source, we want the linked target. continue; } String volumeElementName = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_ELEMENT_NAME); s_logger.info("volumeElementName: {}", volumeElementName); String volumeWWN = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_WWN_NAME); s_logger.info("volumeWWN: {}", volumeWWN); String volumeAltName = CIMPropertyFactory.getPropertyValue(volume, SmisConstants.CP_NAME); s_logger.info("volumeAltName: {}", volumeAltName); StorageSystem system = dbClient.queryObject(StorageSystem.class, getStorageSystemURI()); snapshot.setNativeId(volumeDeviceId); snapshot.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(system, snapshot)); snapshot.setDeviceLabel(volumeElementName); snapshot.setInactive(false); snapshot.setIsSyncActive(Boolean.TRUE); snapshot.setCreationTime(Calendar.getInstance()); snapshot.setWWN(volumeWWN.toUpperCase()); snapshot.setAlternateName(volumeAltName); snapshot.setSettingsInstance(snapSession.getSessionInstance()); commonSnapshotUpdate( snapshot, volume, client, system, sourceObj.getNativeId(), volumeDeviceId, false, dbClient); s_logger.info( String.format( "For target volume path %1$s, going to set blocksnapshot %2$s nativeId to %3$s (%4$s). Associated volume is %5$s (%6$s)", volumePath.toString(), snapshot.getId().toString(), volumeDeviceId, volumeElementName, sourceObj.getNativeId(), sourceObj.getDeviceLabel())); dbClient.updateObject(snapshot); } } else if (jobStatus == JobStatus.FAILED || jobStatus == JobStatus.FATAL_ERROR) { s_logger.info( "Failed to link snapshot session target {} for task {}", snapshot.getId(), completer.getOpId()); snapshot.setInactive(true); dbClient.updateObject(snapshot); } } catch (Exception e) { setPostProcessingErrorStatus( "Encountered an internal error in link snapshot session target job status processing: " + e.getMessage()); s_logger.error( "Encountered an internal error in link snapshot session target job status processing", e); } finally { if (volumeIter != null) { volumeIter.close(); } super.updateStatus(jobContext); } }