diff --git a/config.go b/config.go index 2dbc13c4a..c7cb5f3ed 100644 --- a/config.go +++ b/config.go @@ -19,15 +19,19 @@ type Config struct { Username string `mapstructure:"username"` Password string `mapstructure:"password"` - Template string `mapstructure:"template"` - VMName string `mapstructure:"vm_name"` - FolderName string `mapstructure:"folder_name"` - DCName string `mapstructure:"dc_name"` + // Location + Template string `mapstructure:"template"` + VMName string `mapstructure:"vm_name"` + FolderName string `mapstructure:"folder_name"` + DCName string `mapstructure:"dc_name"` + Host string `mapstructure:"host"` + ResourcePool string `mapstructure:"resource_pool"` + Datastore string `mapstructure:"datastore"` + // Hardware Cpus string `mapstructure:"cpus"` ShutdownCommand string `mapstructure:"shutdown_command"` Ram string `mapstructure:"RAM"` - //TODO: add more options ctx interpolate.Context } @@ -64,6 +68,9 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { if c.VMName == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Target VM name required")) } + if c.Host == "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("Target host required")) + } // Verify numeric parameters if present if c.Cpus != "" { @@ -79,6 +86,9 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { // Warnings var warnings []string + if c.Datastore == "" { + warnings = append(warnings, "Datastore is not specified, will try to find a default one") + } if len(errs.Errors) > 0 { return nil, warnings, errs diff --git a/glide.lock b/glide.lock deleted file mode 100644 index d4f6dda26..000000000 --- a/glide.lock +++ /dev/null @@ -1,101 +0,0 @@ -hash: 9caf4a309ee0ce30e273ceb77d66b9b49090765e1f0dcbe6e05ce0da88b1435f -updated: 2017-05-16T08:15:30.457888159+03:00 -imports: -- name: github.com/Azure/go-ntlmssp - version: 29affced641074a59483ed003b5ef73a8bd3593c -- name: github.com/dylanmei/iso8601 - version: 2075bf119b58e5576c6ed9f867b8f3d17f2e54d4 -- name: github.com/hashicorp/errwrap - version: 7554cd9344cec97297fa6649b055a8c98c2a1e55 -- name: github.com/hashicorp/go-multierror - version: ed905158d87462226a13fe39ddf685ea65f1c11f -- name: github.com/hashicorp/go-version - version: 03c5bf6be031b6dd45afec16b1cf94fc8938bc77 -- name: github.com/hashicorp/packer - version: 45a48132d0c455f777163538002aeb8784b64e50 - subpackages: - - common - - common/ssh - - common/uuid - - communicator/none - - communicator/ssh - - communicator/winrm - - helper/communicator - - helper/config - - packer - - packer/plugin - - packer/rpc - - template - - template/interpolate -- name: github.com/hashicorp/yamux - version: d1caa6c97c9fc1cc9e83bbe34d0603f9ff0ce8bd -- name: github.com/kr/fs - version: 2788f0dbd16903de03cb8186e5c7d97b69ad387b -- name: github.com/masterzen/azure-sdk-for-go - version: ee4f0065d00cd12b542f18f5bc45799e88163b12 - subpackages: - - core/http - - core/tls -- name: github.com/masterzen/simplexml - version: 4572e39b1ab9fe03ee513ce6fc7e289e98482190 - subpackages: - - dom -- name: github.com/masterzen/winrm - version: acf371f6aff113fc0104a61cd72db45a7c27d310 - subpackages: - - soap -- name: github.com/masterzen/xmlpath - version: 13f4951698adc0fa9c1dda3e275d489a24201161 -- name: github.com/mitchellh/go-fs - version: 7bae45d9a684750e82b97ff320c82556614e621b - subpackages: - - fat -- name: github.com/mitchellh/iochan - version: 87b45ffd0e9581375c491fef3d32130bb15c5bd7 -- name: github.com/mitchellh/mapstructure - version: cc8532a8e9a55ea36402aa21efdf403a60d34096 -- name: github.com/mitchellh/multistep - version: 391576a156a54cfbb4cf5d5eda40cf6ffa3e3a4d -- name: github.com/mitchellh/reflectwalk - version: 8d802ff4ae93611b807597f639c19f76074df5c6 -- name: github.com/nu7hatch/gouuid - version: 179d4d0c4d8d407a32af483c2354df1d2c91e6c3 -- name: github.com/packer-community/winrmcp - version: c804d432b8b7fa77896f43cc426134348c3fd19e - subpackages: - - winrmcp -- name: github.com/pkg/errors - version: c605e284fe17294bda444b34710735b29d1a9d90 -- name: github.com/pkg/sftp - version: a5f8514e29e90a859e93871b1582e5c81f466f82 -- name: github.com/ugorji/go - version: 708a42d246822952f38190a8d8c4e6b16a0e600c - subpackages: - - codec -- name: github.com/vmware/govmomi - version: 9bfdc5ce62c0585b48b154cc460f8664dcd124c3 - subpackages: - - find - - list - - object - - property - - session - - task - - vim25 - - vim25/debug - - vim25/methods - - vim25/mo - - vim25/progress - - vim25/soap - - vim25/types - - vim25/xml -- name: golang.org/x/crypto - version: ab89591268e0c8b748cbe4047b00197516011af5 - subpackages: - - curve25519 - - ed25519 - - ed25519/internal/edwards25519 - - md4 - - ssh - - ssh/agent -testImports: [] diff --git a/step_clone_vm.go b/step_clone_vm.go index 921b9e696..e3fc04c1b 100644 --- a/step_clone_vm.go +++ b/step_clone_vm.go @@ -13,11 +13,13 @@ import ( ) type CloneParameters struct { - client *govmomi.Client - folder *object.Folder - vmSrc *object.VirtualMachine - ctx context.Context - vmName string + client *govmomi.Client + folder *object.Folder + resourcePool *object.ResourcePool + datastore *object.Datastore + vmSrc *object.VirtualMachine + ctx context.Context + vmName string } type StepCloneVM struct{ @@ -35,31 +37,56 @@ func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { state.Put("error", err) return multistep.ActionHalt } - finder, ctx, err := createFinder(ctx, client, s.config.DCName) + + // Set up finder + finder := find.NewFinder(client.Client, false) + dc, err := finder.DatacenterOrDefault(ctx, s.config.DCName) if err != nil { state.Put("error", err) return multistep.ActionHalt } + finder.SetDatacenter(dc) + + // Get folder folder, err := finder.FolderOrDefault(ctx, s.config.FolderName) if err != nil { state.Put("error", err) return multistep.ActionHalt } + + // Get resource pool + pool, err := finder.ResourcePoolOrDefault(ctx, fmt.Sprintf("/%v/host/%v/Resources/%v", dc.Name(), s.config.Host, s.config.ResourcePool)) + if err != nil { + state.Put("error", err) + return multistep.ActionHalt + } + + // Get datastore + var datastore *object.Datastore = nil + if s.config.Datastore != "" { + datastore, err = finder.Datastore(ctx, s.config.Datastore) + if err != nil { + state.Put("error", err) + return multistep.ActionHalt + } + } + + // Get source VM vmSrc, err := finder.VirtualMachine(ctx, s.config.Template) if err != nil { state.Put("error", err) return multistep.ActionHalt } - cloneParameters := CloneParameters{ - client: client, - folder: folder, - vmSrc: vmSrc, - ctx: ctx, - vmName: s.config.VMName, - } - - vm, err := cloneVM(&cloneParameters) + vm, err := cloneVM(&CloneParameters{ + client: client, + folder: folder, + resourcePool: pool, + datastore: datastore, + vmSrc: vmSrc, + ctx: ctx, + vmName: s.config.VMName, + }) if err != nil { state.Put("error", err) return multistep.ActionHalt @@ -102,9 +129,17 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) { func cloneVM(params *CloneParameters) (vm *object.VirtualMachine, err error) { vm = nil err = nil + poolRef := params.resourcePool.Reference() // Creating specs for cloning - var relocateSpec types.VirtualMachineRelocateSpec + relocateSpec := types.VirtualMachineRelocateSpec{ + Pool: &(poolRef), + } + if params.datastore != nil { + datastoreRef := params.datastore.Reference() + relocateSpec.Datastore = &datastoreRef + } + cloneSpec := types.VirtualMachineCloneSpec{ Location: relocateSpec, PowerOn: false, @@ -145,23 +180,3 @@ func createClient(URL, username, password string) (*govmomi.Client, context.Cont return client, ctx, nil } - -func createFinder(ctx context.Context, client *govmomi.Client, dcName string) (*find.Finder, context.Context, error) { - // Create a finder to search for a vm with the specified name - finder := find.NewFinder(client.Client, false) - // Need to specify the datacenter - if dcName == "" { - dc, err := finder.DefaultDatacenter(ctx) - if err != nil { - return nil, nil, err - } - finder.SetDatacenter(dc) - } else { - dc, err := finder.Datacenter(ctx, dcName) - if err != nil { - return nil, nil, err - } - finder.SetDatacenter(dc) - } - return finder, ctx, nil -}