use of com.emc.storageos.volumecontroller.impl.job.QueueJob in project coprhd-controller by CoprHD.
the class VNXUnitySnapshotOperations method restoreSingleVolumeSnapshot.
@Override
public void restoreSingleVolumeSnapshot(StorageSystem storage, URI volume, URI snapshot, TaskCompleter taskCompleter) throws DeviceControllerException {
try {
BlockSnapshot snapshotObj = _dbClient.queryObject(BlockSnapshot.class, snapshot);
VNXeApiClient apiClient = getVnxeClient(storage);
Snap snap = apiClient.getSnapshot(snapshotObj.getNativeId());
// Error out if the snapshot is attached
if (snap.isAttached()) {
log.error("Snapshot {})is exported and cannot be used for restore, please unexport it first", snapshotObj.getLabel());
ServiceError error = DeviceControllerErrors.vnxe.cannotRestoreAttachedSnapshot(snapshotObj.getLabel());
taskCompleter.error(_dbClient, error);
}
VNXeCommandJob job = apiClient.restoreSnap(snap.getId());
if (job != null) {
ControllerServiceImpl.enqueueJob(new QueueJob(new VNXUnityRestoreSnapshotJob(job.getId(), storage.getId(), taskCompleter)));
}
} catch (Exception ex) {
log.error("Restore snapshot got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("RestoreSnapshotJob", ex.getMessage());
taskCompleter.error(_dbClient, error);
}
}
use of com.emc.storageos.volumecontroller.impl.job.QueueJob in project coprhd-controller by CoprHD.
the class VNXUnitySnapshotOperations method createSingleVolumeSnapshot.
@Override
public void createSingleVolumeSnapshot(StorageSystem storage, URI snapshot, Boolean createInactive, Boolean readOnly, TaskCompleter taskCompleter) throws DeviceControllerException {
try {
BlockSnapshot snapshotObj = _dbClient.queryObject(BlockSnapshot.class, snapshot);
if (readOnly) {
snapshotObj.setIsReadOnly(readOnly);
_dbClient.updateObject(snapshotObj);
}
Volume volume = _dbClient.queryObject(Volume.class, snapshotObj.getParent());
TenantOrg tenant = _dbClient.queryObject(TenantOrg.class, volume.getTenant().getURI());
String tenantName = tenant.getLabel();
String snapLabelToUse = _nameGenerator.generate(tenantName, snapshotObj.getLabel(), snapshot.toString(), '-', SmisConstants.MAX_SNAPSHOT_NAME_LENGTH);
VNXeApiClient apiClient = getVnxeClient(storage);
VNXeCommandJob job = apiClient.createSnap(volume.getNativeId(), snapLabelToUse, readOnly);
if (job != null) {
ControllerServiceImpl.enqueueJob(new QueueJob(new VNXeBlockSnapshotCreateJob(job.getId(), storage.getId(), !createInactive, taskCompleter)));
}
} catch (Exception ex) {
log.error("Create volume snapshot got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("CreateVolumeSnapshot", ex.getMessage());
taskCompleter.error(_dbClient, error);
}
}
use of com.emc.storageos.volumecontroller.impl.job.QueueJob in project coprhd-controller by CoprHD.
the class VNXUnitySnapshotOperations method restoreGroupSnapshots.
@Override
public void restoreGroupSnapshots(StorageSystem storage, URI volume, URI snapshot, TaskCompleter taskCompleter) throws DeviceControllerException {
try {
BlockSnapshot snapshotObj = _dbClient.queryObject(BlockSnapshot.class, snapshot);
VNXeApiClient apiClient = getVnxeClient(storage);
Snap groupSnap = apiClient.getSnapshot(snapshotObj.getReplicationGroupInstance());
Snap snap = apiClient.getSnapshot(snapshotObj.getNativeId());
// Error out if the snapshot is attached
if (snap.isAttached()) {
log.error("Snapshot {})is exported and cannot be used for restore", snapshotObj.getLabel());
ServiceError error = DeviceControllerErrors.vnxe.cannotRestoreAttachedSnapshot(snapshotObj.getLabel());
taskCompleter.error(_dbClient, error);
}
VNXeCommandJob job = apiClient.restoreSnap(groupSnap.getId());
if (job != null) {
ControllerServiceImpl.enqueueJob(new QueueJob(new VNXUnityRestoreSnapshotJob(job.getId(), storage.getId(), taskCompleter)));
}
} catch (Exception ex) {
log.error("Restore group snapshot got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("RestoreSnapshotJob", ex.getMessage());
taskCompleter.error(_dbClient, error);
}
}
use of com.emc.storageos.volumecontroller.impl.job.QueueJob in project coprhd-controller by CoprHD.
the class VPlexDeviceController method invalidateCache.
/**
* Called to invalidate the read cache for a VPLEX volume when
* restoring a snapshot.
*
* @param vplexURI
* The URI of the VPLEX system.
* @param vplexVolumeURI
* The URI of a VPLEX volume.
* @param stepId
* The workflow step identifier.
*/
public void invalidateCache(URI vplexURI, URI vplexVolumeURI, String stepId) {
_log.info("Executing invalidate cache for volume {} on VPLEX {}", vplexVolumeURI, vplexURI);
try {
// Update workflow step.
WorkflowStepCompleter.stepExecuting(stepId);
// Get the API client.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
_log.info("Got VPLEX API client");
// Get the VPLEX volume.
Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
String vplexVolumeName = vplexVolume.getDeviceLabel();
_log.info("Got VPLEX volumes");
// Invalidate the cache for the volume.
boolean stillInProgress = client.invalidateVirtualVolumeCache(vplexVolumeName);
_log.info("Invalidated the VPLEX volume cache");
// invalidation completes.
if (stillInProgress) {
CacheStatusTaskCompleter invalidateCompleter = new CacheStatusTaskCompleter(vplexVolumeURI, stepId);
VPlexCacheStatusJob cacheStatusJob = new VPlexCacheStatusJob(invalidateCompleter);
ControllerServiceImpl.enqueueJob(new QueueJob(cacheStatusJob));
_log.info("Queued job to monitor migration progress.");
} else {
// Update workflow step state to success.
WorkflowStepCompleter.stepSucceded(stepId);
_log.info("Updated workflow step state to success");
}
} catch (VPlexApiException vae) {
_log.error("Exception invalidating VPLEX volume cache " + vae.getMessage(), vae);
WorkflowStepCompleter.stepFailed(stepId, vae);
} catch (Exception e) {
_log.error("Exception invalidating VPLEX volume cache " + e.getMessage(), e);
WorkflowStepCompleter.stepFailed(stepId, VPlexApiException.exceptions.failedInvalidatingVolumeCache(vplexVolumeURI.toString(), e));
}
}
use of com.emc.storageos.volumecontroller.impl.job.QueueJob in project coprhd-controller by CoprHD.
the class VPlexDeviceController method migrateVirtualVolume.
/**
* Creates and starts a VPlex data migration for the passed virtual volume
* on the passed VPlex storage system. The passed target is a newly created
* backend volume to which the data will be migrated. The source for the
* data migration is the current backend volume for the virtual volume that
* is in the same varray as the passed target. The method also creates
* a migration job to monitor the progress of the migration. The workflow
* step will complete when the migration completes, at which point the
* migration is automatically committed.
*
* @param vplexURI
* The URI of the VPlex storage system.
* @param virtualVolumeURI
* The URI of the virtual volume.
* @param targetVolumeURI
* The URI of the migration target.
* @param migrationURI
* The URI of the migration.
* @param newNhURI
* The URI of the new varray for the virtual volume
* when a local virtual volume is being migrated to the other
* cluster, or null.
* @param stepId
* The workflow step identifier.
* @throws WorkflowException
*/
public void migrateVirtualVolume(URI vplexURI, URI virtualVolumeURI, URI targetVolumeURI, URI migrationURI, URI newNhURI, String stepId) throws WorkflowException {
_log.info("Migration {} using target {}", migrationURI, targetVolumeURI);
try {
// Update step state to executing.
WorkflowStepCompleter.stepExecuting(stepId);
// Initialize the step data. The step data indicates if we
// successfully started the migration and is used in
// rollback.
_workflowService.storeStepData(stepId, Boolean.FALSE);
// Get the virtual volume.
Volume virtualVolume = getDataObject(Volume.class, virtualVolumeURI, _dbClient);
String virtualVolumeName = virtualVolume.getDeviceLabel();
_log.info("Virtual volume name is {}", virtualVolumeName);
// Setup the native volume info for the migration target.
Volume migrationTarget = getDataObject(Volume.class, targetVolumeURI, _dbClient);
StorageSystem targetStorageSystem = getDataObject(StorageSystem.class, migrationTarget.getStorageController(), _dbClient);
_log.info("Storage system for migration target is {}", migrationTarget.getStorageController());
List<String> itls = VPlexControllerUtils.getVolumeITLs(migrationTarget);
VolumeInfo nativeVolumeInfo = new VolumeInfo(targetStorageSystem.getNativeGuid(), targetStorageSystem.getSystemType(), migrationTarget.getWWN().toUpperCase().replaceAll(":", ""), migrationTarget.getNativeId(), migrationTarget.getThinlyProvisioned().booleanValue(), itls);
// Get the migration associated with the target.
Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
// Determine the unique name for the migration. We identifying
// the migration source and target, using array serial number
// and volume native id, in the migration name. This was fine
// for VPlex extent migration, which has a max length of 63
// for the migration name. However, for remote migrations,
// which require VPlex device migration, the max length is much
// more restrictive, like 20 characters. So, we switched over
// timestamps.
StringBuilder migrationNameBuilder = new StringBuilder(MIGRATION_NAME_PREFIX);
DateFormat dateFormatter = new SimpleDateFormat(MIGRATION_NAME_DATE_FORMAT);
migrationNameBuilder.append(dateFormatter.format(new Date()));
String migrationName = migrationNameBuilder.toString();
migration.setLabel(migrationName);
_dbClient.updateObject(migration);
_log.info("Migration name is {}", migrationName);
// Get the VPlex API client.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
_log.info("Got VPlex API client for VPlex {}", vplexURI);
// Get the configured migration speed
String speed = customConfigHandler.getComputedCustomConfigValue(CustomConfigConstants.MIGRATION_SPEED, vplexSystem.getSystemType(), null);
_log.info("Migration speed is {}", speed);
String transferSize = migrationSpeedToTransferSizeMap.get(speed);
// Make a call to the VPlex API client to migrate the virtual
// volume. Note that we need to do a remote migration when a
// local virtual volume is being migrated to the other VPlex
// cluster. If the passed new varray is not null, then
// this is the case.
Boolean isRemoteMigration = newNhURI != null;
// We support both device and extent migrations, however,
// when we don't know anything about the backend volumes
// we must use device migration.
Boolean useDeviceMigration = migration.getSource() == null;
List<VPlexMigrationInfo> migrationInfoList = client.migrateVirtualVolume(migrationName, virtualVolumeName, Arrays.asList(nativeVolumeInfo), isRemoteMigration, useDeviceMigration, true, true, transferSize);
_log.info("Started VPlex migration");
// We store step data indicating that the migration was successfully
// create and started. We will use this to determine the behavior
// on rollback. If we never got to the point that the migration
// was created and started, then there is no rollback to attempt
// on the VLPEX as the migrate API already tried to clean everything
// up on the VLPEX.
_workflowService.storeStepData(stepId, Boolean.TRUE);
// Initialize the migration info in the database.
VPlexMigrationInfo migrationInfo = migrationInfoList.get(0);
migration.setMigrationStatus(VPlexMigrationInfo.MigrationStatus.READY.getStatusValue());
migration.setPercentDone("0");
migration.setStartTime(migrationInfo.getStartTime());
_dbClient.updateObject(migration);
_log.info("Update migration info");
// Create a migration task completer and queue a job to monitor
// the migration progress. The completer will be invoked by the
// job when the migration completes.
MigrationTaskCompleter migrationCompleter = new MigrationTaskCompleter(migrationURI, stepId);
VPlexMigrationJob migrationJob = new VPlexMigrationJob(migrationCompleter);
migrationJob.setTimeoutTimeMsec(MINUTE_TO_MILLISECONDS * Long.valueOf(ControllerUtils.getPropertyValueFromCoordinator(coordinator, CONTROLLER_VPLEX_MIGRATION_TIMEOUT_MINUTES)));
ControllerServiceImpl.enqueueJob(new QueueJob(migrationJob));
_log.info("Queued job to monitor migration progress.");
} catch (VPlexApiException vae) {
_log.error("Exception migrating VPlex virtual volume: " + vae.getMessage(), vae);
WorkflowStepCompleter.stepFailed(stepId, vae);
} catch (Exception ex) {
_log.error("Exception migrating VPlex virtual volume: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.MIGRATE_VIRTUAL_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.migrateVirtualVolume(opName, ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
Aggregations