github.com/rothwerx/packer@v0.9.0/builder/amazon/chroot/step_mount_extra.go (about) 1 package chroot 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/mitchellh/multistep" 7 "github.com/mitchellh/packer/packer" 8 "os" 9 "os/exec" 10 "syscall" 11 ) 12 13 // StepMountExtra mounts the attached device. 14 // 15 // Produces: 16 // mount_extra_cleanup CleanupFunc - To perform early cleanup 17 type StepMountExtra struct { 18 mounts []string 19 } 20 21 func (s *StepMountExtra) Run(state multistep.StateBag) multistep.StepAction { 22 config := state.Get("config").(*Config) 23 mountPath := state.Get("mount_path").(string) 24 ui := state.Get("ui").(packer.Ui) 25 wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) 26 27 s.mounts = make([]string, 0, len(config.ChrootMounts)) 28 29 ui.Say("Mounting additional paths within the chroot...") 30 for _, mountInfo := range config.ChrootMounts { 31 innerPath := mountPath + mountInfo[2] 32 33 if err := os.MkdirAll(innerPath, 0755); err != nil { 34 err := fmt.Errorf("Error creating mount directory: %s", err) 35 state.Put("error", err) 36 ui.Error(err.Error()) 37 return multistep.ActionHalt 38 } 39 40 flags := "-t " + mountInfo[0] 41 if mountInfo[0] == "bind" { 42 flags = "--bind" 43 } 44 45 ui.Message(fmt.Sprintf("Mounting: %s", mountInfo[2])) 46 stderr := new(bytes.Buffer) 47 mountCommand, err := wrappedCommand(fmt.Sprintf( 48 "mount %s %s %s", 49 flags, 50 mountInfo[1], 51 innerPath)) 52 if err != nil { 53 err := fmt.Errorf("Error creating mount command: %s", err) 54 state.Put("error", err) 55 ui.Error(err.Error()) 56 return multistep.ActionHalt 57 } 58 59 cmd := ShellCommand(mountCommand) 60 cmd.Stderr = stderr 61 if err := cmd.Run(); err != nil { 62 err := fmt.Errorf( 63 "Error mounting: %s\nStderr: %s", err, stderr.String()) 64 state.Put("error", err) 65 ui.Error(err.Error()) 66 return multistep.ActionHalt 67 } 68 69 s.mounts = append(s.mounts, innerPath) 70 } 71 72 state.Put("mount_extra_cleanup", s) 73 return multistep.ActionContinue 74 } 75 76 func (s *StepMountExtra) Cleanup(state multistep.StateBag) { 77 ui := state.Get("ui").(packer.Ui) 78 79 if err := s.CleanupFunc(state); err != nil { 80 ui.Error(err.Error()) 81 return 82 } 83 } 84 85 func (s *StepMountExtra) CleanupFunc(state multistep.StateBag) error { 86 if s.mounts == nil { 87 return nil 88 } 89 90 wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) 91 for len(s.mounts) > 0 { 92 var path string 93 lastIndex := len(s.mounts) - 1 94 path, s.mounts = s.mounts[lastIndex], s.mounts[:lastIndex] 95 96 grepCommand, err := wrappedCommand(fmt.Sprintf("grep %s /proc/mounts", path)) 97 if err != nil { 98 return fmt.Errorf("Error creating grep command: %s", err) 99 } 100 101 // Before attempting to unmount, 102 // check to see if path is already unmounted 103 stderr := new(bytes.Buffer) 104 cmd := ShellCommand(grepCommand) 105 cmd.Stderr = stderr 106 if err := cmd.Run(); err != nil { 107 if exitError, ok := err.(*exec.ExitError); ok { 108 if status, ok := exitError.Sys().(syscall.WaitStatus); ok { 109 exitStatus := status.ExitStatus() 110 if exitStatus == 1 { 111 // path has already been unmounted 112 // just skip this path 113 continue 114 } 115 } 116 } 117 } 118 119 unmountCommand, err := wrappedCommand(fmt.Sprintf("umount %s", path)) 120 if err != nil { 121 return fmt.Errorf("Error creating unmount command: %s", err) 122 } 123 124 stderr = new(bytes.Buffer) 125 cmd = ShellCommand(unmountCommand) 126 cmd.Stderr = stderr 127 if err := cmd.Run(); err != nil { 128 return fmt.Errorf( 129 "Error unmounting device: %s\nStderr: %s", err, stderr.String()) 130 } 131 } 132 133 s.mounts = nil 134 return nil 135 }