diff --git a/builder/amazon/chroot/device.go b/builder/amazon/chroot/device.go index 77b7b444a..02a68433c 100644 --- a/builder/amazon/chroot/device.go +++ b/builder/amazon/chroot/device.go @@ -27,11 +27,12 @@ func AvailableDevice() (string, error) { continue } - for i := 1; i < 16; i++ { - device := fmt.Sprintf("/dev/%s%c%d", prefix, letter, i) - if _, err := os.Stat(device); err != nil { - return device, nil - } + // To be able to build both Paravirtual and HVM images, the unnumbered + // device and the first numbered one must be available. + // E.g. /dev/xvdf and /dev/xvdf1 + numbered_device := fmt.Sprintf("%s%d", device, 1) + if _, err := os.Stat(numbered_device); err != nil { + return device, nil } } diff --git a/builder/amazon/chroot/step_mount_device.go b/builder/amazon/chroot/step_mount_device.go index a6419774f..3c3d959c1 100644 --- a/builder/amazon/chroot/step_mount_device.go +++ b/builder/amazon/chroot/step_mount_device.go @@ -3,6 +3,7 @@ package chroot import ( "bytes" "fmt" + "github.com/mitchellh/goamz/ec2" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" "log" @@ -26,6 +27,7 @@ type StepMountDevice struct { func (s *StepMountDevice) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) + image := state.Get("source_image").(*ec2.Image) device := state.Get("device").(string) wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) @@ -57,10 +59,17 @@ func (s *StepMountDevice) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } + log.Printf("Source image virtualization type is: %s", image.VirtualizationType) + deviceMount := device + if image.VirtualizationType == "hvm" { + deviceMount = fmt.Sprintf("%s%d", device, 1) + } + state.Put("deviceMount", deviceMount) + ui.Say("Mounting the root device...") stderr := new(bytes.Buffer) mountCommand, err := wrappedCommand( - fmt.Sprintf("mount %s %s", device, mountPath)) + fmt.Sprintf("mount %s %s", deviceMount, mountPath)) if err != nil { err := fmt.Errorf("Error creating mount command: %s", err) state.Put("error", err) diff --git a/builder/amazon/chroot/step_register_ami.go b/builder/amazon/chroot/step_register_ami.go index 69ec6dbb6..62e6a3ff0 100644 --- a/builder/amazon/chroot/step_register_ami.go +++ b/builder/amazon/chroot/step_register_ami.go @@ -30,14 +30,7 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction { blockDevices[i] = newDevice } - registerOpts := &ec2.RegisterImage{ - Name: config.AMIName, - Architecture: image.Architecture, - KernelId: image.KernelId, - RamdiskId: image.RamdiskId, - RootDeviceName: image.RootDeviceName, - BlockDevices: blockDevices, - } + registerOpts := buildRegisterOpts(config, image, blockDevices) // Set SriovNetSupport to "simple". See http://goo.gl/icuXh5 if config.AMIEnhancedNetworking { @@ -77,3 +70,20 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction { } func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {} + +func buildRegisterOpts(config *Config, image *ec2.Image, blockDevices []ec2.BlockDeviceMapping) *ec2.RegisterImage { + registerOpts := &ec2.RegisterImage{ + Name: config.AMIName, + Architecture: image.Architecture, + RootDeviceName: image.RootDeviceName, + BlockDevices: blockDevices, + VirtType: config.AMIVirtType, + } + + if config.AMIVirtType != "hvm" { + registerOpts.KernelId = image.KernelId + registerOpts.RamdiskId = image.RamdiskId + } + + return registerOpts +} diff --git a/builder/amazon/chroot/step_register_ami_test.go b/builder/amazon/chroot/step_register_ami_test.go new file mode 100644 index 000000000..f85106a8d --- /dev/null +++ b/builder/amazon/chroot/step_register_ami_test.go @@ -0,0 +1,73 @@ +package chroot + +import ( + "testing" + "github.com/mitchellh/goamz/ec2" +) + +func testImage() ec2.Image { + return ec2.Image{ + Id: "ami-abcd1234", + Name: "ami_test_name", + Architecture: "x86_64", + KernelId: "aki-abcd1234", + } +} + +func TestStepRegisterAmi_buildRegisterOpts_pv(t *testing.T) { + config := Config{} + config.AMIName = "test_ami_name" + config.AMIDescription = "test_ami_description" + config.AMIVirtType = "paravirtual" + + image := testImage() + + blockDevices := []ec2.BlockDeviceMapping{} + + opts := buildRegisterOpts(&config, &image, blockDevices) + + expected := config.AMIVirtType + if opts.VirtType != expected { + t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, opts.VirtType) + } + + expected = config.AMIName + if opts.Name != expected { + t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, opts.Name) + } + + expected = image.KernelId + if opts.KernelId != expected { + t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, opts.KernelId) + } + +} + +func TestStepRegisterAmi_buildRegisterOpts_hvm(t *testing.T) { + config := Config{} + config.AMIName = "test_ami_name" + config.AMIDescription = "test_ami_description" + config.AMIVirtType = "hvm" + + image := testImage() + + blockDevices := []ec2.BlockDeviceMapping{} + + opts := buildRegisterOpts(&config, &image, blockDevices) + + expected := config.AMIVirtType + if opts.VirtType != expected { + t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, opts.VirtType) + } + + expected = config.AMIName + if opts.Name != expected { + t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, opts.Name) + } + + expected = "" + if opts.KernelId != expected { + t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, opts.KernelId) + } + +}