2013-07-30 21:28:21 -04:00
|
|
|
package chroot
|
|
|
|
|
|
|
|
import (
|
2018-01-22 18:32:33 -05:00
|
|
|
"context"
|
2013-07-30 21:28:21 -04:00
|
|
|
"fmt"
|
2014-06-04 17:58:11 -04:00
|
|
|
|
2015-06-03 17:13:52 -04:00
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
|
|
"github.com/aws/aws-sdk-go/service/ec2"
|
2017-04-04 16:39:01 -04:00
|
|
|
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
2018-01-19 19:18:44 -05:00
|
|
|
"github.com/hashicorp/packer/helper/multistep"
|
2017-04-04 16:39:01 -04:00
|
|
|
"github.com/hashicorp/packer/packer"
|
2013-07-30 21:28:21 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// StepRegisterAMI creates the AMI.
|
2015-06-23 11:35:59 -04:00
|
|
|
type StepRegisterAMI struct {
|
2017-08-28 12:18:23 -04:00
|
|
|
RootVolumeSize int64
|
|
|
|
EnableAMIENASupport bool
|
|
|
|
EnableAMISriovNetSupport bool
|
2015-06-23 11:35:59 -04:00
|
|
|
}
|
2013-07-30 21:28:21 -04:00
|
|
|
|
2018-01-22 18:31:41 -05:00
|
|
|
func (s *StepRegisterAMI) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
2013-08-31 15:58:55 -04:00
|
|
|
config := state.Get("config").(*Config)
|
|
|
|
ec2conn := state.Get("ec2").(*ec2.EC2)
|
|
|
|
snapshotId := state.Get("snapshot_id").(string)
|
|
|
|
ui := state.Get("ui").(packer.Ui)
|
2013-07-30 21:28:21 -04:00
|
|
|
|
|
|
|
ui.Say("Registering the AMI...")
|
2016-08-10 20:24:30 -04:00
|
|
|
|
|
|
|
var (
|
|
|
|
registerOpts *ec2.RegisterImageInput
|
2016-09-16 21:35:36 -04:00
|
|
|
mappings []*ec2.BlockDeviceMapping
|
2016-08-10 20:24:30 -04:00
|
|
|
image *ec2.Image
|
|
|
|
rootDeviceName string
|
|
|
|
)
|
|
|
|
|
|
|
|
if config.FromScratch {
|
2016-09-16 21:35:36 -04:00
|
|
|
mappings = config.AMIBlockDevices.BuildAMIDevices()
|
2016-08-10 20:24:30 -04:00
|
|
|
rootDeviceName = config.RootDeviceName
|
|
|
|
} else {
|
|
|
|
image = state.Get("source_image").(*ec2.Image)
|
2016-09-16 21:35:36 -04:00
|
|
|
mappings = image.BlockDeviceMappings
|
2016-08-10 20:24:30 -04:00
|
|
|
rootDeviceName = *image.RootDeviceName
|
|
|
|
}
|
2016-09-16 21:35:36 -04:00
|
|
|
|
|
|
|
newMappings := make([]*ec2.BlockDeviceMapping, len(mappings))
|
|
|
|
for i, device := range mappings {
|
2013-07-30 21:28:21 -04:00
|
|
|
newDevice := device
|
2016-08-10 20:24:30 -04:00
|
|
|
if *newDevice.DeviceName == rootDeviceName {
|
2015-08-17 20:44:01 -04:00
|
|
|
if newDevice.Ebs != nil {
|
|
|
|
newDevice.Ebs.SnapshotId = aws.String(snapshotId)
|
2015-04-15 14:49:29 -04:00
|
|
|
} else {
|
2015-08-17 20:44:01 -04:00
|
|
|
newDevice.Ebs = &ec2.EbsBlockDevice{SnapshotId: aws.String(snapshotId)}
|
2015-04-15 14:49:29 -04:00
|
|
|
}
|
2015-06-23 11:35:59 -04:00
|
|
|
|
2016-08-10 20:24:30 -04:00
|
|
|
if config.FromScratch || s.RootVolumeSize > *newDevice.Ebs.VolumeSize {
|
2015-08-17 20:44:01 -04:00
|
|
|
newDevice.Ebs.VolumeSize = aws.Int64(s.RootVolumeSize)
|
2015-06-23 11:35:59 -04:00
|
|
|
}
|
2013-07-30 21:28:21 -04:00
|
|
|
}
|
|
|
|
|
2015-06-22 18:08:41 -04:00
|
|
|
// assume working from a snapshot, so we unset the Encrypted field if set,
|
|
|
|
// otherwise AWS API will return InvalidParameter
|
2015-08-17 20:44:01 -04:00
|
|
|
if newDevice.Ebs != nil && newDevice.Ebs.Encrypted != nil {
|
|
|
|
newDevice.Ebs.Encrypted = nil
|
2015-06-22 18:08:41 -04:00
|
|
|
}
|
|
|
|
|
2016-09-16 21:35:36 -04:00
|
|
|
newMappings[i] = newDevice
|
2013-07-30 21:28:21 -04:00
|
|
|
}
|
|
|
|
|
2016-08-10 20:24:30 -04:00
|
|
|
if config.FromScratch {
|
|
|
|
registerOpts = &ec2.RegisterImageInput{
|
|
|
|
Name: &config.AMIName,
|
|
|
|
Architecture: aws.String(ec2.ArchitectureValuesX8664),
|
|
|
|
RootDeviceName: aws.String(rootDeviceName),
|
|
|
|
VirtualizationType: aws.String(config.AMIVirtType),
|
2016-09-16 21:35:36 -04:00
|
|
|
BlockDeviceMappings: newMappings,
|
2016-08-10 20:24:30 -04:00
|
|
|
}
|
|
|
|
} else {
|
2016-09-16 21:35:36 -04:00
|
|
|
registerOpts = buildRegisterOpts(config, image, newMappings)
|
2016-08-10 20:24:30 -04:00
|
|
|
}
|
2013-07-30 21:28:21 -04:00
|
|
|
|
2017-08-28 12:18:23 -04:00
|
|
|
if s.EnableAMISriovNetSupport {
|
Always set both SRIOV and ENA when Enhanced Networking is enabled
Set SriovNetSupport to "simple". As of February 2017, this applies to C3, C4,
D2, I2, R3, and M4 (excluding m4.16xlarge).
Set EnaSupport to true. As of February 2017, this applies to C5, I3, P2, R4,
X1, and m4.16xlarge.
2017-02-21 20:46:16 -05:00
|
|
|
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
|
|
|
|
// As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge)
|
2015-08-17 20:44:01 -04:00
|
|
|
registerOpts.SriovNetSupport = aws.String("simple")
|
2017-08-28 12:18:23 -04:00
|
|
|
}
|
|
|
|
if s.EnableAMIENASupport {
|
Always set both SRIOV and ENA when Enhanced Networking is enabled
Set SriovNetSupport to "simple". As of February 2017, this applies to C3, C4,
D2, I2, R3, and M4 (excluding m4.16xlarge).
Set EnaSupport to true. As of February 2017, this applies to C5, I3, P2, R4,
X1, and m4.16xlarge.
2017-02-21 20:46:16 -05:00
|
|
|
// Set EnaSupport to true
|
|
|
|
// As of February 2017, this applies to C5, I3, P2, R4, X1, and m4.16xlarge
|
|
|
|
registerOpts.EnaSupport = aws.Bool(true)
|
2014-06-04 17:58:11 -04:00
|
|
|
}
|
|
|
|
|
2013-07-30 21:28:21 -04:00
|
|
|
registerResp, err := ec2conn.RegisterImage(registerOpts)
|
|
|
|
if err != nil {
|
2013-08-31 15:58:55 -04:00
|
|
|
state.Put("error", fmt.Errorf("Error registering AMI: %s", err))
|
|
|
|
ui.Error(state.Get("error").(error).Error())
|
2013-07-30 21:28:21 -04:00
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the AMI ID in the state
|
2015-08-17 20:44:01 -04:00
|
|
|
ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageId))
|
2013-07-30 21:28:21 -04:00
|
|
|
amis := make(map[string]string)
|
2015-08-17 20:44:01 -04:00
|
|
|
amis[*ec2conn.Config.Region] = *registerResp.ImageId
|
2013-08-31 15:58:55 -04:00
|
|
|
state.Put("amis", amis)
|
2013-07-30 21:28:21 -04:00
|
|
|
|
|
|
|
// Wait for the image to become ready
|
2013-09-12 23:33:32 -04:00
|
|
|
stateChange := awscommon.StateChangeConf{
|
|
|
|
Pending: []string{"pending"},
|
|
|
|
Target: "available",
|
2015-08-17 20:44:01 -04:00
|
|
|
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageId),
|
2013-09-12 23:33:32 -04:00
|
|
|
StepState: state,
|
|
|
|
}
|
|
|
|
|
2013-07-30 21:28:21 -04:00
|
|
|
ui.Say("Waiting for AMI to become ready...")
|
2013-09-12 23:33:32 -04:00
|
|
|
if _, err := awscommon.WaitForState(&stateChange); err != nil {
|
2013-07-30 21:28:21 -04:00
|
|
|
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
2013-08-31 15:58:55 -04:00
|
|
|
state.Put("error", err)
|
2013-07-30 21:28:21 -04:00
|
|
|
ui.Error(err.Error())
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
|
|
|
|
|
|
|
return multistep.ActionContinue
|
|
|
|
}
|
|
|
|
|
2013-08-31 15:58:55 -04:00
|
|
|
func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {}
|
2014-07-30 00:56:37 -04:00
|
|
|
|
2016-09-16 21:35:36 -04:00
|
|
|
func buildRegisterOpts(config *Config, image *ec2.Image, mappings []*ec2.BlockDeviceMapping) *ec2.RegisterImageInput {
|
2015-04-05 17:58:48 -04:00
|
|
|
registerOpts := &ec2.RegisterImageInput{
|
|
|
|
Name: &config.AMIName,
|
|
|
|
Architecture: image.Architecture,
|
|
|
|
RootDeviceName: image.RootDeviceName,
|
2016-09-16 21:35:36 -04:00
|
|
|
BlockDeviceMappings: mappings,
|
2015-06-22 23:08:31 -04:00
|
|
|
VirtualizationType: image.VirtualizationType,
|
2015-06-22 18:08:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if config.AMIVirtType != "" {
|
|
|
|
registerOpts.VirtualizationType = aws.String(config.AMIVirtType)
|
2014-07-30 00:56:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if config.AMIVirtType != "hvm" {
|
2015-08-17 20:44:01 -04:00
|
|
|
registerOpts.KernelId = image.KernelId
|
|
|
|
registerOpts.RamdiskId = image.RamdiskId
|
2014-07-30 00:56:37 -04:00
|
|
|
}
|
|
|
|
return registerOpts
|
|
|
|
}
|