cloning step uses vSphere driver
This commit is contained in:
parent
1e747c8c93
commit
b7d58590a7
85
driver.go
85
driver.go
|
@ -7,6 +7,9 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/vmware/govmomi/object"
|
||||||
|
"github.com/vmware/govmomi/vim25/types"
|
||||||
|
"github.com/vmware/govmomi/vim25/mo"
|
||||||
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Driver struct {
|
type Driver struct {
|
||||||
|
@ -44,3 +47,85 @@ func NewDriverVSphere(config *ConnectConfig) (Driver, error) {
|
||||||
}
|
}
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Driver) cloneVM(config *CloneConfig) (*object.VirtualMachine, error) {
|
||||||
|
vmSrc, err := d.finder.VirtualMachine(d.ctx, config.Template)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
folder, err := d.finder.FolderOrDefault(d.ctx, fmt.Sprintf("/%v/vm/%v", d.datacenter.Name(), config.FolderName))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, err := d.finder.ResourcePoolOrDefault(d.ctx, fmt.Sprintf("/%v/host/%v/Resources/%v", d.datacenter.Name(), config.Host, config.ResourcePool))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
poolRef := pool.Reference()
|
||||||
|
|
||||||
|
var datastore *object.Datastore
|
||||||
|
if config.Datastore != "" {
|
||||||
|
datastore, err = d.finder.Datastore(d.ctx, config.Datastore)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating specs for cloning
|
||||||
|
relocateSpec := types.VirtualMachineRelocateSpec{
|
||||||
|
Pool: &(poolRef),
|
||||||
|
}
|
||||||
|
if datastore != nil {
|
||||||
|
datastoreRef := datastore.Reference()
|
||||||
|
relocateSpec.Datastore = &datastoreRef
|
||||||
|
}
|
||||||
|
if config.LinkedClone == true {
|
||||||
|
relocateSpec.DiskMoveType = "createNewChildDiskBacking"
|
||||||
|
}
|
||||||
|
|
||||||
|
cloneSpec := types.VirtualMachineCloneSpec{
|
||||||
|
Location: relocateSpec,
|
||||||
|
PowerOn: false,
|
||||||
|
}
|
||||||
|
if config.LinkedClone == true {
|
||||||
|
var vmImage mo.VirtualMachine
|
||||||
|
err = vmSrc.Properties(d.ctx, vmSrc.Reference(), []string{"snapshot"}, &vmImage)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Error reading base VM properties: %s", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if vmImage.Snapshot == nil {
|
||||||
|
err = errors.New("`linked_clone=true`, but image VM has no snapshots")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cloneSpec.Snapshot = vmImage.Snapshot.CurrentSnapshot
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloning itself
|
||||||
|
task, err := vmSrc.Clone(d.ctx, folder, config.VMName, cloneSpec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := task.WaitForResult(d.ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
vm := object.NewVirtualMachine(vmSrc.Client(), info.Result.(types.ManagedObjectReference))
|
||||||
|
return vm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) destroyVM(vm *object.VirtualMachine) error {
|
||||||
|
task, err := vm.Destroy(d.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = task.WaitForResult(d.ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
110
step_clone.go
110
step_clone.go
|
@ -1,14 +1,10 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/vmware/govmomi/vim25/types"
|
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/vmware/govmomi/object"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/vmware/govmomi/vim25/mo"
|
|
||||||
"errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CloneConfig struct {
|
type CloneConfig struct {
|
||||||
|
@ -37,16 +33,6 @@ func (c *CloneConfig) Prepare() []error {
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
type CloneParameters struct {
|
|
||||||
ctx context.Context
|
|
||||||
vmSrc *object.VirtualMachine
|
|
||||||
vmName string
|
|
||||||
folder *object.Folder
|
|
||||||
resourcePool *object.ResourcePool
|
|
||||||
datastore *object.Datastore
|
|
||||||
linkedClone bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type StepCloneVM struct {
|
type StepCloneVM struct {
|
||||||
config *CloneConfig
|
config *CloneConfig
|
||||||
}
|
}
|
||||||
|
@ -55,45 +41,9 @@ func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
d := state.Get("driver").(Driver)
|
d := state.Get("driver").(Driver)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
vmSrc, err := d.finder.VirtualMachine(d.ctx, s.config.Template)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
state.Put("vmSrc", vmSrc)
|
|
||||||
|
|
||||||
ui.Say("Cloning VM...")
|
ui.Say("Cloning VM...")
|
||||||
|
|
||||||
folder, err := d.finder.FolderOrDefault(d.ctx, fmt.Sprintf("/%v/vm/%v", d.datacenter.Name(), s.config.FolderName))
|
vm, err := d.cloneVM(s.config)
|
||||||
if err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
pool, err := d.finder.ResourcePoolOrDefault(d.ctx, fmt.Sprintf("/%v/host/%v/Resources/%v", d.datacenter.Name(), s.config.Host, s.config.ResourcePool))
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
var datastore *object.Datastore
|
|
||||||
if s.config.Datastore != "" {
|
|
||||||
datastore, err = d.finder.Datastore(d.ctx, s.config.Datastore)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vm, err := cloneVM(&CloneParameters{
|
|
||||||
ctx: d.ctx,
|
|
||||||
vmSrc: vmSrc,
|
|
||||||
vmName: s.config.VMName,
|
|
||||||
folder: folder,
|
|
||||||
resourcePool: pool,
|
|
||||||
datastore: datastore,
|
|
||||||
linkedClone: s.config.LinkedClone,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
@ -116,65 +66,9 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
|
||||||
|
|
||||||
ui.Say("Destroying VM...")
|
ui.Say("Destroying VM...")
|
||||||
|
|
||||||
task, err := vm.(*object.VirtualMachine).Destroy(d.ctx)
|
err := d.destroyVM(vm.(*object.VirtualMachine))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = task.WaitForResult(d.ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cloneVM(params *CloneParameters) (vm *object.VirtualMachine, err error) {
|
|
||||||
vm = nil
|
|
||||||
err = nil
|
|
||||||
poolRef := params.resourcePool.Reference()
|
|
||||||
|
|
||||||
// Creating specs for cloning
|
|
||||||
relocateSpec := types.VirtualMachineRelocateSpec{
|
|
||||||
Pool: &(poolRef),
|
|
||||||
}
|
|
||||||
if params.datastore != nil {
|
|
||||||
datastoreRef := params.datastore.Reference()
|
|
||||||
relocateSpec.Datastore = &datastoreRef
|
|
||||||
}
|
|
||||||
if params.linkedClone == true {
|
|
||||||
relocateSpec.DiskMoveType = "createNewChildDiskBacking"
|
|
||||||
}
|
|
||||||
|
|
||||||
cloneSpec := types.VirtualMachineCloneSpec{
|
|
||||||
Location: relocateSpec,
|
|
||||||
PowerOn: false,
|
|
||||||
}
|
|
||||||
if params.linkedClone == true {
|
|
||||||
var vmImage mo.VirtualMachine
|
|
||||||
err = params.vmSrc.Properties(params.ctx, params.vmSrc.Reference(), []string{"snapshot"}, &vmImage)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("Error reading base VM properties: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if vmImage.Snapshot == nil {
|
|
||||||
err = errors.New("`linked_clone=true`, but image VM has no snapshots")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cloneSpec.Snapshot = vmImage.Snapshot.CurrentSnapshot
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cloning itself
|
|
||||||
task, err := params.vmSrc.Clone(params.ctx, params.folder, params.vmName, cloneSpec)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := task.WaitForResult(params.ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vm = object.NewVirtualMachine(params.vmSrc.Client(), info.Result.(types.ManagedObjectReference))
|
|
||||||
return vm, nil
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue