[lxd] it 'works'

This commit is contained in:
Chris Lundquist 2016-05-30 23:13:59 +00:00 committed by Megan Marsh
parent 821cca56a8
commit 3a0ef7b8b8
10 changed files with 69 additions and 111 deletions

View File

@ -2,7 +2,6 @@ package lxd
import (
"fmt"
"os"
)
type Artifact struct {
@ -23,7 +22,7 @@ func (*Artifact) Id() string {
}
func (a *Artifact) String() string {
return fmt.Sprintf("Container files in directory: %s", a.dir)
return fmt.Sprintf("Container: %s", a.dir)
}
func (a *Artifact) State(name string) interface{} {
@ -31,5 +30,6 @@ func (a *Artifact) State(name string) interface{} {
}
func (a *Artifact) Destroy() error {
return os.RemoveAll(a.dir)
//return os.RemoveAll(a.dir)
return nil
}

View File

@ -7,8 +7,6 @@ import (
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
"log"
"os"
"path/filepath"
"runtime"
)
@ -45,10 +43,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
}
steps := []multistep.Step{
new(stepPrepareOutputDir),
new(stepLxdLaunch),
new(StepProvision),
new(stepExport),
new(stepPublish),
}
// Setup the state bag
@ -85,23 +82,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
return nil, errors.New("Build was halted.")
}
// Compile the artifact list
files := make([]string, 0, 5)
visit := func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
files = append(files, path)
}
return err
}
if err := filepath.Walk(b.config.OutputDir, visit); err != nil {
return nil, err
}
artifact := &Artifact{
dir: b.config.OutputDir,
f: files,
// dir: b.config.OutputDir,
// f: files,
}
return artifact, nil

View File

@ -6,10 +6,11 @@ import (
"github.com/mitchellh/packer/packer"
)
func testConfig() map[string]interface{} {
return map[string]interface{}{
"output_dir": "foo",
"image": "bar",
"image": "bar",
}
}

View File

@ -69,20 +69,44 @@ func (c *Communicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error {
}
func (c *Communicator) UploadDir(dst string, src string, exclude []string) error {
// XXX FIXME. lxc file push doesn't yet support directory uploads
// NOTE:lxc file push doesn't yet support directory uploads.
// As a work around, we tar up the folder, upload it as a file, then extract it
// TODO: make a tar tmpfile of the source, upload it to the dest, then untar it on the remote.
// This approach would work when the LXD host is not the localhost.
dest := filepath.Join("/var/lib/lxd/containers/", c.ContainerName, "rootfs", dst)
log.Printf("Uploading directory '%s' to rootfs '%s'", src, dest)
cpCmd, err := c.CmdWrapper(fmt.Sprintf("sudo cp -R %s/. %s", src, dest))
os.Chdir(src)
tar, err := c.CmdWrapper("tar -czf - .")
if err != nil {
log.Printf("Error when uploading directory '%s' to rootfs '%s': %s", src, dest, err)
return err
}
log.Printf("Running copy command: %s", cpCmd)
return ShellCommand(cpCmd).Run()
cp, err := c.CmdWrapper(fmt.Sprintf("lxc exec %s -- tar -xzf - -C %s ", c.ContainerName, dst))
if err != nil {
return err
}
tarCmd := ShellCommand(tar)
cpCmd := ShellCommand(cp)
cpCmd.Stdin, _ = tarCmd.StdoutPipe()
log.Printf("Starting tar command: %s", tar)
err = tarCmd.Start()
if err != nil {
return err
}
log.Printf("Running cp command: %s", cp)
err = cpCmd.Run()
if err != nil {
log.Printf("Error running cp command: %s", err)
return err
}
err = tarCmd.Wait()
if err != nil {
log.Printf("Error running tar command: %s", err)
return err
}
return nil
}
func (c *Communicator) Download(src string, w io.Writer) error {
@ -99,6 +123,7 @@ func (c *Communicator) Download(src string, w io.Writer) error {
}
func (c *Communicator) DownloadDir(src string, dst string, exclude []string) error {
// TODO This could probably be "lxc exec <container> -- cd <src> && tar -czf - | tar -xzf - -C <dst>"
return fmt.Errorf("DownloadDir is not implemented for lxc")
}

View File

@ -12,3 +12,9 @@ func TestCommunicator_ImplementsCommunicator(t *testing.T) {
t.Fatalf("Communicator should be a communicator")
}
}
// Acceptance tests
// TODO Execute a command
// TODO Upload a file
// TODO Download a file
// TODO Upload a Directory

View File

@ -13,15 +13,15 @@ import (
type Config struct {
common.PackerConfig `mapstructure:",squash"`
///ConfigFile string `mapstructure:"config_file"`
OutputDir string `mapstructure:"output_dir"`
ContainerName string `mapstructure:"container_name"`
CommandWrapper string `mapstructure:"command_wrapper"`
RawInitTimeout string `mapstructure:"init_timeout"`
Image string `mapstructure:"image"`
Remote string `mapstructure:"remote"`
OutputImage string `mapstructure:"output_image"`
ContainerName string `mapstructure:"container_name"`
CommandWrapper string `mapstructure:"command_wrapper"`
RawInitTimeout string `mapstructure:"init_timeout"`
Image string `mapstructure:"image"`
Remote string `mapstructure:"remote"`
//EnvVars []string `mapstructure:"template_environment_vars"`
//TargetRunlevel int `mapstructure:"target_runlevel"`
InitTimeout time.Duration
InitTimeout time.Duration
ctx interpolate.Context
}
@ -41,14 +41,14 @@ func NewConfig(raws ...interface{}) (*Config, error) {
// Accumulate any errors
var errs *packer.MultiError
if c.OutputDir == "" {
c.OutputDir = fmt.Sprintf("output-%s", c.PackerBuildName)
}
if c.ContainerName == "" {
c.ContainerName = fmt.Sprintf("packer-%s", c.PackerBuildName)
}
if c.OutputImage == "" {
c.OutputImage = c.ContainerName
}
if c.CommandWrapper == "" {
c.CommandWrapper = "{{.Command}}"
}

View File

@ -8,6 +8,7 @@ import (
"log"
"os/exec"
"strings"
"time"
)
type stepLxdLaunch struct{}
@ -41,8 +42,7 @@ func (s *stepLxdLaunch) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
}
//state.Put("mount_path", rootfs)
time.Sleep(2 * time.Second)
return multistep.ActionContinue
}

View File

@ -1,49 +0,0 @@
package lxd
import (
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"os"
"time"
)
type stepPrepareOutputDir struct{}
func (stepPrepareOutputDir) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
if _, err := os.Stat(config.OutputDir); err == nil && config.PackerForce {
ui.Say("Deleting previous output directory...")
os.RemoveAll(config.OutputDir)
}
if err := os.MkdirAll(config.OutputDir, 0755); err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
return multistep.ActionContinue
}
func (stepPrepareOutputDir) Cleanup(state multistep.StateBag) {
_, cancelled := state.GetOk(multistep.StateCancelled)
_, halted := state.GetOk(multistep.StateHalted)
if cancelled || halted {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
ui.Say("Deleting output directory...")
for i := 0; i < 5; i++ {
err := os.RemoveAll(config.OutputDir)
if err == nil {
break
}
log.Printf("Error removing output dir: %s", err)
time.Sleep(2 * time.Second)
}
}
}

View File

@ -18,7 +18,6 @@ func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
// Create our communicator
comm := &Communicator{
ContainerName: config.ContainerName,
//RootFs: mountPath,
CmdWrapper: wrappedCommand,
}

View File

@ -7,13 +7,12 @@ import (
"github.com/mitchellh/packer/packer"
"log"
"os/exec"
"path/filepath"
"strings"
)
type stepExport struct{}
type stepPublish struct{}
func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
func (s *stepPublish) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
@ -21,21 +20,15 @@ func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
//outputPath := filepath.Join(config.OutputDir, "rootfs.tar.gz")
commands := make([][]string, 3)
commands := make([][]string, 2)
commands[0] = []string{
"lxc", "stop", name,
"lxc", "stop", "--force", name,
}
commands[1] = []string{
"lxc", "export",
}
//commands[1] = []string{
// "tar", "-C", containerDir, "--numeric-owner", "--anchored", "--exclude=./rootfs/dev/log", "-czf", outputPath, "./rootfs",
//}
commands[2] = []string{
"sh", "-c", "chown $USER:`id -gn` " + filepath.Join(config.OutputDir, "*"),
"lxc", "publish", name,
}
ui.Say("Exporting container...")
ui.Say("Publishing container...")
for _, command := range commands {
err := s.SudoCommand(command...)
if err != nil {
@ -49,9 +42,9 @@ func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionContinue
}
func (s *stepExport) Cleanup(state multistep.StateBag) {}
func (s *stepPublish) Cleanup(state multistep.StateBag) {}
func (s *stepExport) SudoCommand(args ...string) error {
func (s *stepPublish) SudoCommand(args ...string) error {
var stdout, stderr bytes.Buffer
log.Printf("Executing sudo command: %#v", args)