changed to not use # as a delimiter, and fixed keypair prefix logic

This commit is contained in:
Adrian Cole 2012-03-21 19:11:03 -07:00
parent 2373f89c78
commit 09d97a2103
17 changed files with 135 additions and 88 deletions

View File

@ -67,6 +67,7 @@ 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;
@ -131,7 +132,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.nameEquals("jclouds_" + group))) {
ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, securityGroup.getName());
logger.debug(">> deleting securityGroup(%s)", zoneAndName);
securityGroupClient.get().deleteSecurityGroup(securityGroup.getId());
@ -148,7 +149,10 @@ public class NovaComputeService extends BaseComputeService {
if (keyPairClient.isPresent()) {
for (String group : groups) {
for (Map<String, KeyPair> wrapper : keyPairClient.get().listKeyPairs()) {
for (KeyPair pair : Iterables.filter(wrapper.values(), KeyPairPredicates.nameStartsWith("jclouds#" + group + "#"))) {
for (KeyPair pair : Iterables.filter(
wrapper.values(),
Predicates.or(KeyPairPredicates.nameStartsWith("jclouds_" + group + "_"),
KeyPairPredicates.nameEquals("jclouds_" + group)))) {
ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, pair.getName());
logger.debug(">> deleting keypair(%s)", zoneAndName);
keyPairClient.get().deleteKeyPair(pair.getName());
@ -157,7 +161,7 @@ public class NovaComputeService extends BaseComputeService {
logger.debug("<< deleted keypair(%s)", zoneAndName);
}
}
keyPairCache.invalidate(ZoneAndName.fromZoneAndName(zoneId, "jclouds#" + group));
keyPairCache.invalidate(ZoneAndName.fromZoneAndName(zoneId, "jclouds_" + group));
}
}
}

View File

@ -63,7 +63,7 @@ public class CreateSecurityGroupIfNeeded implements Function<ZoneSecurityGroupNa
String zoneId = zoneSecurityGroupNameAndPorts.getZone();
Optional<SecurityGroupClient> client = novaClient.getSecurityGroupExtensionForZone(zoneId);
checkArgument(client.isPresent(), "Security groups are required, but the extension is not available!");
checkArgument(client.isPresent(), "Security groups are required, but the extension is not availablein zone %s!", zoneId);
logger.debug(">> creating securityGroup %s", zoneSecurityGroupNameAndPorts);
try {

View File

@ -20,18 +20,22 @@ package org.jclouds.openstack.nova.v1_1.compute.functions;
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 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;
/**
@ -53,30 +57,31 @@ public class CreateUniqueKeyPair implements Function<ZoneAndName, KeyPair> {
@Override
public KeyPair apply(ZoneAndName zoneAndName) {
checkNotNull(zoneAndName, "zoneAndName");
return createNewKeyPairInZone(zoneAndName.getZone(), zoneAndName.getName());
}
String zoneId = checkNotNull(zoneAndName, "zoneAndName").getZone();
String prefix = zoneAndName.getName();
@VisibleForTesting
KeyPair createNewKeyPairInZone(String zone, String group) {
checkNotNull(zone, "zone");
checkNotNull(group, "group");
logger.debug(">> creating keyPair zone(%s) group(%s)", zone, group);
Optional<KeyPairClient> client = novaClient.getKeyPairExtensionForZone(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 = novaClient.getKeyPairExtensionForZone(zone).get().createKeyPair(getNextName(group));
keyPair = client.get().createKeyPair(getNextName(prefix));
} catch (IllegalStateException e) {
}
}
logger.debug("<< created keyPair(%s)", keyPair);
logger.debug("<< created keyPair(%s)", keyPair.getName());
return keyPair;
}
private String getNextName(String group) {
return String.format("jclouds#%s#%s", group, randomSuffix.get());
// 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

@ -18,6 +18,7 @@
*/
package org.jclouds.openstack.nova.v1_1.compute.options;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
@ -32,6 +33,7 @@ import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
@ -69,10 +71,34 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
}
}
private boolean autoAssignFloatingIp = false;
private boolean generateKeyPair = false;
private Set<String> securityGroupNames = ImmutableSet.of();
private String keyPairName;
protected boolean autoAssignFloatingIp = false;
protected Set<String> securityGroupNames = ImmutableSet.of();
protected boolean generateKeyPair = false;
protected String keyPairName;
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
NovaTemplateOptions that = NovaTemplateOptions.class.cast(o);
return super.equals(that) && equal(this.autoAssignFloatingIp, that.autoAssignFloatingIp)
&& equal(this.securityGroupNames, that.securityGroupNames)
&& equal(this.generateKeyPair, that.generateKeyPair) && equal(this.keyPairName, that.keyPairName);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName);
}
@Override
public ToStringHelper string() {
return super.string().add("autoAssignFloatingIp", autoAssignFloatingIp)
.add("securityGroupNames", securityGroupNames).add("generateKeyPair", generateKeyPair)
.add("keyPairName", keyPairName);
}
public static final NovaTemplateOptions NONE = new NovaTemplateOptions();
@ -445,26 +471,4 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
return NovaTemplateOptions.class.cast(super.userMetadata(key, value));
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), autoAssignFloatingIp);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
NovaTemplateOptions other = (NovaTemplateOptions) obj;
return Objects.equal(autoAssignFloatingIp, other.autoAssignFloatingIp);
}
@Override
public String toString() {
return String.format("[autoAssignFloatingIp=%s]", autoAssignFloatingIp);
}
}

View File

@ -20,6 +20,7 @@ package org.jclouds.openstack.nova.v1_1.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
import java.util.List;
import java.util.Map;
@ -107,14 +108,21 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
templateOptions);
}
boolean keyPairExensionPresent = novaClient.getKeyPairExtensionForZone(zone).isPresent();
if (templateOptions.shouldGenerateKeyPair()) {
checkArgument(novaClient.getKeyPairExtensionForZone(zone).isPresent(),
"Key Pairs are required by options, but the extension is not available! options: %s",
templateOptions);
if (templateOptions.getKeyPairName() == null) {
KeyPair keyPair = keyPairCache.getUnchecked(ZoneAndName.fromZoneAndName(zone, "jclouds#" + group));
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));
keyPairCache.asMap().put(ZoneAndName.fromZoneAndName(zone, keyPair.getName()), keyPair);
templateOptions.keyPairName(keyPair.getName());
} else if (templateOptions.getKeyPairName() != null) {
checkArgument(keyPairExensionPresent,
"Key Pairs are required by options, but the extension is not available! options: %s", templateOptions);
if (templateOptions.getLoginPrivateKey() != null) {
String pem = templateOptions.getLoginPrivateKey();
KeyPair keyPair = KeyPair.builder().name(templateOptions.getKeyPairName())
.fingerprint(fingerprintPrivateKey(pem)).privateKey(pem).build();
keyPairCache.asMap().put(ZoneAndName.fromZoneAndName(zone, keyPair.getName()), keyPair);
templateOptions.keyPairName(keyPair.getName());
}
}
@ -125,7 +133,7 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
"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 = "jclouds_" + group;
try {
securityGroupCache.get(new ZoneSecurityGroupNameAndPorts(zone, securityGroupName, inboundPorts));
} catch (ExecutionException e) {

View File

@ -164,7 +164,6 @@ public class KeyPair implements Comparable<KeyPair> {
@Override
public String toString() {
return toStringHelper("").add("publicKey", publicKey).add("privateKey", privateKey).add("userId", userId)
.add("name", name).add("fingerprint", fingerprint).toString();
return toStringHelper("").add("userId", userId).add("name", name).add("fingerprint", fingerprint).toString();
}
}

View File

@ -34,7 +34,7 @@ import org.jclouds.openstack.services.ServiceType;
* @author Jeremy Daggett
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface FloatingIPClient {
/**

View File

@ -35,7 +35,7 @@ import org.jclouds.openstack.services.ServiceType;
* @author Jeremy Daggett
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface KeyPairClient {
/**

View File

@ -36,7 +36,7 @@ import org.jclouds.openstack.services.ServiceType;
* @author Jeremy Daggett
*/
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS)
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface SecurityGroupClient {
/**

View File

@ -35,7 +35,7 @@ import org.jclouds.openstack.nova.v1_1.domain.Image;
* />
* @author Adrian Cole
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ImageClient {
/**

View File

@ -38,7 +38,7 @@ import org.jclouds.openstack.nova.v1_1.options.RebuildServerOptions;
* />
* @author Adrian Cole
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ServerClient {
/**
@ -78,6 +78,7 @@ public interface ServerClient {
* request
* @return the newly created server
*/
@Timeout(duration = 5, timeUnit = TimeUnit.MINUTES)
Server createServer(String name, String imageRef, String flavorRef, CreateServerOptions... options);
/**

View File

@ -52,4 +52,26 @@ public class KeyPairPredicates {
}
};
}
/**
* matches name of the given keypair starts with the specified prefix
*
* @param name the prefix you are looking for
* @return the predicate
*/
public static Predicate<KeyPair> nameEquals(final String name) {
checkNotNull(name, "name must be defined");
return new Predicate<KeyPair>() {
@Override
public boolean apply(KeyPair ext) {
return ext.getName() != null && ext.getName().equals(name);
}
@Override
public String toString() {
return "nameEquals(" + name + ")";
}
};
}
}

View File

@ -18,18 +18,22 @@
*/
package org.jclouds.openstack.nova.v1_1.compute.functions;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import org.jclouds.openstack.nova.v1_1.NovaClient;
import org.jclouds.openstack.nova.v1_1.domain.KeyPair;
import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient;
import org.testng.annotations.Test;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.*;
import static org.testng.Assert.assertEquals;
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.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
/**
* @author Adam Lowe
@ -48,7 +52,7 @@ public class CreateUniqueKeyPairTest {
expect(client.getKeyPairExtensionForZone("zone")).andReturn(Optional.of(keyClient)).atLeastOnce();
expect(uniqueIdSupplier.get()).andReturn("1");
expect(keyClient.createKeyPair("jclouds#group#1")).andReturn(pair);
expect(keyClient.createKeyPair("group_1")).andReturn(pair);
replay(client);
replay(keyClient);
@ -56,7 +60,7 @@ public class CreateUniqueKeyPairTest {
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(client, uniqueIdSupplier);
assertEquals(parser.createNewKeyPairInZone("zone", "group"), pair);
assertEquals(parser.apply(ZoneAndName.fromZoneAndName("zone", "group")), pair);
verify(client);
verify(keyClient);
@ -74,9 +78,9 @@ public class CreateUniqueKeyPairTest {
expect(client.getKeyPairExtensionForZone("zone")).andReturn(Optional.of(keyClient)).atLeastOnce();
expect(uniqueIdSupplier.get()).andReturn("1");
expect(keyClient.createKeyPair("jclouds#group#1")).andThrow(new IllegalStateException());
expect(keyClient.createKeyPair("group_1")).andThrow(new IllegalStateException());
expect(uniqueIdSupplier.get()).andReturn("2");
expect(keyClient.createKeyPair("jclouds#group#2")).andReturn(pair);
expect(keyClient.createKeyPair("group_2")).andReturn(pair);
replay(client);
replay(keyClient);
@ -84,7 +88,7 @@ public class CreateUniqueKeyPairTest {
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(client, uniqueIdSupplier);
assertEquals(parser.createNewKeyPairInZone("zone", "group"), pair);
assertEquals(parser.apply(ZoneAndName.fromZoneAndName("zone", "group")), pair);
verify(client);
verify(keyClient);

View File

@ -50,7 +50,7 @@ public class CreateSecurityGroupIfNeededTest extends BaseNovaClientExpectTest {
authToken).build())
.payload(
payloadFromStringWithContentType(
"{\"security_group\":{\"name\":\"jclouds#mygroup\",\"description\":\"jclouds#mygroup\"}}",
"{\"security_group\":{\"name\":\"jclouds_mygroup\",\"description\":\"jclouds_mygroup\"}}",
"application/json")).build();
public void testCreateNewGroup() throws Exception {
@ -64,7 +64,7 @@ public class CreateSecurityGroupIfNeededTest extends BaseNovaClientExpectTest {
HttpResponse createSecurityGroupResponse = HttpResponse.builder().statusCode(200)
.payload(
payloadFromStringWithContentType(
String.format("{\"security_group\": {\"rules\": [], \"tenant_id\": \"37936628937291\", \"id\": %s, \"name\": \"jclouds#mygroup\", \"description\": \"jclouds#mygroup\"}}", groupId),
String.format("{\"security_group\": {\"rules\": [], \"tenant_id\": \"37936628937291\", \"id\": %s, \"name\": \"jclouds_mygroup\", \"description\": \"jclouds_mygroup\"}}", groupId),
"application/json; charset=UTF-8")).build();
builder.put(createSecurityGroup, createSecurityGroupResponse);
@ -103,7 +103,7 @@ public class CreateSecurityGroupIfNeededTest extends BaseNovaClientExpectTest {
HttpResponse createSelfRuleResponse = HttpResponse.builder().statusCode(200)
.payload(
payloadFromStringWithContentType(
String.format("{\"security_group_rule\": {\"from_port\": %d, \"group\": {\"tenant_id\": \"37936628937291\", \"name\": \"jclouds#mygroup\"}, \"ip_protocol\": \"tcp\", \"to_port\": %d, \"parent_group_id\": %d, \"ip_range\": {}, \"id\": %d}}",
String.format("{\"security_group_rule\": {\"from_port\": %d, \"group\": {\"tenant_id\": \"37936628937291\", \"name\": \"jclouds_mygroup\"}, \"ip_protocol\": \"tcp\", \"to_port\": %d, \"parent_group_id\": %d, \"ip_range\": {}, \"id\": %d}}",
port, port, groupId, ruleId++), "application/json; charset=UTF-8")).build();
builder.put(createSelfRule, createSelfRuleResponse);
@ -125,7 +125,7 @@ public class CreateSecurityGroupIfNeededTest extends BaseNovaClientExpectTest {
// we can find it
assertEquals(fn.apply(
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds#mygroup", ImmutableSet.of(22, 8080)))
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds_mygroup", ImmutableSet.of(22, 8080)))
.toString(), new SecurityGroupInZone(new ParseComputeServiceTypicalSecurityGroupTest().expected(),
"az-1.region-a.geo-1").toString());
@ -162,7 +162,7 @@ public class CreateSecurityGroupIfNeededTest extends BaseNovaClientExpectTest {
// we can find it
assertEquals(fn.apply(
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds#mygroup", ImmutableSet.of(22, 8080)))
new ZoneSecurityGroupNameAndPorts("az-1.region-a.geo-1", "jclouds_mygroup", ImmutableSet.of(22, 8080)))
.toString(), new SecurityGroupInZone(new ParseComputeServiceTypicalSecurityGroupTest().expected(),
"az-1.region-a.geo-1").toString());

View File

@ -58,19 +58,19 @@ public class ParseComputeServiceTypicalSecurityGroupTest extends BaseItemParserT
SecurityGroupRule.builder().fromPort(22)
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("2769")
.ipRange("0.0.0.0/0").id("10331").build(),
SecurityGroupRule.builder().fromPort(22).group(new TenantIdAndName("37936628937291", "jclouds#mygroup"))
SecurityGroupRule.builder().fromPort(22).group(new TenantIdAndName("37936628937291", "jclouds_mygroup"))
.ipProtocol(IpProtocol.TCP).toPort(22).parentGroupId("2769")
.id("10332").build(),
SecurityGroupRule.builder().fromPort(8080)
.ipProtocol(IpProtocol.TCP).toPort(8080).parentGroupId("2769")
.ipRange("0.0.0.0/0").id("10333").build(),
SecurityGroupRule.builder().fromPort(8080).group(new TenantIdAndName("37936628937291", "jclouds#mygroup"))
SecurityGroupRule.builder().fromPort(8080).group(new TenantIdAndName("37936628937291", "jclouds_mygroup"))
.ipProtocol(IpProtocol.TCP).toPort(8080).parentGroupId("2769")
.id("10334").build()
);
return SecurityGroup.builder().description("jclouds#mygroup").id("2769").tenantId("37936628937291").rules(securityGroupRules)
.name("jclouds#mygroup").build();
return SecurityGroup.builder().description("jclouds_mygroup").id("2769").tenantId("37936628937291").rules(securityGroupRules)
.name("jclouds_mygroup").build();
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());

View File

@ -14,7 +14,7 @@
"from_port": 22,
"group": {
"tenant_id": "37936628937291",
"name": "jclouds#mygroup"
"name": "jclouds_mygroup"
},
"ip_protocol": "tcp",
"to_port": 22,
@ -35,7 +35,7 @@
"from_port": 8080,
"group": {
"tenant_id": "37936628937291",
"name": "jclouds#mygroup"
"name": "jclouds_mygroup"
},
"ip_protocol": "tcp",
"to_port": 8080,
@ -45,7 +45,7 @@
}],
"tenant_id": "37936628937291",
"id": 2769,
"name": "jclouds#mygroup",
"description": "jclouds#mygroup"
"name": "jclouds_mygroup",
"description": "jclouds_mygroup"
}
}

View File

@ -15,7 +15,7 @@
"from_port": 22,
"group": {
"tenant_id": "37936628937291",
"name": "jclouds#mygroup"
"name": "jclouds_mygroup"
},
"ip_protocol": "tcp",
"to_port": 22,
@ -36,7 +36,7 @@
"from_port": 8080,
"group": {
"tenant_id": "37936628937291",
"name": "jclouds#mygroup"
"name": "jclouds_mygroup"
},
"ip_protocol": "tcp",
"to_port": 8080,
@ -46,8 +46,8 @@
}],
"tenant_id": "37936628937291",
"id": 2769,
"name": "jclouds#mygroup",
"description": "jclouds#mygroup"
"name": "jclouds_mygroup",
"description": "jclouds_mygroup"
}
]
}