github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/lxc/step_export.go (about)

     1  package lxc
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/hashicorp/packer/packer"
     7  	"github.com/mitchellh/multistep"
     8  	"io"
     9  	"log"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"strings"
    14  )
    15  
    16  type stepExport struct{}
    17  
    18  func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
    19  	config := state.Get("config").(*Config)
    20  	ui := state.Get("ui").(packer.Ui)
    21  
    22  	name := config.ContainerName
    23  
    24  	containerDir := fmt.Sprintf("/var/lib/lxc/%s", name)
    25  	outputPath := filepath.Join(config.OutputDir, "rootfs.tar.gz")
    26  	configFilePath := filepath.Join(config.OutputDir, "lxc-config")
    27  
    28  	configFile, err := os.Create(configFilePath)
    29  
    30  	if err != nil {
    31  		err := fmt.Errorf("Error creating config file: %s", err)
    32  		state.Put("error", err)
    33  		ui.Error(err.Error())
    34  		return multistep.ActionHalt
    35  	}
    36  
    37  	originalConfigFile, err := os.Open(config.ConfigFile)
    38  
    39  	if err != nil {
    40  		err := fmt.Errorf("Error opening config file: %s", err)
    41  		state.Put("error", err)
    42  		ui.Error(err.Error())
    43  		return multistep.ActionHalt
    44  	}
    45  
    46  	_, err = io.Copy(configFile, originalConfigFile)
    47  
    48  	commands := make([][]string, 4)
    49  	commands[0] = []string{
    50  		"lxc-stop", "--name", name,
    51  	}
    52  	commands[1] = []string{
    53  		"tar", "-C", containerDir, "--numeric-owner", "--anchored", "--exclude=./rootfs/dev/log", "-czf", outputPath, "./rootfs",
    54  	}
    55  	commands[2] = []string{
    56  		"chmod", "+x", configFilePath,
    57  	}
    58  	commands[3] = []string{
    59  		"sh", "-c", "chown $USER:`id -gn` " + filepath.Join(config.OutputDir, "*"),
    60  	}
    61  
    62  	ui.Say("Exporting container...")
    63  	for _, command := range commands {
    64  		err := s.SudoCommand(command...)
    65  		if err != nil {
    66  			err := fmt.Errorf("Error exporting container: %s", err)
    67  			state.Put("error", err)
    68  			ui.Error(err.Error())
    69  			return multistep.ActionHalt
    70  		}
    71  	}
    72  
    73  	return multistep.ActionContinue
    74  }
    75  
    76  func (s *stepExport) Cleanup(state multistep.StateBag) {}
    77  
    78  func (s *stepExport) SudoCommand(args ...string) error {
    79  	var stdout, stderr bytes.Buffer
    80  
    81  	log.Printf("Executing sudo command: %#v", args)
    82  	cmd := exec.Command("sudo", args...)
    83  	cmd.Stdout = &stdout
    84  	cmd.Stderr = &stderr
    85  	err := cmd.Run()
    86  
    87  	stdoutString := strings.TrimSpace(stdout.String())
    88  	stderrString := strings.TrimSpace(stderr.String())
    89  
    90  	if _, ok := err.(*exec.ExitError); ok {
    91  		err = fmt.Errorf("Sudo command error: %s", stderrString)
    92  	}
    93  
    94  	log.Printf("stdout: %s", stdoutString)
    95  	log.Printf("stderr: %s", stderrString)
    96  
    97  	return err
    98  }