vsphere/internal/virtualdevice/virtual_machine_disk_subresource.go
func DiskCloneRelocateOperation(d *schema.ResourceData, c *govmomi.Client, l object.VirtualDeviceList) ([]types.VirtualMachineRelocateSpecDiskLocator, error) {
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Generating full disk relocate spec list")
	devices := SelectDisks(l, d.Get("scsi_controller_count").(int))
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk devices located: %s", DeviceListString(devices))
	// Sort the device list, in case it's not sorted already.
	devSort := virtualDeviceListSorter{
		Sort:       devices,
		DeviceList: l,
	}
	sort.Sort(devSort)
	devices = devSort.Sort
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk devices order after sort: %s", DeviceListString(devices))
	// Do the same for our listed disks.
	curSet := d.Get(subresourceTypeDisk).([]interface{})
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Current resource set: %s", subresourceListString(curSet))
	sort.Sort(virtualDiskSubresourceSorter(curSet))
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Resource set order after sort: %s", subresourceListString(curSet))

	log.Printf("[DEBUG] DiskCloneRelocateOperation: Generating relocators for source disks")
	var relocators []types.VirtualMachineRelocateSpecDiskLocator
	for i, device := range devices {
		m := curSet[i].(map[string]interface{})
		vd := device.GetVirtualDevice()
		ctlr := l.FindByKey(vd.ControllerKey)
		if ctlr == nil {
			return nil, fmt.Errorf("could not find controller with key %d", vd.Key)
		}
		m["key"] = int(vd.Key)
		var err error
		m["device_address"], err = computeDevAddr(vd, ctlr.(types.BaseVirtualController))
		if err != nil {
			return nil, fmt.Errorf("error computing device address: %s", err)
		}
		r := NewDiskSubresource(c, d, m, nil, i)
		// A disk locator is only useful if a target datastore is available. If we
		// don't have a datastore specified (ie: when Storage DRS is in use), then
		// we just need to skip this disk. The disk will be migrated properly
		// through the SDRS API.
		if dsID := r.Get("datastore_id"); dsID == "" || dsID == diskDatastoreComputedName {
			continue
		}
		// Otherwise, proceed with generating and appending the locator.
		relocator, err := r.Relocate(l, true)
		if err != nil {
			return nil, fmt.Errorf("%s: %s", r.Addr(), err)
		}
		relocators = append(relocators, relocator)
	}

	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk relocator list: %s", diskRelocateListString(relocators))
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk relocator generation complete")
	return relocators, nil
}
func DiskCloneRelocateOperation(d *schema.ResourceData, c *govmomi.Client, l object.VirtualDeviceList) ([]types.VirtualMachineRelocateSpecDiskLocator, error) {
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Generating full disk relocate spec list")
	devices := SelectDisks(l, d.Get("scsi_controller_count").(int))
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk devices located: %s", DeviceListString(devices))
	// Sort the device list, in case it's not sorted already.
	devSort := virtualDeviceListSorter{
		Sort:       devices,
		DeviceList: l,
	}
	sort.Sort(devSort)
	devices = devSort.Sort
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk devices order after sort: %s", DeviceListString(devices))
	// Do the same for our listed disks.
	curSet := d.Get(subresourceTypeDisk).([]interface{})
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Current resource set: %s", subresourceListString(curSet))
	sort.Sort(virtualDiskSubresourceSorter(curSet))
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Resource set order after sort: %s", subresourceListString(curSet))

	log.Printf("[DEBUG] DiskCloneRelocateOperation: Generating relocators for source disks")
	var relocators []types.VirtualMachineRelocateSpecDiskLocator
	for i, device := range devices {
		m := curSet[i].(map[string]interface{})
		vd := device.GetVirtualDevice()
		ctlr := l.FindByKey(vd.ControllerKey)
		if ctlr == nil {
			return nil, fmt.Errorf("could not find controller with key %d", vd.Key)
		}
		m["key"] = int(vd.Key)
		var err error
		m["device_address"], err = computeDevAddr(vd, ctlr.(types.BaseVirtualController))
		if err != nil {
			return nil, fmt.Errorf("error computing device address: %s", err)
		}
		r := NewDiskSubresource(c, d, m, nil, i)
		// A disk locator is only useful if a target datastore is available. If we
		// don't have a datastore specified (ie: when Storage DRS is in use), then
		// we just need to skip this disk. The disk will be migrated properly
		// through the SDRS API.
		if dsID := r.Get("datastore_id"); dsID == "" || dsID == diskDatastoreComputedName {
			continue
		}
		// Otherwise, proceed with generating and appending the locator.
		relocator, err := r.Relocate(l, true)
		if err != nil {
			return nil, fmt.Errorf("%s: %s", r.Addr(), err)
		}
		relocators = append(relocators, relocator)
	}

	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk relocator list: %s", diskRelocateListString(relocators))
	log.Printf("[DEBUG] DiskCloneRelocateOperation: Disk relocator generation complete")
	return relocators, nil
}
func DiskCloneRelocateOperation ( d * schema . ResourceData , c * govmomi . Client , l object . VirtualDeviceList ) ( [ ] types . VirtualMachineRelocateSpecDiskLocator , error ) { log . Printf ( " " ) devices := SelectDisks ( l , d . Get ( " " ) . ( int ) ) log . Printf ( " " , DeviceListString ( devices ) ) // Sort the device list, in case it's not sorted already. devSort := virtualDeviceListSorter { Sort : devices , DeviceList : l , } sort . Sort ( devSort ) devices = devSort . Sort log . Printf ( " " , DeviceListString ( devices ) ) // Do the same for our listed disks. curSet := d . Get ( subresourceTypeDisk ) . ( [ ] interface { } ) log . Printf ( " " , subresourceListString ( curSet ) ) sort . Sort ( virtualDiskSubresourceSorter ( curSet ) ) log . Printf ( " " , subresourceListString ( curSet ) ) log . Printf ( " " ) var relocators [ ] types . VirtualMachineRelocateSpecDiskLocator for i , device := range devices { m := curSet [ i ] . ( map [ string ] interface { } ) vd := device . GetVirtualDevice ( ) ctlr := l . FindByKey ( vd . ControllerKey ) if ctlr == nil { return nil , fmt . Errorf ( " " , vd . Key ) } m [ " " ] = int ( vd . Key ) var err error m [ " " ] , err = computeDevAddr ( vd , ctlr . ( types . BaseVirtualController ) ) if err != nil { return nil , fmt . Errorf ( " " , err ) } r := NewDiskSubresource ( c , d , m , nil , i ) // A disk locator is only useful if a target datastore is available. If we // don't have a datastore specified (ie: when Storage DRS is in use), then // we just need to skip this disk. The disk will be migrated properly // through the SDRS API. if dsID := r . Get ( " " ) ; dsID == " " || dsID == diskDatastoreComputedName { continue } // Otherwise, proceed with generating and appending the locator. relocator , err := r . Relocate ( l , true ) if err != nil { return nil , fmt . Errorf ( " " , r . Addr ( ) , err ) } relocators = append ( relocators , relocator ) } log . Printf ( " " , diskRelocateListString ( relocators ) ) log . Printf ( " " ) return relocators , nil }
// DiskCloneRelocateOperation assembles the
// VirtualMachineRelocateSpecDiskLocator slice for a virtual machine clone
// operation.
//
// This differs from a regular storage vMotion in that we have no existing
// devices in the resource to work off of - the disks in the source virtual
// machine is our source of truth. These disks are assigned to our disk
// sub-resources in config and the relocate specs are generated off of the
// backing data defined in config, taking on these filenames when cloned. After
// the clone is complete, natural re-configuration happens to bring the disk
// configurations fully in sync with what is defined.
DiskCloneRelocateOperation assembles the VirtualMachineRelocateSpecDiskLocator slice for a virtual machine clone operation . This differs from a regular storage vMotion in that we have no existing devices in the resource to work off of - the disks in the source virtual machine is our source of truth . These disks are assigned to our disk sub - resources in config and the relocate specs are generated off of the backing data defined in config taking on these filenames when cloned . After the clone is complete natural re - configuration happens to bring the disk configurations fully in sync with what is defined .