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/config"
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
"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/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 {
|
||||||
|
@ -120,9 +122,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),
|
||||||
VMName: artifact.Id(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
runner := common.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state)
|
runner := common.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state)
|
||||||
runner.Run(state)
|
runner.Run(state)
|
||||||
|
|
|
@ -9,13 +9,31 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
|
"github.com/hashicorp/packer/post-processor/vsphere"
|
||||||
"github.com/vmware/govmomi"
|
"github.com/vmware/govmomi"
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/vmware/govmomi/object"
|
||||||
"github.com/vmware/govmomi/vim25/types"
|
"github.com/vmware/govmomi/vim25/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepMarkAsTemplate struct {
|
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 {
|
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...")
|
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())
|
||||||
return multistep.ActionHalt
|
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)
|
dsPath, err := datastorePath(vm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -59,6 +71,12 @@ func (s *stepMarkAsTemplate) Run(_ context.Context, state multistep.StateBag) mu
|
||||||
return multistep.ActionHalt
|
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)
|
task, err := folder.RegisterVM(context.Background(), dsPath.String(), s.VMName, true, nil, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -106,10 +124,9 @@ func datastorePath(vm *object.VirtualMachine) (*object.DatastorePath, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We will use the virtual machine created by vmware-iso builder
|
func findRuntimeVM(cli *govmomi.Client, dcPath, name, remoteFolder string) (*object.VirtualMachine, error) {
|
||||||
func findRuntimeVM(cli *govmomi.Client, dcPath, name 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,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()))
|
ui.Message(p.filterLog(out.String()))
|
||||||
|
|
||||||
|
artifact = NewArtifact(p.config.Datastore, p.config.VMFolder, p.config.VMName, artifact.Files())
|
||||||
|
|
||||||
return artifact, false, nil
|
return artifact, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
description: |
|
description: |
|
||||||
The Packer vSphere Template post-processor takes an artifact from the VMware-iso builder built on ESXi (i.e. remote)
|
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.
|
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
|
layout: docs
|
||||||
page_title: 'vSphere Template - Post-Processors'
|
page_title: 'vSphere Template - Post-Processors'
|
||||||
sidebar_current: 'docs-post-processors-vSphere-template'
|
sidebar_current: 'docs-post-processors-vSphere-template'
|
||||||
|
@ -11,8 +11,9 @@ sidebar_current: 'docs-post-processors-vSphere-template'
|
||||||
|
|
||||||
Type: `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
|
The Packer vSphere Template post-processor takes an artifact from the VMware-iso builder, built on ESXi (i.e. remote)
|
||||||
allows to mark a VM as a template and leaving it in a path of choice.
|
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
|
## Example
|
||||||
|
|
||||||
|
@ -50,4 +51,32 @@ Optional:
|
||||||
|
|
||||||
- `folder` (string) - Target path where the template will be created.
|
- `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.
|
||||||
|
|
Loading…
Reference in New Issue