diff --git a/post-processor/vsphere-template/post-processor.go b/post-processor/vsphere-template/post-processor.go index 86c9f54b4..8b0918b05 100644 --- a/post-processor/vsphere-template/post-processor.go +++ b/post-processor/vsphere-template/post-processor.go @@ -88,13 +88,6 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) } - source := "" - for _, path := range artifact.Files() { - if strings.HasSuffix(path, ".vmx") { - source = path - break - } - } // 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. ui.Message("Waiting 10s for VMware vSphere to start") @@ -119,12 +112,10 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac }, &stepMarkAsTemplate{ VMName: artifact.Id(), - Source: source, }, } runner := common.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state) runner.Run(state) - if rawErr, ok := state.GetOk("error"); ok { return nil, false, rawErr.(error) } diff --git a/post-processor/vsphere-template/step_mark_as_template.go b/post-processor/vsphere-template/step_mark_as_template.go index 0e5465054..f5d362e6f 100644 --- a/post-processor/vsphere-template/step_mark_as_template.go +++ b/post-processor/vsphere-template/step_mark_as_template.go @@ -4,17 +4,18 @@ import ( "context" "fmt" "path" + "regexp" "strings" "github.com/hashicorp/packer/packer" "github.com/mitchellh/multistep" "github.com/vmware/govmomi" "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/types" ) type stepMarkAsTemplate struct { VMName string - Source string } func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction { @@ -32,34 +33,33 @@ func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction return multistep.ActionHalt } - host, err := vm.HostSystem(context.Background()) - if err != nil { + if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } - if err := vm.Unregister(context.Background()); err != nil { + path, err := datastorePath(vm, s.VMName) + if err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } - source := strings.Split(s.Source, "/vmfs/volumes/")[1] - i := strings.Index(source, "/") - - path := (&object.DatastorePath{ - Datastore: source[:i], - Path: source[i:], - }).String() + host, err := vm.HostSystem(context.Background()) + if err != nil { + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } - if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil { + if err := vm.Unregister(context.Background()); err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } - task, err := folder.RegisterVM(context.Background(), path, s.VMName, true, nil, host) + task, err := folder.RegisterVM(context.Background(), path.String(), s.VMName, true, nil, host) if err != nil { state.Put("error", err) ui.Error(err.Error()) @@ -75,6 +75,34 @@ func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction return multistep.ActionContinue } +func datastorePath(vm *object.VirtualMachine, name string) (*object.DatastorePath, error) { + devices, err := vm.Device(context.Background()) + if err != nil { + return nil, err + } + + disk := "" + for _, device := range devices { + if d, ok := device.(*types.VirtualDisk); ok { + if b, ok := d.Backing.(types.BaseVirtualDeviceFileBackingInfo); ok { + disk = b.GetVirtualDeviceFileBackingInfo().FileName + } + break + } + } + + if disk == "" { + return nil, fmt.Errorf("disk not found in '%v'", name) + } + + re := regexp.MustCompile("\\[(.*?)\\]") + + datastore := re.FindStringSubmatch(disk)[1] + vmx := path.Join("/", path.Dir(strings.Split(disk, " ")[1]), name+".vmx") + + return &object.DatastorePath{datastore, vmx}, nil +} + // We will use the virtual machine created by vmware-iso builder func findRuntimeVM(cli *govmomi.Client, dcPath, name string) (*object.VirtualMachine, error) { si := object.NewSearchIndex(cli.Client)