package org.zstack.header.volume;
import org.zstack.header.exception.CloudRuntimeException;
import org.zstack.header.host.HypervisorType;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.function.Function;
import org.zstack.utils.logging.CLogger;
import java.util.*;
/**
*/
public class VolumeFormat {
private static final CLogger logger = Utils.getLogger(VolumeFormat.class);
private static Map<String, VolumeFormat> types = Collections.synchronizedMap(new HashMap<String, VolumeFormat>());
private final String typeName;
private final HypervisorType masterHypervisorType;
private final List<HypervisorType> attachableHypervisorTypes = new ArrayList<HypervisorType>();
private final Map<HypervisorType, Map<String, String>> inputOuputFormatsMap = new HashMap<HypervisorType, Map<String, String>>();
private boolean exposed = true;
private HypervisorType firstChoice;
public static Collection<VolumeFormat> getAllFormats() {
HashSet<VolumeFormat> exposedFormats = new HashSet<VolumeFormat>();
for (VolumeFormat format : types.values()) {
if (format.isExposed()) {
exposedFormats.add(format);
}
}
return exposedFormats;
}
public HypervisorType getFirstChoice() {
return firstChoice;
}
public void setFirstChoice(HypervisorType firstChoice) {
this.firstChoice = firstChoice;
}
public boolean isExposed() {
return exposed;
}
public void setExposed(boolean exposed) {
this.exposed = exposed;
}
public VolumeFormat(String typeName, HypervisorType master, HypervisorType... attachables) {
this.typeName = typeName;
types.put(typeName, this);
masterHypervisorType = master;
Collections.addAll(attachableHypervisorTypes, attachables);
logger.debug(String.format("volume format[%s] registers itself with master hypervisor type[%s] and attachable hypervisor types%s", typeName, masterHypervisorType, attachableHypervisorTypes));
}
public VolumeFormat(String typeName, HypervisorType master, boolean exposed, HypervisorType... attachables) {
this(typeName, master, attachables);
this.exposed = exposed;
}
public static boolean hasType(String type) {
return types.keySet().contains(type);
}
public static VolumeFormat valueOf(String typeName) {
VolumeFormat type = types.get(typeName);
if (type == null) {
throw new IllegalArgumentException(String.format("cannot find VolumeFormat[%s]", typeName));
}
return type;
}
@Override
public String toString() {
return typeName;
}
@Override
public boolean equals(Object t) {
if (t == null || !(t instanceof VolumeFormat)) {
return false;
}
VolumeFormat type = (VolumeFormat) t;
return type.toString().equals(typeName);
}
@Override
public int hashCode() {
return typeName.hashCode();
}
public static Set<String> getAllTypeNames() {
return types.keySet();
}
public HypervisorType getMasterHypervisorType() {
return masterHypervisorType;
}
public List<HypervisorType> getAttachableHypervisorTypes() {
return attachableHypervisorTypes;
}
public static HypervisorType getMasterHypervisorTypeByVolumeFormat(String volumeFormat) {
VolumeFormat f = VolumeFormat.valueOf(volumeFormat);
return f.getMasterHypervisorType();
}
public static VolumeFormat getVolumeFormatByMasterHypervisorType(String hvType) {
for (VolumeFormat f : types.values()) {
if (f.getFirstChoice() != null && f.getFirstChoice().toString().equals(hvType)) {
return f;
}
}
for (VolumeFormat f : types.values()) {
if (f.getMasterHypervisorType() != null && f.getMasterHypervisorType().toString().equals(hvType)) {
return f;
}
}
throw new CloudRuntimeException(String.format("cannot find volume format which has master hypervisor type[%s]", hvType));
}
public List<String> getHypervisorTypesSupportingThisVolumeFormatInString() {
return CollectionUtils.transformToList(getHypervisorTypesSupportingThisVolumeFormat(), new Function<String, HypervisorType>() {
@Override
public String call(HypervisorType arg) {
return arg.toString();
}
});
}
public List<HypervisorType> getHypervisorTypesSupportingThisVolumeFormat() {
List<HypervisorType> hvTypes = new ArrayList<HypervisorType>();
if (masterHypervisorType != null) {
hvTypes.add(masterHypervisorType);
}
hvTypes.addAll(attachableHypervisorTypes);
return hvTypes;
}
public static List<VolumeFormat> getVolumeFormatSupportedByHypervisorType(HypervisorType hvType) {
List<VolumeFormat> formats = new ArrayList<VolumeFormat>();
for (VolumeFormat format : types.values()) {
if (hvType.equals(format.getMasterHypervisorType()) || format.getAttachableHypervisorTypes().contains(hvType)) {
formats.add(format);
}
}
return formats;
}
public static List<VolumeFormat> getVolumeFormatSupportedByHypervisorType(String hvType) {
return getVolumeFormatSupportedByHypervisorType(HypervisorType.valueOf(hvType));
}
public static List<String> getVolumeFormatSupportedByHypervisorTypeInString(HypervisorType hvType) {
return CollectionUtils.transformToList(getVolumeFormatSupportedByHypervisorType(hvType), new Function<String, VolumeFormat>() {
@Override
public String call(VolumeFormat arg) {
return arg.toString();
}
});
}
public static List<String> getVolumeFormatSupportedByHypervisorTypeInString(String hvType) {
return getVolumeFormatSupportedByHypervisorTypeInString(HypervisorType.valueOf(hvType));
}
public void newFormatInputOutputMapping(HypervisorType hvType, String output) {
Map<String, String> io = inputOuputFormatsMap.get(hvType);
if (io == null) {
io = new HashMap<String, String>();
inputOuputFormatsMap.put(hvType, io);
}
io.put(toString(), output);
}
public String getOutputFormat(String hvType) {
return getOutputFormat(HypervisorType.valueOf(hvType));
}
public String getOutputFormat(HypervisorType hvType) {
Map<String, String> io = inputOuputFormatsMap.get(hvType);
if (io == null) {
return toString();
}
String output = io.get(toString());
return output == null ? toString() : output;
}
}