|
|
@@ -16,7 +16,6 @@ import com.amazonaws.services.ec2.AmazonEC2; |
|
|
|
import com.amazonaws.services.ec2.AmazonEC2ClientBuilder; |
|
|
|
import com.amazonaws.services.ec2.model.*; |
|
|
|
import lombok.Getter; |
|
|
|
import lombok.NonNull; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.cobbzilla.util.http.HttpRequestBean; |
|
|
|
import org.cobbzilla.util.http.HttpResponseBean; |
|
|
@@ -38,9 +37,9 @@ public class AmazonEC2Driver extends ComputeServiceDriverBase { |
|
|
|
|
|
|
|
public static final String TAG_CLOUD_UUID = "cloudUUID"; |
|
|
|
public static final String TAG_NODE_UUID = "nodeUUID"; |
|
|
|
public static final String SUBNET_ID_PREFIX = "subnet_id_"; |
|
|
|
public static final String KEY_NAME_PREFIX = "KeyName_"; |
|
|
|
public static final int MIN_COUNT = 1; |
|
|
|
public static final int MAX_COUNT = 1; |
|
|
|
public static final int MAX_COUNT = 5; |
|
|
|
|
|
|
|
@Getter(lazy = true) private final AWSCredentialsProvider ec2credentials = new BubbleAwsCredentialsProvider(cloud, getCredentials()); |
|
|
|
|
|
|
@@ -69,16 +68,22 @@ public class AmazonEC2Driver extends ComputeServiceDriverBase { |
|
|
|
} |
|
|
|
|
|
|
|
@Override public List<BubbleNode> listNodes() throws IOException { |
|
|
|
|
|
|
|
final List<BubbleNode> nodes = new ArrayList<>(); |
|
|
|
DescribeInstancesResult result = new DescribeInstancesResult(); |
|
|
|
final AmazonEC2 ec2Client = getEc2Client(); |
|
|
|
|
|
|
|
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest() |
|
|
|
.withFilters( |
|
|
|
new Filter("instance.group-id").withValues(config.getConfig("group")), |
|
|
|
new Filter("tag:" + TAG_CLOUD_UUID).withValues(cloud.getUuid()), |
|
|
|
new Filter("instance-state-name").withValues("running", "pending") |
|
|
|
); |
|
|
|
|
|
|
|
DescribeInstancesResult result = ec2Client.describeInstances(describeInstancesRequest); |
|
|
|
|
|
|
|
if (result.getSdkHttpMetadata().getHttpStatusCode() == OK) { |
|
|
|
for (Reservation reservation : result.getReservations()) { |
|
|
|
for (Instance instance : reservation.getInstances()) { |
|
|
|
if (instance.getState().equals("terminated") |
|
|
|
|| !instance.getTags().contains(new Tag().withKey(TAG_CLOUD_UUID).withValue(cloud.getUuid()))) { |
|
|
|
log.debug("Skipping terminated node or node without cloud tag " + cloud.getUuid()); |
|
|
|
continue; |
|
|
|
} |
|
|
|
final String instanceId = instance.getInstanceId(); |
|
|
|
final String ip4 = instance.getPrivateIpAddress(); |
|
|
|
final String ip6 = instance.getPublicIpAddress(); |
|
|
@@ -92,21 +97,25 @@ public class AmazonEC2Driver extends ComputeServiceDriverBase { |
|
|
|
return nodes; |
|
|
|
} |
|
|
|
|
|
|
|
@Override public BubbleNode start(@NonNull BubbleNode node) throws Exception { |
|
|
|
final ComputeNodeSize size = config.getSize(node.getSize()); |
|
|
|
@Override public BubbleNode start(BubbleNode node) throws Exception { |
|
|
|
|
|
|
|
final ComputeNodeSize size = config.getSize(node.getSize()); |
|
|
|
final AmazonEC2 ec2Client = getEc2Client(); |
|
|
|
|
|
|
|
DescribeSubnetsRequest describeSubnetsRequest = new DescribeSubnetsRequest(); |
|
|
|
DescribeSubnetsRequest describeSubnetsRequest = new DescribeSubnetsRequest() |
|
|
|
.withFilters(new Filter().withName("state").withValues("available")); |
|
|
|
|
|
|
|
String subnetId = ec2Client.describeSubnets(describeSubnetsRequest).getSubnets().stream() |
|
|
|
.filter(s -> s.getAvailableIpAddressCount() != 0) |
|
|
|
.findAny().orElseThrow(() -> new NoSuchElementException("Subnet not found")).getSubnetId(); |
|
|
|
|
|
|
|
final String keyId = registerSshKey(node); |
|
|
|
|
|
|
|
RunInstancesRequest runInstancesRequest = new RunInstancesRequest().withImageId(config.getConfig("imageId")) |
|
|
|
.withInstanceType(size.getInternalName()) |
|
|
|
.withMinCount(MIN_COUNT) |
|
|
|
.withMaxCount(MAX_COUNT) |
|
|
|
.withKeyName(KEY_NAME_PREFIX+node.getUuid()) |
|
|
|
.withNetworkInterfaces(new InstanceNetworkInterfaceSpecification() |
|
|
|
.withAssociatePublicIpAddress(true) |
|
|
|
.withDeviceIndex(0) |
|
|
@@ -119,37 +128,46 @@ public class AmazonEC2Driver extends ComputeServiceDriverBase { |
|
|
|
return die("start: error running instance: " |
|
|
|
+ runInstancesResult.getSdkHttpMetadata().getAllHttpHeaders()); |
|
|
|
|
|
|
|
Instance instance = runInstancesResult.getReservation().getInstances().get(0); |
|
|
|
final String instanceId = instance.getInstanceId(); |
|
|
|
final String ip4 = instance.getPrivateIpAddress(); |
|
|
|
final String ip6 = instance.getPublicIpAddress(); |
|
|
|
final String keyId = registerSshKey(node); |
|
|
|
|
|
|
|
instance.setKeyName(keyId); |
|
|
|
node.setIp4(ip4).setIp6(ip6).setTag(TAG_INSTANCE_ID, instanceId).setTag(TAG_SSH_KEY_ID, keyId); |
|
|
|
final String instanceId = runInstancesResult.getReservation().getInstances().get(0).getInstanceId(); |
|
|
|
|
|
|
|
node.setState(BubbleNodeState.booting); |
|
|
|
node.setTag(TAG_INSTANCE_ID, instanceId).setTag(TAG_SSH_KEY_ID, keyId); |
|
|
|
nodeDAO.update(node); |
|
|
|
|
|
|
|
// Describe instances to check run instance result and get IP addresses |
|
|
|
DescribeInstancesResult result = ec2Client.describeInstances( |
|
|
|
new DescribeInstancesRequest().withInstanceIds(instanceId)); |
|
|
|
|
|
|
|
if (result.getSdkHttpMetadata().getHttpStatusCode() == OK) { |
|
|
|
for (Reservation reservation : result.getReservations()) { |
|
|
|
for (Instance i : reservation.getInstances()) { |
|
|
|
if (i.getInstanceId().equals(instanceId)) { |
|
|
|
final String ip4 = i.getPrivateIpAddress(); |
|
|
|
if (ip4 != null && ip4.length() > 0 && !ip4.equals("0.0.0.0")){ |
|
|
|
node.setIp4(ip4); |
|
|
|
nodeDAO.update(node); |
|
|
|
} |
|
|
|
final String ip6 = i.getPublicIpAddress(); |
|
|
|
if (ip6 != null && ip6.length() > 0) { |
|
|
|
node.setIp6(ip6); |
|
|
|
nodeDAO.update(node); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Setting up the tags for the instance |
|
|
|
CreateTagsRequest createTagsRequest = new CreateTagsRequest() |
|
|
|
.withResources(instance.getInstanceId()) |
|
|
|
.withResources(instanceId) |
|
|
|
.withTags(new Tag(TAG_NODE_UUID, node.getUuid()), |
|
|
|
new Tag(TAG_CLOUD_UUID, cloud.getUuid())); |
|
|
|
|
|
|
|
try { |
|
|
|
ec2Client.createTags(createTagsRequest); |
|
|
|
} catch (AmazonServiceException e) { |
|
|
|
log.warn("start: error creating tags for instance: " + instanceId + e.getErrorMessage() + e.getErrorCode()); |
|
|
|
} |
|
|
|
|
|
|
|
// Starting the Instance |
|
|
|
StartInstancesRequest startInstancesRequest = new StartInstancesRequest().withInstanceIds(instanceId); |
|
|
|
|
|
|
|
ec2Client.startInstances(startInstancesRequest); |
|
|
|
return node; |
|
|
|
} |
|
|
|
|
|
|
|
@Override public BubbleNode cleanupStart(@NonNull BubbleNode node) throws Exception { |
|
|
|
@Override public BubbleNode cleanupStart(BubbleNode node) throws Exception { |
|
|
|
deleteEC2KeyPair(node); |
|
|
|
return node; |
|
|
|
} |
|
|
@@ -176,14 +194,14 @@ public class AmazonEC2Driver extends ComputeServiceDriverBase { |
|
|
|
return node; |
|
|
|
} |
|
|
|
|
|
|
|
@Override public BubbleNode status(@NonNull BubbleNode node) throws Exception { |
|
|
|
@Override public BubbleNode status(BubbleNode node) throws Exception { |
|
|
|
final List<BubbleNode> found = listNodes(); |
|
|
|
if (found.isEmpty()) { |
|
|
|
return node.setState(BubbleNodeState.stopped); |
|
|
|
} else { |
|
|
|
boolean isFound = false; |
|
|
|
for (BubbleNode foundNode : found) { |
|
|
|
if (foundNode.getTag(TAG_INSTANCE_ID).equals(node.getTag(TAG_NODE_UUID))) { |
|
|
|
if (foundNode.getTag(TAG_INSTANCE_ID).equals(node.getTag(TAG_INSTANCE_ID))) { |
|
|
|
node.setState(foundNode.getState()); |
|
|
|
isFound = true; |
|
|
|
break; |
|
|
@@ -194,10 +212,10 @@ public class AmazonEC2Driver extends ComputeServiceDriverBase { |
|
|
|
return node; |
|
|
|
} |
|
|
|
|
|
|
|
private void deleteEC2KeyPair(@NonNull BubbleNode node) throws Exception { |
|
|
|
private void deleteEC2KeyPair(BubbleNode node) throws Exception { |
|
|
|
if (node.hasTag(TAG_SSH_KEY_ID)) { |
|
|
|
DeleteKeyPairRequest request = new DeleteKeyPairRequest() |
|
|
|
.withKeyName(node.getUuid()); |
|
|
|
.withKeyName(KEY_NAME_PREFIX + node.getUuid()); |
|
|
|
|
|
|
|
// destroy key, check response |
|
|
|
final AmazonEC2 ec2Client = getEc2Client(); |
|
|
@@ -214,10 +232,13 @@ public class AmazonEC2Driver extends ComputeServiceDriverBase { |
|
|
|
node.setSshKey(newRsaKeyPair()); |
|
|
|
|
|
|
|
final AmazonEC2 ec2Client = getEc2Client(); |
|
|
|
ImportKeyPairRequest importKeyPairRequest = new ImportKeyPairRequest(node.getUuid(), node.getSshKey().getSshPublicKey()); |
|
|
|
ImportKeyPairRequest importKeyPairRequest = new ImportKeyPairRequest( |
|
|
|
KEY_NAME_PREFIX + node.getUuid(), node.getSshKey().getSshPublicKey() |
|
|
|
); |
|
|
|
ImportKeyPairResult importKeyPairResult = ec2Client.importKeyPair(importKeyPairRequest); |
|
|
|
if (importKeyPairResult.getSdkHttpMetadata().getHttpStatusCode() != OK) { |
|
|
|
return die("registerSshKey: error creating keyPair: " + importKeyPairResult.getSdkHttpMetadata().getAllHttpHeaders()); |
|
|
|
return die("registerSshKey: error creating keyPair: " |
|
|
|
+ importKeyPairResult.getSdkHttpMetadata().getAllHttpHeaders()); |
|
|
|
} |
|
|
|
return importKeyPairResult.getKeyFingerprint(); |
|
|
|
} |
|
|
|