Changes requested applied
This commit is contained in:
parent
2ddc07d3b9
commit
fa10616f57
|
@ -25,7 +25,7 @@ type Config struct {
|
|||
Insecure bool `mapstructure:"insecure"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
Datacenter string `mapstructure:"datacenter"`
|
||||
Datacenter string `mapstructure:"Datacenter"`
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
Folder string `mapstructure:"folder"`
|
||||
|
||||
|
@ -64,11 +64,20 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := p.configureURL(); err != nil {
|
||||
if p.config.Folder != "" && !strings.HasPrefix(p.config.Folder, "/") {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, err)
|
||||
errs, fmt.Errorf("Folder must be bound to the root"))
|
||||
}
|
||||
|
||||
sdk, err := url.Parse(fmt.Sprintf("https://%v/sdk", p.config.Host))
|
||||
if err != nil {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, fmt.Errorf("Error invalid vSphere sdk endpoint: %s", err))
|
||||
}
|
||||
|
||||
sdk.User = url.UserPassword(p.config.Username, p.config.Password)
|
||||
p.url = sdk
|
||||
|
||||
if len(errs.Errors) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
@ -77,7 +86,7 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
|||
|
||||
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
|
||||
if _, ok := builtins[artifact.BuilderId()]; !ok {
|
||||
return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId())
|
||||
return nil, false, fmt.Errorf("Unknown artifact type, can't build template: %s", artifact.BuilderId())
|
||||
}
|
||||
|
||||
source := ""
|
||||
|
@ -87,34 +96,33 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
|||
break
|
||||
}
|
||||
}
|
||||
//We give a vSphere-ESXI 10s to sync
|
||||
// In some occasions when the VM is mark as template it loses its configuration if it's done immediately
|
||||
// after the ESXi creates it. If vSphere is given a few seconds this behavior doesn't reappear.
|
||||
ui.Message("Waiting 10s for VMWare vSphere to start")
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
ctx := context.Background()
|
||||
c, err := govmomi.NewClient(ctx, p.url, p.config.Insecure)
|
||||
c, err := govmomi.NewClient(context.Background(), p.url, p.config.Insecure)
|
||||
if err != nil {
|
||||
return artifact, true, fmt.Errorf("Error trying to connect: %s", err)
|
||||
return nil, true, fmt.Errorf("Error connecting to vSphere: %s", err)
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", ui)
|
||||
state.Put("context", ctx)
|
||||
state.Put("client", c)
|
||||
|
||||
steps := []multistep.Step{
|
||||
&StepChooseDatacenter{
|
||||
&stepChooseDatacenter{
|
||||
Datacenter: p.config.Datacenter,
|
||||
},
|
||||
&StepFetchVm{
|
||||
&stepFetchVm{
|
||||
VMName: p.config.VMName,
|
||||
Source: source,
|
||||
},
|
||||
&StepCreateFolder{
|
||||
&stepCreateFolder{
|
||||
Folder: p.config.Folder,
|
||||
},
|
||||
&StepMarkAsTemplate{},
|
||||
&StepMoveTemplate{
|
||||
&stepMarkAsTemplate{},
|
||||
&stepMoveTemplate{
|
||||
Folder: p.config.Folder,
|
||||
},
|
||||
}
|
||||
|
@ -123,18 +131,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
|||
runner.Run(state)
|
||||
|
||||
if rawErr, ok := state.GetOk("error"); ok {
|
||||
return artifact, true, rawErr.(error)
|
||||
return nil, true, rawErr.(error)
|
||||
}
|
||||
return artifact, true, nil
|
||||
}
|
||||
|
||||
func (p *PostProcessor) configureURL() error {
|
||||
sdk, err := url.Parse(fmt.Sprintf("https://%v/sdk", p.config.Host))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sdk.User = url.UserPassword(p.config.Username, p.config.Password)
|
||||
p.url = sdk
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package vsphere_template
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConfigureURL(t *testing.T) {
|
||||
var p PostProcessor
|
||||
p.config.Username = "me"
|
||||
p.config.Password = "notpassword"
|
||||
p.config.Host = "myhost"
|
||||
p.config.Datacenter = "mydc"
|
||||
p.config.VMName = "my vm"
|
||||
p.config.Insecure = true
|
||||
|
||||
if err := p.configureURL(); err != nil {
|
||||
t.Errorf("Error: %s", err)
|
||||
}
|
||||
}
|
|
@ -9,17 +9,16 @@ import (
|
|||
"github.com/vmware/govmomi/find"
|
||||
)
|
||||
|
||||
type StepChooseDatacenter struct {
|
||||
type stepChooseDatacenter struct {
|
||||
Datacenter string
|
||||
}
|
||||
|
||||
func (s *StepChooseDatacenter) Run(state multistep.StateBag) multistep.StepAction {
|
||||
func (s *stepChooseDatacenter) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
cli := state.Get("client").(*govmomi.Client)
|
||||
ctx := state.Get("context").(context.Context)
|
||||
finder := find.NewFinder(cli.Client, false)
|
||||
|
||||
datacenter, err := finder.DatacenterOrDefault(ctx, s.Datacenter)
|
||||
datacenter, err := finder.DatacenterOrDefault(context.Background(), s.Datacenter)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
@ -28,9 +27,9 @@ func (s *StepChooseDatacenter) Run(state multistep.StateBag) multistep.StepActio
|
|||
}
|
||||
|
||||
finder.SetDatacenter(datacenter)
|
||||
state.Put("datacenter", datacenter.Name())
|
||||
state.Put("Datacenter", datacenter.Name())
|
||||
state.Put("finder", finder)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepChooseDatacenter) Cleanup(multistep.StateBag) {}
|
||||
func (s *stepChooseDatacenter) Cleanup(multistep.StateBag) {}
|
||||
|
|
|
@ -12,36 +12,33 @@ import (
|
|||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type StepCreateFolder struct {
|
||||
type stepCreateFolder struct {
|
||||
Folder string
|
||||
}
|
||||
|
||||
func (s *StepCreateFolder) Run(state multistep.StateBag) multistep.StepAction {
|
||||
func (s *stepCreateFolder) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ctx := state.Get("context").(context.Context)
|
||||
f := state.Get("finder").(*find.Finder)
|
||||
d := state.Get("datacenter").(string)
|
||||
finder := state.Get("finder").(*find.Finder)
|
||||
dc := state.Get("Datacenter").(string)
|
||||
|
||||
if s.Folder != "" {
|
||||
ui.Say("Creating or checking destination folders...")
|
||||
|
||||
if !strings.HasPrefix(s.Folder, "/") {
|
||||
s.Folder = filepath.Join("/", s.Folder)
|
||||
}
|
||||
|
||||
path := s.Folder
|
||||
base := filepath.Join("/", d, "vm")
|
||||
base := filepath.Join("/", dc, "vm")
|
||||
var folders []string
|
||||
var root *object.Folder
|
||||
var err error
|
||||
|
||||
// We iterate over the path starting with full path
|
||||
// If we don't find it, we save the folder name and continue with the previous path
|
||||
// The iteration ends when we find an existing path
|
||||
for {
|
||||
root, err = f.Folder(ctx, filepath.ToSlash(filepath.Join(base, path)))
|
||||
root, err = finder.Folder(context.Background(), filepath.ToSlash(filepath.Join(base, path)))
|
||||
if err != nil {
|
||||
_, folder := filepath.Split(path)
|
||||
folders = append(folders, folder)
|
||||
if i := strings.LastIndex(path, "/"); i == 0 {
|
||||
root, err = f.Folder(ctx, filepath.ToSlash(base))
|
||||
root, err = finder.Folder(context.Background(), filepath.ToSlash(base))
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
@ -58,7 +55,7 @@ func (s *StepCreateFolder) Run(state multistep.StateBag) multistep.StepAction {
|
|||
|
||||
for i := len(folders) - 1; i >= 0; i-- {
|
||||
ui.Message(fmt.Sprintf("Creating folder: %v", folders[i]))
|
||||
root, err = root.CreateFolder(ctx, folders[i])
|
||||
root, err = root.CreateFolder(context.Background(), folders[i])
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
@ -69,4 +66,4 @@ func (s *StepCreateFolder) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateFolder) Cleanup(multistep.StateBag) {}
|
||||
func (s *stepCreateFolder) Cleanup(multistep.StateBag) {}
|
||||
|
|
|
@ -9,19 +9,18 @@ import (
|
|||
"github.com/vmware/govmomi/find"
|
||||
)
|
||||
|
||||
type StepFetchVm struct {
|
||||
type stepFetchVm struct {
|
||||
VMName string
|
||||
Source string
|
||||
}
|
||||
|
||||
func (s *StepFetchVm) Run(state multistep.StateBag) multistep.StepAction {
|
||||
func (s *stepFetchVm) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ctx := state.Get("context").(context.Context)
|
||||
f := state.Get("finder").(*find.Finder)
|
||||
|
||||
ui.Say("Fetching VM...")
|
||||
|
||||
if err := avoidOrphaned(ctx, f, s.VMName); err != nil {
|
||||
if err := avoidOrphaned(f, s.VMName); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -32,41 +31,41 @@ func (s *StepFetchVm) Run(state multistep.StateBag) multistep.StepAction {
|
|||
storage := path[:i]
|
||||
vmx := path[i:]
|
||||
|
||||
ds, err := f.DatastoreOrDefault(ctx, storage)
|
||||
ds, err := f.DatastoreOrDefault(context.Background(), storage)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
folder, err := f.DefaultFolder(ctx)
|
||||
folder, err := f.DefaultFolder(context.Background())
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
pool, err := f.DefaultResourcePool(ctx)
|
||||
pool, err := f.DefaultResourcePool(context.Background())
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
task, err := folder.RegisterVM(ctx, ds.Path(vmx), s.VMName, false, pool, nil)
|
||||
task, err := folder.RegisterVM(context.Background(), ds.Path(vmx), s.VMName, false, pool, nil)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err = task.Wait(ctx); err != nil {
|
||||
if err = task.Wait(context.Background()); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
vm, err := f.VirtualMachine(ctx, s.VMName)
|
||||
vm, err := f.VirtualMachine(context.Background(), s.VMName)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
@ -77,13 +76,13 @@ func (s *StepFetchVm) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// When ESXI remove the VM, vSphere keep the VM as orphaned
|
||||
func avoidOrphaned(ctx context.Context, f *find.Finder, vm_name string) error {
|
||||
vm, err := f.VirtualMachine(ctx, vm_name)
|
||||
// When ESXi remove the VM, vSphere keep the VM as orphaned
|
||||
func avoidOrphaned(f *find.Finder, vm_name string) error {
|
||||
vm, err := f.VirtualMachine(context.Background(), vm_name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return vm.Unregister(ctx)
|
||||
return vm.Unregister(context.Background())
|
||||
}
|
||||
|
||||
func (s *StepFetchVm) Cleanup(multistep.StateBag) {}
|
||||
func (s *stepFetchVm) Cleanup(multistep.StateBag) {}
|
||||
|
|
|
@ -8,16 +8,15 @@ import (
|
|||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type StepMarkAsTemplate struct{}
|
||||
type stepMarkAsTemplate struct{}
|
||||
|
||||
func (s *StepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
||||
func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ctx := state.Get("context").(context.Context)
|
||||
vm := state.Get("vm").(*object.VirtualMachine)
|
||||
|
||||
ui.Say("Marking as a template...")
|
||||
|
||||
if err := vm.MarkAsTemplate(ctx); err != nil {
|
||||
if err := vm.MarkAsTemplate(context.Background()); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -25,4 +24,4 @@ func (s *StepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepMarkAsTemplate) Cleanup(multistep.StateBag) {}
|
||||
func (s *stepMarkAsTemplate) Cleanup(multistep.StateBag) {}
|
||||
|
|
|
@ -11,21 +11,20 @@ import (
|
|||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type StepMoveTemplate struct {
|
||||
type stepMoveTemplate struct {
|
||||
Folder string
|
||||
}
|
||||
|
||||
func (s *StepMoveTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
||||
func (s *stepMoveTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ctx := state.Get("context").(context.Context)
|
||||
finder := state.Get("finder").(*find.Finder)
|
||||
d := state.Get("datacenter").(string)
|
||||
dc := state.Get("Datacenter").(string)
|
||||
vm := state.Get("vm").(*object.VirtualMachine)
|
||||
|
||||
if s.Folder != "" {
|
||||
ui.Say("Moving template...")
|
||||
|
||||
folder, err := finder.Folder(ctx, filepath.ToSlash(filepath.Join("/", d, "vm", s.Folder)))
|
||||
folder, err := finder.Folder(context.Background(), filepath.ToSlash(filepath.Join("/", dc, "vm", s.Folder)))
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
@ -33,13 +32,13 @@ func (s *StepMoveTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
task, err := folder.MoveInto(ctx, []types.ManagedObjectReference{vm.Reference()})
|
||||
task, err := folder.MoveInto(context.Background(), []types.ManagedObjectReference{vm.Reference()})
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
if err = task.Wait(ctx); err != nil {
|
||||
if err = task.Wait(context.Background()); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -48,4 +47,4 @@ func (s *StepMoveTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepMoveTemplate) Cleanup(multistep.StateBag) {}
|
||||
func (s *stepMoveTemplate) Cleanup(multistep.StateBag) {}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
description: |
|
||||
The Packer vSphere Template post-processor takes an artifact from the VMware-iso builder -**only if remote ESXI was chosen**-
|
||||
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.
|
||||
layout: docs
|
||||
page_title: 'vSphere Template - Post-Processors'
|
||||
|
@ -11,7 +11,7 @@ sidebar_current: 'docs-post-processors-vSphere-template'
|
|||
|
||||
Type: `vsphere-template`
|
||||
|
||||
The Packer vSphere template post-processor takes an artifact from the VMware-iso builder -**only if remote ESXI was chosen**-
|
||||
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.
|
||||
|
||||
## Example
|
||||
|
@ -22,11 +22,12 @@ An example is shown below, showing only the post-processor configuration:
|
|||
{
|
||||
"type": "vsphere-template",
|
||||
"host": "vcenter.local",
|
||||
"insecure": true,
|
||||
"username": "root",
|
||||
"password": "secret",
|
||||
"datacenter": "murlock",
|
||||
"password": "secret",
|
||||
"vm_name": "distro-7.3",
|
||||
"folder": "/packer-templates/os/distro-7"
|
||||
"datacenter": "mydatacenter",
|
||||
"folder": "/packer-templates/os/distro-7"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -53,6 +54,6 @@ Required:
|
|||
|
||||
Optional:
|
||||
|
||||
- `datacenter` (string) - If you have more than one, you will need to specify which one the ESXi used.
|
||||
|
||||
- `folder` (string) - Target path where the template will be created.
|
||||
|
||||
- `datacenter` (string) - If you have more than one, you will need to specify which one the ESXI used.
|
||||
|
|
Loading…
Reference in New Issue