commit
0db6cd3533
|
@ -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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 (
|
||||||
// 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 {
|
||||||
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
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
// 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 {
|
||||||
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 {
|
||||||
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
|
||||||
|
|
||||||
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 {
|
||||||
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) {
|
||||||
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 {
|
||||||
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) {
|
||||||
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() {
|
||||||
}
|
}
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
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{
|
||||||
"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 {
|
||||||
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.
|
||||||
* DigitalOcean
|
* DigitalOcean
|
||||||
* Hyper-V
|
* Hyper-V
|
||||||
* Parallels
|
* Parallels
|
||||||
|
* QEMU
|
||||||
* VirtualBox
|
* VirtualBox
|
||||||
* VMware
|
* VMware
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue