github.com/sneal/packer@v0.5.2/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  )
    10  
    11  // StepMountExtra mounts the attached device.
    12  //
    13  // Produces:
    14  //   mount_extra_cleanup CleanupFunc - To perform early cleanup
    15  type StepMountExtra struct {
    16  	mounts []string
    17  }
    18  
    19  func (s *StepMountExtra) Run(state multistep.StateBag) multistep.StepAction {
    20  	config := state.Get("config").(*Config)
    21  	mountPath := state.Get("mount_path").(string)
    22  	ui := state.Get("ui").(packer.Ui)
    23  	wrappedCommand := state.Get("wrappedCommand").(CommandWrapper)
    24  
    25  	s.mounts = make([]string, 0, len(config.ChrootMounts))
    26  
    27  	ui.Say("Mounting additional paths within the chroot...")
    28  	for _, mountInfo := range config.ChrootMounts {
    29  		innerPath := mountPath + mountInfo[2]
    30  
    31  		if err := os.MkdirAll(innerPath, 0755); err != nil {
    32  			err := fmt.Errorf("Error creating mount directory: %s", err)
    33  			state.Put("error", err)
    34  			ui.Error(err.Error())
    35  			return multistep.ActionHalt
    36  		}
    37  
    38  		flags := "-t " + mountInfo[0]
    39  		if mountInfo[0] == "bind" {
    40  			flags = "--bind"
    41  		}
    42  
    43  		ui.Message(fmt.Sprintf("Mounting: %s", mountInfo[2]))
    44  		stderr := new(bytes.Buffer)
    45  		mountCommand, err := wrappedCommand(fmt.Sprintf(
    46  			"mount %s %s %s",
    47  			flags,
    48  			mountInfo[1],
    49  			innerPath))
    50  		if err != nil {
    51  			err := fmt.Errorf("Error creating mount command: %s", err)
    52  			state.Put("error", err)
    53  			ui.Error(err.Error())
    54  			return multistep.ActionHalt
    55  		}
    56  
    57  		cmd := ShellCommand(mountCommand)
    58  		cmd.Stderr = stderr
    59  		if err := cmd.Run(); err != nil {
    60  			err := fmt.Errorf(
    61  				"Error mounting: %s\nStderr: %s", err, stderr.String())
    62  			state.Put("error", err)
    63  			ui.Error(err.Error())
    64  			return multistep.ActionHalt
    65  		}
    66  
    67  		s.mounts = append(s.mounts, innerPath)
    68  	}
    69  
    70  	state.Put("mount_extra_cleanup", s)
    71  	return multistep.ActionContinue
    72  }
    73  
    74  func (s *StepMountExtra) Cleanup(state multistep.StateBag) {
    75  	ui := state.Get("ui").(packer.Ui)
    76  
    77  	if err := s.CleanupFunc(state); err != nil {
    78  		ui.Error(err.Error())
    79  		return
    80  	}
    81  }
    82  
    83  func (s *StepMountExtra) CleanupFunc(state multistep.StateBag) error {
    84  	if s.mounts == nil {
    85  		return nil
    86  	}
    87  
    88  	wrappedCommand := state.Get("wrappedCommand").(CommandWrapper)
    89  	for len(s.mounts) > 0 {
    90  		var path string
    91  		lastIndex := len(s.mounts) - 1
    92  		path, s.mounts = s.mounts[lastIndex], s.mounts[:lastIndex]
    93  		unmountCommand, err := wrappedCommand(fmt.Sprintf("umount %s", path))
    94  		if err != nil {
    95  			return fmt.Errorf("Error creating unmount command: %s", err)
    96  		}
    97  
    98  		stderr := new(bytes.Buffer)
    99  		cmd := ShellCommand(unmountCommand)
   100  		cmd.Stderr = stderr
   101  		if err := cmd.Run(); err != nil {
   102  			return fmt.Errorf(
   103  				"Error unmounting device: %s\nStderr: %s", err, stderr.String())
   104  		}
   105  	}
   106  
   107  	s.mounts = nil
   108  	return nil
   109  }