Merge pull request #78 from jsonking/master

Issue 158: Functions for Image and Hardware. Implemented SoftLayerComputeServiceAdapter listImages/listHardwareProfiles methods
This commit is contained in:
Adrian Cole 2011-09-27 09:04:20 -07:00
commit 94c74a7424
17 changed files with 834 additions and 178 deletions

View File

@ -18,34 +18,36 @@
*/
package org.jclouds.softlayer.compute.config;
import java.util.Set;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
import org.jclouds.softlayer.compute.functions.ProductItemPriceToImage;
import org.jclouds.softlayer.compute.functions.ProductItemPricesToHardware;
import org.jclouds.softlayer.compute.functions.ProductItemToImage;
import org.jclouds.softlayer.compute.functions.ProductItemsToHardware;
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.VirtualGuest;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.TypeLiteral;
import java.util.Set;
/**
*
* @author Adrian Cole
*/
public class SoftLayerComputeServiceContextModule extends
ComputeServiceAdapterContextModule<SoftLayerClient, SoftLayerAsyncClient, VirtualGuest, Set<ProductItemPrice>, ProductItemPrice, Datacenter> {
ComputeServiceAdapterContextModule<SoftLayerClient, SoftLayerAsyncClient, VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
public SoftLayerComputeServiceContextModule() {
super(SoftLayerClient.class, SoftLayerAsyncClient.class);
@ -54,17 +56,25 @@ public class SoftLayerComputeServiceContextModule extends
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Set<ProductItemPrice>, ProductItemPrice, Datacenter>>() {
}).to(SoftLayerComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {
}).to(VirtualGuestToNodeMetadata.class);
bind(new TypeLiteral<Function<ProductItemPrice, org.jclouds.compute.domain.Image>>() {
}).to(ProductItemPriceToImage.class);
bind(new TypeLiteral<Function<Set<ProductItemPrice>, org.jclouds.compute.domain.Hardware>>() {
}).to(ProductItemPricesToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>() {
}).to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
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);
}
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.osFamily(OsFamily.UBUNTU)
.osVersionMatches("1[10].[10][04]")
.os64Bit(true)
.osDescriptionMatches(".*Minimal Install.*")
.minCores(2);
}
}

View File

@ -1,61 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute.functions;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.softlayer.domain.ProductItemPrice;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ProductItemPriceToImage implements Function<ProductItemPrice, Image> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Override
public Image apply(ProductItemPrice from) {
ImageBuilder builder = new ImageBuilder();
//TODO
// builder.ids(from.id + "");
// builder.name(from.name);
// builder.description(from.name);
//
// OsFamily family = null;
// try {
// family = OsFamily.fromValue(from.name);
// builder.operatingSystem(new OperatingSystem.Builder().name(from.name).family(family).build());
// } catch (IllegalArgumentException e) {
// logger.debug("<< didn't match os(%s)", from);
// }
return builder.build();
}
}

View File

@ -1,48 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute.functions;
import java.util.Set;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.softlayer.domain.ProductItemPrice;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ProductItemPricesToHardware implements Function<Set<ProductItemPrice>, Hardware> {
@Override
public Hardware apply(Set<ProductItemPrice> from) {
HardwareBuilder builder = new HardwareBuilder();
// builder.ids(from.id + "");
// builder.name(from.name);
// builder.processors(ImmutableList.of(new Processor(from.cores, 1.0)));
// builder.ram(from.ram);
// builder.volumes(ImmutableList.<Volume> of(new VolumeImpl(from.disk, true, false)));
return builder.build();
}
}

View File

@ -0,0 +1,169 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute.functions;
import com.google.common.base.Function;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Jason King
*/
@Singleton
public class ProductItemToImage implements Function<ProductItem, Image> {
/** Pattern to capture the number of bits e.g. "a (32 bit) os" */
private static final Pattern OS_BITS_PATTERN = Pattern.compile(".*\\((\\d+) ?bit\\).*");
private static final String CENTOS = "CentOS";
private static final String DEBIAN = "Debian GNU/Linux";
private static final String FEDORA = "Fedora Release";
private static final String RHEL = "Red Hat Enterprise Linux";
private static final String UBUNTU = "Ubuntu Linux";
private static final String WINDOWS = "Windows Server";
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Override
public Image apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
OsFamily family = osFamily().apply(productItem);
Integer bits = osBits().apply(productItem);
OperatingSystem os = OperatingSystem.builder()
.description(productItem.getDescription())
.family(family)
.version(osVersion().apply(productItem))
.is64Bit(bits.equals(64))
.build();
return new ImageBuilder()
.id(imageId().apply(productItem))
.description(productItem.getDescription())
.operatingSystem(os)
.build();
}
/**
* Parses the item description to determine the OSFamily
* @return the @see OsFamily or OsFamily.UNRECOGNIZED
*/
public static Function<ProductItem,OsFamily> osFamily() {
return new Function<ProductItem,OsFamily>() {
@Override
public OsFamily apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
final String description = productItem.getDescription();
if(description.startsWith(CENTOS)) return OsFamily.CENTOS;
else if(description.startsWith(DEBIAN)) return OsFamily.DEBIAN;
else if(description.startsWith(FEDORA)) return OsFamily.FEDORA;
else if(description.startsWith(RHEL)) return OsFamily.RHEL;
else if(description.startsWith(UBUNTU)) return OsFamily.UBUNTU;
else if(description.startsWith(WINDOWS)) return OsFamily.WINDOWS;
return OsFamily.UNRECOGNIZED;
}
};
}
/**
* Parses the item description to determine the os version
* @return the version
* @throws java.util.NoSuchElementException if the version cannot be determined
*/
public static Function<ProductItem,String> osVersion() {
return new Function<ProductItem,String>() {
@Override
public String apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
final String description = productItem.getDescription();
OsFamily family = osFamily().apply(productItem);
if (family.equals(OsFamily.CENTOS)) return parseVersion(description, CENTOS);
else if(family.equals(OsFamily.DEBIAN)) return parseVersion(description, DEBIAN);
else if(family.equals(OsFamily.FEDORA)) return parseVersion(description, FEDORA);
else if(family.equals(OsFamily.RHEL)) return parseVersion(description, RHEL);
else if(family.equals(OsFamily.UBUNTU)) return parseVersion(description, UBUNTU);
else if(family.equals(OsFamily.WINDOWS)) return parseVersion(description, WINDOWS);
else throw new NoSuchElementException("No os version for item:"+productItem);
}
};
}
private static String parseVersion(String description, String os) {
String noOsName = description.replaceFirst(os,"").trim();
return noOsName.split(" ")[0];
}
/**
* Parses the item description to determine the number of OS bits
* Expects the number to be in parenthesis and to contain the word "bit".
* The following return 64: "A (64 bit) OS", "A (64bit) OS"
* @return the number of bits
* @throws java.util.NoSuchElementException if the number of bits cannot be determined
*/
public static Function<ProductItem,Integer> osBits() {
return new Function<ProductItem,Integer>() {
@Override
public Integer apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
Matcher m = OS_BITS_PATTERN.matcher(productItem.getDescription());
if (m.matches()) {
return Integer.parseInt(m.group(1));
} else {
throw new NoSuchElementException("Cannot determine os-bits for item:"+productItem);
}
}
};
}
/**
* Generates an id for an Image.
* @return the generated id
*/
public static Function<ProductItem,String> imageId() {
return new Function<ProductItem,String>() {
@Override
public String apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
ProductItemPrice price = ProductItems.price().apply(productItem);
return ""+price.getId();
}
};
}
}

View File

@ -0,0 +1,91 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute.functions;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
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.*;
/**
* 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> {
private static final double CORE_SPEED = 2.0;
@Override
public Hardware apply(Set<ProductItem> items) {
ProductItem coresItem = getOnlyElement(filter(items, units("PRIVATE_CORE")));
ProductItem ramItem = getOnlyElement(filter(items, categoryCode("ram")));
ProductItem volumeItem = getOnlyElement(filter(items, matches(SoftLayerComputeServiceAdapter.SAN_DESCRIPTION_REGEX)));
final String hardwareId = hardwareId().apply(ImmutableList.of(coresItem, ramItem, volumeItem));
final double cores = ProductItems.capacity().apply(coresItem).doubleValue();
final int ram = ProductItems.capacity().apply(ramItem).intValue();
final float volumeSize = ProductItems.capacity().apply(volumeItem);
return new HardwareBuilder()
.id(hardwareId)
.processors(ImmutableList.of(new Processor(cores, CORE_SPEED)))
.ram(ram)
.volumes(ImmutableList.<Volume> of(new VolumeImpl(volumeSize, true, 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>() {
@Override
public String apply(List<ProductItem> productItems) {
StringBuilder builder = new StringBuilder();
for(ProductItem item:productItems) {
ProductItemPrice price = ProductItems.price().apply(item);
builder.append(price.getId())
.append(",");
}
return builder.toString().substring(0,builder.lastIndexOf(","));
}
};
}
}

View File

@ -49,14 +49,13 @@ import com.google.common.collect.ImmutableSet;
@Singleton
public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMetadata> {
//TODO: There may be more states than this.
public static final Map<VirtualGuest.State, NodeState> serverStateToNodeState = ImmutableMap
.<VirtualGuest.State, NodeState> builder()
.put(VirtualGuest.State.RUNNING, NodeState.RUNNING)
.put(VirtualGuest.State.PAUSED, NodeState.SUSPENDED)
.put(VirtualGuest.State.HALTED, NodeState.PENDING)
.put(VirtualGuest.State.UNRECOGNIZED, NodeState.UNRECOGNIZED)
.build();
.put(VirtualGuest.State.HALTED, NodeState.PENDING)
.put(VirtualGuest.State.PAUSED, NodeState.SUSPENDED)
.put(VirtualGuest.State.RUNNING, NodeState.RUNNING)
.put(VirtualGuest.State.UNRECOGNIZED, NodeState.UNRECOGNIZED)
.build();
private final FindHardwareForVirtualGuest findHardwareForVirtualGuest;
private final FindLocationForVirtualGuest findLocationForVirtualGuest;

View File

@ -18,29 +18,31 @@
*/
package org.jclouds.softlayer.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
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.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.predicates.ProductPackagePredicates;
import org.jclouds.softlayer.compute.functions.ProductItems;
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.collect.ImmutableSet;
import com.google.common.collect.Iterables;
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.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
@ -49,7 +51,12 @@ import com.google.common.collect.Iterables;
*/
@Singleton
public class SoftLayerComputeServiceAdapter implements
ComputeServiceAdapter<VirtualGuest, Set<ProductItemPrice>, ProductItemPrice, Datacenter> {
ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> {
public static final String SAN_DESCRIPTION_REGEX=".*GB \\(SAN\\).*";
//TODO: Better to pass this in as a property like virtualGuestPackageName?
private static final Float BOOT_VOLUME_CAPACITY = 100F;
private final SoftLayerClient client;
private final String virtualGuestPackageName;
@ -76,15 +83,37 @@ public class SoftLayerComputeServiceAdapter implements
}
@Override
public Iterable<Set<ProductItemPrice>> listHardwareProfiles() {
// TODO: get the set of product item prices corresponding to the hardware profiles
return ImmutableSet.of();
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")));
Map<Float, ProductItem> cpuMap = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
Map<Float, ProductItem> ramMap = Maps.uniqueIndex(ramItems, ProductItems.capacity());
Map<Float, ProductItem> sanMap = Maps.uniqueIndex(sanItems, ProductItems.capacity());
final ProductItem bootVolume = sanMap.get(BOOT_VOLUME_CAPACITY);
assert bootVolume!=null : "Boot volume capacity not found:"+BOOT_VOLUME_CAPACITY+", available:"+sanItems;
Set<Set<ProductItem>> result = Sets.newLinkedHashSet();
for(Map.Entry<Float, ProductItem> coresEntry : cpuMap.entrySet()) {
Float cores = coresEntry.getKey();
ProductItem ramItem = ramMap.get(cores);
//Amount of RAM and number of cores must match.
if(ramItem==null) continue;
result.add(ImmutableSet.of(coresEntry.getValue(),ramItem,bootVolume));
}
return result;
}
@Override
public Iterable<ProductItemPrice> listImages() {
// TODO: get the list of product item prices corresponding to images
return ImmutableSet.of();
public Iterable<ProductItem> listImages() {
return Iterables.filter(getProductPackage().getItems(), categoryCode("os"));
}
@Override
@ -94,10 +123,15 @@ public class SoftLayerComputeServiceAdapter implements
@Override
public Iterable<Datacenter> listLocations() {
// TODO we should be able to specify a filter that gets the datacenters here.
ProductPackage virtualGuestPackage = Iterables.find(client.getAccountClient().getActivePackages(),
ProductPackagePredicates.named(virtualGuestPackageName));
return client.getProductPackageClient().getProductPackage(virtualGuestPackage.getId()).getDatacenters();
return getProductPackage().getDatacenters();
}
private ProductPackage getProductPackage() {
AccountClient accountClient = client.getAccountClient();
ProductPackageClient productPackageClient = client.getProductPackageClient();
ProductPackage p = Iterables.find(accountClient.getActivePackages(),named(virtualGuestPackageName));
return productPackageClient.getProductPackage(p.getId());
}
@Override
@ -108,8 +142,13 @@ public class SoftLayerComputeServiceAdapter implements
@Override
public void destroyNode(String id) {
// TODO
// client.getVirtualGuestClient().destroyVirtualGuest(Long.parseLong(id));
VirtualGuest guest = getNode(id);
if(guest==null) return;
BillingItemVirtualGuest billingItem = guest.getBillingItem();
if (billingItem==null) return;
client.getVirtualGuestClient().cancelService(billingItem.getId());
}
@Override

View File

@ -205,14 +205,13 @@ public class VirtualGuest implements Comparable<VirtualGuest> {
}
/**
* TBD: These states come from the powerState field. i.e.
* These states come from the powerState field. i.e.
* https://api.softlayer.com/rest/v3/SoftLayer_Account/getVirtualGuests/{id}?objectMask=powerState
*/
public static enum State {
//ACTIVE, // Get this from https://api.softlayer.com/rest/v3/SoftLayer_Virtual_Guest/{id}/getStatus
HALTED,
PAUSED,
RUNNING,
HALTED,
UNRECOGNIZED;
@Override

View File

@ -22,6 +22,8 @@ import com.google.common.base.Predicate;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemCategory;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
public class ProductItemPredicates {
@ -73,9 +75,8 @@ public class ProductItemPredicates {
};
}
/**
/**
* Tests if the ProductItem has the required units.
* TODO Write test method
* @param units
* @return true if it does, otherwise false.
*/
@ -94,4 +95,28 @@ public class ProductItemPredicates {
}
};
}
/**
* Tests if the ProductItem's description matches the supplied regular expression.
* @param regex a regular expression to match against.
* @return true if it does, otherwise false.
* @throws java.util.regex.PatternSyntaxException if the regex is invalid
*/
public static Predicate<ProductItem> matches(final String regex) {
checkNotNull(regex, "regex cannot be null");
final Pattern PATTERN = Pattern.compile(regex);
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
return PATTERN.matcher(productItem.getDescription()).matches();
}
@Override
public String toString() {
return "regex("+regex+")";
}
};
}
}

View File

@ -34,11 +34,6 @@ public interface SoftLayerConstants {
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME = "jclouds.softlayer.virtualguest.package-name";
/**
* Name of the package used for ordering virtual guests.
*/
public static final String CLOUD_SERVER_PACKAGE_NAME = "Cloud Server";
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

View File

@ -0,0 +1,70 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.features.BaseSoftLayerClientLiveTest;
import org.jclouds.softlayer.features.ProductPackageClientLiveTest;
import org.testng.Assert;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import java.util.LinkedHashSet;
import java.util.Set;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.testng.Assert.assertFalse;
import static org.testng.AssertJUnit.assertEquals;
@Test(groups = "live", testName = "SoftLayerComputeServiceAdapterLiveTest")
public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientLiveTest {
private SoftLayerComputeServiceAdapter adapter;
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();
adapter = new SoftLayerComputeServiceAdapter(context.getApi(), ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME);
}
@Test
public void testListLocations() {
assertFalse(Iterables.isEmpty(adapter.listLocations()));
}
@Test
public void testListHardwareProfiles() {
Iterable<Set<ProductItem>> profiles = adapter.listHardwareProfiles();
assertFalse(Iterables.isEmpty(profiles));
for( Set<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")));
Assert.assertEquals(cpuItem.getCapacity(),ramItem.getCapacity());
}
}
}

View File

@ -0,0 +1,89 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Template;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.Set;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
/**
*
* @author Jason King
*/
@Test(groups = "live")
public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public SoftLayerTemplateBuilderLiveTest() {
provider = "softlayer";
}
/// allows us to break when a new os is added
@Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return Predicates.not(new Predicate<OsFamilyVersion64Bit>() {
@Override
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("10.04") || input.version.equals("8"));
case DEBIAN:
return !(input.version.equals("5.0"));
case FEDORA:
return !(input.version.equals("13") || input.version.equals("15"));
case RHEL:
return !(input.version.equals("5") || input.version.equals("6"));
case CENTOS:
return !(input.version.equals("5") || input.version.equals("6.0"));
case WINDOWS:
return !(input.version.equals("2003") || input.version.equals("2008"));
default:
return false;
}
}
});
}
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
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);
}
@Override
protected Set<String> getIso3166Codes() {
return ImmutableSet.<String> of("US-IL", "US-TX", "US-MO");
}
}

View File

@ -0,0 +1,169 @@
package org.jclouds.softlayer.compute.functions;
import com.google.common.collect.ImmutableSet;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import static org.jclouds.softlayer.compute.functions.ProductItemToImage.*;
import static org.testng.AssertJUnit.*;
/**
* Tests {@code ProductItemToImage}
*
* @author Jason King
*/
@Test(groups = "unit")
public class ProductItemToImageTest {
// Operating Systems available SEPT 2011
private static final List<String> operatingSystems = Arrays.asList(
"CentOS 5 - LAMP Install (32 bit)",
"CentOS 5 - LAMP Install (64 bit)",
"CentOS 5 - Minimal Install (32 bit)",
"CentOS 5 - Minimal Install (64 bit)",
"CentOS 6.0 - LAMP Install (32 bit)",
"CentOS 6.0 - LAMP Install (64 bit)",
"CentOS 6.0 - Minimal Install (32 bit)",
"CentOS 6.0 - Minimal Install (64 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (32 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (64 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (32 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (64 bit)",
"Fedora Release 13 (32bit) - LAMP Install",
"Fedora Release 13 (32bit) - Minimal Install",
"Fedora Release 13 (64bit) - LAMP Install",
"Fedora Release 13 (64bit) - Minimal Install",
"Fedora Release 15 (32bit) - LAMP Install",
"Fedora Release 15 (32bit) - Minimal Install",
"Fedora Release 15 (64bit) - LAMP Install",
"Fedora Release 15 (64bit) - Minimal Install",
"Red Hat Enterprise Linux 5 - LAMP Install (32 bit)",
"Red Hat Enterprise Linux 5 - LAMP Install (64 bit)",
"Red Hat Enterprise Linux 5 - Minimal Install (64 bit)",
"Red Hat Enterprise Linux 6 - LAMP Install (32 bit)",
"Red Hat Enterprise Linux 6 - LAMP Install (64 bit)",
"Red Hat Enterprise Linux 6 - Minimal Install (32 bit)",
"Red Hat Enterprise Linux 6 - Minimal Install (64 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - LAMP Install (32 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - LAMP Install (64 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (32 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (64 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (32 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (64 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (32 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)",
"Windows Server 2003 Datacenter SP2 with R2 (32 bit)",
"Windows Server 2003 Datacenter SP2 with R2 (64 bit)",
"Windows Server 2003 Enterprise SP2 with R2 (64 bit)",
"Windows Server 2003 Standard SP2 with R2 (64 bit)",
"Windows Server 2008 Datacenter Edition SP2 (32bit)",
"Windows Server 2008 Datacenter Edition SP2 (64bit)",
"Windows Server 2008 Enterprise Edition SP2 (32bit)",
"Windows Server 2008 Enterprise Edition SP2 (64bit)",
"Windows Server 2008 R2 Datacenter Edition (64bit)",
"Windows Server 2008 R2 Enterprise Edition (64bit)",
"Windows Server 2008 R2 Standard Edition (64bit)",
"Windows Server 2008 Standard Edition SP2 (32bit)",
"Windows Server 2008 Standard Edition SP2 (64bit)");
@Test
public void testConversion() {
for( String description : operatingSystems )
{
ProductItem item = ProductItem.builder()
.description(description)
.price(ProductItemPrice.builder().id(1234).build())
.build();
Image i = new ProductItemToImage().apply(item);
OperatingSystem os = i.getOperatingSystem();
assertNotNull(os);
assertNotNull(os.getFamily());
assertFalse(os.getFamily().equals(OsFamily.UNRECOGNIZED));
assertNotNull(os.getVersion());
}
}
@Test
public void testUbuntu() {
ProductItem item = ProductItem.builder()
.description("Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (64 bit)")
.price(ProductItemPrice.builder().id(1234).build())
.build();
Image i = new ProductItemToImage().apply(item);
OperatingSystem os = i.getOperatingSystem();
assertNotNull(os);
assertEquals(OsFamily.UBUNTU, os.getFamily());
assertEquals("10.04",os.getVersion());
assertTrue(os.is64Bit());
}
@Test
public void testId() {
ProductItemPrice price = ProductItemPrice.builder().id(1234).build();
ProductItem item = ProductItem.builder().price(price).build();
assertEquals("1234",imageId().apply(item));
}
@Test
public void testIdManyPrices() {
ProductItemPrice price1 = ProductItemPrice.builder().id(1234).build();
ProductItemPrice price2 = ProductItemPrice.builder().id(5678).build();
ProductItem item = ProductItem.builder().prices(ImmutableSet.of(price1,price2)).build();
assertEquals("1234",imageId().apply(item));
}
@Test(expectedExceptions = NoSuchElementException.class)
public void testIdMissingPrices() {
ProductItem item = ProductItem.builder().build();
imageId().apply(item);
}
@Test
public void testOsFamily() {
ProductItem item = ProductItem.builder().description("Ubuntu Linux os").build();
assertEquals(OsFamily.UBUNTU,osFamily().apply(item));
}
@Test
public void testOsFamilyUnrecognized() {
ProductItem item = ProductItem.builder().description("not a known operating system").build();
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply(item));
}
@Test
public void testBitsWithSpace() {
ProductItem item = ProductItem.builder().description("a (32 bit) os").build();
assertEquals(osBits().apply(item),new Integer(32));
}
@Test
public void testBitsNoSpace() {
ProductItem item = ProductItem.builder().description("a (64bit) os").build();
assertEquals(osBits().apply(item),new Integer(64));
}
@Test(expectedExceptions = NoSuchElementException.class)
public void testBitsMissing() {
ProductItem item = ProductItem.builder().description("an os").build();
osBits().apply(item);
}
@Test
public void testOsVersion() {
ProductItem item = ProductItem.builder().description("Windows Server 2099 (256 bit)").build();
assertEquals("2099",osVersion().apply(item));
}
@Test(expectedExceptions = NoSuchElementException.class)
public void testOsVersionMissing() {
ProductItem item = ProductItem.builder().description("asd Server").build();
osVersion().apply(item);
}
}

View File

@ -0,0 +1,93 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.softlayer.compute.functions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
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;
/**
* Tests {@code ProductItemsToHardware}
*
* @author Jason King
*/
@Test(groups = "unit")
public class ProductItemsToHardwareTest {
@Test
public void testHardwareId() {
ProductItem item1 = ProductItem.builder().price(ProductItemPrice.builder().id(123).build()).build();
ProductItem item2 = ProductItem.builder().price(ProductItemPrice.builder().id(456).build()).build();
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);
}
@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 volumeItem = ProductItem.builder()
.id(3)
.description("100 GB (SAN)")
.capacity(100F)
.price(ProductItemPrice.builder().id(789).build())
.build();
Hardware hardware = new ProductItemsToHardware().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(2, hardware.getRam());
List<? extends Volume> volumes = hardware.getVolumes();
assertEquals(1,volumes.size());
assertEquals(100F,volumes.get(0).getSize());
}
}

View File

@ -32,7 +32,6 @@ import java.util.Set;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import static org.jclouds.softlayer.reference.SoftLayerConstants.CLOUD_SERVER_PACKAGE_NAME;
import static org.testng.Assert.*;
/**
@ -42,6 +41,14 @@ import static org.testng.Assert.*;
*/
@Test(groups = "live")
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}
*/
public static final String CLOUD_SERVER_PACKAGE_NAME = "Cloud Server";
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();

View File

@ -34,7 +34,6 @@ import java.util.Set;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import static org.jclouds.softlayer.reference.SoftLayerConstants.CLOUD_SERVER_PACKAGE_NAME;
import static org.testng.Assert.*;
/**
@ -81,7 +80,7 @@ public class VirtualGuestClientLiveTest extends BaseSoftLayerClientLiveTest {
}
}
int pkgId = Iterables.find(context.getApi().getAccountClient().getActivePackages(),named(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(),

View File

@ -38,6 +38,7 @@ public class ProductItemPredicatesTest {
ramCategory = ProductItemCategory.builder().id(1).categoryCode("ram").build();
item = ProductItem.builder().id(1)
.description("a test item")
.categories(ImmutableSet.of(ramCategory))
.capacity(2.0f)
.units("GB")
@ -88,4 +89,14 @@ public class ProductItemPredicatesTest {
public void testUnitsMissing() {
assertFalse(ProductItemPredicates.units("Kg").apply(item));
}
@Test
public void testMatchesRegex() {
assert ProductItemPredicates.matches(".*test.*").apply(item);
}
@Test
public void testNoMatchRegex() {
assertFalse(ProductItemPredicates.matches("no match").apply(item));
}
}