Merge pull request #5380 from bennu/local-vsphere-template

enable vsphere-template post processor to work with local builders
This commit is contained in:
Matthew Hooker 2018-02-09 13:01:36 -08:00 committed by GitHub
commit 0935ba3e9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 20 deletions

View File

@ -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)

View File

@ -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 {

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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
@ -50,4 +51,32 @@ 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
- `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.