From efe2c3c8b360fadfc4d2de5b5859da112605e26a Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Wed, 23 Aug 2017 21:40:57 +0200 Subject: [PATCH] Extract vSphere driver into separate package (#35) --- builder_acc_test.go | 37 +++++++++++++++-------------------- driver.go => driver/driver.go | 29 ++++++++++++++++++++++++++- driver/host.go | 26 ++++++++++++++++++++++++ driver/resource_pool.go | 26 ++++++++++++++++++++++++ driver/vm.go | 25 +++++++++++++++++++++++ step_clone.go | 15 +++++++++++--- step_connect.go | 11 +++++++++-- step_hardware.go | 12 ++++++++++-- step_run.go | 5 +++-- step_shutdown.go | 3 ++- step_snapshot.go | 3 ++- step_template.go | 3 ++- 12 files changed, 161 insertions(+), 34 deletions(-) rename driver.go => driver/driver.go (91%) create mode 100644 driver/host.go create mode 100644 driver/resource_pool.go create mode 100644 driver/vm.go diff --git a/builder_acc_test.go b/builder_acc_test.go index 8fc363837..69dacf6a7 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -5,10 +5,10 @@ import ( builderT "github.com/hashicorp/packer/helper/builder/testing" "fmt" "github.com/hashicorp/packer/packer" - "github.com/vmware/govmomi/vim25/mo" "encoding/json" "math/rand" "github.com/vmware/govmomi/object" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) func TestBuilderAcc_default(t *testing.T) { @@ -51,13 +51,12 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc conn := testConn(t) - vm, err := conn.finder.VirtualMachine(conn.ctx, artifact.Name) + vm, err := conn.FindVM(artifact.Name) if err != nil { t.Fatal("Cannot find VM: ", err) } - var vmInfo mo.VirtualMachine - err = vm.Properties(conn.ctx, vm.Reference(), []string{"name", "runtime.host", "resourcePool", "layoutEx.disk"}, &vmInfo) + vmInfo, err := conn.VMInfo(vm, "name", "runtime.host", "resourcePool", "layoutEx.disk") if err != nil { 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) } - var hostInfo mo.HostSystem - err = vm.Properties(conn.ctx, vmInfo.Runtime.Host.Reference(), []string{"name"}, &hostInfo) + h := conn.NewHost(vmInfo.Runtime.Host) + hostInfo, err := conn.HostInfo(h, "name") if err != nil { 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) } - var rpInfo = mo.ResourcePool{} - err = vm.Properties(conn.ctx, vmInfo.ResourcePool.Reference(), []string{"owner", "parent"}, &rpInfo) + p := conn.NewResourcePool(vmInfo.ResourcePool) + poolInfo, err := conn.ResourcePoolInfo(p, "owner", "parent") if err != nil { 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") } @@ -115,13 +114,12 @@ func checkLinkedClone(t *testing.T) builderT.TestCheckFunc { conn := testConn(t) - vm, err := conn.finder.VirtualMachine(conn.ctx, artifact.Name) + vm, err := conn.FindVM(artifact.Name) if err != nil { t.Fatalf("Cannot find VM: %v", err) } - var vmInfo mo.VirtualMachine - err = vm.Properties(conn.ctx, vm.Reference(), []string{"layoutEx.disk"}, &vmInfo) + vmInfo, err := conn.VMInfo(vm, "layoutEx.disk") if err != nil { t.Fatalf("Cannot read VM properties: %v", err) } @@ -154,8 +152,7 @@ func checkTemplate(t *testing.T) builderT.TestCheckFunc { d := testConn(t) vm := getVM(t, d, artifacts) - var vmInfo mo.VirtualMachine - err := vm.Properties(d.ctx, vm.Reference(), []string{"config.template"}, &vmInfo) + vmInfo, err := d.VMInfo(vm, "config.template") if err != nil { t.Fatalf("Cannot read VM properties: %v", err) } @@ -184,26 +181,24 @@ func renderConfig(config map[string]interface{}) string { return string(j) } -func testConn(t *testing.T) *Driver { - config := &ConnectConfig{ +func testConn(t *testing.T) *driver.Driver { + d, err := driver.NewDriver(&driver.ConnectConfig{ VCenterServer: "vcenter.vsphere55.test", Username: "root", Password: "jetbrains", InsecureConnection: true, - } - - d, err := NewDriver(config) + }) if err != nil { t.Fatal("Cannot connect: ", err) } 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] artifact, _ := artifactRaw.(*Artifact) - vm, err := d.finder.VirtualMachine(d.ctx, artifact.Name) + vm, err := d.FindVM(artifact.Name) if err != nil { t.Fatalf("Cannot find VM: %v", err) } diff --git a/driver.go b/driver/driver.go similarity index 91% rename from driver.go rename to driver/driver.go index 93ff4fa15..13718c226 100644 --- a/driver.go +++ b/driver/driver.go @@ -1,4 +1,4 @@ -package main +package driver import ( "github.com/vmware/govmomi" @@ -23,6 +23,33 @@ type Driver struct { 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) { ctx := context.TODO() diff --git a/driver/host.go b/driver/host.go new file mode 100644 index 000000000..646c76b2d --- /dev/null +++ b/driver/host.go @@ -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 +} diff --git a/driver/resource_pool.go b/driver/resource_pool.go new file mode 100644 index 000000000..743528900 --- /dev/null +++ b/driver/resource_pool.go @@ -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 +} diff --git a/driver/vm.go b/driver/vm.go new file mode 100644 index 000000000..1c6196478 --- /dev/null +++ b/driver/vm.go @@ -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 +} diff --git a/step_clone.go b/step_clone.go index 195e49859..b9dbc8c45 100644 --- a/step_clone.go +++ b/step_clone.go @@ -5,6 +5,7 @@ import ( "github.com/vmware/govmomi/object" "github.com/hashicorp/packer/packer" "fmt" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) type CloneConfig struct { @@ -39,11 +40,19 @@ type StepCloneVM struct { func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) 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 { state.Put("error", err) return multistep.ActionHalt @@ -62,7 +71,7 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) { if vm, ok := state.GetOk("vm"); ok { ui := state.Get("ui").(packer.Ui) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) ui.Say("Destroying VM...") diff --git a/step_connect.go b/step_connect.go index 0657fd5ed..57bce17ba 100644 --- a/step_connect.go +++ b/step_connect.go @@ -3,6 +3,7 @@ package main import ( "github.com/mitchellh/multistep" "fmt" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) type ConnectConfig struct { @@ -34,12 +35,18 @@ type StepConnect struct { } 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 { state.Put("error", err) return multistep.ActionHalt } - state.Put("driver", driver) + state.Put("driver", d) return multistep.ActionContinue } diff --git a/step_hardware.go b/step_hardware.go index 4c1e95a39..33045eda1 100644 --- a/step_hardware.go +++ b/step_hardware.go @@ -5,6 +5,7 @@ import ( "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/object" "fmt" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) type HardwareConfig struct { @@ -32,13 +33,20 @@ type StepConfigureHardware struct { func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) vm := state.Get("vm").(*object.VirtualMachine) if *s.config != (HardwareConfig{}) { 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 { state.Put("error", err) return multistep.ActionHalt diff --git a/step_run.go b/step_run.go index 4d68b0d2b..353f3df00 100644 --- a/step_run.go +++ b/step_run.go @@ -5,6 +5,7 @@ import ( "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/object" "fmt" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) type StepRun struct { @@ -12,7 +13,7 @@ type StepRun struct { func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) vm := state.Get("vm").(*object.VirtualMachine) ui.Say("Power on VM...") @@ -42,7 +43,7 @@ func (s *StepRun) Cleanup(state multistep.StateBag) { } ui := state.Get("ui").(packer.Ui) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) vm := state.Get("vm").(*object.VirtualMachine) ui.Say("Power off VM...") diff --git a/step_shutdown.go b/step_shutdown.go index 2b2e4c1a8..dc8539a13 100644 --- a/step_shutdown.go +++ b/step_shutdown.go @@ -8,6 +8,7 @@ import ( "log" "time" "bytes" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) type ShutdownConfig struct { @@ -40,7 +41,7 @@ type StepShutdown struct { func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) comm := state.Get("communicator").(packer.Communicator) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) vm := state.Get("vm").(*object.VirtualMachine) if s.config.Command != "" { diff --git a/step_snapshot.go b/step_snapshot.go index 740d98728..ad9965445 100644 --- a/step_snapshot.go +++ b/step_snapshot.go @@ -4,6 +4,7 @@ import ( "github.com/mitchellh/multistep" "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/object" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) type StepCreateSnapshot struct{ @@ -12,7 +13,7 @@ type StepCreateSnapshot struct{ func (s *StepCreateSnapshot) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) vm := state.Get("vm").(*object.VirtualMachine) if s.createSnapshot { diff --git a/step_template.go b/step_template.go index 1b3767015..2b3d42a6b 100644 --- a/step_template.go +++ b/step_template.go @@ -4,6 +4,7 @@ import ( "github.com/mitchellh/multistep" "github.com/hashicorp/packer/packer" "github.com/vmware/govmomi/object" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) type StepConvertToTemplate struct{ @@ -12,7 +13,7 @@ type StepConvertToTemplate struct{ func (s *StepConvertToTemplate) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) - d := state.Get("driver").(*Driver) + d := state.Get("driver").(*driver.Driver) vm := state.Get("vm").(*object.VirtualMachine) if s.ConvertToTemplate {