vsphere/internal/virtualdevice/virtual_machine_device_subresource.go
func swapSCSIDevice(l object.VirtualDeviceList, device types.BaseVirtualSCSIController, ct string, st string) ([]types.BaseVirtualDeviceConfigSpec, error) {
	log.Printf("[DEBUG] swapSCSIDevice: Swapping SCSI device for one of controller type %s: %s", ct, l.Name(device.(types.BaseVirtualDevice)))
	var spec []types.BaseVirtualDeviceConfigSpec
	bvd := device.(types.BaseVirtualDevice)
	cspec, err := object.VirtualDeviceList{bvd}.ConfigSpec(types.VirtualDeviceConfigSpecOperationRemove)
	if err != nil {
		return nil, err
	}
	spec = append(spec, cspec...)

	nsd, err := l.CreateSCSIController(ct)
	if err != nil {
		return nil, err
	}
	nsd.(types.BaseVirtualSCSIController).GetVirtualSCSIController().SharedBus = types.VirtualSCSISharing(st)
	nsd.(types.BaseVirtualSCSIController).GetVirtualSCSIController().BusNumber = device.GetVirtualSCSIController().BusNumber
	cspec, err = object.VirtualDeviceList{nsd}.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
	if err != nil {
		return nil, err
	}
	spec = append(spec, cspec...)
	ockey := device.GetVirtualSCSIController().Key
	nckey := nsd.GetVirtualDevice().Key
	for _, vd := range l {
		if vd.GetVirtualDevice().ControllerKey == ockey {
			vd.GetVirtualDevice().ControllerKey = nckey
			cspec, err := object.VirtualDeviceList{vd}.ConfigSpec(types.VirtualDeviceConfigSpecOperationEdit)
			if err != nil {
				return nil, err
			}
			if len(cspec) != 1 {
				return nil, fmt.Errorf("incorrect number of config spec items returned - expected 1, got %d", len(cspec))
			}
			// Clear the file operation
			cspec[0].GetVirtualDeviceConfigSpec().FileOperation = ""
			spec = append(spec, cspec...)
		}
	}
	log.Printf("[DEBUG] swapSCSIDevice: Outgoing device config spec: %s", DeviceChangeString(spec))
	return spec, nil
}
func swapSCSIDevice(l object.VirtualDeviceList, device types.BaseVirtualSCSIController, ct string, st string) ([]types.BaseVirtualDeviceConfigSpec, error) {
	log.Printf("[DEBUG] swapSCSIDevice: Swapping SCSI device for one of controller type %s: %s", ct, l.Name(device.(types.BaseVirtualDevice)))
	var spec []types.BaseVirtualDeviceConfigSpec
	bvd := device.(types.BaseVirtualDevice)
	cspec, err := object.VirtualDeviceList{bvd}.ConfigSpec(types.VirtualDeviceConfigSpecOperationRemove)
	if err != nil {
		return nil, err
	}
	spec = append(spec, cspec...)

	nsd, err := l.CreateSCSIController(ct)
	if err != nil {
		return nil, err
	}
	nsd.(types.BaseVirtualSCSIController).GetVirtualSCSIController().SharedBus = types.VirtualSCSISharing(st)
	nsd.(types.BaseVirtualSCSIController).GetVirtualSCSIController().BusNumber = device.GetVirtualSCSIController().BusNumber
	cspec, err = object.VirtualDeviceList{nsd}.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
	if err != nil {
		return nil, err
	}
	spec = append(spec, cspec...)
	ockey := device.GetVirtualSCSIController().Key
	nckey := nsd.GetVirtualDevice().Key
	for _, vd := range l {
		if vd.GetVirtualDevice().ControllerKey == ockey {
			vd.GetVirtualDevice().ControllerKey = nckey
			cspec, err := object.VirtualDeviceList{vd}.ConfigSpec(types.VirtualDeviceConfigSpecOperationEdit)
			if err != nil {
				return nil, err
			}
			if len(cspec) != 1 {
				return nil, fmt.Errorf("incorrect number of config spec items returned - expected 1, got %d", len(cspec))
			}
			// Clear the file operation
			cspec[0].GetVirtualDeviceConfigSpec().FileOperation = ""
			spec = append(spec, cspec...)
		}
	}
	log.Printf("[DEBUG] swapSCSIDevice: Outgoing device config spec: %s", DeviceChangeString(spec))
	return spec, nil
}
// swapSCSIDevice swaps out the supplied controller for a new one of the
// supplied controller type. Any connected devices are re-connected at the same
// device units on the new device. A list of changes is returned.