From 033218df0ddf97a47f40f83c121626be8e71fba0 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 29 Jul 2013 19:07:51 -0700 Subject: [PATCH] builder/amazon/chroot: Attach volume --- builder/amazon/chroot/builder.go | 2 +- builder/amazon/chroot/step_attach_volume.go | 115 ++++++++++++++++++++ builder/amazon/chroot/step_create_volume.go | 1 + 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 builder/amazon/chroot/step_attach_volume.go diff --git a/builder/amazon/chroot/builder.go b/builder/amazon/chroot/builder.go index 15928a220..37c308a98 100644 --- a/builder/amazon/chroot/builder.go +++ b/builder/amazon/chroot/builder.go @@ -75,7 +75,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &StepInstanceInfo{}, &StepSourceAMIInfo{}, &StepCreateVolume{}, - //&StepAttachVolume{}, + &StepAttachVolume{}, } // Run! diff --git a/builder/amazon/chroot/step_attach_volume.go b/builder/amazon/chroot/step_attach_volume.go new file mode 100644 index 000000000..df7c85b47 --- /dev/null +++ b/builder/amazon/chroot/step_attach_volume.go @@ -0,0 +1,115 @@ +package chroot + +import ( + "errors" + "fmt" + "github.com/mitchellh/goamz/ec2" + "github.com/mitchellh/multistep" + awscommon "github.com/mitchellh/packer/builder/amazon/common" + "github.com/mitchellh/packer/packer" +) + +// StepAttachVolume attaches the previously created volume to an +// available device location. +// +// Produces: +// volume_id string - The ID of the created volume +type StepAttachVolume struct { + attached bool + volumeId string +} + +func (s *StepAttachVolume) Run(state map[string]interface{}) multistep.StepAction { + ec2conn := state["ec2"].(*ec2.EC2) + instance := state["instance"].(*ec2.Instance) + ui := state["ui"].(packer.Ui) + volumeId := state["volume_id"].(string) + + device := "/dev/sdh" + + ui.Say("Attaching the root volume...") + _, err := ec2conn.AttachVolume(volumeId, instance.InstanceId, device) + if err != nil { + err := fmt.Errorf("Error attaching volume: %s", err) + state["error"] = err + ui.Error(err.Error()) + return multistep.ActionHalt + } + + // Mark that we attached it so we can detach it later + s.attached = true + s.volumeId = volumeId + + // Wait for the volume to become attached + stateChange := awscommon.StateChangeConf{ + Conn: ec2conn, + Pending: []string{"attaching"}, + StepState: state, + Target: "attached", + Refresh: func() (interface{}, string, error) { + resp, err := ec2conn.Volumes([]string{volumeId}, ec2.NewFilter()) + if err != nil { + return nil, "", err + } + + if len(resp.Volumes[0].Attachments) == 0 { + return nil, "", errors.New("No attachments on volume.") + } + + return nil, resp.Volumes[0].Attachments[0].Status, nil + }, + } + + _, err = awscommon.WaitForState(&stateChange) + if err != nil { + err := fmt.Errorf("Error waiting for volume: %s", err) + state["error"] = err + ui.Error(err.Error()) + return multistep.ActionHalt + } + + return multistep.ActionContinue +} + +func (s *StepAttachVolume) Cleanup(state map[string]interface{}) { + if !s.attached { + return + } + + ec2conn := state["ec2"].(*ec2.EC2) + ui := state["ui"].(packer.Ui) + + ui.Say("Detaching EBS volume...") + _, err := ec2conn.DetachVolume(s.volumeId) + if err != nil { + ui.Error(fmt.Sprintf("Error detaching EBS volume: %s", err)) + return + } + + // Wait for the volume to detach + stateChange := awscommon.StateChangeConf{ + Conn: ec2conn, + Pending: []string{"detaching"}, + StepState: state, + Target: "detached", + Refresh: func() (interface{}, string, error) { + resp, err := ec2conn.Volumes([]string{s.volumeId}, ec2.NewFilter()) + if err != nil { + return nil, "", err + } + + state := "detached" + if len(resp.Volumes[0].Attachments) > 0 { + state = resp.Volumes[0].Attachments[0].Status + } + + return nil, state, nil + }, + } + + _, err = awscommon.WaitForState(&stateChange) + if err != nil { + ui.Error(fmt.Sprintf("Error waiting for volume: %s", err)) + return + } +} diff --git a/builder/amazon/chroot/step_create_volume.go b/builder/amazon/chroot/step_create_volume.go index 9d7e0a1cb..0e9cb2a36 100644 --- a/builder/amazon/chroot/step_create_volume.go +++ b/builder/amazon/chroot/step_create_volume.go @@ -86,6 +86,7 @@ func (s *StepCreateVolume) Run(state map[string]interface{}) multistep.StepActio return multistep.ActionHalt } + state["volume_id"] = s.volumeId return multistep.ActionContinue }