Add driver mocks and write tests to steps Remote Upload and Create VM (#9833)
This commit is contained in:
parent
cf622346ab
commit
942bfbf221
|
@ -139,7 +139,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
artifact := &common.Artifact{
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||
VM: state.Get("vm").(*driver.VirtualMachineDriver),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
if b.config.Export != nil {
|
||||
|
|
|
@ -67,7 +67,7 @@ type StepCloneVM struct {
|
|||
|
||||
func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
d := state.Get("driver").(*driver.Driver)
|
||||
d := state.Get("driver").(*driver.VCenterDriver)
|
||||
vmPath := path.Join(s.Location.Folder, s.Location.VMName)
|
||||
|
||||
err := d.PreCleanVM(ui, vmPath, s.Force)
|
||||
|
@ -128,7 +128,7 @@ func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
|
|||
if st == nil {
|
||||
return
|
||||
}
|
||||
vm := st.(*driver.VirtualMachine)
|
||||
vm := st.(*driver.VirtualMachineDriver)
|
||||
|
||||
ui.Say("Destroying VM...")
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ func (c *CustomizeConfig) Prepare() []error {
|
|||
}
|
||||
|
||||
func (s *StepCustomize) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
identity, err := s.identitySettings()
|
||||
|
|
|
@ -11,7 +11,7 @@ const BuilderId = "jetbrains.vsphere"
|
|||
type Artifact struct {
|
||||
Outconfig *OutputConfig
|
||||
Name string
|
||||
VM *driver.VirtualMachine
|
||||
VM *driver.VirtualMachineDriver
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
|
|
|
@ -43,7 +43,7 @@ type StepBootCommand struct {
|
|||
func (s *StepBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
debug := state.Get("debug").(bool)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.Config.BootCommand == nil {
|
||||
return multistep.ActionContinue
|
||||
|
|
|
@ -33,7 +33,7 @@ type StepConfigParams struct {
|
|||
|
||||
func (s *StepConfigParams) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
configParams := make(map[string]string)
|
||||
|
||||
if s.Config.ConfigParams != nil {
|
||||
|
|
|
@ -154,7 +154,7 @@ func (s *StepExport) Cleanup(multistep.StateBag) {
|
|||
|
||||
func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
ui.Message("Starting export...")
|
||||
lease, err := vm.Export()
|
||||
|
|
|
@ -65,7 +65,7 @@ type StepConfigureHardware struct {
|
|||
|
||||
func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if *s.Config != (HardwareConfig{}) {
|
||||
ui.Say("Customizing hardware...")
|
||||
|
|
|
@ -118,7 +118,7 @@ type StepImportToContentLibrary struct {
|
|||
|
||||
func (s *StepImportToContentLibrary) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
var err error
|
||||
|
||||
if s.ContentLibConfig.Ovf {
|
||||
|
@ -142,7 +142,7 @@ func (s *StepImportToContentLibrary) Run(_ context.Context, state multistep.Stat
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepImportToContentLibrary) importOvfTemplate(vm *driver.VirtualMachine) error {
|
||||
func (s *StepImportToContentLibrary) importOvfTemplate(vm *driver.VirtualMachineDriver) error {
|
||||
ovf := vcenter.OVF{
|
||||
Spec: vcenter.CreateSpec{
|
||||
Name: s.ContentLibConfig.Name,
|
||||
|
@ -154,7 +154,7 @@ func (s *StepImportToContentLibrary) importOvfTemplate(vm *driver.VirtualMachine
|
|||
return vm.ImportOvfToContentLibrary(ovf)
|
||||
}
|
||||
|
||||
func (s *StepImportToContentLibrary) importVmTemplate(vm *driver.VirtualMachine) error {
|
||||
func (s *StepImportToContentLibrary) importVmTemplate(vm *driver.VirtualMachineDriver) error {
|
||||
template := vcenter.Template{
|
||||
Name: s.ContentLibConfig.Name,
|
||||
Description: s.ContentLibConfig.Description,
|
||||
|
|
|
@ -24,7 +24,7 @@ type StepRun struct {
|
|||
|
||||
func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.Config.BootOrder != "" {
|
||||
ui.Say("Set boot order...")
|
||||
|
@ -55,7 +55,7 @@ func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.Ste
|
|||
|
||||
func (s *StepRun) Cleanup(state multistep.StateBag) {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.Config.BootOrder == "" && s.SetOrder {
|
||||
ui.Say("Clear boot order...")
|
||||
|
|
|
@ -48,7 +48,7 @@ type StepShutdown struct {
|
|||
func (s *StepShutdown) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
comm := state.Get("communicator").(packer.Communicator)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if off, _ := vm.IsPoweredOff(); off {
|
||||
// Probably power off initiated by last provisioner, though disable_shutdown is not set
|
||||
|
|
|
@ -14,7 +14,7 @@ type StepCreateSnapshot struct {
|
|||
|
||||
func (s *StepCreateSnapshot) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.CreateSnapshot {
|
||||
ui.Say("Creating snapshot...")
|
||||
|
|
|
@ -81,7 +81,7 @@ func (s *StepSshKeyPair) Run(ctx context.Context, state multistep.StateBag) mult
|
|||
s.Comm.SSHPublicKey = kp.PublicKeyAuthorizedKeysLine
|
||||
s.Comm.SSHClearAuthorizedKeys = true
|
||||
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
err = vm.AddPublicKeys(ctx, string(s.Comm.SSHPublicKey))
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("error saving temporary keypair in the vm: %s", err))
|
||||
|
|
|
@ -14,7 +14,7 @@ type StepConvertToTemplate struct {
|
|||
|
||||
func (s *StepConvertToTemplate) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.ConvertToTemplate {
|
||||
ui.Say("Convert VM into template...")
|
||||
|
|
|
@ -75,7 +75,7 @@ func (c *WaitIpConfig) GetIPNet() *net.IPNet {
|
|||
|
||||
func (s *StepWaitForIp) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
var ip string
|
||||
var err error
|
||||
|
@ -128,7 +128,7 @@ func (s *StepWaitForIp) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
}
|
||||
}
|
||||
|
||||
func doGetIp(vm *driver.VirtualMachine, ctx context.Context, c *WaitIpConfig) (string, error) {
|
||||
func doGetIp(vm *driver.VirtualMachineDriver, ctx context.Context, c *WaitIpConfig) (string, error) {
|
||||
var prevIp = ""
|
||||
var stopTime time.Time
|
||||
var interval time.Duration
|
||||
|
|
|
@ -34,7 +34,7 @@ func RenderConfig(config map[string]interface{}) string {
|
|||
return string(j)
|
||||
}
|
||||
|
||||
func TestConn(t *testing.T) *driver.Driver {
|
||||
func TestConn(t *testing.T) driver.Driver {
|
||||
username := os.Getenv("VSPHERE_USERNAME")
|
||||
if username == "" {
|
||||
username = "root"
|
||||
|
@ -56,7 +56,7 @@ func TestConn(t *testing.T) *driver.Driver {
|
|||
return d
|
||||
}
|
||||
|
||||
func GetVM(t *testing.T, d *driver.Driver, artifacts []packer.Artifact) *driver.VirtualMachine {
|
||||
func GetVM(t *testing.T, d driver.Driver, artifacts []packer.Artifact) driver.VirtualMachine {
|
||||
artifactRaw := artifacts[0]
|
||||
artifact, _ := artifactRaw.(*common.Artifact)
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ package driver
|
|||
import "github.com/vmware/govmomi/object"
|
||||
|
||||
type Cluster struct {
|
||||
driver *Driver
|
||||
driver *VCenterDriver
|
||||
cluster *object.ClusterComputeResource
|
||||
}
|
||||
|
||||
func (d *Driver) FindCluster(name string) (*Cluster, error) {
|
||||
func (d *VCenterDriver) FindCluster(name string) (*Cluster, error) {
|
||||
c, err := d.finder.ClusterComputeResource(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -13,20 +13,31 @@ import (
|
|||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Datastore struct {
|
||||
ds *object.Datastore
|
||||
driver *Driver
|
||||
type Datastore interface {
|
||||
Info(params ...string) (*mo.Datastore, error)
|
||||
FileExists(path string) bool
|
||||
Name() string
|
||||
ResolvePath(path string) string
|
||||
UploadFile(src, dst, host string, setHost bool) error
|
||||
Delete(path string) error
|
||||
MakeDirectory(path string) error
|
||||
Reference() types.ManagedObjectReference
|
||||
}
|
||||
|
||||
func (d *Driver) NewDatastore(ref *types.ManagedObjectReference) *Datastore {
|
||||
return &Datastore{
|
||||
type DatastoreDriver struct {
|
||||
ds *object.Datastore
|
||||
driver *VCenterDriver
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) NewDatastore(ref *types.ManagedObjectReference) Datastore {
|
||||
return &DatastoreDriver{
|
||||
ds: object.NewDatastore(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
// If name is an empty string, then resolve host's one
|
||||
func (d *Driver) FindDatastore(name string, host string) (*Datastore, error) {
|
||||
func (d *VCenterDriver) FindDatastore(name string, host string) (Datastore, error) {
|
||||
if name == "" {
|
||||
h, err := d.FindHost(host)
|
||||
if err != nil {
|
||||
|
@ -55,13 +66,13 @@ func (d *Driver) FindDatastore(name string, host string) (*Datastore, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &Datastore{
|
||||
return &DatastoreDriver{
|
||||
ds: ds,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetDatastoreName(id string) (string, error) {
|
||||
func (d *VCenterDriver) GetDatastoreName(id string) (string, error) {
|
||||
obj := types.ManagedObjectReference{
|
||||
Type: "Datastore",
|
||||
Value: id,
|
||||
|
@ -76,7 +87,7 @@ func (d *Driver) GetDatastoreName(id string) (string, error) {
|
|||
return me.Name, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) Info(params ...string) (*mo.Datastore, error) {
|
||||
func (ds *DatastoreDriver) Info(params ...string) (*mo.Datastore, error) {
|
||||
var p []string
|
||||
if len(params) == 0 {
|
||||
p = []string{"*"}
|
||||
|
@ -91,21 +102,25 @@ func (ds *Datastore) Info(params ...string) (*mo.Datastore, error) {
|
|||
return &info, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) FileExists(path string) bool {
|
||||
func (ds *DatastoreDriver) FileExists(path string) bool {
|
||||
_, err := ds.ds.Stat(ds.driver.ctx, path)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) Name() string {
|
||||
func (ds *DatastoreDriver) Name() string {
|
||||
return ds.ds.Name()
|
||||
}
|
||||
|
||||
func (ds *Datastore) ResolvePath(path string) string {
|
||||
func (ds *DatastoreDriver) Reference() types.ManagedObjectReference {
|
||||
return ds.ds.Reference()
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) ResolvePath(path string) string {
|
||||
return ds.ds.Path(path)
|
||||
}
|
||||
|
||||
// The file ID isn't available via the API, so we use DatastoreBrowser to search
|
||||
func (d *Driver) GetDatastoreFilePath(datastoreID, dir, filename string) (string, error) {
|
||||
func (d *VCenterDriver) GetDatastoreFilePath(datastoreID, dir, filename string) (string, error) {
|
||||
ref := types.ManagedObjectReference{Type: "Datastore", Value: datastoreID}
|
||||
ds := object.NewDatastore(d.vimClient, ref)
|
||||
|
||||
|
@ -140,11 +155,11 @@ func (d *Driver) GetDatastoreFilePath(datastoreID, dir, filename string) (string
|
|||
return res.File[0].GetFileInfo().Path, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) UploadFile(src, dst, host string, set_host_for_datastore_uploads bool) error {
|
||||
func (ds *DatastoreDriver) UploadFile(src, dst, host string, setHost bool) error {
|
||||
p := soap.DefaultUpload
|
||||
ctx := ds.driver.ctx
|
||||
|
||||
if set_host_for_datastore_uploads && host != "" {
|
||||
if setHost && host != "" {
|
||||
h, err := ds.driver.FindHost(host)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -155,7 +170,7 @@ func (ds *Datastore) UploadFile(src, dst, host string, set_host_for_datastore_up
|
|||
return ds.ds.UploadFile(ctx, src, dst, &p)
|
||||
}
|
||||
|
||||
func (ds *Datastore) Delete(path string) error {
|
||||
func (ds *DatastoreDriver) Delete(path string) error {
|
||||
dc, err := ds.driver.finder.Datacenter(ds.driver.ctx, ds.ds.DatacenterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -164,7 +179,7 @@ func (ds *Datastore) Delete(path string) error {
|
|||
return fm.Delete(ds.driver.ctx, path)
|
||||
}
|
||||
|
||||
func (ds *Datastore) MakeDirectory(path string) error {
|
||||
func (ds *DatastoreDriver) MakeDirectory(path string) error {
|
||||
dc, err := ds.driver.finder.Datacenter(ds.driver.ctx, ds.ds.DatacenterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type DatastoreMock struct {
|
||||
FileExistsCalled bool
|
||||
MakeDirectoryCalled bool
|
||||
UploadFileCalled bool
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) Info(params ...string) (*mo.Datastore, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) FileExists(path string) bool {
|
||||
ds.FileExistsCalled = true
|
||||
return false
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) Name() string {
|
||||
return "datastore-mock"
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) Reference() types.ManagedObjectReference {
|
||||
return types.ManagedObjectReference{}
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) ResolvePath(path string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) UploadFile(src, dst, host string, setHost bool) error {
|
||||
ds.UploadFileCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) Delete(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) MakeDirectory(path string) error {
|
||||
ds.MakeDirectoryCalled = true
|
||||
return nil
|
||||
}
|
|
@ -6,16 +6,46 @@ import (
|
|||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/session"
|
||||
"github.com/vmware/govmomi/vapi/library"
|
||||
"github.com/vmware/govmomi/vapi/rest"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
type Driver interface {
|
||||
NewVM(ref *types.ManagedObjectReference) VirtualMachine
|
||||
FindVM(name string) (VirtualMachine, error)
|
||||
FindCluster(name string) (*Cluster, error)
|
||||
PreCleanVM(ui packer.Ui, vmPath string, force bool) error
|
||||
CreateVM(config *CreateConfig) (VirtualMachine, error)
|
||||
|
||||
NewDatastore(ref *types.ManagedObjectReference) Datastore
|
||||
FindDatastore(name string, host string) (Datastore, error)
|
||||
GetDatastoreName(id string) (string, error)
|
||||
GetDatastoreFilePath(datastoreID, dir, filename string) (string, error)
|
||||
|
||||
NewFolder(ref *types.ManagedObjectReference) *Folder
|
||||
FindFolder(name string) (*Folder, error)
|
||||
NewHost(ref *types.ManagedObjectReference) *Host
|
||||
FindHost(name string) (*Host, error)
|
||||
NewNetwork(ref *types.ManagedObjectReference) *Network
|
||||
FindNetwork(name string) (*Network, error)
|
||||
FindNetworks(name string) ([]*Network, error)
|
||||
NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool
|
||||
FindResourcePool(cluster string, host string, name string) (*ResourcePool, error)
|
||||
|
||||
FindContentLibraryByName(name string) (*Library, error)
|
||||
FindContentLibraryItem(libraryId string, name string) (*library.Item, error)
|
||||
FindContentLibraryFileDatastorePath(isoPath string) (string, error)
|
||||
}
|
||||
|
||||
type VCenterDriver struct {
|
||||
// context that controls the authenticated sessions used to run the VM commands
|
||||
ctx context.Context
|
||||
client *govmomi.Client
|
||||
|
@ -33,7 +63,7 @@ type ConnectConfig struct {
|
|||
Datacenter string
|
||||
}
|
||||
|
||||
func NewDriver(config *ConnectConfig) (*Driver, error) {
|
||||
func NewDriver(config *ConnectConfig) (Driver, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
vcenterUrl, err := url.Parse(fmt.Sprintf("https://%v/sdk", config.VCenterServer))
|
||||
|
@ -67,7 +97,8 @@ func NewDriver(config *ConnectConfig) (*Driver, error) {
|
|||
}
|
||||
finder.SetDatacenter(datacenter)
|
||||
|
||||
d := Driver{
|
||||
var d Driver
|
||||
d = &VCenterDriver{
|
||||
ctx: ctx,
|
||||
client: client,
|
||||
vimClient: vimClient,
|
||||
|
@ -78,7 +109,7 @@ func NewDriver(config *ConnectConfig) (*Driver, error) {
|
|||
datacenter: datacenter,
|
||||
finder: finder,
|
||||
}
|
||||
return &d, nil
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// The rest.Client requires vCenter.
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/vmware/govmomi/vapi/library"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type DriverMock struct {
|
||||
FindDatastoreCalled bool
|
||||
DatastoreMock *DatastoreMock
|
||||
|
||||
PreCleanShouldFail bool
|
||||
PreCleanVMCalled bool
|
||||
PreCleanForce bool
|
||||
PreCleanVMPath string
|
||||
|
||||
CreateVMShouldFail bool
|
||||
CreateVMCalled bool
|
||||
CreateConfig *CreateConfig
|
||||
VM VirtualMachine
|
||||
}
|
||||
|
||||
func NewDriverMock() *DriverMock {
|
||||
return new(DriverMock)
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindDatastore(name string, host string) (Datastore, error) {
|
||||
d.FindDatastoreCalled = true
|
||||
if d.DatastoreMock == nil {
|
||||
d.DatastoreMock = new(DatastoreMock)
|
||||
}
|
||||
return d.DatastoreMock, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) NewVM(ref *types.ManagedObjectReference) VirtualMachine {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindVM(name string) (VirtualMachine, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindCluster(name string) (*Cluster, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) PreCleanVM(ui packer.Ui, vmPath string, force bool) error {
|
||||
d.PreCleanVMCalled = true
|
||||
if d.PreCleanShouldFail {
|
||||
return fmt.Errorf("pre clean failed")
|
||||
}
|
||||
d.PreCleanForce = true
|
||||
d.PreCleanVMPath = vmPath
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) CreateVM(config *CreateConfig) (VirtualMachine, error) {
|
||||
d.CreateVMCalled = true
|
||||
if d.CreateVMShouldFail {
|
||||
return nil, fmt.Errorf("create vm failed")
|
||||
}
|
||||
d.CreateConfig = config
|
||||
d.VM = new(VirtualMachineDriver)
|
||||
return d.VM, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) NewDatastore(ref *types.ManagedObjectReference) Datastore { return nil }
|
||||
|
||||
func (d *DriverMock) GetDatastoreName(id string) (string, error) { return "", nil }
|
||||
|
||||
func (d *DriverMock) GetDatastoreFilePath(datastoreID, dir, filename string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) NewFolder(ref *types.ManagedObjectReference) *Folder { return nil }
|
||||
|
||||
func (d *DriverMock) FindFolder(name string) (*Folder, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) NewHost(ref *types.ManagedObjectReference) *Host { return nil }
|
||||
|
||||
func (d *DriverMock) FindHost(name string) (*Host, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) NewNetwork(ref *types.ManagedObjectReference) *Network { return nil }
|
||||
|
||||
func (d *DriverMock) FindNetwork(name string) (*Network, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) FindNetworks(name string) ([]*Network, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool { return nil }
|
||||
|
||||
func (d *DriverMock) FindResourcePool(cluster string, host string, name string) (*ResourcePool, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindContentLibraryByName(name string) (*Library, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) FindContentLibraryItem(libraryId string, name string) (*library.Item, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindContentLibraryFileDatastorePath(isoPath string) (string, error) {
|
||||
return "", nil
|
||||
}
|
|
@ -11,7 +11,7 @@ import (
|
|||
// Defines whether acceptance tests should be run
|
||||
const TestHostName = "esxi-1.vsphere65.test"
|
||||
|
||||
func newTestDriver(t *testing.T) *Driver {
|
||||
func newTestDriver(t *testing.T) Driver {
|
||||
username := os.Getenv("VSPHERE_USERNAME")
|
||||
if username == "" {
|
||||
username = "root"
|
||||
|
|
|
@ -12,18 +12,18 @@ import (
|
|||
)
|
||||
|
||||
type Folder struct {
|
||||
driver *Driver
|
||||
driver *VCenterDriver
|
||||
folder *object.Folder
|
||||
}
|
||||
|
||||
func (d *Driver) NewFolder(ref *types.ManagedObjectReference) *Folder {
|
||||
func (d *VCenterDriver) NewFolder(ref *types.ManagedObjectReference) *Folder {
|
||||
return &Folder{
|
||||
folder: object.NewFolder(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) FindFolder(name string) (*Folder, error) {
|
||||
func (d *VCenterDriver) FindFolder(name string) (*Folder, error) {
|
||||
if name != "" {
|
||||
// create folders if they don't exist
|
||||
parent := ""
|
||||
|
|
|
@ -7,18 +7,18 @@ import (
|
|||
)
|
||||
|
||||
type Host struct {
|
||||
driver *Driver
|
||||
driver *VCenterDriver
|
||||
host *object.HostSystem
|
||||
}
|
||||
|
||||
func (d *Driver) NewHost(ref *types.ManagedObjectReference) *Host {
|
||||
func (d *VCenterDriver) NewHost(ref *types.ManagedObjectReference) *Host {
|
||||
return &Host{
|
||||
host: object.NewHostSystem(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) FindHost(name string) (*Host, error) {
|
||||
func (d *VCenterDriver) FindHost(name string) (*Host, error) {
|
||||
h, err := d.finder.HostSystem(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -10,11 +10,11 @@ import (
|
|||
)
|
||||
|
||||
type Library struct {
|
||||
driver *Driver
|
||||
driver *VCenterDriver
|
||||
library *library.Library
|
||||
}
|
||||
|
||||
func (d *Driver) FindContentLibraryByName(name string) (*Library, error) {
|
||||
func (d *VCenterDriver) FindContentLibraryByName(name string) (*Library, error) {
|
||||
lm := library.NewManager(d.restClient.client)
|
||||
l, err := lm.GetLibraryByName(d.ctx, name)
|
||||
if err != nil {
|
||||
|
@ -26,7 +26,7 @@ func (d *Driver) FindContentLibraryByName(name string) (*Library, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) FindContentLibraryItem(libraryId string, name string) (*library.Item, error) {
|
||||
func (d *VCenterDriver) FindContentLibraryItem(libraryId string, name string) (*library.Item, error) {
|
||||
lm := library.NewManager(d.restClient.client)
|
||||
items, err := lm.GetLibraryItems(d.ctx, libraryId)
|
||||
if err != nil {
|
||||
|
@ -40,7 +40,7 @@ func (d *Driver) FindContentLibraryItem(libraryId string, name string) (*library
|
|||
return nil, fmt.Errorf("Item %s not found", name)
|
||||
}
|
||||
|
||||
func (d *Driver) FindContentLibraryFileDatastorePath(isoPath string) (string, error) {
|
||||
func (d *VCenterDriver) FindContentLibraryFileDatastorePath(isoPath string) (string, error) {
|
||||
log.Printf("Check if ISO path is a Content Library path")
|
||||
err := d.restClient.Login(d.ctx)
|
||||
if err != nil {
|
||||
|
|
|
@ -9,18 +9,18 @@ import (
|
|||
)
|
||||
|
||||
type Network struct {
|
||||
driver *Driver
|
||||
driver *VCenterDriver
|
||||
network object.NetworkReference
|
||||
}
|
||||
|
||||
func (d *Driver) NewNetwork(ref *types.ManagedObjectReference) *Network {
|
||||
func (d *VCenterDriver) NewNetwork(ref *types.ManagedObjectReference) *Network {
|
||||
return &Network{
|
||||
network: object.NewNetwork(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) FindNetwork(name string) (*Network, error) {
|
||||
func (d *VCenterDriver) FindNetwork(name string) (*Network, error) {
|
||||
n, err := d.finder.Network(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -31,7 +31,7 @@ func (d *Driver) FindNetwork(name string) (*Network, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) FindNetworks(name string) ([]*Network, error) {
|
||||
func (d *VCenterDriver) FindNetworks(name string) ([]*Network, error) {
|
||||
ns, err := d.finder.NetworkList(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -10,17 +10,17 @@ import (
|
|||
|
||||
type ResourcePool struct {
|
||||
pool *object.ResourcePool
|
||||
driver *Driver
|
||||
driver *VCenterDriver
|
||||
}
|
||||
|
||||
func (d *Driver) NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool {
|
||||
func (d *VCenterDriver) NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool {
|
||||
return &ResourcePool{
|
||||
pool: object.NewResourcePool(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) FindResourcePool(cluster string, host string, name string) (*ResourcePool, error) {
|
||||
func (d *VCenterDriver) FindResourcePool(cluster string, host string, name string) (*ResourcePool, error) {
|
||||
var res string
|
||||
if cluster != "" {
|
||||
res = cluster
|
||||
|
|
|
@ -21,9 +21,43 @@ import (
|
|||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type VirtualMachine struct {
|
||||
type VirtualMachine interface {
|
||||
Info(params ...string) (*mo.VirtualMachine, error)
|
||||
Devices() (object.VirtualDeviceList, error)
|
||||
Clone(ctx context.Context, config *CloneConfig) (VirtualMachine, error)
|
||||
updateVAppConfig(ctx context.Context, newProps map[string]string) (*types.VmConfigSpec, error)
|
||||
AddPublicKeys(ctx context.Context, publicKeys string) error
|
||||
Properties(ctx context.Context) (*mo.VirtualMachine, error)
|
||||
Destroy() error
|
||||
Configure(config *HardwareConfig) error
|
||||
Customize(spec types.CustomizationSpec) error
|
||||
ResizeDisk(diskSize int64) error
|
||||
PowerOn() error
|
||||
WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error)
|
||||
PowerOff() error
|
||||
IsPoweredOff() (bool, error)
|
||||
StartShutdown() error
|
||||
WaitForShutdown(ctx context.Context, timeout time.Duration) error
|
||||
CreateSnapshot(name string) error
|
||||
ConvertToTemplate() error
|
||||
ImportOvfToContentLibrary(ovf vcenter.OVF) error
|
||||
ImportToContentLibrary(template vcenter.Template) error
|
||||
GetDir() (string, error)
|
||||
AddCdrom(controllerType string, datastoreIsoPath string) error
|
||||
AddFloppy(imgPath string) error
|
||||
SetBootOrder(order []string) error
|
||||
RemoveDevice(keepFiles bool, device ...types.BaseVirtualDevice) error
|
||||
addDevice(device types.BaseVirtualDevice) error
|
||||
AddConfigParams(params map[string]string, info *types.ToolsConfigInfo) error
|
||||
Export() (*nfc.Lease, error)
|
||||
CreateDescriptor(m *ovf.Manager, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error)
|
||||
NewOvfManager() *ovf.Manager
|
||||
GetOvfExportOptions(m *ovf.Manager) ([]types.OvfOptionInfo, error)
|
||||
}
|
||||
|
||||
type VirtualMachineDriver struct {
|
||||
vm *object.VirtualMachine
|
||||
driver *Driver
|
||||
driver *VCenterDriver
|
||||
}
|
||||
|
||||
type CloneConfig struct {
|
||||
|
@ -87,25 +121,25 @@ type Disk struct {
|
|||
ControllerIndex int
|
||||
}
|
||||
|
||||
func (d *Driver) NewVM(ref *types.ManagedObjectReference) *VirtualMachine {
|
||||
return &VirtualMachine{
|
||||
func (d *VCenterDriver) NewVM(ref *types.ManagedObjectReference) VirtualMachine {
|
||||
return &VirtualMachineDriver{
|
||||
vm: object.NewVirtualMachine(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) FindVM(name string) (*VirtualMachine, error) {
|
||||
func (d *VCenterDriver) FindVM(name string) (VirtualMachine, error) {
|
||||
vm, err := d.finder.VirtualMachine(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &VirtualMachine{
|
||||
return &VirtualMachineDriver{
|
||||
vm: vm,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) PreCleanVM(ui packer.Ui, vmPath string, force bool) error {
|
||||
func (d *VCenterDriver) PreCleanVM(ui packer.Ui, vmPath string, force bool) error {
|
||||
vm, err := d.FindVM(vmPath)
|
||||
if err != nil {
|
||||
if _, ok := err.(*find.NotFoundError); !ok {
|
||||
|
@ -130,7 +164,7 @@ func (d *Driver) PreCleanVM(ui packer.Ui, vmPath string, force bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) CreateVM(config *CreateConfig) (*VirtualMachine, error) {
|
||||
func (d *VCenterDriver) CreateVM(config *CreateConfig) (VirtualMachine, error) {
|
||||
createSpec := types.VirtualMachineConfigSpec{
|
||||
Name: config.Name,
|
||||
Annotation: config.Annotation,
|
||||
|
@ -219,7 +253,7 @@ func (d *Driver) CreateVM(config *CreateConfig) (*VirtualMachine, error) {
|
|||
return d.NewVM(&vmRef), nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Info(params ...string) (*mo.VirtualMachine, error) {
|
||||
func (vm *VirtualMachineDriver) Info(params ...string) (*mo.VirtualMachine, error) {
|
||||
var p []string
|
||||
if len(params) == 0 {
|
||||
p = []string{"*"}
|
||||
|
@ -234,7 +268,7 @@ func (vm *VirtualMachine) Info(params ...string) (*mo.VirtualMachine, error) {
|
|||
return &info, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Devices() (object.VirtualDeviceList, error) {
|
||||
func (vm *VirtualMachineDriver) Devices() (object.VirtualDeviceList, error) {
|
||||
vmInfo, err := vm.Info("config.hardware.device")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -243,7 +277,7 @@ func (vm *VirtualMachine) Devices() (object.VirtualDeviceList, error) {
|
|||
return vmInfo.Config.Hardware.Device, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Clone(ctx context.Context, config *CloneConfig) (*VirtualMachine, error) {
|
||||
func (vm *VirtualMachineDriver) Clone(ctx context.Context, config *CloneConfig) (VirtualMachine, error) {
|
||||
folder, err := vm.driver.FindFolder(config.Folder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -262,7 +296,7 @@ func (vm *VirtualMachine) Clone(ctx context.Context, config *CloneConfig) (*Virt
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
datastoreRef := datastore.ds.Reference()
|
||||
datastoreRef := datastore.Reference()
|
||||
relocateSpec.Datastore = &datastoreRef
|
||||
|
||||
var cloneSpec types.VirtualMachineCloneSpec
|
||||
|
@ -350,7 +384,7 @@ func (vm *VirtualMachine) Clone(ctx context.Context, config *CloneConfig) (*Virt
|
|||
return created, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) updateVAppConfig(ctx context.Context, newProps map[string]string) (*types.VmConfigSpec, error) {
|
||||
func (vm *VirtualMachineDriver) updateVAppConfig(ctx context.Context, newProps map[string]string) (*types.VmConfigSpec, error) {
|
||||
if len(newProps) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -398,7 +432,7 @@ func (vm *VirtualMachine) updateVAppConfig(ctx context.Context, newProps map[str
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) AddPublicKeys(ctx context.Context, publicKeys string) error {
|
||||
func (vm *VirtualMachineDriver) AddPublicKeys(ctx context.Context, publicKeys string) error {
|
||||
newProps := map[string]string{"public-keys": publicKeys}
|
||||
config, err := vm.updateVAppConfig(ctx, newProps)
|
||||
if err != nil {
|
||||
|
@ -415,7 +449,7 @@ func (vm *VirtualMachine) AddPublicKeys(ctx context.Context, publicKeys string)
|
|||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Properties(ctx context.Context) (*mo.VirtualMachine, error) {
|
||||
func (vm *VirtualMachineDriver) Properties(ctx context.Context) (*mo.VirtualMachine, error) {
|
||||
log.Printf("fetching properties for VM %q", vm.vm.InventoryPath)
|
||||
var props mo.VirtualMachine
|
||||
if err := vm.vm.Properties(ctx, vm.vm.Reference(), nil, &props); err != nil {
|
||||
|
@ -424,7 +458,7 @@ func (vm *VirtualMachine) Properties(ctx context.Context) (*mo.VirtualMachine, e
|
|||
return &props, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Destroy() error {
|
||||
func (vm *VirtualMachineDriver) Destroy() error {
|
||||
task, err := vm.vm.Destroy(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -433,7 +467,7 @@ func (vm *VirtualMachine) Destroy() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Configure(config *HardwareConfig) error {
|
||||
func (vm *VirtualMachineDriver) Configure(config *HardwareConfig) error {
|
||||
var confSpec types.VirtualMachineConfigSpec
|
||||
confSpec.NumCPUs = config.CPUs
|
||||
confSpec.NumCoresPerSocket = config.CpuCores
|
||||
|
@ -524,7 +558,7 @@ func (vm *VirtualMachine) Configure(config *HardwareConfig) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Customize(spec types.CustomizationSpec) error {
|
||||
func (vm *VirtualMachineDriver) Customize(spec types.CustomizationSpec) error {
|
||||
task, err := vm.vm.Customize(vm.driver.ctx, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -532,7 +566,7 @@ func (vm *VirtualMachine) Customize(spec types.CustomizationSpec) error {
|
|||
return task.Wait(vm.driver.ctx)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) ResizeDisk(diskSize int64) error {
|
||||
func (vm *VirtualMachineDriver) ResizeDisk(diskSize int64) error {
|
||||
var confSpec types.VirtualMachineConfigSpec
|
||||
|
||||
devices, err := vm.vm.Device(vm.driver.ctx)
|
||||
|
@ -581,7 +615,7 @@ func findDisk(devices object.VirtualDeviceList) (*types.VirtualDisk, error) {
|
|||
return nil, errors.New("VM has multiple disks")
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) PowerOn() error {
|
||||
func (vm *VirtualMachineDriver) PowerOn() error {
|
||||
task, err := vm.vm.PowerOn(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -590,7 +624,7 @@ func (vm *VirtualMachine) PowerOn() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error) {
|
||||
func (vm *VirtualMachineDriver) WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error) {
|
||||
netIP, err := vm.vm.WaitForNetIP(ctx, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -614,7 +648,7 @@ func (vm *VirtualMachine) WaitForIP(ctx context.Context, ipNet *net.IPNet) (stri
|
|||
return "", fmt.Errorf("unable to find an IP")
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) PowerOff() error {
|
||||
func (vm *VirtualMachineDriver) PowerOff() error {
|
||||
state, err := vm.vm.PowerState(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -632,7 +666,7 @@ func (vm *VirtualMachine) PowerOff() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) IsPoweredOff() (bool, error) {
|
||||
func (vm *VirtualMachineDriver) IsPoweredOff() (bool, error) {
|
||||
state, err := vm.vm.PowerState(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -641,12 +675,12 @@ func (vm *VirtualMachine) IsPoweredOff() (bool, error) {
|
|||
return state == types.VirtualMachinePowerStatePoweredOff, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) StartShutdown() error {
|
||||
func (vm *VirtualMachineDriver) StartShutdown() error {
|
||||
err := vm.vm.ShutdownGuest(vm.driver.ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) WaitForShutdown(ctx context.Context, timeout time.Duration) error {
|
||||
func (vm *VirtualMachineDriver) WaitForShutdown(ctx context.Context, timeout time.Duration) error {
|
||||
shutdownTimer := time.After(timeout)
|
||||
for {
|
||||
off, err := vm.IsPoweredOff()
|
||||
|
@ -670,7 +704,7 @@ func (vm *VirtualMachine) WaitForShutdown(ctx context.Context, timeout time.Dura
|
|||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) CreateSnapshot(name string) error {
|
||||
func (vm *VirtualMachineDriver) CreateSnapshot(name string) error {
|
||||
task, err := vm.vm.CreateSnapshot(vm.driver.ctx, name, "", false, false)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -679,11 +713,11 @@ func (vm *VirtualMachine) CreateSnapshot(name string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) ConvertToTemplate() error {
|
||||
func (vm *VirtualMachineDriver) ConvertToTemplate() error {
|
||||
return vm.vm.MarkAsTemplate(vm.driver.ctx)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) ImportOvfToContentLibrary(ovf vcenter.OVF) error {
|
||||
func (vm *VirtualMachineDriver) ImportOvfToContentLibrary(ovf vcenter.OVF) error {
|
||||
err := vm.driver.restClient.Login(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -717,7 +751,7 @@ func (vm *VirtualMachine) ImportOvfToContentLibrary(ovf vcenter.OVF) error {
|
|||
return vm.driver.restClient.Logout(vm.driver.ctx)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) ImportToContentLibrary(template vcenter.Template) error {
|
||||
func (vm *VirtualMachineDriver) ImportToContentLibrary(template vcenter.Template) error {
|
||||
err := vm.driver.restClient.Login(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -769,7 +803,7 @@ func (vm *VirtualMachine) ImportToContentLibrary(template vcenter.Template) erro
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
template.VMHomeStorage.Datastore = d.ds.Reference().Value
|
||||
template.VMHomeStorage.Datastore = d.Reference().Value
|
||||
}
|
||||
|
||||
vcm := vcenter.NewManager(vm.driver.restClient.client)
|
||||
|
@ -781,7 +815,7 @@ func (vm *VirtualMachine) ImportToContentLibrary(template vcenter.Template) erro
|
|||
return vm.driver.restClient.Logout(vm.driver.ctx)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) GetDir() (string, error) {
|
||||
func (vm *VirtualMachineDriver) GetDir() (string, error) {
|
||||
vmInfo, err := vm.Info("name", "layoutEx.file")
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -789,14 +823,14 @@ func (vm *VirtualMachine) GetDir() (string, error) {
|
|||
|
||||
vmxName := fmt.Sprintf("/%s.vmx", vmInfo.Name)
|
||||
for _, file := range vmInfo.LayoutEx.File {
|
||||
if strings.HasSuffix(file.Name, vmxName) {
|
||||
if strings.Contains(file.Name, vmInfo.Name) {
|
||||
return RemoveDatastorePrefix(file.Name[:len(file.Name)-len(vmxName)]), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("cannot find '%s'", vmxName)
|
||||
}
|
||||
|
||||
func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
|
||||
func addDisk(_ *VCenterDriver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
|
||||
if len(config.Storage) == 0 {
|
||||
return nil, errors.New("no storage devices have been defined")
|
||||
}
|
||||
|
@ -839,7 +873,7 @@ func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig)
|
|||
return devices, nil
|
||||
}
|
||||
|
||||
func addNetwork(d *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
|
||||
func addNetwork(d *VCenterDriver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
|
||||
if len(config.NICs) == 0 {
|
||||
return nil, errors.New("no network adapters have been defined")
|
||||
}
|
||||
|
@ -872,7 +906,7 @@ func addNetwork(d *Driver, devices object.VirtualDeviceList, config *CreateConfi
|
|||
return devices, nil
|
||||
}
|
||||
|
||||
func findNetwork(network string, host string, d *Driver) (object.NetworkReference, error) {
|
||||
func findNetwork(network string, host string, d *VCenterDriver) (object.NetworkReference, error) {
|
||||
if network != "" {
|
||||
var err error
|
||||
networks, err := d.FindNetworks(network)
|
||||
|
@ -941,7 +975,7 @@ func newVGPUProfile(vGPUProfile string) types.VirtualPCIPassthrough {
|
|||
}
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) AddCdrom(controllerType string, datastoreIsoPath string) error {
|
||||
func (vm *VirtualMachineDriver) AddCdrom(controllerType string, datastoreIsoPath string) error {
|
||||
devices, err := vm.vm.Device(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -985,7 +1019,7 @@ func (vm *VirtualMachine) AddCdrom(controllerType string, datastoreIsoPath strin
|
|||
return vm.addDevice(cdrom)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) AddFloppy(imgPath string) error {
|
||||
func (vm *VirtualMachineDriver) AddFloppy(imgPath string) error {
|
||||
devices, err := vm.vm.Device(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1003,7 +1037,7 @@ func (vm *VirtualMachine) AddFloppy(imgPath string) error {
|
|||
return vm.addDevice(floppy)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) SetBootOrder(order []string) error {
|
||||
func (vm *VirtualMachineDriver) SetBootOrder(order []string) error {
|
||||
devices, err := vm.vm.Device(vm.driver.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1016,11 +1050,11 @@ func (vm *VirtualMachine) SetBootOrder(order []string) error {
|
|||
return vm.vm.SetBootOptions(vm.driver.ctx, &bootOptions)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) RemoveDevice(keepFiles bool, device ...types.BaseVirtualDevice) error {
|
||||
func (vm *VirtualMachineDriver) RemoveDevice(keepFiles bool, device ...types.BaseVirtualDevice) error {
|
||||
return vm.vm.RemoveDevice(vm.driver.ctx, keepFiles, device...)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) addDevice(device types.BaseVirtualDevice) error {
|
||||
func (vm *VirtualMachineDriver) addDevice(device types.BaseVirtualDevice) error {
|
||||
newDevices := object.VirtualDeviceList{device}
|
||||
confSpec := types.VirtualMachineConfigSpec{}
|
||||
var err error
|
||||
|
@ -1038,7 +1072,7 @@ func (vm *VirtualMachine) addDevice(device types.BaseVirtualDevice) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) AddConfigParams(params map[string]string, info *types.ToolsConfigInfo) error {
|
||||
func (vm *VirtualMachineDriver) AddConfigParams(params map[string]string, info *types.ToolsConfigInfo) error {
|
||||
var confSpec types.VirtualMachineConfigSpec
|
||||
|
||||
var ov []types.BaseOptionValue
|
||||
|
@ -1066,19 +1100,19 @@ func (vm *VirtualMachine) AddConfigParams(params map[string]string, info *types.
|
|||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) Export() (*nfc.Lease, error) {
|
||||
func (vm *VirtualMachineDriver) Export() (*nfc.Lease, error) {
|
||||
return vm.vm.Export(vm.driver.ctx)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) CreateDescriptor(m *ovf.Manager, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
|
||||
func (vm *VirtualMachineDriver) CreateDescriptor(m *ovf.Manager, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
|
||||
return m.CreateDescriptor(vm.driver.ctx, vm.vm, cdp)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) NewOvfManager() *ovf.Manager {
|
||||
func (vm *VirtualMachineDriver) NewOvfManager() *ovf.Manager {
|
||||
return ovf.NewManager(vm.vm.Client())
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) GetOvfExportOptions(m *ovf.Manager) ([]types.OvfOptionInfo, error) {
|
||||
func (vm *VirtualMachineDriver) GetOvfExportOptions(m *ovf.Manager) ([]types.OvfOptionInfo, error) {
|
||||
var mgr mo.OvfManager
|
||||
err := property.DefaultCollector(vm.vm.Client()).RetrieveOne(vm.driver.ctx, m.Reference(), nil, &mgr)
|
||||
if err != nil {
|
||||
|
|
|
@ -10,12 +10,12 @@ var (
|
|||
ErrNoSataController = errors.New("no available SATA controller")
|
||||
)
|
||||
|
||||
func (vm *VirtualMachine) AddSATAController() error {
|
||||
func (vm *VirtualMachineDriver) AddSATAController() error {
|
||||
sata := &types.VirtualAHCIController{}
|
||||
return vm.addDevice(sata)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) FindSATAController() (*types.VirtualAHCIController, error) {
|
||||
func (vm *VirtualMachineDriver) FindSATAController() (*types.VirtualAHCIController, error) {
|
||||
l, err := vm.Devices()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -29,7 +29,7 @@ func (vm *VirtualMachine) FindSATAController() (*types.VirtualAHCIController, er
|
|||
return c.(*types.VirtualAHCIController), nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) CreateCdrom(c *types.VirtualController) (*types.VirtualCdrom, error) {
|
||||
func (vm *VirtualMachineDriver) CreateCdrom(c *types.VirtualController) (*types.VirtualCdrom, error) {
|
||||
l, err := vm.Devices()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -52,7 +52,7 @@ func (vm *VirtualMachine) CreateCdrom(c *types.VirtualController) (*types.Virtua
|
|||
return device, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) RemoveCdroms() error {
|
||||
func (vm *VirtualMachineDriver) RemoveCdroms() error {
|
||||
devices, err := vm.Devices()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -69,7 +69,7 @@ func (vm *VirtualMachine) RemoveCdroms() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) EjectCdroms() error {
|
||||
func (vm *VirtualMachineDriver) EjectCdroms() error {
|
||||
devices, err := vm.Devices()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -13,7 +13,7 @@ func TestVMAcc_clone(t *testing.T) {
|
|||
testCases := []struct {
|
||||
name string
|
||||
config *CloneConfig
|
||||
checkFunction func(*testing.T, *VirtualMachine, *CloneConfig)
|
||||
checkFunction func(*testing.T, VirtualMachine, *CloneConfig)
|
||||
}{
|
||||
{"Default", &CloneConfig{}, cloneDefaultCheck},
|
||||
{"LinkedClone", &CloneConfig{LinkedClone: true}, cloneLinkedCloneCheck},
|
||||
|
@ -53,8 +53,8 @@ func TestVMAcc_clone(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func cloneDefaultCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
||||
d := vm.driver
|
||||
func cloneDefaultCheck(t *testing.T, vm VirtualMachine, config *CloneConfig) {
|
||||
d := vm.(*VirtualMachineDriver).driver
|
||||
|
||||
// Check that the clone can be found by its name
|
||||
if _, err := d.FindVM(config.Name); err != nil {
|
||||
|
@ -112,7 +112,7 @@ func cloneDefaultCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func configureCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) {
|
||||
func configureCheck(t *testing.T, vm VirtualMachine, _ *CloneConfig) {
|
||||
log.Printf("[DEBUG] Configuring the vm")
|
||||
hwConfig := &HardwareConfig{
|
||||
CPUs: 2,
|
||||
|
@ -170,7 +170,7 @@ func configureCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func configureRAMReserveAllCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) {
|
||||
func configureRAMReserveAllCheck(t *testing.T, vm VirtualMachine, _ *CloneConfig) {
|
||||
log.Printf("[DEBUG] Configuring the vm")
|
||||
err := vm.Configure(&HardwareConfig{RAMReserveAll: true})
|
||||
if err != nil {
|
||||
|
@ -188,7 +188,7 @@ func configureRAMReserveAllCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfi
|
|||
}
|
||||
}
|
||||
|
||||
func cloneLinkedCloneCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) {
|
||||
func cloneLinkedCloneCheck(t *testing.T, vm VirtualMachine, _ *CloneConfig) {
|
||||
vmInfo, err := vm.Info("layoutEx.disk")
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot read VM properties: %v", err)
|
||||
|
@ -199,13 +199,13 @@ func cloneLinkedCloneCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func cloneFolderCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
||||
func cloneFolderCheck(t *testing.T, vm VirtualMachine, config *CloneConfig) {
|
||||
vmInfo, err := vm.Info("parent")
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot read VM properties: %v", err)
|
||||
}
|
||||
|
||||
f := vm.driver.NewFolder(vmInfo.Parent)
|
||||
f := vm.(*VirtualMachineDriver).driver.NewFolder(vmInfo.Parent)
|
||||
path, err := f.Path()
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot read folder name: %v", err)
|
||||
|
@ -215,13 +215,13 @@ func cloneFolderCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func cloneResourcePoolCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
||||
func cloneResourcePoolCheck(t *testing.T, vm VirtualMachine, config *CloneConfig) {
|
||||
vmInfo, err := vm.Info("resourcePool")
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot read VM properties: %v", err)
|
||||
}
|
||||
|
||||
p := vm.driver.NewResourcePool(vmInfo.ResourcePool)
|
||||
p := vm.(*VirtualMachineDriver).driver.NewResourcePool(vmInfo.ResourcePool)
|
||||
path, err := p.Path()
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot read resource pool name: %v", err)
|
||||
|
@ -231,7 +231,7 @@ func cloneResourcePoolCheck(t *testing.T, vm *VirtualMachine, config *CloneConfi
|
|||
}
|
||||
}
|
||||
|
||||
func startAndStopCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
||||
func startAndStopCheck(t *testing.T, vm VirtualMachine, config *CloneConfig) {
|
||||
stopper := startVM(t, vm, config.Name)
|
||||
defer stopper()
|
||||
|
||||
|
@ -253,7 +253,7 @@ func startAndStopCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func snapshotCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
||||
func snapshotCheck(t *testing.T, vm VirtualMachine, config *CloneConfig) {
|
||||
stopper := startVM(t, vm, config.Name)
|
||||
defer stopper()
|
||||
|
||||
|
@ -273,7 +273,7 @@ func snapshotCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func templateCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) {
|
||||
func templateCheck(t *testing.T, vm VirtualMachine, _ *CloneConfig) {
|
||||
err := vm.ConvertToTemplate()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to convert to template: %v", err)
|
||||
|
@ -286,7 +286,7 @@ func templateCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func startVM(t *testing.T, vm *VirtualMachine, vmName string) (stopper func()) {
|
||||
func startVM(t *testing.T, vm VirtualMachine, vmName string) (stopper func()) {
|
||||
log.Printf("[DEBUG] Starting the vm")
|
||||
if err := vm.PowerOn(); err != nil {
|
||||
t.Fatalf("Cannot start vm '%v': %v", vmName, err)
|
||||
|
@ -299,14 +299,14 @@ func startVM(t *testing.T, vm *VirtualMachine, vmName string) (stopper func()) {
|
|||
}
|
||||
}
|
||||
|
||||
func destroyVM(t *testing.T, vm *VirtualMachine, vmName string) {
|
||||
func destroyVM(t *testing.T, vm VirtualMachine, vmName string) {
|
||||
log.Printf("[DEBUG] Deleting the VM")
|
||||
if err := vm.Destroy(); err != nil {
|
||||
t.Errorf("!!! ERROR DELETING VM '%v': %v!!!", vmName, err)
|
||||
}
|
||||
|
||||
// Check that the clone is no longer exists
|
||||
if _, err := vm.driver.FindVM(vmName); err == nil {
|
||||
if _, err := vm.(*VirtualMachineDriver).driver.FindVM(vmName); err == nil {
|
||||
t.Errorf("!!! STILL CAN FIND VM '%v'. IT MIGHT NOT HAVE BEEN DELETED !!!", vmName)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ func TestVMAcc_create(t *testing.T) {
|
|||
testCases := []struct {
|
||||
name string
|
||||
config *CreateConfig
|
||||
checkFunction func(*testing.T, *VirtualMachine, *CreateConfig)
|
||||
checkFunction func(*testing.T, VirtualMachine, *CreateConfig)
|
||||
}{
|
||||
{"MinimalConfiguration", &CreateConfig{}, createDefaultCheck},
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ func TestVMAcc_create(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func createDefaultCheck(t *testing.T, vm *VirtualMachine, config *CreateConfig) {
|
||||
d := vm.driver
|
||||
func createDefaultCheck(t *testing.T, vm VirtualMachine, config *CreateConfig) {
|
||||
d := vm.(*VirtualMachineDriver).driver
|
||||
|
||||
// Check that the clone can be found by its name
|
||||
if _, err := d.FindVM(config.Name); err != nil {
|
||||
|
|
|
@ -13,7 +13,7 @@ type KeyInput struct {
|
|||
Shift bool
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) TypeOnKeyboard(input KeyInput) (int32, error) {
|
||||
func (vm *VirtualMachineDriver) TypeOnKeyboard(input KeyInput) (int32, error) {
|
||||
var spec types.UsbScanCodeSpec
|
||||
|
||||
spec.KeyEvents = append(spec.KeyEvents, types.UsbScanCodeSpecKeyEvent{
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/nfc"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vapi/vcenter"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type VirtualMachineMock struct {
|
||||
DestroyError error
|
||||
DestroyCalled bool
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Info(params ...string) (*mo.VirtualMachine, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Devices() (object.VirtualDeviceList, error) {
|
||||
return object.VirtualDeviceList{}, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Clone(ctx context.Context, config *CloneConfig) (VirtualMachine, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) updateVAppConfig(ctx context.Context, newProps map[string]string) (*types.VmConfigSpec, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddPublicKeys(ctx context.Context, publicKeys string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Properties(ctx context.Context) (*mo.VirtualMachine, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Destroy() error {
|
||||
vm.DestroyCalled = true
|
||||
if vm.DestroyError != nil {
|
||||
return vm.DestroyError
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Configure(config *HardwareConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Customize(spec types.CustomizationSpec) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ResizeDisk(diskSize int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) PowerOn() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) PowerOff() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) IsPoweredOff() (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) StartShutdown() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) WaitForShutdown(ctx context.Context, timeout time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) CreateSnapshot(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ConvertToTemplate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ImportOvfToContentLibrary(ovf vcenter.OVF) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ImportToContentLibrary(template vcenter.Template) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) GetDir() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddCdrom(controllerType string, datastoreIsoPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddFloppy(imgPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) SetBootOrder(order []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) RemoveDevice(keepFiles bool, device ...types.BaseVirtualDevice) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) addDevice(device types.BaseVirtualDevice) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddConfigParams(params map[string]string, info *types.ToolsConfigInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Export() (*nfc.Lease, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) CreateDescriptor(m *ovf.Manager, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) NewOvfManager() *ovf.Manager {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) GetOvfExportOptions(m *ovf.Manager) ([]types.OvfOptionInfo, error) {
|
||||
return nil, nil
|
||||
}
|
|
@ -170,7 +170,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
artifact := &common.Artifact{
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||
VM: state.Get("vm").(*driver.VirtualMachineDriver),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func basicStateBag() *multistep.BasicStateBag {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", &packer.BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
})
|
||||
return state
|
||||
}
|
|
@ -42,7 +42,7 @@ func (c *CDRomConfig) Prepare() []error {
|
|||
|
||||
func (s *StepAddCDRom) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.Config.CdromType == "sata" {
|
||||
if _, err := vm.FindSATAController(); err == driver.ErrNoSataController {
|
||||
|
|
|
@ -37,8 +37,8 @@ type StepAddFloppy struct {
|
|||
|
||||
func (s *StepAddFloppy) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
d := state.Get("driver").(*driver.Driver)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
d := state.Get("driver").(*driver.VCenterDriver)
|
||||
|
||||
if floppyPath, ok := state.GetOk("floppy_path"); ok {
|
||||
ui.Say("Uploading created floppy image")
|
||||
|
@ -90,7 +90,7 @@ func (s *StepAddFloppy) Cleanup(state multistep.StateBag) {
|
|||
}
|
||||
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
d := state.Get("driver").(*driver.Driver)
|
||||
d := state.Get("driver").(*driver.VCenterDriver)
|
||||
|
||||
if UploadedFloppyPath, ok := state.GetOk("uploaded_floppy_path"); ok {
|
||||
ui.Say("Deleting Floppy image ...")
|
||||
|
|
|
@ -216,7 +216,7 @@ type StepCreateVM struct {
|
|||
|
||||
func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
d := state.Get("driver").(*driver.Driver)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
vmPath := path.Join(s.Location.Folder, s.Location.VMName)
|
||||
|
||||
err := d.PreCleanVM(ui, vmPath, s.Force)
|
||||
|
@ -287,7 +287,7 @@ func (s *StepCreateVM) Cleanup(state multistep.StateBag) {
|
|||
if st == nil {
|
||||
return
|
||||
}
|
||||
vm := st.(*driver.VirtualMachine)
|
||||
vm := st.(driver.VirtualMachine)
|
||||
|
||||
ui.Say("Destroying VM...")
|
||||
err := vm.Destroy()
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/packer/builder/vsphere/common"
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func TestCreateConfig_Prepare(t *testing.T) {
|
||||
// Empty config - check defaults
|
||||
config := &CreateConfig{}
|
||||
if errs := config.Prepare(); len(errs) != 0 {
|
||||
t.Fatalf("Config preprare should not fail")
|
||||
}
|
||||
if config.GuestOSType != "otherGuest" {
|
||||
t.Fatalf("GuestOSType should default to 'otherGuest'")
|
||||
}
|
||||
if len(config.DiskControllerType) != 1 {
|
||||
t.Fatalf("DiskControllerType should have at least one element as default")
|
||||
}
|
||||
|
||||
// Data validation
|
||||
tc := []struct {
|
||||
name string
|
||||
config *CreateConfig
|
||||
fail bool
|
||||
expectedErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "Storage validate disk_size",
|
||||
config: &CreateConfig{
|
||||
Storage: []DiskConfig{
|
||||
{
|
||||
DiskSize: 0,
|
||||
DiskThinProvisioned: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "storage[0].'disk_size' is required",
|
||||
},
|
||||
{
|
||||
name: "Storage validate disk_controller_index",
|
||||
config: &CreateConfig{
|
||||
Storage: []DiskConfig{
|
||||
{
|
||||
DiskSize: 32768,
|
||||
DiskControllerIndex: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "storage[0].'disk_controller_index' references an unknown disk controller",
|
||||
},
|
||||
{
|
||||
name: "USBController validate 'usb' and 'xhci' can be set together",
|
||||
config: &CreateConfig{
|
||||
USBController: []string{"usb", "xhci"},
|
||||
},
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
name: "USBController validate '1' and '0' can be set together",
|
||||
config: &CreateConfig{
|
||||
USBController: []string{"1", "0"},
|
||||
},
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
name: "USBController validate 'true' and 'false' can be set together",
|
||||
config: &CreateConfig{
|
||||
USBController: []string{"true", "false"},
|
||||
},
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
name: "USBController validate 'true' and 'usb' cannot be set together",
|
||||
config: &CreateConfig{
|
||||
USBController: []string{"true", "usb"},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "there can only be one usb controller and one xhci controller",
|
||||
},
|
||||
{
|
||||
name: "USBController validate '1' and 'usb' cannot be set together",
|
||||
config: &CreateConfig{
|
||||
USBController: []string{"1", "usb"},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "there can only be one usb controller and one xhci controller",
|
||||
},
|
||||
{
|
||||
name: "USBController validate 'xhci' cannot be set more that once",
|
||||
config: &CreateConfig{
|
||||
USBController: []string{"xhci", "xhci"},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "there can only be one usb controller and one xhci controller",
|
||||
},
|
||||
{
|
||||
name: "USBController validate unknown value cannot be set",
|
||||
config: &CreateConfig{
|
||||
USBController: []string{"unknown"},
|
||||
},
|
||||
fail: true,
|
||||
expectedErrMsg: "usb_controller[0] references an unknown usb controller",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range tc {
|
||||
errs := c.config.Prepare()
|
||||
if c.fail {
|
||||
if len(errs) == 0 {
|
||||
t.Fatalf("Config preprare should fail")
|
||||
}
|
||||
if errs[0].Error() != c.expectedErrMsg {
|
||||
t.Fatalf("Expected error message: %s but was '%s'", c.expectedErrMsg, errs[0].Error())
|
||||
}
|
||||
} else {
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("Config preprare should not fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateVM_Run(t *testing.T) {
|
||||
state := basicStateBag()
|
||||
driverMock := driver.NewDriverMock()
|
||||
state.Put("driver", driverMock)
|
||||
step := basicStepCreateVM()
|
||||
step.Force = true
|
||||
vmPath := path.Join(step.Location.Folder, step.Location.VMName)
|
||||
|
||||
if action := step.Run(context.TODO(), state); action == multistep.ActionHalt {
|
||||
t.Fatalf("Should not halt.")
|
||||
}
|
||||
|
||||
// Pre clean VM
|
||||
if !driverMock.PreCleanVMCalled {
|
||||
t.Fatalf("driver.PreCleanVM should be called.")
|
||||
}
|
||||
if driverMock.PreCleanForce != step.Force {
|
||||
t.Fatalf("Force PreCleanVM should be %t but was %t.", step.Force, driverMock.PreCleanForce)
|
||||
}
|
||||
if driverMock.PreCleanVMPath != vmPath {
|
||||
t.Fatalf("VM path expected to be %s but was %s", vmPath, driverMock.PreCleanVMPath)
|
||||
}
|
||||
|
||||
if !driverMock.CreateVMCalled {
|
||||
t.Fatalf("driver.CreateVM should be called.")
|
||||
}
|
||||
if diff := cmp.Diff(driverMock.CreateConfig, driverCreateConfig(step.Config, step.Location)); diff != "" {
|
||||
t.Fatalf("wrog driver.CreateConfig: %s", diff)
|
||||
}
|
||||
vm, ok := state.GetOk("vm")
|
||||
if !ok {
|
||||
t.Fatal("state must contain the VM")
|
||||
}
|
||||
if vm != driverMock.VM {
|
||||
t.Fatalf("state doesn't contain the created VM.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateVM_RunHalt(t *testing.T) {
|
||||
state := basicStateBag()
|
||||
step := basicStepCreateVM()
|
||||
|
||||
// PreCleanVM fails
|
||||
driverMock := driver.NewDriverMock()
|
||||
driverMock.PreCleanShouldFail = true
|
||||
state.Put("driver", driverMock)
|
||||
if action := step.Run(context.TODO(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("Step should halt.")
|
||||
}
|
||||
if !driverMock.PreCleanVMCalled {
|
||||
t.Fatalf("driver.PreCleanVM should be called")
|
||||
}
|
||||
|
||||
// CreateVM fails
|
||||
driverMock = driver.NewDriverMock()
|
||||
driverMock.CreateVMShouldFail = true
|
||||
state.Put("driver", driverMock)
|
||||
if action := step.Run(context.TODO(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("Step should halt.")
|
||||
}
|
||||
if !driverMock.PreCleanVMCalled {
|
||||
t.Fatalf("driver.PreCleanVM should be called")
|
||||
}
|
||||
if !driverMock.CreateVMCalled {
|
||||
t.Fatalf("driver.PreCleanVM should be called")
|
||||
}
|
||||
if _, ok := state.GetOk("vm"); ok {
|
||||
t.Fatal("state should not contain a VM")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateVM_Cleanup(t *testing.T) {
|
||||
state := basicStateBag()
|
||||
step := basicStepCreateVM()
|
||||
vm := new(driver.VirtualMachineMock)
|
||||
state.Put("vm", vm)
|
||||
|
||||
// Clean up when state is cancelled
|
||||
state.Put(multistep.StateCancelled, true)
|
||||
step.Cleanup(state)
|
||||
if !vm.DestroyCalled {
|
||||
t.Fatalf("vm.Destroy should be called")
|
||||
}
|
||||
vm.DestroyCalled = false
|
||||
state.Remove(multistep.StateCancelled)
|
||||
|
||||
// Clean up when state is halted
|
||||
state.Put(multistep.StateHalted, true)
|
||||
step.Cleanup(state)
|
||||
if !vm.DestroyCalled {
|
||||
t.Fatalf("vm.Destroy should be called")
|
||||
}
|
||||
vm.DestroyCalled = false
|
||||
state.Remove(multistep.StateHalted)
|
||||
|
||||
// Clean up when state is destroy_vm is set
|
||||
state.Put("destroy_vm", true)
|
||||
step.Cleanup(state)
|
||||
if !vm.DestroyCalled {
|
||||
t.Fatalf("vm.Destroy should be called")
|
||||
}
|
||||
vm.DestroyCalled = false
|
||||
state.Remove("destroy_vm")
|
||||
|
||||
// Don't clean up if state is not set with previous values
|
||||
step.Cleanup(state)
|
||||
if vm.DestroyCalled {
|
||||
t.Fatalf("vm.Destroy should not be called")
|
||||
}
|
||||
|
||||
// Destroy fail
|
||||
errorBuffer := &strings.Builder{}
|
||||
ui := &packer.BasicUi{
|
||||
Reader: strings.NewReader(""),
|
||||
Writer: ioutil.Discard,
|
||||
ErrorWriter: errorBuffer,
|
||||
}
|
||||
state.Put("ui", ui)
|
||||
state.Put(multistep.StateCancelled, true)
|
||||
vm.DestroyError = errors.New("destroy failed")
|
||||
|
||||
step.Cleanup(state)
|
||||
if !vm.DestroyCalled {
|
||||
t.Fatalf("vm.Destroy should be called")
|
||||
}
|
||||
if !strings.Contains(errorBuffer.String(), vm.DestroyError.Error()) {
|
||||
t.Fatalf("Destroy should fail with error message '%s' but failed with '%s'", vm.DestroyError.Error(), errorBuffer.String())
|
||||
}
|
||||
vm.DestroyCalled = false
|
||||
state.Remove(multistep.StateCancelled)
|
||||
|
||||
// Should not destroy if VM is not set
|
||||
state.Remove("vm")
|
||||
state.Put(multistep.StateCancelled, true)
|
||||
step.Cleanup(state)
|
||||
if vm.DestroyCalled {
|
||||
t.Fatalf("vm.Destroy should not be called")
|
||||
}
|
||||
}
|
||||
|
||||
func basicStepCreateVM() *StepCreateVM {
|
||||
step := &StepCreateVM{
|
||||
Config: createConfig(),
|
||||
Location: basicLocationConfig(),
|
||||
}
|
||||
return step
|
||||
}
|
||||
|
||||
func basicLocationConfig() *common.LocationConfig {
|
||||
return &common.LocationConfig{
|
||||
VMName: "test-vm",
|
||||
Folder: "test-folder",
|
||||
Cluster: "test-cluster",
|
||||
Host: "test-host",
|
||||
ResourcePool: "test-resource-pool",
|
||||
Datastore: "test-datastore",
|
||||
}
|
||||
}
|
||||
|
||||
func createConfig() *CreateConfig {
|
||||
return &CreateConfig{
|
||||
Version: 1,
|
||||
GuestOSType: "ubuntu64Guest",
|
||||
DiskControllerType: []string{"pvscsi"},
|
||||
Storage: []DiskConfig{
|
||||
{
|
||||
DiskSize: 32768,
|
||||
DiskThinProvisioned: true,
|
||||
},
|
||||
},
|
||||
NICs: []NIC{
|
||||
{
|
||||
Network: "VM Network",
|
||||
NetworkCard: "vmxnet3",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func driverCreateConfig(config *CreateConfig, location *common.LocationConfig) *driver.CreateConfig {
|
||||
var networkCards []driver.NIC
|
||||
for _, nic := range config.NICs {
|
||||
networkCards = append(networkCards, driver.NIC{
|
||||
Network: nic.Network,
|
||||
NetworkCard: nic.NetworkCard,
|
||||
MacAddress: nic.MacAddress,
|
||||
Passthrough: nic.Passthrough,
|
||||
})
|
||||
}
|
||||
|
||||
var disks []driver.Disk
|
||||
for _, disk := range config.Storage {
|
||||
disks = append(disks, driver.Disk{
|
||||
DiskSize: disk.DiskSize,
|
||||
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
||||
DiskThinProvisioned: disk.DiskThinProvisioned,
|
||||
ControllerIndex: disk.DiskControllerIndex,
|
||||
})
|
||||
}
|
||||
|
||||
return &driver.CreateConfig{
|
||||
DiskControllerType: config.DiskControllerType,
|
||||
Storage: disks,
|
||||
Annotation: config.Notes,
|
||||
Name: location.VMName,
|
||||
Folder: location.Folder,
|
||||
Cluster: location.Cluster,
|
||||
Host: location.Host,
|
||||
ResourcePool: location.ResourcePool,
|
||||
Datastore: location.Datastore,
|
||||
GuestOS: config.GuestOSType,
|
||||
NICs: networkCards,
|
||||
USBController: config.USBController,
|
||||
Version: config.Version,
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ type StepRemoteUpload struct {
|
|||
|
||||
func (s *StepRemoteUpload) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
d := state.Get("driver").(*driver.Driver)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
|
||||
if path, ok := state.GetOk("iso_path"); ok {
|
||||
filename := filepath.Base(path.(string))
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
func TestStepRemoteUpload_Run(t *testing.T) {
|
||||
state := basicStateBag()
|
||||
driverMock := driver.NewDriverMock()
|
||||
state.Put("driver", driverMock)
|
||||
state.Put("iso_path", "[datastore] iso/path")
|
||||
|
||||
step := &StepRemoteUpload{
|
||||
Datastore: "datastore",
|
||||
Host: "host",
|
||||
SetHostForDatastoreUploads: false,
|
||||
}
|
||||
|
||||
if action := step.Run(context.TODO(), state); action == multistep.ActionHalt {
|
||||
t.Fatalf("Should not halt.")
|
||||
}
|
||||
|
||||
if !driverMock.FindDatastoreCalled {
|
||||
t.Fatalf("driver.FindDatastore should be called.")
|
||||
}
|
||||
if !driverMock.DatastoreMock.FileExistsCalled {
|
||||
t.Fatalf("datastore.FindDatastore should be called.")
|
||||
}
|
||||
if !driverMock.DatastoreMock.MakeDirectoryCalled {
|
||||
t.Fatalf("datastore.MakeDirectory should be called.")
|
||||
}
|
||||
if !driverMock.DatastoreMock.UploadFileCalled {
|
||||
t.Fatalf("datastore.UploadFile should be called.")
|
||||
}
|
||||
remotePath, ok := state.GetOk("iso_remote_path")
|
||||
if !ok {
|
||||
t.Fatalf("state should contain iso_remote_path")
|
||||
}
|
||||
expectedRemovePath := fmt.Sprintf("[%s] packer_cache//path", driverMock.DatastoreMock.Name())
|
||||
if remotePath != expectedRemovePath {
|
||||
t.Fatalf("iso_remote_path expected to be %s but was %s", expectedRemovePath, remotePath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepRemoteUpload_SkipRun(t *testing.T) {
|
||||
state := basicStateBag()
|
||||
driverMock := driver.NewDriverMock()
|
||||
state.Put("driver", driverMock)
|
||||
|
||||
step := &StepRemoteUpload{}
|
||||
|
||||
if action := step.Run(context.TODO(), state); action == multistep.ActionHalt {
|
||||
t.Fatalf("Should not halt.")
|
||||
}
|
||||
|
||||
if driverMock.FindDatastoreCalled {
|
||||
t.Fatalf("driver.FindDatastore should not be called.")
|
||||
}
|
||||
if _, ok := state.GetOk("iso_remote_path"); ok {
|
||||
t.Fatalf("state should not contain iso_remote_path")
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ type StepRemoveCDRom struct {
|
|||
|
||||
func (s *StepRemoveCDRom) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
ui.Say("Eject CD-ROM drives...")
|
||||
err := vm.EjectCdroms()
|
||||
|
|
|
@ -16,8 +16,8 @@ type StepRemoveFloppy struct {
|
|||
|
||||
func (s *StepRemoveFloppy) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
d := state.Get("driver").(*driver.Driver)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
d := state.Get("driver").(*driver.VCenterDriver)
|
||||
|
||||
ui.Say("Deleting Floppy drives...")
|
||||
devices, err := vm.Devices()
|
||||
|
|
Loading…
Reference in New Issue