blob: 69249ea9b93abfe17135b2e3b485f6d0936f71c4 [file] [log] [blame]
package brooklyn.location.jclouds;
import static org.testng.Assert.assertNotNull;
import java.io.File;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import org.jclouds.Constants;
import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.util.text.Identifiers;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;
public class StandaloneJcloudsTest {
// FIXME Why do this?
// Were we seeing bugs in jclouds for which this was easier to debug and report
// Is it because testProvisioningVmWithCustomUsername is disabled and not working?
public static final Logger LOG = LoggerFactory.getLogger(StandaloneJcloudsTest.class);
static BrooklynProperties globals = BrooklynProperties.Factory.newDefault();
String identity = globals.getFirst("brooklyn.jclouds.aws-ec2.identity");
String credential = globals.getFirst("brooklyn.jclouds.aws-ec2.credential");
@Test(groups={"WIP","Live"})
public void createVm() {
String groupId = "mygroup-"+System.getProperty("user.name")+"-"+UUID.randomUUID().toString();
Properties properties = new Properties();
properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, Boolean.toString(true));
properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, Boolean.toString(true));
// handy to list all images... but very slow!
// properties.setProperty(AWSEC2Constants.PROPERTY_EC2_AMI_QUERY, "state=available;image-type=machine");
ComputeServiceContext computeServiceContext = ContextBuilder.newBuilder("aws-ec2").
modules(Arrays.asList(new SshjSshClientModule(), new SLF4JLoggingModule())).
credentials(identity, credential).
overrides(properties).
build(ComputeServiceContext.class);
final ComputeService computeService = computeServiceContext.getComputeService();
NodeMetadata node = null;
try {
LOG.info("Creating VM for "+identity);
TemplateBuilder templateBuilder = computeService.templateBuilder();
templateBuilder.locationId("eu-west-1");
Template template = templateBuilder.build();
Set<? extends NodeMetadata> nodes = computeService.createNodesInGroup(groupId, 1, template);
node = Iterables.getOnlyElement(nodes, null);
if (node == null) throw new IllegalStateException("No nodes returned");
assertNotNull(node.getOperatingSystem());
Credentials nodeCredentials = node.getCredentials();
final LoginCredentials expectedCredentials = LoginCredentials.fromCredentials(nodeCredentials);
LOG.info("Started VM, waiting for it to be sshable");
boolean reachable = false;
for (int i=0; i<120; i++) {
try {
Statement statement = Statements.newStatementList(Statements.exec("date"));
ExecResponse response = computeService.runScriptOnNode(node.getId(), statement,
RunScriptOptions.Builder.overrideLoginCredentials(expectedCredentials));
if (response.getExitStatus() == 0) {
LOG.info("ssh 'date' succeeded");
reachable = true;
break;
}
LOG.info("ssh 'date' failed, exit "+response.getExitStatus()+", but still in retry loop");
} catch (Exception e) {
if (i<120)
LOG.info("ssh 'date' failed, but still in retry loop: "+e);
else {
LOG.error("ssh 'date' failed after timeout: "+e, e);
Throwables.propagate(e);
}
}
Thread.sleep(1000);
}
if (!reachable) {
throw new IllegalStateException("SSH failed, never reachable");
}
} catch (RunNodesException e) {
if (e.getNodeErrors().size() > 0) {
node = Iterables.get(e.getNodeErrors().keySet(), 0);
}
LOG.error("Failed to start VM: "+e, e);
throw Throwables.propagate(e);
} catch (Exception e) {
LOG.error("Failed to start VM: "+e, e);
throw Throwables.propagate(e);
} finally {
LOG.info("Now destroying VM: "+node);
computeService.destroyNode( node.getId() );
computeService.getContext().close();
}
}
@Test(groups={"WIP","Live"})
public void createVmWithAdminUser() {
String groupId = "mygroup-"+System.getProperty("user.name")+"-"+UUID.randomUUID().toString();
Properties properties = new Properties();
properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, Boolean.toString(true));
properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, Boolean.toString(true));
ComputeServiceContext computeServiceContext = ContextBuilder.newBuilder("aws-ec2").
modules(Arrays.asList(new SshjSshClientModule(), new SLF4JLoggingModule())).
credentials(identity, credential).
overrides(properties).
build(ComputeServiceContext.class);
final ComputeService computeService = computeServiceContext.getComputeService();
NodeMetadata node = null;
try {
LOG.info("Creating VM for "+identity);
String myPubKey = Files.toString(new File(System.getProperty("user.home")+"/.ssh/aws-id_rsa.pub"), Charset.defaultCharset());
String myPrivKey = Files.toString(new File(System.getProperty("user.home")+"/.ssh/aws-id_rsa"), Charset.defaultCharset());
TemplateBuilder templateBuilder = computeService.templateBuilder();
templateBuilder.locationId("us-east-1");
TemplateOptions opts = new TemplateOptions();
// templateBuilder.imageId("us-east-1/ami-2342a94a"); //rightscale
// either use above, or below
templateBuilder.imageId("us-east-1/ami-f95cf390"); //private one (to test when user isn't autodetected)
opts.overrideLoginUser("ec2-user");
AdminAccess.Builder adminBuilder = AdminAccess.builder().
adminUsername("bob").
grantSudoToAdminUser(true).
authorizeAdminPublicKey(true).adminPublicKey(myPubKey).
// items below aren't wanted but values for some are required otherwise AdminAccess uses all defaults
lockSsh(true).adminPassword(Identifiers.makeRandomId(12)).
resetLoginPassword(false).loginPassword(Identifiers.makeRandomId(12)).
installAdminPrivateKey(false).adminPrivateKey("ignored");
opts.runScript(adminBuilder.build());
templateBuilder.options(opts);
Template template = templateBuilder.build();
Set<? extends NodeMetadata> nodes = computeService.createNodesInGroup(groupId, 1, template);
node = Iterables.getOnlyElement(nodes, null);
if (node == null) throw new IllegalStateException("No nodes returned");
LOG.info("Started VM, waiting for it to be sshable on "+node.getPublicAddresses());
final LoginCredentials crds =
// node.getCredentials();
LoginCredentials.builder().user("bob").privateKey(myPrivKey).build();
boolean reachable = false;
for (int i=0; i<120; i++) {
try {
Statement statement = Statements.newStatementList(Statements.exec("date"));
ExecResponse response = computeService.runScriptOnNode(node.getId(), statement,
RunScriptOptions.Builder.overrideLoginCredentials(crds));
if (response.getExitStatus() == 0) {
LOG.info("ssh 'date' succeeded");
reachable = true;
break;
}
LOG.info("ssh 'date' failed, exit "+response.getExitStatus()+", but still in retry loop");
} catch (Exception e) {
if (i<120)
LOG.info("ssh 'date' failed, but still in retry loop: "+e);
else {
LOG.error("ssh 'date' failed after timeout: "+e, e);
Throwables.propagate(e);
}
}
Thread.sleep(1000);
}
if (!reachable) {
throw new IllegalStateException("SSH failed, never reachable");
}
} catch (RunNodesException e) {
if (e.getNodeErrors().size() > 0) {
node = Iterables.get(e.getNodeErrors().keySet(), 0);
}
LOG.error("Failed to start VM: "+e, e);
throw Throwables.propagate(e);
} catch (Exception e) {
LOG.error("Failed to start VM: "+e, e);
throw Throwables.propagate(e);
} finally {
LOG.info("Now destroying VM: "+node);
computeService.destroyNode( node.getId() );
computeService.getContext().close();
}
}
}