adjusted defaults to allow smallest softlayer size; parameterized configuration; fixed state where guest without billing item was permitted

This commit is contained in:
Adrian Cole 2011-10-03 22:36:39 -07:00
parent 007ebc693e
commit d5e130ab3c
16 changed files with 861 additions and 511 deletions

View File

@ -21,11 +21,20 @@ package org.jclouds.softlayer;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
import org.jclouds.softlayer.reference.SoftLayerConstants;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/**
* Builds properties used in SoftLayer Clients
@ -38,9 +47,28 @@ public class SoftLayerPropertiesBuilder extends PropertiesBuilder {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_ENDPOINT, "https://api.softlayer.com/rest");
properties.setProperty(PROPERTY_API_VERSION, "3");
properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME, "Cloud Server");
properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY, ""+60*60*1000);
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY, "" + 60 * 60 * 1000);
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME, "Cloud Server");
// ex: for private (ex. don't share hardware) use "Private [0-9]+ x ([.0-9]+) GHz Core[s]?"
// ex: for private and public use ".*[0-9]+ x ([.0-9]+) GHz Core[s]?"
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX, "[0-9]+ x ([0-9.]+) GHz Core[s]?");
// SAN or LOCAL
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE, "LOCAL");
// 10, 100, 1000
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED, "10");
properties.setProperty(PROPERTY_ISO3166_CODES, "SG,US-CA,US-TX,US-VA,US-WA,US-TX");
Builder<String> prices = ImmutableSet.<String> builder();
prices.add("21"); // 1 IP Address
prices.add("55"); // Host Ping: categoryCode: monitoring, notification
prices.add("57"); // Email and Ticket: categoryCode: notification
prices.add("58"); // Automated Notification: categoryCode: response
prices.add("1800"); // 0 GB Bandwidth: categoryCode: bandwidth
prices.add("905"); // Reboot / Remote Console: categoryCode: remote_management
prices.add("418"); // Nessus Vulnerability Assessment & Reporting: categoryCode:
// vulnerability_scanner
prices.add("420"); // Unlimited SSL VPN Users & 1 PPTP VPN User per account: categoryCode:
// vpn_management
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES, Joiner.on(',').join(prices.build()));
return properties;
}

View File

@ -18,8 +18,17 @@
*/
package org.jclouds.softlayer.compute.config;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata;
@ -28,6 +37,7 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
@ -38,19 +48,27 @@ import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
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.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.features.AccountClient;
import org.jclouds.softlayer.features.ProductPackageClient;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
public class SoftLayerComputeServiceContextModule extends
ComputeServiceAdapterContextModule<SoftLayerClient, SoftLayerAsyncClient, VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
public class SoftLayerComputeServiceContextModule
extends
ComputeServiceAdapterContextModule<SoftLayerClient, SoftLayerAsyncClient, VirtualGuest, Iterable<ProductItem>, ProductItem, Datacenter> {
public SoftLayerComputeServiceContextModule() {
super(SoftLayerClient.class, SoftLayerAsyncClient.class);
@ -59,26 +77,59 @@ public class SoftLayerComputeServiceContextModule extends
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter>>() {})
.to(SoftLayerComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {})
.to(VirtualGuestToNodeMetadata.class);
bind(new TypeLiteral<Function<ProductItem, org.jclouds.compute.domain.Image>>() {})
.to(ProductItemToImage.class);
bind(new TypeLiteral<Function<Set<ProductItem>, org.jclouds.compute.domain.Hardware>>() {})
.to(ProductItemsToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>() {})
.to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {})
.to(OnlyLocationOrFirstZone.class);
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Iterable<ProductItem>, ProductItem, Datacenter>>() {
}).to(SoftLayerComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {
}).to(VirtualGuestToNodeMetadata.class);
bind(new TypeLiteral<Function<ProductItem, org.jclouds.compute.domain.Image>>() {
}).to(ProductItemToImage.class);
bind(new TypeLiteral<Function<Iterable<ProductItem>, org.jclouds.compute.domain.Hardware>>() {
}).to(ProductItemsToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>() {
}).to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
bind(TemplateOptions.class).to(SoftLayerTemplateOptions.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);
return template.osFamily(OsFamily.UBUNTU).osVersionMatches("1[10].[10][04]").os64Bit(true).osDescriptionMatches(
".*Minimal Install.*");
}
}
/**
* Many requests need the same productPackage, which is in this case the package for virtual
* guests. We may at some point need to make an annotation qualifying it as such. ex. @VirtualGuest
*/
@Provides
@Singleton
@Memoized
public Supplier<ProductPackage> getProductPackage(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final SoftLayerClient client,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) final String virtualGuestPackageName) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<ProductPackage>(authException, seconds,
new Supplier<ProductPackage>() {
@Override
public ProductPackage get() {
AccountClient accountClient = client.getAccountClient();
ProductPackageClient productPackageClient = client.getProductPackageClient();
ProductPackage p = find(accountClient.getActivePackages(), named(virtualGuestPackageName));
return productPackageClient.getProductPackage(p.getId());
}
});
}
// TODO: check the prices really do exist
@Provides
@Singleton
public Iterable<ProductItemPrice> prices(@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES) String prices) {
return Iterables.transform(Splitter.on(',').split(checkNotNull(prices, "prices")),
new Function<String, ProductItemPrice>() {
@Override
public ProductItemPrice apply(String arg0) {
return ProductItemPrice.builder().id(Integer.parseInt(arg0)).build();
}
});
}
}

View File

@ -29,63 +29,63 @@ import java.util.Set;
public class ProductItems {
/**
* Creates a function to get the capacity from a product item.
*/
public static Function<ProductItem,Float> capacity() {
return new Function<ProductItem,Float>() {
@Override
public Float apply(ProductItem productItem) {
return productItem.getCapacity();
}
};
}
/**
* Creates a function to get the description from a product item.
*/
public static Function<ProductItem,String> description() {
return new Function<ProductItem,String>() {
@Override
public String apply(ProductItem productItem) {
return productItem.getDescription();
}
};
}
/**
* Creates a function to get the ProductItemPrice for the ProductItem.
* Currently returns the first price.
* This will need to be changed if more than one price is returned.
*/
public static Function<ProductItem,ProductItemPrice> price() {
return new Function<ProductItem,ProductItemPrice>() {
@Override
public ProductItemPrice apply(ProductItem productItem) {
if(productItem.getPrices().size()<1) throw new NoSuchElementException("ProductItem has no prices:"+productItem);
return Iterables.get(productItem.getPrices(), 0);
}
};
}
/**
* Creates a function to get the capacity from a product item.
*/
public static Function<ProductItem, Float> capacity() {
return new Function<ProductItem, Float>() {
@Override
public Float apply(ProductItem productItem) {
return productItem.getCapacity();
}
};
}
/**
* Creates a function to get the ProductItem for the ProductItemPrice.
* Copies the category information from the price to the item if necessary
* The ProductItemPrices must have ProductItems.
*/
public static Function<ProductItemPrice,ProductItem> item() {
return new Function<ProductItemPrice,ProductItem>() {
@Override
public ProductItem apply(ProductItemPrice productItemPrice) {
Set<ProductItemCategory> categories = productItemPrice.getCategories();
ProductItem item = productItemPrice.getItem();
ProductItem.Builder builder = ProductItem.Builder.fromProductItem(productItemPrice.getItem());
if( item.getCategories().size()==0 && categories.size() != 0) {
builder.categories(categories);
}
* Creates a function to get the description from a product item.
*/
public static Function<ProductItem, String> description() {
return new Function<ProductItem, String>() {
@Override
public String apply(ProductItem productItem) {
return productItem.getDescription();
}
};
}
return builder.build();
/**
* Creates a function to get the ProductItemPrice for the ProductItem. Currently returns the
* first price. This will need to be changed if more than one price is returned.
*/
public static Function<ProductItem, ProductItemPrice> price() {
return new Function<ProductItem, ProductItemPrice>() {
@Override
public ProductItemPrice apply(ProductItem productItem) {
if (productItem.getPrices().size() < 1)
throw new NoSuchElementException("ProductItem has no prices:" + productItem);
return Iterables.get(productItem.getPrices(), 0);
}
};
}
/**
* Creates a function to get the ProductItem for the ProductItemPrice. Copies the category
* information from the price to the item if necessary The ProductItemPrices must have
* ProductItems.
*/
public static Function<ProductItemPrice, ProductItem> item() {
return new Function<ProductItemPrice, ProductItem>() {
@Override
public ProductItem apply(ProductItemPrice productItemPrice) {
Set<ProductItemCategory> categories = productItemPrice.getCategories();
ProductItem item = productItemPrice.getItem();
ProductItem.Builder builder = ProductItem.Builder.fromProductItem(productItemPrice.getItem());
if (item.getCategories().size() == 0 && categories.size() != 0) {
builder.categories(categories);
}
};
}
return builder.build();
}
};
}
}

View File

@ -18,73 +18,101 @@
*/
package org.jclouds.softlayer.compute.functions;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCodeMatches;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
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.Set;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
/**
* Converts a set of ProductItems to Hardware.
* All cores have a speed of 2.0Ghz
* The Hardware Id will be a comma separated list containing the price ids:
* cpus,ram,volume
*
* Converts a set of ProductItems to Hardware. All cores have a speed of 2.0Ghz The Hardware Id will
* be a comma separated list containing the price ids: cpus,ram,volume
*
* @author Jason King
*/
@Singleton
public class ProductItemsToHardware implements Function<Set<ProductItem>, Hardware> {
public class ProductItemsToHardware implements Function<Iterable<ProductItem>, Hardware> {
static final double CORE_SPEED = 2.0;
private final Pattern cpuRegex;
private final Pattern categoryCodeMatches;
@Inject
public ProductItemsToHardware(@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX) String cpuRegex) {
this(Pattern.compile(checkNotNull(cpuRegex, "cpuRegex")), Pattern.compile("guest_disk[0-9]"));
}
public ProductItemsToHardware(Pattern cpuRegex, Pattern categoryCodeMatches) {
this.cpuRegex = checkNotNull(cpuRegex, "cpuRegex");
this.categoryCodeMatches = checkNotNull(categoryCodeMatches, "categoryCodeMatches");
}
@Override
public Hardware apply(Set<ProductItem> items) {
public Hardware apply(Iterable<ProductItem> items) {
ProductItem coresItem = getOnlyElement(filter(items, units("PRIVATE_CORE")));
ProductItem coresItem = getOnlyElement(filter(items, matches(cpuRegex)));
ProductItem ramItem = getOnlyElement(filter(items, categoryCode("ram")));
ProductItem volumeItem = getOnlyElement(filter(items, matches(SoftLayerComputeServiceAdapter.SAN_DESCRIPTION_REGEX)));
ProductItem volumeItem = get(filter(items, categoryCode("guest_disk0")), 0);
final String hardwareId = hardwareId().apply(ImmutableList.of(coresItem, ramItem, volumeItem));
final double cores = ProductItems.capacity().apply(coresItem).doubleValue();
final int ram = ProductItems.capacity().apply(ramItem).intValue();
final float volumeSize = ProductItems.capacity().apply(volumeItem);
String hardwareId = hardwareId().apply(ImmutableList.of(coresItem, ramItem, volumeItem));
double cores = ProductItems.capacity().apply(coresItem).doubleValue();
Matcher cpuMatcher = cpuRegex.matcher(coresItem.getDescription());
double coreSpeed = (cpuMatcher.matches()) ? Double.parseDouble(cpuMatcher.group(cpuMatcher.groupCount())) : 2.0;
int ram = ProductItems.capacity().apply(ramItem).intValue();
return new HardwareBuilder()
.ids(hardwareId)
.processors(ImmutableList.of(new Processor(cores, CORE_SPEED)))
.ram(ram)
.volumes(ImmutableList.<Volume> of(new VolumeImpl(volumeSize, true, false)))
.build();
return new HardwareBuilder().ids(hardwareId).processors(ImmutableList.of(new Processor(cores, coreSpeed))).ram(
ram).volumes(
Iterables.transform(filter(items, categoryCodeMatches(categoryCodeMatches)),
new Function<ProductItem, Volume>() {
@Override
public Volume apply(ProductItem arg0) {
float volumeSize = ProductItems.capacity().apply(arg0);
return new VolumeImpl(
arg0.getId() + "",
arg0.getDescription().indexOf("SAN") != -1 ? Volume.Type.SAN : Volume.Type.LOCAL,
volumeSize, null, categoryCode("guest_disk0").apply(arg0), false);
}
})).build();
}
/**
* Generates a hardwareId based on the priceId's of the items in the list
*
* @return comma separated list of priceid's
*/
public static Function<List<ProductItem>,String> hardwareId() {
return new Function<List<ProductItem>,String>() {
public static Function<List<ProductItem>, String> hardwareId() {
return new Function<List<ProductItem>, String>() {
@Override
public String apply(List<ProductItem> productItems) {
StringBuilder builder = new StringBuilder();
for(ProductItem item:productItems) {
for (ProductItem item : productItems) {
ProductItemPrice price = ProductItems.price().apply(item);
builder.append(price.getId())
.append(",");
builder.append(price.getId()).append(",");
}
return builder.toString().substring(0,builder.lastIndexOf(","));
return builder.toString().substring(0, builder.lastIndexOf(","));
}
};
}

View File

@ -36,7 +36,6 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.http.HttpResponseException;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItem;
@ -49,7 +48,6 @@ import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* @author Adrian Cole
@ -129,25 +127,24 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
@Singleton
public static class GetHardwareForVirtualGuest {
private SoftLayerClient client;
private final SoftLayerClient client;
private final Function<Iterable<ProductItem>, Hardware> productItemsToHardware;
@Inject
public GetHardwareForVirtualGuest(SoftLayerClient client) {
this.client = client;
public GetHardwareForVirtualGuest(SoftLayerClient client,
Function<Iterable<ProductItem>, Hardware> productItemsToHardware) {
this.client = checkNotNull(client, "client");
this.productItemsToHardware = checkNotNull(productItemsToHardware, "productItemsToHardware");
}
public Hardware getHardware(VirtualGuest guest) {
// 'bad' orders have no start cpu's and cause the order lookup to fail.
if (guest.getStartCpus() < 1)
return null;
try {
ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId());
Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item());
return new ProductItemsToHardware().apply(Sets.newLinkedHashSet(items));
} catch (HttpResponseException e) {
// Shouldn't happen any more - was blowing up in Singapore
return null;
}
ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId());
Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item());
return productItemsToHardware.apply(items);
}
}
@ -165,15 +162,10 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
// 'bad' orders have no start cpu's and cause the order lookup to fail.
if (guest.getStartCpus() < 1)
return null;
try {
ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId());
Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item());
ProductItem os = Iterables.find(items, ProductItemPredicates.categoryCode("os"));
return new ProductItemToImage().apply(os);
} catch (HttpResponseException e) {
// Shouldn't happen any more - was blowing up in Singapore
return null;
}
ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId());
Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item());
ProductItem os = Iterables.find(items, ProductItemPredicates.categoryCode("os"));
return new ProductItemToImage().apply(os);
}
}

View File

@ -18,37 +18,54 @@
*/
package org.jclouds.softlayer.compute.strategy;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
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.predicates.RetryablePredicate;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.ProductItems;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.domain.*;
import org.jclouds.softlayer.features.AccountClient;
import org.jclouds.softlayer.features.ProductPackageClient;
import org.jclouds.softlayer.reference.SoftLayerConstants;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import static com.google.common.base.Predicates.and;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.capacity;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.Password;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductOrder;
import org.jclouds.softlayer.domain.ProductOrderReceipt;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/**
* defines the connection between the {@link SoftLayerClient} implementation and the jclouds
@ -57,28 +74,40 @@ import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
*/
@Singleton
public class SoftLayerComputeServiceAdapter implements
ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
ComputeServiceAdapter<VirtualGuest, Iterable<ProductItem>, ProductItem, Datacenter> {
public static final String SAN_DESCRIPTION_REGEX = ".*GB \\(SAN\\).*";
private static final Float BOOT_VOLUME_CAPACITY = 100F;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final SoftLayerClient client;
private final String virtualGuestPackageName;
private final Supplier<ProductPackage> productPackageSupplier;
private final RetryablePredicate<VirtualGuest> loginDetailsTester;
private final long guestLoginDelay;
private final Pattern cpuPattern;
private final Pattern disk0Type;
private final float portSpeed;
private final Iterable<ProductItemPrice> prices;
@Inject
public SoftLayerComputeServiceAdapter(SoftLayerClient client,
@Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName,
VirtualGuestHasLoginDetailsPresent virtualGuestHasLoginDetailsPresent,
@Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY) long guestLoginDelay) {
@Memoized Supplier<ProductPackage> productPackageSupplier, Iterable<ProductItemPrice> prices,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX) String cpuRegex,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE) String disk0Type,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED) float portSpeed,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY) long guestLoginDelay) {
this.client = checkNotNull(client, "client");
this.virtualGuestPackageName = checkNotNull(virtualGuestPackageName, "virtualGuestPackageName");
this.guestLoginDelay = guestLoginDelay;
this.productPackageSupplier = checkNotNull(productPackageSupplier, "productPackageSupplier");
checkArgument(guestLoginDelay > 500, "guestOrderDelay must be in milliseconds and greater than 500");
this.guestLoginDelay =guestLoginDelay;
this.loginDetailsTester = new RetryablePredicate<VirtualGuest>(virtualGuestHasLoginDetailsPresent,
guestLoginDelay);
this.cpuPattern = Pattern.compile(checkNotNull(cpuRegex, "cpuRegex"));
this.prices = checkNotNull(prices, "prices");
this.portSpeed = portSpeed;
checkArgument(portSpeed > 0, "portSpeed must be greater than zero, often 10, 100, 1000, 10000");
this.disk0Type = Pattern.compile(".*" + checkNotNull(disk0Type, "disk0Type") + ".*");
}
@Override
@ -87,34 +116,38 @@ public class SoftLayerComputeServiceAdapter implements
checkNotNull(template, "template was null");
checkNotNull(template.getOptions(), "template options was null");
checkArgument(template.getOptions().getClass().isAssignableFrom(SoftLayerTemplateOptions.class),
"options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions()
.getClass());
"options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions()
.getClass());
String domainName = template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName();
VirtualGuest newGuest = VirtualGuest.builder().domain(domainName).hostname(name).build();
ProductOrder order = ProductOrder.builder().packageId(getProductPackage().getId()).location(
ProductOrder order = ProductOrder.builder().packageId(productPackageSupplier.get().getId()).location(
template.getLocation().getId()).quantity(1).useHourlyPricing(true).prices(getPrices(template))
.virtualGuest(newGuest).build();
logger.debug(">> ordering new virtualGuest domain(%s) hostname(%s)", domainName, name);
ProductOrderReceipt productOrderReceipt = client.getVirtualGuestClient().orderVirtualGuest(order);
VirtualGuest result = Iterables.get(productOrderReceipt.getOrderDetails().getVirtualGuests(), 0);
VirtualGuest result = get(productOrderReceipt.getOrderDetails().getVirtualGuests(), 0);
logger.trace("<< virtualGuest(%s)", result.getId());
logger.debug(">> awaiting login details for virtualGuest(%s)", result.getId());
boolean orderInSystem = loginDetailsTester.apply(result);
logger.trace("<< virtualGuest(%s) complete(%s)", result.getId(), orderInSystem);
checkState(orderInSystem, "order for guest %s doesn't have login details within %sms", result, Long.toString(guestLoginDelay));
checkState(orderInSystem, "order for guest %s doesn't have login details within %sms", result, Long
.toString(guestLoginDelay));
result = client.getVirtualGuestClient().getVirtualGuest(result.getId());
Password pw = Iterables.get(result.getOperatingSystem().getPasswords(),0);
Password pw = get(result.getOperatingSystem().getPasswords(), 0);
Credentials credentials = new Credentials(pw.getUsername(), pw.getPassword());
credentialStore.put("node#" + result.getId(), credentials);
return result;
}
private Iterable<ProductItemPrice> getPrices(Template template) {
Set<ProductItemPrice> result = Sets.newLinkedHashSet();
Builder<ProductItemPrice> result = ImmutableSet.<ProductItemPrice> builder();
int imageId = Integer.parseInt(template.getImage().getId());
result.add(ProductItemPrice.builder().id(imageId).build());
@ -124,46 +157,31 @@ public class SoftLayerComputeServiceAdapter implements
int id = Integer.parseInt(hardwareId);
result.add(ProductItemPrice.builder().id(id).build());
}
result.addAll(SoftLayerConstants.DEFAULT_VIRTUAL_GUEST_PRICES);
return result;
ProductItem uplinkItem = find(productPackageSupplier.get().getItems(), and(capacity(portSpeed),
categoryCode("port_speed")));
result.add(get(uplinkItem.getPrices(), 0));
result.addAll(prices);
return result.build();
}
@Override
public Iterable<Set<ProductItem>> listHardwareProfiles() {
ProductPackage productPackage = getProductPackage();
public Iterable<Iterable<ProductItem>> listHardwareProfiles() {
ProductPackage productPackage = productPackageSupplier.get();
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));
Builder<Iterable<ProductItem>> result = ImmutableSet.<Iterable<ProductItem>> builder();
for (ProductItem cpuItem : filter(items, matches(cpuPattern))) {
for (ProductItem ramItem : filter(items, categoryCode("ram"))) {
for (ProductItem sanItem : filter(items, and(matches(disk0Type), categoryCode("guest_disk0")))) {
result.add(ImmutableSet.of(cpuItem, ramItem, sanItem));
}
}
}
return result;
return result.build();
}
@Override
public Iterable<ProductItem> listImages() {
return Iterables.filter(getProductPackage().getItems(), categoryCode("os"));
return filter(productPackageSupplier.get().getItems(), categoryCode("os"));
}
@Override
@ -173,15 +191,7 @@ public class SoftLayerComputeServiceAdapter implements
@Override
public Iterable<Datacenter> listLocations() {
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());
return productPackageSupplier.get().getDatacenters();
}
@Override
@ -197,8 +207,10 @@ public class SoftLayerComputeServiceAdapter implements
return;
if (guest.getBillingItemId() == -1)
return;
throw new IllegalStateException(String.format("no billing item for guest(%s) so we cannot cancel the order",
id));
logger.debug(">> canceling service for guest(%s) billingItem(%s)", id, guest.getBillingItemId());
client.getVirtualGuestClient().cancelService(guest.getBillingItemId());
}
@ -232,7 +244,8 @@ public class SoftLayerComputeServiceAdapter implements
VirtualGuest newGuest = client.getVirtualGuestClient().getVirtualGuest(guest.getId());
boolean hasBackendIp = newGuest.getPrimaryBackendIpAddress() != null;
boolean hasPrimaryIp = newGuest.getPrimaryIpAddress() != null;
boolean hasPasswords = newGuest.getOperatingSystem()!=null && newGuest.getOperatingSystem().getPasswords().size() > 0;
boolean hasPasswords = newGuest.getOperatingSystem() != null
&& newGuest.getOperatingSystem().getPasswords().size() > 0;
return hasBackendIp && hasPrimaryIp && hasPasswords;
}

View File

@ -30,93 +30,126 @@ public class ProductItemPredicates {
/**
* Tests if the ProductItem contains the required category.
*
* @param category
* @return true if it does, otherwise false.
*/
public static Predicate<ProductItem> categoryCode(final String category) {
checkNotNull(category, "category cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
for(ProductItemCategory productItemCategory: productItem.getCategories()) {
if(category.equals(productItemCategory.getCategoryCode())) return true;
}
return false;
public static Predicate<ProductItem> categoryCode(final String category) {
checkNotNull(category, "category cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
for (ProductItemCategory productItemCategory : productItem.getCategories()) {
if (category.equals(productItemCategory.getCategoryCode()))
return true;
}
return false;
}
@Override
public String toString() {
return "categoryCode("+category+")";
@Override
public String toString() {
return "categoryCode(" + category + ")";
}
};
}
/**
* Tests if the ProductItem contains a category that matches the supplied Pattern
*
* @param category
* @return true if it does, otherwise false.
*/
public static Predicate<ProductItem> categoryCodeMatches(final Pattern category) {
checkNotNull(category, "category cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
for (ProductItemCategory productItemCategory : productItem.getCategories()) {
if (category.matcher(productItemCategory.getCategoryCode()).matches())
return true;
}
};
}
return false;
}
/**
@Override
public String toString() {
return "categoryCodeMatches(" + category + ")";
}
};
}
/**
* Tests if the ProductItem has the required capacity.
*
* @param capacity
* @return true if it does, otherwise false.
*/
public static Predicate<ProductItem> capacity(final Float capacity) {
checkNotNull(capacity, "capacity cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
Float productItemCapacity = productItem.getCapacity();
if (productItemCapacity == null) return false;
return capacity.equals(productItemCapacity);
}
public static Predicate<ProductItem> capacity(final Float capacity) {
checkNotNull(capacity, "capacity cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
Float productItemCapacity = productItem.getCapacity();
if (productItemCapacity == null)
return false;
return capacity.equals(productItemCapacity);
}
@Override
public String toString() {
return "capacity("+capacity+")";
}
};
}
@Override
public String toString() {
return "capacity(" + capacity + ")";
}
};
}
/**
* Tests if the ProductItem has the required units.
*
* @param units
* @return true if it does, otherwise false.
*/
public static Predicate<ProductItem> units(final String units) {
checkNotNull(units, "units cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
return units.equals(productItem.getUnits());
}
public static Predicate<ProductItem> units(final String units) {
checkNotNull(units, "units cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
return units.equals(productItem.getUnits());
}
@Override
public String toString() {
return "units("+units+")";
}
};
}
@Override
public String toString() {
return "units(" + units + ")";
}
};
}
/**
* Tests if the ProductItem's description matches the supplied regular expression.
* @param regex a regular expression to match against.
*
* @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
* @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);
public static Predicate<ProductItem> matches(final Pattern regex) {
checkNotNull(regex, "regex cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
return PATTERN.matcher(productItem.getDescription()).matches();
}
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
return regex.matcher(productItem.getDescription()).matches();
}
@Override
public String toString() {
return "regex("+regex+")";
}
};
}
@Override
public String toString() {
return "regex(" + regex + ")";
}
};
}
}

View File

@ -18,38 +18,41 @@
*/
package org.jclouds.softlayer.reference;
import com.google.common.collect.ImmutableSet;
import org.jclouds.softlayer.domain.ProductItemPrice;
import java.util.Set;
/**
* Configuration properties and constants used in SoftLayer connections.
*
* @author Adrian Cole
*/
public interface SoftLayerConstants {
/**
* Name of the product package corresponding to cloud servers
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME = "jclouds.softlayer.virtualguest.package-name";
/**
* pattern where last group matches core speed
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX = "jclouds.softlayer.virtualguest.cpu-regex";
/**
* Uplink port speed for new guests (10, 100, 1000)
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED = "jclouds.softlayer.virtualguest.port-speed";
/**
* Default Boot Disk type (SAN, LOCAL)
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE = "jclouds.softlayer.virtualguest.disk0-type";
/**
* number of milliseconds to wait for an order to arrive on the api.
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY = "jclouds.softlayer.virtualguest.order-delay";
public static final Set<ProductItemPrice> DEFAULT_VIRTUAL_GUEST_PRICES = ImmutableSet.<ProductItemPrice>builder()
.add(ProductItemPrice.builder().id(1639).build()) // 100 GB (SAN)
.add(ProductItemPrice.builder().id(21).build()) // 1 IP Address
.add(ProductItemPrice.builder().id(55).build()) // Host Ping
.add(ProductItemPrice.builder().id(58).build()) // Automated Notification
.add(ProductItemPrice.builder().id(1800).build()) // 0 GB Bandwidth
.add(ProductItemPrice.builder().id(57).build()) // Email and Ticket
.add(ProductItemPrice.builder().id(274).build()) // 1000 Mbps Public & Private Networks
.add(ProductItemPrice.builder().id(905).build()) // Reboot / Remote Console
.add(ProductItemPrice.builder().id(418).build()) // Nessus Vulnerability Assessment & Reporting
.add(ProductItemPrice.builder().id(420).build()) // Unlimited SSL VPN Users & 1 PPTP VPN User per account
.build();
/**
* standard prices for all new guests.
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES = "jclouds.softlayer.virtualguest.prices";
}

View File

@ -18,25 +18,22 @@
*/
package org.jclouds.softlayer.compute;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.net.IPSocket;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.features.BaseSoftLayerClientLiveTest;
import org.jclouds.softlayer.features.ProductPackageClientLiveTest;
import org.jclouds.ssh.SshClient;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
@ -45,6 +42,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.net.InetAddresses;
import com.google.inject.Guice;
@Test(groups = "live", singleThreaded = true, testName = "SoftLayerComputeServiceAdapterLiveTest")
public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientLiveTest {
@ -55,9 +53,8 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();
adapter = new SoftLayerComputeServiceAdapter(context.getApi(),
ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME,
new SoftLayerComputeServiceAdapter.VirtualGuestHasLoginDetailsPresent(context.getApi()),60*60*1000);
adapter = Guice.createInjector(module, new Log4JLoggingModule())
.getInstance(SoftLayerComputeServiceAdapter.class);
}
@Test
@ -68,12 +65,12 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
@Test
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo";
String name = "node"+new Random().nextInt();
String name = "node" + new Random().nextInt();
Template template = computeContext.getComputeService().templateBuilder().build();
// test passing custom options
template.getOptions().as(SoftLayerTemplateOptions.class).domainName("me.org");
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
guest = adapter.createNodeWithGroupEncodedIntoNameThenStoreCredentials(group, name, template, credentialStore);
assertEquals(guest.getHostname(), name);
@ -86,8 +83,7 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
}
protected void doConnectViaSsh(VirtualGuest guest, Credentials creds) {
SshClient ssh = computeContext.utils().sshFactory()
.create(new IPSocket(guest.getPrimaryIpAddress(), 22), creds);
SshClient ssh = computeContext.utils().sshFactory().create(new IPSocket(guest.getPrimaryIpAddress(), 22), creds);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
@ -103,15 +99,12 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
@Test
public void testListHardwareProfiles() {
Iterable<Set<ProductItem>> profiles = adapter.listHardwareProfiles();
Iterable<Iterable<ProductItem>> profiles = adapter.listHardwareProfiles();
assertFalse(Iterables.isEmpty(profiles));
for (Set<ProductItem> profile : profiles) {
for (Iterable<ProductItem> profile : profiles) {
// CPU, RAM and Volume
assertEquals(profile.size(), 3);
ProductItem cpuItem = Iterables.getOnlyElement(Iterables.filter(profile, units("PRIVATE_CORE")));
ProductItem ramItem = Iterables.getOnlyElement(Iterables.filter(profile, categoryCode("ram")));
assertEquals(cpuItem.getCapacity(), ramItem.getCapacity());
assertEquals(Iterables.size(profile), 3);
}
}

View File

@ -19,21 +19,31 @@
package org.jclouds.softlayer.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.Volume;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
*
@ -46,7 +56,7 @@ public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTes
provider = "softlayer";
}
/// allows us to break when a new os is added
// / allows us to break when a new os is added
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return Predicates.not(new Predicate<OsFamilyVersion64Bit>() {
@ -55,20 +65,20 @@ public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTes
public boolean apply(OsFamilyVersion64Bit input) {
// For each os-type both 32- and 64-bit are supported.
switch (input.family) {
case UBUNTU:
return input.version.equals("") || input.version.equals("10.04") || input.version.equals("8");
case DEBIAN:
return input.version.equals("") || input.version.equals("5.0");
case FEDORA:
return input.version.equals("") || input.version.equals("13") || input.version.equals("15");
case RHEL:
return input.version.equals("") || input.version.equals("5") || input.version.equals("6");
case CENTOS:
return input.version.equals("") || input.version.equals("5") || input.version.equals("6.0");
case WINDOWS:
return input.version.equals("") || input.version.equals("2003") || input.version.equals("2008");
default:
return false;
case UBUNTU:
return input.version.equals("") || input.version.equals("10.04") || input.version.equals("8");
case DEBIAN:
return input.version.equals("") || input.version.equals("5.0");
case FEDORA:
return input.version.equals("") || input.version.equals("13") || input.version.equals("15");
case RHEL:
return input.version.equals("") || input.version.equals("5") || input.version.equals("6");
case CENTOS:
return input.version.equals("") || input.version.equals("5") || input.version.equals("6.0");
case WINDOWS:
return input.version.equals("") || input.version.equals("2003") || input.version.equals("2008");
default:
return false;
}
}
@ -81,13 +91,134 @@ public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTes
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 2.0d);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
assertEquals(defaultTemplate.getHardware().getRam(), 1);
assertEquals(getSpace(defaultTemplate.getHardware()), 25.0d);
assertEquals(defaultTemplate.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
// test that we bound the correct templateoptions in guice
assertEquals(defaultTemplate.getOptions().getClass(), SoftLayerTemplateOptions.class);
}
@Test
public void testTemplateBuilderFindsGigabitUplink() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED, "1000");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
// TODO add something to the template about port speed?
context.getComputeService().templateBuilder().build();
} finally {
if (context != null)
context.close();
}
}
@Test
public void testTemplateBuilderFindsMegabitUplink() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED, "100");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
// TODO add something to the template about port speed?
context.getComputeService().templateBuilder().build();
} finally {
if (context != null)
context.close();
}
}
@Test
public void testBiggestTemplateBuilderWhenBootIsSAN() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE, "SAN");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
Template template = context.getComputeService().templateBuilder().biggest().build();
assertEquals(getCores(template.getHardware()), 16.0d);
assertEquals(template.getHardware().getRam(), 16);
assertEquals(getSpace(template.getHardware()), 100.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.SAN);
} finally {
if (context != null)
context.close();
}
}
@Test
public void testDefaultTemplateBuilderWhenPrivateNetwork() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX, "Private [0-9]+ x ([.0-9]+) GHz Core[s]?");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
Template template = context.getComputeService().templateBuilder().build();
assertEquals(getCores(template.getHardware()), 1.0d);
assertEquals(template.getHardware().getRam(), 1);
assertEquals(getSpace(template.getHardware()), 25.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
} finally {
if (context != null)
context.close();
}
}
@Test
public void testBiggestTemplateBuilderWhenPrivateNetwork() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX, "Private [0-9]+ x ([.0-9]+) GHz Core[s]?");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
Template template = context.getComputeService().templateBuilder().biggest().build();
assertEquals(getCores(template.getHardware()), 8.0d);
assertEquals(template.getHardware().getRam(), 16);
assertEquals(getSpace(template.getHardware()), 100.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
} finally {
if (context != null)
context.close();
}
}
@Test
public void testFastestTemplateBuilder() throws IOException {
Template template = context.getComputeService().templateBuilder().fastest().build();
assertEquals(getCores(template.getHardware()), 16.0d);
assertEquals(template.getHardware().getRam(), 1);
assertEquals(getSpace(template.getHardware()), 25.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
}
@Test
public void testBiggestTemplateBuilder() throws IOException {
Template template = context.getComputeService().templateBuilder().biggest().build();
assertEquals(getCores(template.getHardware()), 16.0d);
assertEquals(template.getHardware().getRam(), 16);
assertEquals(getSpace(template.getHardware()), 100.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
}
@Override
protected Set<String> getIso3166Codes() {
return ImmutableSet.<String> of("SG","US-CA","US-TX","US-VA","US-WA","US-TX");
return ImmutableSet.<String> of("SG", "US-CA", "US-TX", "US-VA", "US-WA", "US-TX");
}
}

View File

@ -18,24 +18,30 @@
*/
package org.jclouds.softlayer.compute.functions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import static com.google.inject.name.Names.bindProperties;
import static org.jclouds.softlayer.compute.functions.ProductItemsToHardware.hardwareId;
import static org.testng.AssertJUnit.assertEquals;
import java.util.List;
import java.util.Properties;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.softlayer.SoftLayerPropertiesBuilder;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemCategory;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.testng.annotations.Test;
import java.util.List;
import static org.jclouds.softlayer.compute.functions.ProductItemsToHardware.hardwareId;
import static org.testng.AssertJUnit.assertEquals;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
/**
* Tests {@code ProductItemsToHardware}
*
*
* @author Jason King
*/
@Test(groups = "unit")
@ -48,46 +54,41 @@ public class ProductItemsToHardwareTest {
ProductItem item3 = ProductItem.builder().price(ProductItemPrice.builder().id(789).build()).build();
String id = hardwareId().apply(ImmutableList.of(item1, item2, item3));
assertEquals("123,456,789",id);
assertEquals("123,456,789", id);
}
@Test
public void testHardware() {
ProductItem cpuItem = ProductItem.builder()
.id(1)
.description("2 cores")
.units("PRIVATE_CORE")
.capacity(2F)
.price(ProductItemPrice.builder().id(123).build())
.build();
ProductItem ramItem = ProductItem.builder()
.id(2)
.description("2GB ram")
.capacity(2F)
.category(ProductItemCategory.builder().categoryCode("ram").build())
.price(ProductItemPrice.builder().id(456).build())
.build();
ProductItem cpuItem = ProductItem.builder().id(1).description("2 x 2.0 GHz Cores").units("PRIVATE_CORE")
.capacity(2F).price(ProductItemPrice.builder().id(123).build()).build();
ProductItem volumeItem = ProductItem.builder()
.id(3)
.description("100 GB (SAN)")
.capacity(100F)
.price(ProductItemPrice.builder().id(789).build())
.build();
ProductItem ramItem = ProductItem.builder().id(2).description("2GB ram").capacity(2F).category(
ProductItemCategory.builder().categoryCode("ram").build()).price(
ProductItemPrice.builder().id(456).build()).build();
Hardware hardware = new ProductItemsToHardware().apply(ImmutableSet.of(cpuItem,ramItem,volumeItem));
ProductItem volumeItem = ProductItem.builder().id(3).description("100 GB (SAN)").capacity(100F).price(
ProductItemPrice.builder().id(789).build()).category(
ProductItemCategory.builder().categoryCode("guest_disk0").build()).build();
assertEquals("123,456,789",hardware.getId());
Hardware hardware = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindProperties(binder(), new SoftLayerPropertiesBuilder(new Properties()).build());
}
}).getInstance(ProductItemsToHardware.class).apply(ImmutableSet.of(cpuItem, ramItem, volumeItem));
assertEquals("123,456,789", hardware.getId());
List<? extends Processor> processors = hardware.getProcessors();
assertEquals(1,processors.size());
assertEquals(2.0,processors.get(0).getCores());
assertEquals(1, processors.size());
assertEquals(2.0, processors.get(0).getCores());
assertEquals(2, hardware.getRam());
List<? extends Volume> volumes = hardware.getVolumes();
assertEquals(1,volumes.size());
assertEquals(100F,volumes.get(0).getSize());
assertEquals(1, volumes.size());
assertEquals(100F, volumes.get(0).getSize());
}
}

View File

@ -18,26 +18,40 @@
*/
package org.jclouds.softlayer.compute.functions;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Iterables;
import org.jclouds.compute.domain.*;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata.FindLocationForVirtualGuest;
import org.jclouds.softlayer.domain.Password;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.parse.*;
import org.jclouds.softlayer.parse.ParseBadVirtualGuest;
import org.jclouds.softlayer.parse.ParseVirtualGuestHaltedTest;
import org.jclouds.softlayer.parse.ParseVirtualGuestPausedTest;
import org.jclouds.softlayer.parse.ParseVirtualGuestRunningTest;
import org.jclouds.softlayer.parse.ParseVirtualGuestWithNoPasswordTest;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -209,8 +223,9 @@ public class VirtualGuestToNodeMetadataTest {
}
private static class GetHardwareForVirtualGuestMock extends VirtualGuestToNodeMetadata.GetHardwareForVirtualGuest {
@SuppressWarnings("unchecked")
public GetHardwareForVirtualGuestMock() {
super(null);
super(createNiceMock(SoftLayerClient.class), createNiceMock(Function.class));
}
@Override

View File

@ -19,20 +19,36 @@
package org.jclouds.softlayer.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.inject.name.Names.bindProperties;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES;
import java.util.Properties;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.SoftLayerPropertiesBuilder;
import org.jclouds.softlayer.compute.config.SoftLayerComputeServiceContextModule;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.Provides;
/**
* Tests behavior of {@code SoftLayerClient}
@ -44,16 +60,41 @@ public class BaseSoftLayerClientLiveTest {
protected RestContext<SoftLayerClient, SoftLayerAsyncClient> context;
protected ComputeServiceContext computeContext;
protected Module module;
@BeforeGroups(groups = { "live" })
public void setupClient() {
String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity");
String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential");
computeContext = new ComputeServiceContextFactory().createContext("softlayer", identity, credential,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()));
computeContext = new ComputeServiceContextFactory().createContext("softlayer", identity, credential, ImmutableSet
.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()));
context = computeContext.getProviderSpecificContext();
module = new AbstractModule() {
@Override
protected void configure() {
bindProperties(binder(), new SoftLayerPropertiesBuilder(new Properties()).build());
bind(SoftLayerClient.class).toInstance(context.getApi());
}
@SuppressWarnings("unused")
@Provides
@Singleton
@Memoized
public Supplier<ProductPackage> getProductPackage(SoftLayerClient client,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName) {
return new SoftLayerComputeServiceContextModule().getProductPackage(30, client, virtualGuestPackageName);
}
@SuppressWarnings("unused")
@Provides
@Singleton
public Iterable<ProductItemPrice> prices(@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES) String prices) {
return new SoftLayerComputeServiceContextModule().prices(prices);
}
};
}
@AfterGroups(groups = "live")

View File

@ -43,9 +43,11 @@ import static org.testng.Assert.*;
public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
/**
* Name of the package used for ordering virtual guests.
* For real this is passed in using the property
* @{code org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME}
* Name of the package used for ordering virtual guests. For real this is passed in using the
* property
*
* @{code org.jclouds.softlayer.reference.SoftLayerConstants.
* PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME}
*/
public static final String CLOUD_SERVER_PACKAGE_NAME = "Cloud Server";
@ -56,7 +58,8 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
accountClient = context.getApi().getAccountClient();
// This is used several times, so cache to speed up the test.
cloudServerPackageId = Iterables.find(accountClient.getActivePackages(),named(CLOUD_SERVER_PACKAGE_NAME)).getId();
cloudServerPackageId = Iterables.find(accountClient.getActivePackages(), named(CLOUD_SERVER_PACKAGE_NAME))
.getId();
cloudServerProductPackage = client.getProductPackage(cloudServerPackageId);
}
@ -107,7 +110,7 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
assertEquals(datacenters.size(), expected.size());
assertTrue(datacenters.containsAll(expected));
for(Datacenter dataCenter: datacenters) {
for (Datacenter dataCenter : datacenters) {
Address address = dataCenter.getLocationAddress();
assertNotNull(address);
checkAddress(address);
@ -116,37 +119,42 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
@Test
public void testGetOneGBRamPrice() {
//Predicate p = Predicates.and(ProductItemPredicates.categoryCode("ram"),ProductItemPredicates.capacity(1.0f));
Iterable<ProductItem> ramItems = Iterables.filter(cloudServerProductPackage.getItems(),
Predicates.and(categoryCode("ram"), capacity(1.0f)));
// Predicate p =
// Predicates.and(ProductItemPredicates.categoryCode("ram"),ProductItemPredicates.capacity(1.0f));
Iterable<ProductItem> ramItems = Iterables.filter(cloudServerProductPackage.getItems(), Predicates.and(
categoryCode("ram"), capacity(1.0f)));
// capacity is key in GB (1Gb = 1.0f)
Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity());
// capacity is key in GB (1Gb = 1.0f)
Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity());
ProductItemPrice price = ProductItems.price().apply(ramToProductItem.get(1.0f));
assert new Integer(1644).equals(price.getId());
ProductItemPrice price = ProductItems.price().apply(ramToProductItem.get(1.0f));
assert new Integer(1644).equals(price.getId());
}
@Test
public void testGetTwoCPUCoresPrice() {
// If use ProductItemPredicates.categoryCode("guest_core") get duplicate capacities (units = PRIVATE_CORE and N/A)
Iterable<ProductItem> cpuItems = Iterables.filter(cloudServerProductPackage.getItems(), Predicates.and(units("PRIVATE_CORE"), capacity(2.0f)));
// If use ProductItemPredicates.categoryCode("guest_core") get duplicate capacities (units =
// PRIVATE_CORE and N/A)
Iterable<ProductItem> cpuItems = Iterables.filter(cloudServerProductPackage.getItems(), Predicates.and(
units("PRIVATE_CORE"), capacity(2.0f)));
// number of cores is the key
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
// number of cores is the key
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
ProductItemPrice price = ProductItems.price().apply(coresToProductItem.get(2.0f));
assert new Integer(1963).equals(price.getId());
ProductItemPrice price = ProductItems.price().apply(coresToProductItem.get(2.0f));
assert new Integer(1963).equals(price.getId());
}
@Test
public void testGetUbuntuPrice() {
Iterable<ProductItem> operatingSystems = Iterables.filter(cloudServerProductPackage.getItems(), categoryCode("os"));
Iterable<ProductItem> operatingSystems = Iterables.filter(cloudServerProductPackage.getItems(),
categoryCode("os"));
Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description());
Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description());
ProductItemPrice price = ProductItems.price().apply(osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)"));
assert new Integer(1693).equals(price.getId());
ProductItemPrice price = ProductItems.price().apply(
osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)"));
assert new Integer(1693).equals(price.getId());
}
private void checkProductItem(ProductItem item) {
@ -178,17 +186,17 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
}
private void checkAddress(Address address) {
assert address.getId() >0 : address;
assert address.getId() > 0 : address;
assert address.getCountry() != null : address;
if (!address.getCountry().equals("SG"))
assert address.getState() != null : address;
}
private void checkCategories(Set<ProductItemCategory> categories) {
for( ProductItemCategory category: categories ) {
assert category.getId() >0 : category;
assert category.getName() != null : category;
assert category.getCategoryCode() != null : category;
}
for (ProductItemCategory category : categories) {
assert category.getId() > 0 : category;
assert category.getName() != null : category;
assert category.getCategoryCode() != null : category;
}
}
}

View File

@ -18,23 +18,36 @@
*/
package org.jclouds.softlayer.features;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jclouds.softlayer.compute.functions.ProductItems;
import org.jclouds.softlayer.domain.*;
import org.jclouds.softlayer.reference.SoftLayerConstants;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.capacity;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import static org.testng.Assert.*;
import org.jclouds.softlayer.compute.functions.ProductItems;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductOrder;
import org.jclouds.softlayer.domain.ProductOrderReceipt;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
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.ImmutableSet.Builder;
import com.google.inject.Guice;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code VirtualGuestClient}
@ -66,70 +79,69 @@ public class VirtualGuestClientLiveTest extends BaseSoftLayerClientLiveTest {
}
}
@Test(enabled = false)
@Test(enabled = false, groups = "live")
public void testCancelAndPlaceOrder() {
// This method was not working needs testing out.
// This method was not working needs testing out.
// TODO: Should also check if there are active transactions before trying to cancel.
// objectMask: virtualGuests.activeTransaction
for( VirtualGuest guest: client.listVirtualGuests()) {
for (VirtualGuest guest : client.listVirtualGuests()) {
if (guest.getHostname().startsWith(TEST_HOSTNAME_PREFIX)) {
if(guest.getBillingItemId()!=-1) {
if (guest.getBillingItemId() != -1) {
client.cancelService(guest.getBillingItemId());
}
}
}
int pkgId = Iterables.find(context.getApi().getAccountClient().getActivePackages(),named(ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME)).getId();
int pkgId = Iterables.find(context.getApi().getAccountClient().getActivePackages(),
named(ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME)).getId();
ProductPackage productPackage = context.getApi().getProductPackageClient().getProductPackage(pkgId);
Iterable<ProductItem> ramItems = Iterables.filter(productPackage.getItems(),
Predicates.and(categoryCode("ram"), capacity(2.0f)));
Iterable<ProductItem> ramItems = Iterables.filter(productPackage.getItems(), Predicates.and(categoryCode("ram"),
capacity(2.0f)));
Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity());
Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity());
ProductItemPrice ramPrice = ProductItems.price().apply(ramToProductItem.get(2.0f));
ProductItemPrice ramPrice = ProductItems.price().apply(ramToProductItem.get(2.0f));
Iterable<ProductItem> cpuItems = Iterables.filter(productPackage.getItems(), Predicates.and(units("PRIVATE_CORE"), capacity(2.0f)));
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
Iterable<ProductItem> cpuItems = Iterables.filter(productPackage.getItems(), Predicates.and(
units("PRIVATE_CORE"), capacity(2.0f)));
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
ProductItemPrice cpuPrice = ProductItems.price().apply(coresToProductItem.get(2.0f));
ProductItemPrice cpuPrice = ProductItems.price().apply(coresToProductItem.get(2.0f));
Iterable<ProductItem> operatingSystems = Iterables.filter(productPackage.getItems(), categoryCode("os"));
Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description());
ProductItemPrice osPrice = ProductItems.price().apply(osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)"));
Iterable<ProductItem> operatingSystems = Iterables.filter(productPackage.getItems(), categoryCode("os"));
Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description());
ProductItemPrice osPrice = ProductItems.price().apply(
osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)"));
Set<ProductItemPrice> prices = Sets.<ProductItemPrice>newLinkedHashSet();
prices.addAll(SoftLayerConstants.DEFAULT_VIRTUAL_GUEST_PRICES);
prices.add(ramPrice);
prices.add(cpuPrice);
prices.add(osPrice);
Builder<ProductItemPrice> prices = ImmutableSet.<ProductItemPrice> builder();
prices.addAll(Guice.createInjector(module).getInstance(Key.get(new TypeLiteral<Iterable<ProductItemPrice>>() {
})));
prices.add(ramPrice);
prices.add(cpuPrice);
prices.add(osPrice);
VirtualGuest guest = VirtualGuest.builder().domain("jclouds.org")
.hostname(TEST_HOSTNAME_PREFIX+new Random().nextInt())
.build();
VirtualGuest guest = VirtualGuest.builder().domain("jclouds.org").hostname(
TEST_HOSTNAME_PREFIX + new Random().nextInt()).build();
ProductOrder order = ProductOrder.builder()
.packageId(pkgId)
.quantity(1)
.useHourlyPricing(true)
.prices(prices)
.virtualGuest(guest)
.build();
ProductOrder order = ProductOrder.builder().packageId(pkgId).quantity(1).useHourlyPricing(true).prices(
prices.build()).virtualGuest(guest).build();
ProductOrderReceipt receipt = context.getApi().getVirtualGuestClient().orderVirtualGuest(order);
ProductOrder order2 = receipt.getOrderDetails();
VirtualGuest result = Iterables.get(order2.getVirtualGuests(), 0);
ProductOrderReceipt receipt = context.getApi().getVirtualGuestClient().orderVirtualGuest(order);
ProductOrder order2 = receipt.getOrderDetails();
VirtualGuest result = Iterables.get(order2.getVirtualGuests(), 0);
ProductOrder order3 = context.getApi().getVirtualGuestClient().getOrderTemplate(result.getId());
ProductOrder order3 = context.getApi().getVirtualGuestClient().getOrderTemplate(result.getId());
assertEquals(order.getPrices(),order3.getPrices());
assertNotNull(receipt);
assertEquals(order.getPrices(), order3.getPrices());
assertNotNull(receipt);
}
private void checkVirtualGuest(VirtualGuest vg) {
if (vg.getBillingItemId()==-1) return;//Quotes and shutting down guests
if (vg.getBillingItemId() == -1)
return;// Quotes and shutting down guests
assert vg.getAccountId() > 0 : vg;
assert vg.getCreateDate() != null : vg;

View File

@ -18,15 +18,18 @@
*/
package org.jclouds.softlayer.predicates;
import com.google.common.collect.ImmutableSet;
import static org.testng.Assert.assertFalse;
import java.util.regex.Pattern;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemCategory;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import static org.testng.Assert.assertFalse;
import com.google.common.collect.ImmutableSet;
@Test(sequential = true,groups = "unit")
@Test(singleThreaded = true, groups = "unit")
public class ProductItemPredicatesTest {
private ProductItemCategory ramCategory;
@ -37,66 +40,64 @@ public class ProductItemPredicatesTest {
public void setupClient() {
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")
.build();
item = ProductItem.builder().id(1).description("a test item").categories(ImmutableSet.of(ramCategory)).capacity(
2.0f).units("GB").build();
emptyItem = ProductItem.builder().id(1).build();
}
@Test
public void testCategoryCodePresent() {
assert ProductItemPredicates.categoryCode("ram").apply(item);
}
@Test
public void testCategoryCodePresent() {
assert ProductItemPredicates.categoryCode("ram").apply(item);
}
@Test
public void testCategoryCodePresentTwoCategories() {
ProductItemCategory osCategory = ProductItemCategory.builder()
.id(2).categoryCode("os")
.build();
@Test
public void testCategoryCodePresentTwoCategories() {
ProductItemCategory osCategory = ProductItemCategory.builder().id(2).categoryCode("os").build();
ProductItem item = ProductItem.builder()
.categories(ImmutableSet.of(ramCategory, osCategory))
.build();
ProductItem item = ProductItem.builder().categories(ImmutableSet.of(ramCategory, osCategory)).build();
assert ProductItemPredicates.categoryCode("ram").apply(item);
}
assert ProductItemPredicates.categoryCode("ram").apply(item);
}
@Test
public void testCategoryCodeMissing() {
assertFalse(ProductItemPredicates.categoryCode("missing").apply(emptyItem));
}
@Test
public void testCategoryCodeMissing() {
assertFalse(ProductItemPredicates.categoryCode("missing").apply(emptyItem));
}
@Test
public void testCategoryCodeMatches() {
ProductItemPredicates.categoryCodeMatches(Pattern.compile("ra.*")).apply(item);
}
@Test
public void testCapacityPresent() {
assert ProductItemPredicates.capacity(2.0f).apply(item);
}
@Test
public void testCapacityMissing() {
assertFalse(ProductItemPredicates.capacity(1.0f).apply(item));
}
@Test
public void testCapacityPresent() {
assert ProductItemPredicates.capacity(2.0f).apply(item);
}
@Test
public void testUnitsPresent() {
assert ProductItemPredicates.units("GB").apply(item);
}
@Test
public void testCapacityMissing() {
assertFalse(ProductItemPredicates.capacity(1.0f).apply(item));
}
@Test
public void testUnitsMissing() {
assertFalse(ProductItemPredicates.units("Kg").apply(item));
}
@Test
public void testUnitsPresent() {
assert ProductItemPredicates.units("GB").apply(item);
}
@Test
public void testMatchesRegex() {
assert ProductItemPredicates.matches(".*test.*").apply(item);
}
@Test
public void testUnitsMissing() {
assertFalse(ProductItemPredicates.units("Kg").apply(item));
}
@Test
public void testNoMatchRegex() {
assertFalse(ProductItemPredicates.matches("no match").apply(item));
}
@Test
public void testMatchesRegex() {
assert ProductItemPredicates.matches(Pattern.compile(".*test.*")).apply(item);
}
@Test
public void testNoMatchRegex() {
assertFalse(ProductItemPredicates.matches(Pattern.compile("no match")).apply(item));
}
}