Commit 0db6cd35 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

Merge pull request #1330 from qur/qemu-vagrant

Qemu vagrant
parents eedf5672 660e82e6
...@@ -52,6 +52,10 @@ func (a *Artifact) String() string { ...@@ -52,6 +52,10 @@ func (a *Artifact) String() string {
return fmt.Sprintf("AMIs were created:\n\n%s", strings.Join(amiStrings, "\n")) return fmt.Sprintf("AMIs were created:\n\n%s", strings.Join(amiStrings, "\n"))
} }
func (a *Artifact) State(name string) interface{} {
return nil
}
func (a *Artifact) Destroy() error { func (a *Artifact) Destroy() error {
errors := make([]error, 0) errors := make([]error, 0)
......
...@@ -37,6 +37,10 @@ func (a *Artifact) String() string { ...@@ -37,6 +37,10 @@ func (a *Artifact) String() string {
return fmt.Sprintf("A snapshot was created: '%v' in region '%v'", a.snapshotName, a.regionName) return fmt.Sprintf("A snapshot was created: '%v' in region '%v'", a.snapshotName, a.regionName)
} }
func (a *Artifact) State(name string) interface{} {
return nil
}
func (a *Artifact) Destroy() error { func (a *Artifact) Destroy() error {
log.Printf("Destroying image: %d (%s)", a.snapshotId, a.snapshotName) log.Printf("Destroying image: %d (%s)", a.snapshotId, a.snapshotName)
return a.client.DestroyImage(a.snapshotId) return a.client.DestroyImage(a.snapshotId)
......
...@@ -27,6 +27,10 @@ func (a *ExportArtifact) String() string { ...@@ -27,6 +27,10 @@ func (a *ExportArtifact) String() string {
return fmt.Sprintf("Exported Docker file: %s", a.path) return fmt.Sprintf("Exported Docker file: %s", a.path)
} }
func (a *ExportArtifact) State(name string) interface{} {
return nil
}
func (a *ExportArtifact) Destroy() error { func (a *ExportArtifact) Destroy() error {
return os.Remove(a.path) return os.Remove(a.path)
} }
...@@ -28,6 +28,10 @@ func (a *ImportArtifact) String() string { ...@@ -28,6 +28,10 @@ func (a *ImportArtifact) String() string {
return fmt.Sprintf("Imported Docker image: %s", a.Id()) return fmt.Sprintf("Imported Docker image: %s", a.Id())
} }
func (*ImportArtifact) State(name string) interface{} {
return nil
}
func (a *ImportArtifact) Destroy() error { func (a *ImportArtifact) Destroy() error {
return a.Driver.DeleteImage(a.Id()) return a.Driver.DeleteImage(a.Id())
} }
...@@ -37,3 +37,7 @@ func (a *Artifact) Id() string { ...@@ -37,3 +37,7 @@ func (a *Artifact) Id() string {
func (a *Artifact) String() string { func (a *Artifact) String() string {
return fmt.Sprintf("A disk image was created: %v", a.imageName) return fmt.Sprintf("A disk image was created: %v", a.imageName)
} }
func (a *Artifact) State(name string) interface{} {
return nil
}
...@@ -24,6 +24,10 @@ func (a *NullArtifact) String() string { ...@@ -24,6 +24,10 @@ func (a *NullArtifact) String() string {
return fmt.Sprintf("Did not export anything. This is the null builder") return fmt.Sprintf("Did not export anything. This is the null builder")
} }
func (a *NullArtifact) State(name string) interface{} {
return nil
}
func (a *NullArtifact) Destroy() error { func (a *NullArtifact) Destroy() error {
return nil return nil
} }
...@@ -36,6 +36,10 @@ func (a *Artifact) String() string { ...@@ -36,6 +36,10 @@ func (a *Artifact) String() string {
return fmt.Sprintf("An image was created: %v", a.ImageId) return fmt.Sprintf("An image was created: %v", a.ImageId)
} }
func (a *Artifact) State(name string) interface{} {
return nil
}
func (a *Artifact) Destroy() error { func (a *Artifact) Destroy() error {
log.Printf("Destroying image: %d", a.ImageId) log.Printf("Destroying image: %d", a.ImageId)
return a.Conn.DeleteImageById(a.ImageId) return a.Conn.DeleteImageById(a.ImageId)
......
...@@ -66,6 +66,10 @@ func (a *artifact) String() string { ...@@ -66,6 +66,10 @@ func (a *artifact) String() string {
return fmt.Sprintf("VM files in directory: %s", a.dir) return fmt.Sprintf("VM files in directory: %s", a.dir)
} }
func (a *artifact) State(name string) interface{} {
return nil
}
func (a *artifact) Destroy() error { func (a *artifact) Destroy() error {
return os.RemoveAll(a.dir) return os.RemoveAll(a.dir)
} }
...@@ -8,8 +8,9 @@ import ( ...@@ -8,8 +8,9 @@ import (
// Artifact is the result of running the Qemu builder, namely a set // Artifact is the result of running the Qemu builder, namely a set
// of files associated with the resulting machine. // of files associated with the resulting machine.
type Artifact struct { type Artifact struct {
dir string dir string
f []string f []string
state map[string]interface{}
} }
func (*Artifact) BuilderId() string { func (*Artifact) BuilderId() string {
...@@ -28,6 +29,10 @@ func (a *Artifact) String() string { ...@@ -28,6 +29,10 @@ func (a *Artifact) String() string {
return fmt.Sprintf("VM files in directory: %s", a.dir) return fmt.Sprintf("VM files in directory: %s", a.dir)
} }
func (a *Artifact) State(name string) interface{} {
return a.state[name]
}
func (a *Artifact) Destroy() error { func (a *Artifact) Destroy() error {
return os.RemoveAll(a.dir) return os.RemoveAll(a.dir)
} }
...@@ -502,8 +502,14 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ...@@ -502,8 +502,14 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
artifact := &Artifact{ artifact := &Artifact{
dir: b.config.OutputDir, dir: b.config.OutputDir,
f: files, f: files,
state: make(map[string]interface{}),
} }
artifact.state["diskName"] = state.Get("disk_filename").(string)
artifact.state["diskType"] = b.config.Format
artifact.state["diskSize"] = uint64(b.config.DiskSize)
artifact.state["domainType"] = b.config.Accelerator
return artifact, nil return artifact, nil
} }
......
...@@ -16,8 +16,8 @@ func (s *stepCreateDisk) Run(state multistep.StateBag) multistep.StepAction { ...@@ -16,8 +16,8 @@ func (s *stepCreateDisk) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*config) config := state.Get("config").(*config)
driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s.%s", config.VMName, name := config.VMName + "." + strings.ToLower(config.Format)
strings.ToLower(config.Format))) path := filepath.Join(config.OutputDir, name)
command := []string{ command := []string{
"create", "create",
...@@ -38,6 +38,8 @@ func (s *stepCreateDisk) Run(state multistep.StateBag) multistep.StepAction { ...@@ -38,6 +38,8 @@ func (s *stepCreateDisk) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt return multistep.ActionHalt
} }
state.Put("disk_filename", name)
return multistep.ActionContinue return multistep.ActionContinue
} }
......
...@@ -56,6 +56,10 @@ func (a *artifact) String() string { ...@@ -56,6 +56,10 @@ func (a *artifact) String() string {
return fmt.Sprintf("VM files in directory: %s", a.dir) return fmt.Sprintf("VM files in directory: %s", a.dir)
} }
func (a *artifact) State(name string) interface{} {
return nil
}
func (a *artifact) Destroy() error { func (a *artifact) Destroy() error {
return os.RemoveAll(a.dir) return os.RemoveAll(a.dir)
} }
...@@ -56,6 +56,10 @@ func (a *localArtifact) String() string { ...@@ -56,6 +56,10 @@ func (a *localArtifact) String() string {
return fmt.Sprintf("VM files in directory: %s", a.dir) return fmt.Sprintf("VM files in directory: %s", a.dir)
} }
func (a *localArtifact) State(name string) interface{} {
return nil
}
func (a *localArtifact) Destroy() error { func (a *localArtifact) Destroy() error {
return os.RemoveAll(a.dir) return os.RemoveAll(a.dir)
} }
...@@ -28,6 +28,10 @@ func (a *Artifact) String() string { ...@@ -28,6 +28,10 @@ func (a *Artifact) String() string {
return fmt.Sprintf("VM files in directory: %s", a.dir) return fmt.Sprintf("VM files in directory: %s", a.dir)
} }
func (a *Artifact) State(name string) interface{} {
return nil
}
func (a *Artifact) Destroy() error { func (a *Artifact) Destroy() error {
return a.dir.RemoveAll() return a.dir.RemoveAll()
} }
...@@ -25,6 +25,10 @@ type Artifact interface { ...@@ -25,6 +25,10 @@ type Artifact interface {
// This is used for UI output. It can be multiple lines. // This is used for UI output. It can be multiple lines.
String() string String() string
// State allows the caller to ask for builder specific state information
// relating to the artifact instance.
State(name string) interface{}
// Destroy deletes the artifact. Packer calls this for various reasons, // Destroy deletes the artifact. Packer calls this for various reasons,
// such as if a post-processor has processed this artifact and it is // such as if a post-processor has processed this artifact and it is
// no longer needed. // no longer needed.
......
...@@ -5,6 +5,7 @@ type MockArtifact struct { ...@@ -5,6 +5,7 @@ type MockArtifact struct {
BuilderIdValue string BuilderIdValue string
FilesValue []string FilesValue []string
IdValue string IdValue string
StateValues map[string]interface{}
DestroyCalled bool DestroyCalled bool
} }
...@@ -37,6 +38,11 @@ func (*MockArtifact) String() string { ...@@ -37,6 +38,11 @@ func (*MockArtifact) String() string {
return "string" return "string"
} }
func (a *MockArtifact) State(name string) interface{} {
value, _ := a.StateValues[name]
return value
}
func (a *MockArtifact) Destroy() error { func (a *MockArtifact) Destroy() error {
a.DestroyCalled = true a.DestroyCalled = true
return nil return nil
......
...@@ -2,6 +2,7 @@ package packer ...@@ -2,6 +2,7 @@ package packer
type TestArtifact struct { type TestArtifact struct {
id string id string
state map[string]interface{}
destroyCalled bool destroyCalled bool
} }
...@@ -26,6 +27,11 @@ func (*TestArtifact) String() string { ...@@ -26,6 +27,11 @@ func (*TestArtifact) String() string {
return "string" return "string"
} }
func (a *TestArtifact) State(name string) interface{} {
value, _ := a.state[name]
return value
}
func (a *TestArtifact) Destroy() error { func (a *TestArtifact) Destroy() error {
a.destroyCalled = true a.destroyCalled = true
return nil return nil
......
...@@ -38,6 +38,11 @@ func (a *artifact) String() (result string) { ...@@ -38,6 +38,11 @@ func (a *artifact) String() (result string) {
return return
} }
func (a *artifact) State(name string) (result interface{}) {
a.client.Call(a.endpoint+".State", name, &result)
return
}
func (a *artifact) Destroy() error { func (a *artifact) Destroy() error {
var result error var result error
if err := a.client.Call(a.endpoint+".Destroy", new(interface{}), &result); err != nil { if err := a.client.Call(a.endpoint+".Destroy", new(interface{}), &result); err != nil {
...@@ -67,6 +72,11 @@ func (s *ArtifactServer) String(args *interface{}, reply *string) error { ...@@ -67,6 +72,11 @@ func (s *ArtifactServer) String(args *interface{}, reply *string) error {
return nil return nil
} }
func (s *ArtifactServer) State(name string, reply *interface{}) error {
*reply = s.artifact.State(name)
return nil
}
func (s *ArtifactServer) Destroy(args *interface{}, reply *error) error { func (s *ArtifactServer) Destroy(args *interface{}, reply *error) error {
err := s.artifact.Destroy() err := s.artifact.Destroy()
if err != nil { if err != nil {
......
...@@ -40,8 +40,11 @@ func newClientWithMux(mux *muxBroker, streamId uint32) (*Client, error) { ...@@ -40,8 +40,11 @@ func newClientWithMux(mux *muxBroker, streamId uint32) (*Client, error) {
return nil, err return nil, err
} }
var h codec.MsgpackHandle h := &codec.MsgpackHandle{
clientCodec := codec.GoRpc.ClientCodec(clientConn, &h) RawToString: true,
WriteExt: true,
}
clientCodec := codec.GoRpc.ClientCodec(clientConn, h)
return &Client{ return &Client{
mux: mux, mux: mux,
......
...@@ -148,8 +148,11 @@ func (s *Server) Serve() { ...@@ -148,8 +148,11 @@ func (s *Server) Serve() {
} }
defer stream.Close() defer stream.Close()
var h codec.MsgpackHandle h := &codec.MsgpackHandle{
rpcCodec := codec.GoRpc.ServerCodec(stream, &h) RawToString: true,
WriteExt: true,
}
rpcCodec := codec.GoRpc.ServerCodec(stream, h)
s.server.ServeCodec(rpcCodec) s.server.ServeCodec(rpcCodec)
} }
......
...@@ -35,6 +35,10 @@ func (self *Artifact) String() string { ...@@ -35,6 +35,10 @@ func (self *Artifact) String() string {
return fmt.Sprintf("'%s' compressing: %s", self.Provider, self.Path) return fmt.Sprintf("'%s' compressing: %s", self.Provider, self.Path)
} }
func (*Artifact) State(name string) interface{} {
return nil
}
func (self *Artifact) Destroy() error { func (self *Artifact) Destroy() error {
return os.Remove(self.Path) return os.Remove(self.Path)
} }
...@@ -34,6 +34,10 @@ func (a *Artifact) String() string { ...@@ -34,6 +34,10 @@ func (a *Artifact) String() string {
return fmt.Sprintf("'%s': %s", a.Provider, a.Tag) return fmt.Sprintf("'%s': %s", a.Provider, a.Tag)
} }
func (*Artifact) State(name string) interface{} {
return nil
}
func (a *Artifact) Destroy() error { func (a *Artifact) Destroy() error {
return nil return nil
} }
...@@ -35,6 +35,10 @@ func (a *Artifact) String() string { ...@@ -35,6 +35,10 @@ func (a *Artifact) String() string {
return fmt.Sprintf("'%s' provider box: %s", a.Provider, a.Path) return fmt.Sprintf("'%s' provider box: %s", a.Provider, a.Path)
} }
func (a *Artifact) State(name string) interface{} {
return nil
}
func (a *Artifact) Destroy() error { func (a *Artifact) Destroy() error {
return os.Remove(a.Path) return os.Remove(a.Path)
} }
package vagrant
import (
"fmt"
"github.com/mitchellh/packer/packer"
"path/filepath"
"strings"
)
type LibVirtProvider struct{}
func (p *LibVirtProvider) KeepInputArtifact() bool {
return false
}
func (p *LibVirtProvider) Process(ui packer.Ui, artifact packer.Artifact, dir string) (vagrantfile string, metadata map[string]interface{}, err error) {
diskName := artifact.State("diskName").(string)
// Copy the disk image into the temporary directory (as box.img)
for _, path := range artifact.Files() {
if strings.HasSuffix(path, "/"+diskName) {
ui.Message(fmt.Sprintf("Copying from artifact: %s", path))
dstPath := filepath.Join(dir, "box.img")
if err = CopyContents(dstPath, path); err != nil {
return
}
}
}
format := artifact.State("diskType").(string)
origSize := artifact.State("diskSize").(uint64)
size := origSize / 1024 // In MB, want GB
if origSize % 1024 > 0 {
// Make sure we don't make the size smaller
size++
}
domainType := artifact.State("domainType").(string)
// Convert domain type to libvirt driver
var driver string
switch domainType {
case "kvm", "qemu":
driver = domainType
default:
return "", nil, fmt.Errorf("Unknown libvirt domain type: %s", domainType)
}
// Create the metadata
metadata = map[string]interface{}{
"provider": "libvirt",
"format": format,
"virtual_size": size,
}
vagrantfile = fmt.Sprintf(libvirtVagrantfile, driver)
return
}
var libvirtVagrantfile = `
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.driver = "%s"
end
end
`
...@@ -23,6 +23,7 @@ var builtins = map[string]string{ ...@@ -23,6 +23,7 @@ var builtins = map[string]string{
"pearkes.digitalocean": "digitalocean", "pearkes.digitalocean": "digitalocean",
"packer.parallels": "parallels", "packer.parallels": "parallels",
"MSOpenTech.hyperv": "hyperv", "MSOpenTech.hyperv": "hyperv",
"transcend.qemu": "libvirt",
} }
type Config struct { type Config struct {
...@@ -228,6 +229,8 @@ func providerForName(name string) Provider { ...@@ -228,6 +229,8 @@ func providerForName(name string) Provider {
return new(ParallelsProvider) return new(ParallelsProvider)
case "hyperv": case "hyperv":
return new(HypervProvider) return new(HypervProvider)
case "libvirt":
return new(LibVirtProvider)
default: default:
return nil return nil
} }
......
...@@ -32,6 +32,7 @@ providers. ...@@ -32,6 +32,7 @@ providers.
* DigitalOcean * DigitalOcean
* Hyper-V * Hyper-V
* Parallels * Parallels
* QEMU
* VirtualBox * VirtualBox
* VMware * VMware
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment