Refactor vSphere driver
This commit is contained in:
parent
8d75c273a9
commit
e8d8fd6205
11
artifact.go
11
artifact.go
|
@ -1,15 +1,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
"context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const BuilderId = "jetbrains.vsphere"
|
const BuilderId = "jetbrains.vsphere"
|
||||||
|
|
||||||
type Artifact struct {
|
type Artifact struct {
|
||||||
Name string
|
Name string
|
||||||
VM *object.VirtualMachine
|
VM *driver.VirtualMachine
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Artifact) BuilderId() string {
|
func (a *Artifact) BuilderId() string {
|
||||||
|
@ -33,11 +32,9 @@ func (a *Artifact) State(name string) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Artifact) Destroy() error {
|
func (a *Artifact) Destroy() error {
|
||||||
ctx := context.TODO()
|
err := a.VM.Destroy()
|
||||||
task, err := a.VM.Destroy(ctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = task.WaitForResult(ctx, nil)
|
return nil
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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"
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
|
@ -93,7 +93,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
|
|
||||||
artifact := &Artifact{
|
artifact := &Artifact{
|
||||||
Name: b.config.VMName,
|
Name: b.config.VMName,
|
||||||
VM: state.Get("vm").(*object.VirtualMachine),
|
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||||
}
|
}
|
||||||
return artifact, nil
|
return artifact, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"github.com/vmware/govmomi/object"
|
|
||||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc
|
||||||
d := testConn(t)
|
d := testConn(t)
|
||||||
vm := getVM(t, d, artifacts)
|
vm := getVM(t, d, artifacts)
|
||||||
|
|
||||||
vmInfo, err := d.VMInfo(vm, "name", "parent", "runtime.host", "resourcePool", "layoutEx.disk")
|
vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "layoutEx.disk")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read VM properties: %v", err)
|
t.Fatalf("Cannot read VM properties: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -52,7 +51,7 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
f := d.NewFolder(vmInfo.Parent)
|
f := d.NewFolder(vmInfo.Parent)
|
||||||
folderPath, err := d.GetFolderPath(f)
|
folderPath, err := f.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read folder name: %v", err)
|
t.Fatalf("Cannot read folder name: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -61,7 +60,7 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
h := d.NewHost(vmInfo.Runtime.Host)
|
h := d.NewHost(vmInfo.Runtime.Host)
|
||||||
hostInfo, err := d.HostInfo(h, "name")
|
hostInfo, err := h.Info("name")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Cannot read host properties: ", err)
|
t.Fatal("Cannot read host properties: ", err)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +70,7 @@ func checkDefault(t *testing.T, name string, host string) builderT.TestCheckFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
p := d.NewResourcePool(vmInfo.ResourcePool)
|
p := d.NewResourcePool(vmInfo.ResourcePool)
|
||||||
poolPath, err := d.GetResourcePoolPath(p)
|
poolPath, err := p.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read resource pool name: %v", err)
|
t.Fatalf("Cannot read resource pool name: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -132,13 +131,13 @@ func checkFolder(t *testing.T, folder string) builderT.TestCheckFunc {
|
||||||
d := testConn(t)
|
d := testConn(t)
|
||||||
vm := getVM(t, d, artifacts)
|
vm := getVM(t, d, artifacts)
|
||||||
|
|
||||||
vmInfo, err := d.VMInfo(vm, "parent")
|
vmInfo, err := vm.Info("parent")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read VM properties: %v", err)
|
t.Fatalf("Cannot read VM properties: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f := d.NewFolder(vmInfo.Parent)
|
f := d.NewFolder(vmInfo.Parent)
|
||||||
path, err := d.GetFolderPath(f)
|
path, err := f.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read folder name: %v", err)
|
t.Fatalf("Cannot read folder name: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -170,13 +169,13 @@ func checkResourcePool(t *testing.T, pool string) builderT.TestCheckFunc {
|
||||||
d := testConn(t)
|
d := testConn(t)
|
||||||
vm := getVM(t, d, artifacts)
|
vm := getVM(t, d, artifacts)
|
||||||
|
|
||||||
vmInfo, err := d.VMInfo(vm, "resourcePool")
|
vmInfo, err := vm.Info("resourcePool")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read VM properties: %v", err)
|
t.Fatalf("Cannot read VM properties: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := d.NewResourcePool(vmInfo.ResourcePool)
|
p := d.NewResourcePool(vmInfo.ResourcePool)
|
||||||
path, err := d.GetResourcePoolPath(p)
|
path, err := p.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read resource pool name: %v", err)
|
t.Fatalf("Cannot read resource pool name: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -207,7 +206,7 @@ func checkLinkedClone(t *testing.T) builderT.TestCheckFunc {
|
||||||
d := testConn(t)
|
d := testConn(t)
|
||||||
vm := getVM(t, d, artifacts)
|
vm := getVM(t, d, artifacts)
|
||||||
|
|
||||||
vmInfo, err := d.VMInfo(vm, "layoutEx.disk")
|
vmInfo, err := vm.Info("layoutEx.disk")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read VM properties: %v", err)
|
t.Fatalf("Cannot read VM properties: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -239,7 +238,7 @@ func checkSnapshot(t *testing.T) builderT.TestCheckFunc {
|
||||||
d := testConn(t)
|
d := testConn(t)
|
||||||
|
|
||||||
vm := getVM(t, d, artifacts)
|
vm := getVM(t, d, artifacts)
|
||||||
vmInfo, err := d.VMInfo(vm, "layoutEx.disk")
|
vmInfo, err := vm.Info("layoutEx.disk")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read VM properties: %v", err)
|
t.Fatalf("Cannot read VM properties: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -273,7 +272,7 @@ func checkTemplate(t *testing.T) builderT.TestCheckFunc {
|
||||||
d := testConn(t)
|
d := testConn(t)
|
||||||
|
|
||||||
vm := getVM(t, d, artifacts)
|
vm := getVM(t, d, artifacts)
|
||||||
vmInfo, err := d.VMInfo(vm, "config.template")
|
vmInfo, err := vm.Info("config.template")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot read VM properties: %v", err)
|
t.Fatalf("Cannot read VM properties: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -315,7 +314,7 @@ func testConn(t *testing.T) *driver.Driver {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVM(t *testing.T, d *driver.Driver, artifacts []packer.Artifact) *object.VirtualMachine {
|
func getVM(t *testing.T, d *driver.Driver, artifacts []packer.Artifact) *driver.VirtualMachine {
|
||||||
artifactRaw := artifacts[0]
|
artifactRaw := artifacts[0]
|
||||||
artifact, _ := artifactRaw.(*Artifact)
|
artifact, _ := artifactRaw.(*Artifact)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/vmware/govmomi/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Datastore struct {
|
||||||
|
ds *object.Datastore
|
||||||
|
driver *Driver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) FindDatastore(name string) (*Datastore, error) {
|
||||||
|
ds, err := d.finder.Datastore(d.ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Datastore{
|
||||||
|
ds: ds,
|
||||||
|
driver: d,
|
||||||
|
}, nil
|
||||||
|
}
|
193
driver/driver.go
193
driver/driver.go
|
@ -7,9 +7,6 @@ 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"
|
|
||||||
"time"
|
"time"
|
||||||
"github.com/vmware/govmomi/session"
|
"github.com/vmware/govmomi/session"
|
||||||
"github.com/vmware/govmomi/vim25/soap"
|
"github.com/vmware/govmomi/vim25/soap"
|
||||||
|
@ -31,25 +28,6 @@ type ConnectConfig struct {
|
||||||
Datacenter string
|
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()
|
||||||
|
|
||||||
|
@ -92,174 +70,3 @@ func NewDriver(config *ConnectConfig) (*Driver, error) {
|
||||||
}
|
}
|
||||||
return &d, nil
|
return &d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) CloneVM(config *CloneConfig) (*object.VirtualMachine, error) {
|
|
||||||
template, 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.Folder))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var relocateSpec types.VirtualMachineRelocateSpec
|
|
||||||
|
|
||||||
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()
|
|
||||||
relocateSpec.Pool = &poolRef
|
|
||||||
|
|
||||||
if config.Datastore != "" {
|
|
||||||
datastore, err := d.finder.Datastore(d.ctx, config.Datastore)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
datastoreRef := datastore.Reference()
|
|
||||||
relocateSpec.Datastore = &datastoreRef
|
|
||||||
}
|
|
||||||
|
|
||||||
var cloneSpec types.VirtualMachineCloneSpec
|
|
||||||
cloneSpec.Location = relocateSpec
|
|
||||||
cloneSpec.PowerOn = false
|
|
||||||
|
|
||||||
if config.LinkedClone == true {
|
|
||||||
cloneSpec.Location.DiskMoveType = "createNewChildDiskBacking"
|
|
||||||
|
|
||||||
var tpl mo.VirtualMachine
|
|
||||||
err = template.Properties(d.ctx, template.Reference(), []string{"snapshot"}, &tpl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if tpl.Snapshot == nil {
|
|
||||||
err = errors.New("`linked_clone=true`, but template has no snapshots")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cloneSpec.Snapshot = tpl.Snapshot.CurrentSnapshot
|
|
||||||
}
|
|
||||||
|
|
||||||
task, err := template.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(d.client.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)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) ConfigureVM(vm *object.VirtualMachine, config *HardwareConfig) error {
|
|
||||||
var confSpec types.VirtualMachineConfigSpec
|
|
||||||
confSpec.NumCPUs = config.CPUs
|
|
||||||
confSpec.MemoryMB = config.RAM
|
|
||||||
|
|
||||||
var cpuSpec types.ResourceAllocationInfo
|
|
||||||
cpuSpec.Reservation = config.CPUReservation
|
|
||||||
cpuSpec.Limit = config.CPULimit
|
|
||||||
confSpec.CpuAllocation = &cpuSpec
|
|
||||||
|
|
||||||
var ramSpec types.ResourceAllocationInfo
|
|
||||||
ramSpec.Reservation = config.RAMReservation
|
|
||||||
confSpec.MemoryAllocation = &ramSpec
|
|
||||||
|
|
||||||
confSpec.MemoryReservationLockedToMax = &config.RAMReserveAll
|
|
||||||
|
|
||||||
task, err := vm.Reconfigure(d.ctx, confSpec)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = task.WaitForResult(d.ctx, nil)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) PowerOn(vm *object.VirtualMachine) error {
|
|
||||||
task, err := vm.PowerOn(d.ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = task.WaitForResult(d.ctx, nil)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) WaitForIP(vm *object.VirtualMachine) (string, error) {
|
|
||||||
ip, err := vm.WaitForIP(d.ctx)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return ip, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) PowerOff(vm *object.VirtualMachine) error {
|
|
||||||
state, err := vm.PowerState(d.ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if state == types.VirtualMachinePowerStatePoweredOff {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
task, err := vm.PowerOff(d.ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = task.WaitForResult(d.ctx, nil)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) StartShutdown(vm *object.VirtualMachine) error {
|
|
||||||
err := vm.ShutdownGuest(d.ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) WaitForShutdown(vm *object.VirtualMachine, timeout time.Duration) error {
|
|
||||||
shutdownTimer := time.After(timeout)
|
|
||||||
for {
|
|
||||||
powerState, err := vm.PowerState(d.ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if powerState == "poweredOff" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-shutdownTimer:
|
|
||||||
err := errors.New("Timeout while waiting for machine to shut down.")
|
|
||||||
return err
|
|
||||||
default:
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) CreateSnapshot(vm *object.VirtualMachine) error {
|
|
||||||
task, err := vm.CreateSnapshot(d.ctx, "Created by Packer", "", false, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = task.WaitForResult(d.ctx, nil)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Driver) ConvertToTemplate(vm *object.VirtualMachine) error {
|
|
||||||
err := vm.MarkAsTemplate(d.ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,42 +7,61 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Driver) NewFolder(ref *types.ManagedObjectReference) *object.Folder {
|
type Folder struct {
|
||||||
return object.NewFolder(d.client.Client, *ref)
|
driver *Driver
|
||||||
|
folder *object.Folder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) FolderInfo(folder *object.Folder, params ...string) (*mo.Folder, error) {
|
func (d *Driver) NewFolder(ref *types.ManagedObjectReference) *Folder {
|
||||||
|
return &Folder{
|
||||||
|
folder: object.NewFolder(d.client.Client, *ref),
|
||||||
|
driver: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) FindFolder(name string) (*Folder, error) {
|
||||||
|
f, err := d.finder.Folder(d.ctx, fmt.Sprintf("/%v/vm/%v", d.datacenter.Name(), name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Folder{
|
||||||
|
folder: f,
|
||||||
|
driver: d,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Folder) Info(params ...string) (*mo.Folder, error) {
|
||||||
var p []string
|
var p []string
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
p = []string{"*"}
|
p = []string{"*"}
|
||||||
} else {
|
} else {
|
||||||
p = params
|
p = params
|
||||||
}
|
}
|
||||||
var folderInfo mo.Folder
|
var info mo.Folder
|
||||||
err := folder.Properties(d.ctx, folder.Reference(), p, &folderInfo)
|
err := f.folder.Properties(f.driver.ctx, f.folder.Reference(), p, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &folderInfo, nil
|
return &info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) GetFolderPath(folder *object.Folder) (string, error) {
|
func (f *Folder) Path() (string, error) {
|
||||||
f, err := d.FolderInfo(folder, "name", "parent")
|
info, err := f.Info("name", "parent")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if f.Parent.Type == "Datacenter" {
|
if info.Parent.Type == "Datacenter" {
|
||||||
return "", nil
|
return "", nil
|
||||||
} else {
|
} else {
|
||||||
parent := d.NewFolder(f.Parent)
|
parent := f.driver.NewFolder(info.Parent)
|
||||||
parentPath, err := d.GetFolderPath(parent)
|
path, err := parent.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if parentPath == "" {
|
if path == "" {
|
||||||
return f.Name, nil
|
return info.Name, nil
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("%v/%v", parentPath, f.Name), nil
|
return fmt.Sprintf("%v/%v", path, info.Name), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,25 +2,33 @@ package driver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/vmware/govmomi/object"
|
||||||
"github.com/vmware/govmomi/vim25/mo"
|
|
||||||
"github.com/vmware/govmomi/vim25/types"
|
"github.com/vmware/govmomi/vim25/types"
|
||||||
|
"github.com/vmware/govmomi/vim25/mo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Driver) NewHost(ref *types.ManagedObjectReference) *object.HostSystem {
|
type Host struct {
|
||||||
return object.NewHostSystem(d.client.Client, *ref)
|
driver *Driver
|
||||||
|
host *object.HostSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) HostInfo(host *object.HostSystem, params ...string) (*mo.HostSystem, error){
|
func (d *Driver) NewHost(ref *types.ManagedObjectReference) *Host {
|
||||||
|
return &Host{
|
||||||
|
host: object.NewHostSystem(d.client.Client, *ref),
|
||||||
|
driver: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Host) Info(params ...string) (*mo.HostSystem, error){
|
||||||
var p []string
|
var p []string
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
p = []string{"*"}
|
p = []string{"*"}
|
||||||
} else {
|
} else {
|
||||||
p = params
|
p = params
|
||||||
}
|
}
|
||||||
var hostInfo mo.HostSystem
|
var info mo.HostSystem
|
||||||
err := host.Properties(d.ctx, host.Reference(), p, &hostInfo)
|
err := h.host.Properties(h.driver.ctx, h.host.Reference(), p, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &hostInfo, nil
|
return &info, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,47 +2,66 @@ package driver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/vmware/govmomi/object"
|
||||||
"github.com/vmware/govmomi/vim25/mo"
|
|
||||||
"github.com/vmware/govmomi/vim25/types"
|
"github.com/vmware/govmomi/vim25/types"
|
||||||
|
"github.com/vmware/govmomi/vim25/mo"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Driver) NewResourcePool(ref *types.ManagedObjectReference) *object.ResourcePool {
|
type ResourcePool struct {
|
||||||
return object.NewResourcePool(d.client.Client, *ref)
|
pool *object.ResourcePool
|
||||||
|
driver *Driver
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) ResourcePoolInfo(host *object.ResourcePool, params ...string) (*mo.ResourcePool, error){
|
func (d *Driver) NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool {
|
||||||
var p []string
|
return &ResourcePool{
|
||||||
if len(params) == 0 {
|
pool: object.NewResourcePool(d.client.Client, *ref),
|
||||||
p = []string{"*"}
|
driver: d,
|
||||||
} else {
|
|
||||||
p = params
|
|
||||||
}
|
}
|
||||||
var poolInfo mo.ResourcePool
|
}
|
||||||
err := host.Properties(d.ctx, host.Reference(), p, &poolInfo)
|
|
||||||
|
func (d *Driver) FindResourcePool(host string, name string) (*ResourcePool, error) {
|
||||||
|
p, err := d.finder.ResourcePool(d.ctx, fmt.Sprintf("/%v/host/%v/Resources/%v", d.datacenter.Name(), host, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &poolInfo, nil
|
return &ResourcePool{
|
||||||
|
pool: p,
|
||||||
|
driver: d,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) GetResourcePoolPath(pool *object.ResourcePool) (string, error) {
|
func (p *ResourcePool) Info(params ...string) (*mo.ResourcePool, error) {
|
||||||
f, err := d.ResourcePoolInfo(pool, "name", "parent")
|
var params2 []string
|
||||||
|
if len(params) == 0 {
|
||||||
|
params2 = []string{"*"}
|
||||||
|
} else {
|
||||||
|
params2 = params
|
||||||
|
}
|
||||||
|
var info mo.ResourcePool
|
||||||
|
err := p.pool.Properties(p.driver.ctx, p.pool.Reference(), params2, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ResourcePool) Path() (string, error) {
|
||||||
|
poolInfo, err := p.Info("name", "parent")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if f.Parent.Type == "ComputeResource" {
|
if poolInfo.Parent.Type == "ComputeResource" {
|
||||||
return "", nil
|
return "", nil
|
||||||
} else {
|
} else {
|
||||||
parent := d.NewResourcePool(f.Parent)
|
parent := p.driver.NewResourcePool(poolInfo.Parent)
|
||||||
parentPath, err := d.GetResourcePoolPath(parent)
|
parentPath, err := parent.Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if parentPath == "" {
|
if parentPath == "" {
|
||||||
return f.Name, nil
|
return poolInfo.Name, nil
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("%v/%v", parentPath, f.Name), nil
|
return fmt.Sprintf("%v/%v", parentPath, poolInfo.Name), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
218
driver/vm.go
218
driver/vm.go
|
@ -3,23 +3,229 @@ package driver
|
||||||
import (
|
import (
|
||||||
"github.com/vmware/govmomi/object"
|
"github.com/vmware/govmomi/object"
|
||||||
"github.com/vmware/govmomi/vim25/mo"
|
"github.com/vmware/govmomi/vim25/mo"
|
||||||
|
"github.com/vmware/govmomi/vim25/types"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Driver) FindVM(name string) (*object.VirtualMachine, error) {
|
type VirtualMachine struct {
|
||||||
return d.finder.VirtualMachine(d.ctx, name)
|
vm *object.VirtualMachine
|
||||||
|
driver *Driver
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) VMInfo(vm *object.VirtualMachine, params ...string) (*mo.VirtualMachine, error){
|
type CloneConfig struct {
|
||||||
|
Name 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 (d *Driver) NewVM(ref *types.ManagedObjectReference) *VirtualMachine {
|
||||||
|
return &VirtualMachine{
|
||||||
|
vm: object.NewVirtualMachine(d.client.Client, *ref),
|
||||||
|
driver: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) FindVM(name string) (*VirtualMachine, error) {
|
||||||
|
vm, err := d.finder.VirtualMachine(d.ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &VirtualMachine{
|
||||||
|
vm: vm,
|
||||||
|
driver: d,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) Info(params ...string) (*mo.VirtualMachine, error) {
|
||||||
var p []string
|
var p []string
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
p = []string{"*"}
|
p = []string{"*"}
|
||||||
} else {
|
} else {
|
||||||
p = params
|
p = params
|
||||||
}
|
}
|
||||||
var vmInfo mo.VirtualMachine
|
var info mo.VirtualMachine
|
||||||
err := vm.Properties(d.ctx, vm.Reference(), p, &vmInfo)
|
err := vm.vm.Properties(vm.driver.ctx, vm.vm.Reference(), p, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &vmInfo, nil
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (template *VirtualMachine) Clone(config *CloneConfig) (*VirtualMachine, error) {
|
||||||
|
folder, err := template.driver.FindFolder(config.Folder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var relocateSpec types.VirtualMachineRelocateSpec
|
||||||
|
|
||||||
|
pool, err := template.driver.FindResourcePool(config.Host, config.ResourcePool)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
poolRef := pool.pool.Reference()
|
||||||
|
relocateSpec.Pool = &poolRef
|
||||||
|
|
||||||
|
if config.Datastore != "" {
|
||||||
|
datastore, err := template.driver.FindDatastore(config.Datastore)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
datastoreRef := datastore.ds.Reference()
|
||||||
|
relocateSpec.Datastore = &datastoreRef
|
||||||
|
}
|
||||||
|
|
||||||
|
var cloneSpec types.VirtualMachineCloneSpec
|
||||||
|
cloneSpec.Location = relocateSpec
|
||||||
|
cloneSpec.PowerOn = false
|
||||||
|
|
||||||
|
if config.LinkedClone == true {
|
||||||
|
cloneSpec.Location.DiskMoveType = "createNewChildDiskBacking"
|
||||||
|
|
||||||
|
tpl, err := template.Info("snapshot")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if tpl.Snapshot == nil {
|
||||||
|
err = errors.New("`linked_clone=true`, but template has no snapshots")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cloneSpec.Snapshot = tpl.Snapshot.CurrentSnapshot
|
||||||
|
}
|
||||||
|
|
||||||
|
task, err := template.vm.Clone(template.driver.ctx, folder.folder, config.Name, cloneSpec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := task.WaitForResult(template.driver.ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ref := info.Result.(types.ManagedObjectReference)
|
||||||
|
vm := template.driver.NewVM(&ref)
|
||||||
|
return vm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) Destroy() error {
|
||||||
|
task, err := vm.vm.Destroy(vm.driver.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = task.WaitForResult(vm.driver.ctx, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) Configure(config *HardwareConfig) error {
|
||||||
|
var confSpec types.VirtualMachineConfigSpec
|
||||||
|
confSpec.NumCPUs = config.CPUs
|
||||||
|
confSpec.MemoryMB = config.RAM
|
||||||
|
|
||||||
|
var cpuSpec types.ResourceAllocationInfo
|
||||||
|
cpuSpec.Reservation = config.CPUReservation
|
||||||
|
cpuSpec.Limit = config.CPULimit
|
||||||
|
confSpec.CpuAllocation = &cpuSpec
|
||||||
|
|
||||||
|
var ramSpec types.ResourceAllocationInfo
|
||||||
|
ramSpec.Reservation = config.RAMReservation
|
||||||
|
confSpec.MemoryAllocation = &ramSpec
|
||||||
|
|
||||||
|
confSpec.MemoryReservationLockedToMax = &config.RAMReserveAll
|
||||||
|
|
||||||
|
task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = task.WaitForResult(vm.driver.ctx, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) PowerOn() error {
|
||||||
|
task, err := vm.vm.PowerOn(vm.driver.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = task.WaitForResult(vm.driver.ctx, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) WaitForIP() (string, error) {
|
||||||
|
ip, err := vm.vm.WaitForIP(vm.driver.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) PowerOff() error {
|
||||||
|
state, err := vm.vm.PowerState(vm.driver.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if state == types.VirtualMachinePowerStatePoweredOff {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
task, err := vm.vm.PowerOff(vm.driver.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = task.WaitForResult(vm.driver.ctx, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) StartShutdown() error {
|
||||||
|
err := vm.vm.ShutdownGuest(vm.driver.ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) WaitForShutdown(timeout time.Duration) error {
|
||||||
|
shutdownTimer := time.After(timeout)
|
||||||
|
for {
|
||||||
|
powerState, err := vm.vm.PowerState(vm.driver.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if powerState == "poweredOff" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-shutdownTimer:
|
||||||
|
err := errors.New("Timeout while waiting for machine to shut down.")
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) CreateSnapshot(name string) error {
|
||||||
|
task, err := vm.vm.CreateSnapshot(vm.driver.ctx, name, "", false, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = task.WaitForResult(vm.driver.ctx, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) ConvertToTemplate() error {
|
||||||
|
err := vm.vm.MarkAsTemplate(vm.driver.ctx)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"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"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
|
@ -44,9 +43,14 @@ func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
ui.Say("Cloning VM...")
|
ui.Say("Cloning VM...")
|
||||||
|
|
||||||
vm, err := d.CloneVM(&driver.CloneConfig{
|
template, err := d.FindVM(s.config.Template)
|
||||||
Template: s.config.Template,
|
if err != nil {
|
||||||
VMName: s.config.VMName,
|
state.Put("error", err)
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
vm, err := template.Clone(&driver.CloneConfig{
|
||||||
|
Name: s.config.VMName,
|
||||||
Folder: s.config.Folder,
|
Folder: s.config.Folder,
|
||||||
Host: s.config.Host,
|
Host: s.config.Host,
|
||||||
ResourcePool: s.config.ResourcePool,
|
ResourcePool: s.config.ResourcePool,
|
||||||
|
@ -69,15 +73,13 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if vm, ok := state.GetOk("vm"); ok {
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
d := state.Get("driver").(*driver.Driver)
|
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||||
|
|
||||||
ui.Say("Destroying VM...")
|
ui.Say("Destroying VM...")
|
||||||
|
|
||||||
err := d.DestroyVM(vm.(*object.VirtualMachine))
|
err := vm.Destroy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
"github.com/vmware/govmomi/object"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
)
|
)
|
||||||
|
@ -33,13 +32,12 @@ 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.Driver)
|
vm := state.Get("vm").(*driver.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, &driver.HardwareConfig{
|
err := vm.Configure(&driver.HardwareConfig{
|
||||||
CPUs: s.config.CPUs,
|
CPUs: s.config.CPUs,
|
||||||
CPUReservation: s.config.CPUReservation,
|
CPUReservation: s.config.CPUReservation,
|
||||||
CPULimit: s.config.CPULimit,
|
CPULimit: s.config.CPULimit,
|
||||||
|
|
15
step_run.go
15
step_run.go
|
@ -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"
|
||||||
"github.com/vmware/govmomi/object"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
)
|
)
|
||||||
|
@ -13,18 +12,18 @@ 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.Driver)
|
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||||
vm := state.Get("vm").(*object.VirtualMachine)
|
|
||||||
|
|
||||||
ui.Say("Power on VM...")
|
ui.Say("Power on VM...")
|
||||||
err := d.PowerOn(vm)
|
|
||||||
|
err := vm.PowerOn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Waiting for IP...")
|
ui.Say("Waiting for IP...")
|
||||||
ip, err := d.WaitForIP(vm)
|
ip, err := vm.WaitForIP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
@ -43,11 +42,11 @@ func (s *StepRun) Cleanup(state multistep.StateBag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
d := state.Get("driver").(*driver.Driver)
|
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||||
vm := state.Get("vm").(*object.VirtualMachine)
|
|
||||||
|
|
||||||
ui.Say("Power off VM...")
|
ui.Say("Power off VM...")
|
||||||
err := d.PowerOff(vm)
|
|
||||||
|
err := vm.PowerOff()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
"github.com/vmware/govmomi/object"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
@ -41,8 +40,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.Driver)
|
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||||
vm := state.Get("vm").(*object.VirtualMachine)
|
|
||||||
|
|
||||||
if s.config.Command != "" {
|
if s.config.Command != "" {
|
||||||
ui.Say("Executing shutdown command...")
|
ui.Say("Executing shutdown command...")
|
||||||
|
@ -62,7 +60,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
} else {
|
} else {
|
||||||
ui.Say("Shut down VM...")
|
ui.Say("Shut down VM...")
|
||||||
|
|
||||||
err := d.StartShutdown(vm)
|
err := vm.StartShutdown()
|
||||||
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
|
||||||
|
@ -70,7 +68,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)
|
||||||
err := d.WaitForShutdown(vm, s.config.Timeout)
|
err := vm.WaitForShutdown(s.config.Timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
|
|
@ -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"
|
||||||
"github.com/vmware/govmomi/object"
|
|
||||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,13 +12,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)
|
||||||
d := state.Get("driver").(*driver.Driver)
|
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||||
vm := state.Get("vm").(*object.VirtualMachine)
|
|
||||||
|
|
||||||
if s.createSnapshot {
|
if s.createSnapshot {
|
||||||
ui.Say("Creating snapshot...")
|
ui.Say("Creating snapshot...")
|
||||||
|
|
||||||
err := d.CreateSnapshot(vm)
|
err := vm.CreateSnapshot("Created by Packer")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
|
|
@ -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"
|
||||||
"github.com/vmware/govmomi/object"
|
|
||||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,12 +12,11 @@ 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.Driver)
|
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||||
vm := state.Get("vm").(*object.VirtualMachine)
|
|
||||||
|
|
||||||
if s.ConvertToTemplate {
|
if s.ConvertToTemplate {
|
||||||
ui.Say("Convert VM into template...")
|
ui.Say("Convert VM into template...")
|
||||||
err := d.ConvertToTemplate(vm)
|
err := vm.ConvertToTemplate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
|
Loading…
Reference in New Issue