[lxd] it 'works'
This commit is contained in:
parent
821cca56a8
commit
3a0ef7b8b8
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue