Merge branch 'master' of git://github.com/jclouds/jclouds

This commit is contained in:
Adam Lowe 2011-09-30 20:46:16 +01:00
commit 9e6d52c54b
5 changed files with 80 additions and 90 deletions

View File

@ -39,6 +39,7 @@ public class SoftLayerPropertiesBuilder extends PropertiesBuilder {
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_ORDER_DELAY, "5000");
properties.setProperty(PROPERTY_ISO3166_CODES, "SG,US-CA,US-TX,US-VA,US-WA,US-TX");
return properties;
}

View File

@ -18,20 +18,12 @@
*/
package org.jclouds.softlayer.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
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;
@ -39,25 +31,21 @@ import org.jclouds.domain.Credentials;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.ProductItems;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.domain.BillingItemVirtualGuest;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.OperatingSystem;
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.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.domain.*;
import org.jclouds.softlayer.features.AccountClient;
import org.jclouds.softlayer.features.ProductPackageClient;
import org.jclouds.softlayer.reference.SoftLayerConstants;
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 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 org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
/**
* defines the connection between the {@link SoftLayerClient} implementation and the jclouds
@ -66,9 +54,9 @@ import com.google.common.collect.Sets;
*/
@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\\).*";
public static final String SAN_DESCRIPTION_REGEX = ".*GB \\(SAN\\).*";
private static final Float BOOT_VOLUME_CAPACITY = 100F;
private final SoftLayerClient client;
@ -87,62 +75,36 @@ 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());
Iterable<VirtualGuest> existing = findVirtualGuests(name,group);
if(!Iterables.isEmpty(existing)) {
throw new IllegalStateException(
"VirtualGuest(s) already exist with hostname:"+name+", group:"+group+". Existing:"+existing);
}
String domainName = template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName();
VirtualGuest newGuest = VirtualGuest.builder()
.domain(template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName())
.hostname(name)
.build();
VirtualGuest newGuest = VirtualGuest.builder().domain(domainName).hostname(name).build();
ProductOrder order = ProductOrder.builder()
.packageId(getProductPackage().getId())
.location(template.getLocation().getId())
.quantity(1)
.useHourlyPricing(true)
.prices(getPrices(template))
.virtualGuest(newGuest)
.build();
ProductOrder order = ProductOrder.builder().packageId(getProductPackage().getId()).location(
template.getLocation().getId()).quantity(1).useHourlyPricing(true).prices(getPrices(template))
.virtualGuest(newGuest).build();
client.getVirtualGuestClient().orderVirtualGuest(order);
ProductOrderReceipt productOrderReceipt = client.getVirtualGuestClient().orderVirtualGuest(order);
VirtualGuest result = Iterables.get(productOrderReceipt.getOrderDetails().getVirtualGuests(), 0);
VirtualGuest result = Iterables.getOnlyElement(findVirtualGuests(name, group));
Credentials credentials = new Credentials(null,null);
Credentials credentials = new Credentials(null, null);
// This information is not always available.
OperatingSystem os = result.getOperatingSystem();
if(os!=null) {
if (os != null) {
Set<Password> passwords = os.getPasswords();
if(passwords.size()>0) {
Password pw = Iterables.get(passwords,0);
credentials = new Credentials(pw.getUsername(),pw.getPassword());
if (passwords.size() > 0) {
Password pw = Iterables.get(passwords, 0);
credentials = new Credentials(pw.getUsername(), pw.getPassword());
}
}
credentialStore.put("node#"+result.getId(),credentials);
credentialStore.put("node#" + result.getId(), credentials);
return result;
}
private Iterable<VirtualGuest> findVirtualGuests(String hostname,String domain) {
checkNotNull(hostname,"hostname");
checkNotNull(domain,"domain");
Set<VirtualGuest> result = Sets.newLinkedHashSet();
for( VirtualGuest guest : client.getVirtualGuestClient().listVirtualGuests()) {
if ( guest.getHostname().equals(hostname) && guest.getDomain().equals(domain)) {
result.add(guest);
}
}
return result;
}
private Iterable<ProductItemPrice> getPrices(Template template) {
Set<ProductItemPrice> result = Sets.newLinkedHashSet();
@ -151,7 +113,7 @@ public class SoftLayerComputeServiceAdapter implements
result.add(ProductItemPrice.builder().id(imageId).build());
Iterable<String> hardwareIds = Splitter.on(",").split(template.getHardware().getId());
for(String hardwareId: hardwareIds) {
for (String hardwareId : hardwareIds) {
int id = Integer.parseInt(hardwareId);
result.add(ProductItemPrice.builder().id(id).build());
}
@ -161,32 +123,32 @@ public class SoftLayerComputeServiceAdapter implements
return result;
}
@Override
public Iterable<Set<ProductItem>> listHardwareProfiles() {
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")));
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;
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()) {
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;
// Amount of RAM and number of cores must match.
if (ramItem == null)
continue;
result.add(ImmutableSet.of(coresEntry.getValue(),ramItem,bootVolume));
result.add(ImmutableSet.of(coresEntry.getValue(), ramItem, bootVolume));
}
return result;
@ -211,7 +173,7 @@ public class SoftLayerComputeServiceAdapter implements
AccountClient accountClient = client.getAccountClient();
ProductPackageClient productPackageClient = client.getProductPackageClient();
ProductPackage p = Iterables.find(accountClient.getActivePackages(),named(virtualGuestPackageName));
ProductPackage p = Iterables.find(accountClient.getActivePackages(), named(virtualGuestPackageName));
return productPackageClient.getProductPackage(p.getId());
}
@ -224,10 +186,12 @@ public class SoftLayerComputeServiceAdapter implements
@Override
public void destroyNode(String id) {
VirtualGuest guest = getNode(id);
if(guest==null) return;
if (guest == null)
return;
BillingItemVirtualGuest billingItem = guest.getBillingItem();
if (billingItem==null) return;
if (billingItem == null)
return;
client.getVirtualGuestClient().cancelService(billingItem.getId());
}

View File

@ -31,30 +31,38 @@ public class ProductOrderReceipt implements Comparable<ProductOrderReceipt> {
public static class Builder {
private int orderId = -1;
private ProductOrder orderDetails;
public Builder orderId(int orderId) {
this.orderId = orderId;
return this;
}
public Builder orderDetails(ProductOrder orderDetails) {
this.orderDetails = orderDetails;
return this;
}
public ProductOrderReceipt build() {
return new ProductOrderReceipt(orderId);
return new ProductOrderReceipt(orderId,orderDetails);
}
public static Builder fromAddress(ProductOrderReceipt in) {
return ProductOrderReceipt.builder().orderId(in.getOrderId());
return ProductOrderReceipt.builder().orderId(in.getOrderId()).orderDetails(in.getOrderDetails());
}
}
private int orderId = -1;
private ProductOrder orderDetails;
// for deserializer
ProductOrderReceipt() {
}
public ProductOrderReceipt(int orderId) {
public ProductOrderReceipt(int orderId,ProductOrder orderDetails) {
this.orderId = orderId;
this.orderDetails = orderDetails;
}
@Override
@ -69,6 +77,16 @@ public class ProductOrderReceipt implements Comparable<ProductOrderReceipt> {
return orderId;
}
/**
* This is a copy of the SoftLayer_Container_Product_Order
* which holds all the data related to an order.
* This will only return when an order is processed successfully.
* It will contain all the items in an order as well as the order totals.
*/
public ProductOrder getOrderDetails() {
return orderDetails;
}
public Builder toBuilder() {
return Builder.fromAddress(this);
}
@ -97,7 +115,7 @@ public class ProductOrderReceipt implements Comparable<ProductOrderReceipt> {
@Override
public String toString() {
return "[orderId=" + orderId + "]";
return "[orderId=" + orderId + ", orderDetails="+orderDetails+"]";
}

View File

@ -33,6 +33,12 @@ 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";
/**
* number of milliseconds to wait for an order to arrive on the api.
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_ORDER_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)

View File

@ -24,6 +24,7 @@ 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;
@ -66,7 +67,7 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
@Test
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo";
String name = "foo-ef4";
String name = "node"+new Random().nextInt();
Template template = computeContext.getComputeService().templateBuilder()
.locationId("3") // the default (singapore) doesn't work.
.build();