extract vSphere driver

This commit is contained in:
Michael Kuzmin 2017-07-02 06:46:38 +03:00
parent 9f93e93c92
commit 1e747c8c93
9 changed files with 78 additions and 64 deletions

View File

@ -10,7 +10,6 @@ import (
"github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/communicator"
gossh "golang.org/x/crypto/ssh" gossh "golang.org/x/crypto/ssh"
"github.com/hashicorp/packer/communicator/ssh" "github.com/hashicorp/packer/communicator/ssh"
"context"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
) )
@ -33,7 +32,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
state := new(multistep.BasicStateBag) state := new(multistep.BasicStateBag)
state.Put("hook", hook) state.Put("hook", hook)
state.Put("ui", ui) state.Put("ui", ui)
state.Put("ctx", context.TODO())
steps := []multistep.Step{ steps := []multistep.Step{
&StepConnect{ &StepConnect{

46
driver.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"context"
"net/url"
"fmt"
"github.com/vmware/govmomi/object"
)
type Driver struct {
ctx context.Context
client *govmomi.Client
datacenter *object.Datacenter
finder *find.Finder
}
func NewDriverVSphere(config *ConnectConfig) (Driver, error) {
ctx := context.TODO()
vcenter_url, err := url.Parse(fmt.Sprintf("https://%v/sdk", config.VCenterServer))
if err != nil {
return Driver{}, err
}
vcenter_url.User = url.UserPassword(config.Username, config.Password)
client, err := govmomi.NewClient(ctx, vcenter_url, config.InsecureConnection)
if err != nil {
return Driver{}, err
}
finder := find.NewFinder(client.Client, false)
datacenter, err := finder.DatacenterOrDefault(ctx, config.Datacenter)
if err != nil {
return Driver{}, err
}
finder.SetDatacenter(datacenter)
d := Driver{
ctx: ctx,
client: client,
datacenter: datacenter,
finder: finder,
}
return d, nil
}

View File

@ -6,7 +6,6 @@ import (
"github.com/vmware/govmomi/vim25/types" "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"
"github.com/vmware/govmomi/find"
"fmt" "fmt"
"github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/mo"
"errors" "errors"
@ -49,39 +48,37 @@ type CloneParameters struct {
} }
type StepCloneVM struct { type StepCloneVM struct {
config *CloneConfig config *CloneConfig
} }
func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction {
ctx := state.Get("ctx").(context.Context) d := state.Get("driver").(Driver)
finder := state.Get("finder").(*find.Finder)
datacenter := state.Get("datacenter").(*object.Datacenter)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmSrc, err := finder.VirtualMachine(ctx, s.config.Template) vmSrc, err := d.finder.VirtualMachine(d.ctx, s.config.Template)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
state.Put("vmSrc", vmSrc) state.Put("vmSrc", vmSrc)
ui.Say("start cloning...") ui.Say("Cloning VM...")
folder, err := finder.FolderOrDefault(ctx, fmt.Sprintf("/%v/vm/%v", datacenter.Name(), s.config.FolderName)) folder, err := d.finder.FolderOrDefault(d.ctx, fmt.Sprintf("/%v/vm/%v", d.datacenter.Name(), s.config.FolderName))
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
pool, err := finder.ResourcePoolOrDefault(ctx, fmt.Sprintf("/%v/host/%v/Resources/%v", datacenter.Name(), s.config.Host, s.config.ResourcePool)) 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 { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
var datastore *object.Datastore = nil var datastore *object.Datastore
if s.config.Datastore != "" { if s.config.Datastore != "" {
datastore, err = finder.Datastore(ctx, s.config.Datastore) datastore, err = d.finder.Datastore(d.ctx, s.config.Datastore)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
@ -89,7 +86,7 @@ func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction {
} }
vm, err := cloneVM(&CloneParameters{ vm, err := cloneVM(&CloneParameters{
ctx: ctx, ctx: d.ctx,
vmSrc: vmSrc, vmSrc: vmSrc,
vmName: s.config.VMName, vmName: s.config.VMName,
folder: folder, folder: folder,
@ -114,17 +111,17 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
} }
if vm, ok := state.GetOk("vm"); ok { if vm, ok := state.GetOk("vm"); ok {
ctx := state.Get("ctx").(context.Context) d := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
ui.Say("Destroying VM...") ui.Say("Destroying VM...")
task, err := vm.(*object.VirtualMachine).Destroy(ctx) task, err := vm.(*object.VirtualMachine).Destroy(d.ctx)
if err != nil { if err != nil {
ui.Error(err.Error()) ui.Error(err.Error())
return return
} }
_, err = task.WaitForResult(ctx, nil) _, err = task.WaitForResult(d.ctx, nil)
if err != nil { if err != nil {
ui.Error(err.Error()) ui.Error(err.Error())
return return

View File

@ -2,11 +2,7 @@ package main
import ( import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"context"
"fmt" "fmt"
"net/url"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
) )
type ConnectConfig struct { type ConnectConfig struct {
@ -38,30 +34,12 @@ type StepConnect struct {
} }
func (s *StepConnect) Run(state multistep.StateBag) multistep.StepAction { func (s *StepConnect) Run(state multistep.StateBag) multistep.StepAction {
ctx := state.Get("ctx").(context.Context) driver, err := NewDriverVSphere(s.config)
vcenter_url, err := url.Parse(fmt.Sprintf("https://%v/sdk", s.config.VCenterServer))
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
vcenter_url.User = url.UserPassword(s.config.Username, s.config.Password) state.Put("driver", driver)
client, err := govmomi.NewClient(ctx, vcenter_url, s.config.InsecureConnection)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
state.Put("client", client)
finder := find.NewFinder(client.Client, false)
datacenter, err := finder.DatacenterOrDefault(ctx, s.config.Datacenter)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
finder.SetDatacenter(datacenter)
state.Put("finder", finder)
state.Put("datacenter", datacenter)
return multistep.ActionContinue return multistep.ActionContinue
} }

View File

@ -4,7 +4,6 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
"context"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"fmt" "fmt"
) )
@ -33,8 +32,8 @@ type StepConfigureHardware struct {
} }
func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepAction { func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepAction {
d := state.Get("driver").(Driver)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
if *s.config != (HardwareConfig{}) { if *s.config != (HardwareConfig{}) {
@ -55,12 +54,12 @@ func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepActi
confSpec.MemoryReservationLockedToMax = &s.config.RAMReserveAll confSpec.MemoryReservationLockedToMax = &s.config.RAMReserveAll
task, err := vm.Reconfigure(ctx, confSpec) task, err := vm.Reconfigure(d.ctx, confSpec)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
_, err = task.WaitForResult(ctx, nil) _, err = task.WaitForResult(d.ctx, nil)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt

View File

@ -4,7 +4,6 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"context"
"fmt" "fmt"
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
) )
@ -16,22 +15,22 @@ type StepRun struct{
func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction { func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context) d := state.Get("driver").(Driver)
ui.Say("VM power on...") ui.Say("VM power on...")
task, err := vm.PowerOn(ctx) task, err := vm.PowerOn(d.ctx)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
_, err = task.WaitForResult(ctx, nil) _, err = task.WaitForResult(d.ctx, nil)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
ui.Say("VM waiting for IP...") ui.Say("VM waiting for IP...")
ip, err := vm.WaitForIP(ctx) ip, err := vm.WaitForIP(d.ctx)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
@ -48,18 +47,18 @@ func (s *StepRun) Cleanup(state multistep.StateBag) {
if cancelled || halted { if cancelled || halted {
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context) d := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
if state, err := vm.PowerState(ctx); state != types.VirtualMachinePowerStatePoweredOff && err == nil { if state, err := vm.PowerState(d.ctx); state != types.VirtualMachinePowerStatePoweredOff && err == nil {
ui.Say("shutting down VM...") ui.Say("shutting down VM...")
task, err := vm.PowerOff(ctx) task, err := vm.PowerOff(d.ctx)
if err != nil { if err != nil {
ui.Error(err.Error()) ui.Error(err.Error())
return return
} }
_, err = task.WaitForResult(ctx, nil) _, err = task.WaitForResult(d.ctx, nil)
if err != nil { if err != nil {
ui.Error(err.Error()) ui.Error(err.Error())
return return

View File

@ -4,7 +4,6 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"context"
"fmt" "fmt"
"log" "log"
"time" "time"
@ -44,7 +43,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
comm := state.Get("communicator").(packer.Communicator) comm := state.Get("communicator").(packer.Communicator)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context) d := state.Get("driver").(Driver)
ui.Say("Shut down VM...") ui.Say("Shut down VM...")
@ -65,7 +64,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
} else { } else {
ui.Say("Forcibly halting virtual machine...") ui.Say("Forcibly halting virtual machine...")
err := vm.ShutdownGuest(ctx) err := vm.ShutdownGuest(d.ctx)
if err != nil { if err != nil {
state.Put("error", fmt.Errorf("Cannot shut down VM: %v", err)) state.Put("error", fmt.Errorf("Cannot shut down VM: %v", err))
return multistep.ActionHalt return multistep.ActionHalt
@ -76,7 +75,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
log.Printf("Waiting max %s for shutdown to complete", s.config.Timeout) log.Printf("Waiting max %s for shutdown to complete", s.config.Timeout)
shutdownTimer := time.After(s.config.Timeout) shutdownTimer := time.After(s.config.Timeout)
for { for {
powerState, err := vm.PowerState(ctx) powerState, err := vm.PowerState(d.ctx)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt

View File

@ -3,7 +3,6 @@ package main
import ( import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"context"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
) )
@ -14,12 +13,12 @@ type StepCreateSnapshot struct{
func (s *StepCreateSnapshot) Run(state multistep.StateBag) multistep.StepAction { func (s *StepCreateSnapshot) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context) d := state.Get("driver").(Driver)
if s.createSnapshot { if s.createSnapshot {
ui.Say("creating snapshot...") ui.Say("creating snapshot...")
_, err := vm.CreateSnapshot(ctx, "packer_snapshot", "", true, true) _, err := vm.CreateSnapshot(d.ctx, "packer_snapshot", "", true, true)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt

View File

@ -4,7 +4,6 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"context"
) )
type StepConvertToTemplate struct{ type StepConvertToTemplate struct{
@ -14,12 +13,12 @@ type StepConvertToTemplate struct{
func (s *StepConvertToTemplate) Run(state multistep.StateBag) multistep.StepAction { func (s *StepConvertToTemplate) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ctx := state.Get("ctx").(context.Context) d := state.Get("driver").(Driver)
// Turning into template if needed // Turning into template if needed
if s.ConvertToTemplate { if s.ConvertToTemplate {
ui.Say("turning into template...") ui.Say("turning into template...")
err := vm.MarkAsTemplate(ctx) err := vm.MarkAsTemplate(d.ctx)
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt