enable vsphere-template to work with local builders
This commit is contained in:
parent
4ce381cae7
commit
644ac5b367
|
@ -7,16 +7,19 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/builder/vmware/iso"
|
||||||
"github.com/hashicorp/packer/common"
|
"github.com/hashicorp/packer/common"
|
||||||
"github.com/hashicorp/packer/helper/config"
|
"github.com/hashicorp/packer/helper/config"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
|
"github.com/hashicorp/packer/post-processor/vsphere"
|
||||||
"github.com/hashicorp/packer/template/interpolate"
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/vmware/govmomi"
|
"github.com/vmware/govmomi"
|
||||||
)
|
)
|
||||||
|
|
||||||
var builtins = map[string]string{
|
var builtins = map[string]string{
|
||||||
"mitchellh.vmware-esx": "vmware",
|
vsphere.BuilderId: "vmware",
|
||||||
|
iso.BuilderIdESX: "vmware",
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -90,11 +93,16 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
||||||
|
|
||||||
source := ""
|
source := ""
|
||||||
for _, path := range artifact.Files() {
|
for _, path := range artifact.Files() {
|
||||||
if strings.HasSuffix(path, ".vmx") {
|
if strings.HasSuffix(path, ".vmx") || strings.HasSuffix(path, ".ovf") || strings.HasSuffix(path, ".ova") {
|
||||||
source = path
|
source = path
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if source == "" {
|
||||||
|
return nil, false, fmt.Errorf("VMX, OVF or OVA file not found")
|
||||||
|
}
|
||||||
|
|
||||||
// In some occasions the VM state is powered on and if we immediately try to mark as template
|
// In some occasions the VM state is powered on and if we immediately try to mark as template
|
||||||
// (after the ESXi creates it) it will fail. If vSphere is given a few seconds this behavior doesn't reappear.
|
// (after the ESXi creates it) it will fail. If vSphere is given a few seconds this behavior doesn't reappear.
|
||||||
ui.Message("Waiting 10s for VMware vSphere to start")
|
ui.Message("Waiting 10s for VMware vSphere to start")
|
||||||
|
@ -117,10 +125,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
||||||
&stepCreateFolder{
|
&stepCreateFolder{
|
||||||
Folder: p.config.Folder,
|
Folder: p.config.Folder,
|
||||||
},
|
},
|
||||||
&stepMarkAsTemplate{
|
NewStepMarkAsTemplate(artifact.Id(), source),
|
||||||
VMName: artifact.Id(),
|
|
||||||
Source: source,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
runner := common.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state)
|
runner := common.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state)
|
||||||
runner.Run(state)
|
runner.Run(state)
|
||||||
|
|
|
@ -13,8 +13,30 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepMarkAsTemplate struct {
|
type stepMarkAsTemplate struct {
|
||||||
VMName string
|
VMName string
|
||||||
Source string
|
Source string
|
||||||
|
RemoteFolder string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStepMarkAsTemplate(vmname, source string) *stepMarkAsTemplate {
|
||||||
|
remoteFolder := "Discovered virtual machine"
|
||||||
|
|
||||||
|
if strings.Contains(vmname, "::") {
|
||||||
|
local := strings.Split(vmname, "::")
|
||||||
|
|
||||||
|
datastore := local[0]
|
||||||
|
remoteFolder = local[1]
|
||||||
|
vmname = local[2]
|
||||||
|
|
||||||
|
source = path.Join("/vmfs/volumes/", datastore, vmname, path.Base(source))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &stepMarkAsTemplate{
|
||||||
|
VMName: vmname,
|
||||||
|
Source: source,
|
||||||
|
RemoteFolder: remoteFolder,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
@ -25,7 +47,7 @@ func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction
|
||||||
|
|
||||||
ui.Message("Marking as a template...")
|
ui.Message("Marking as a template...")
|
||||||
|
|
||||||
vm, err := findRuntimeVM(cli, dcPath, s.VMName)
|
vm, err := findRuntimeVM(cli, dcPath, s.VMName, s.RemoteFolder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
@ -75,10 +97,10 @@ func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
// We will use the virtual machine created by vmware-iso builder
|
// We will use the virtual machine created/uploaded by vmware builder (remote or local)
|
||||||
func findRuntimeVM(cli *govmomi.Client, dcPath, name string) (*object.VirtualMachine, error) {
|
func findRuntimeVM(cli *govmomi.Client, dcPath, name, remoteFolder string) (*object.VirtualMachine, error) {
|
||||||
si := object.NewSearchIndex(cli.Client)
|
si := object.NewSearchIndex(cli.Client)
|
||||||
fullPath := path.Join(dcPath, "vm", "Discovered virtual machine", name)
|
fullPath := path.Join(dcPath, "vm", remoteFolder, name)
|
||||||
|
|
||||||
ref, err := si.FindByInventoryPath(context.Background(), fullPath)
|
ref, err := si.FindByInventoryPath(context.Background(), fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package vsphere
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const BuilderId = "packer.post-processor.vsphere"
|
||||||
|
|
||||||
|
type Artifact struct {
|
||||||
|
files []string
|
||||||
|
datastore string
|
||||||
|
vmfolder string
|
||||||
|
vmname string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Artifact) BuilderId() string {
|
||||||
|
return BuilderId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Artifact) Files() []string {
|
||||||
|
return a.files
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Artifact) Id() string {
|
||||||
|
return fmt.Sprintf("%s::%s::%s", a.datastore, a.vmfolder, a.vmname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Artifact) String() string {
|
||||||
|
return fmt.Sprintf("VM: %s Folder: %s Datastore: %s", a.vmname, a.vmfolder, a.datastore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Artifact) State(name string) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Artifact) Destroy() error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -142,7 +142,14 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
||||||
return nil, false, fmt.Errorf("Failed: %s\n", err)
|
return nil, false, fmt.Errorf("Failed: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return artifact, false, nil
|
artifact = &Artifact{
|
||||||
|
datastore: p.config.Datastore,
|
||||||
|
files: artifact.Files(),
|
||||||
|
vmfolder: p.config.VMFolder,
|
||||||
|
vmname: p.config.VMName,
|
||||||
|
}
|
||||||
|
|
||||||
|
return artifact, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostProcessor) BuildArgs(source, ovftool_uri string) ([]string, error) {
|
func (p *PostProcessor) BuildArgs(source, ovftool_uri string) ([]string, error) {
|
||||||
|
|
Loading…
Reference in New Issue