vsphere/internal/virtualdevice/virtual_machine_device_subresource.go
func (r *Subresource) ControllerForCreateUpdate(l object.VirtualDeviceList, ct string, bus int) (types.BaseVirtualController, error) {
	log.Printf("[DEBUG] ControllerForCreateUpdate: Looking for controller type %s", ct)
	var ctlr types.BaseVirtualController
	var err error
	switch ct {
	case SubresourceControllerTypeIDE:
		ctlr = l.PickController(&types.VirtualIDEController{})
	case SubresourceControllerTypeSATA:
		ctlr = l.PickController(&types.VirtualAHCIController{})
	case SubresourceControllerTypeSCSI:
		ctlr, err = pickSCSIController(l, bus)
	case SubresourceControllerTypePCI:
		ctlr = l.PickController(&types.VirtualPCIController{})
	default:
		return nil, fmt.Errorf("invalid controller type %T", ct)
	}
	if err != nil {
		return nil, err
	}
	if ctlr == nil {
		return nil, fmt.Errorf("could not find an available %s controller", ct)
	}

	// Assert that we are on bus 0 when we aren't looking for a SCSI controller.
	// We currently do not support attaching devices to multiple non-SCSI buses.
	if ctlr.GetVirtualController().BusNumber != 0 && ct != SubresourceControllerTypeSCSI {
		return nil, fmt.Errorf("there are no available slots on the primary %s controller", ct)
	}
	log.Printf("[DEBUG] ControllerForCreateUpdate: Found controller: %s", l.Name(ctlr.(types.BaseVirtualDevice)))

	return ctlr, nil
}
func (r *Subresource) ControllerForCreateUpdate(l object.VirtualDeviceList, ct string, bus int) (types.BaseVirtualController, error) {
	log.Printf("[DEBUG] ControllerForCreateUpdate: Looking for controller type %s", ct)
	var ctlr types.BaseVirtualController
	var err error
	switch ct {
	case SubresourceControllerTypeIDE:
		ctlr = l.PickController(&types.VirtualIDEController{})
	case SubresourceControllerTypeSATA:
		ctlr = l.PickController(&types.VirtualAHCIController{})
	case SubresourceControllerTypeSCSI:
		ctlr, err = pickSCSIController(l, bus)
	case SubresourceControllerTypePCI:
		ctlr = l.PickController(&types.VirtualPCIController{})
	default:
		return nil, fmt.Errorf("invalid controller type %T", ct)
	}
	if err != nil {
		return nil, err
	}
	if ctlr == nil {
		return nil, fmt.Errorf("could not find an available %s controller", ct)
	}

	// Assert that we are on bus 0 when we aren't looking for a SCSI controller.
	// We currently do not support attaching devices to multiple non-SCSI buses.
	if ctlr.GetVirtualController().BusNumber != 0 && ct != SubresourceControllerTypeSCSI {
		return nil, fmt.Errorf("there are no available slots on the primary %s controller", ct)
	}
	log.Printf("[DEBUG] ControllerForCreateUpdate: Found controller: %s", l.Name(ctlr.(types.BaseVirtualDevice)))

	return ctlr, nil
}
// ControllerForCreateUpdate wraps the controller selection logic to make it
// easier to use in create or update operations. If the controller type is a
// SCSI device, the bus number is searched as well.