Skip to content

Commit

Permalink
vSphere Volume Attach limit bug
Browse files Browse the repository at this point in the history
- Cannot attach scsi devices to slot kubernetes#7
- Limit of 4 scsi controllers per vm MAX
  • Loading branch information
dagnello authored and fabioy committed Aug 18, 2016
1 parent 2c7978c commit fb9eaa2
Showing 1 changed file with 94 additions and 10 deletions.
104 changes: 94 additions & 10 deletions pkg/cloudprovider/providers/vsphere/vsphere.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,19 @@ import (
"k8s.io/kubernetes/pkg/util/runtime"
)

const ProviderName = "vsphere"
const ActivePowerState = "poweredOn"
const DefaultDiskController = "scsi"
const DefaultSCSIControllerType = "lsilogic-sas"
const (
ProviderName = "vsphere"
ActivePowerState = "poweredOn"
SCSIControllerType = "scsi"
LSILogicControllerType = "lsilogic"
BusLogicControllerType = "buslogic"
PVSCSIControllerType = "pvscsi"
LSILogicSASControllerType = "lsilogic-sas"
SCSIControllerLimit = 4
SCSIControllerDeviceLimit = 15
SCSIDeviceSlots = 16
SCSIReservedSlot = 7
)

// Controller types that are currently supported for hot attach of disks
// lsilogic driver type is currently not supported because,when a device gets detached
Expand Down Expand Up @@ -156,7 +165,7 @@ func newVSphere(cfg VSphereConfig) (*VSphere, error) {
}

if cfg.Disk.SCSIControllerType == "" {
cfg.Disk.SCSIControllerType = DefaultSCSIControllerType
cfg.Disk.SCSIControllerType = LSILogicSASControllerType
} else if !checkControllerSupported(cfg.Disk.SCSIControllerType) {
glog.Errorf("%v is not a supported SCSI Controller type. Please configure 'lsilogic-sas' OR 'pvscsi'", cfg.Disk.SCSIControllerType)
return nil, errors.New("Controller type not supported. Please configure 'lsilogic-sas' OR 'pvscsi'")
Expand Down Expand Up @@ -547,12 +556,19 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, nodeName string) (diskID string

var diskControllerType = vs.cfg.Disk.SCSIControllerType
// find SCSI controller of particular type from VM devices
var diskController = getSCSIController(vmDevices, diskControllerType)
allSCSIControllers := getSCSIControllers(vmDevices)
scsiControllersOfRequiredType := getSCSIControllersOfType(vmDevices, diskControllerType)
scsiController := getAvailableSCSIController(scsiControllersOfRequiredType)

var newSCSICreated = false
var newSCSIController types.BaseVirtualDevice

// creating a scsi controller as there is none found of controller type defined
if diskController == nil {
if scsiController == nil {
if len(allSCSIControllers) >= SCSIControllerLimit {
// we reached the maximum number of controllers we can attach
return "", "", fmt.Errorf("SCSI Controller Limit of %d has been reached, cannot create another SCSI controller", SCSIControllerLimit)
}
glog.V(4).Infof("Creating a SCSI controller of %v type", diskControllerType)
newSCSIController, err := vmDevices.CreateSCSIController(diskControllerType)
if err != nil {
Expand Down Expand Up @@ -582,8 +598,8 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, nodeName string) (diskID string
return "", "", err
}

diskController = getSCSIController(vmDevices, vs.cfg.Disk.SCSIControllerType)
if diskController == nil {
scsiController = getSCSIController(vmDevices, vs.cfg.Disk.SCSIControllerType)
if scsiController == nil {
glog.Errorf("cannot find SCSI controller in VM - %v", err)
// attempt clean up of scsi controller
cleanUpController(newSCSIController, vmDevices, vm, ctx)
Expand All @@ -592,7 +608,14 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, nodeName string) (diskID string
newSCSICreated = true
}

disk := vmDevices.CreateDisk(diskController, ds.Reference(), vmDiskPath)
disk := vmDevices.CreateDisk(scsiController, ds.Reference(), vmDiskPath)
unitNumber, err := getNextUnitNumber(vmDevices, scsiController)
if err != nil {
glog.Errorf("cannot attach disk to VM, limit reached - %v.", err)
return "", "", err
}
*disk.UnitNumber = unitNumber

backing := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo)
backing.DiskMode = string(types.VirtualDiskModeIndependent_persistent)

Expand Down Expand Up @@ -638,6 +661,28 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, nodeName string) (diskID string
return deviceName, diskUUID, nil
}

func getNextUnitNumber(devices object.VirtualDeviceList, c types.BaseVirtualController) (int32, error) {
// get next available SCSI controller unit number
var takenUnitNumbers [SCSIDeviceSlots]bool
takenUnitNumbers[SCSIReservedSlot] = true
key := c.GetVirtualController().Key

for _, device := range devices {
d := device.GetVirtualDevice()
if d.ControllerKey == key {
if d.UnitNumber != nil {
takenUnitNumbers[*d.UnitNumber] = true
}
}
}
for unitNumber, takenUnitNumber := range takenUnitNumbers {
if !takenUnitNumber {
return int32(unitNumber), nil
}
}
return -1, fmt.Errorf("SCSI Controller with key=%d does not have any avaiable slots (LUN).", key)
}

func getSCSIController(vmDevices object.VirtualDeviceList, scsiType string) *types.VirtualController {
// get virtual scsi controller of passed argument type
for _, device := range vmDevices {
Expand All @@ -651,6 +696,45 @@ func getSCSIController(vmDevices object.VirtualDeviceList, scsiType string) *typ
return nil
}

func getSCSIControllersOfType(vmDevices object.VirtualDeviceList, scsiType string) []*types.VirtualController {
// get virtual scsi controllers of passed argument type
var scsiControllers []*types.VirtualController
for _, device := range vmDevices {
devType := vmDevices.Type(device)
if devType == scsiType {
if c, ok := device.(types.BaseVirtualController); ok {
scsiControllers = append(scsiControllers, c.GetVirtualController())
}
}
}
return scsiControllers
}

func getSCSIControllers(vmDevices object.VirtualDeviceList) []*types.VirtualController {
// get all virtual scsi controllers
var scsiControllers []*types.VirtualController
for _, device := range vmDevices {
devType := vmDevices.Type(device)
switch devType {
case SCSIControllerType, LSILogicControllerType, BusLogicControllerType, PVSCSIControllerType, LSILogicSASControllerType:
if c, ok := device.(types.BaseVirtualController); ok {
scsiControllers = append(scsiControllers, c.GetVirtualController())
}
}
}
return scsiControllers
}

func getAvailableSCSIController(scsiControllers []*types.VirtualController) *types.VirtualController {
// get SCSI controller which has space for adding more devices
for _, controller := range scsiControllers {
if len(controller.Device) < SCSIControllerDeviceLimit {
return controller
}
}
return nil
}

func getVirtualDiskUUID(newDevice types.BaseVirtualDevice) (string, error) {
vd := newDevice.GetVirtualDevice()

Expand Down

0 comments on commit fb9eaa2

Please sign in to comment.