github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/builder/amazon/chroot/step_mount_device.go (about) 1 package chroot 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "os" 8 "path/filepath" 9 "strings" 10 11 "github.com/aws/aws-sdk-go/service/ec2" 12 "github.com/mitchellh/multistep" 13 "github.com/mitchellh/packer/packer" 14 "github.com/mitchellh/packer/template/interpolate" 15 ) 16 17 type mountPathData struct { 18 Device string 19 } 20 21 // StepMountDevice mounts the attached device. 22 // 23 // Produces: 24 // mount_path string - The location where the volume was mounted. 25 // mount_device_cleanup CleanupFunc - To perform early cleanup 26 type StepMountDevice struct { 27 MountOptions []string 28 29 mountPath string 30 } 31 32 func (s *StepMountDevice) Run(state multistep.StateBag) multistep.StepAction { 33 config := state.Get("config").(*Config) 34 ui := state.Get("ui").(packer.Ui) 35 image := state.Get("source_image").(*ec2.Image) 36 device := state.Get("device").(string) 37 wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) 38 39 ctx := config.ctx 40 ctx.Data = &mountPathData{Device: filepath.Base(device)} 41 mountPath, err := interpolate.Render(config.MountPath, &ctx) 42 43 if err != nil { 44 err := fmt.Errorf("Error preparing mount directory: %s", err) 45 state.Put("error", err) 46 ui.Error(err.Error()) 47 return multistep.ActionHalt 48 } 49 50 mountPath, err = filepath.Abs(mountPath) 51 if err != nil { 52 err := fmt.Errorf("Error preparing mount directory: %s", err) 53 state.Put("error", err) 54 ui.Error(err.Error()) 55 return multistep.ActionHalt 56 } 57 58 log.Printf("Mount path: %s", mountPath) 59 60 if err := os.MkdirAll(mountPath, 0755); err != nil { 61 err := fmt.Errorf("Error creating mount directory: %s", err) 62 state.Put("error", err) 63 ui.Error(err.Error()) 64 return multistep.ActionHalt 65 } 66 67 log.Printf("Source image virtualization type is: %s", *image.VirtualizationType) 68 deviceMount := device 69 if *image.VirtualizationType == "hvm" { 70 deviceMount = fmt.Sprintf("%s%d", device, 1) 71 } 72 state.Put("deviceMount", deviceMount) 73 74 ui.Say("Mounting the root device...") 75 stderr := new(bytes.Buffer) 76 77 // build mount options from mount_options config, usefull for nouuid options 78 // or other specific device type settings for mount 79 opts := "" 80 if len(s.MountOptions) > 0 { 81 opts = "-o " + strings.Join(s.MountOptions, " -o ") 82 } 83 mountCommand, err := wrappedCommand( 84 fmt.Sprintf("mount %s %s %s", opts, deviceMount, mountPath)) 85 if err != nil { 86 err := fmt.Errorf("Error creating mount command: %s", err) 87 state.Put("error", err) 88 ui.Error(err.Error()) 89 return multistep.ActionHalt 90 } 91 92 cmd := ShellCommand(mountCommand) 93 cmd.Stderr = stderr 94 if err := cmd.Run(); err != nil { 95 err := fmt.Errorf( 96 "Error mounting root volume: %s\nStderr: %s", err, stderr.String()) 97 state.Put("error", err) 98 ui.Error(err.Error()) 99 return multistep.ActionHalt 100 } 101 102 // Set the mount path so we remember to unmount it later 103 s.mountPath = mountPath 104 state.Put("mount_path", s.mountPath) 105 state.Put("mount_device_cleanup", s) 106 107 return multistep.ActionContinue 108 } 109 110 func (s *StepMountDevice) Cleanup(state multistep.StateBag) { 111 ui := state.Get("ui").(packer.Ui) 112 if err := s.CleanupFunc(state); err != nil { 113 ui.Error(err.Error()) 114 } 115 } 116 117 func (s *StepMountDevice) CleanupFunc(state multistep.StateBag) error { 118 if s.mountPath == "" { 119 return nil 120 } 121 122 ui := state.Get("ui").(packer.Ui) 123 wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) 124 125 ui.Say("Unmounting the root device...") 126 unmountCommand, err := wrappedCommand(fmt.Sprintf("umount %s", s.mountPath)) 127 if err != nil { 128 return fmt.Errorf("Error creating unmount command: %s", err) 129 } 130 131 cmd := ShellCommand(unmountCommand) 132 if err := cmd.Run(); err != nil { 133 return fmt.Errorf("Error unmounting root device: %s", err) 134 } 135 136 s.mountPath = "" 137 return nil 138 }