
com.vmware.photon.controller.model.adapters.awsadapter.util.AWSBlockDeviceNameMapper Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2018-2019 VMware, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, without warranties or
* conditions of any kind, EITHER EXPRESS OR IMPLIED. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.vmware.photon.controller.model.adapters.awsadapter.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSStorageType;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSStorageType.EBS;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSStorageType.INSTANCE_STORE;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSSupportedOS;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSSupportedOS.LINUX;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSSupportedOS.WINDOWS;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSSupportedVirtualizationTypes;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSSupportedVirtualizationTypes.DEFAULT;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSSupportedVirtualizationTypes.HVM;
import static com.vmware.photon.controller.model.adapters.awsadapter.AWSConstants.AWSSupportedVirtualizationTypes.PARAVIRTUAL;
/**
* Utility class that generates a mapping of block device names as specified by AWS.
*
* @see Device Naming on Linux Instances
* @see Device Naming on Windows Instances
*/
public class AWSBlockDeviceNameMapper {
private static final String DEFAULT_INSTANCE_TYPE = "_default";
private static final Pattern regexPattern = Pattern.compile("(?<=\\[).+?(?=\\])");
private static final Map>>>> OS_STORAGE_TYPE_MAPPINGS = new HashMap<>();
private static final Map> EXPANDED_NAMES = new HashMap<>();
static {
// Linux mappings
addMapping(LINUX,
PARAVIRTUAL,
EBS,
DEFAULT_INSTANCE_TYPE,
Arrays.asList(new String[]{"/dev/sd[f-p]",
"/dev/sd[f-p][1-6]"}));
addMapping(LINUX,
PARAVIRTUAL,
INSTANCE_STORE,
DEFAULT_INSTANCE_TYPE,
Arrays.asList(new String[]{"/dev/sd[b-e]"}));
addMapping(LINUX,
PARAVIRTUAL,
INSTANCE_STORE,
"hs1.8xlarge",
Arrays.asList(new String[]{"/dev/sd[b-y]"}));
addMapping(LINUX,
HVM,
EBS,
DEFAULT_INSTANCE_TYPE,
Arrays.asList(new String[]{"/dev/sd[f-p]"}));
addMapping(LINUX,
HVM,
INSTANCE_STORE,
DEFAULT_INSTANCE_TYPE,
Arrays.asList(new String[]{"/dev/sd[b-e]"}));
addMapping(LINUX,
HVM,
EBS,
"hs1.8xlarge",
Arrays.asList(new String[]{"/dev/sd[b-y]"}));
addMapping(LINUX,
HVM,
EBS,
"d2.8xlarge",
Arrays.asList(new String[]{"/dev/sd[b-y]"}));
addMapping(LINUX,
HVM,
EBS,
"i2.8xlarge",
Arrays.asList(new String[]{"/dev/sd[b-i]"}));
// Windows mappings
addMapping(WINDOWS,
DEFAULT,
EBS,
DEFAULT_INSTANCE_TYPE,
Arrays.asList(new String[]{"xvd[f-p]"}));
addMapping(WINDOWS,
DEFAULT,
INSTANCE_STORE,
DEFAULT_INSTANCE_TYPE,
Arrays.asList(new String[]{"xvd[a-e]"}));
addMapping(WINDOWS,
DEFAULT,
EBS,
"hs1.8xlarge",
Arrays.asList(new String[]{"xvdc[a-x]"}));
}
public static void addMapping(AWSSupportedOS operatingSystem,
AWSSupportedVirtualizationTypes virtualizationType,
AWSStorageType storageType,
String instanceType,
List names) {
instanceType = Optional.ofNullable(instanceType).orElse(DEFAULT_INSTANCE_TYPE);
Map>>> virtualizationMappingsByOS = OS_STORAGE_TYPE_MAPPINGS.getOrDefault(operatingSystem, new HashMap<>());
// add new OS level mapping if absent
OS_STORAGE_TYPE_MAPPINGS.putIfAbsent(operatingSystem, virtualizationMappingsByOS);
Map>> storageTypeMappingsByVirtualization = virtualizationMappingsByOS.getOrDefault(virtualizationType, new HashMap<>());
// add new virtualization mapping (Paravirtual/ HVM) if absent
virtualizationMappingsByOS.putIfAbsent(virtualizationType, storageTypeMappingsByVirtualization);
Map> instanceMappingsByVolumeType =
storageTypeMappingsByVirtualization.getOrDefault(storageType, new HashMap<>());
// add new storage mapping (EBS/ Instance Store) if absent
storageTypeMappingsByVirtualization.putIfAbsent(storageType, instanceMappingsByVolumeType);
// add new name mapping
instanceMappingsByVolumeType.putIfAbsent(instanceType, names);
// cached entries of expanded names for character classes
names.stream().forEach(name -> {
EXPANDED_NAMES.computeIfAbsent(name, AWSBlockDeviceNameMapper::expand);
});
}
/**
* Expands the range : xvd[a-z] -> [xvda, xvdb, xvdc..... xvdz]
*/
private static List expand(String range) {
String prefix = range.substring(0, range.indexOf("["));
String suffix = range.substring(range.lastIndexOf("]") + 1);
List results = Arrays.asList(new String[]{prefix});
Matcher m = regexPattern.matcher(range);
while (m.find()) {
results = cartesian(expandCharacterClass(m.group()), results);
}
return Stream.of(results)
.flatMap(Collection::parallelStream)
.map(x -> x + suffix)
.collect(Collectors.toList());
}
/**
* Expands the regex char class [a-b] into a list [a,b,c..z]
* Expands the regex char class [0-9] into a list [0,1,2..9]
*/
private static List expandCharacterClass(String str) {
List wildcards = new ArrayList<>();
String[] boundaries = str.split("-");
int s = (int) boundaries[0].charAt(0);
int e = (int) boundaries[1].charAt(0);
int total = e - s;
for (int i = 0; i <= total; i++) {
char c = (char) (s + i);
wildcards.add(String.valueOf(c));
}
return wildcards;
}
/**
* listA: [a, b, c]
* listB: [x, y]
* outputs: [ax, ay, bx, by, cx, cy]
*/
private static List cartesian(List listA, final List listB) {
List output = new ArrayList<>();
listA.stream().forEach(w -> {
listB.stream().forEach(r -> {
output.add(r + w);
});
});
return output;
}
/**
* Returns a list of available names
*/
public static List getAvailableNames(AWSSupportedOS operatingSystem,
AWSSupportedVirtualizationTypes virtualizationType,
AWSStorageType storageType,
String instanceType) {
/**
* @see com.amazonaws.services.ec2.model.PlatformValues
* AWS provides the platform value only if its Windows and null otherwise, hence set it to LINUX if its null
*/
if (operatingSystem == null) {
operatingSystem = LINUX;
}
/**
* Presently theres no provision to figure out the Driver PV for Windows Platform
* So if OS = WINDOWS , then set the virtualization to DEFAULT as all mappings are stored for DEFAULT key.
*/
if (operatingSystem == WINDOWS) {
virtualizationType = DEFAULT;
}
List availableNamesPattern = OS_STORAGE_TYPE_MAPPINGS.getOrDefault(operatingSystem, Collections.emptyMap())
.getOrDefault(virtualizationType, Collections.emptyMap())
.getOrDefault(storageType, Collections.emptyMap())
.getOrDefault(instanceType, Collections.emptyList());
if (availableNamesPattern.isEmpty()) {
// no mapping present for the given instanceType hence get the default list.
availableNamesPattern = OS_STORAGE_TYPE_MAPPINGS.getOrDefault(operatingSystem, Collections.emptyMap())
.getOrDefault(virtualizationType, Collections.emptyMap())
.getOrDefault(storageType, Collections.emptyMap())
.getOrDefault(DEFAULT_INSTANCE_TYPE, Collections.emptyList());
}
List availableNames = new ArrayList<>();
availableNamesPattern.forEach(pattern -> {
availableNames.addAll(EXPANDED_NAMES.get(pattern)
.stream()
.collect(Collectors.toList()));
});
return availableNames;
}
/**
* Returns a list of available names which isn't present in the namesToExclude
*/
public static List getAvailableNames(AWSSupportedOS operatingSystem,
AWSSupportedVirtualizationTypes virtualizationType,
AWSStorageType storageType,
String instanceType,
final List namesToExclude) {
List availableNames = getAvailableNames(operatingSystem, virtualizationType, storageType, instanceType);
availableNames.removeAll(namesToExclude);
if (availableNames.isEmpty()) {
throw new RuntimeException("All recommended names are used up");
}
return availableNames;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy