Extract vSphere driver into separate package (#35)

This commit is contained in:
Michael Kuzmin 2017-08-23 21:40:57 +02:00 committed by GitHub
parent ae3a1d6f24
commit efe2c3c8b3
12 changed files with 161 additions and 34 deletions

View File

@ -5,10 +5,10 @@ import (
builderT "github.com/hashicorp/packer/helper/builder/testing" builderT "github.com/hashicorp/packer/helper/builder/testing"
"fmt" "fmt"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/vim25/mo"
"encoding/json" "encoding/json"
"math/rand" "math/rand"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
func TestBuilderAcc_default(t *testing.T) { func TestBuilderAcc_default(t *testing.T) {
@ -51,13 +51,12 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc
conn := testConn(t) conn := testConn(t)
vm, err := conn.finder.VirtualMachine(conn.ctx, artifact.Name) vm, err := conn.FindVM(artifact.Name)
if err != nil { if err != nil {
t.Fatal("Cannot find VM: ", err) t.Fatal("Cannot find VM: ", err)
} }
var vmInfo mo.VirtualMachine vmInfo, err := conn.VMInfo(vm, "name", "runtime.host", "resourcePool", "layoutEx.disk")
err = vm.Properties(conn.ctx, vm.Reference(), []string{"name", "runtime.host", "resourcePool", "layoutEx.disk"}, &vmInfo)
if err != nil { if err != nil {
t.Fatalf("Cannot read VM properties: %v", err) t.Fatalf("Cannot read VM properties: %v", err)
} }
@ -66,8 +65,8 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc
t.Errorf("Invalid VM name: expected '%v', got '%v'", name, vmInfo.Name) t.Errorf("Invalid VM name: expected '%v', got '%v'", name, vmInfo.Name)
} }
var hostInfo mo.HostSystem h := conn.NewHost(vmInfo.Runtime.Host)
err = vm.Properties(conn.ctx, vmInfo.Runtime.Host.Reference(), []string{"name"}, &hostInfo) hostInfo, err := conn.HostInfo(h, "name")
if err != nil { if err != nil {
t.Fatal("Cannot read VM properties: ", err) t.Fatal("Cannot read VM properties: ", err)
} }
@ -76,13 +75,13 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc
t.Errorf("Invalid host name: expected '%v', got '%v'", host, hostInfo.Name) t.Errorf("Invalid host name: expected '%v', got '%v'", host, hostInfo.Name)
} }
var rpInfo = mo.ResourcePool{} p := conn.NewResourcePool(vmInfo.ResourcePool)
err = vm.Properties(conn.ctx, vmInfo.ResourcePool.Reference(), []string{"owner", "parent"}, &rpInfo) poolInfo, err := conn.ResourcePoolInfo(p, "owner", "parent")
if err != nil { if err != nil {
t.Fatalf("Cannot read resource pool properties: %v", err) t.Fatalf("Cannot read resource pool properties: %v", err)
} }
if rpInfo.Owner != *rpInfo.Parent { if poolInfo.Owner != *poolInfo.Parent {
t.Error("Not a root resource pool") t.Error("Not a root resource pool")
} }
@ -115,13 +114,12 @@ func checkLinkedClone(t *testing.T) builderT.TestCheckFunc {
conn := testConn(t) conn := testConn(t)
vm, err := conn.finder.VirtualMachine(conn.ctx, artifact.Name) vm, err := conn.FindVM(artifact.Name)
if err != nil { if err != nil {
t.Fatalf("Cannot find VM: %v", err) t.Fatalf("Cannot find VM: %v", err)
} }
var vmInfo mo.VirtualMachine vmInfo, err := conn.VMInfo(vm, "layoutEx.disk")
err = vm.Properties(conn.ctx, vm.Reference(), []string{"layoutEx.disk"}, &vmInfo)
if err != nil { if err != nil {
t.Fatalf("Cannot read VM properties: %v", err) t.Fatalf("Cannot read VM properties: %v", err)
} }
@ -154,8 +152,7 @@ func checkTemplate(t *testing.T) builderT.TestCheckFunc {
d := testConn(t) d := testConn(t)
vm := getVM(t, d, artifacts) vm := getVM(t, d, artifacts)
var vmInfo mo.VirtualMachine vmInfo, err := d.VMInfo(vm, "config.template")
err := vm.Properties(d.ctx, vm.Reference(), []string{"config.template"}, &vmInfo)
if err != nil { if err != nil {
t.Fatalf("Cannot read VM properties: %v", err) t.Fatalf("Cannot read VM properties: %v", err)
} }
@ -184,26 +181,24 @@ func renderConfig(config map[string]interface{}) string {
return string(j) return string(j)
} }
func testConn(t *testing.T) *Driver { func testConn(t *testing.T) *driver.Driver {
config := &ConnectConfig{ d, err := driver.NewDriver(&driver.ConnectConfig{
VCenterServer: "vcenter.vsphere55.test", VCenterServer: "vcenter.vsphere55.test",
Username: "root", Username: "root",
Password: "jetbrains", Password: "jetbrains",
InsecureConnection: true, InsecureConnection: true,
} })
d, err := NewDriver(config)
if err != nil { if err != nil {
t.Fatal("Cannot connect: ", err) t.Fatal("Cannot connect: ", err)
} }
return d return d
} }
func getVM(t *testing.T, d *Driver, artifacts []packer.Artifact) *object.VirtualMachine { func getVM(t *testing.T, d *driver.Driver, artifacts []packer.Artifact) *object.VirtualMachine {
artifactRaw := artifacts[0] artifactRaw := artifacts[0]
artifact, _ := artifactRaw.(*Artifact) artifact, _ := artifactRaw.(*Artifact)
vm, err := d.finder.VirtualMachine(d.ctx, artifact.Name) vm, err := d.FindVM(artifact.Name)
if err != nil { if err != nil {
t.Fatalf("Cannot find VM: %v", err) t.Fatalf("Cannot find VM: %v", err)
} }

View File

@ -1,4 +1,4 @@
package main package driver
import ( import (
"github.com/vmware/govmomi" "github.com/vmware/govmomi"
@ -23,6 +23,33 @@ type Driver struct {
datacenter *object.Datacenter datacenter *object.Datacenter
} }
type ConnectConfig struct {
VCenterServer string
Username string
Password string
InsecureConnection bool
Datacenter string
}
type CloneConfig struct {
Template string
VMName string
Folder string
Host string
ResourcePool string
Datastore string
LinkedClone bool
}
type HardwareConfig struct {
CPUs int32
CPUReservation int64
CPULimit int64
RAM int64
RAMReservation int64
RAMReserveAll bool
}
func NewDriver(config *ConnectConfig) (*Driver, error) { func NewDriver(config *ConnectConfig) (*Driver, error) {
ctx := context.TODO() ctx := context.TODO()

26
driver/host.go Normal file
View File

@ -0,0 +1,26 @@
package driver
import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
func (d *Driver) NewHost(ref *types.ManagedObjectReference) *object.HostSystem {
return object.NewHostSystem(d.client.Client, *ref)
}
func (d *Driver) HostInfo(host *object.HostSystem, params ...string) (*mo.HostSystem, error){
var p []string
if len(params) == 0 {
p = []string{"*"}
} else {
p = params
}
var hostInfo mo.HostSystem
err := host.Properties(d.ctx, host.Reference(), p, &hostInfo)
if err != nil {
return nil, err
}
return &hostInfo, nil
}

26
driver/resource_pool.go Normal file
View File

@ -0,0 +1,26 @@
package driver
import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
func (d *Driver) NewResourcePool(ref *types.ManagedObjectReference) *object.ResourcePool {
return object.NewResourcePool(d.client.Client, *ref)
}
func (d *Driver) ResourcePoolInfo(host *object.ResourcePool, params ...string) (*mo.ResourcePool, error){
var p []string
if len(params) == 0 {
p = []string{"*"}
} else {
p = params
}
var poolInfo mo.ResourcePool
err := host.Properties(d.ctx, host.Reference(), p, &poolInfo)
if err != nil {
return nil, err
}
return &poolInfo, nil
}

25
driver/vm.go Normal file
View File

@ -0,0 +1,25 @@
package driver
import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
)
func (d *Driver) FindVM(name string) (*object.VirtualMachine, error) {
return d.finder.VirtualMachine(d.ctx, name)
}
func (d *Driver) VMInfo(vm *object.VirtualMachine, params ...string) (*mo.VirtualMachine, error){
var p []string
if len(params) == 0 {
p = []string{"*"}
} else {
p = params
}
var vmInfo mo.VirtualMachine
err := vm.Properties(d.ctx, vm.Reference(), p, &vmInfo)
if err != nil {
return nil, err
}
return &vmInfo, nil
}

View File

@ -5,6 +5,7 @@ import (
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"fmt" "fmt"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
type CloneConfig struct { type CloneConfig struct {
@ -39,11 +40,19 @@ type StepCloneVM struct {
func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
ui.Say("Cloning VM...") ui.Say("Cloning VM...")
vm, err := d.CloneVM(s.config) vm, err := d.CloneVM(&driver.CloneConfig{
Template: s.config.Template,
VMName: s.config.VMName,
Folder: s.config.Folder,
Host: s.config.Host,
ResourcePool: s.config.ResourcePool,
Datastore: s.config.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
@ -62,7 +71,7 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
if vm, ok := state.GetOk("vm"); ok { if vm, ok := state.GetOk("vm"); ok {
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
ui.Say("Destroying VM...") ui.Say("Destroying VM...")

View File

@ -3,6 +3,7 @@ package main
import ( import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"fmt" "fmt"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
type ConnectConfig struct { type ConnectConfig struct {
@ -34,12 +35,18 @@ type StepConnect struct {
} }
func (s *StepConnect) Run(state multistep.StateBag) multistep.StepAction { func (s *StepConnect) Run(state multistep.StateBag) multistep.StepAction {
driver, err := NewDriver(s.config) d, err := driver.NewDriver(&driver.ConnectConfig{
VCenterServer: s.config.VCenterServer,
Username: s.config.Username,
Password: s.config.Password,
InsecureConnection: s.config.InsecureConnection,
Datacenter: s.config.Datacenter,
})
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt
} }
state.Put("driver", driver) state.Put("driver", d)
return multistep.ActionContinue return multistep.ActionContinue
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"fmt" "fmt"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
type HardwareConfig struct { type HardwareConfig struct {
@ -32,13 +33,20 @@ type StepConfigureHardware struct {
func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepAction { func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
if *s.config != (HardwareConfig{}) { if *s.config != (HardwareConfig{}) {
ui.Say("Customizing hardware parameters...") ui.Say("Customizing hardware parameters...")
err := d.ConfigureVM(vm, s.config) err := d.ConfigureVM(vm, &driver.HardwareConfig{
CPUs: s.config.CPUs,
CPUReservation: s.config.CPUReservation,
CPULimit: s.config.CPULimit,
RAM: s.config.RAM,
RAMReservation: s.config.RAMReservation,
RAMReserveAll: s.config.RAMReserveAll,
})
if err != nil { if err != nil {
state.Put("error", err) state.Put("error", err)
return multistep.ActionHalt return multistep.ActionHalt

View File

@ -5,6 +5,7 @@ import (
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/object" "github.com/vmware/govmomi/object"
"fmt" "fmt"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
type StepRun struct { type StepRun struct {
@ -12,7 +13,7 @@ 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)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ui.Say("Power on VM...") ui.Say("Power on VM...")
@ -42,7 +43,7 @@ func (s *StepRun) Cleanup(state multistep.StateBag) {
} }
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
ui.Say("Power off VM...") ui.Say("Power off VM...")

View File

@ -8,6 +8,7 @@ import (
"log" "log"
"time" "time"
"bytes" "bytes"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
type ShutdownConfig struct { type ShutdownConfig struct {
@ -40,7 +41,7 @@ type StepShutdown struct {
func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
comm := state.Get("communicator").(packer.Communicator) comm := state.Get("communicator").(packer.Communicator)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
if s.config.Command != "" { if s.config.Command != "" {

View File

@ -4,6 +4,7 @@ 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"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
type StepCreateSnapshot struct{ type StepCreateSnapshot struct{
@ -12,7 +13,7 @@ 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)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
if s.createSnapshot { if s.createSnapshot {

View File

@ -4,6 +4,7 @@ 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"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
) )
type StepConvertToTemplate struct{ type StepConvertToTemplate struct{
@ -12,7 +13,7 @@ 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)
d := state.Get("driver").(*Driver) d := state.Get("driver").(*driver.Driver)
vm := state.Get("vm").(*object.VirtualMachine) vm := state.Get("vm").(*object.VirtualMachine)
if s.ConvertToTemplate { if s.ConvertToTemplate {