/*
* Copyright (c) 2012-2015 iWave Software LLC
* All Rights Reserved
*/
package com.iwave.ext.linux.util;
/**
* Some array types like HDS do not have a mechanism to get the full actual WWN of volumes.
* So the ViPR object may contain a partial WWN instead of a full one. This utility will match
* an actual WWN for a volume from a system against the partial ones in ViPR.
*/
public class VolumeWWNUtils {
public static final int PARTIAL_WWN_LENGTH = 16;
public static final int HUS_VM_PARTIAL_WWN_LENGTH = 12;
public static final int SUFFIX_LENGTH = 4;
public static final int HUS_PREFIX_LENGTH = 4;
public static final int PARTIAL_PREFIX_LENGTH = 5;
public static boolean wwnMatches(String actualWwn, String blockWwn) {
return partialMatch(actualWwn, blockWwn);
}
public static boolean wwnHDSMatches(String actualWwn, String blockWwn) {
String convertedWwn = convertAsciiHDSWwn(actualWwn);
if (convertedWwn == null) {
return false; // convert failed
}
String useableWwn = convertedWwn;
// check if we need to created HUS compatible wwn
if (isHusVmPartialWwn(blockWwn)) {
useableWwn = createHusPartialWwn(convertedWwn); // 12 char long
} else {
useableWwn = createPartialWwn(convertedWwn); // 16 char long
}
return partialMatch(useableWwn, blockWwn);
}
/**
* Converts ascii encoded wwn returned from powerpath to useable wwn
*
* @param wwn from powerpath
* @return converted wwn
*/
private static String convertAsciiHDSWwn(String wwn) {
if (wwn.length() % 2 != 0) {
return null; // can't convert if not an even number
}
StringBuilder output = new StringBuilder();
for (int i = 0; i < wwn.length(); i += 2) {
String str = wwn.substring(i, i + 2);
output.append((char) Integer.parseInt(str, 16));
}
return output.toString();
}
/**
* Create ViPR compatible 12 char wwn
*
* @param wwn to modify
* @return HUS compatible wwn
*/
private static String createHusPartialWwn(String wwn) {
if (wwn.length() < SUFFIX_LENGTH + HUS_PREFIX_LENGTH) {
return wwn; // return original wwn if length not long enough to make partial
}
String prefix = wwn.substring(wwn.length() - (SUFFIX_LENGTH + HUS_PREFIX_LENGTH), wwn.length() - SUFFIX_LENGTH);
String sufix = wwn.substring(wwn.length() - SUFFIX_LENGTH);
return (prefix + "0000" + sufix);
}
/**
* Create ViPR compatible 16 char wwn
*
* @param wwn
* @return HDS compatible 16 char wwn
*/
private static String createPartialWwn(String wwn) {
if (wwn.length() < SUFFIX_LENGTH + PARTIAL_PREFIX_LENGTH) {
return wwn; // return original wwn if length not long enough to make partial
}
String prefix = wwn.substring(wwn.length() - (SUFFIX_LENGTH + PARTIAL_PREFIX_LENGTH), wwn.length() - SUFFIX_LENGTH);
String sufix = wwn.substring(wwn.length() - SUFFIX_LENGTH);
return ("000" + prefix + "0000" + sufix);
}
public static String getPartialWwn(String wwn) {
if (wwn.length() >= PARTIAL_WWN_LENGTH) {
return wwn.substring(wwn.length() - PARTIAL_WWN_LENGTH);
}
return wwn;
}
public static boolean isPartialWwn(String wwn) {
return (wwn.length() == PARTIAL_WWN_LENGTH);
}
public static String getHusVmPartialWwn(String wwn) {
if (wwn.length() >= HUS_VM_PARTIAL_WWN_LENGTH) {
return wwn.substring(wwn.length() - HUS_VM_PARTIAL_WWN_LENGTH);
}
return wwn;
}
public static boolean isHusVmPartialWwn(String wwn) {
return (wwn.length() == HUS_VM_PARTIAL_WWN_LENGTH);
}
/**
* Partial match of two WWNs. The partial string may match the end or middle characters of the full WWN.
*
* @param actual The actual WWN of a volume. Always 32 characters.
* @param partial The partial WWN which must match the end or middle part of the actual.
* @return True if the strings are equal or the partial string is at the end or middle of the actual.
*/
private static boolean partialMatch(String actual, String partial) {
if (actual == null || partial == null) {
return actual == null && partial == null;
}
int actualLength = actual.length();
int partialLength = partial.length();
if (actualLength == partialLength) {
return actual.equalsIgnoreCase(partial);
} else if (actualLength > partialLength) {
if (actual.toLowerCase().endsWith(partial.toLowerCase())) {
return true;
} else if (partialLength == PARTIAL_WWN_LENGTH &&
actual.toLowerCase().contains(partial.toLowerCase())) {
return true;
}
}
// This would only happen is for some reason the partial string was longer
return false;
}
}