vsphere/internal/virtualdevice/virtual_machine_disk_subresource.go
func DiskMigrateRelocateOperation(d *schema.ResourceData, c *govmomi.Client, l object.VirtualDeviceList) ([]types.VirtualMachineRelocateSpecDiskLocator, bool, error) {
	log.Printf("[DEBUG] DiskMigrateRelocateOperation: Generating any necessary disk relocate specs")
	ods, nds := d.GetChange(subresourceTypeDisk)

	var relocators []types.VirtualMachineRelocateSpecDiskLocator
	var relocateOK bool

	// We are only concerned with resources that would normally be updated, as
	// incoming or outgoing disks obviously won't need migrating. Hence, this is
	// a simplified subset of the normal apply logic.
	for ni, ne := range nds.([]interface{}) {
		nm := ne.(map[string]interface{})
		var name string
		var err error
		if name, err = diskLabelOrName(nm); err != nil {
			return nil, false, fmt.Errorf("disk.%d: %s", ni, err)
		}
		if name == diskDeletedName || name == diskDetachedName {
			continue
		}
		for _, oe := range ods.([]interface{}) {
			om := oe.(map[string]interface{})
			if nm["uuid"] == om["uuid"] {
				// No change in datastore is a no-op, unless we are changing default datastores
				if nm["datastore_id"] == om["datastore_id"] && !d.HasChange("datastore_id") {
					break
				}
				// If we got this far, some sort of datastore migration will be
				// necessary. Flag this now.
				relocateOK = true

				// 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 nm["datastore_id"] == "" || nm["datastore_id"] == diskDatastoreComputedName {
					break
				}
				r := NewDiskSubresource(c, d, nm, om, ni)
				relocator, err := r.Relocate(l, false)
				if err != nil {
					return nil, false, fmt.Errorf("%s: %s", r.Addr(), err)
				}
				if d.Get("datastore_id").(string) == relocator.Datastore.Value {
					log.Printf("[DEBUG] %s: Datastore in spec is same as default, dropping in favor of implicit relocation", r.Addr())
					break
				}
				relocators = append(relocators, relocator)
			}
		}
	}

	if !relocateOK {
		log.Printf("[DEBUG] DiskMigrateRelocateOperation: Disk relocation not necessary")
		return nil, false, nil
	}

	log.Printf("[DEBUG] DiskMigrateRelocateOperation: Disk relocator list: %s", diskRelocateListString(relocators))
	log.Printf("[DEBUG] DiskMigrateRelocateOperation: Disk relocator generation complete")
	return relocators, true, nil
}
func DiskMigrateRelocateOperation(d *schema.ResourceData, c *govmomi.Client, l object.VirtualDeviceList) ([]types.VirtualMachineRelocateSpecDiskLocator, bool, error) {
	log.Printf("[DEBUG] DiskMigrateRelocateOperation: Generating any necessary disk relocate specs")
	ods, nds := d.GetChange(subresourceTypeDisk)

	var relocators []types.VirtualMachineRelocateSpecDiskLocator
	var relocateOK bool

	// We are only concerned with resources that would normally be updated, as
	// incoming or outgoing disks obviously won't need migrating. Hence, this is
	// a simplified subset of the normal apply logic.
	for ni, ne := range nds.([]interface{}) {
		nm := ne.(map[string]interface{})
		var name string
		var err error
		if name, err = diskLabelOrName(nm); err != nil {
			return nil, false, fmt.Errorf("disk.%d: %s", ni, err)
		}
		if name == diskDeletedName || name == diskDetachedName {
			continue
		}
		for _, oe := range ods.([]interface{}) {
			om := oe.(map[string]interface{})
			if nm["uuid"] == om["uuid"] {
				// No change in datastore is a no-op, unless we are changing default datastores
				if nm["datastore_id"] == om["datastore_id"] && !d.HasChange("datastore_id") {
					break
				}
				// If we got this far, some sort of datastore migration will be
				// necessary. Flag this now.
				relocateOK = true

				// 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 nm["datastore_id"] == "" || nm["datastore_id"] == diskDatastoreComputedName {
					break
				}
				r := NewDiskSubresource(c, d, nm, om, ni)
				relocator, err := r.Relocate(l, false)
				if err != nil {
					return nil, false, fmt.Errorf("%s: %s", r.Addr(), err)
				}
				if d.Get("datastore_id").(string) == relocator.Datastore.Value {
					log.Printf("[DEBUG] %s: Datastore in spec is same as default, dropping in favor of implicit relocation", r.Addr())
					break
				}
				relocators = append(relocators, relocator)
			}
		}
	}

	if !relocateOK {
		log.Printf("[DEBUG] DiskMigrateRelocateOperation: Disk relocation not necessary")
		return nil, false, nil
	}

	log.Printf("[DEBUG] DiskMigrateRelocateOperation: Disk relocator list: %s", diskRelocateListString(relocators))
	log.Printf("[DEBUG] DiskMigrateRelocateOperation: Disk relocator generation complete")
	return relocators, true, nil
}
func DiskMigrateRelocateOperation ( d * schema . ResourceData , c * govmomi . Client , l object . VirtualDeviceList ) ( [ ] types . VirtualMachineRelocateSpecDiskLocator , bool , error ) { log . Printf ( " " ) ods , nds := d . GetChange ( subresourceTypeDisk ) var relocators [ ] types . VirtualMachineRelocateSpecDiskLocator var relocateOK bool // We are only concerned with resources that would normally be updated, as // incoming or outgoing disks obviously won't need migrating. Hence, this is // a simplified subset of the normal apply logic. for ni , ne := range nds . ( [ ] interface { } ) { nm := ne . ( map [ string ] interface { } ) var name string var err error if name , err = diskLabelOrName ( nm ) ; err != nil { return nil , false , fmt . Errorf ( " " , ni , err ) } if name == diskDeletedName || name == diskDetachedName { continue } for _ , oe := range ods . ( [ ] interface { } ) { om := oe . ( map [ string ] interface { } ) if nm [ " " ] == om [ " " ] { // No change in datastore is a no-op, unless we are changing default datastores if nm [ " " ] == om [ " " ] && ! d . HasChange ( " " ) { break } // If we got this far, some sort of datastore migration will be // necessary. Flag this now. relocateOK = true // 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 nm [ " " ] == " " || nm [ " " ] == diskDatastoreComputedName { break } r := NewDiskSubresource ( c , d , nm , om , ni ) relocator , err := r . Relocate ( l , false ) if err != nil { return nil , false , fmt . Errorf ( " " , r . Addr ( ) , err ) } if d . Get ( " " ) . ( string ) == relocator . Datastore . Value { log . Printf ( " " , r . Addr ( ) ) break } relocators = append ( relocators , relocator ) } } } if ! relocateOK { log . Printf ( " " ) return nil , false , nil } log . Printf ( " " , diskRelocateListString ( relocators ) ) log . Printf ( " " ) return relocators , true , nil }
// DiskMigrateRelocateOperation assembles the
// VirtualMachineRelocateSpecDiskLocator slice for a virtual machine migration
// operation, otherwise known as storage vMotion.
DiskMigrateRelocateOperation assembles the VirtualMachineRelocateSpecDiskLocator slice for a virtual machine migration operation otherwise known as storage vMotion .