List<String> getSnapshotIdsFromImageId(AmazonEC2Async client, ImageCreateRequest request, Context context) { // LambdaLogger logger = context.getLogger(); String imageId = request.getImageId(); DescribeImagesResult result = client.describeImages(new DescribeImagesRequest().withImageIds(imageId)); List<String> snapshotIds = new ArrayList<String>(); for (Image image : result.getImages()) { for (BlockDeviceMapping block : image.getBlockDeviceMappings()) { snapshotIds.add(block.getEbs().getSnapshotId()); } } return snapshotIds; }
/** * Instance Type(like r3.large etc) supports a limited number of instance-store disks. All the * extra instance-store mappings that are more than those supported by the instance-type are * termed as excess. Excess mappings does not result in provisioning a disk. * <p> * Suppress the excess instance-store mappings in the image by setting NoDevice to 'true'. */ private void suppressExcessInstanceStoreDevices(List<BlockDeviceMapping> deviceMappings, InstanceType type) { List<BlockDeviceMapping> unsuppressedInstanceStoreMappings = getUnsuppressedInstanceStoreMappings(deviceMappings); int imageInstanceStoreCount = unsuppressedInstanceStoreMappings != null ? unsuppressedInstanceStoreMappings.size() : 0; int maxSupported = type.dataDiskMaxCount != null ? type.dataDiskMaxCount : 0; if (imageInstanceStoreCount > maxSupported) { for (int i = 0; i < imageInstanceStoreCount; i++) { if (i >= maxSupported) { unsuppressedInstanceStoreMappings.get(i).setNoDevice(""); } } } }
/** * Add the disk information to disk state so that the disk state reflects the volume * information */ private void addMandatoryProperties(DiskState diskState, BlockDeviceMapping deviceMapping, InstanceType instanceType) { if (diskState.customProperties == null) { diskState.customProperties = new HashMap<>(); } String deviceName = deviceMapping.getDeviceName(); diskState.customProperties.put(DEVICE_NAME, deviceName); EbsBlockDevice ebs = deviceMapping.getEbs(); if (ebs != null) { diskState.capacityMBytes = ebs.getVolumeSize() * 1024; diskState.customProperties.put(DEVICE_TYPE, AWSStorageType.EBS.getName()); } else { diskState.capacityMBytes = instanceType.dataDiskSizeInMB; diskState.customProperties.put(DEVICE_TYPE, AWSStorageType.INSTANCE_STORE.getName()); } }
private void customizeBootDiskProperties(DiskState bootDisk, String rootDeviceType, BlockDeviceMapping rootDeviceMapping, boolean hasHardConstraint, AWSInstanceContext aws) { if (rootDeviceType.equals(AWSStorageType.EBS.name().toLowerCase())) { String requestedType = bootDisk.customProperties.get(DEVICE_TYPE); EbsBlockDevice ebs = rootDeviceMapping.getEbs(); if (hasHardConstraint) { validateIfDeviceTypesAreMatching(rootDeviceType, requestedType); } bootDisk.capacityMBytes = ebs.getVolumeSize() * 1024; updateDeviceMapping(rootDeviceType, requestedType, rootDeviceMapping.getDeviceName(), ebs, bootDisk); bootDisk.customProperties.put(DEVICE_TYPE, AWSStorageType.EBS.getName()); bootDisk.customProperties.put(DEVICE_NAME, rootDeviceMapping.getDeviceName()); bootDisk.customProperties.put(VOLUME_TYPE, ebs.getVolumeType()); bootDisk.customProperties.put(DISK_IOPS, String.valueOf(ebs.getIops())); } else { if (aws.instanceTypeInfo.dataDiskSizeInMB != null) { this.logInfo( () -> "[AWSInstanceService] Instance-Store boot disk size is set to the " + "value supported by instance-type."); bootDisk.capacityMBytes = aws.instanceTypeInfo.dataDiskSizeInMB; bootDisk.customProperties.put(DEVICE_TYPE, AWSStorageType.INSTANCE_STORE.getName()); } } }
public static String provisionAWSEBSVMWithEC2Client(VerificationHost host, AmazonEC2Client client, String ami, String subnetId, String securityGroupId, BlockDeviceMapping blockDeviceMapping) { RunInstancesRequest runInstancesRequest = new RunInstancesRequest() .withSubnetId(subnetId) .withImageId(ami) .withInstanceType(instanceType) .withMinCount(1).withMaxCount(1) .withSecurityGroupIds(securityGroupId) .withBlockDeviceMappings(blockDeviceMapping); // handler invoked once the EC2 runInstancesAsync commands completes RunInstancesResult result = null; try { result = client.runInstances(runInstancesRequest); } catch (Exception e) { host.log(Level.SEVERE, "Error encountered in provisioning machine on AWS", Utils.toString(e)); } assertNotNull(result); assertNotNull(result.getReservation()); assertNotNull(result.getReservation().getInstances()); assertEquals(1, result.getReservation().getInstances().size()); return result.getReservation().getInstances().get(0).getInstanceId(); }
/** * Get EBS volumes attached to the specified virtual instance id. * * @return list of ebs volumes */ @VisibleForTesting List<Volume> getVolumes(String virtualInstanceId) { String ec2InstanceId = getOnlyElement( getEC2InstanceIdsByVirtualInstanceId( Collections.singletonList(virtualInstanceId) ).values() ); InstanceAttribute instanceAttribute = describeInstanceAttribute(ec2InstanceId, InstanceAttributeName.BlockDeviceMapping); List<InstanceBlockDeviceMapping> blockDeviceMappings = instanceAttribute.getBlockDeviceMappings(); List<String> volumeIds = Lists.newArrayList(); for (InstanceBlockDeviceMapping mapping : blockDeviceMappings) { volumeIds.add(mapping.getEbs().getVolumeId()); } DescribeVolumesResult volumeResults = client.describeVolumes( new DescribeVolumesRequest().withVolumeIds(volumeIds) ); return volumeResults.getVolumes(); }
private List<BlockDeviceMapping> getEbsBlockDeviceMapping(int count, String volumeType, int volumeSizeGib, boolean enableEncryption) { List<String> deviceNames = ebsAllocator.getEbsDeviceNames(count); List<BlockDeviceMapping> mappings = Lists.newArrayList(); for (String deviceName : deviceNames) { EbsBlockDevice ebs = new EbsBlockDevice() .withVolumeType(volumeType) .withVolumeSize(volumeSizeGib) .withEncrypted(enableEncryption) .withDeleteOnTermination(true); BlockDeviceMapping mapping = new BlockDeviceMapping() .withDeviceName(deviceName) .withEbs(ebs); mappings.add(mapping); } return mappings; }
public static List<BlockDeviceMapping> parse(String customDeviceMapping) { List<BlockDeviceMapping> deviceMappings = new ArrayList<BlockDeviceMapping>(); for (String mapping: customDeviceMapping.split(",")) { String[] mappingPair = mapping.split("="); String device = mappingPair[0]; String blockDevice = mappingPair[1]; BlockDeviceMapping deviceMapping = new BlockDeviceMapping().withDeviceName(device); if (blockDevice.equals("none")) { deviceMapping.setNoDevice("none"); } else if (blockDevice.startsWith("ephemeral")) { deviceMapping.setVirtualName(blockDevice); } else { deviceMapping.setEbs(parseEbs(blockDevice)); } deviceMappings.add(deviceMapping); } return deviceMappings; }
public void testParserWithTermination() throws Exception { List<BlockDeviceMapping> expected = new ArrayList<BlockDeviceMapping>(); expected.add( new BlockDeviceMapping(). withDeviceName("/dev/sdc"). withEbs( new EbsBlockDevice(). withSnapshotId("snap-7eb96d16"). withVolumeSize(80). withDeleteOnTermination(false) ) ); String customDeviceMappings = "/dev/sdc=snap-7eb96d16:80:false"; List<BlockDeviceMapping> actual = DeviceMappingParser.parse(customDeviceMappings); assertEquals(expected, actual); }
public void testParserWithIo() throws Exception { List<BlockDeviceMapping> expected = new ArrayList<BlockDeviceMapping>(); expected.add( new BlockDeviceMapping(). withDeviceName("/dev/sdc"). withEbs( new EbsBlockDevice(). withSnapshotId("snap-7eb96d16"). withVolumeSize(80). withDeleteOnTermination(false). withVolumeType("io1"). withIops(100) ) ); String customDeviceMappings = "/dev/sdc=snap-7eb96d16:80:false:io1:100"; List<BlockDeviceMapping> actual = DeviceMappingParser.parse(customDeviceMappings); assertEquals(expected, actual); }
public void testParserWithEncrypted() throws Exception { List<BlockDeviceMapping> expected = new ArrayList<BlockDeviceMapping>(); expected.add( new BlockDeviceMapping(). withDeviceName("/dev/sdd"). withEbs( new EbsBlockDevice(). withVolumeSize(120). withEncrypted(true) ) ); String customDeviceMappings = "/dev/sdd=:120::::encrypted"; List<BlockDeviceMapping> actual = DeviceMappingParser.parse(customDeviceMappings); assertEquals(expected, actual); }
public void testParserWithMultiple() throws Exception { List<BlockDeviceMapping> expected = new ArrayList<BlockDeviceMapping>(); expected.add( new BlockDeviceMapping(). withDeviceName("/dev/sdd"). withEbs( new EbsBlockDevice(). withVolumeSize(120). withEncrypted(true) ) ); expected.add( new BlockDeviceMapping(). withDeviceName("/dev/sdc"). withEbs( new EbsBlockDevice(). withVolumeSize(120) ) ); String customDeviceMappings = "/dev/sdd=:120::::encrypted,/dev/sdc=:120"; List<BlockDeviceMapping> actual = DeviceMappingParser.parse(customDeviceMappings); assertEquals(expected, actual); }
public void deleteImage(Image image) { String imageId = image.getImageId(); logger.info("delete image, imageId={}", imageId); ec2.deregisterImage(new DeregisterImageRequest(imageId)); // our image always uses EBS as first and only drive List<BlockDeviceMapping> mappings = image.getBlockDeviceMappings(); if (!mappings.isEmpty()) { EbsBlockDevice ebs = mappings.get(0).getEbs(); if (ebs != null) { String snapshotId = ebs.getSnapshotId(); logger.info("delete snapshot, snapshotId={}", snapshotId); ec2.deleteSnapshot(new DeleteSnapshotRequest(snapshotId)); } } }
public CompareResult<BlockDeviceMapping> compareBlockDeviceMappings(List<BlockDeviceMapping> oldBlockDeviceMappings, List<BlockDeviceMapping> newBlockDeviceMappings) { Validate.noNullElements(new Object[]{oldBlockDeviceMappings, newBlockDeviceMappings}); CompareResult<BlockDeviceMapping> result = new CompareResult<>(); Map<String, BlockDeviceMapping> oldBlockDeviceMappingMap = generateBlockDeviceMapping(oldBlockDeviceMappings); Map<String, BlockDeviceMapping> newBlockDeviceMappingMap = generateBlockDeviceMapping(newBlockDeviceMappings); for (String newKey : newBlockDeviceMappingMap.keySet()) { BlockDeviceMapping newBDM = newBlockDeviceMappingMap.get(newKey); BlockDeviceMapping oldBDM = oldBlockDeviceMappingMap.get(newKey); if (oldBDM != null) { if (!oldBDM.equals(newBDM)) { result.getUpdate().add(Pair.of(oldBDM, newBDM)); } } else { result.getAdd().add(newBDM); } oldBlockDeviceMappingMap.remove(newKey); } for (String oldKey : oldBlockDeviceMappingMap.keySet()) { BlockDeviceMapping oldBlockDeviceMapping = oldBlockDeviceMappingMap.get(oldKey); result.getDelete().add(oldBlockDeviceMapping); } return result; }
private void pargeImages(AmazonEC2 ec2, Image image) { String imageId = image.getImageId(); ec2.deregisterImage(new DeregisterImageRequest(imageId)); for (BlockDeviceMapping block : image.getBlockDeviceMappings()) { String snapshotId = block.getEbs().getSnapshotId(); ec2.deleteSnapshot(new DeleteSnapshotRequest().withSnapshotId(snapshotId)); } }
private void validateSupportForAdditionalInstanceStoreDisks(List<DiskState> disks, List<BlockDeviceMapping> blockDeviceMappings, InstanceType type, String rootDeviceType) { validateImageAndInstanceTypeCompatibility(type, rootDeviceType); int numInstanceStoreDisksInImage = countInstanceStoreDisksInImage(blockDeviceMappings); int totalInstanceStoreDisks = numInstanceStoreDisksInImage + disks.size(); AssertUtil.assertTrue(totalInstanceStoreDisks <= type.dataDiskMaxCount, String.format("%s does not support %s additional instance-store disks", type, disks.size())); }
private List<String> getUsedDeviceNames(List<BlockDeviceMapping> blockDeviceMappings) { List<String> usedDeviceNames = new ArrayList<>(); for (BlockDeviceMapping blockDeviceMapping : blockDeviceMappings) { usedDeviceNames.add(blockDeviceMapping.getDeviceName()); } return usedDeviceNames; }
private List<String> getUsedVirtualNames(List<BlockDeviceMapping> blockDeviceMappings) { List<String> usedVirtualNames = new ArrayList<>(); for (BlockDeviceMapping blockDeviceMapping : blockDeviceMappings) { if (blockDeviceMapping.getEbs() == null) { usedVirtualNames.add(blockDeviceMapping.getVirtualName()); } } return usedVirtualNames; }
/** * Count the number of instance-store disks configured in the image that are marked for * provisioning. */ private int countInstanceStoreDisksInImage(List<BlockDeviceMapping> blockDeviceMappings) { List<BlockDeviceMapping> unsuppressedInstanceStoreMappings = getUnsuppressedInstanceStoreMappings(blockDeviceMappings); return unsuppressedInstanceStoreMappings != null ? unsuppressedInstanceStoreMappings.size() : 0; }
/** * Get the list of instance store mappings available in the image and are mapped for * provisioning. If noDevice != null then that device is suppressed and cannot provision a * disk. */ private List<BlockDeviceMapping> getUnsuppressedInstanceStoreMappings( List<BlockDeviceMapping> blockDeviceMappings) { return blockDeviceMappings.stream() .filter(blockDeviceMapping -> blockDeviceMapping.getDeviceName() != null && blockDeviceMapping.getEbs() == null && blockDeviceMapping.getNoDevice() == null ).collect(Collectors.toList()); }
/** * Generates a list of block device mappings for all ephemeral drives for * the given instance type. * * @param instanceType EC2 instance type * @return list of block device mappings * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html">Block Device Mapping</a> */ @Nonnull public List<BlockDeviceMapping> apply(String instanceType) { checkNotNull(instanceType, "instanceType is null"); Optional<Integer> optCount = getCount(instanceType); if (!optCount.isPresent()) { LOG.error("Unsupported instance type {}, add its ephemeral instance " + "volume count as a custom mapping; assuming zero", instanceType); return Collections.emptyList(); } int count = optCount.get(); if (count == 0) { return Collections.emptyList(); } List<String> deviceNames = getLinuxDeviceNames( ephemeralDeviceMappingsConfigProperties.getDeviceNamePrefix(), ephemeralDeviceMappingsConfigProperties.getRangeStart(), count); List<BlockDeviceMapping> result = Lists.newArrayListWithExpectedSize(count); int index = 0; for (String device : deviceNames) { result.add(new BlockDeviceMapping() .withDeviceName(device) .withVirtualName("ephemeral" + index)); index += 1; } return result; }
public void testParserWithAmi() throws Exception { List<BlockDeviceMapping> expected = new ArrayList<BlockDeviceMapping>(); expected.add( new BlockDeviceMapping(). withDeviceName("/dev/sdb"). withEbs( new EbsBlockDevice(). withSnapshotId("snap-7eb96d16") ) ); String customDeviceMappings = "/dev/sdb=snap-7eb96d16"; List<BlockDeviceMapping> actual = DeviceMappingParser.parse(customDeviceMappings); assertEquals(expected, actual); }
public void testParserWithSize() throws Exception { List<BlockDeviceMapping> expected = new ArrayList<BlockDeviceMapping>(); expected.add( new BlockDeviceMapping(). withDeviceName("/dev/sdd"). withEbs( new EbsBlockDevice(). withVolumeSize(120) ) ); String customDeviceMappings = "/dev/sdd=:120"; List<BlockDeviceMapping> actual = DeviceMappingParser.parse(customDeviceMappings); assertEquals(expected, actual); }
protected List<BlockDeviceMapping> createBlockDeviceMappings(AwsProcessClient awsProcessClient, ImageAws imageAws, AwsInstance awsInstance) { // イメージの取得 com.amazonaws.services.ec2.model.Image image = awsCommonProcess.describeImage(awsProcessClient, imageAws.getImageId()); if (image == null) { return null; } // EBSイメージでなければBlockDeviceMappingsを設定しない if (!image.getRootDeviceType().equals(DeviceType.Ebs.toString())) { return null; } List<BlockDeviceMapping> mappings = new ArrayList<BlockDeviceMapping>(); // イメージのBlockDeviceMappingの設定 List<BlockDeviceMapping> imageMappings = createImageBlockDeviceMappings(awsProcessClient, imageAws, awsInstance, image); if (imageMappings != null) { mappings.addAll(imageMappings); } // インスタンスストアのBlockDeviceMappingの設定 List<BlockDeviceMapping> instanceStoreMappings = createInstanceStoreBlockDeviceMappings(awsProcessClient, imageAws, awsInstance, image); if (instanceStoreMappings != null) { mappings.addAll(instanceStoreMappings); } // 追加のBlockDeviceMappingの設定 List<BlockDeviceMapping> additionalMappings = createAdditionalBlockDeviceMappings(awsProcessClient, imageAws, awsInstance, image); if (additionalMappings != null) { mappings.addAll(additionalMappings); } return mappings; }
private Instance runVirtualMachineLaunch(Formation formation) { Properties generalProperties = getMetaInformationProperties(formation); Machine machine = formation.getMachine(); CloudInitScript initScript = getParallelCloudInitScript(machine, generalProperties); initScript.save(); this.console.newLine(); // if ( true ) // return null; BlockDeviceMapping volumn = this.ec2Client.getBlockDeviceMapping("/dev/sda1", 20); IamInstanceProfileSpecification profil = this.ec2Client.getIamInstanceProfileSpecification(getUserProperty(REPO_PROFILE)); RunInstancesRequest request = new RunInstancesRequest().withInstanceType(machine.getInstanceType()) .withImageId(machine.getImageId()).withIamInstanceProfile(profil).withMinCount(1) .withMaxCount(1).withBlockDeviceMappings(volumn) .withUserData(initScript.renderAsBase64()) .withSecurityGroupIds(machine.getSecurityGroup()) .withKeyName(getUserProperty(EC2_INSTANCE_KEY)); String instanceId = runInstance(request); this.console.writeNl("Starting..."); waitForInstanceState(instanceId, "running"); assigneIpIfAvailable(instanceId, machine); assigneName(instanceId, machine); return this.ec2Client.getEC2InstanceById(instanceId); }
public Map<String, BlockDeviceMapping> generateBlockDeviceMapping(List<BlockDeviceMapping> blockDeviceMappings) { Map<String, BlockDeviceMapping> result = new HashMap<>(); for (BlockDeviceMapping blockDeviceMapping : blockDeviceMappings) { result.put(blockDeviceMapping.getDeviceName(), blockDeviceMapping); } return result; }
/** * creates the device mapping for each of the data disk and adds it to the runInstancesRequest. */ private void addEbsDeviceMappings(List<DiskState> ebsDiskStates, List<BlockDeviceMapping> blockDeviceMappings, List<String> usedDeviceNames) { }
/** * Creates device mappings for the instance-store disks. */ private List<BlockDeviceMapping> createInstanceStoreMappings(List<DiskState> instanceStoreDisks, List<String> usedDeviceNames, List<String> usedVirtualNames, String instanceType, Integer capacityMBytes, String platform, String virtualizationType) { List<BlockDeviceMapping> deviceMappings = new ArrayList<>(); if (!instanceStoreDisks.isEmpty()) { this.logInfo( () -> String.format("[AWSInstanceService] Ignores the size and type of the " + "additional disk. Instance-store type of additional disks are " + "provisioned with the capacity supported by %s", instanceType)); List<String> availableDeviceNames = AWSBlockDeviceNameMapper.getAvailableNames(AWSSupportedOS.get(platform), AWSSupportedVirtualizationTypes.get(virtualizationType), AWSStorageType.INSTANCE_STORE, instanceType, usedDeviceNames); List<String> availableVirtualNames = getAvailableVirtualNames(usedVirtualNames); if (availableDeviceNames.size() >= instanceStoreDisks.size() && availableVirtualNames.size() >= instanceStoreDisks.size()) { for (DiskState diskState : instanceStoreDisks) { BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping(); String deviceName = availableDeviceNames.get(0); blockDeviceMapping.setDeviceName(deviceName); availableDeviceNames.remove(0); usedDeviceNames.add(deviceName); String virtualName = availableVirtualNames.get(0); blockDeviceMapping.setVirtualName(virtualName); availableVirtualNames.remove(0); deviceMappings.add(blockDeviceMapping); if (diskState.customProperties == null) { diskState.customProperties = new HashMap<>(); } diskState.customProperties.put(DEVICE_NAME, deviceName); diskState.customProperties .put(DEVICE_TYPE, AWSStorageType.INSTANCE_STORE.getName()); diskState.capacityMBytes = capacityMBytes; } } else { String message = "Additional instance-store disks cannot be attached. " + "Not sufficient device names are available."; this.logWarning(() -> "[AWSInstanceService] " + message); throw new IllegalArgumentException(message); } } return deviceMappings; }
@Override protected DeferredResult<LocalStateHolder> buildLocalResourceState( Image remoteImage, ImageState existingImageState) { LocalStateHolder holder = new LocalStateHolder(); holder.localState = new ImageState(); if (existingImageState == null) { // Create flow if (this.request.requestType == ImageEnumerateRequestType.PUBLIC) { holder.localState.endpointType = this.endpointState.endpointType; } } else { // Update flow: do nothing } // Both flows - populate from remote Image holder.localState.name = remoteImage.getName(); holder.localState.description = remoteImage.getDescription(); holder.localState.osFamily = remoteImage.getPlatform(); holder.localState.diskConfigs = new ArrayList<>(); if (DeviceType.Ebs == DeviceType.fromValue(remoteImage.getRootDeviceType())) { for (BlockDeviceMapping blockDeviceMapping : remoteImage.getBlockDeviceMappings()) { // blockDeviceMapping can be with noDevice EbsBlockDevice ebs = blockDeviceMapping.getEbs(); if (ebs != null) { DiskConfiguration diskConfig = new DiskConfiguration(); diskConfig.id = blockDeviceMapping.getDeviceName(); diskConfig.encrypted = ebs.getEncrypted(); diskConfig.persistent = true; if (ebs.getVolumeSize() != null) { diskConfig.capacityMBytes = ebs.getVolumeSize() * 1024; } diskConfig.properties = Collections.singletonMap( VOLUME_TYPE, ebs.getVolumeType()); holder.localState.diskConfigs.add(diskConfig); } } } for (Tag remoteImageTag : remoteImage.getTags()) { holder.remoteTags.put(remoteImageTag.getKey(), remoteImageTag.getValue()); } return DeferredResult.completed(holder); }
/** * Builds a {@code RunInstancesRequest} starting from a template and a virtual instance ID. * Instances will be tagged as they're created. * * @param template the instance template * @param virtualInstanceId the virtual instance IDs * @param userDefinedTags user defined tags to attach to the instance */ @SuppressWarnings("ConstantConditions") private RunInstancesRequest newRunInstancesRequest(EC2InstanceTemplate template, String virtualInstanceId, List<Tag> userDefinedTags) { String image = template.getImage(); String type = template.getType(); InstanceNetworkInterfaceSpecification network = getInstanceNetworkInterfaceSpecification(template); List<BlockDeviceMapping> deviceMappings = getBlockDeviceMappings(template); LOG.info(">> Instance request type: {}, image: {}", type, image); List<Tag> tags = ec2TagHelper.getInstanceTags(template, virtualInstanceId, userDefinedTags); List<TagSpecification> tagSpecifications = Lists.newArrayList( new TagSpecification().withTags(tags).withResourceType(ResourceType.Instance), new TagSpecification().withTags(tags).withResourceType(ResourceType.Volume)); RunInstancesRequest request = new RunInstancesRequest() .withImageId(image) .withInstanceType(type) .withMaxCount(1) .withMinCount(1) .withClientToken(UUID.randomUUID().toString()) .withNetworkInterfaces(network) .withTagSpecifications(tagSpecifications) .withBlockDeviceMappings(deviceMappings) .withEbsOptimized(template.isEbsOptimized()); if (template.getIamProfileName().isPresent()) { request.withIamInstanceProfile(new IamInstanceProfileSpecification() .withName(template.getIamProfileName().get())); } if (template.getKeyName().isPresent()) { request.withKeyName(template.getKeyName().get()); } Placement placement = null; if (template.getAvailabilityZone().isPresent()) { placement = new Placement().withAvailabilityZone(template.getAvailabilityZone().get()); } if (template.getPlacementGroup().isPresent()) { placement = (placement == null) ? new Placement().withGroupName(template.getPlacementGroup().get()) : placement.withGroupName(template.getPlacementGroup().get()); } placement = (placement == null) ? new Placement().withTenancy(template.getTenancy()) : placement.withTenancy(template.getTenancy()); request.withPlacement(placement); Optional<String> userData = template.getUserData(); if (userData.isPresent()) { request.withUserData(userData.get()); } return request; }
/** * Creates block device mappings based on the specified instance template. * * @param template the instance template * @return the block device mappings */ private List<BlockDeviceMapping> getBlockDeviceMappings(EC2InstanceTemplate template) { // Query the AMI about the root device name & mapping information DescribeImagesResult result = client.describeImages( new DescribeImagesRequest().withImageIds(template.getImage())); if (result.getImages().isEmpty()) { throw new IllegalArgumentException("The description for image " + template.getImage() + " is empty"); } Image templateImage = result.getImages().get(0); String rootDeviceType = templateImage.getRootDeviceType(); if (!DEVICE_TYPE_EBS.equals(rootDeviceType)) { throw new IllegalArgumentException("The root device for image " + template.getImage() + " must be \"" + DEVICE_TYPE_EBS + "\", found: " + rootDeviceType); } List<BlockDeviceMapping> originalMappings = templateImage.getBlockDeviceMappings(); LOG.info(">> Original image block device mappings: {}", originalMappings); if (originalMappings.isEmpty()) { throw new IllegalArgumentException("The image " + template.getImage() + " has no block device mappings"); } BlockDeviceMapping rootDevice = selectRootDevice(originalMappings, templateImage.getRootDeviceName()); if (rootDevice == null) { throw new IllegalArgumentException("Could not determine root device for image " + template.getImage() + " based on root device name " + templateImage.getRootDeviceName()); } // The encrypted property was added to the block device mapping in version 1.8 of the SDK. // It is a Boolean, but defaults to false instead of being unset, so we set it to null here. rootDevice.getEbs().setEncrypted(null); rootDevice.getEbs().setVolumeSize(template.getRootVolumeSizeGB()); rootDevice.getEbs().setVolumeType(template.getRootVolumeType()); rootDevice.getEbs().setDeleteOnTermination(true); List<BlockDeviceMapping> deviceMappings = Lists.newArrayList(rootDevice); int ebsVolumeCount = template.getEbsVolumeCount(); EBSAllocationStrategy ebsAllocationStrategy = EBSAllocationStrategy.get(template); switch (ebsAllocationStrategy) { case NO_EBS_VOLUMES: // The volumes within an instance should be homogeneous. So we only add // instance store volumes when additional EBS volumes aren't mounted. deviceMappings.addAll(ephemeralDeviceMappings.apply(template.getType())); break; case AS_INSTANCE_REQUEST: LOG.info("EBS volumes will be allocated as part of instance launch request"); List<BlockDeviceMapping> ebsDeviceMappings = getEbsBlockDeviceMapping(ebsVolumeCount, template.getEbsVolumeType(), template.getEbsVolumeSizeGiB(), template.isEnableEbsEncryption()); deviceMappings.addAll(ebsDeviceMappings); break; case AS_SEPARATE_REQUESTS: LOG.info("EBS volumes will be separately allocated after instance launch request"); break; default: throw new IllegalStateException("Invalid EBS allocation strategy " + ebsAllocationStrategy); } LOG.info(">> Block device mappings: {}", deviceMappings); return deviceMappings; }
/** * Selects the root device from a list of block device mappings based on the * root device name for the mappings' image. * * @param mappings list of block device mappings * @param rootDeviceName image root device name * @return root device mapping, or null if it could not be determined */ @VisibleForTesting static BlockDeviceMapping selectRootDevice(List<BlockDeviceMapping> mappings, String rootDeviceName) { /* * Heuristic to find the root device: * - The best match is the EBS device that matches the root device name for the image, but * this may not happen (/dev/sda1 vs. /dev/sda). See: * http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html * - If there isn't a best match, then a device whose name is a prefix for the image's root * device name is selected. * - If all else fails, it's the first EBS volume in the list. */ BlockDeviceMapping bestMatch = null; BlockDeviceMapping firstEbs = null; for (BlockDeviceMapping mapping : mappings) { if (mapping.getEbs() == null) { continue; } if (firstEbs == null) { firstEbs = mapping; } if (mapping.getDeviceName() == null) { continue; } if (rootDeviceName.equals(mapping.getDeviceName())) { return mapping; } if (rootDeviceName.startsWith(mapping.getDeviceName())) { bestMatch = mapping; } } if (bestMatch != null) { return bestMatch; } else if (firstEbs != null) { return firstEbs; } else { return null; } }
/** * Builds a {@code RequestSpotInstancesRequest}. * * @return the {@code RequestSpotInstancesRequest} */ @VisibleForTesting protected RequestSpotInstancesRequest newRequestSpotInstanceRequest(String virtualInstanceId) { String image = template.getImage(); String type = template.getType(); InstanceNetworkInterfaceSpecification network = getInstanceNetworkInterfaceSpecification(template); List<BlockDeviceMapping> deviceMappings = getBlockDeviceMappings(template); LaunchSpecification launchSpecification = new LaunchSpecification() .withImageId(image) .withInstanceType(type) .withNetworkInterfaces(network) .withBlockDeviceMappings(deviceMappings) .withEbsOptimized(template.isEbsOptimized()); if (template.getIamProfileName().isPresent()) { launchSpecification.withIamInstanceProfile(new IamInstanceProfileSpecification() .withName(template.getIamProfileName().get())); } if (template.getKeyName().isPresent()) { launchSpecification.withKeyName(template.getKeyName().get()); } SpotPlacement placement = null; if (template.getAvailabilityZone().isPresent()) { placement = new SpotPlacement().withAvailabilityZone(template.getAvailabilityZone().get()); } if (template.getPlacementGroup().isPresent()) { placement = (placement == null) ? new SpotPlacement().withGroupName(template.getPlacementGroup().get()) : placement.withGroupName(template.getPlacementGroup().get()); } launchSpecification.withPlacement(placement); Optional<String> userData = template.getUserData(); if (userData.isPresent()) { launchSpecification.withUserData(userData.get()); } LOG.info(">> Spot instance request type: {}, image: {}", type, image); RequestSpotInstancesRequest request = new RequestSpotInstancesRequest() .withSpotPrice(template.getSpotBidUSDPerHour().get().toString()) .withLaunchSpecification(launchSpecification) .withInstanceCount(1) .withClientToken(determineClientToken(virtualInstanceId, requestExpirationTime.getTime())) .withValidUntil(requestExpirationTime); Optional<Integer> blockDurationMinutes = template.getBlockDurationMinutes(); if (blockDurationMinutes.isPresent()) { request.withBlockDurationMinutes(blockDurationMinutes.get()); } return request; }
public void spotRequest() { if (instances <= instancesSet.size()) { logger.info("No more instances will be launched because there are already enough."); return; } com.amazonaws.services.ec2.AmazonEC2 client = AmazonEC2.connect(); RequestSpotInstancesRequest requestRequest = new RequestSpotInstancesRequest(); requestRequest.setSpotPrice(Double.valueOf(maxPrice).toString()); // requestRequest.setInstanceCount(instances); requestRequest.setInstanceCount(instances - instancesSet.size()); LaunchSpecification launchSpecification = new LaunchSpecification(); launchSpecification.setImageId(ami); launchSpecification.setInstanceType(size); if (userData != null) launchSpecification.setUserData(Base64.encodeAsString(userData .getBytes())); BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping(); blockDeviceMapping.setDeviceName("/dev/sda1"); EbsBlockDevice ebs = new EbsBlockDevice(); ebs.setDeleteOnTermination(Boolean.TRUE); ebs.setVolumeSize(diskSize); blockDeviceMapping.setEbs(ebs); ArrayList<BlockDeviceMapping> blockList = new ArrayList<BlockDeviceMapping>(); blockList.add(blockDeviceMapping); launchSpecification.setBlockDeviceMappings(blockList); ArrayList<String> securityGroups = new ArrayList<String>(); securityGroups.add(Configuration.SECURITY_GROUP_NAME); launchSpecification.setSecurityGroups(securityGroups); launchSpecification.setKeyName(keyName); requestRequest.setLaunchSpecification(launchSpecification); RequestSpotInstancesResult requestResult = client .requestSpotInstances(requestRequest); List<SpotInstanceRequest> reqs = requestResult .getSpotInstanceRequests(); for (SpotInstanceRequest req : reqs) instancesSet.add(new Instance(this, req.getInstanceId(), req .getSpotInstanceRequestId())); }
public void onDemandRequest() { if (instances <= instancesSet.size()) { logger.info("No more instances will be launched because there are already enough."); return; } com.amazonaws.services.ec2.AmazonEC2 client = AmazonEC2.connect(); RunInstancesRequest request = new RunInstancesRequest(); // request.setMinCount(instances); // request.setMaxCount(instances); request.setMinCount(instances - instancesSet.size()); request.setMaxCount(instances - instancesSet.size()); request.setImageId(ami); request.setInstanceType(size); if (userData != null) request.setUserData(Base64.encodeAsString(userData .getBytes())); BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping(); blockDeviceMapping.setDeviceName("/dev/sda1"); EbsBlockDevice ebs = new EbsBlockDevice(); ebs.setDeleteOnTermination(Boolean.TRUE); ebs.setVolumeSize(diskSize); blockDeviceMapping.setEbs(ebs); ArrayList<BlockDeviceMapping> blockList = new ArrayList<BlockDeviceMapping>(); blockList.add(blockDeviceMapping); request.setBlockDeviceMappings(blockList); ArrayList<String> securityGroups = new ArrayList<String>(); securityGroups.add(Configuration.SECURITY_GROUP_NAME); request.setSecurityGroups(securityGroups); request.setKeyName(keyName); RunInstancesResult requestResult = client.runInstances(request); Reservation reservation = requestResult.getReservation(); reservation.getInstances(); for (com.amazonaws.services.ec2.model.Instance i : reservation.getInstances()) instancesSet.add(new Instance(this, i.getInstanceId(), null)); }
private void createInstance(Context context, int count, String subnetId) throws Exception { String sgId = resource.securityGroup.remoteSecurityGroup.getGroupId(); RunInstancesRequest request = new RunInstancesRequest() .withKeyName(resource.keyPair.remoteKeyPair.getKeyName()) .withInstanceType(resource.instanceType) .withImageId(resource.ami.imageId()) .withSubnetId(subnetId) .withSecurityGroupIds(sgId) .withMinCount(count) .withMaxCount(count) .withUserData(Base64.encodeBase64String(Strings.bytes(userData(context.env)))); if (EBS.enableEBSOptimized(resource.instanceType)) { request.withEbsOptimized(true); } if (resource.instanceProfile != null) request.withIamInstanceProfile(new IamInstanceProfileSpecification() .withName(resource.instanceProfile.remoteInstanceProfile.getInstanceProfileName())); if (resource.ebs.rootVolumeSize != null) { request.getBlockDeviceMappings().add(new BlockDeviceMapping() .withDeviceName("/dev/sda1") .withEbs(new EbsBlockDevice().withVolumeSize(resource.ebs.rootVolumeSize).withVolumeType(resource.ebs.type))); } List<com.amazonaws.services.ec2.model.Instance> remoteInstances = AWS.ec2.runInstances(request, tags(context.env)); resource.remoteInstances.addAll(remoteInstances); for (com.amazonaws.services.ec2.model.Instance remoteInstance : remoteInstances) { String key = String.format("instance/%s/%s", resource.id, remoteInstance.getInstanceId()); StringBuilder builder = new StringBuilder(); builder.append("privateIP=").append(remoteInstance.getPrivateIpAddress()); if (resource.subnet == null || resource.subnet.type == SubnetType.PUBLIC) { builder.append(", publicDNS=").append(remoteInstance.getPublicDnsName()); } context.output(key, builder.toString()); } if (resource.elb != null) { List<String> instanceIds = remoteInstances.stream().map(com.amazonaws.services.ec2.model.Instance::getInstanceId).collect(Collectors.toList()); AWS.elb.attachInstances(resource.elb.remoteELB.getLoadBalancerName(), instanceIds, waitUntilInService); } }
protected List<BlockDeviceMapping> createAdditionalBlockDeviceMappings(AwsProcessClient awsProcessClient, ImageAws imageAws, AwsInstance awsInstance, com.amazonaws.services.ec2.model.Image image) { return null; }
public BlockDeviceMapping getBlockDeviceMapping(String deviceName, int sizeInGb) { return new BlockDeviceMapping().withDeviceName(deviceName).withEbs( new EbsBlockDevice().withVolumeSize(sizeInGb)); }
@Override public List<BlockDeviceMapping> getBlockDeviceMappings() { return (List<BlockDeviceMapping>) resource.getAttribute("BlockDeviceMappings"); }
public List<Instance> launchEc2Instances(AmazonEC2Client ec2Client, Properties props) throws Exception { Integer totalExpectedWorkers = Integer.valueOf(props.getProperty("master.workers.total")); // disk size Collection<BlockDeviceMapping> blockDevices = new ArrayList<BlockDeviceMapping>(); blockDevices.add( new BlockDeviceMapping() .withDeviceName(props.getProperty("master.workers.ec2.disk.deviceName")) .withEbs(new EbsBlockDevice() .withVolumeType(VolumeType.valueOf(props.getProperty("master.workers.ec2.disk.volumeType"))) .withDeleteOnTermination(true) .withVolumeSize(Integer.valueOf(props.getProperty("master.workers.ec2.disk.size.gigabytes"))))); // create our run request for the total workers we expect RunInstancesRequest runInstancesRequest = new RunInstancesRequest(); runInstancesRequest.withImageId(props.getProperty("master.workers.ec2.ami.id")) .withInstanceType(props.getProperty("master.workers.ec2.instanceType")) .withMinCount(totalExpectedWorkers) .withMaxCount(totalExpectedWorkers) .withBlockDeviceMappings(blockDevices) .withKeyName(props.getProperty("master.workers.ec2.keyName")) .withSecurityGroupIds(props.getProperty("master.workers.ec2.securityGroupId")) .withInstanceInitiatedShutdownBehavior(ShutdownBehavior.valueOf(props.getProperty("master.workers.ec2.shutdownBehavior"))) .withSubnetId(props.getProperty("master.workers.ec2.subnetId")) .withUserData(Base64.encodeAsString(readFile(props.getProperty("master.workers.ec2.userDataFile")).getBytes())); // launch logger.debug("Launching " + totalExpectedWorkers + " EC2 instances, " + "it may take few minutes for workers to come up...: \n" + "\tamiId:" + runInstancesRequest.getImageId() +"\n"+ "\tsecGrpId:" + runInstancesRequest.getSecurityGroupIds().get(0) +"\n"+ "\tsubnetId:" + runInstancesRequest.getSubnetId() +"\n"+ "\tinstanceType:" + runInstancesRequest.getInstanceType() +"\n"+ "\tshutdownBehavior:" + runInstancesRequest.getInstanceInitiatedShutdownBehavior() +"\n"+ "\tkeyName:" + runInstancesRequest.getKeyName() ); // as the instances come up, assuming the "userData" above launches the worker we will be good // they will auto register w/ us the master RunInstancesResult result = ec2Client.runInstances(runInstancesRequest); Reservation reservation = result.getReservation(); return reservation.getInstances(); }