PageRenderTime 342ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/pkg/cloudprovider/providers/vsphere/vclib/utils.go

https://gitlab.com/unofficial-mirrors/kubernetes
Go | 210 lines | 149 code | 23 blank | 38 comment | 30 complexity | e1b2459dfcf39ddb49a3f97d14f88222 MD5 | raw file
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package vclib
  14. import (
  15. "fmt"
  16. "path/filepath"
  17. "regexp"
  18. "strings"
  19. "github.com/golang/glog"
  20. "github.com/vmware/govmomi/find"
  21. "github.com/vmware/govmomi/object"
  22. "github.com/vmware/govmomi/vim25/mo"
  23. "github.com/vmware/govmomi/vim25/soap"
  24. "github.com/vmware/govmomi/vim25/types"
  25. )
  26. // IsNotFound return true if err is NotFoundError or DefaultNotFoundError
  27. func IsNotFound(err error) bool {
  28. _, ok := err.(*find.NotFoundError)
  29. if ok {
  30. return true
  31. }
  32. _, ok = err.(*find.DefaultNotFoundError)
  33. if ok {
  34. return true
  35. }
  36. return false
  37. }
  38. func getFinder(dc *Datacenter) *find.Finder {
  39. finder := find.NewFinder(dc.Client(), false)
  40. finder.SetDatacenter(dc.Datacenter)
  41. return finder
  42. }
  43. // formatVirtualDiskUUID removes any spaces and hyphens in UUID
  44. // Example UUID input is 42375390-71f9-43a3-a770-56803bcd7baa and output after format is 4237539071f943a3a77056803bcd7baa
  45. func formatVirtualDiskUUID(uuid string) string {
  46. uuidwithNoSpace := strings.Replace(uuid, " ", "", -1)
  47. uuidWithNoHypens := strings.Replace(uuidwithNoSpace, "-", "", -1)
  48. return strings.ToLower(uuidWithNoHypens)
  49. }
  50. // getSCSIControllersOfType filters specific type of Controller device from given list of Virtual Machine Devices
  51. func getSCSIControllersOfType(vmDevices object.VirtualDeviceList, scsiType string) []*types.VirtualController {
  52. // get virtual scsi controllers of passed argument type
  53. var scsiControllers []*types.VirtualController
  54. for _, device := range vmDevices {
  55. devType := vmDevices.Type(device)
  56. if devType == scsiType {
  57. if c, ok := device.(types.BaseVirtualController); ok {
  58. scsiControllers = append(scsiControllers, c.GetVirtualController())
  59. }
  60. }
  61. }
  62. return scsiControllers
  63. }
  64. // getAvailableSCSIController gets available SCSI Controller from list of given controllers, which has less than 15 disk devices.
  65. func getAvailableSCSIController(scsiControllers []*types.VirtualController) *types.VirtualController {
  66. // get SCSI controller which has space for adding more devices
  67. for _, controller := range scsiControllers {
  68. if len(controller.Device) < SCSIControllerDeviceLimit {
  69. return controller
  70. }
  71. }
  72. return nil
  73. }
  74. // getNextUnitNumber gets the next available SCSI controller unit number from given list of Controller Device List
  75. func getNextUnitNumber(devices object.VirtualDeviceList, c types.BaseVirtualController) (int32, error) {
  76. var takenUnitNumbers [SCSIDeviceSlots]bool
  77. takenUnitNumbers[SCSIReservedSlot] = true
  78. key := c.GetVirtualController().Key
  79. for _, device := range devices {
  80. d := device.GetVirtualDevice()
  81. if d.ControllerKey == key {
  82. if d.UnitNumber != nil {
  83. takenUnitNumbers[*d.UnitNumber] = true
  84. }
  85. }
  86. }
  87. for unitNumber, takenUnitNumber := range takenUnitNumbers {
  88. if !takenUnitNumber {
  89. return int32(unitNumber), nil
  90. }
  91. }
  92. return -1, fmt.Errorf("SCSI Controller with key=%d does not have any available slots", key)
  93. }
  94. // getSCSIControllers filters and return list of Controller Devices from given list of Virtual Machine Devices.
  95. func getSCSIControllers(vmDevices object.VirtualDeviceList) []*types.VirtualController {
  96. // get all virtual scsi controllers
  97. var scsiControllers []*types.VirtualController
  98. for _, device := range vmDevices {
  99. devType := vmDevices.Type(device)
  100. switch devType {
  101. case SCSIControllerType, strings.ToLower(LSILogicControllerType), strings.ToLower(BusLogicControllerType), PVSCSIControllerType, strings.ToLower(LSILogicSASControllerType):
  102. if c, ok := device.(types.BaseVirtualController); ok {
  103. scsiControllers = append(scsiControllers, c.GetVirtualController())
  104. }
  105. }
  106. }
  107. return scsiControllers
  108. }
  109. // RemoveStorageClusterORFolderNameFromVDiskPath removes the cluster or folder path from the vDiskPath
  110. // for vDiskPath [DatastoreCluster/sharedVmfs-0] kubevols/e2e-vmdk-1234.vmdk, return value is [sharedVmfs-0] kubevols/e2e-vmdk-1234.vmdk
  111. // for vDiskPath [sharedVmfs-0] kubevols/e2e-vmdk-1234.vmdk, return value remains same [sharedVmfs-0] kubevols/e2e-vmdk-1234.vmdk
  112. func RemoveStorageClusterORFolderNameFromVDiskPath(vDiskPath string) string {
  113. datastore := regexp.MustCompile("\\[(.*?)\\]").FindStringSubmatch(vDiskPath)[1]
  114. if filepath.Base(datastore) != datastore {
  115. vDiskPath = strings.Replace(vDiskPath, datastore, filepath.Base(datastore), 1)
  116. }
  117. return vDiskPath
  118. }
  119. // GetPathFromVMDiskPath retrieves the path from VM Disk Path.
  120. // Example: For vmDiskPath - [vsanDatastore] kubevols/volume.vmdk, the path is kubevols/volume.vmdk
  121. func GetPathFromVMDiskPath(vmDiskPath string) string {
  122. datastorePathObj := new(object.DatastorePath)
  123. isSuccess := datastorePathObj.FromString(vmDiskPath)
  124. if !isSuccess {
  125. glog.Errorf("Failed to parse vmDiskPath: %s", vmDiskPath)
  126. return ""
  127. }
  128. return datastorePathObj.Path
  129. }
  130. //GetDatastorePathObjFromVMDiskPath gets the datastorePathObj from VM disk path.
  131. func GetDatastorePathObjFromVMDiskPath(vmDiskPath string) (*object.DatastorePath, error) {
  132. datastorePathObj := new(object.DatastorePath)
  133. isSuccess := datastorePathObj.FromString(vmDiskPath)
  134. if !isSuccess {
  135. glog.Errorf("Failed to parse volPath: %s", vmDiskPath)
  136. return nil, fmt.Errorf("Failed to parse volPath: %s", vmDiskPath)
  137. }
  138. return datastorePathObj, nil
  139. }
  140. //IsValidUUID checks if the string is a valid UUID.
  141. func IsValidUUID(uuid string) bool {
  142. r := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$")
  143. return r.MatchString(uuid)
  144. }
  145. // IsManagedObjectNotFoundError returns true if error is of type ManagedObjectNotFound
  146. func IsManagedObjectNotFoundError(err error) bool {
  147. isManagedObjectNotFoundError := false
  148. if soap.IsSoapFault(err) {
  149. _, isManagedObjectNotFoundError = soap.ToSoapFault(err).VimFault().(types.ManagedObjectNotFound)
  150. }
  151. return isManagedObjectNotFoundError
  152. }
  153. // IsInvalidCredentialsError returns true if error is of type InvalidLogin
  154. func IsInvalidCredentialsError(err error) bool {
  155. isInvalidCredentialsError := false
  156. if soap.IsSoapFault(err) {
  157. _, isInvalidCredentialsError = soap.ToSoapFault(err).VimFault().(types.InvalidLogin)
  158. }
  159. return isInvalidCredentialsError
  160. }
  161. // VerifyVolumePathsForVM verifies if the volume paths (volPaths) are attached to VM.
  162. func VerifyVolumePathsForVM(vmMo mo.VirtualMachine, volPaths []string, nodeName string, nodeVolumeMap map[string]map[string]bool) {
  163. // Verify if the volume paths are present on the VM backing virtual disk devices
  164. vmDevices := object.VirtualDeviceList(vmMo.Config.Hardware.Device)
  165. VerifyVolumePathsForVMDevices(vmDevices, volPaths, nodeName, nodeVolumeMap)
  166. }
  167. // VerifyVolumePathsForVMDevices verifies if the volume paths (volPaths) are attached to VM.
  168. func VerifyVolumePathsForVMDevices(vmDevices object.VirtualDeviceList, volPaths []string, nodeName string, nodeVolumeMap map[string]map[string]bool) {
  169. volPathsMap := make(map[string]bool)
  170. for _, volPath := range volPaths {
  171. volPathsMap[volPath] = true
  172. }
  173. // Verify if the volume paths are present on the VM backing virtual disk devices
  174. for _, device := range vmDevices {
  175. if vmDevices.TypeName(device) == "VirtualDisk" {
  176. virtualDevice := device.GetVirtualDevice()
  177. if backing, ok := virtualDevice.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok {
  178. if volPathsMap[backing.FileName] {
  179. setNodeVolumeMap(nodeVolumeMap, backing.FileName, nodeName, true)
  180. }
  181. }
  182. }
  183. }
  184. }