github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/post-processor/vsphere-template/step_mark_as_template.go (about)

     1  package vsphere_template
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/packer/packer"
    10  	"github.com/mitchellh/multistep"
    11  	"github.com/vmware/govmomi"
    12  	"github.com/vmware/govmomi/object"
    13  )
    14  
    15  type stepMarkAsTemplate struct {
    16  	VMName string
    17  	Source string
    18  }
    19  
    20  func (s *stepMarkAsTemplate) Run(state multistep.StateBag) multistep.StepAction {
    21  	ui := state.Get("ui").(packer.Ui)
    22  	cli := state.Get("client").(*govmomi.Client)
    23  	folder := state.Get("folder").(*object.Folder)
    24  	dcPath := state.Get("dcPath").(string)
    25  
    26  	ui.Message("Marking as a template...")
    27  
    28  	vm, err := findRuntimeVM(cli, dcPath, s.VMName)
    29  	if err != nil {
    30  		state.Put("error", err)
    31  		ui.Error(err.Error())
    32  		return multistep.ActionHalt
    33  	}
    34  
    35  	host, err := vm.HostSystem(context.Background())
    36  	if err != nil {
    37  		state.Put("error", err)
    38  		ui.Error(err.Error())
    39  		return multistep.ActionHalt
    40  	}
    41  
    42  	if err := vm.Unregister(context.Background()); err != nil {
    43  		state.Put("error", err)
    44  		ui.Error(err.Error())
    45  		return multistep.ActionHalt
    46  	}
    47  
    48  	source := strings.Split(s.Source, "/vmfs/volumes/")[1]
    49  	i := strings.Index(source, "/")
    50  
    51  	path := (&object.DatastorePath{
    52  		Datastore: source[:i],
    53  		Path:      source[i:],
    54  	}).String()
    55  
    56  	if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil {
    57  		state.Put("error", err)
    58  		ui.Error(err.Error())
    59  		return multistep.ActionHalt
    60  	}
    61  
    62  	task, err := folder.RegisterVM(context.Background(), path, s.VMName, true, nil, host)
    63  	if err != nil {
    64  		state.Put("error", err)
    65  		ui.Error(err.Error())
    66  		return multistep.ActionHalt
    67  	}
    68  
    69  	if err = task.Wait(context.Background()); err != nil {
    70  		state.Put("error", err)
    71  		ui.Error(err.Error())
    72  		return multistep.ActionHalt
    73  	}
    74  
    75  	return multistep.ActionContinue
    76  }
    77  
    78  // We will use the virtual machine created by vmware-iso builder
    79  func findRuntimeVM(cli *govmomi.Client, dcPath, name string) (*object.VirtualMachine, error) {
    80  	si := object.NewSearchIndex(cli.Client)
    81  	fullPath := path.Join(dcPath, "vm", "Discovered virtual machine", name)
    82  
    83  	ref, err := si.FindByInventoryPath(context.Background(), fullPath)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	if ref == nil {
    89  		return nil, fmt.Errorf("VM at path %s not found", fullPath)
    90  	}
    91  
    92  	return ref.(*object.VirtualMachine), nil
    93  }
    94  
    95  // If in the target folder a virtual machine or template already exists
    96  // it will be removed to maintain consistency
    97  func unregisterPreviousVM(cli *govmomi.Client, folder *object.Folder, name string) error {
    98  	si := object.NewSearchIndex(cli.Client)
    99  	fullPath := path.Join(folder.InventoryPath, name)
   100  
   101  	ref, err := si.FindByInventoryPath(context.Background(), fullPath)
   102  	if err != nil {
   103  		return err
   104  	}
   105  
   106  	if ref != nil {
   107  		if vm, ok := ref.(*object.VirtualMachine); ok {
   108  			return vm.Unregister(context.Background())
   109  		} else {
   110  			return fmt.Errorf("an object name '%v' already exists", name)
   111  		}
   112  
   113  	}
   114  
   115  	return nil
   116  }
   117  
   118  func (s *stepMarkAsTemplate) Cleanup(multistep.StateBag) {}