/* * Copyright (c) 2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.vplex.api; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import com.emc.storageos.services.util.EnvConfig; import com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo.WaitOnRebuildResult; import com.emc.storageos.vplex.api.clientdata.PortInfo; import com.emc.storageos.vplex.api.clientdata.VolumeInfo; /** * Test client for VPlex API. */ public class VPlexApiTest { // Properties file name private static final String PROP_FILE_NAME = "/com/emc/storageos/vplex/api/VPlexApiTest.properties"; // Properties file for vplex credentials. private static final String UNIT_TEST_CONFIG_FILE = "sanity"; // Property keys private static final String VPLEX_VERSION_KEY = "VPLEX_VERSION"; private static final String VPLEX_PROVIDER_IP = EnvConfig.get(UNIT_TEST_CONFIG_FILE, "vplex.host.ipaddress"); private static final String VPLEX_PROVIDER_PORT = EnvConfig.get(UNIT_TEST_CONFIG_FILE, "vplex.host.port"); private static final String VPLEX_PROVIDER_USER = EnvConfig.get(UNIT_TEST_CONFIG_FILE, "vplex.host.username"); private static final String VPLEX_PROVIDER_PWD = EnvConfig.get(UNIT_TEST_CONFIG_FILE, "vplex.host.password"); private static final String CONNECTED_SYSTEMS_PROP_KEY = "CONNECTED_SYSTEMS"; private static final String SIMPLE_VV_INFO_PROP_KEY = "SIMPLE_VIRTUAL_VOLUME_TEST"; private static final String DISTRIBUTED_VV_INFO_PROP_KEY = "DISTRIBUTED_VIRTUAL_VOLUME_TEST"; private static final String STORAGE_VIEW_TARGETS_PROP_KEY = "STORAGE_VIEW_TARGETS"; private static final String STORAGE_VIEW_INITIATORS_PROP_KEY = "STORAGE_VIEW_INITIATORS"; private static final String STORAGE_VIEW_NAME_PROP_KEY = "STORAGE_VIEW_NAME"; private static final String MIGRATION_VV_INFO_PROP_KEY = "MIGRATION_VIRTUAL_VOLUME_TEST"; private static final String SIMPLE_MIGRATION_VV_INFO_PROP_KEY = "SIMPLE_MIGRATION_VIRTUAL_VOLUME_TEST"; private static final String MIGRATION_NAME_PROP_KEY = "MIGRATION_NAME"; private static final String DEVICE_MIRROR_TEST_VOLUME_PROP_KEY = "DEVICE_MIRROR_TEST_VOLUME"; private static final String VPLEX_TEST_CLUSTER = "cluster-1"; // The configuration properties for the test. private static Properties _properties = new Properties(); // Factory used to create and manage client connections; private static volatile VPlexApiFactory _apiFactory = null; // The VPlex API client used to make http requests to the VPlex. private static volatile VPlexApiClient _client = null; // The native guids for the arrays attached to the VPlex private static final List<String> _attachedStorageSystems = new ArrayList<String>(); /** * Setup is called once before tests are executed. Loads the test properties, * creates the VPlex API factory, and creates the VPlex API client connection to * the VPlex management server specified in the test properties file. * * @throws Exception When test setup fails. */ @BeforeClass public static void setup() throws Exception { try { // Load test properties. _properties.load(VPlexApiTest.class.getResourceAsStream(PROP_FILE_NAME)); // Create API factory. _apiFactory = VPlexApiFactory.getInstance(); // Get the Http API client. URI vplexEndpointURI = new URI("https", null, VPLEX_PROVIDER_IP, Integer.parseInt(VPLEX_PROVIDER_PORT), "/", null, null); _client = _apiFactory.getClient(vplexEndpointURI, _properties.getProperty(VPLEX_PROVIDER_USER), _properties.getProperty(VPLEX_PROVIDER_PWD)); // Setup the list of storage systems attached to the VPlex. String connectedStorageSystemInfo = _properties .getProperty(CONNECTED_SYSTEMS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(connectedStorageSystemInfo, ","); while (tokenizer.hasMoreTokens()) { String storageSystemGuid = tokenizer.nextToken(); _attachedStorageSystems.add(storageSystemGuid); } } catch (Exception e) { System.out.println("Failed setup: " + e.getMessage()); Assert.assertTrue(false); } } /** * Tests the virtual volume deep discovery */ @Test public void testGetVirtualVolumes() { boolean wasException = false; try { double start = System.currentTimeMillis(); Map<String, VPlexVirtualVolumeInfo> volumesMap = _client.getVirtualVolumes(false); double end = System.currentTimeMillis(); double duration = (end - start) / 1000; double timePerVolume = duration / volumesMap.size(); double projected = (timePerVolume * 5000) / 60; System.out.printf("Number of volumes found: %d%n", volumesMap.size()); System.out.printf("Virtual volume deep discovery time (s): %.2f%n", duration); System.out.printf("Average per volume (s): %.5f%n", timePerVolume); System.out.printf("Projected Time for 5000 volumes (m): %.2f%n", projected); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the virtual volume deep discovery */ @Test public void testGetConsistencyGroups() { boolean wasException = false; try { List<VPlexConsistencyGroupInfo> cgInfoList = _client.getConsistencyGroups(); for (VPlexConsistencyGroupInfo cgInfo : cgInfoList) { System.out.println(cgInfo.toString()); } } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API getStorageSystemInfo, which gets the information about the * backend storage systems connected to the VPlex. */ @Test public void testGetManagementSoftwareVersion() { boolean wasException = false; try { String supportedVersion = _properties.getProperty(VPLEX_VERSION_KEY); String vplexVersion = _client.getManagementSoftwareVersion(); Assert.assertEquals(supportedVersion, vplexVersion); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API getStorageSystemInfo, which gets the information about the * backend storage systems connected to the VPlex. */ @Test public void testGetStorageSystemInfo() { boolean wasException = false; try { List<VPlexStorageSystemInfo> storageSystemInfoList = _client .getStorageSystemInfo(); Assert.assertTrue(storageSystemInfoList.size() == _attachedStorageSystems .size()); for (VPlexStorageSystemInfo storageSystemInfo : storageSystemInfoList) { boolean foundAMatch = false; for (String nativeGuid : _attachedStorageSystems) { if (storageSystemInfo.matches(nativeGuid)) { foundAMatch = true; break; } } Assert.assertTrue(foundAMatch); } } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API getPortInfo, which gets the information about the * director ports in the VPlex engines. */ @Test public void testGetPortInfo() { boolean wasException = false; try { List<VPlexPortInfo> portInfoList = _client.getPortInfo(false); Integer totalPorts = 0; List<String> directorList = new ArrayList<String>(); for (VPlexPortInfo portInfo : portInfoList) { VPlexDirectorInfo directorInfo = portInfo.getDirectorInfo(); if (!directorList.contains(directorInfo.getName())) { totalPorts += directorInfo.getPortInfo().size(); directorList.add(directorInfo.getName()); } } Assert.assertTrue(portInfoList.size() == totalPorts); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API rediscoverStorageSystems. Test sleeps a bit at the end * to ensure the rediscover call does not interfere with subsequent tests. * * @throws InterruptedException If an error occurs during the sleep. */ @Test public void testRediscoverStorageSystems() throws InterruptedException { boolean wasException = false; try { List<VPlexStorageSystemInfo> storageSystemInfoList = _client .getStorageSystemInfo(); Assert.assertTrue(!storageSystemInfoList.isEmpty()); List<String> storageSystemNativeGuids = new ArrayList<String>(); for (VPlexStorageSystemInfo storageSystemInfo : storageSystemInfoList) { storageSystemNativeGuids.add(storageSystemInfo.getUniqueId()); } _client.rediscoverStorageSystems(storageSystemNativeGuids); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); // Let rediscover finish, which can interfere with subsequent tests. Thread.sleep(2000); } /** * Tests the API createVirtualVolume when only a single storage volume * is passed, thereby creating a simple virtual volume on one cluster * of the VPlex. */ @Test public void testCreateVirtualVolumeSimple() { boolean wasException = false; try { // Create the virtual volume. String volumeInfo = _properties.getProperty(SIMPLE_VV_INFO_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(volumeInfo, ","); String systemGuid = tokenizer.nextToken(); tokenizer.nextToken(); String volumeNativeId = tokenizer.nextToken(); VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume(); Assert.assertNotNull(vvInfo); StringBuilder builder = new StringBuilder(); builder.append(VPlexApiConstants.DEVICE_PREFIX); builder.append(VPlexApiConstants.VOLUME_NAME_PREFIX); builder.append(systemGuid.substring(systemGuid.indexOf("+") + 1)); builder.append("-"); builder.append(volumeNativeId); builder.append(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX); Assert.assertEquals(builder.toString(), vvInfo.getName()); // Cleanup _client.deleteVirtualVolume(vvInfo.getName(), true, false); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * 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); } /** * Tests the API createStorageView when the view name is not specified. */ @Test public void testCreateStorageViewNoViewName() { // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Test with a null view name. boolean wasException = false; try { Assert.assertTrue(!targetPortInfoList.isEmpty()); _client.createStorageView(null, targetPortInfoList, null, null); } catch (VPlexApiException vae) { wasException = true; } Assert.assertTrue(wasException); // Test with a blank view name. wasException = false; try { Assert.assertTrue(!targetPortInfoList.isEmpty()); _client.createStorageView("", targetPortInfoList, null, null); } catch (VPlexApiException vae) { wasException = true; } Assert.assertTrue(wasException); // Test with a view name consisting only of white space. wasException = false; try { Assert.assertTrue(!targetPortInfoList.isEmpty()); _client.createStorageView(" ", targetPortInfoList, null, null); } catch (VPlexApiException vae) { wasException = true; } Assert.assertTrue(wasException); } /** * Tests the API createStorageView when no targets are specified. */ @Test public void testCreateStorageViewNoTargets() { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Test with a null view name. boolean wasException = false; try { Assert.assertNotNull(storageViewName); Assert.assertTrue(storageViewName.trim().length() != 0); _client.createStorageView(storageViewName, new ArrayList<PortInfo>(), null, null); } catch (VPlexApiException vae) { wasException = true; } Assert.assertTrue(wasException); } /** * Tests the API createStorageView when only a target ports are passed * in the request. */ @Test public void testCreateStorageViewTargetsOnly() { boolean wasException = false; try { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Create the storage view VPlexStorageViewInfo storageViewInfo = _client.createStorageView( storageViewName, targetPortInfoList, null, null); Assert.assertNotNull(storageViewInfo); Assert.assertEquals(storageViewInfo.getName(), storageViewName); // Cleanup Boolean[] viewFound = new Boolean[] { new Boolean(false) }; _client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API createStorageView when both target ports and virtual * volumes are passed in the request. */ @Test public void testCreateStorageViewWithVolumes() { boolean wasException = false; try { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Create the virtual volume. VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume(); Assert.assertNotNull(vvInfo); Map<String, Integer> vvMap = new HashMap<String, Integer>(); vvMap.put(vvInfo.getName(), Integer.valueOf(VPlexApiConstants.LUN_UNASSIGNED)); // Create the storage view VPlexStorageViewInfo storageViewInfo = _client.createStorageView( storageViewName, targetPortInfoList, null, vvMap); Assert.assertNotNull(storageViewInfo); Assert.assertEquals(storageViewInfo.getName(), storageViewName); // Cleanup Boolean[] viewFound = new Boolean[] { new Boolean(false) }; _client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound); _client.deleteVirtualVolume(vvInfo.getName(), true, false); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API createStorageView when target ports, initiator ports, and * virtual volumes are passed in the request. */ @Test public void testCreateStorageViewWithInitiatorsAndVolumes() { boolean wasException = false; try { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Get the initiator ports List<PortInfo> initiatorPortInfoList = new ArrayList<PortInfo>(); String storageViewInitiatorsStr = _properties .getProperty(STORAGE_VIEW_INITIATORS_PROP_KEY); tokenizer = new StringTokenizer(storageViewInitiatorsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo initiatorPortInfo = new PortInfo(portWWN); initiatorPortInfoList.add(initiatorPortInfo); } // Create the virtual volume. VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume(); Assert.assertNotNull(vvInfo); Map<String, Integer> vvMap = new HashMap<String, Integer>(); vvMap.put(vvInfo.getName(), Integer.valueOf(VPlexApiConstants.LUN_UNASSIGNED)); // Create the storage view VPlexStorageViewInfo storageViewInfo = _client.createStorageView( storageViewName, targetPortInfoList, initiatorPortInfoList, vvMap); Assert.assertNotNull(storageViewInfo); Assert.assertEquals(storageViewInfo.getName(), storageViewName); // Cleanup Boolean[] viewFound = new Boolean[] { new Boolean(false) }; _client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound); _client.deleteVirtualVolume(vvInfo.getName(), true, false); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API addVirtualVolumesToStorageView. */ @Test public void testAddVirtualVolumesToStorageView() { boolean wasException = false; try { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Create the storage view VPlexStorageViewInfo storageViewInfo = _client.createStorageView( storageViewName, targetPortInfoList, null, null); Assert.assertNotNull(storageViewInfo); Assert.assertEquals(storageViewInfo.getName(), storageViewName); // Create a virtual volume. VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume(); Assert.assertNotNull(vvInfo); Map<String, Integer> vvMap = new HashMap<String, Integer>(); vvMap.put(vvInfo.getName(), Integer.valueOf(VPlexApiConstants.LUN_UNASSIGNED)); // Add the virtual volume to the storage view. _client.addVirtualVolumesToStorageView(storageViewName, VPLEX_TEST_CLUSTER, vvMap); // Cleanup Boolean[] viewFound = new Boolean[] { new Boolean(false) }; _client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound); _client.deleteVirtualVolume(vvInfo.getName(), true, false); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API removeVirtualVolumesFromStorageView. */ @Test public void testRemoveVirtualVolumesFromStorageView() { boolean wasException = false; try { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Create the virtual volume. VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume(); Assert.assertNotNull(vvInfo); Map<String, Integer> vvMap = new HashMap<String, Integer>(); vvMap.put(vvInfo.getName(), Integer.valueOf(VPlexApiConstants.LUN_UNASSIGNED)); // Create the storage view VPlexStorageViewInfo storageViewInfo = _client.createStorageView( storageViewName, targetPortInfoList, null, vvMap); Assert.assertNotNull(storageViewInfo); Assert.assertEquals(storageViewInfo.getName(), storageViewName); // Remove the virtual volume from the storage view. List<String> vvNames = new ArrayList<String>(); vvNames.addAll(vvMap.keySet()); _client.removeVirtualVolumesFromStorageView(storageViewName, VPLEX_TEST_CLUSTER, vvNames); // Cleanup Boolean[] viewFound = new Boolean[] { new Boolean(false) }; _client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound); _client.deleteVirtualVolume(vvInfo.getName(), true, false); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API addInitiatorsToStorageView. */ @Test public void testAddInitiatorsToStorageView() { boolean wasException = false; try { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Create the storage view VPlexStorageViewInfo storageViewInfo = _client.createStorageView( storageViewName, targetPortInfoList, null, null); Assert.assertNotNull(storageViewInfo); Assert.assertEquals(storageViewInfo.getName(), storageViewName); // Get the initiator ports List<PortInfo> initiatorPortInfoList = new ArrayList<PortInfo>(); String storageViewInitiatorsStr = _properties .getProperty(STORAGE_VIEW_INITIATORS_PROP_KEY); tokenizer = new StringTokenizer(storageViewInitiatorsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo initiatorPortInfo = new PortInfo(portWWN); initiatorPortInfoList.add(initiatorPortInfo); } // Add the initiators to the storage view. _client.addInitiatorsToStorageView(storageViewName, VPLEX_TEST_CLUSTER, initiatorPortInfoList); // Cleanup Boolean[] viewFound = new Boolean[] { new Boolean(false) }; _client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API removeInitiatorFromStorageView. */ @Test public void testRemoveInitiatorsFromStorageView() { boolean wasException = false; try { // Get the storage view name String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY); // Get the target ports List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>(); String storageViewTargetsStr = _properties .getProperty(STORAGE_VIEW_TARGETS_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo targetPortInfo = new PortInfo(portWWN); targetPortInfoList.add(targetPortInfo); } // Get the initiator ports List<PortInfo> initiatorPortInfoList = new ArrayList<PortInfo>(); String storageViewInitiatorsStr = _properties .getProperty(STORAGE_VIEW_INITIATORS_PROP_KEY); tokenizer = new StringTokenizer(storageViewInitiatorsStr, ","); while (tokenizer.hasMoreTokens()) { String portWWN = tokenizer.nextToken(); PortInfo initiatorPortInfo = new PortInfo(portWWN); initiatorPortInfoList.add(initiatorPortInfo); } // Create the storage view VPlexStorageViewInfo storageViewInfo = _client.createStorageView( storageViewName, targetPortInfoList, initiatorPortInfoList, null); Assert.assertNotNull(storageViewInfo); Assert.assertEquals(storageViewInfo.getName(), storageViewName); // Remove the initiators from the storage view. _client.removeInitiatorsFromStorageView(storageViewName, VPLEX_TEST_CLUSTER, initiatorPortInfoList); // Cleanup Boolean[] viewFound = new Boolean[] { new Boolean(false) }; _client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * Tests the API migrateVirtualVolume for a simple virtual volume. */ @Test public void testMigrateVirtualVolumeSimple() { boolean wasException = false; try { // Create the simple virtual volume. // Create the virtual volume. String volumeInfo = _properties.getProperty(SIMPLE_VV_INFO_PROP_KEY); StringTokenizer tokenizer = new StringTokenizer(volumeInfo, ","); String systemGuid = tokenizer.nextToken(); tokenizer.nextToken(); String volumeNativeId = tokenizer.nextToken(); VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume(); Assert.assertNotNull(vvInfo); StringBuilder vvNameBuilder = new StringBuilder(); vvNameBuilder.append(VPlexApiConstants.DEVICE_PREFIX); 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(); Assert.assertEquals(vvName, vvInfo.getName()); // Migrate the virtual volume List<VolumeInfo> nativeVolumeInfoList = new ArrayList<VolumeInfo>(); String migrationVolumeInfo = _properties .getProperty(SIMPLE_MIGRATION_VV_INFO_PROP_KEY); StringTokenizer volumeInfoTokenizer = new StringTokenizer(migrationVolumeInfo, ","); systemGuid = volumeInfoTokenizer.nextToken(); String volumeId = volumeInfoTokenizer.nextToken(); volumeNativeId = volumeInfoTokenizer.nextToken(); nativeVolumeInfoList.add(new VolumeInfo(systemGuid, "vmax", volumeId, volumeNativeId, false, Collections.<String> emptyList())); vvNameBuilder = new StringBuilder(); vvNameBuilder.append(VPlexApiConstants.DEVICE_PREFIX); 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(), 1); // Wait until migrations complete and commit the migrations with // automatic clean and remove. Thread.sleep(15000); List<String> migrationNames = new ArrayList<String>(); for (VPlexMigrationInfo migrationInfo : migrationInfoList) { migrationNames.add(migrationInfo.getName()); } migrationInfoList = _client.commitMigrations(vvName, migrationNames, true, true, true); Assert.assertEquals(migrationInfoList.size(), 1); // Clean up the virtual volume. vvInfo = migrationInfoList.get(0).getVirtualVolumeInfo(); Assert.assertEquals(vvNameBuilder.toString(), vvInfo.getName()); _client.deleteVirtualVolume(vvInfo.getName(), true, false); } catch (Exception e) { wasException = true; } Assert.assertFalse(wasException); } /** * 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); } /* * 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()); } } } /** * 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; } }