merged createVirtualMachine and deployVirtualMachine to setupVirtualMachine (#6659)
This commit is contained in:
parent
40db82f25e
commit
62639620e1
|
@ -691,17 +691,10 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{
|
|||
log.Printf("[DEBUG] cdrom init: %v", cdroms)
|
||||
}
|
||||
|
||||
if vm.template != "" {
|
||||
err := vm.deployVirtualMachine(client)
|
||||
err := vm.setupVirtualMachine(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := vm.createVirtualMachine(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.SetId(vm.Path())
|
||||
log.Printf("[INFO] Created virtual machine: %s", d.Id())
|
||||
|
@ -1157,8 +1150,7 @@ func createCdroms(vm *object.VirtualMachine, cdroms []cdrom) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// createVirtualMachine creates a new VirtualMachine.
|
||||
func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
||||
func (vm *virtualMachine) setupVirtualMachine(c *govmomi.Client) error {
|
||||
dc, err := getDatacenter(c, vm.datacenter)
|
||||
|
||||
if err != nil {
|
||||
|
@ -1167,6 +1159,21 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
|||
finder := find.NewFinder(c.Client, true)
|
||||
finder = finder.SetDatacenter(dc)
|
||||
|
||||
var template *object.VirtualMachine
|
||||
var template_mo mo.VirtualMachine
|
||||
if vm.template != "" {
|
||||
template, err = finder.VirtualMachine(context.TODO(), vm.template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] template: %#v", template)
|
||||
|
||||
err = template.Properties(context.TODO(), template.Reference(), []string{"parent", "config.template", "config.guestId", "resourcePool", "snapshot", "guest.toolsVersionStatus2", "config.guestFullName"}, &template_mo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var resourcePool *object.ResourcePool
|
||||
if vm.resourcePool == "" {
|
||||
if vm.cluster == "" {
|
||||
|
@ -1192,8 +1199,8 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] folder: %#v", vm.folder)
|
||||
|
||||
folder := dcFolders.VmFolder
|
||||
if len(vm.folder) > 0 {
|
||||
si := object.NewSearchIndex(c.Client)
|
||||
|
@ -1208,20 +1215,8 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
|||
}
|
||||
}
|
||||
|
||||
// network
|
||||
networkDevices := []types.BaseVirtualDeviceConfigSpec{}
|
||||
for _, network := range vm.networkInterfaces {
|
||||
// network device
|
||||
nd, err := buildNetworkDevice(finder, network.label, "e1000")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkDevices = append(networkDevices, nd)
|
||||
}
|
||||
|
||||
// make config spec
|
||||
configSpec := types.VirtualMachineConfigSpec{
|
||||
GuestId: "otherLinux64Guest",
|
||||
Name: vm.name,
|
||||
NumCPUs: vm.vcpu,
|
||||
NumCoresPerSocket: 1,
|
||||
|
@ -1229,7 +1224,9 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
|||
MemoryAllocation: &types.ResourceAllocationInfo{
|
||||
Reservation: vm.memoryAllocation.reservation,
|
||||
},
|
||||
DeviceChange: networkDevices,
|
||||
}
|
||||
if vm.template == "" {
|
||||
configSpec.GuestId = "otherLinux64Guest"
|
||||
}
|
||||
log.Printf("[DEBUG] virtual machine config spec: %v", configSpec)
|
||||
|
||||
|
@ -1270,7 +1267,14 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
|||
sp := object.StoragePod{
|
||||
Folder: object.NewFolder(c.Client, d),
|
||||
}
|
||||
sps := buildStoragePlacementSpecCreate(dcFolders, resourcePool, sp, configSpec)
|
||||
|
||||
var sps types.StoragePlacementSpec
|
||||
if vm.template != "" {
|
||||
sps = buildStoragePlacementSpecClone(c, dcFolders, template, resourcePool, sp)
|
||||
} else {
|
||||
sps = buildStoragePlacementSpecCreate(dcFolders, resourcePool, sp, configSpec)
|
||||
}
|
||||
|
||||
datastore, err = findDatastore(c, sps)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1283,172 +1287,24 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
|||
|
||||
log.Printf("[DEBUG] datastore: %#v", datastore)
|
||||
|
||||
var mds mo.Datastore
|
||||
if err = datastore.Properties(context.TODO(), datastore.Reference(), []string{"name"}, &mds); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] datastore: %#v", mds.Name)
|
||||
scsi, err := object.SCSIControllerTypes().CreateSCSIController("scsi")
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] %s", err)
|
||||
}
|
||||
|
||||
configSpec.DeviceChange = append(configSpec.DeviceChange, &types.VirtualDeviceConfigSpec{
|
||||
Operation: types.VirtualDeviceConfigSpecOperationAdd,
|
||||
Device: scsi,
|
||||
})
|
||||
|
||||
configSpec.Files = &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", mds.Name)}
|
||||
|
||||
task, err := folder.CreateVM(context.TODO(), configSpec, resourcePool, nil)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] %s", err)
|
||||
}
|
||||
|
||||
err = task.Wait(context.TODO())
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] %s", err)
|
||||
}
|
||||
|
||||
newVM, err := finder.VirtualMachine(context.TODO(), vm.Path())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] new vm: %v", newVM)
|
||||
|
||||
log.Printf("[DEBUG] add hard disk: %v", vm.hardDisks)
|
||||
for _, hd := range vm.hardDisks {
|
||||
log.Printf("[DEBUG] add hard disk: %v", hd.size)
|
||||
log.Printf("[DEBUG] add hard disk: %v", hd.iops)
|
||||
err = addHardDisk(newVM, hd.size, hd.iops, "thin", datastore, hd.vmdkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the cdroms if needed.
|
||||
if err := createCdroms(newVM, vm.cdroms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if vm.bootableVmdk {
|
||||
newVM.PowerOn(context.TODO())
|
||||
ip, err := newVM.WaitForIP(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] ip address: %v", ip)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// deployVirtualMachine deploys a new VirtualMachine.
|
||||
func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
|
||||
dc, err := getDatacenter(c, vm.datacenter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
finder := find.NewFinder(c.Client, true)
|
||||
finder = finder.SetDatacenter(dc)
|
||||
|
||||
template, err := finder.VirtualMachine(context.TODO(), vm.template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] template: %#v", template)
|
||||
|
||||
var resourcePool *object.ResourcePool
|
||||
if vm.resourcePool == "" {
|
||||
if vm.cluster == "" {
|
||||
resourcePool, err = finder.DefaultResourcePool(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
resourcePool, err = finder.ResourcePool(context.TODO(), "*"+vm.cluster+"/Resources")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resourcePool, err = finder.ResourcePool(context.TODO(), vm.resourcePool)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Printf("[DEBUG] resource pool: %#v", resourcePool)
|
||||
|
||||
dcFolders, err := dc.Folders(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] folder: %#v", vm.folder)
|
||||
folder := dcFolders.VmFolder
|
||||
if len(vm.folder) > 0 {
|
||||
si := object.NewSearchIndex(c.Client)
|
||||
folderRef, err := si.FindByInventoryPath(
|
||||
context.TODO(), fmt.Sprintf("%v/vm/%v", vm.datacenter, vm.folder))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading folder %s: %s", vm.folder, err)
|
||||
} else if folderRef == nil {
|
||||
return fmt.Errorf("Cannot find folder %s", vm.folder)
|
||||
} else {
|
||||
folder = folderRef.(*object.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
var datastore *object.Datastore
|
||||
if vm.datastore == "" {
|
||||
datastore, err = finder.DefaultDatastore(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
datastore, err = finder.Datastore(context.TODO(), vm.datastore)
|
||||
if err != nil {
|
||||
// TODO: datastore cluster support in govmomi finder function
|
||||
d, err := getDatastoreObject(c, dcFolders, vm.datastore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.Type == "StoragePod" {
|
||||
sp := object.StoragePod{
|
||||
Folder: object.NewFolder(c.Client, d),
|
||||
}
|
||||
sps := buildStoragePlacementSpecClone(c, dcFolders, template, resourcePool, sp)
|
||||
|
||||
datastore, err = findDatastore(c, sps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
datastore = object.NewDatastore(c.Client, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Printf("[DEBUG] datastore: %#v", datastore)
|
||||
|
||||
relocateSpec, err := buildVMRelocateSpec(resourcePool, datastore, template, vm.linkedClone, vm.hardDisks[0].initType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] relocate spec: %v", relocateSpec)
|
||||
|
||||
// network
|
||||
networkDevices := []types.BaseVirtualDeviceConfigSpec{}
|
||||
networkConfigs := []types.CustomizationAdapterMapping{}
|
||||
for _, network := range vm.networkInterfaces {
|
||||
// network device
|
||||
nd, err := buildNetworkDevice(finder, network.label, "vmxnet3")
|
||||
var networkDeviceType string
|
||||
if vm.template == "" {
|
||||
networkDeviceType = "e1000"
|
||||
} else {
|
||||
networkDeviceType = "vmxnet3"
|
||||
}
|
||||
nd, err := buildNetworkDevice(finder, network.label, networkDeviceType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkDevices = append(networkDevices, nd)
|
||||
|
||||
if vm.template != "" {
|
||||
var ipSetting types.CustomizationIPSettings
|
||||
if network.ipv4Address == "" {
|
||||
ipSetting.Ip = &types.CustomizationDhcpIpGenerator{}
|
||||
|
@ -1498,41 +1354,124 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
|
|||
}
|
||||
networkConfigs = append(networkConfigs, config)
|
||||
}
|
||||
log.Printf("[DEBUG] network configs: %v", networkConfigs[0].Adapter)
|
||||
}
|
||||
log.Printf("[DEBUG] network devices: %v", networkDevices)
|
||||
log.Printf("[DEBUG] network configs: %v", networkConfigs)
|
||||
|
||||
// make config spec
|
||||
configSpec := types.VirtualMachineConfigSpec{
|
||||
NumCPUs: vm.vcpu,
|
||||
NumCoresPerSocket: 1,
|
||||
MemoryMB: vm.memoryMb,
|
||||
MemoryAllocation: &types.ResourceAllocationInfo{
|
||||
Reservation: vm.memoryAllocation.reservation,
|
||||
},
|
||||
var task *object.Task
|
||||
if vm.template == "" {
|
||||
var mds mo.Datastore
|
||||
if err = datastore.Properties(context.TODO(), datastore.Reference(), []string{"name"}, &mds); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] datastore: %#v", mds.Name)
|
||||
scsi, err := object.SCSIControllerTypes().CreateSCSIController("scsi")
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] virtual machine config spec: %v", configSpec)
|
||||
configSpec.DeviceChange = append(configSpec.DeviceChange, &types.VirtualDeviceConfigSpec{
|
||||
Operation: types.VirtualDeviceConfigSpecOperationAdd,
|
||||
Device: scsi,
|
||||
})
|
||||
|
||||
log.Printf("[DEBUG] starting extra custom config spec: %v", vm.customConfigurations)
|
||||
configSpec.Files = &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", mds.Name)}
|
||||
|
||||
// make ExtraConfig
|
||||
if len(vm.customConfigurations) > 0 {
|
||||
var ov []types.BaseOptionValue
|
||||
for k, v := range vm.customConfigurations {
|
||||
key := k
|
||||
value := v
|
||||
o := types.OptionValue{
|
||||
Key: key,
|
||||
Value: &value,
|
||||
}
|
||||
ov = append(ov, &o)
|
||||
}
|
||||
configSpec.ExtraConfig = ov
|
||||
log.Printf("[DEBUG] virtual machine Extra Config spec: %v", configSpec.ExtraConfig)
|
||||
task, err = folder.CreateVM(context.TODO(), configSpec, resourcePool, nil)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] %s", err)
|
||||
}
|
||||
|
||||
var template_mo mo.VirtualMachine
|
||||
err = template.Properties(context.TODO(), template.Reference(), []string{"parent", "config.template", "config.guestId", "resourcePool", "snapshot", "guest.toolsVersionStatus2", "config.guestFullName"}, &template_mo)
|
||||
err = task.Wait(context.TODO())
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] %s", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
relocateSpec, err := buildVMRelocateSpec(resourcePool, datastore, template, vm.linkedClone, vm.hardDisks[0].initType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] relocate spec: %v", relocateSpec)
|
||||
|
||||
// make vm clone spec
|
||||
cloneSpec := types.VirtualMachineCloneSpec{
|
||||
Location: relocateSpec,
|
||||
Template: false,
|
||||
Config: &configSpec,
|
||||
PowerOn: false,
|
||||
}
|
||||
if vm.linkedClone {
|
||||
if template_mo.Snapshot == nil {
|
||||
return fmt.Errorf("`linkedClone=true`, but image VM has no snapshots")
|
||||
}
|
||||
cloneSpec.Snapshot = template_mo.Snapshot.CurrentSnapshot
|
||||
}
|
||||
log.Printf("[DEBUG] clone spec: %v", cloneSpec)
|
||||
|
||||
task, err = template.Clone(context.TODO(), folder, vm.name, cloneSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = task.Wait(context.TODO())
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] %s", err)
|
||||
}
|
||||
|
||||
newVM, err := finder.VirtualMachine(context.TODO(), vm.Path())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] new vm: %v", newVM)
|
||||
|
||||
devices, err := newVM.Device(context.TODO())
|
||||
if err != nil {
|
||||
log.Printf("[DEBUG] Template devices can't be found")
|
||||
return err
|
||||
}
|
||||
|
||||
for _, dvc := range devices {
|
||||
// Issue 3559/3560: Delete all ethernet devices to add the correct ones later
|
||||
if devices.Type(dvc) == "ethernet" {
|
||||
err := newVM.RemoveDevice(context.TODO(), false, dvc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add Network devices
|
||||
for _, dvc := range networkDevices {
|
||||
err := newVM.AddDevice(
|
||||
context.TODO(), dvc.GetVirtualDeviceConfigSpec().Device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the cdroms if needed.
|
||||
if err := createCdroms(newVM, vm.cdroms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
firstDisk := 0
|
||||
if vm.template != "" {
|
||||
firstDisk++
|
||||
}
|
||||
for i := firstDisk; i < len(vm.hardDisks); i++ {
|
||||
log.Printf("[DEBUG] disk index: %v", i)
|
||||
err = addHardDisk(newVM, vm.hardDisks[i].size, vm.hardDisks[i].iops, vm.hardDisks[i].initType, datastore, vm.hardDisks[i].vmdkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if vm.skipCustomization || vm.template == "" {
|
||||
log.Printf("[DEBUG] VM customization skipped")
|
||||
} else {
|
||||
var identity_options types.BaseCustomizationIdentitySettings
|
||||
if strings.HasPrefix(template_mo.Config.GuestId, "win") {
|
||||
var timeZone int
|
||||
|
@ -1604,72 +1543,6 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
|
|||
}
|
||||
log.Printf("[DEBUG] custom spec: %v", customSpec)
|
||||
|
||||
// make vm clone spec
|
||||
cloneSpec := types.VirtualMachineCloneSpec{
|
||||
Location: relocateSpec,
|
||||
Template: false,
|
||||
Config: &configSpec,
|
||||
PowerOn: false,
|
||||
}
|
||||
if vm.linkedClone {
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading base VM properties: %s", err)
|
||||
}
|
||||
if template_mo.Snapshot == nil {
|
||||
return fmt.Errorf("`linkedClone=true`, but image VM has no snapshots")
|
||||
}
|
||||
cloneSpec.Snapshot = template_mo.Snapshot.CurrentSnapshot
|
||||
}
|
||||
log.Printf("[DEBUG] clone spec: %v", cloneSpec)
|
||||
|
||||
task, err := template.Clone(context.TODO(), folder, vm.name, cloneSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = task.WaitForResult(context.TODO(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newVM, err := finder.VirtualMachine(context.TODO(), vm.Path())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] new vm: %v", newVM)
|
||||
|
||||
devices, err := newVM.Device(context.TODO())
|
||||
if err != nil {
|
||||
log.Printf("[DEBUG] Template devices can't be found")
|
||||
return err
|
||||
}
|
||||
|
||||
for _, dvc := range devices {
|
||||
// Issue 3559/3560: Delete all ethernet devices to add the correct ones later
|
||||
if devices.Type(dvc) == "ethernet" {
|
||||
err := newVM.RemoveDevice(context.TODO(), false, dvc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add Network devices
|
||||
for _, dvc := range networkDevices {
|
||||
err := newVM.AddDevice(
|
||||
context.TODO(), dvc.GetVirtualDeviceConfigSpec().Device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the cdroms if needed.
|
||||
if err := createCdroms(newVM, vm.cdroms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if vm.skipCustomization {
|
||||
log.Printf("[DEBUG] VM customization skipped")
|
||||
} else {
|
||||
log.Printf("[DEBUG] VM customization starting")
|
||||
taskb, err := newVM.Customize(context.TODO(), customSpec)
|
||||
if err != nil {
|
||||
|
@ -1682,16 +1555,8 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
|
|||
log.Printf("[DEBUG] VM customization finished")
|
||||
}
|
||||
|
||||
for i := 1; i < len(vm.hardDisks); i++ {
|
||||
err = addHardDisk(newVM, vm.hardDisks[i].size, vm.hardDisks[i].iops, vm.hardDisks[i].initType, datastore, vm.hardDisks[i].vmdkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] virtual machine config spec: %v", configSpec)
|
||||
|
||||
if vm.bootableVmdk || vm.template != "" {
|
||||
newVM.PowerOn(context.TODO())
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue