mirror of https://github.com/apache/jclouds.git
Issue 158: implemented listImages and listHardwareProfiles in SoftLayerComputeServiceAdapter. Tidied ProductItemsToHardware and tests
This commit is contained in:
parent
afda717d2f
commit
2f73dbc539
|
@ -20,22 +20,24 @@ package org.jclouds.softlayer.compute.config;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import org.jclouds.compute.ComputeServiceAdapter;
|
||||
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
|
||||
import org.jclouds.softlayer.SoftLayerAsyncClient;
|
||||
import org.jclouds.softlayer.SoftLayerClient;
|
||||
import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
|
||||
import org.jclouds.softlayer.compute.functions.ProductItemsToHardware;
|
||||
import org.jclouds.softlayer.compute.functions.ProductItemToImage;
|
||||
import org.jclouds.softlayer.compute.functions.ProductItemsToHardware;
|
||||
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata;
|
||||
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
|
||||
import org.jclouds.softlayer.domain.Datacenter;
|
||||
import org.jclouds.softlayer.domain.ProductItem;
|
||||
import org.jclouds.softlayer.domain.ProductItemPrice;
|
||||
import org.jclouds.softlayer.domain.VirtualGuest;
|
||||
|
||||
import java.util.Set;
|
||||
|
@ -67,4 +69,12 @@ public class SoftLayerComputeServiceContextModule extends
|
|||
bind(new TypeLiteral<Supplier<Location>>() {})
|
||||
.to(OnlyLocationOrFirstZone.class);
|
||||
}
|
||||
|
||||
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
|
||||
return template.osFamily(OsFamily.UBUNTU)
|
||||
.osVersionMatches("1[10].[10][04]")
|
||||
.os64Bit(true)
|
||||
.osDescriptionMatches(".*Minimal Install.*")
|
||||
.minCores(2);
|
||||
}
|
||||
}
|
|
@ -20,25 +20,22 @@ package org.jclouds.softlayer.compute.functions;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.HardwareBuilder;
|
||||
import org.jclouds.compute.domain.Processor;
|
||||
import org.jclouds.compute.domain.Volume;
|
||||
import org.jclouds.compute.domain.internal.VolumeImpl;
|
||||
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
|
||||
import org.jclouds.softlayer.domain.ProductItem;
|
||||
import org.jclouds.softlayer.domain.ProductItemPrice;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
|
||||
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
|
||||
|
||||
/**
|
||||
* Converts a set of ProductItems to Hardware.
|
||||
|
@ -52,18 +49,17 @@ import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
|
|||
public class ProductItemsToHardware implements Function<Set<ProductItem>, Hardware> {
|
||||
|
||||
private static final double CORE_SPEED = 2.0;
|
||||
private static final Pattern SAN_REGEX = Pattern.compile(".*GB \\(SAN\\).*");
|
||||
|
||||
@Override
|
||||
public Hardware apply(Set<ProductItem> from) {
|
||||
public Hardware apply(Set<ProductItem> items) {
|
||||
|
||||
ProductItem coresItem = getCoresItem(from);
|
||||
ProductItem ramItem = getRamItem(from);
|
||||
ProductItem volumeItem = bootVolume().apply(from);
|
||||
ProductItem coresItem = getOnlyElement(filter(items, units("PRIVATE_CORE")));
|
||||
ProductItem ramItem = getOnlyElement(filter(items, categoryCode("ram")));
|
||||
ProductItem volumeItem = getOnlyElement(filter(items, matches(SoftLayerComputeServiceAdapter.SAN_DESCRIPTION_REGEX)));
|
||||
|
||||
final String hardwareId = hardwareId().apply(ImmutableList.of(coresItem, ramItem, volumeItem));
|
||||
final double cores = getCores(coresItem);
|
||||
final int ram = getRam(ramItem);
|
||||
final double cores = ProductItems.capacity().apply(coresItem).doubleValue();
|
||||
final int ram = ProductItems.capacity().apply(ramItem).intValue();
|
||||
final float volumeSize = ProductItems.capacity().apply(volumeItem);
|
||||
|
||||
return new HardwareBuilder()
|
||||
|
@ -92,48 +88,4 @@ public class ProductItemsToHardware implements Function<Set<ProductItem>, Hardwa
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an item that is usable as the hardware volume (is a SAN)
|
||||
* @return The product item
|
||||
* @throws java.util.NoSuchElementException if the item cannot be found
|
||||
*/
|
||||
public static Function<Set<ProductItem>,ProductItem> bootVolume() {
|
||||
return new Function<Set<ProductItem>,ProductItem>() {
|
||||
@Override
|
||||
public ProductItem apply(Set<ProductItem> productItems) {
|
||||
for(ProductItem item: productItems) {
|
||||
String description = item.getDescription();
|
||||
if (SAN_REGEX.matcher(description).matches()) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
throw new NoSuchElementException("cannot find suitable boot volume item");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ProductItem getCoresItem(Set<ProductItem> from) {
|
||||
Iterable<ProductItem> cpuItems = Iterables.filter(from, units("PRIVATE_CORE"));
|
||||
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
|
||||
assert coresToProductItem.size() == 1 : "Must have 1 cpu product item:"+coresToProductItem;
|
||||
|
||||
return coresToProductItem.entrySet().iterator().next().getValue();
|
||||
}
|
||||
|
||||
private double getCores(ProductItem from) {
|
||||
return ProductItems.capacity().apply(from).doubleValue();
|
||||
}
|
||||
|
||||
private ProductItem getRamItem(Set<ProductItem> from) {
|
||||
Iterable<ProductItem> ramItems = Iterables.filter(from,categoryCode("ram"));
|
||||
Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity());
|
||||
assert ramToProductItem.size() == 1 : "Must have 1 ram product item:"+ramToProductItem;
|
||||
|
||||
return ramToProductItem.entrySet().iterator().next().getValue();
|
||||
}
|
||||
|
||||
private int getRam(ProductItem from) {
|
||||
return ProductItems.capacity().apply(from).intValue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,18 +18,23 @@
|
|||
*/
|
||||
package org.jclouds.softlayer.compute.strategy;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.ComputeServiceAdapter;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.softlayer.SoftLayerClient;
|
||||
import org.jclouds.softlayer.compute.functions.ProductItems;
|
||||
import org.jclouds.softlayer.domain.Datacenter;
|
||||
import org.jclouds.softlayer.domain.ProductItem;
|
||||
import org.jclouds.softlayer.domain.ProductPackage;
|
||||
import org.jclouds.softlayer.domain.VirtualGuest;
|
||||
import org.jclouds.softlayer.predicates.ProductPackagePredicates;
|
||||
import org.jclouds.softlayer.features.AccountClient;
|
||||
import org.jclouds.softlayer.features.ProductPackageClient;
|
||||
import org.jclouds.softlayer.reference.SoftLayerConstants;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -39,6 +44,8 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
|
||||
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
|
||||
|
||||
/**
|
||||
* defines the connection between the {@link SoftLayerClient} implementation and the jclouds
|
||||
|
@ -47,7 +54,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
*/
|
||||
@Singleton
|
||||
public class SoftLayerComputeServiceAdapter implements
|
||||
ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
|
||||
ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
|
||||
|
||||
public static final String SAN_DESCRIPTION_REGEX=".*GB \\(SAN\\).*";
|
||||
//TODO: Better to pass this in as a property like virtualGuestPackageName?
|
||||
private static final Float BOOT_VOLUME_CAPACITY = 100F;
|
||||
|
||||
private final SoftLayerClient client;
|
||||
private final String virtualGuestPackageName;
|
||||
|
||||
|
@ -75,14 +87,36 @@ public class SoftLayerComputeServiceAdapter implements
|
|||
|
||||
@Override
|
||||
public Iterable<Set<ProductItem>> listHardwareProfiles() {
|
||||
// TODO: get the set of product item prices corresponding to the hardware profiles
|
||||
return ImmutableSet.of();
|
||||
ProductPackage productPackage = getProductPackage();
|
||||
Set<ProductItem> items = productPackage.getItems();
|
||||
|
||||
Iterable<ProductItem> cpuItems = Iterables.filter(items, units("PRIVATE_CORE"));
|
||||
Iterable<ProductItem> ramItems = Iterables.filter(items,categoryCode("ram"));
|
||||
Iterable<ProductItem> sanItems = Iterables.filter(items, Predicates.and(matches(SAN_DESCRIPTION_REGEX),categoryCode("one_time_charge")));
|
||||
|
||||
Map<Float, ProductItem> cpuMap = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
|
||||
Map<Float, ProductItem> ramMap = Maps.uniqueIndex(ramItems, ProductItems.capacity());
|
||||
Map<Float, ProductItem> sanMap = Maps.uniqueIndex(sanItems, ProductItems.capacity());
|
||||
|
||||
final ProductItem bootVolume = sanMap.get(BOOT_VOLUME_CAPACITY);
|
||||
assert bootVolume!=null : "Boot volume capacity not found:"+BOOT_VOLUME_CAPACITY+", available:"+sanItems;
|
||||
|
||||
Set<Set<ProductItem>> result = Sets.newLinkedHashSet();
|
||||
for(Map.Entry<Float, ProductItem> coresEntry : cpuMap.entrySet()) {
|
||||
Float cores = coresEntry.getKey();
|
||||
ProductItem ramItem = ramMap.get(cores);
|
||||
//Amount of RAM and number of cores must match.
|
||||
if(ramItem==null) continue;
|
||||
|
||||
result.add(ImmutableSet.of(coresEntry.getValue(),ramItem,bootVolume));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ProductItem> listImages() {
|
||||
// TODO: get the list of product item prices corresponding to images
|
||||
return ImmutableSet.of();
|
||||
return Iterables.filter(getProductPackage().getItems(), categoryCode("os"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,10 +126,15 @@ public class SoftLayerComputeServiceAdapter implements
|
|||
|
||||
@Override
|
||||
public Iterable<Datacenter> listLocations() {
|
||||
// TODO we should be able to specify a filter that gets the datacenters here.
|
||||
ProductPackage virtualGuestPackage = Iterables.find(client.getAccountClient().getActivePackages(),
|
||||
ProductPackagePredicates.named(virtualGuestPackageName));
|
||||
return client.getProductPackageClient().getProductPackage(virtualGuestPackage.getId()).getDatacenters();
|
||||
return getProductPackage().getDatacenters();
|
||||
}
|
||||
|
||||
private ProductPackage getProductPackage() {
|
||||
AccountClient accountClient = client.getAccountClient();
|
||||
ProductPackageClient productPackageClient = client.getProductPackageClient();
|
||||
|
||||
ProductPackage p = Iterables.find(accountClient.getActivePackages(),named(virtualGuestPackageName));
|
||||
return productPackageClient.getProductPackage(p.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,6 +22,8 @@ import com.google.common.base.Predicate;
|
|||
import org.jclouds.softlayer.domain.ProductItem;
|
||||
import org.jclouds.softlayer.domain.ProductItemCategory;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class ProductItemPredicates {
|
||||
|
@ -73,9 +75,8 @@ public class ProductItemPredicates {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Tests if the ProductItem has the required units.
|
||||
* TODO Write test method
|
||||
* @param units
|
||||
* @return true if it does, otherwise false.
|
||||
*/
|
||||
|
@ -94,4 +95,28 @@ public class ProductItemPredicates {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the ProductItem's description matches the supplied regular expression.
|
||||
* @param regex a regular expression to match against.
|
||||
* @return true if it does, otherwise false.
|
||||
* @throws java.util.regex.PatternSyntaxException if the regex is invalid
|
||||
*/
|
||||
public static Predicate<ProductItem> matches(final String regex) {
|
||||
checkNotNull(regex, "regex cannot be null");
|
||||
final Pattern PATTERN = Pattern.compile(regex);
|
||||
|
||||
return new Predicate<ProductItem>() {
|
||||
@Override
|
||||
public boolean apply(ProductItem productItem) {
|
||||
checkNotNull(productItem, "productItem cannot ne null");
|
||||
return PATTERN.matcher(productItem.getDescription()).matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "regex("+regex+")";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@ import org.jclouds.softlayer.domain.ProductItemPrice;
|
|||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import static org.jclouds.softlayer.compute.functions.ProductItemsToHardware.bootVolume;
|
||||
import static org.jclouds.softlayer.compute.functions.ProductItemsToHardware.hardwareId;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
|
||||
|
@ -53,21 +51,6 @@ public class ProductItemsToHardwareTest {
|
|||
assertEquals("123,456,789",id);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBootVolume() {
|
||||
ProductItem item1 = ProductItem.builder().id(1).description("Not a SAN").build();
|
||||
ProductItem item2 = ProductItem.builder().id(2).description("100 GB (SAN)").build();
|
||||
|
||||
ProductItem found = bootVolume().apply(ImmutableSet.of(item1,item2));
|
||||
assertEquals(item2,found);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NoSuchElementException.class)
|
||||
public void testBootVolumeMissing() {
|
||||
ProductItem item1 = ProductItem.builder().id(1).description("Not a SAN").build();
|
||||
bootVolume().apply(ImmutableSet.of(item1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHardware() {
|
||||
ProductItem cpuItem = ProductItem.builder()
|
||||
|
|
|
@ -38,6 +38,7 @@ public class ProductItemPredicatesTest {
|
|||
ramCategory = ProductItemCategory.builder().id(1).categoryCode("ram").build();
|
||||
|
||||
item = ProductItem.builder().id(1)
|
||||
.description("a test item")
|
||||
.categories(ImmutableSet.of(ramCategory))
|
||||
.capacity(2.0f)
|
||||
.units("GB")
|
||||
|
@ -88,4 +89,14 @@ public class ProductItemPredicatesTest {
|
|||
public void testUnitsMissing() {
|
||||
assertFalse(ProductItemPredicates.units("Kg").apply(item));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesRegex() {
|
||||
assert ProductItemPredicates.matches(".*test.*").apply(item);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoMatchRegex() {
|
||||
assertFalse(ProductItemPredicates.matches("no match").apply(item));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue