builder/amazon: Add `ebs-volume` builder
This commit adds a builder that works like EBS builders, except does not
create an AMI, and instead is intended to create EBS volumes in an
initialized state. For example, the following template can be used to
create and export a set of 3 EBS Volumes in a ZFS zpool named `data` for
importing by instances running production systems:
```
{
"variables": {
"aws_access_key_id": "{{ env `AWS_ACCESS_KEY_ID` }}",
"aws_secret_access_key": "{{ env `AWS_SECRET_ACCESS_KEY` }}",
"region": "{{ env `AWS_REGION` }}",
"source_ami": "{{ env `PACKER_SOURCE_AMI` }}",
"vpc_id": "{{ env `PACKER_VPC_ID` }}",
"subnet_id": "{{ env `PACKER_SUBNET_ID` }}"
},
"builders": [{
"type": "amazon-ebs-volume",
"access_key": "{{ user `aws_access_key_id` }}",
"secret_key": "{{ user `aws_secret_access_key` }}",
"region": "{{user `region`}}",
"spot_price_auto_product": "Linux/UNIX (Amazon VPC)",
"ssh_pty": true,
"instance_type": "t2.medium",
"vpc_id": "{{user `vpc_id` }}",
"subnet_id": "{{user `subnet_id` }}",
"associate_public_ip_address": true,
"source_ami": "{{user `source_ami` }}",
"ssh_username": "ubuntu",
"ssh_timeout": "5m",
"ebs_volumes": [
{
"device_name": "/dev/xvdf",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data1",
"zpool": "data",
"Component": "TeamCity"
}
},
{
"device_name": "/dev/xvdg",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data2",
"zpool": "data",
"Component": "TeamCity"
}
},
{
"device_name": "/dev/xvdh",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data3",
"zpool": "data",
"Component": "TeamCity"
}
}
]
}],
"provisioners": [
{
"type": "shell",
"start_retry_timeout": "10m",
"inline": [
"DEBIAN_FRONTEND=noninteractive sudo apt-get update",
"DEBIAN_FRONTEND=noninteractive sudo apt-get install -y zfs",
"lsblk",
"sudo parted /dev/xvdf --script mklabel GPT",
"sudo parted /dev/xvdg --script mklabel GPT",
"sudo parted /dev/xvdh --script mklabel GPT",
"sudo zpool create -m none data raidz xvdf xvdg xvdh",
"sudo zpool status",
"sudo zpool export data",
"sudo zpool status"
]
}
]
}
```
StepModifyInstance and StepStopInstance are now shared between EBS and
EBS-Volume builders - move them into the AWS common directory and rename
them to indicate that they only apply to EBS-backed builders.
2016-10-31 17:44:41 -04:00
|
|
|
package common
|
2013-05-21 03:55:32 -04:00
|
|
|
|
|
|
|
import (
|
2018-01-22 18:32:33 -05:00
|
|
|
"context"
|
2013-06-19 23:54:02 -04:00
|
|
|
"fmt"
|
2019-04-08 11:57:27 -04:00
|
|
|
"time"
|
2015-04-05 17:58:48 -04:00
|
|
|
|
2015-06-03 17:13:52 -04:00
|
|
|
"github.com/aws/aws-sdk-go/service/ec2"
|
2020-10-29 06:57:14 -04:00
|
|
|
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
|
2017-04-04 16:39:01 -04:00
|
|
|
"github.com/hashicorp/packer/packer"
|
2020-11-17 19:31:03 -05:00
|
|
|
"github.com/hashicorp/packer/packer-plugin-sdk/multistep"
|
2020-11-12 17:44:02 -05:00
|
|
|
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
|
2013-05-21 03:55:32 -04:00
|
|
|
)
|
|
|
|
|
builder/amazon: Add `ebs-volume` builder
This commit adds a builder that works like EBS builders, except does not
create an AMI, and instead is intended to create EBS volumes in an
initialized state. For example, the following template can be used to
create and export a set of 3 EBS Volumes in a ZFS zpool named `data` for
importing by instances running production systems:
```
{
"variables": {
"aws_access_key_id": "{{ env `AWS_ACCESS_KEY_ID` }}",
"aws_secret_access_key": "{{ env `AWS_SECRET_ACCESS_KEY` }}",
"region": "{{ env `AWS_REGION` }}",
"source_ami": "{{ env `PACKER_SOURCE_AMI` }}",
"vpc_id": "{{ env `PACKER_VPC_ID` }}",
"subnet_id": "{{ env `PACKER_SUBNET_ID` }}"
},
"builders": [{
"type": "amazon-ebs-volume",
"access_key": "{{ user `aws_access_key_id` }}",
"secret_key": "{{ user `aws_secret_access_key` }}",
"region": "{{user `region`}}",
"spot_price_auto_product": "Linux/UNIX (Amazon VPC)",
"ssh_pty": true,
"instance_type": "t2.medium",
"vpc_id": "{{user `vpc_id` }}",
"subnet_id": "{{user `subnet_id` }}",
"associate_public_ip_address": true,
"source_ami": "{{user `source_ami` }}",
"ssh_username": "ubuntu",
"ssh_timeout": "5m",
"ebs_volumes": [
{
"device_name": "/dev/xvdf",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data1",
"zpool": "data",
"Component": "TeamCity"
}
},
{
"device_name": "/dev/xvdg",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data2",
"zpool": "data",
"Component": "TeamCity"
}
},
{
"device_name": "/dev/xvdh",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data3",
"zpool": "data",
"Component": "TeamCity"
}
}
]
}],
"provisioners": [
{
"type": "shell",
"start_retry_timeout": "10m",
"inline": [
"DEBIAN_FRONTEND=noninteractive sudo apt-get update",
"DEBIAN_FRONTEND=noninteractive sudo apt-get install -y zfs",
"lsblk",
"sudo parted /dev/xvdf --script mklabel GPT",
"sudo parted /dev/xvdg --script mklabel GPT",
"sudo parted /dev/xvdh --script mklabel GPT",
"sudo zpool create -m none data raidz xvdf xvdg xvdh",
"sudo zpool status",
"sudo zpool export data",
"sudo zpool status"
]
}
]
}
```
StepModifyInstance and StepStopInstance are now shared between EBS and
EBS-Volume builders - move them into the AWS common directory and rename
them to indicate that they only apply to EBS-backed builders.
2016-10-31 17:44:41 -04:00
|
|
|
type StepStopEBSBackedInstance struct {
|
2020-08-17 11:09:19 -04:00
|
|
|
PollingConfig *AWSPollingConfig
|
2017-10-23 15:16:12 -04:00
|
|
|
Skip bool
|
2016-03-14 13:49:42 -04:00
|
|
|
DisableStopInstance bool
|
2014-05-07 13:13:27 -04:00
|
|
|
}
|
2013-05-21 03:55:32 -04:00
|
|
|
|
2018-04-23 15:57:04 -04:00
|
|
|
func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
2013-08-31 16:00:43 -04:00
|
|
|
ec2conn := state.Get("ec2").(*ec2.EC2)
|
|
|
|
instance := state.Get("instance").(*ec2.Instance)
|
|
|
|
ui := state.Get("ui").(packer.Ui)
|
2013-05-21 03:55:32 -04:00
|
|
|
|
2014-05-08 01:58:05 -04:00
|
|
|
// Skip when it is a spot instance
|
2017-10-23 15:16:12 -04:00
|
|
|
if s.Skip {
|
2014-05-08 01:58:05 -04:00
|
|
|
return multistep.ActionContinue
|
|
|
|
}
|
2014-05-07 13:13:27 -04:00
|
|
|
|
2016-03-14 13:49:42 -04:00
|
|
|
var err error
|
2016-03-14 12:54:03 -04:00
|
|
|
|
2016-03-15 08:01:20 -04:00
|
|
|
if !s.DisableStopInstance {
|
2016-03-14 13:49:42 -04:00
|
|
|
// Stop the instance so we can create an AMI from it
|
|
|
|
ui.Say("Stopping the source instance...")
|
2017-06-13 17:28:44 -04:00
|
|
|
|
|
|
|
// Amazon EC2 API follows an eventual consistency model.
|
|
|
|
|
|
|
|
// This means that if you run a command to modify or describe a resource
|
|
|
|
// that you just created, its ID might not have propagated throughout
|
|
|
|
// the system, and you will get an error responding that the resource
|
|
|
|
// does not exist.
|
|
|
|
|
|
|
|
// Work around this by retrying a few times, up to about 5 minutes.
|
2019-11-12 15:27:47 -05:00
|
|
|
err := retry.Config{Tries: 6, ShouldRetry: func(error) bool {
|
2020-10-29 06:57:14 -04:00
|
|
|
if awserrors.Matches(err, "InvalidInstanceID.NotFound", "") {
|
2019-11-12 15:27:47 -05:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
2019-04-08 11:57:27 -04:00
|
|
|
RetryDelay: (&retry.Backoff{InitialBackoff: 10 * time.Second, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear,
|
|
|
|
}.Run(ctx, func(ctx context.Context) error {
|
|
|
|
ui.Message(fmt.Sprintf("Stopping instance"))
|
2017-06-13 17:28:44 -04:00
|
|
|
|
|
|
|
_, err = ec2conn.StopInstances(&ec2.StopInstancesInput{
|
|
|
|
InstanceIds: []*string{instance.InstanceId},
|
|
|
|
})
|
|
|
|
|
2019-04-08 11:57:27 -04:00
|
|
|
return err
|
2016-03-14 13:49:42 -04:00
|
|
|
})
|
2017-06-13 17:28:44 -04:00
|
|
|
|
2016-03-14 13:49:42 -04:00
|
|
|
if err != nil {
|
|
|
|
err := fmt.Errorf("Error stopping instance: %s", err)
|
|
|
|
state.Put("error", err)
|
|
|
|
ui.Error(err.Error())
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
2017-06-13 17:28:44 -04:00
|
|
|
|
2016-03-15 08:01:20 -04:00
|
|
|
} else {
|
|
|
|
ui.Say("Automatic instance stop disabled. Please stop instance manually.")
|
2016-03-14 13:49:42 -04:00
|
|
|
}
|
2013-05-21 03:55:32 -04:00
|
|
|
|
2017-12-07 17:05:59 -05:00
|
|
|
// Wait for the instance to actually stop
|
2013-05-21 03:55:32 -04:00
|
|
|
ui.Say("Waiting for the instance to stop...")
|
2018-07-12 17:30:44 -04:00
|
|
|
err = ec2conn.WaitUntilInstanceStoppedWithContext(ctx,
|
|
|
|
&ec2.DescribeInstancesInput{
|
|
|
|
InstanceIds: []*string{instance.InstanceId},
|
|
|
|
},
|
2020-08-17 11:09:19 -04:00
|
|
|
s.PollingConfig.getWaiterOptions()...)
|
2017-12-07 17:05:59 -05:00
|
|
|
|
2013-05-21 03:55:32 -04:00
|
|
|
if err != nil {
|
2013-06-19 23:54:02 -04:00
|
|
|
err := fmt.Errorf("Error waiting for instance to stop: %s", err)
|
2013-08-31 16:00:43 -04:00
|
|
|
state.Put("error", err)
|
2013-05-21 03:55:32 -04:00
|
|
|
ui.Error(err.Error())
|
2013-06-04 13:00:06 -04:00
|
|
|
return multistep.ActionHalt
|
2013-05-21 03:55:32 -04:00
|
|
|
}
|
|
|
|
|
2013-06-04 13:00:06 -04:00
|
|
|
return multistep.ActionContinue
|
2013-05-21 03:55:32 -04:00
|
|
|
}
|
|
|
|
|
builder/amazon: Add `ebs-volume` builder
This commit adds a builder that works like EBS builders, except does not
create an AMI, and instead is intended to create EBS volumes in an
initialized state. For example, the following template can be used to
create and export a set of 3 EBS Volumes in a ZFS zpool named `data` for
importing by instances running production systems:
```
{
"variables": {
"aws_access_key_id": "{{ env `AWS_ACCESS_KEY_ID` }}",
"aws_secret_access_key": "{{ env `AWS_SECRET_ACCESS_KEY` }}",
"region": "{{ env `AWS_REGION` }}",
"source_ami": "{{ env `PACKER_SOURCE_AMI` }}",
"vpc_id": "{{ env `PACKER_VPC_ID` }}",
"subnet_id": "{{ env `PACKER_SUBNET_ID` }}"
},
"builders": [{
"type": "amazon-ebs-volume",
"access_key": "{{ user `aws_access_key_id` }}",
"secret_key": "{{ user `aws_secret_access_key` }}",
"region": "{{user `region`}}",
"spot_price_auto_product": "Linux/UNIX (Amazon VPC)",
"ssh_pty": true,
"instance_type": "t2.medium",
"vpc_id": "{{user `vpc_id` }}",
"subnet_id": "{{user `subnet_id` }}",
"associate_public_ip_address": true,
"source_ami": "{{user `source_ami` }}",
"ssh_username": "ubuntu",
"ssh_timeout": "5m",
"ebs_volumes": [
{
"device_name": "/dev/xvdf",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data1",
"zpool": "data",
"Component": "TeamCity"
}
},
{
"device_name": "/dev/xvdg",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data2",
"zpool": "data",
"Component": "TeamCity"
}
},
{
"device_name": "/dev/xvdh",
"delete_on_termination": false,
"volume_size": 10,
"volume_type": "gp2",
"tags": {
"Name": "TeamCity-Data3",
"zpool": "data",
"Component": "TeamCity"
}
}
]
}],
"provisioners": [
{
"type": "shell",
"start_retry_timeout": "10m",
"inline": [
"DEBIAN_FRONTEND=noninteractive sudo apt-get update",
"DEBIAN_FRONTEND=noninteractive sudo apt-get install -y zfs",
"lsblk",
"sudo parted /dev/xvdf --script mklabel GPT",
"sudo parted /dev/xvdg --script mklabel GPT",
"sudo parted /dev/xvdh --script mklabel GPT",
"sudo zpool create -m none data raidz xvdf xvdg xvdh",
"sudo zpool status",
"sudo zpool export data",
"sudo zpool status"
]
}
]
}
```
StepModifyInstance and StepStopInstance are now shared between EBS and
EBS-Volume builders - move them into the AWS common directory and rename
them to indicate that they only apply to EBS-backed builders.
2016-10-31 17:44:41 -04:00
|
|
|
func (s *StepStopEBSBackedInstance) Cleanup(multistep.StateBag) {
|
2013-05-21 03:55:32 -04:00
|
|
|
// No cleanup...
|
|
|
|
}
|