Updated Branches: refs/heads/master 7651657cf -> a3488dc43
JCLOUDS-105. Real fix for keypairs being ignored if VM says it's password-enabled. Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/commit/a3488dc4 Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/tree/a3488dc4 Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/diff/a3488dc4 Branch: refs/heads/master Commit: a3488dc43cd60580374532f3780bdb1b1ec8697c Parents: fbe637c Author: Andrew Bayer <[email protected]> Authored: Fri May 31 10:53:18 2013 -0700 Committer: Andrew Bayer <[email protected]> Committed: Thu Jun 6 10:26:20 2013 -0700 ---------------------------------------------------------------------- .../strategy/CloudStackComputeServiceAdapter.java | 23 ++++-- .../CloudStackComputeServiceAdapterExpectTest.java | 63 ++++++++++++- .../CloudStackComputeServiceAdapterLiveTest.java | 71 ++++----------- 3 files changed, 91 insertions(+), 66 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/a3488dc4/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/CloudStackComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/CloudStackComputeServiceAdapter.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/CloudStackComputeServiceAdapter.java index a4f7176..5ad2fff 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/CloudStackComputeServiceAdapter.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/CloudStackComputeServiceAdapter.java @@ -174,12 +174,19 @@ public class CloudStackComputeServiceAdapter implements } if (templateOptions.getKeyPair() != null) { + SshKeyPair keyPair = null; if (templateOptions.getLoginPrivateKey() != null) { String pem = templateOptions.getLoginPrivateKey(); - SshKeyPair keyPair = SshKeyPair.builder().name(templateOptions.getKeyPair()) + keyPair = SshKeyPair.builder().name(templateOptions.getKeyPair()) .fingerprint(fingerprintPrivateKey(pem)).privateKey(pem).build(); keyPairCache.asMap().put(keyPair.getName(), keyPair); options.keyPair(keyPair.getName()); + } else if (client.getSSHKeyPairClient().getSSHKeyPair(templateOptions.getKeyPair()) != null) { + keyPair = client.getSSHKeyPairClient().getSSHKeyPair(templateOptions.getKeyPair()); + } + if (keyPair != null) { + keyPairCache.asMap().put(keyPair.getName(), keyPair); + options.keyPair(keyPair.getName()); } } else if (templateOptions.shouldGenerateKeyPair()) { SshKeyPair keyPair = keyPairCache.getUnchecked(namingConvention.create() @@ -214,13 +221,15 @@ public class CloudStackComputeServiceAdapter implements templateId, options); VirtualMachine vm = blockUntilJobCompletesAndReturnResult.<VirtualMachine>apply(job); logger.debug("--- virtualmachine: %s", vm); - LoginCredentials credentials = null; - if (vm.isPasswordEnabled()) { - assert vm.getPassword() != null : vm; - credentials = LoginCredentials.builder().password(vm.getPassword()).build(); + LoginCredentials.Builder credentialsBuilder = LoginCredentials.builder(); + if (!vm.isPasswordEnabled() || templateOptions.getKeyPair() != null) { + SshKeyPair keyPair = keyPairCache.getUnchecked(templateOptions.getKeyPair()); + credentialsBuilder.privateKey(keyPair.getPrivateKey()); } else { - credentials = LoginCredentials.fromCredentials(credentialStore.get("keypair#" + templateOptions.getKeyPair())); + assert vm.getPassword() != null : vm; + credentialsBuilder.password(vm.getPassword()); } + if (templateOptions.shouldSetupStaticNat()) { Capabilities capabilities = client.getConfigurationClient().listCapabilities(); // TODO: possibly not all network ids, do we want to do this @@ -241,7 +250,7 @@ public class CloudStackComputeServiceAdapter implements } } } - return new NodeAndInitialCredentials<VirtualMachine>(vm, vm.getId() + "", credentials); + return new NodeAndInitialCredentials<VirtualMachine>(vm, vm.getId() + "", credentialsBuilder.build()); } @Override http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/a3488dc4/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java ---------------------------------------------------------------------- diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java index 1e6ff6f..4eb89aa 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java @@ -83,6 +83,57 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom .payload(payloadFromResource("/queryasyncjobresultresponse-authorizeingress.json")) .build(); + HttpRequest listCapabilitiesNotListAll = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "listCapabilities") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "l3PVoJnKK2G2gHk3HPHtpwWjlW4%3D") + .addHeader("Accept", "application/json") + .build(); + + public void testCreateNodeWithGroupEncodedIntoName() { + HttpRequest deployVM = HttpRequest.builder().method("GET") + .endpoint("http://localhost:8080/client/api") + .addQueryParam("response", "json") + .addQueryParam("command", "deployVirtualMachine") + .addQueryParam("zoneid", "1") + .addQueryParam("serviceofferingid", "1") + .addQueryParam("templateid", "4") + .addQueryParam("displayname", "test-e92") + .addQueryParam("name", "test-e92") + .addQueryParam("networkids", "204") + .addQueryParam("apiKey", "APIKEY") + .addQueryParam("signature", "wJ%2BiflOS3am5qcjQOd8Y/Pw8/Dc%3D") + .addHeader("Accept", "application/json") + .build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(listTemplates, listTemplatesResponse) + .put(listOsTypes, listOsTypesResponse) + .put(listOsCategories, listOsCategoriesResponse) + .put(listZones, listZonesResponse) + .put(listServiceOfferings, listServiceOfferingsResponse) + .put(listAccounts, listAccountsResponse) + .put(listNetworks, listNetworksResponse) + .put(getZone, getZoneResponse) + .put(deployVM, deployVMResponse) + .put(queryAsyncJobResult, queryAsyncJobResultResponse) + .build(); + + Injector forNode = requestsSendResponses(requestResponseMap); + + Template template = forNode.getInstance(TemplateBuilder.class).osFamily(OsFamily.CENTOS).build(); + template.getOptions().as(CloudStackTemplateOptions.class).setupStaticNat(false); + + CloudStackComputeServiceAdapter adapter = forNode.getInstance(CloudStackComputeServiceAdapter.class); + + NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", + template); + assertNotNull(server); + assertEquals(server.getCredentials(), LoginCredentials.builder().password("dD7jwajkh").build()); + } + public void testCreateNodeWithGroupEncodedIntoNameWithKeyPair() throws IOException { HttpRequest deployVM = HttpRequest.builder().method("GET") .endpoint("http://localhost:8080/client/api") @@ -126,7 +177,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template); assertNotNull(server); - assertEquals(server.getCredentials(), LoginCredentials.builder().password("dD7jwajkh").build()); + assertEquals(server.getCredentials().getPrivateKey(), privKey); } public void testCreateNodeWithGroupEncodedIntoNameWithGenerateKeyPair() throws IOException { @@ -171,7 +222,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template); assertNotNull(server); - assertEquals(server.getCredentials(), LoginCredentials.builder().password("dD7jwajkh").build()); + assertNotNull(server.getCredentials().getPrivateKey()); } public void testCreateNodeWithGroupEncodedIntoNameWithKeyPairDefaultSecurityGroup() throws IOException { @@ -220,7 +271,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template); assertNotNull(server); - assertEquals(server.getCredentials(), LoginCredentials.builder().password("dD7jwajkh").build()); + assertEquals(server.getCredentials().getPrivateKey(), privKey); } public void testCreateNodeWithGroupEncodedIntoNameWithKeyPairGenerateSecurityGroup() throws IOException { @@ -271,11 +322,12 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom .overrideLoginPrivateKey(privKey); CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + CloudStackContext context = forKeyPair.getInstance(CloudStackContext.class); NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template); assertNotNull(server); - assertEquals(server.getCredentials(), LoginCredentials.builder().password("dD7jwajkh").build()); + assertEquals(server.getCredentials().getPrivateKey(), privKey); } public void testCreateNodeWithGroupEncodedIntoNameWithKeyPairAssignedToAccountAndDomain() throws IOException { @@ -321,11 +373,12 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom .overrideLoginPrivateKey(privKey); CloudStackComputeServiceAdapter adapter = forKeyPair.getInstance(CloudStackComputeServiceAdapter.class); + CloudStackContext context = forKeyPair.getInstance(CloudStackContext.class); NodeAndInitialCredentials<VirtualMachine> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template); assertNotNull(server); - assertEquals(server.getCredentials(), LoginCredentials.builder().password("dD7jwajkh").build()); + assertEquals(server.getCredentials().getPrivateKey(), privKey); } @Override http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/a3488dc4/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java ---------------------------------------------------------------------- diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java index a1ad652..82efa60 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java @@ -31,17 +31,27 @@ import javax.inject.Singleton; import org.jclouds.cloudstack.CloudStackClient; import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule; +import org.jclouds.cloudstack.compute.functions.OrphanedGroupsByZoneId; +import org.jclouds.cloudstack.compute.loaders.CreateUniqueKeyPair; +import org.jclouds.cloudstack.compute.loaders.FindSecurityGroupOrCreate; import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter; import org.jclouds.cloudstack.compute.strategy.OptionsConverter; +import org.jclouds.cloudstack.config.CloudStackParserModule; +import org.jclouds.cloudstack.config.CloudStackRestClientModule; import org.jclouds.cloudstack.domain.FirewallRule; import org.jclouds.cloudstack.domain.IPForwardingRule; import org.jclouds.cloudstack.domain.Network; import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.SecurityGroup; import org.jclouds.cloudstack.domain.ServiceOffering; +import org.jclouds.cloudstack.domain.SshKeyPair; import org.jclouds.cloudstack.domain.User; import org.jclouds.cloudstack.domain.VirtualMachine; import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.domain.ZoneAndName; +import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs; +import org.jclouds.cloudstack.functions.CreateSecurityGroupIfNeeded; import org.jclouds.cloudstack.functions.GetFirewallRulesByVirtualMachine; import org.jclouds.cloudstack.functions.GetIPForwardingRulesByVirtualMachine; import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork; @@ -55,15 +65,19 @@ import org.jclouds.cloudstack.suppliers.ZoneIdToZoneSupplier; import org.jclouds.collect.Memoized; import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; import org.jclouds.compute.ComputeTestUtils; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; +import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials; import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; import org.jclouds.domain.Credentials; +import org.jclouds.location.Provider; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; +import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; @@ -72,6 +86,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.common.net.HostAndPort; import com.google.common.net.InetAddresses; import com.google.inject.AbstractModule; @@ -96,60 +111,8 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien @BeforeGroups(groups = { "live" }) public void setupContext() { super.setupContext(); - Module module = new AbstractModule() { - - @Override - protected void configure() { - bindProperties(binder(), setupProperties()); - bind(new TypeLiteral<Supplier<User>>() { - }).annotatedWith(Memoized.class).to(GetCurrentUser.class).in(Scopes.SINGLETON); - bind(new TypeLiteral<Supplier<Map<String, Network>>>() { - }).annotatedWith(Memoized.class).to(NetworksForCurrentUser.class).in(Scopes.SINGLETON); - bind(new TypeLiteral<Map<String, Credentials>>() { - }).toInstance(credentialStore); - bind(CloudStackClient.class).toInstance(client); - bind(new TypeLiteral<Map<NetworkType, ? extends OptionsConverter>>() {}). - toInstance(new CloudStackComputeServiceContextModule().optionsConverters()); - bind(String.class).annotatedWith(Names.named(PROPERTY_SESSION_INTERVAL)).toInstance("60"); - bind(new TypeLiteral<CacheLoader<String, Set<IPForwardingRule>>>() { - }).to(GetIPForwardingRulesByVirtualMachine.class); - bind(new TypeLiteral<CacheLoader<String, Set<FirewallRule>>>() { - }).to(GetFirewallRulesByVirtualMachine.class); - bind(new TypeLiteral<CacheLoader<String, Zone>>() {}). - to(ZoneIdToZone.class); - bind(new TypeLiteral<Supplier<LoadingCache<String, Zone>>>() {}). - to(ZoneIdToZoneSupplier.class); - install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class)); - } - - @Provides - @Singleton - Supplier<Credentials> supplyCredentials(){ - return Suppliers.ofInstance(new Credentials(identity, credential)); - } - - @Provides - @Singleton - protected Predicate<String> jobComplete(JobComplete jobComplete) { - return retry(jobComplete, 1200, 1, 5, SECONDS); - } - - @Provides - @Singleton - protected LoadingCache<String, Set<IPForwardingRule>> getIPForwardingRulesByVirtualMachine( - GetIPForwardingRulesByVirtualMachine getIPForwardingRules) { - return CacheBuilder.newBuilder().build(getIPForwardingRules); - } - - - @Provides - @Singleton - protected LoadingCache<String, Set<FirewallRule>> getFirewallRulesByVirtualMachine( - GetFirewallRulesByVirtualMachine getFirewallRules) { - return CacheBuilder.newBuilder().build(getFirewallRules); - } - }; - adapter = Guice.createInjector(module, new SLF4JLoggingModule()).getInstance( + + adapter = context.utils().injector().getInstance( CloudStackComputeServiceAdapter.class); keyPairName = prefix + "-adapter-test-keypair";
