* 'master' of https://github.com/jsonking/jclouds:
  Issue 158: Removed function to find virtual guest - no longer needed
  issue 384: IsoToMachine + Test started
  issue 384: IsoToMachine + Test started
  Issue 158: Property/Predicate/finder to test that the product order got created. Initial timeout of 5s
  added option to specify domainName as an option when using softlayer
  fixed location for openhosting to FL, not VA
This commit is contained in:
Adrian Cole 2011-09-30 11:14:16 -07:00
commit ae98f06d99
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();