blob: 48cf8c55675df7b6f218e8de9fb3ff6df7a1d005 [file] [log] [blame]
/**
* 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.ec2.compute;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDevice;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.domain.Snapshot;
import org.jclouds.ec2.domain.Volume;
import org.jclouds.ec2.reference.EC2Constants;
import org.jclouds.ec2.services.ElasticBlockStoreClient;
import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.ec2.services.KeyPairClient;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.net.IPSocket;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.util.InetAddresses2;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true)
public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public EC2ComputeServiceLiveTest() {
provider = "ec2";
}
@Override
protected Module getSshModule() {
return new SshjSshClientModule();
}
// normal ec2 does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
assert node.getUserMetadata().equals(ImmutableMap.<String, String> of()) : String.format(
"node userMetadata did not match %s %s", userMetadata, node);
}
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testImagesResolveCorrectly() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getId(), defaultTemplate.getImage().getLocation().getId() + "/"
+ defaultTemplate.getImage().getProviderId());
Template byId = client.templateBuilder().imageId(defaultTemplate.getImage().getId()).build();
assertEquals(byId.getImage(), defaultTemplate.getImage());
}
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsAndLogin() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
String group = this.group + "o";
TemplateOptions options = client.templateOptions();
options.as(EC2TemplateOptions.class).securityGroups(group);
String startedId = null;
try {
cleanupExtendedStuffInRegion(null, securityGroupClient, keyPairClient, group);
// create a security group that allows ssh in so that our scripts later
// will work
securityGroupClient.createSecurityGroupInRegion(null, group, group);
securityGroupClient.authorizeSecurityGroupIngressInRegion(null, group, IpProtocol.TCP, 22, 22, "0.0.0.0/0");
// create a keypair to pass in as well
KeyPair result = keyPairClient.createKeyPairInRegion(null, group);
options.as(EC2TemplateOptions.class).keyPair(result.getKeyName());
// pass in the private key, so that we can run a script with it
assert result.getKeyMaterial() != null : result;
options.overrideLoginPrivateKey(result.getKeyMaterial());
// an arbitrary command to run
options.runScript(Statements.exec("find /usr"));
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options);
NodeMetadata first = Iterables.get(nodes, 0);
assert first.getCredentials() != null : first;
assert first.getCredentials().identity != null : first;
startedId = Iterables.getOnlyElement(nodes).getProviderId();
RunningInstance instance = getInstance(instanceClient, startedId);
assertEquals(instance.getKeyName(), group);
// make sure we made our dummy group and also let in the user's group
assertEquals(Sets.newTreeSet(instance.getGroupIds()), ImmutableSortedSet.<String> of("jclouds#" + group + "#"
+ instance.getRegion(), group));
// make sure our dummy group has no rules
SecurityGroup secgroup = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
"jclouds#" + group + "#" + instance.getRegion()));
assert secgroup.getIpPermissions().size() == 0 : secgroup;
// try to run a script with the original keyPair
runScriptWithCreds(group, first.getOperatingSystem(),
LoginCredentials.builder().user(first.getCredentials().identity).privateKey(result.getKeyMaterial())
.build());
} finally {
client.destroyNodesMatching(NodePredicates.inGroup(group));
if (startedId != null) {
// ensure we didn't delete these resources!
assertEquals(keyPairClient.describeKeyPairsInRegion(null, group).size(), 1);
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, group).size(), 1);
}
cleanupExtendedStuffInRegion(null, securityGroupClient, keyPairClient, group);
}
}
@Test(enabled = true) //, dependsOnMethods = "testCompareSizes")
public void testAutoIpAllocation() throws Exception {
ComputeServiceContext context = null;
String group = this.group + "aip";
try {
Properties overrides = setupProperties();
overrides.setProperty(EC2Constants.PROPERTY_EC2_AUTO_ALLOCATE_ELASTIC_IPS, "true");
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides);
// create a node
Set<? extends NodeMetadata> nodes =
context.getComputeService().createNodesInGroup(group, 1);
assertEquals(nodes.size(), 1, "One node should have been created");
// Get public IPs (We should get 1)
NodeMetadata node = Iterables.get(nodes, 0);
String region = node.getLocation().getParent().getId();
Set<String> publicIps = node.getPublicAddresses();
assertFalse(Iterables.isEmpty(publicIps), String.format("no public addresses attached to node %s", node));
assertEquals(Iterables.size(publicIps), 1);
// Check that the address is public and port 22 is accessible
String ip = Iterables.getOnlyElement(publicIps);
assertFalse(InetAddresses2.isPrivateIPAddress(ip));
IPSocket socket = new IPSocket(ip, 22);
assertTrue(socketTester.apply(socket), String.format("failed to open socket %s on node %s", socket, node));
// check that there is an elastic ip correlating to it
EC2Client ec2 = EC2Client.class.cast(context.getProviderSpecificContext().getApi());
Set<PublicIpInstanceIdPair> ipidpairs =
ec2.getElasticIPAddressServices().describeAddressesInRegion(region, publicIps.toArray(new String[0]));
assertEquals(ipidpairs.size(), 1, String.format("there should only be one address pair (%s)",
Iterables.toString(ipidpairs)));
// check that the elastic ip is in node.publicAddresses
PublicIpInstanceIdPair ipidpair = Iterables.get(ipidpairs, 0);
assertEquals(region + "/" + ipidpair.getInstanceId(), node.getId());
// delete the node
context.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
// check that the ip is deallocated
Set<PublicIpInstanceIdPair> ipidcheck =
ec2.getElasticIPAddressServices().describeAddressesInRegion(region, ipidpair.getPublicIp());
assertTrue(Iterables.isEmpty(ipidcheck), String.format("there should be no address pairs (%s)",
Iterables.toString(ipidcheck)));
} finally {
context.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
if (context != null)
context.close();
}
}
/**
* Note we cannot use the micro size as it has no ephemeral space.
*/
@Test(enabled = true)
public void testMapEBS() throws Exception {
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
ElasticBlockStoreClient ebsClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getElasticBlockStoreServices();
String group = this.group + "e";
int volumeSize = 8;
final Template template = context.getComputeService().templateBuilder().hardwareId(InstanceType.M1_SMALL)
.osFamily(OsFamily.UBUNTU).osVersionMatches("10.04").imageDescriptionMatches(".*ebs.*").build();
Location zone = Iterables.find(context.getComputeService().listAssignableLocations(), new Predicate<Location>() {
@Override
public boolean apply(Location arg0) {
return arg0.getScope() == LocationScope.ZONE
&& arg0.getParent().getId().equals(template.getLocation().getId());
}
});
// create volume only to make a snapshot
Volume volume = ebsClient.createVolumeInAvailabilityZone(zone.getId(), 4);
Snapshot snapshot = ebsClient.createSnapshotInRegion(volume.getRegion(), volume.getId());
ebsClient.deleteVolumeInRegion(volume.getRegion(), volume.getId());
template.getOptions().as(EC2TemplateOptions.class)//
// .unmapDeviceNamed("/dev/foo)
.mapEphemeralDeviceToDeviceName("/dev/sdm", "ephemeral0")//
.mapNewVolumeToDeviceName("/dev/sdn", volumeSize, true)//
.mapEBSSnapshotToDeviceName("/dev/sdo", snapshot.getId(), volumeSize, true);
try {
NodeMetadata node = Iterables.getOnlyElement(client.createNodesInGroup(group, 1, template));
// TODO figure out how to validate the ephemeral drive. perhaps with df -k?
Map<String, BlockDevice> devices = instanceClient.getBlockDeviceMappingForInstanceInRegion(node.getLocation()
.getParent().getId(), node.getProviderId());
BlockDevice device = devices.get("/dev/sdn");
// check delete on termination
assertTrue(device.isDeleteOnTermination());
volume = Iterables.getOnlyElement(ebsClient.describeVolumesInRegion(node.getLocation().getParent().getId(),
device.getVolumeId()));
// check volume size
assertEquals(volumeSize, volume.getSize());
device = devices.get("/dev/sdo");
// check delete on termination
assertTrue(device.isDeleteOnTermination());
volume = Iterables.getOnlyElement(ebsClient.describeVolumesInRegion(node.getLocation().getParent().getId(),
device.getVolumeId()));
// check volume size
assertEquals(volumeSize, volume.getSize());
// check volume's snapshot id
assertEquals(snapshot.getId(), volume.getSnapshotId());
} finally {
client.destroyNodesMatching(NodePredicates.inGroup(group));
ebsClient.deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
}
}
protected RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = Iterables.getOnlyElement(Iterables.getOnlyElement(instanceClient
.describeInstancesInRegion(null, id)));
return instance;
}
protected void cleanupExtendedStuffInRegion(String region, SecurityGroupClient securityGroupClient,
KeyPairClient keyPairClient, String group) throws InterruptedException {
try {
for (SecurityGroup secgroup : securityGroupClient.describeSecurityGroupsInRegion(region))
if (secgroup.getName().startsWith("jclouds#" + group) || secgroup.getName().equals(group)) {
securityGroupClient.deleteSecurityGroupInRegion(region, secgroup.getName());
}
} catch (Exception e) {
}
try {
for (KeyPair pair : keyPairClient.describeKeyPairsInRegion(region))
if (pair.getKeyName().startsWith("jclouds#" + group) || pair.getKeyName().equals(group)) {
keyPairClient.deleteKeyPairInRegion(region, pair.getKeyName());
}
} catch (Exception e) {
}
Thread.sleep(2000);
}
}