Merge pull request #5380 from bennu/local-vsphere-template
enable vsphere-template post processor to work with local builders
This commit is contained in:
commit
0935ba3e9d
|
@ -13,12 +13,14 @@ import (
|
|||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/post-processor/vsphere"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/vmware/govmomi"
|
||||
)
|
||||
|
||||
var builtins = map[string]string{
|
||||
"mitchellh.vmware-esx": "vmware",
|
||||
vsphere.BuilderId: "vmware",
|
||||
iso.BuilderIdESX: "vmware",
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
@ -120,9 +122,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
|||
&stepCreateFolder{
|
||||
Folder: p.config.Folder,
|
||||
},
|
||||
&stepMarkAsTemplate{
|
||||
VMName: artifact.Id(),
|
||||
},
|
||||
NewStepMarkAsTemplate(artifact),
|
||||
}
|
||||
runner := common.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state)
|
||||
runner.Run(state)
|
||||
|
|
|
@ -9,13 +9,31 @@ import (
|
|||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/post-processor/vsphere"
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type stepMarkAsTemplate struct {
|
||||
VMName string
|
||||
VMName string
|
||||
RemoteFolder string
|
||||
}
|
||||
|
||||
func NewStepMarkAsTemplate(artifact packer.Artifact) *stepMarkAsTemplate {
|
||||
remoteFolder := "Discovered virtual machine"
|
||||
vmname := artifact.Id()
|
||||
|
||||
if artifact.BuilderId() == vsphere.BuilderId {
|
||||
id := strings.Split(artifact.Id(), "::")
|
||||
remoteFolder = id[1]
|
||||
vmname = id[2]
|
||||
}
|
||||
|
||||
return &stepMarkAsTemplate{
|
||||
VMName: vmname,
|
||||
RemoteFolder: remoteFolder,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stepMarkAsTemplate) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
|
@ -26,19 +44,13 @@ func (s *stepMarkAsTemplate) Run(_ context.Context, state multistep.StateBag) mu
|
|||
|
||||
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 {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
dsPath, err := datastorePath(vm)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
|
@ -59,6 +71,12 @@ func (s *stepMarkAsTemplate) Run(_ context.Context, state multistep.StateBag) mu
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
task, err := folder.RegisterVM(context.Background(), dsPath.String(), s.VMName, true, nil, host)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
|
@ -106,10 +124,9 @@ func datastorePath(vm *object.VirtualMachine) (*object.DatastorePath, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// We will use the virtual machine created by vmware-iso builder
|
||||
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)
|
||||
fullPath := path.Join(dcPath, "vm", "Discovered virtual machine", name)
|
||||
fullPath := path.Join(dcPath, "vm", remoteFolder, name)
|
||||
|
||||
ref, err := si.FindByInventoryPath(context.Background(), fullPath)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package vsphere
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const BuilderId = "packer.post-processor.vsphere"
|
||||
|
||||
type Artifact struct {
|
||||
files []string
|
||||
datastore string
|
||||
vmfolder string
|
||||
vmname string
|
||||
}
|
||||
|
||||
func NewArtifact(datastore, vmfolder, vmname string, files []string) *Artifact {
|
||||
return &Artifact{
|
||||
files: files,
|
||||
datastore: datastore,
|
||||
vmfolder: vmfolder,
|
||||
vmname: vmname,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package vsphere
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArtifact_ImplementsArtifact(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Artifact{}
|
||||
if _, ok := raw.(packer.Artifact); !ok {
|
||||
t.Fatalf("Artifact should be a Artifact")
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifact_Id(t *testing.T) {
|
||||
artifact := NewArtifact("datastore", "vmfolder", "vmname", nil)
|
||||
if artifact.Id() != "datastore::vmfolder::vmname" {
|
||||
t.Fatalf("must return datastore, vmfolder and vmname splitted by :: as Id")
|
||||
}
|
||||
}
|
|
@ -140,6 +140,8 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
|||
|
||||
ui.Message(p.filterLog(out.String()))
|
||||
|
||||
artifact = NewArtifact(p.config.Datastore, p.config.VMFolder, p.config.VMName, artifact.Files())
|
||||
|
||||
return artifact, false, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: |
|
||||
The Packer vSphere Template post-processor takes an artifact from the VMware-iso builder built on ESXi (i.e. remote)
|
||||
and allows to mark a VM as a template and leaving it in a path of choice.
|
||||
The Packer vSphere Template post-processor takes an artifact from the VMware-iso builder, built on ESXi (i.e. remote)
|
||||
or an artifact from the vSphere post-processor and allows to mark a VM as a template and leaving it in a path of choice.
|
||||
layout: docs
|
||||
page_title: 'vSphere Template - Post-Processors'
|
||||
sidebar_current: 'docs-post-processors-vSphere-template'
|
||||
|
@ -11,8 +11,9 @@ sidebar_current: 'docs-post-processors-vSphere-template'
|
|||
|
||||
Type: `vsphere-template`
|
||||
|
||||
The Packer vSphere template post-processor takes an artifact from the VMware-iso builder built on ESXi (i.e. remote) and
|
||||
allows to mark a VM as a template and leaving it in a path of choice.
|
||||
The Packer vSphere Template post-processor takes an artifact from the VMware-iso builder, built on ESXi (i.e. remote)
|
||||
or an artifact from the [vSphere](/docs/post-processors/vsphere.html) post-processor and allows to mark a VM as a
|
||||
template and leaving it in a path of choice.
|
||||
|
||||
## Example
|
||||
|
||||
|
@ -51,3 +52,31 @@ Optional:
|
|||
- `folder` (string) - Target path where the template will be created.
|
||||
|
||||
- `insecure` (boolean) - If it's true skip verification of server certificate. Default is false
|
||||
|
||||
## Using the vSphere Template with local builders
|
||||
|
||||
Once the [vSphere](/docs/post-processors/vsphere.html) takes an artifact from the VMware builder and uploads it
|
||||
to a vSphere endpoint, you will likely want to mark that VM as template. Packer can do this for you automatically
|
||||
using a sequence definition (a collection of post-processors that are treated as as single pipeline, see
|
||||
[Post-Processors](/docs/templates/post-processors.html) for more information):
|
||||
|
||||
``` json
|
||||
{
|
||||
"post-processors": [
|
||||
[
|
||||
{
|
||||
"type": "vsphere",
|
||||
...
|
||||
},
|
||||
{
|
||||
"type": "vsphere-template",
|
||||
...
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
In the example above, the result of each builder is passed through the defined sequence of post-processors starting
|
||||
with the `vsphere` post-processor which will upload the artifact to a vSphere endpoint. The resulting artifact is then
|
||||
passed on to the `vsphere-template` post-processor which handles marking a VM as a template.
|
||||
|
|
Loading…
Reference in New Issue