Issue 888: consolidate code that addresses naming conventions, using hyphen as default delimiter

This commit is contained in:
Adrian Cole 2012-03-27 14:01:10 -04:00
parent 5c6ce9f081
commit 49e475edcd
44 changed files with 891 additions and 356 deletions

View File

@ -19,7 +19,6 @@
package org.jclouds.cloudservers.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -39,6 +38,7 @@ 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.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
@ -63,6 +63,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
protected final Map<ServerStatus, NodeState> serverToNodeState;
protected final Supplier<Set<? extends Image>> images;
protected final Supplier<Set<? extends Hardware>> hardwares;
protected final GroupNamingConvention nodeNamingConvention;
private static class FindImageForServer implements Predicate<Image> {
private final Server instance;
@ -93,7 +94,9 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Inject
ServerToNodeMetadata(Map<ServerStatus, NodeState> serverStateToNodeState,
@Memoized Supplier<Set<? extends Image>> images, Supplier<Location> location,
@Memoized Supplier<Set<? extends Hardware>> hardwares) {
@Memoized Supplier<Set<? extends Hardware>> hardwares,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState");
this.images = checkNotNull(images, "images");
this.location = checkNotNull(location, "location");
@ -109,7 +112,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
builder.location(new LocationBuilder().scope(LocationScope.HOST).id(from.getHostId()).description(
from.getHostId()).parent(location.get()).build());
builder.userMetadata(from.getMetadata());
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.imageId(from.getImageId() + "");
builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from));

View File

@ -38,6 +38,7 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
@ -47,13 +48,15 @@ import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
@Test(groups = "unit", testName = "ServerToNodeMetadataTest")
public class ServerToNodeMetadataTest {
Location provider = new LocationBuilder().scope(LocationScope.ZONE).id("dallas").description("description").build();
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@Test
public void testApplyWhereImageAndHardwareNotFound() {
@ -63,7 +66,7 @@ public class ServerToNodeMetadataTest {
Server server = ParseServerFromJsonResponseTest.parseServer();
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server);
@ -77,6 +80,7 @@ public class ServerToNodeMetadataTest {
.id("1234")
.providerId("1234")
.name("sample-server")
.group("sample")
.hostname("sample-server")
.location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")
@ -94,7 +98,7 @@ public class ServerToNodeMetadataTest {
Server server = ParseServerFromJsonResponseTest.parseServer();
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server);
@ -112,6 +116,7 @@ public class ServerToNodeMetadataTest {
.providerId("1234")
.name("sample-server")
.hostname("sample-server")
.group("sample")
.location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")
.description("e4d909c290d0fb1ca068ffaddf22cbd0").parent(provider).build())
@ -127,7 +132,7 @@ public class ServerToNodeMetadataTest {
Server server = ParseServerFromJsonResponseTest.parseServer();
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
.ofInstance(provider), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server);
@ -153,6 +158,7 @@ public class ServerToNodeMetadataTest {
.id("1234")
.providerId("1234")
.name("sample-server")
.group("sample")
.hostname("sample-server")
.location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")

View File

@ -19,7 +19,6 @@
package org.jclouds.cloudsigma.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.Set;
@ -43,6 +42,7 @@ import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
@ -73,24 +73,26 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
private final Function<String, Image> findImageForId;
private final Supplier<Location> locationSupplier;
private final Function<Device, Volume> deviceToVolume;
private final GroupNamingConvention nodeNamingConvention;
@Inject
ServerInfoToNodeMetadata(Function<Server, String> getImageIdFromServer, Function<String, Image> findImageForId,
Function<Device, Volume> deviceToVolume, Supplier<Location> locationSupplier) {
Function<Device, Volume> deviceToVolume, Supplier<Location> locationSupplier,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
this.deviceToVolume = checkNotNull(deviceToVolume, "deviceToVolume");
this.findImageForId = checkNotNull(findImageForId, "findImageForId");
this.getImageIdFromServer = checkNotNull(getImageIdFromServer, "getImageIdFromServer");
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public NodeMetadata apply(ServerInfo from) {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(from.getUuid());
builder.name(from.getName());
builder.location(locationSupplier.get());
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
String imageId = getImageIdFromServer.apply(from);
if (imageId != null) {

View File

@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import static org.jclouds.util.InetAddresses2.isPrivateIPAddress;
import java.util.Map;
@ -44,6 +43,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.util.Throwables2;
@ -79,11 +79,14 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
private final FindLocationForVirtualMachine findLocationForVirtualMachine;
private final FindImageForVirtualMachine findImageForVirtualMachine;
private final LoadingCache<Long, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine;
private final GroupNamingConvention nodeNamingConvention;
@Inject
VirtualMachineToNodeMetadata(FindLocationForVirtualMachine findLocationForVirtualMachine,
FindImageForVirtualMachine findImageForVirtualMachine,
LoadingCache<Long, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine) {
LoadingCache<Long, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.findLocationForVirtualMachine = checkNotNull(findLocationForVirtualMachine, "findLocationForVirtualMachine");
this.findImageForVirtualMachine = checkNotNull(findImageForVirtualMachine, "findImageForVirtualMachine");
this.getIPForwardingRulesByVirtualMachine = checkNotNull(getIPForwardingRulesByVirtualMachine,
@ -104,7 +107,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
// on hosts not started with jclouds
builder.hostname(from.getDisplayName());
builder.location(findLocationForVirtualMachine.apply(from));
builder.group(parseGroupFromName(from.getDisplayName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getDisplayName()));
Image image = findImageForVirtualMachine.apply(from);
if (image != null) {
builder.imageId(image.getId());

View File

@ -37,6 +37,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.domain.Location;
import org.jclouds.rest.ResourceNotFoundException;
@ -48,6 +49,7 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Guice;
/**
* @author Adrian Cole, Andrei Savu
@ -55,6 +57,8 @@ import com.google.common.collect.Iterables;
@Test(groups = "unit", testName = "VirtualMachineToNodeMetadataTest")
public class VirtualMachineToNodeMetadataTest {
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@Test
public void testApplyWhereVirtualMachineWithIPForwardingRule() throws UnknownHostException {
@ -73,7 +77,7 @@ public class VirtualMachineToNodeMetadataTest {
return ImmutableSet.of(IPForwardingRule.builder().id(1234l).IPAddress("1.1.1.1").build());
}
}));
}), namingConvention);
// notice if we've already parsed this properly here, we can rely on it.
VirtualMachine guest = Iterables.get(new ListVirtualMachinesResponseTest().expected(), 0);
@ -82,7 +86,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals(
node.toString(),
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3")
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54")
.location(ZoneToLocationTest.one).state(NodeState.PENDING).hostname("i-3-54-VM")
.privateAddresses(ImmutableSet.of("10.1.1.18")).publicAddresses(ImmutableSet.of("1.1.1.1"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))
@ -109,7 +113,7 @@ public class VirtualMachineToNodeMetadataTest {
return ImmutableSet.of();
}
}));
}), namingConvention);
VirtualMachine guest =VirtualMachine.builder()
.id(54)
@ -145,7 +149,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals(
node.toString(),
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3")
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54")
.location(ZoneToLocationTest.one).state(NodeState.PENDING).hostname("i-3-54-VM")
.privateAddresses(ImmutableSet.<String>of())
.publicAddresses(ImmutableSet.<String>of("1.1.1.5"))
@ -172,7 +176,7 @@ public class VirtualMachineToNodeMetadataTest {
throw new ResourceNotFoundException("no ip forwarding rule for: " + arg0);
}
}));
}), namingConvention);
// notice if we've already parsed this properly here, we can rely on it.
VirtualMachine guest = Iterables.get(new ListVirtualMachinesResponseTest().expected(), 0);
@ -181,7 +185,7 @@ public class VirtualMachineToNodeMetadataTest {
assertEquals(
node.toString(),
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3")
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").group("i-3-54")
.location(ZoneToLocationTest.one).state(NodeState.PENDING).hostname("i-3-54-VM")
.privateAddresses(ImmutableSet.of("10.1.1.18"))
.hardware(addHypervisor(ServiceOfferingToHardwareTest.one, "XenServer"))

View File

@ -19,7 +19,6 @@
package org.jclouds.deltacloud.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -37,6 +36,7 @@ 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.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.deltacloud.domain.Instance;
import org.jclouds.domain.Location;
@ -67,6 +67,7 @@ public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata>
protected final Supplier<Set<? extends Location>> locations;
protected final Supplier<Set<? extends Image>> images;
protected final Supplier<Set<? extends Hardware>> hardwares;
protected final GroupNamingConvention nodeNamingConvention;
private static class FindImageForInstance implements Predicate<Image> {
private final Instance instance;
@ -136,7 +137,9 @@ public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata>
@Inject
InstanceToNodeMetadata(@Memoized Supplier<Set<? extends Location>> locations,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.images = checkNotNull(images, "images");
this.locations = checkNotNull(locations, "locations");
this.hardwares = checkNotNull(hardwares, "hardwares");
@ -148,7 +151,7 @@ public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata>
builder.ids(from.getHref().toASCIIString());
builder.name(from.getName());
builder.location(parseLocation(from));
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.imageId(from.getImage().toASCIIString());
builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from));

View File

@ -36,7 +36,7 @@ import com.google.common.base.Supplier;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
@Test(groups = "unit", testName = "CreateUniqueKeyPairTest")
public class CreateUniqueKeyPairTest {
@SuppressWarnings( { "unchecked" })
@Test

View File

@ -19,7 +19,6 @@
package org.jclouds.elasticstack.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.List;
import java.util.Map;
@ -39,6 +38,7 @@ import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.elasticstack.domain.Device;
import org.jclouds.elasticstack.domain.DriveInfo;
@ -74,10 +74,13 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
private final Function<String, Image> findImageForId;
private final Supplier<Location> locationSupplier;
private final Function<Device, Volume> deviceToVolume;
private final GroupNamingConvention nodeNamingConvention;
@Inject
ServerInfoToNodeMetadata(Function<Server, String> getImageIdFromServer, Function<String, Image> findImageForId,
Function<Device, Volume> deviceToVolume, Supplier<Location> locationSupplier) {
Function<Device, Volume> deviceToVolume, Supplier<Location> locationSupplier,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
this.deviceToVolume = checkNotNull(deviceToVolume, "deviceToVolume");
this.findImageForId = checkNotNull(findImageForId, "findImageForId");
@ -91,7 +94,7 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
builder.ids(from.getUuid());
builder.name(from.getName());
builder.location(locationSupplier.get());
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
String imageId = getImageIdFromServer.apply(from);
if (imageId != null) {

View File

@ -19,7 +19,6 @@
package org.jclouds.openstack.nova.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -36,6 +35,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
@ -63,6 +63,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
protected final Map<ServerStatus, NodeState> serverToNodeState;
protected final Supplier<Set<? extends Image>> images;
protected final Supplier<Set<? extends Hardware>> hardwares;
protected final GroupNamingConvention nodeNamingConvention;
private static class FindImageForServer implements Predicate<Image> {
private final Server instance;
@ -93,7 +94,9 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Inject
ServerToNodeMetadata(Map<ServerStatus, NodeState> serverStateToNodeState,
@Memoized Supplier<Set<? extends Image>> images, Supplier<Location> location,
@Memoized Supplier<Set<? extends Hardware>> hardwares) {
@Memoized Supplier<Set<? extends Hardware>> hardwares,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState");
this.images = checkNotNull(images, "images");
this.location = checkNotNull(location, "location");
@ -108,7 +111,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
builder.location(new LocationBuilder().scope(LocationScope.HOST).id(from.getHostId()).description(
from.getHostId()).parent(location.get()).build());
builder.userMetadata(from.getMetadata());
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
Image image = parseImage(from);
if (image != null) {
builder.imageId(image.getId());

View File

@ -37,6 +37,7 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
@ -50,6 +51,7 @@ import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
* @author Adrian Cole
@ -57,6 +59,7 @@ import com.google.common.collect.ImmutableSet;
@Test(groups = "unit")
public class ServerToNodeMetadataTest {
Location provider = new LocationBuilder().scope(LocationScope.ZONE).id("dallas").description("description").build();
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@Test
public void testApplyWhereImageAndHardwareNotFound() throws UnknownHostException, NoSuchMethodException,
@ -68,7 +71,7 @@ public class ServerToNodeMetadataTest {
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState,
Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers.ofInstance(provider),
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server);
@ -85,6 +88,7 @@ public class ServerToNodeMetadataTest {
.privateAddresses(ImmutableSet.of("10.176.42.16", "::babe:10.176.42.16"))
.id("1234")
.providerId("1234")
.group("sample")
.name("sample-server")
.location(
new LocationBuilder().scope(LocationScope.HOST).id("e4d909c290d0fb1ca068ffaddf22cbd0")
@ -104,7 +108,7 @@ public class ServerToNodeMetadataTest {
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState,
Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers.ofInstance(provider),
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server);
@ -128,12 +132,13 @@ public class ServerToNodeMetadataTest {
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState,
Suppliers.<Set<? extends Image>> ofInstance(images), Suppliers.ofInstance(provider),
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(server);
NodeMetadata constructedMetadata = newNodeMetadataBuilder()
.imageId("2")
.group("sample")
.operatingSystem(
new OperatingSystem.Builder().family(OsFamily.CENTOS).description("CentOS 5.2").version("5.2")
.is64Bit(true).build())

View File

@ -38,6 +38,7 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
@ -67,7 +68,6 @@ import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
@ -79,39 +79,41 @@ import com.google.common.collect.Multimap;
*/
@Singleton
public class NovaComputeService extends BaseComputeService {
private final NovaClient novaClient;
private final LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap;
private final LoadingCache<ZoneAndName, KeyPair> keyPairCache;
private final Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId;
protected final NovaClient novaClient;
protected final LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap;
protected final LoadingCache<ZoneAndName, KeyPair> keyPairCache;
protected final Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId;
protected final GroupNamingConvention.Factory namingConvention;
@Inject
protected NovaComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named("NODE_TERMINATED") Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, NovaClient novaClient,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap,
LoadingCache<ZoneAndName, KeyPair> keyPairCache,
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named("NODE_TERMINATED") Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, NovaClient novaClient,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap,
LoadingCache<ZoneAndName, KeyPair> keyPairCache,
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId,
GroupNamingConvention.Factory namingConvention) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials,
timeouts, executor);
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials, timeouts,
executor);
this.novaClient = checkNotNull(novaClient, "novaClient");
this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
this.orphanedGroupsByZoneId = checkNotNull(orphanedGroupsByZoneId, "orphanedGroupsByZoneId");
this.namingConvention = checkNotNull(namingConvention, "namingConvention");
}
@Override
@ -132,7 +134,7 @@ public class NovaComputeService extends BaseComputeService {
if (securityGroupClient.isPresent()) {
for (String group : groups) {
for (SecurityGroup securityGroup : Iterables.filter(securityGroupClient.get().listSecurityGroups(),
SecurityGroupPredicates.nameEquals("jclouds_" + group))) {
SecurityGroupPredicates.nameMatches(namingConvention.create().containsGroup(group)))) {
ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, securityGroup.getName());
logger.debug(">> deleting securityGroup(%s)", zoneAndName);
securityGroupClient.get().deleteSecurityGroup(securityGroup.getId());
@ -143,16 +145,14 @@ public class NovaComputeService extends BaseComputeService {
}
}
}
private void cleanupOrphanedKeyPairsInZone(Set<String> groups, String zoneId) {
Optional<KeyPairClient> keyPairClient = novaClient.getKeyPairExtensionForZone(zoneId);
if (keyPairClient.isPresent()) {
for (String group : groups) {
for (Map<String, KeyPair> wrapper : keyPairClient.get().listKeyPairs()) {
for (KeyPair pair : Iterables.filter(
wrapper.values(),
Predicates.or(KeyPairPredicates.nameStartsWith("jclouds_" + group + "_"),
KeyPairPredicates.nameEquals("jclouds_" + group)))) {
for (KeyPair pair : Iterables.filter(wrapper.values(),
KeyPairPredicates.nameMatches(namingConvention.create().containsGroup(group)))) {
ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, pair.getName());
logger.debug(">> deleting keypair(%s)", zoneAndName);
keyPairClient.get().deleteKeyPair(pair.getName());
@ -161,7 +161,8 @@ public class NovaComputeService extends BaseComputeService {
logger.debug("<< deleted keypair(%s)", zoneAndName);
}
}
keyPairCache.invalidate(ZoneAndName.fromZoneAndName(zoneId, "jclouds_" + group));
keyPairCache.invalidate(ZoneAndName.fromZoneAndName(zoneId,
namingConvention.create().sharedNameForGroup(group)));
}
}
}

View File

@ -22,7 +22,6 @@ import static org.jclouds.openstack.nova.v1_1.config.NovaProperties.AUTO_ALLOCAT
import static org.jclouds.openstack.nova.v1_1.config.NovaProperties.AUTO_GENERATE_KEYPAIRS;
import static org.jclouds.openstack.nova.v1_1.config.NovaProperties.TIMEOUT_SECURITYGROUP_PRESENT;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -50,13 +49,12 @@ import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.NovaComputeService;
import org.jclouds.openstack.nova.v1_1.compute.NovaComputeServiceAdapter;
import org.jclouds.openstack.nova.v1_1.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.openstack.nova.v1_1.compute.functions.CreateUniqueKeyPair;
import org.jclouds.openstack.nova.v1_1.compute.functions.FlavorInZoneToHardware;
import org.jclouds.openstack.nova.v1_1.compute.functions.ImageInZoneToImage;
import org.jclouds.openstack.nova.v1_1.compute.functions.ImageToOperatingSystem;
import org.jclouds.openstack.nova.v1_1.compute.functions.OrphanedGroupsByZoneId;
import org.jclouds.openstack.nova.v1_1.compute.functions.ServerInZoneToNodeMetadata;
import org.jclouds.openstack.nova.v1_1.compute.loaders.FindKeyPairOrCreate;
import org.jclouds.openstack.nova.v1_1.compute.loaders.CreateUniqueKeyPair;
import org.jclouds.openstack.nova.v1_1.compute.loaders.FindSecurityGroupOrCreate;
import org.jclouds.openstack.nova.v1_1.compute.loaders.LoadFloatingIpsForInstance;
import org.jclouds.openstack.nova.v1_1.compute.options.NovaTemplateOptions;
@ -141,11 +139,8 @@ public class NovaComputeServiceContextModule
bind(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
bind(new TypeLiteral<Function<ZoneAndName, KeyPair>>() {
}).to(CreateUniqueKeyPair.class);
bind(new TypeLiteral<CacheLoader<ZoneAndName, KeyPair>>() {
}).to(FindKeyPairOrCreate.class);
}).to(CreateUniqueKeyPair.class);
}
@Override
@ -194,20 +189,6 @@ public class NovaComputeServiceContextModule
return CacheBuilder.newBuilder().build(in);
}
@Provides
@Singleton
Supplier<String> provideSuffix() {
return new Supplier<String>() {
final SecureRandom random = new SecureRandom();
@Override
public String get() {
return random.nextInt(100) + "";
}
};
}
@Provides
@Singleton
protected Supplier<Map<String, Location>> createLocationIndexedById(

View File

@ -24,7 +24,6 @@ import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.net.Inet4Address;
import java.util.Map;
@ -42,6 +41,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
@ -58,7 +58,8 @@ import com.google.common.base.Supplier;
import com.google.common.net.InetAddresses;
/**
* A function for transforming a nova-specific Server into a generic NodeMetadata object.
* A function for transforming a nova-specific Server into a generic
* NodeMetadata object.
*
* @author Matt Stephenson, Adam Lowe, Adrian Cole
*/
@ -70,10 +71,13 @@ public class ServerInZoneToNodeMetadata implements Function<ServerInZone, NodeMe
protected final Supplier<Map<String, Location>> locationIndex;
protected final Supplier<Set<? extends Image>> images;
protected final Supplier<Set<? extends Hardware>> hardwares;
protected final GroupNamingConvention nodeNamingConvention;
@Inject
public ServerInZoneToNodeMetadata(Supplier<Map<String, Location>> locationIndex,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.locationIndex = checkNotNull(locationIndex, "locationIndex");
this.images = checkNotNull(images, "images");
this.hardwares = checkNotNull(hardwares, "hardwares");
@ -91,17 +95,18 @@ public class ServerInZoneToNodeMetadata implements Function<ServerInZone, NodeMe
builder.name(from.getName());
builder.hostname(from.getName());
builder.location(from.getHostId() != null ? new LocationBuilder().scope(LocationScope.HOST).id(from.getHostId())
.description(from.getHostId()).parent(zone).build() : zone);
.description(from.getHostId()).parent(zone).build() : zone);
builder.userMetadata(from.getMetadata());
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.imageId(ZoneAndId.fromZoneAndId(serverInZone.getZone(), from.getImage().getId()).slashEncode());
builder.operatingSystem(findOperatingSystemForServerOrNull(serverInZone));
builder.hardware(findHardwareForServerOrNull(serverInZone));
builder.state(from.getStatus().getNodeState());
builder.publicAddresses(filter(transform(concat(from.getPublicAddresses(), from.getInternetAddresses()),
AddressToStringTransformationFunction.INSTANCE), isInet4Address));
builder.privateAddresses(filter(transform(from.getPrivateAddresses(),
AddressToStringTransformationFunction.INSTANCE), isInet4Address));
builder.publicAddresses(filter(
transform(concat(from.getPublicAddresses(), from.getInternetAddresses()),
AddressToStringTransformationFunction.INSTANCE), isInet4Address));
builder.privateAddresses(filter(
transform(from.getPrivateAddresses(), AddressToStringTransformationFunction.INSTANCE), isInet4Address));
return builder.build();
}
@ -130,17 +135,17 @@ public class ServerInZoneToNodeMetadata implements Function<ServerInZone, NodeMe
protected Hardware findHardwareForServerOrNull(ServerInZone serverInZone) {
return findObjectOfTypeForServerOrNull(hardwares.get(), "hardware", serverInZone.getServer().getFlavor().getId(),
serverInZone);
serverInZone);
}
protected OperatingSystem findOperatingSystemForServerOrNull(ServerInZone serverInZone) {
Image image = findObjectOfTypeForServerOrNull(images.get(), "image", serverInZone.getServer().getImage().getId(),
serverInZone);
serverInZone);
return (image != null) ? image.getOperatingSystem() : null;
}
public <T extends ComputeMetadata> T findObjectOfTypeForServerOrNull(Set<? extends T> supply, String type,
final String objectId, final ZoneAndId serverInZone) {
final String objectId, final ZoneAndId serverInZone) {
try {
return find(supply, new Predicate<T>() {
@Override

View File

@ -16,59 +16,59 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.functions;
package org.jclouds.openstack.nova.v1_1.compute.loaders;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Optional;
import com.google.common.cache.CacheLoader;
import com.google.inject.Inject;
/**
* @author Adam Lowe
*/
@Singleton
public class CreateUniqueKeyPair implements Function<ZoneAndName, KeyPair> {
public class CreateUniqueKeyPair extends CacheLoader<ZoneAndName, KeyPair> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final NovaClient novaClient;
protected final Supplier<String> randomSuffix;
protected final GroupNamingConvention.Factory namingConvention;
@Inject
public CreateUniqueKeyPair(NovaClient novaClient, Supplier<String> randomSuffix) {
public CreateUniqueKeyPair(NovaClient novaClient, GroupNamingConvention.Factory namingConvention) {
this.novaClient = checkNotNull(novaClient, "novaClient");
this.randomSuffix = randomSuffix;
this.namingConvention = checkNotNull(namingConvention, "namingConvention");
}
@Override
public KeyPair apply(ZoneAndName zoneAndName) {
public KeyPair load(ZoneAndName zoneAndName) {
String zoneId = checkNotNull(zoneAndName, "zoneAndName").getZone();
String prefix = zoneAndName.getName();
Optional<KeyPairClient> client = novaClient.getKeyPairExtensionForZone(zoneId);
checkArgument(client.isPresent(), "Key pairs are required, but the extension is not available in zone %s!", zoneId);
checkArgument(client.isPresent(), "Key pairs are required, but the extension is not available in zone %s!",
zoneId);
logger.debug(">> creating keyPair zone(%s) prefix(%s)", zoneId, prefix);
KeyPair keyPair = null;
while (keyPair == null) {
try {
keyPair = client.get().createKeyPair(getNextName(prefix));
keyPair = client.get().createKeyPair(namingConvention.createWithoutPrefix().uniqueNameForGroup(prefix));
} catch (IllegalStateException e) {
}
@ -78,10 +78,4 @@ public class CreateUniqueKeyPair implements Function<ZoneAndName, KeyPair> {
return keyPair;
}
// nova cannot use hashes, else a hang on the console like this:
// Caught exception reading instance data:
// http://169.254.169.254/2009-04-04/meta-data/mpi/jclouds#hpcloud-computeblock#11
private String getNextName(String prefix) {
return String.format("%s_%s", prefix, randomSuffix.get());
}
}

View File

@ -1,54 +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.openstack.nova.v1_1.compute.loaders;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import com.google.common.base.Function;
import com.google.common.cache.CacheLoader;
/**
* @author Adam Lowe
*/
public class FindKeyPairOrCreate extends CacheLoader<ZoneAndName, KeyPair> {
protected final Function<ZoneAndName, KeyPair> keypairCreator;
@Inject
public FindKeyPairOrCreate(
Function<ZoneAndName, KeyPair> keypairCreator) {
this.keypairCreator = checkNotNull(keypairCreator, "keypairCreator");
}
@Override
public KeyPair load(ZoneAndName in) {
// not retrieving KeyPairs from the server as the private key isn't returned
return keypairCreator.apply(in);
}
@Override
public String toString() {
return "returnExistingKeyPairInZoneOrCreateAsNeeded()";
}
}

View File

@ -40,6 +40,7 @@ import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
@ -64,7 +65,7 @@ import com.google.common.primitives.Ints;
*/
@Singleton
public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet extends
CreateNodesWithGroupEncodedIntoNameThenAddToSet {
CreateNodesWithGroupEncodedIntoNameThenAddToSet {
private final AllocateAndAddFloatingIpToNode allocateAndAddFloatingIpToNode;
private final LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache;
@ -74,28 +75,28 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
@Inject
protected ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet(
CreateNodeWithGroupEncodedIntoName addNodeWithTagStrategy,
ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Provider<TemplateBuilder> templateBuilderProvider,
AllocateAndAddFloatingIpToNode allocateAndAddFloatingIpToNode,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache,
LoadingCache<ZoneAndName, KeyPair> keyPairCache, NovaClient novaClient) {
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, executor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
CreateNodeWithGroupEncodedIntoName addNodeWithTagStrategy,
ListNodesStrategy listNodesStrategy,
GroupNamingConvention.Factory namingConvention,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Provider<TemplateBuilder> templateBuilderProvider,
AllocateAndAddFloatingIpToNode allocateAndAddFloatingIpToNode,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache,
LoadingCache<ZoneAndName, KeyPair> keyPairCache, NovaClient novaClient) {
super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, executor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
this.securityGroupCache = checkNotNull(securityGroupCache, "securityGroupCache");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
this.allocateAndAddFloatingIpToNode = checkNotNull(allocateAndAddFloatingIpToNode,
"allocateAndAddFloatingIpToNode");
"allocateAndAddFloatingIpToNode");
this.novaClient = checkNotNull(novaClient, "novaClient");
}
@Override
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
// ensure we don't mutate the input template
Template mutableTemplate = templateBuilderProvider.get().fromTemplate(template).build();
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(mutableTemplate.getOptions());
@ -104,15 +105,15 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
if (templateOptions.shouldAutoAssignFloatingIp()) {
checkArgument(novaClient.getFloatingIPExtensionForZone(zone).isPresent(),
"Floating IPs are required by options, but the extension is not available! options: %s",
templateOptions);
"Floating IPs are required by options, but the extension is not available! options: %s", templateOptions);
}
boolean keyPairExensionPresent = novaClient.getKeyPairExtensionForZone(zone).isPresent();
if (templateOptions.shouldGenerateKeyPair()) {
checkArgument(keyPairExensionPresent,
"Key Pairs are required by options, but the extension is not available! options: %s", templateOptions);
KeyPair keyPair = keyPairCache.getUnchecked(ZoneAndName.fromZoneAndName(zone, "jclouds_" + group));
KeyPair keyPair = keyPairCache.getUnchecked(ZoneAndName.fromZoneAndName(zone, namingConvention.create()
.sharedNameForGroup(group)));
keyPairCache.asMap().put(ZoneAndName.fromZoneAndName(zone, keyPair.getName()), keyPair);
templateOptions.keyPairName(keyPair.getName());
} else if (templateOptions.getKeyPairName() != null) {
@ -130,10 +131,10 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
List<Integer> inboundPorts = Ints.asList(templateOptions.getInboundPorts());
if (templateOptions.getSecurityGroupNames().size() > 0) {
checkArgument(novaClient.getSecurityGroupExtensionForZone(zone).isPresent(),
"Security groups are required by options, but the extension is not available! options: %s",
templateOptions);
"Security groups are required by options, but the extension is not available! options: %s",
templateOptions);
} else if (securityGroupExensionPresent && inboundPorts.size() > 0) {
String securityGroupName = "jclouds_" + group;
String securityGroupName = namingConvention.create().sharedNameForGroup(group);
try {
securityGroupCache.get(new ZoneSecurityGroupNameAndPorts(zone, securityGroupName, inboundPorts));
} catch (ExecutionException e) {
@ -147,7 +148,7 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
@Override
protected Future<AtomicReference<NodeMetadata>> createNodeInGroupWithNameAndTemplate(String group,
final String name, Template template) {
final String name, Template template) {
Future<AtomicReference<NodeMetadata>> future = super.createNodeInGroupWithNameAndTemplate(group, name, template);
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());

View File

@ -32,24 +32,25 @@ import com.google.common.base.Predicate;
public class KeyPairPredicates {
/**
* matches name of the given keypair starts with the specified prefix
*
* @param prefix the prefix you are looking for
* @return the predicate
* matches name of the given key pair
*
* @param name
* @return predicate that matches name
*/
public static Predicate<KeyPair> nameStartsWith(final String prefix) {
checkNotNull(prefix, "name must be defined");
public static Predicate<KeyPair> nameMatches(final Predicate<String> name) {
checkNotNull(name, "name must be defined");
return new Predicate<KeyPair>() {
@Override
public boolean apply(KeyPair ext) {
return ext.getName() != null && ext.getName().startsWith(prefix);
return name.apply(ext.getName());
}
@Override
public String toString() {
return "nameStartsWith(" + prefix + ")";
return "nameMatches(" + name + ")";
}
};
}

View File

@ -33,7 +33,7 @@ import com.google.common.base.Predicate;
public class SecurityGroupPredicates {
/**
* matches name of the given extension
* matches name of the given security group
*
* @param name
* @return predicate that matches name
@ -53,4 +53,26 @@ public class SecurityGroupPredicates {
}
};
}
/**
* matches name of the given security group
*
* @param name
* @return predicate that matches name
*/
public static Predicate<SecurityGroup> nameMatches(final Predicate<String> name) {
checkNotNull(name, "name must be defined");
return new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup ext) {
return name.apply(ext.getName());
}
@Override
public String toString() {
return "nameMatches(" + name + ")";
}
};
}
}

View File

@ -26,6 +26,7 @@ import java.util.Set;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
@ -41,6 +42,7 @@ import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
*
@ -57,6 +59,8 @@ public class OrphanedGroupsByZoneIdTest {
Supplier<Map<String, Location>> locationIndex = Suppliers.<Map<String, Location>> ofInstance(ImmutableMap
.<String, Location> of("az-1.region-a.geo-1", zone));
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@Test
public void testWhenComputeServiceSaysAllNodesAreDeadBothGroupsAreReturned() {
@ -65,7 +69,7 @@ public class OrphanedGroupsByZoneIdTest {
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex, Suppliers
.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of()), Suppliers
.<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()));
.<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()), namingConvention);
Set<? extends NodeMetadata> set = ImmutableSet.of(converter.apply(withHost), converter.apply(withoutHost));
@ -81,7 +85,7 @@ public class OrphanedGroupsByZoneIdTest {
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex, Suppliers
.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of()), Suppliers
.<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()));
.<Set<? extends Hardware>> ofInstance(ImmutableSet.<Hardware> of()), namingConvention);
Set<? extends NodeMetadata> set = ImmutableSet.of(converter.apply(withHost), converter.apply(withoutHost));

View File

@ -31,6 +31,7 @@ import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
@ -44,62 +45,66 @@ 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.inject.Guice;
/**
* Tests for the function for transforming a nova specific Server into a generic NodeMetadata
* object.
* Tests for the function for transforming a nova specific Server into a generic
* NodeMetadata object.
*
* @author Matt Stephenson, Adam Lowe, Adrian Cole
*/
@Test(testName = "ServerInZoneToNodeMetadataTest")
public class ServerInZoneToNodeMetadataTest {
Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("openstack-nova").description(
"openstack-nova").build();
Location zone = new LocationBuilder().id("az-1.region-a.geo-1").description("az-1.region-a.geo-1").scope(
LocationScope.ZONE).parent(provider).build();
Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("openstack-nova")
.description("openstack-nova").build();
Location zone = new LocationBuilder().id("az-1.region-a.geo-1").description("az-1.region-a.geo-1")
.scope(LocationScope.ZONE).parent(provider).build();
Supplier<Map<String, Location>> locationIndex = Suppliers.<Map<String, Location>> ofInstance(ImmutableMap
.<String, Location> of("az-1.region-a.geo-1", zone));
.<String, Location> of("az-1.region-a.geo-1", zone));
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@Test
public void testWhenNoHardwareOrImageMatchServerScopedIdsImageIdIsStillSet() {
Hardware existingHardware = new HardwareBuilder().id("az-1.region-a.geo-1/FOOOOOOOO").providerId("FOOOOOOOO")
.location(zone).build();
Image existingImage = new ImageBuilder().id("az-1.region-a.geo-1/FOOOOOOOO").operatingSystem(
OperatingSystem.builder().family(OsFamily.LINUX).description("foobuntu").build())
.providerId("FOOOOOOOO").description("foobuntu").location(zone).build();
.location(zone).build();
Image existingImage = new ImageBuilder().id("az-1.region-a.geo-1/FOOOOOOOO")
.operatingSystem(OperatingSystem.builder().family(OsFamily.LINUX).description("foobuntu").build())
.providerId("FOOOOOOOO").description("foobuntu").location(zone).build();
checkHardwareAndImageStatus(null, existingHardware, "az-1.region-a.geo-1/52415800-8b69-11e0-9b19-734f6f006e54",
null, existingImage);
null, existingImage);
}
@Test
public void testWhenNoHardwareAndImageMatchServerScopedIdsHardwareOperatingSystemAndImageIdAreSet() {
Hardware existingHardware = new HardwareBuilder().id("az-1.region-a.geo-1/52415800-8b69-11e0-9b19-734f216543fd")
.providerId("52415800-8b69-11e0-9b19-734f216543fd").location(zone).build();
.providerId("52415800-8b69-11e0-9b19-734f216543fd").location(zone).build();
Image existingImage = new ImageBuilder().id("az-1.region-a.geo-1/52415800-8b69-11e0-9b19-734f6f006e54")
.operatingSystem(OperatingSystem.builder().family(OsFamily.LINUX).description("foobuntu").build())
.providerId("52415800-8b69-11e0-9b19-734f6f006e54").description("foobuntu").location(zone).build();
.operatingSystem(OperatingSystem.builder().family(OsFamily.LINUX).description("foobuntu").build())
.providerId("52415800-8b69-11e0-9b19-734f6f006e54").description("foobuntu").location(zone).build();
checkHardwareAndImageStatus(existingHardware, existingHardware, existingImage.getId(), existingImage
.getOperatingSystem(), existingImage);
checkHardwareAndImageStatus(existingHardware, existingHardware, existingImage.getId(),
existingImage.getOperatingSystem(), existingImage);
}
// TODO: clean up this syntax
private void checkHardwareAndImageStatus(Hardware expectedHardware, Hardware existingHardware,
String expectedImageId, OperatingSystem expectedOs, Image existingImage) {
String expectedImageId, OperatingSystem expectedOs, Image existingImage) {
Set<Image> images = existingImage == null ? ImmutableSet.<Image> of() : ImmutableSet.of(existingImage);
Set<Hardware> hardwares = existingHardware == null ? ImmutableSet.<Hardware> of() : ImmutableSet
.of(existingHardware);
.of(existingHardware);
Server serverToConvert = new ParseServerTest().expected();
ServerInZone serverInZoneToConvert = new ServerInZone(serverToConvert, "az-1.region-a.geo-1");
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex, Suppliers
.<Set<? extends Image>> ofInstance(images), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex,
Suppliers.<Set<? extends Image>> ofInstance(images),
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata convertedNodeMetadata = converter.apply(serverInZoneToConvert);
@ -129,8 +134,8 @@ public class ServerInZoneToNodeMetadataTest {
assertEquals(convertedNodeMetadata.getPublicAddresses(), ImmutableSet.of("67.23.10.132", "67.23.10.131"));
assertNotNull(convertedNodeMetadata.getUserMetadata());
assertEquals(convertedNodeMetadata.getUserMetadata(), ImmutableMap.<String, String> of("Server Label",
"Web Head 1", "Image Version", "2.1"));
assertEquals(convertedNodeMetadata.getUserMetadata(),
ImmutableMap.<String, String> of("Server Label", "Web Head 1", "Image Version", "2.1"));
}
@Test
@ -143,9 +148,9 @@ public class ServerInZoneToNodeMetadataTest {
ServerInZone serverInZoneToConvert = new ServerInZone(serverToConvert, "az-1.region-a.geo-1");
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex, Suppliers
.<Set<? extends Image>> ofInstance(images), Suppliers.<Set<? extends Hardware>> ofInstance(hardwares));
ServerInZoneToNodeMetadata converter = new ServerInZoneToNodeMetadata(locationIndex,
Suppliers.<Set<? extends Image>> ofInstance(images),
Suppliers.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata convertedNodeMetadata = converter.apply(serverInZoneToConvert);

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.nova.v1_1.compute.functions;
package org.jclouds.openstack.nova.v1_1.compute.loaders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@ -27,6 +27,7 @@ import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.compute.loaders.CreateUniqueKeyPair;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndName;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
@ -34,65 +35,78 @@ import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.TypeLiteral;
/**
* @author Adam Lowe
*/
@Test(groups = "unit")
@Test(groups = "unit", testName = "CreateUniqueKeyPairTest")
public class CreateUniqueKeyPairTest {
@Test
public void testApply() throws UnknownHostException {
NovaClient client = createMock(NovaClient.class);
final NovaClient client = createMock(NovaClient.class);
KeyPairClient keyClient = createMock(KeyPairClient.class);
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
KeyPair pair = createMock(KeyPair.class);
expect(client.getKeyPairExtensionForZone("zone")).andReturn(Optional.of(keyClient)).atLeastOnce();
expect(uniqueIdSupplier.get()).andReturn("1");
expect(keyClient.createKeyPair("group_1")).andReturn(pair);
expect(keyClient.createKeyPair("group-1")).andReturn(pair);
replay(client);
replay(keyClient);
replay(uniqueIdSupplier);
replay(client, keyClient);
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(client, uniqueIdSupplier);
CreateUniqueKeyPair parser = Guice.createInjector(new AbstractModule() {
assertEquals(parser.apply(ZoneAndName.fromZoneAndName("zone", "group")), pair);
@Override
protected void configure() {
bind(new TypeLiteral<Supplier<String>>() {
}).toInstance(Suppliers.ofInstance("1"));
bind(NovaClient.class).toInstance(client);
}
verify(client);
verify(keyClient);
verify(uniqueIdSupplier);
}).getInstance(CreateUniqueKeyPair.class);
assertEquals(parser.load(ZoneAndName.fromZoneAndName("zone", "group")), pair);
verify(client, keyClient);
}
@Test
public void testApplyWithIllegalStateException() throws UnknownHostException {
NovaClient client = createMock(NovaClient.class);
final NovaClient client = createMock(NovaClient.class);
KeyPairClient keyClient = createMock(KeyPairClient.class);
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
@SuppressWarnings("unchecked")
final Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
KeyPair pair = createMock(KeyPair.class);
expect(client.getKeyPairExtensionForZone("zone")).andReturn(Optional.of(keyClient)).atLeastOnce();
expect(uniqueIdSupplier.get()).andReturn("1");
expect(keyClient.createKeyPair("group_1")).andThrow(new IllegalStateException());
expect(keyClient.createKeyPair("group-1")).andThrow(new IllegalStateException());
expect(uniqueIdSupplier.get()).andReturn("2");
expect(keyClient.createKeyPair("group_2")).andReturn(pair);
expect(keyClient.createKeyPair("group-2")).andReturn(pair);
replay(client);
replay(keyClient);
replay(uniqueIdSupplier);
replay(client, keyClient, uniqueIdSupplier);
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(client, uniqueIdSupplier);
CreateUniqueKeyPair parser = Guice.createInjector(new AbstractModule() {
assertEquals(parser.apply(ZoneAndName.fromZoneAndName("zone", "group")), pair);
@Override
protected void configure() {
bind(new TypeLiteral<Supplier<String>>() {
}).toInstance(uniqueIdSupplier);
bind(NovaClient.class).toInstance(client);
}
verify(client);
verify(keyClient);
verify(uniqueIdSupplier);
}).getInstance(CreateUniqueKeyPair.class);
assertEquals(parser.load(ZoneAndName.fromZoneAndName("zone", "group")), pair);
verify(client, keyClient, uniqueIdSupplier);
}
}

View File

@ -21,7 +21,6 @@ package org.jclouds.vcloud.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import static org.jclouds.vcloud.compute.util.VCloudComputeUtils.getCredentialsFrom;
import static org.jclouds.vcloud.compute.util.VCloudComputeUtils.getIpsFromVApp;
import static org.jclouds.vcloud.compute.util.VCloudComputeUtils.toComputeOs;
@ -37,6 +36,7 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
import org.jclouds.util.InetAddresses2.IsPrivateIPAddress;
@ -57,10 +57,13 @@ public class VAppToNodeMetadata implements Function<VApp, NodeMetadata> {
protected final Function<VApp, Hardware> hardwareForVApp;
protected final Map<Status, NodeState> vAppStatusToNodeState;
protected final Map<String, Credentials> credentialStore;
protected final GroupNamingConvention nodeNamingConvention;
@Inject
protected VAppToNodeMetadata(Map<Status, NodeState> vAppStatusToNodeState, Map<String, Credentials> credentialStore,
FindLocationForResource findLocationForResourceInVDC, Function<VApp, Hardware> hardwareForVApp) {
FindLocationForResource findLocationForResourceInVDC, Function<VApp, Hardware> hardwareForVApp,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.hardwareForVApp = checkNotNull(hardwareForVApp, "hardwareForVApp");
this.findLocationForResourceInVDC = checkNotNull(findLocationForResourceInVDC, "findLocationForResourceInVDC");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
@ -74,14 +77,14 @@ public class VAppToNodeMetadata implements Function<VApp, NodeMetadata> {
builder.name(from.getName());
builder.hostname(from.getName());
builder.location(findLocationForResourceInVDC.apply(from.getVDC()));
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.operatingSystem(toComputeOs(from, null));
builder.hardware(hardwareForVApp.apply(from));
builder.state(vAppStatusToNodeState.get(from.getStatus()));
Set<String> addresses = getIpsFromVApp(from);
builder.publicAddresses(filter(addresses, not(IsPrivateIPAddress.INSTANCE)));
builder.privateAddresses(filter(addresses, IsPrivateIPAddress.INSTANCE));
// normally, we don't affect the credential store when reading vApps.
// However, login user, etc, is actually in the metadata, so lets see
Credentials fromApi = getCredentialsFrom(from);

View File

@ -101,13 +101,6 @@ public class ${providerName}ComputeServiceContextModule extends ${providerName}C
protected TemplateBuilder provideTemplate(TemplateBuilder template) {
return template.osFamily(UBUNTU);
}
@Provides
@Named("NAMING_CONVENTION")
@Singleton
String provideNamingConvention() {
return "%s-%s";
}
@Singleton
public static class ${providerName}AddNodeWithTagStrategy implements AddNodeWithTagStrategy {

View File

@ -19,7 +19,6 @@
package org.jclouds.trmk.vcloud_0_8.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.Set;
@ -35,6 +34,7 @@ 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.compute.functions.GroupNamingConvention;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
@ -58,11 +58,14 @@ public class VAppToNodeMetadata implements Function<VApp, NodeMetadata> {
protected final FindLocationForResource findLocationForResourceInVDC;
protected final HardwareForVCloudExpressVApp hardwareForVCloudExpressVApp;
protected final Map<Status, NodeState> vAppStatusToNodeState;
protected final GroupNamingConvention nodeNamingConvention;
@Inject
protected VAppToNodeMetadata(TerremarkVCloudComputeClient computeClient, Map<String, Credentials> credentialStore,
Map<Status, NodeState> vAppStatusToNodeState, HardwareForVCloudExpressVApp hardwareForVCloudExpressVApp,
FindLocationForResource findLocationForResourceInVDC, @Memoized Supplier<Set<? extends Image>> images) {
FindLocationForResource findLocationForResourceInVDC, @Memoized Supplier<Set<? extends Image>> images,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.images = checkNotNull(images, "images");
this.hardwareForVCloudExpressVApp = checkNotNull(hardwareForVCloudExpressVApp, "hardwareForVCloudExpressVApp");
this.findLocationForResourceInVDC = checkNotNull(findLocationForResourceInVDC, "findLocationForResourceInVDC");
@ -97,8 +100,7 @@ public class VAppToNodeMetadata implements Function<VApp, NodeMetadata> {
builder.state(vAppStatusToNodeState.get(from.getStatus()));
builder.publicAddresses(computeClient.getPublicAddresses(from.getHref()));
builder.privateAddresses(computeClient.getPrivateAddresses(from.getHref()));
String group = parseGroupFromName(from.getName());
builder.group(group);
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.credentials(LoginCredentials.fromCredentials(credentialStore
.get("node#" + from.getHref().toASCIIString())));
return builder.build();

View File

@ -32,6 +32,7 @@ import org.jclouds.Constants;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
@ -55,11 +56,11 @@ public class TerremarkEncodeTagIntoNameRunNodesAndAddToSetStrategy extends Creat
protected TerremarkEncodeTagIntoNameRunNodesAndAddToSetStrategy(
CreateNodeWithGroupEncodedIntoName addNodeWithTagStrategy,
ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention,
GroupNamingConvention.Factory namingConvention,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
CreateNewKeyPairUnlessUserSpecifiedOtherwise createNewKeyPairUnlessUserSpecifiedOtherwise) {
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, executor,
super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, executor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.createNewKeyPairUnlessUserSpecifiedOtherwise = createNewKeyPairUnlessUserSpecifiedOtherwise;
}

View File

@ -200,17 +200,6 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
return options;
}
/**
* supplies how the tag is encoded into the name. A string of hex characters
* is the last argument and tag is the first
*/
@Provides
@Named("NAMING_CONVENTION")
@Singleton
protected String provideNamingConvention() {
return "%s-%s";
}
@Provides
@Singleton
protected Supplier<Map<String, ? extends Image>> provideImageMap(@Memoized Supplier<Set<? extends Image>> images) {

View File

@ -24,6 +24,8 @@ package org.jclouds.compute.config;
* @author Adrian Cole
*/
public interface ComputeServiceProperties {
public static final String RESOURCENAME_PREFIX = "jclouds.compute.resourcename-prefix";
public static final String RESOURCENAME_DELIMITER = "jclouds.compute.resourcename-delimiter";
public static final String TIMEOUT_NODE_TERMINATED = "jclouds.compute.timeout.node-terminated";
public static final String TIMEOUT_NODE_RUNNING = "jclouds.compute.timeout.node-running";

View File

@ -0,0 +1,163 @@
/**
* 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.compute.functions;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.internal.FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.base.Predicate;
import com.google.inject.ImplementedBy;
/**
* jclouds needs to understand the difference between resources it creates and
* those supplied by the user. For example, if jclouds creates a security group,
* it should be able to delete this as a part of cleanup without accidentally
* deleting resources the user specified manually.
*
* <h3>uniqueness of a name</h3>
*
* The naming convention must apply to both to resources shared across all
* members of a group, and those created for a subset of members.
*
* <ol>
* <li>shared: something shared across all members of a group, and fully
* retrievable via api. Ex. security group or network</li>
* <li>unique: something that only applies to individuals or subsets of a group,
* or isn't fully retrievable via api. Ex. node names or keypair names</li>
* </ol>
*
* <h4>why repeat?</h4>
*
* Some resources we'd otherwise want to share across a group must be
* redundantly created, if the user has no access to the complete object via api
* or otherwise. For example, ssh key apis generally do not store the private
* key data on the server. In order to ensure we can always log into a server
* without configuration, we may generate a temporary key on-demand for each
* call to {@link ComputeService#createNodesInGroup}
*
*
* Typically, a security group or network is something shared across all members
* of a group, so the name should be concise, yet unique.
*
* <h2>implementation</h2>
*
* Typically, a security group or network is something shared across all members
* of a group, so the name should be concise, yet unique.
*
* <h4>character sets and delimiters</h4>
*
* Character sets in apis are often bound to dns names, perhaps also allowing
* underscores. Since jclouds groups are allowed to be alphanumeric with hyphens
* (hostname style), care must be taken to implement this in a way that allows
* the delimiter to be also nested in the group name itself. In other words, we
* need to be able to encode a group into a name even when they share the same
* character set. Note that characters like {@code #} can sometimes break apis.
* As such, you may end preferring always using a hyphen.
*
* <h4>shared resources</h4>
*
* A good name for a shared resources might include a prefix of jclouds, a
* delimiter of {@code -} followed by the group name. The jclouds prefix
* signifies this resource is safe to delete, and the hash clearly delineates
* the encoding from what's in the group name.
*
* <h3>example</h3>
*
* given a jclouds group named {@code mycluster}, the naming convention for
* shared resources would produce {@code jclouds-mycluster}
*
* <h4>unique resources</h4>
*
* A good name for a unique resource might be the same as the shared, with a
* random hex string suffix. A few hex characters can give you 4096
* combinations, giving a small degree of collision avoidance, yet without
* making the resource name difficult.
*
* <h3>example</h3>
*
* given a jclouds group named {@code mycluster}, the naming convention for
* unique resources could produce {@code jclouds-mycluster-f3e} the first time,
* and {@code jclouds-mycluster-e64} the next.
*
* <h3>note</h3>
*
* It is typically safe to assume that an {@link IllegalStateException} is
* thrown when attempting to create a named resource which already exists.
* However, if you attempt to create a resource with a name generated by
* {@link GroupNamingConvention}, and receive an {@link IllegalStateException},
* it may have been for another reason besides name conflict.
*
* @author Adrian Cole
*/
@Beta
public interface GroupNamingConvention {
@ImplementedBy(FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat.Factory.class)
public static interface Factory {
GroupNamingConvention create();
/**
* top-level resources do not need a prefix, yet still may need to follow
* a naming convention
*/
GroupNamingConvention createWithoutPrefix();
}
/**
* encodes the {code group parameter} into a name that exists only once in
* the group.
*
*/
String sharedNameForGroup(String group);
/**
* encodes the {code group parameter} into a name that exists more than once
* in the group.
*
* <h3>note</h3>
*
* Do not expect this name to be guaranteed unique, though a good
* implementation should guess a unique name in one or two tries.
*/
String uniqueNameForGroup(String group);
/**
* retrieve the group associated with the encoded name
*
*/
@Nullable
String groupInUniqueNameOrNull(String encoded);
/**
* retrieve the group associated with the encoded name
*
*/
@Nullable
String groupInSharedNameOrNull(String encoded);
/**
* identifies if this name has a group encoded in it.
*/
Predicate<String> containsGroup(String group);
}

View File

@ -0,0 +1,175 @@
/**
* 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.compute.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
import java.security.SecureRandom;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.predicates.Validator;
import org.jclouds.predicates.validators.DnsNameValidator;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.inject.Inject;
/**
* Get a name using a random mechanism that still ties all nodes in a group
* together.
*
* This implementation will pass the group and a hex formatted random number to
* the configured naming convention.
*
*/
public class FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat implements GroupNamingConvention {
protected final String prefix;
protected final char delimiter;
protected final Supplier<String> suffixSupplier;
protected final String sharedFormat;
protected final String uniqueFormat;
protected final Pattern uniqueGroupPattern;
protected final Pattern sharedGroupPattern;
protected final Validator<String> groupValidator;
@Singleton
public static class Factory implements GroupNamingConvention.Factory {
@Inject(optional = true)
@Named(RESOURCENAME_PREFIX)
private String prefix = "jclouds";
@Inject(optional = true)
@Named(RESOURCENAME_DELIMITER)
private char delimiter = '-';
@Inject(optional = true)
private Supplier<String> suffixSupplier = new Supplier<String>() {
final SecureRandom random = new SecureRandom();
@Override
public String get() {
return Integer.toHexString(random.nextInt(4095));
}
};
@Inject(optional = true)
private Validator<String> groupValidator = new DnsNameValidator(3, 63);
// lazy init, so that @Inject stuff can work, and avoid calling the
// constructor
// each time, as it compiles new regexes
LoadingCache<String, GroupNamingConvention> cache = CacheBuilder.newBuilder().build(
new CacheLoader<String, GroupNamingConvention>() {
@Override
public GroupNamingConvention load(String key) throws Exception {
return new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(key, delimiter, suffixSupplier, groupValidator);
}
});
@Override
public GroupNamingConvention create() {
return cache.getUnchecked(prefix);
}
@Override
public GroupNamingConvention createWithoutPrefix() {
return cache.getUnchecked("");
}
}
public FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(String prefix, char delimiter,
Supplier<String> suffixSupplier, Validator<String> groupValidator) {
this.prefix = checkNotNull(prefix, "prefix");
this.delimiter = delimiter;
this.suffixSupplier = checkNotNull(suffixSupplier, "suffixSupplier");
this.groupValidator = checkNotNull(groupValidator, "groupValidator");
this.sharedFormat = "".equals(prefix) ? "%s" : new StringBuilder().append(prefix).append(delimiter).append("%s")
.toString();
this.uniqueFormat = new StringBuilder(sharedFormat).append(delimiter).append("%s").toString();
this.uniqueGroupPattern = Pattern.compile("^" + ("".equals(prefix) ? "" : (prefix + delimiter)) + "(.+)"
+ delimiter + "[^" + delimiter + "]+");
this.sharedGroupPattern = Pattern.compile("^" + ("".equals(prefix) ? "" : (prefix + delimiter)) + "(.+)$");
}
@Override
public String sharedNameForGroup(String group) {
return String.format(sharedFormat, checkGroup(group));
}
protected String checkGroup(String group) {
groupValidator.validate(checkNotNull(group, "group"));
return group;
}
@Override
public String uniqueNameForGroup(String group) {
return String.format(uniqueFormat, checkGroup(group), suffixSupplier.get());
}
@Override
public String groupInUniqueNameOrNull(String encoded) {
return firstGroupInPatternOrNull(uniqueGroupPattern, encoded);
}
protected String firstGroupInPatternOrNull(Pattern pattern, String encoded) {
Matcher matcher = pattern.matcher(checkNotNull(encoded, "encoded"));
if (!matcher.matches())
return null;
return matcher.group(1);
}
@Override
public String groupInSharedNameOrNull(String encoded) {
return firstGroupInPatternOrNull(sharedGroupPattern, encoded);
}
@Override
public Predicate<String> containsGroup(final String group) {
checkGroup(group);
return new Predicate<String>() {
@Override
public boolean apply(String input) {
try {
return group.equals(groupInUniqueNameOrNull(input)) || group.equals(groupInSharedNameOrNull(input));
} catch (NoSuchElementException e) {
return false;
}
}
@Override
public String toString() {
return "containsGroup(" + group + ")";
}
};
}
}

View File

@ -31,11 +31,14 @@ import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_T
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
import java.security.SecureRandom;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.config.ComputeServiceProperties;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
/**
@ -108,6 +111,20 @@ public interface ComputeServiceConstants {
@Deprecated
public static final String PROPERTY_OS_VERSION_MAP_JSON = OS_VERSION_MAP_JSON;
@Singleton
public static class NamingConvention {
@Inject(optional = true)
public final Supplier<String> randomSuffix = new Supplier<String>() {
final SecureRandom random = new SecureRandom();
@Override
public String get() {
return random.nextInt(100) + "";
}
};
}
@Singleton
public static class InitStatusProperties {
@Inject(optional = true)

View File

@ -25,7 +25,6 @@ import static com.google.common.collect.Maps.newLinkedHashMap;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static org.jclouds.concurrent.Futures.compose;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
@ -44,6 +43,7 @@ import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
@ -94,7 +94,7 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
protected Logger logger = Logger.NULL;
protected final CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy;
protected final ListNodesStrategy listNodesStrategy;
protected final String nodeNamingConvention;
protected final GroupNamingConvention.Factory namingConvention;
protected final ExecutorService executor;
protected final CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
@ -102,12 +102,12 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
protected CreateNodesWithGroupEncodedIntoNameThenAddToSet(
CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention,
GroupNamingConvention.Factory namingConvention,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory) {
this.addNodeWithGroupStrategy = addNodeWithGroupStrategy;
this.listNodesStrategy = listNodesStrategy;
this.nodeNamingConvention = nodeNamingConvention;
this.namingConvention = namingConvention;
this.executor = executor;
this.customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
}
@ -185,7 +185,7 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
int maxTries = 100;
int currentTries = 0;
while (names.size() < count && currentTries++ < maxTries) {
final String name = getNextName(group, template);
final String name = namingConvention.createWithoutPrefix().uniqueNameForGroup(group);
if (!any(currentNodes, new Predicate<ComputeMetadata>() {
@Override
@ -200,15 +200,4 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
return names;
}
/**
* Get a name using a random mechanism that still ties all nodes in a group together.
*
* This implementation will pass the group and a hex formatted random number to the configured
* naming convention.
*
*/
protected String getNextName(final String group, final Template template) {
return String.format(nodeNamingConvention, group, Integer.toHexString(new SecureRandom().nextInt(4095)));
}
}

View File

@ -32,7 +32,6 @@ import java.util.Formatter;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jclouds.compute.ComputeServiceContextBuilder;
@ -100,17 +99,6 @@ public class ComputeServiceUtils {
return extractZipIntoDirectory(new HttpRequest("GET", zip), directory);
}
/**
*
* @return null if group cannot be parsed
*/
public static String parseGroupFromName(String from) {
if (from == null)
return null;
Matcher matcher = DELIMETED_BY_HYPHEN_ENDING_IN_HYPHEN_HEX.matcher(from);
return matcher.find() ? matcher.group(1) : null;
}
public static double getCores(Hardware input) {
double cores = 0;
for (Processor processor : input.getProcessors())

View File

@ -0,0 +1,182 @@
/**
* 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.compute.internal;
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.predicates.Validator;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
/**
*
* @author Adrian Cole
*/
@Test(testName = "FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeatTest")
public class FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeatTest {
Validator<String> okValidator = new Validator<String>() {
@Override
public void validate(String t) throws IllegalArgumentException {
}
};
public void testSharedName() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"jclouds", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.sharedNameForGroup("cluster"), "jclouds_cluster");
assertEquals(fn.groupInSharedNameOrNull("jclouds_cluster"), "cluster");
assertEquals(fn.groupInUniqueNameOrNull("jclouds_cluster"), null);
assertTrue(fn.containsGroup("cluster").apply("jclouds_cluster"));
}
public void testOkToHaveDelimiterInGroupOnUniqueName() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"jclouds", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.sharedNameForGroup("cluster_"), "jclouds_cluster_");
assertEquals(fn.groupInSharedNameOrNull("jclouds_cluster_"), "cluster_");
assertEquals(fn.groupInUniqueNameOrNull("jclouds_cluster_"), null);
assertTrue(fn.containsGroup("cluster_").apply("jclouds_cluster_"));
}
public void testSharedNameWithHyphenInGroup() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"jclouds", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.sharedNameForGroup("cluster-"), "jclouds_cluster-");
assertEquals(fn.groupInSharedNameOrNull("jclouds_cluster-"), "cluster-");
assertEquals(fn.groupInUniqueNameOrNull("jclouds_cluster-"), null);
assertTrue(fn.containsGroup("cluster-").apply("jclouds_cluster-"));
}
public void testNextName() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"jclouds", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.uniqueNameForGroup("cluster"), "jclouds_cluster_123");
// note accidental treatment of a unique node as a shared one can lead to
// incorrect group names, as long as we permit delimiter to be in group name
assertEquals(fn.groupInSharedNameOrNull("jclouds_cluster_123"), "cluster_123");
assertEquals(fn.groupInUniqueNameOrNull("jclouds_cluster_123"), "cluster");
assertTrue(fn.containsGroup("cluster").apply("jclouds_cluster_123"));
}
public void testCannotFindSharedNameWhenDelimiterWrong() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"jclouds", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.groupInSharedNameOrNull("jclouds#cluster"), null);
assertEquals(fn.groupInUniqueNameOrNull("jclouds#cluster"), null);
assertFalse(fn.containsGroup("cluster").apply("jclouds#cluster"));
}
public void testCannotFindNextNameWhenDelimiterWrong() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"jclouds", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.groupInSharedNameOrNull("jclouds#cluster#123"), null);
assertEquals(fn.groupInUniqueNameOrNull("jclouds#cluster#123"), null);
assertFalse(fn.containsGroup("cluster").apply("jclouds#cluster#123"));
}
public void testPropertyChangesDelimiter() {
GroupNamingConvention fn = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(RESOURCENAME_DELIMITER)).to('#');
}
}).getInstance(GroupNamingConvention.Factory.class).create();
assertEquals(fn.sharedNameForGroup("cluster"), "jclouds#cluster");
assertEquals(fn.groupInSharedNameOrNull("jclouds#cluster"), "cluster");
assertEquals(fn.groupInUniqueNameOrNull("jclouds#cluster"), null);
assertTrue(fn.containsGroup("cluster").apply("jclouds#cluster"));
}
public void testPropertyChangesPrefix() {
GroupNamingConvention fn = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(RESOURCENAME_PREFIX)).to("kclouds");
}
}).getInstance(GroupNamingConvention.Factory.class).create();
assertEquals(fn.sharedNameForGroup("cluster"), "kclouds-cluster");
assertEquals(fn.groupInSharedNameOrNull("kclouds-cluster"), "cluster");
assertEquals(fn.groupInUniqueNameOrNull("kclouds-cluster"), null);
assertTrue(fn.containsGroup("cluster").apply("kclouds-cluster"));
}
public void testCanChangeSuffixSupplier() {
GroupNamingConvention fn = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(new TypeLiteral<Supplier<String>>() {
}).toInstance(Suppliers.ofInstance("foo"));
}
}).getInstance(GroupNamingConvention.Factory.class).create();
assertEquals(fn.uniqueNameForGroup("cluster"), "jclouds-cluster-foo");
// note accidental treatment of a unique node as a shared one can lead to
// incorrect group names, as long as we permit delimiter to be in group name
assertEquals(fn.groupInSharedNameOrNull("jclouds-cluster-foo"), "cluster-foo");
assertEquals(fn.groupInUniqueNameOrNull("jclouds-cluster-foo"), "cluster");
assertTrue(fn.containsGroup("cluster").apply("jclouds-cluster-foo"));
}
// ///
public void testSharedNameNoPrefix() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.sharedNameForGroup("cluster"), "cluster");
assertEquals(fn.groupInSharedNameOrNull("cluster"), "cluster");
assertEquals(fn.groupInUniqueNameOrNull("cluster"), null);
assertTrue(fn.containsGroup("cluster").apply("cluster"));
}
public void testNextNameNoPrefix() {
FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat fn = new FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat(
"", '_', Suppliers.ofInstance("123"), okValidator);
assertEquals(fn.uniqueNameForGroup("cluster"), "cluster_123");
assertEquals(fn.groupInSharedNameOrNull("cluster_123"), "cluster_123");
assertEquals(fn.groupInUniqueNameOrNull("cluster_123"), "cluster");
assertTrue(fn.containsGroup("cluster").apply("cluster_123"));
}
}

View File

@ -18,7 +18,6 @@
*/
package org.jclouds.compute.util;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import static org.jclouds.compute.util.ComputeServiceUtils.parseVersionOrReturnEmptyString;
import static org.testng.Assert.assertEquals;
@ -48,11 +47,6 @@ public class ComputeServiceUtilsTest {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule())
.getInstance(Json.class));
@Test
public void testParseGroupFromName() {
assertEquals(parseGroupFromName("gogrid--849"), "gogrid-");
}
@Test
public void testParseVersionOrReturnEmptyStringUbuntu1004() {
assertEquals(parseVersionOrReturnEmptyString(OsFamily.UBUNTU, "Ubuntu 10.04", map), "10.04");

View File

@ -19,7 +19,6 @@
package org.jclouds.glesys.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -41,6 +40,7 @@ import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.glesys.domain.Ip;
@ -73,6 +73,7 @@ public class ServerDetailsToNodeMetadata implements Function<ServerDetails, Node
protected final Supplier<Set<? extends Image>> images;
protected final FindLocationForServerDetails findLocationForServerDetails;
protected final GroupNamingConvention nodeNamingConvention;
private static class FindImageForServer implements Predicate<Image> {
private final ServerDetails instance;
@ -89,7 +90,9 @@ public class ServerDetailsToNodeMetadata implements Function<ServerDetails, Node
@Inject
ServerDetailsToNodeMetadata(FindLocationForServerDetails findLocationForServerDetails,
@Memoized Supplier<Set<? extends Image>> images) {
@Memoized Supplier<Set<? extends Image>> images,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.findLocationForServerDetails = checkNotNull(findLocationForServerDetails, "findLocationForServerDetails");
this.images = checkNotNull(images, "images");
}
@ -102,7 +105,7 @@ public class ServerDetailsToNodeMetadata implements Function<ServerDetails, Node
builder.hostname(from.getHostname());
Location location = findLocationForServerDetails.apply(from);
assert (location != null) : String.format("no location matched ServerDetails %s", from);
builder.group(parseGroupFromName(from.getDescription()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getDescription()));
builder.imageId(from.getTemplateName() + "");
builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(new HardwareBuilder().ids(from.getId() + "").ram(from.getMemorySizeMB())

View File

@ -21,7 +21,6 @@ package org.jclouds.savvis.vpdc.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.Set;
@ -35,6 +34,7 @@ import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.util.Utils;
@ -58,9 +58,12 @@ public class VMToNodeMetadata implements Function<VM, NodeMetadata> {
NodeState.SUSPENDED).put(VM.Status.UNRESOLVED, NodeState.PENDING).build();
private final FindLocationForVM findLocationForVM;
private final GroupNamingConvention nodeNamingConvention;
@Inject
VMToNodeMetadata(FindLocationForVM findLocationForVM) {
VMToNodeMetadata(FindLocationForVM findLocationForVM,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.findLocationForVM = checkNotNull(findLocationForVM, "findLocationForVM");
}
@ -70,7 +73,7 @@ public class VMToNodeMetadata implements Function<VM, NodeMetadata> {
builder.ids(from.getHref().toASCIIString());
builder.name(from.getName());
builder.location(findLocationForVM.apply(from));
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
try {
builder.operatingSystem(CIMOperatingSystem.toComputeOs(from.getOperatingSystemSection()));
} catch (NullPointerException e) {

View File

@ -18,7 +18,6 @@
*/
package org.jclouds.gogrid.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -34,6 +33,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.domain.ServerState;
@ -58,6 +58,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
private final Supplier<Set<? extends Image>> images;
private final Supplier<Set<? extends Hardware>> hardwares;
private final Supplier<Set<? extends Location>> locations;
private final GroupNamingConvention nodeNamingConvention;
static class FindImageForServer implements Predicate<Image> {
private final Server instance;
@ -92,7 +93,9 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Inject
ServerToNodeMetadata(Map<ServerState, NodeState> serverStateToNodeState,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares,
@Memoized Supplier<Set<? extends Location>> locations) {
@Memoized Supplier<Set<? extends Location>> locations,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.serverStateToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState");
this.images = checkNotNull(images, "images");
this.hardwares = checkNotNull(hardwares, "hardwares");
@ -106,7 +109,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
builder.name(from.getName());
Location location = Iterables.find(locations.get(), LocationPredicates.idEquals(from.getDatacenter().getId() + ""));
builder.location(location);
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.hardware(parseHardware(from));
builder.imageId(from.getImage().getId() + "");

View File

@ -32,6 +32,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
@ -45,6 +46,7 @@ import org.testng.annotations.Test;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
* @author Adrian Cole
@ -52,6 +54,7 @@ import com.google.common.collect.ImmutableSet;
//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "ServerToNodeMetadataTest")
public class ServerToNodeMetadataTest {
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@SuppressWarnings("unchecked")
@Test
@ -93,7 +96,7 @@ public class ServerToNodeMetadataTest {
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, Suppliers
.<Set<? extends Image>> ofInstance(images), Suppliers
.<Set<? extends Hardware>> ofInstance(GoGridHardwareSupplier.H_ALL), Suppliers
.<Set<? extends Location>> ofInstance(locations));
.<Set<? extends Location>> ofInstance(locations), namingConvention);
NodeMetadata metadata = parser.apply(server);
assertEquals(metadata.getLocation(), location);

View File

@ -19,7 +19,6 @@
package org.jclouds.rimuhosting.miro.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -35,6 +34,7 @@ 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.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.rimuhosting.miro.domain.Server;
@ -54,10 +54,12 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Resource
protected Logger logger = Logger.NULL;
protected final Supplier<Set<? extends Location>> locations;
protected final Function<Server, Iterable<String>> getPublicAddresses;
protected final Map<RunningState, NodeState> runningStateToNodeState;
protected final Supplier<Set<? extends Image>> images;
protected final GroupNamingConvention nodeNamingConvention;
private static class FindImageForServer implements Predicate<Image> {
private final Location location;
@ -79,7 +81,9 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Inject
ServerToNodeMetadata(Function<Server, Iterable<String>> getPublicAddresses,
@Memoized Supplier<Set<? extends Location>> locations, Map<RunningState, NodeState> runningStateToNodeState,
@Memoized Supplier<Set<? extends Image>> images) {
@Memoized Supplier<Set<? extends Image>> images,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.getPublicAddresses = checkNotNull(getPublicAddresses, "serverStateToNodeState");
this.locations = checkNotNull(locations, "locations");
this.runningStateToNodeState = checkNotNull(runningStateToNodeState, "serverStateToNodeState");
@ -94,7 +98,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
builder.hostname(from.getName());
Location location = findLocationWithId(from.getLocation().getId());
builder.location(location);
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.imageId(from.getImageId() + "");
builder.operatingSystem(parseOperatingSystem(from, location));
builder.hardware(null);// TODO

View File

@ -19,7 +19,6 @@
package org.jclouds.slicehost.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.NoSuchElementException;
@ -36,6 +35,7 @@ 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.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.slicehost.domain.Slice;
@ -54,6 +54,7 @@ public class SliceToNodeMetadata implements Function<Slice, NodeMetadata> {
protected final Map<Slice.Status, NodeState> sliceToNodeState;
protected final Supplier<Set<? extends Image>> images;
protected final Supplier<Set<? extends Hardware>> hardwares;
protected final GroupNamingConvention nodeNamingConvention;
@Resource
protected Logger logger = Logger.NULL;
@ -87,7 +88,9 @@ public class SliceToNodeMetadata implements Function<Slice, NodeMetadata> {
@Inject
SliceToNodeMetadata(Map<Slice.Status, NodeState> sliceStateToNodeState,
@Memoized Supplier<Set<? extends Image>> images, Supplier<Location> location,
@Memoized Supplier<Set<? extends Hardware>> hardwares) {
@Memoized Supplier<Set<? extends Hardware>> hardwares,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.sliceToNodeState = checkNotNull(sliceStateToNodeState, "sliceStateToNodeState");
this.images = checkNotNull(images, "images");
this.location = checkNotNull(location, "location");
@ -101,7 +104,7 @@ public class SliceToNodeMetadata implements Function<Slice, NodeMetadata> {
builder.name(from.getName());
builder.hostname(from.getName());
builder.location(location.get());
builder.group(parseGroupFromName(from.getName()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
builder.imageId(from.getImageId() + "");
builder.operatingSystem(parseOperatingSystem(from));
builder.hardware(parseHardware(from));

View File

@ -34,6 +34,7 @@ import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
@ -46,13 +47,15 @@ import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
@Test(groups = "unit", testName = "SliceToNodeMetadataTest")
public class SliceToNodeMetadataTest {
Location provider = new LocationBuilder().scope(LocationScope.ZONE).id("dallas").description("description").build();
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@Test
public void testApplyWhereImageAndHardwareNotFound() {
@ -63,7 +66,7 @@ public class SliceToNodeMetadataTest {
SliceToNodeMetadata parser = new SliceToNodeMetadata(sliceStateToNodeState, Suppliers
.<Set<? extends Image>> ofInstance(images), Suppliers.ofInstance(provider), Suppliers
.<Set<? extends Hardware>> ofInstance(hardwares));
.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(slice);
@ -83,7 +86,7 @@ public class SliceToNodeMetadataTest {
SliceToNodeMetadata parser = new SliceToNodeMetadata(sliceStateToNodeState, Suppliers
.<Set<? extends Image>> ofInstance(images), Suppliers.ofInstance(provider), Suppliers
.<Set<? extends Hardware>> ofInstance(hardwares));
.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(slice);
assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses(
@ -104,7 +107,7 @@ public class SliceToNodeMetadataTest {
SliceToNodeMetadata parser = new SliceToNodeMetadata(sliceStateToNodeState, Suppliers
.<Set<? extends Image>> ofInstance(images), Suppliers.ofInstance(provider), Suppliers
.<Set<? extends Hardware>> ofInstance(hardwares));
.<Set<? extends Hardware>> ofInstance(hardwares), namingConvention);
NodeMetadata metadata = parser.apply(slice);
assertEquals(metadata, new NodeMetadataBuilder().state(NodeState.PENDING).publicAddresses(

View File

@ -19,7 +19,6 @@
package org.jclouds.softlayer.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.Set;
@ -34,6 +33,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.domain.Datacenter;
@ -62,10 +62,13 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
private final FindLocationForVirtualGuest findLocationForVirtualGuest;
private final GetHardwareForVirtualGuest getHardwareForVirtualGuest;
private final GetImageForVirtualGuest getImageForVirtualGuest;
private final GroupNamingConvention nodeNamingConvention;
@Inject
VirtualGuestToNodeMetadata(FindLocationForVirtualGuest findLocationForVirtualGuest,
GetHardwareForVirtualGuest getHardwareForVirtualGuest, GetImageForVirtualGuest getImageForVirtualGuest) {
GetHardwareForVirtualGuest getHardwareForVirtualGuest, GetImageForVirtualGuest getImageForVirtualGuest,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.findLocationForVirtualGuest = checkNotNull(findLocationForVirtualGuest, "findLocationForVirtualGuest");
this.getHardwareForVirtualGuest = checkNotNull(getHardwareForVirtualGuest, "getHardwareForVirtualGuest");
this.getImageForVirtualGuest = checkNotNull(getImageForVirtualGuest, "getImageForVirtualGuest");
@ -79,7 +82,7 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
builder.name(from.getHostname());
builder.hostname(from.getHostname());
builder.location(findLocationForVirtualGuest.apply(from));
builder.group(parseGroupFromName(from.getHostname()));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getHostname()));
Image image = getImageForVirtualGuest.getImage(from);
if (image != null) {

View File

@ -31,6 +31,7 @@ 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.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata.FindLocationForVirtualGuest;
@ -46,12 +47,14 @@ import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "VirtualGuestToNodeMetadataTest")
public class VirtualGuestToNodeMetadataTest {
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
@Test
public void testApplyWhereVirtualGuestWithNoPassword() {
@ -65,7 +68,7 @@ public class VirtualGuestToNodeMetadataTest {
.<Location> of(expectedLocation));
VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(new FindLocationForVirtualGuest(
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock());
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock(), namingConvention);
NodeMetadata node = parser.apply(guest);
@ -92,7 +95,7 @@ public class VirtualGuestToNodeMetadataTest {
.<Location> of());
VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(new FindLocationForVirtualGuest(
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock());
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock(), namingConvention);
NodeMetadata node = parser.apply(guest);
@ -117,7 +120,7 @@ public class VirtualGuestToNodeMetadataTest {
.<Location> of(expectedLocation));
VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(new FindLocationForVirtualGuest(
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock());
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock(), namingConvention);
NodeMetadata node = parser.apply(guest);
@ -145,7 +148,7 @@ public class VirtualGuestToNodeMetadataTest {
.<Location> of(expectedLocation));
VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(new FindLocationForVirtualGuest(
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock());
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock(), namingConvention);
NodeMetadata node = parser.apply(guest);
@ -173,7 +176,7 @@ public class VirtualGuestToNodeMetadataTest {
.<Location> of(expectedLocation));
VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(new FindLocationForVirtualGuest(
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock());
locationSupplier), new GetHardwareForVirtualGuestMock(), new GetImageForVirtualGuestMock(), namingConvention);
NodeMetadata node = parser.apply(guest);

View File

@ -19,7 +19,6 @@
package org.jclouds.servermanager.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
import java.util.Map;
import java.util.Set;
@ -34,6 +33,7 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
@ -61,10 +61,13 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
private final FindLocationForServer findLocationForServer;
private final FindImageForServer findImageForServer;
private final Map<String, Credentials> credentialStore;
private final GroupNamingConvention nodeNamingConvention;
@Inject
ServerToNodeMetadata(Map<String, Credentials> credentialStore, FindHardwareForServer findHardwareForServer,
FindLocationForServer findLocationForServer, FindImageForServer findImageForServer) {
FindLocationForServer findLocationForServer, FindImageForServer findImageForServer,
GroupNamingConvention.Factory namingConvention) {
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.findHardwareForServer = checkNotNull(findHardwareForServer, "findHardwareForServer");
this.findLocationForServer = checkNotNull(findLocationForServer, "findLocationForServer");
@ -78,7 +81,7 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
builder.ids(from.id + "");
builder.name(from.name);
builder.location(findLocationForServer.apply(from));
builder.group(parseGroupFromName(from.name));
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.name));
builder.imageId(from.imageId + "");
Image image = findImageForServer.apply(from);
if (image != null)