use of com.emc.storageos.vplex.api.clientdata.VolumeInfo in project coprhd-controller by CoprHD.
the class VPlexApiVirtualVolumeManager method createDistributedVirtualVolume.
/**
* Creates a distributed virtual volume from a non-distributed one plus a new unclaimed
* remote storage volume.
*
* @param virtualVolume - Existing non-distributed virtual volume.
* @param newRemoteVolume - Unclaimed storage volume in remote cluster.
* @param discoveryRequired - Set if discovery required.
* @param clusterId - Used to set the detach rule for the distributed volume.
* @return - VPlexVirtualVolumeInfo representing the distributed virtual volume.
* @throws VPlexApiException
*/
VPlexVirtualVolumeInfo createDistributedVirtualVolume(VPlexVirtualVolumeInfo virtualVolume, VolumeInfo newRemoteVolume, boolean discoveryRequired, String clusterId, String transferSize) throws VPlexApiException {
// Determine the "local" device
String virtualVolumeName = virtualVolume.getName();
String localDeviceName = virtualVolume.getSupportingDevice();
// Find the storage volumes corresponding to the passed remote
// volume information, discovery them if required.
s_logger.info("Find remote storage volume");
List<VolumeInfo> remoteVolumeInfoList = new ArrayList<VolumeInfo>();
remoteVolumeInfoList.add(newRemoteVolume);
List<VPlexClusterInfo> clusterInfoList = new ArrayList<VPlexClusterInfo>();
Map<VolumeInfo, VPlexStorageVolumeInfo> storageVolumeInfoMap = findStorageVolumes(remoteVolumeInfoList, discoveryRequired, clusterInfoList, null);
if (storageVolumeInfoMap.isEmpty()) {
throw VPlexApiException.exceptions.cantDiscoverStorageVolume(newRemoteVolume.getVolumeWWN());
}
// Claim the storage volumes
claimStorageVolumes(storageVolumeInfoMap, false);
s_logger.info("Claimed remote storage volume");
// Try and build up the VPLEX local device from the claimed storage
// volume and attach the local device to the local device of the
// passed virtual volume to form the local mirror. If we get an error,
// clean up the VPLEX artifacts and unclaim the storage volume.
VPlexDeviceInfo remoteDevice, localDevice;
VPlexApiDiscoveryManager discoveryMgr = _vplexApiClient.getDiscoveryManager();
try {
// Create extents
List<VPlexStorageVolumeInfo> storageVolumeInfoList = new ArrayList<VPlexStorageVolumeInfo>();
for (VolumeInfo nativeVolumeInfo : remoteVolumeInfoList) {
storageVolumeInfoList.add(storageVolumeInfoMap.get(nativeVolumeInfo));
}
createExtents(storageVolumeInfoList);
s_logger.info("Created extent on remote storage volume");
// Find the extents just created and create local devices on
// those extents.
List<VPlexExtentInfo> extentInfoList = discoveryMgr.findExtents(storageVolumeInfoList);
if (extentInfoList.isEmpty()) {
throw VPlexApiException.exceptions.cantFindExtentForClaimedVolume(storageVolumeInfoList.get(0).getName());
}
createLocalDevices(extentInfoList);
s_logger.info("Created local devices on extents");
// Find the local device for the extent just created.
List<VPlexDeviceInfo> remoteDevices = discoveryMgr.findLocalDevices(extentInfoList);
if (remoteDevices.isEmpty()) {
throw VPlexApiException.exceptions.cantFindLocalDeviceForExtent(extentInfoList.get(0).getName());
}
remoteDevice = remoteDevices.get(0);
s_logger.info("Found the remote device {}", remoteDevice.getPath());
// Find the local device.
localDevice = discoveryMgr.findLocalDevice(localDeviceName);
if (localDevice == null) {
throw VPlexApiException.exceptions.cantFindLocalDevice(localDeviceName);
}
s_logger.info("Found the local device {}", localDevice.getPath());
// Now use "device attach-mirror" to create a distributed device from an already exported volume.
String rulesetName = VPlexApiConstants.CLUSTER_1_DETACHES;
if (clusterId.equals(VPlexApiConstants.CLUSTER_2_ID)) {
rulesetName = VPlexApiConstants.CLUSTER_2_DETACHES;
}
deviceAttachMirror(localDevice.getPath(), remoteDevice.getPath(), rulesetName);
s_logger.info("Finished device attach-mirror on device {}", localDevice.getPath());
} catch (Exception e) {
// An error occurred. Clean up the VPLEX artifacts created for
// the mirror and unclaim the storage volume.
s_logger.info("Exception occurred creating and attaching remote mirror " + " to local VPLEX volume, attempting to cleanup VPLEX artifacts");
throw e;
}
try {
// Find virtual volume.
VPlexVirtualVolumeInfo vvInfo = discoveryMgr.findVirtualVolume(localDevice.getCluster(), virtualVolumeName, false);
// If transferSize is set, set the rebuild size for the distributed device created by
// device-attach mirror.
VPlexDistributedDeviceInfo distDeviceInfo = discoveryMgr.findDistributedDevice(localDevice.getName());
if (transferSize != null) {
String deviceName = distDeviceInfo.getName();
s_logger.info("Rebuild transfer size of {} will be set for device {}", transferSize, deviceName);
setRebuildTransferSize(deviceName, transferSize);
}
// conforms to the standard naming convention.
if (localDeviceName.length() > VPlexApiConstants.DEVICE_PREFIX.length()) {
List<String> claimedVolumeNames = Arrays.asList(localDeviceName.substring(VPlexApiConstants.DEVICE_PREFIX.length()));
if (VPlexApiUtils.volumeHasDefaultNamingConvention(virtualVolumeName, localDeviceName, false, claimedVolumeNames)) {
// Update both the volume and supporting device names.
String remoteName = remoteDevice.getName().replaceAll(VPlexApiConstants.DEVICE_PREFIX, "");
String newVvName = vvInfo.getName();
newVvName = newVvName.replaceFirst(VPlexApiConstants.DEVICE_PREFIX, VPlexApiConstants.DIST_DEVICE_PREFIX + VPlexApiConstants.DIST_DEVICE_NAME_DELIM);
newVvName = newVvName.replaceFirst(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX, "");
newVvName = newVvName + VPlexApiConstants.DIST_DEVICE_NAME_DELIM + remoteName + VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX;
vvInfo = renameVPlexResource(vvInfo, newVvName);
String newDdName = distDeviceInfo.getName();
newDdName = newDdName.replaceFirst(VPlexApiConstants.DEVICE_PREFIX, VPlexApiConstants.DIST_DEVICE_PREFIX + VPlexApiConstants.DIST_DEVICE_NAME_DELIM);
newDdName = newDdName + VPlexApiConstants.DIST_DEVICE_NAME_DELIM + remoteName;
distDeviceInfo = renameVPlexResource(distDeviceInfo, newDdName);
} else if (VPlexApiUtils.localDeviceHasDefaultNamingConvention(localDeviceName, claimedVolumeNames)) {
// The volume name does not conform, but then supporting device does, so
// update just the device name.
String newDdName = distDeviceInfo.getName();
newDdName = newDdName.replaceFirst(VPlexApiConstants.DEVICE_PREFIX, VPlexApiConstants.DIST_DEVICE_PREFIX + VPlexApiConstants.DIST_DEVICE_NAME_DELIM);
String remoteName = remoteDevice.getName().replaceAll(VPlexApiConstants.DEVICE_PREFIX, "");
newDdName = newDdName + VPlexApiConstants.DIST_DEVICE_NAME_DELIM + remoteName;
distDeviceInfo = renameVPlexResource(distDeviceInfo, newDdName);
}
}
return vvInfo;
} catch (Exception e) {
// created for the remote mirror and unclaim the storage volume.
try {
// Detach the mirror as the attach was successful.
detachMirrorFromLocalVirtualVolume(virtualVolumeName, remoteDevice.getName(), true);
// This will look for any artifacts, starting with a virtual
// volume, that use the passed native volume info and destroy
// them and then unclaim the volume.
deleteVirtualVolume(Collections.singletonList(newRemoteVolume));
} catch (Exception ex) {
s_logger.error("Failed attempting to cleanup VPLEX after failed attempt " + "to find and rename local virtual volume {} after remote mirror attached.", virtualVolume.getPath(), ex);
}
throw e;
}
}
use of com.emc.storageos.vplex.api.clientdata.VolumeInfo in project coprhd-controller by CoprHD.
the class VPlexApiTest method testCreateVolumeWithDeviceMirror.
/*
* Tests creation of a distributed virtual volume from a non-distributed virtual volume
* and the addition of a new remote volume.
*/
@Test
public void testCreateVolumeWithDeviceMirror() {
VPlexVirtualVolumeInfo vvInfo = null;
VolumeInfo newVolumeInfo = null;
VPlexVirtualVolumeInfo distVolInfo = null;
try {
vvInfo = createSimpleVirtualVolume();
String volumeInfo = _properties.getProperty(DEVICE_MIRROR_TEST_VOLUME_PROP_KEY);
StringTokenizer tokenizer = new StringTokenizer(volumeInfo, ",");
String storageSystemGuid = tokenizer.nextToken();
String volumeId = tokenizer.nextToken();
String volumeNativeId = tokenizer.nextToken();
String transferSize = "8M";
newVolumeInfo = new VolumeInfo(storageSystemGuid, "vmax", volumeId, volumeNativeId, false, Collections.<String>emptyList());
distVolInfo = _client.upgradeVirtualVolumeToDistributed(vvInfo, newVolumeInfo, true, "1", transferSize);
Assert.assertNotNull(distVolInfo);
WaitOnRebuildResult goodRebuild = _client.waitOnRebuildCompletion(distVolInfo.getName());
Assert.assertEquals(WaitOnRebuildResult.SUCCESS, goodRebuild);
} catch (Exception ex) {
Assert.fail(ex.getMessage());
} finally {
try {
if (distVolInfo != null) {
_client.deleteVirtualVolume(distVolInfo.getName(), true, false);
} else if (vvInfo != null) {
_client.deleteVirtualVolume(vvInfo.getName(), true, false);
}
} catch (Exception exx) {
// ignoring exceptions
System.out.println("an ignorable exception was encountered: " + exx.getLocalizedMessage());
}
}
}
use of com.emc.storageos.vplex.api.clientdata.VolumeInfo in project coprhd-controller by CoprHD.
the class VPlexApiTest method testMigrateVirtualVolumeDistributed.
/**
* Tests the API migrateVirtualVolume for a distributed virtual volume.
*/
@Test
public void testMigrateVirtualVolumeDistributed() {
boolean wasException = false;
try {
// Create the distributed virtual volume.
StringBuilder vvNameBuilder = new StringBuilder(VPlexApiConstants.DIST_DEVICE_PREFIX);
List<VolumeInfo> nativeVolumeInfoList = new ArrayList<VolumeInfo>();
String distVolumeInfo = _properties.getProperty(DISTRIBUTED_VV_INFO_PROP_KEY);
StringTokenizer tokenizer = new StringTokenizer(distVolumeInfo, "::");
while (tokenizer.hasMoreTokens()) {
String volumeInfo = tokenizer.nextToken();
StringTokenizer volumeInfoTokenizer = new StringTokenizer(volumeInfo, ",");
String systemGuid = volumeInfoTokenizer.nextToken();
String volumeId = volumeInfoTokenizer.nextToken();
String volumeNativeId = volumeInfoTokenizer.nextToken();
nativeVolumeInfoList.add(new VolumeInfo(systemGuid, "vmax", volumeId, volumeNativeId, false, Collections.<String>emptyList()));
vvNameBuilder.append(VPlexApiConstants.DIST_DEVICE_NAME_DELIM);
vvNameBuilder.append(VPlexApiConstants.VOLUME_NAME_PREFIX);
vvNameBuilder.append(systemGuid.substring(systemGuid.indexOf("+") + 1));
vvNameBuilder.append("-");
vvNameBuilder.append(volumeNativeId);
}
vvNameBuilder.append(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX);
String vvName = vvNameBuilder.toString();
List<VPlexClusterInfo> clusterInfoList = _client.getClusterInfoDetails();
VPlexVirtualVolumeInfo vvInfo = _client.createVirtualVolume(nativeVolumeInfoList, true, false, false, "1", clusterInfoList, true, false, true);
Assert.assertNotNull(vvInfo);
Assert.assertEquals(vvName, vvInfo.getName());
// Migrate the virtual volume
vvNameBuilder = new StringBuilder(VPlexApiConstants.DIST_DEVICE_PREFIX);
nativeVolumeInfoList.clear();
String migrationVolumeInfo = _properties.getProperty(MIGRATION_VV_INFO_PROP_KEY);
tokenizer = new StringTokenizer(migrationVolumeInfo, "::");
while (tokenizer.hasMoreTokens()) {
String volumeInfo = tokenizer.nextToken();
StringTokenizer volumeInfoTokenizer = new StringTokenizer(volumeInfo, ",");
String systemGuid = volumeInfoTokenizer.nextToken();
String volumeId = volumeInfoTokenizer.nextToken();
String volumeNativeId = volumeInfoTokenizer.nextToken();
nativeVolumeInfoList.add(new VolumeInfo(systemGuid, "vmax", volumeId, volumeNativeId, false, Collections.<String>emptyList()));
vvNameBuilder.append(VPlexApiConstants.DIST_DEVICE_NAME_DELIM);
vvNameBuilder.append(VPlexApiConstants.VOLUME_NAME_PREFIX);
vvNameBuilder.append(systemGuid.substring(systemGuid.indexOf("+") + 1));
vvNameBuilder.append("-");
vvNameBuilder.append(volumeNativeId);
}
vvNameBuilder.append(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX);
String migrationName = _properties.getProperty(MIGRATION_NAME_PROP_KEY);
List<VPlexMigrationInfo> migrationInfoList = _client.migrateVirtualVolume(migrationName, vvName, nativeVolumeInfoList, false, false, false, true, null);
Assert.assertEquals(migrationInfoList.size(), 2);
// Wait until migrations complete and commit the migrations with
// automatic clean and remove.
Thread.sleep(15000);
for (VPlexMigrationInfo migrationInfo : migrationInfoList) {
List<String> migrationNames = new ArrayList<String>();
migrationNames.add(migrationInfo.getName());
List<VPlexMigrationInfo> committedMigrationInfoList = _client.commitMigrations(vvName, migrationNames, true, true, true);
Assert.assertEquals(committedMigrationInfoList.size(), 1);
VPlexMigrationInfo committedMigrationInfo = committedMigrationInfoList.get(0);
vvInfo = committedMigrationInfo.getVirtualVolumeInfo();
vvName = vvInfo.getName();
}
// Clean up the virtual volume. Use the second one as it will have the
// fully update virtual volume name.
Assert.assertEquals(vvNameBuilder.toString(), vvInfo.getName());
_client.deleteVirtualVolume(vvInfo.getName(), true, true);
} catch (Exception e) {
wasException = true;
}
Assert.assertFalse(wasException);
}
use of com.emc.storageos.vplex.api.clientdata.VolumeInfo in project coprhd-controller by CoprHD.
the class VPlexApiTest method testCreateVirtualVolumeDistributed.
/**
* Tests the API createVirtualVolume when multiple storage volumes
* are passed, thereby creating a distributed virtual volume on the
* VPlex.
*/
@Test
public void testCreateVirtualVolumeDistributed() {
boolean wasException = false;
try {
// Create the distributed virtual volume.
StringBuilder vvNameBuilder = new StringBuilder(VPlexApiConstants.DIST_DEVICE_PREFIX);
List<VolumeInfo> nativeVolumeInfoList = new ArrayList<VolumeInfo>();
String distVolumeInfo = _properties.getProperty(DISTRIBUTED_VV_INFO_PROP_KEY);
StringTokenizer tokenizer = new StringTokenizer(distVolumeInfo, "::");
while (tokenizer.hasMoreTokens()) {
String volumeInfo = tokenizer.nextToken();
StringTokenizer volumeInfoTokenizer = new StringTokenizer(volumeInfo, ",");
String systemGuid = volumeInfoTokenizer.nextToken();
String volumeId = volumeInfoTokenizer.nextToken();
String volumeNativeId = volumeInfoTokenizer.nextToken();
nativeVolumeInfoList.add(new VolumeInfo(systemGuid, "vmax", volumeId, volumeNativeId, false, Collections.<String>emptyList()));
vvNameBuilder.append(VPlexApiConstants.DIST_DEVICE_NAME_DELIM);
vvNameBuilder.append(VPlexApiConstants.VOLUME_NAME_PREFIX);
vvNameBuilder.append(systemGuid.substring(systemGuid.indexOf("+") + 1));
vvNameBuilder.append("-");
vvNameBuilder.append(volumeNativeId);
}
vvNameBuilder.append(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX);
List<VPlexClusterInfo> clusterInfoList = _client.getClusterInfoDetails();
VPlexVirtualVolumeInfo vvInfo = _client.createVirtualVolume(nativeVolumeInfoList, true, false, false, "1", clusterInfoList, true, false, true);
Assert.assertNotNull(vvInfo);
Assert.assertEquals(vvNameBuilder.toString(), vvInfo.getName());
// Cleanup
_client.deleteVirtualVolume(vvInfo.getName(), true, false);
} catch (Exception e) {
wasException = true;
}
Assert.assertFalse(wasException);
}
use of com.emc.storageos.vplex.api.clientdata.VolumeInfo in project coprhd-controller by CoprHD.
the class VPlexApiTest method createSimpleVirtualVolume.
/**
* Creates a simple virtual volume from one storage volume.
*
* @return A reference to the VPlexVirtualVolumeInfo.
*
* @throws VPlexApiException When an error occurs creating the virtual volume.
*/
private VPlexVirtualVolumeInfo createSimpleVirtualVolume() throws VPlexApiException {
String volumeInfo = _properties.getProperty(SIMPLE_VV_INFO_PROP_KEY);
StringTokenizer tokenizer = new StringTokenizer(volumeInfo, ",");
String storageSystemGuid = tokenizer.nextToken();
String volumeId = tokenizer.nextToken();
String volumeNativeId = tokenizer.nextToken();
List<VolumeInfo> nativeVolumeInfoList = new ArrayList<VolumeInfo>();
VolumeInfo nativeVolumeInfo = new VolumeInfo(storageSystemGuid, "vmax", volumeId, volumeNativeId, false, Collections.<String>emptyList());
nativeVolumeInfoList.add(nativeVolumeInfo);
List<VPlexClusterInfo> clusterInfoList = _client.getClusterInfoDetails();
VPlexVirtualVolumeInfo vvInfo = _client.createVirtualVolume(nativeVolumeInfoList, false, false, false, null, clusterInfoList, true, false, true);
return vvInfo;
}
Aggregations