vsphere/internal/virtualdevice/virtual_machine_device_subresource.go
func NormalizeSCSIBus(l object.VirtualDeviceList, ct string, count int, st string) (object.VirtualDeviceList, []types.BaseVirtualDeviceConfigSpec, error) {
	log.Printf("[DEBUG] NormalizeSCSIBus: Normalizing first %d controllers on SCSI bus to device type %s", count, ct)
	var spec []types.BaseVirtualDeviceConfigSpec
	ctlrs := make([]types.BaseVirtualSCSIController, count)
	// Don't worry about doing any fancy select stuff here, just go thru the
	// VirtualDeviceList and populate the controllers.
	iCount := int32(count)
	for _, dev := range l {
		if sc, ok := dev.(types.BaseVirtualSCSIController); ok {
			if busNumber := sc.GetVirtualSCSIController().BusNumber; busNumber < iCount {
				ctlrs[busNumber] = sc
			}
		}
	}
	log.Printf("[DEBUG] NormalizeSCSIBus: Current SCSI bus contents: %s", scsiControllerListString(ctlrs))
	// Now iterate over the controllers
	for n, ctlr := range ctlrs {
		if ctlr == nil {
			log.Printf("[DEBUG] NormalizeSCSIBus: Creating SCSI controller of type %s at bus number %d", ct, n)
			cspec, err := createSCSIController(&l, ct, st)
			if err != nil {
				return nil, nil, err
			}
			spec = append(spec, cspec...)
			continue
		}
		if l.Type(ctlr.(types.BaseVirtualDevice)) == ct {
			cspec, err := setSCSIBusSharing(&l, ctlr, st)
			if err != nil {
				return nil, nil, err
			}
			spec = append(spec, cspec...)
			continue
		}
		cspec, err := swapSCSIDevice(l, ctlr, ct, st)
		if err != nil {
			return nil, nil, err
		}
		spec = append(spec, cspec...)
		l = applyDeviceChange(l, cspec)
		continue
	}
	log.Printf("[DEBUG] NormalizeSCSIBus: Outgoing device list: %s", DeviceListString(l))
	log.Printf("[DEBUG] NormalizeSCSIBus: Outgoing device config spec: %s", DeviceChangeString(spec))
	return l, spec, nil
}
func NormalizeSCSIBus(l object.VirtualDeviceList, ct string, count int, st string) (object.VirtualDeviceList, []types.BaseVirtualDeviceConfigSpec, error) {
	log.Printf("[DEBUG] NormalizeSCSIBus: Normalizing first %d controllers on SCSI bus to device type %s", count, ct)
	var spec []types.BaseVirtualDeviceConfigSpec
	ctlrs := make([]types.BaseVirtualSCSIController, count)
	// Don't worry about doing any fancy select stuff here, just go thru the
	// VirtualDeviceList and populate the controllers.
	iCount := int32(count)
	for _, dev := range l {
		if sc, ok := dev.(types.BaseVirtualSCSIController); ok {
			if busNumber := sc.GetVirtualSCSIController().BusNumber; busNumber < iCount {
				ctlrs[busNumber] = sc
			}
		}
	}
	log.Printf("[DEBUG] NormalizeSCSIBus: Current SCSI bus contents: %s", scsiControllerListString(ctlrs))
	// Now iterate over the controllers
	for n, ctlr := range ctlrs {
		if ctlr == nil {
			log.Printf("[DEBUG] NormalizeSCSIBus: Creating SCSI controller of type %s at bus number %d", ct, n)
			cspec, err := createSCSIController(&l, ct, st)
			if err != nil {
				return nil, nil, err
			}
			spec = append(spec, cspec...)
			continue
		}
		if l.Type(ctlr.(types.BaseVirtualDevice)) == ct {
			cspec, err := setSCSIBusSharing(&l, ctlr, st)
			if err != nil {
				return nil, nil, err
			}
			spec = append(spec, cspec...)
			continue
		}
		cspec, err := swapSCSIDevice(l, ctlr, ct, st)
		if err != nil {
			return nil, nil, err
		}
		spec = append(spec, cspec...)
		l = applyDeviceChange(l, cspec)
		continue
	}
	log.Printf("[DEBUG] NormalizeSCSIBus: Outgoing device list: %s", DeviceListString(l))
	log.Printf("[DEBUG] NormalizeSCSIBus: Outgoing device config spec: %s", DeviceChangeString(spec))
	return l, spec, nil
}
// NormalizeSCSIBus checks the SCSI controllers on the virtual machine and
// either creates them if they don't exist, or migrates them to the specified
// controller type. Devices are migrated to the new controller appropriately. A
// spec slice is returned with the changes.
//
// The first number of slots specified by count are normalized by this
// function. Any others are left unchanged.