Skip to content

Commit

Permalink
Add support for NVME Controllers
Browse files Browse the repository at this point in the history
  • Loading branch information
girijaasoni committed May 15, 2024
1 parent 4a7f4e7 commit 2c9aa8e
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 12 deletions.
2 changes: 2 additions & 0 deletions lib/fog/vsphere/compute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Compute < Fog::Service
model :customfield
collection :customfields
model :scsicontroller
model :nvmecontroller
model :process
model :cdrom
collection :cdroms
Expand Down Expand Up @@ -111,6 +112,7 @@ class Compute < Fog::Service
request :list_customfields
request :get_vm_first_scsi_controller
request :list_vm_scsi_controllers
request :list_vm_nvme_controllers
request :set_vm_customvalue
request :vm_take_snapshot
request :list_vm_snapshots
Expand Down
22 changes: 22 additions & 0 deletions lib/fog/vsphere/models/compute/nvmecontroller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Fog
module Vsphere
class Compute
class NVMEController < Fog::Model
attribute :type
attribute :unit_number
attribute :key, type: :integer
attribute :server_id

def initialize(attributes = {})
super
self.key ||= 2000
self.type ||= "VirtualNVMEController"
end

def to_s
"#{type} ##{key}:, unit_number: #{unit_number}"
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/fog/vsphere/models/compute/scsicontroller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class SCSIController < Fog::Model
def initialize(attributes = {})
super
self.key ||= 1000
self.type ||= "VirtualLsiLogicController"
end

def to_s
Expand Down
44 changes: 37 additions & 7 deletions lib/fog/vsphere/models/compute/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Server < Fog::Compute::Server
extend Fog::Deprecation
deprecate(:ipaddress, :public_ip_address)
deprecate(:scsi_controller, :scsi_controllers)
deprecate(:nvme_controller, :nvme_controllers)

# This will be the instance uuid which is globally unique across
# a vSphere deployment.
Expand Down Expand Up @@ -49,6 +50,7 @@ class Server < Fog::Compute::Server
attribute :guest_id
attribute :hardware_version
attribute :scsi_controllers, type: :array
attribute :nvme_controllers, type: :array
attribute :cpuHotAddEnabled
attribute :memoryHotAddEnabled
attribute :firmware
Expand All @@ -60,9 +62,10 @@ def initialize(attributes = {})
super defaults.merge(attributes)
self.instance_uuid ||= id # TODO: remvoe instance_uuid as it can be replaced with simple id
initialize_interfaces
initialize_volumes
initialize_customvalues
initialize_scsi_controllers
initialize_nvme_controllers
initialize_volumes
end

# Lazy Loaded Attributes
Expand Down Expand Up @@ -289,10 +292,18 @@ def scsi_controllers
attributes[:scsi_controllers] ||= service.list_vm_scsi_controllers(id)
end

def nvme_controllers
attributes[:nvme_controllers] ||= service.list_vm_nvme_controllers(id)
end

def scsi_controller
scsi_controllers.first
end

def nvme_controller
nvme_controllers.first
end

def folder
return nil unless datacenter && path
attributes[:folder] ||= service.folders(datacenter: datacenter, type: :vm).get(path)
Expand Down Expand Up @@ -348,6 +359,13 @@ def initialize_interfaces
end
end

def unassignedVolumes?

Check failure on line 362 in lib/fog/vsphere/models/compute/server.rb

View workflow job for this annotation

GitHub Actions / rubocop

Naming/MethodName: Use snake_case for method names.
attributes[:volumes]&.map! do |vol|
return true unless vol.has_key?("controller_key")

Check failure on line 364 in lib/fog/vsphere/models/compute/server.rb

View workflow job for this annotation

GitHub Actions / rubocop

Style/PreferredHashMethods: Use `Hash#key?` instead of `Hash#has_key?`.
end
false
end

def initialize_volumes
if attributes[:volumes] && attributes[:volumes].is_a?(Array)
attributes[:volumes].map! do |vol|
Expand All @@ -368,18 +386,30 @@ def initialize_customvalues
end

def initialize_scsi_controllers
controllers = []
if attributes[:scsi_controllers] && attributes[:scsi_controllers].is_a?(Array)
attributes[:scsi_controllers].map! do |controller|
controllers = attributes[:scsi_controllers].map! do |controller|
controller.is_a?(Hash) ? Fog::Vsphere::Compute::SCSIController.new(controller) : controller
end
elsif attributes[:scsi_controller] && attributes[:scsi_controller].is_a?(Hash)
attributes[:scsi_controllers] = [

controllers = [
Fog::Vsphere::Compute::SCSIController.new(attributes[:scsi_controller])
]
elsif attributes[:volumes] && attributes[:volumes].is_a?(Array) && !attributes[:volumes].empty?
# Create a default scsi controller if there are any disks but no controller defined
attributes[:scsi_controllers] = [
Fog::Vsphere::Compute::SCSIController.new
end
# Create a default scsi controller if there are exisiting hard disks with no controller assigned to them
controllers.concat([Fog::Vsphere::Compute::SCSIController.new]) if unassignedVolumes?
attributes[:scsi_controllers] = controllers
end

def initialize_nvme_controllers
if attributes[:nvme_controllers] && attributes[:nvme_controllers].is_a?(Array)
attributes[:nvme_controllers].map! do |controller|
controller.is_a?(Hash) ? Fog::Vsphere::Compute::NVMEController.new(controller) : controller
end
elsif attributes[:nvme_controller] && attributes[:nvme_controller].is_a?(Hash)
attributes[:nvme_controllers] = [
Fog::Vsphere::Compute::NVMEController.new(attributes[:nvme_controllers])
]
end
end
Expand Down
12 changes: 10 additions & 2 deletions lib/fog/vsphere/models/compute/volume.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ def server_id
server.id
end

def set_controller_key(controllers)

Check failure on line 98 in lib/fog/vsphere/models/compute/volume.rb

View workflow job for this annotation

GitHub Actions / rubocop

Naming/AccessorMethodName: Do not prefix writer method names with `set_`.
# if a disk has no controller assigned, default shall be the first scsi controller
if controllers && !controllers.empty? && !controller_key
self.controller_key = controllers.first.key
elsif !controller_key
self.controller_key = 1000
end
end

def set_unit_number
requires :server
# When adding volumes to vsphere, if our unit_number is 7 or higher, vsphere will increment the unit_number
Expand Down Expand Up @@ -126,8 +135,7 @@ def defaults
{
thin: true,
name: 'Hard disk',
mode: 'persistent',
controller_key: 1000
mode: 'persistent'
}
end

Expand Down
18 changes: 15 additions & 3 deletions lib/fog/vsphere/requests/compute/create_vm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,12 @@ def device_change(attributes)
devices << scsi_controllers.each_with_index.map { |controller, index| create_controller(controller, index) }
end

if (nvme_controllers = (attributes[:nvme_controllers] || attributes['nvme_controller']))
devices << nvme_controllers.each_with_index.map { |controller, index| create_controller(controller, index) }
end

if (disks = attributes[:volumes])
devices << disks.map { |disk| create_disk(disk, :add, storage_pod: get_storage_pod_from_volumes(attributes)) }
devices << disks.map { |disk| create_disk(disk, :add, storage_pod: get_storage_pod_from_volumes(attributes), scsi_controllers: scsi_controllers) }
end

if (cdroms = attributes[:cdroms])
Expand Down Expand Up @@ -255,14 +259,22 @@ def create_controller(controller = nil, index = 0)
operation: options[:operation],
device: controller_class.new(key: options[:key] || (1000 + index),
busNumber: options[:bus_id] || index,
**(options[:type] == RbVmomi::VIM::VirtualAHCIController ? {} : {sharedBus: controller_get_shared_from_options(options)}))
**(checkType(options[:type]) ? {} : {sharedBus: controller_get_shared_from_options(options)}))
}
end

def controller_default_options
{ operation: :add, type: RbVmomi::VIM.VirtualLsiLogicController.class, shared: false }
end

def checkType(type)

Check failure on line 270 in lib/fog/vsphere/requests/compute/create_vm.rb

View workflow job for this annotation

GitHub Actions / rubocop

Naming/MethodName: Use snake_case for method names.
if [RbVmomi::VIM::VirtualAHCIController, "VirtualNVMEController"].include?(type)

Check failure on line 271 in lib/fog/vsphere/requests/compute/create_vm.rb

View workflow job for this annotation

GitHub Actions / rubocop

Style/IfWithBooleanLiteralBranches: Remove redundant `if` with boolean literal branches.
true
else
false
end
end

def controller_get_shared_from_options(options)
if (options.key?(:shared) && (options[:shared] == false)) || (!options.key? :shared)
:noSharing
Expand All @@ -282,7 +294,7 @@ def create_disk(disk, operation = :add, options = {})
else
"[#{disk.datastore}]"
end

disk.set_controller_key(options[:scsi_controllers])

Check failure on line 297 in lib/fog/vsphere/requests/compute/create_vm.rb

View workflow job for this annotation

GitHub Actions / rubocop

Layout/TrailingWhitespace: Trailing whitespace detected.
disk.set_unit_number
disk.set_key

Expand Down
29 changes: 29 additions & 0 deletions lib/fog/vsphere/requests/compute/list_vm_nvme_controllers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Fog
module Vsphere
class Compute
class Real
def list_vm_nvme_controllers(vm_id)
list_vm_nvme_controllers_raw(vm_id).map do |raw_controller|
Fog::Vsphere::Compute::NVMEController.new(raw_controller)
end
end

def list_vm_nvme_controllers_raw(vm_id)
get_vm_ref(vm_id).config.hardware.device.grep(RbVmomi::VIM::VirtualNVMEController).map do |ctrl|
{
type: ctrl.class.to_s,
key: ctrl.key
}
end
end
end
class Mock
def list_vm_nvme_controllers(vm_id)
raise Fog::Vsphere::Compute::NotFound, 'VM not Found' unless data[:servers].key?(vm_id)
return [] unless data[:servers][vm_id].key?('nvme_controllers')
data[:servers][vm_id]['nvme_controllers'].map { |h| h.merge(server_id: vm_id) }
end
end
end
end
end

0 comments on commit 2c9aa8e

Please sign in to comment.