@Test public void testLaunchCluster() throws RunNodesException { int numNodes = 3; final String clusterName = "test-launch-cluster"; Set<? extends NodeMetadata> nodes = context .getComputeService() .createNodesInGroup( clusterName, numNodes, TemplateOptions.Builder.overrideLoginUser("toor") .runScript(AdminAccess.standard())); assertEquals(numNodes, nodes.size(), "wrong number of nodes"); for (NodeMetadata node : nodes) { assertEquals("test-launch-cluster", node.getGroup()); logger.debug("Created Node: %s", node); SshClient client = context.utils().sshForNode().apply(node); client.connect(); ExecResponse hello = client.exec("echo hello"); assertEquals(hello.getOutput().trim(), "hello"); } context .getComputeService() .destroyNodesMatching( new Predicate<NodeMetadata>() { @Override public boolean apply(NodeMetadata input) { return input.getId().contains(clusterName); } }); }
// Suggest at least 15 minutes for timeout public static String waitForPasswordOnAws( ComputeService computeService, final NodeMetadata node, long timeout, TimeUnit timeUnit) throws TimeoutException { ComputeServiceContext computeServiceContext = computeService.getContext(); AWSEC2Api ec2Client = computeServiceContext.unwrapApi(AWSEC2Api.class); final WindowsApi client = ec2Client.getWindowsApi().get(); final String region = node.getLocation().getParent().getId(); // The Administrator password will take some time before it is ready - Amazon says sometimes 15 // minutes. // So we create a predicate that tests if the password is ready, and wrap it in a retryable // predicate. Predicate<String> passwordReady = new Predicate<String>() { @Override public boolean apply(String s) { if (Strings.isNullOrEmpty(s)) return false; PasswordData data = client.getPasswordDataInRegion(region, s); if (data == null) return false; return !Strings.isNullOrEmpty(data.getPasswordData()); } }; LOG.info("Waiting for password, for " + node.getProviderId() + ":" + node.getId()); Predicate<String> passwordReadyRetryable = Predicates2.retry( passwordReady, timeUnit.toMillis(timeout), 10 * 1000, TimeUnit.MILLISECONDS); boolean ready = passwordReadyRetryable.apply(node.getProviderId()); if (!ready) throw new TimeoutException( "Password not available for " + node + " in region " + region + " after " + timeout + " " + timeUnit.name()); // Now pull together Amazon's encrypted password blob, and the private key that jclouds // generated PasswordDataAndPrivateKey dataAndKey = new PasswordDataAndPrivateKey( client.getPasswordDataInRegion(region, node.getProviderId()), node.getCredentials().getPrivateKey()); // And apply it to the decryption function WindowsLoginCredentialsFromEncryptedData f = computeServiceContext .utils() .injector() .getInstance(WindowsLoginCredentialsFromEncryptedData.class); LoginCredentials credentials = f.apply(dataAndKey); return credentials.getPassword(); }
public static String getFirstReachableAddress(ComputeServiceContext context, NodeMetadata node) { // To pick the address, it relies on jclouds `sshForNode().apply(Node)` to check all IPs of node // (private+public), // to find one that is reachable. It does `openSocketFinder.findOpenSocketOnNode(node, // node.getLoginPort(), ...)`. // This keeps trying for time // org.jclouds.compute.reference.ComputeServiceConstants.Timeouts.portOpen. // TODO Want to configure this timeout here. // // TODO We could perhaps instead just set `templateOptions.blockOnPort(loginPort, 120)`, but // need // to be careful to only set that if config WAIT_FOR_SSHABLE is true. For some advanced // networking examples // (e.g. using DNAT on CloudStack), the brooklyn machine won't be able to reach the VM until // some additional // setup steps have been done. See links from Andrea: // https://github.com/jclouds/jclouds/pull/895 // https://issues.apache.org/jira/browse/WHIRR-420 // jclouds.ssh.max-retries // jclouds.ssh.retry-auth SshClient client; try { client = context.utils().sshForNode().apply(node); } catch (Exception e) { Exceptions.propagateIfFatal(e); /* i've seen: java.lang.IllegalStateException: Optional.get() cannot be called on an absent value * from org.jclouds.crypto.ASN1Codec.createASN1Sequence(ASN1Codec.java:86), if the ssh key has a passphrase, against AWS. * * others have reported: java.lang.IllegalArgumentException: DER length more than 4 bytes * when using a key with a passphrase (perhaps from other clouds?); not sure if that's this callpath or a different one. */ throw new IllegalStateException( "Unable to connect SshClient to " + node + "; check that the node is accessible and that the SSH key exists and is correctly configured, including any passphrase defined", e); } return client.getHostAddress(); }
public static CloudTransformer tranformerFor(ComputeServiceContext source, String target) { return checkNotNull( source.utils().injector().getInstance(Key.get(mapOfString)).get(target), " no transformer were registered for targget cloud: " + target); }
protected Logger logger() { return context.utils().loggerFactory().getLogger("jclouds.compute"); }