Search in sources :

Example 21 with VolumeInfo

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;
    }
}
Also used : ArrayList(java.util.ArrayList) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo)

Example 22 with VolumeInfo

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());
        }
    }
}
Also used : StringTokenizer(java.util.StringTokenizer) WaitOnRebuildResult(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo.WaitOnRebuildResult) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) Test(org.junit.Test)

Example 23 with VolumeInfo

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);
}
Also used : ArrayList(java.util.ArrayList) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) StringTokenizer(java.util.StringTokenizer) Test(org.junit.Test)

Example 24 with VolumeInfo

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);
}
Also used : StringTokenizer(java.util.StringTokenizer) ArrayList(java.util.ArrayList) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo) Test(org.junit.Test)

Example 25 with VolumeInfo

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;
}
Also used : StringTokenizer(java.util.StringTokenizer) ArrayList(java.util.ArrayList) VolumeInfo(com.emc.storageos.vplex.api.clientdata.VolumeInfo)

Aggregations

VolumeInfo (com.emc.storageos.vplex.api.clientdata.VolumeInfo)25 ArrayList (java.util.ArrayList)18 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)11 VPlexVirtualVolumeInfo (com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo)11 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)10 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)9 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)9 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)9 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)9 ControllerException (com.emc.storageos.volumecontroller.ControllerException)9 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)9 WorkflowException (com.emc.storageos.workflow.WorkflowException)9 IOException (java.io.IOException)9 URISyntaxException (java.net.URISyntaxException)9 Volume (com.emc.storageos.db.client.model.Volume)8 URI (java.net.URI)8 NamedURI (com.emc.storageos.db.client.model.NamedURI)6 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)6 HashMap (java.util.HashMap)6 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)4