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 31, 2024
1 parent 4a7f4e7 commit e8469e2
Show file tree
Hide file tree
Showing 12 changed files with 276 additions and 21 deletions.
9 changes: 9 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,12 @@ Style/RescueModifier:

Metrics/MethodLength:
Max: 45

Metrics/ClassLength:
Enabled: false

Metrics/BlockLength:
Enabled: false

Style/MutableConstant:
Enabled: false
9 changes: 9 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 All @@ -136,6 +138,7 @@ class Compute < Fog::Service
request :host_start_maintenance
request :host_finish_maintenance
request :get_vm_first_sata_controller
request :get_vm_first_nvme_controller

module Shared
attr_reader :vsphere_is_vcenter
Expand Down Expand Up @@ -380,6 +383,12 @@ def self.data
'type' => 'VirtualLsiLogicController',
'unit_number' => 7,
'key' => 1000 }],
'nvme_controllers' =>
[{
'type' => 'VirtualNVMEController',

'key' => 2000
}],
'interfaces' =>
[{ 'mac' => '00:50:56:a9:00:28',
'network' => 'dvportgroup-123456',
Expand Down
24 changes: 24 additions & 0 deletions lib/fog/vsphere/models/compute/nvmecontroller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Fog
module Vsphere
class Compute
class NVMEController < Fog::Model
attribute :type
attribute :unit_number
attribute :key, type: :integer
attribute :server_id
DEFAULT_KEY = 2000
DEFAULT_TYPE = "VirtualNVMEController"

def initialize(attributes = {})
super
self.key ||= DEFAULT_KEY
self.type ||= DEFAULT_TYPE
end

def to_s
"#{type} ##{key}:, unit_number: #{unit_number}"
end
end
end
end
end
6 changes: 5 additions & 1 deletion lib/fog/vsphere/models/compute/scsicontroller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ class SCSIController < Fog::Model
attribute :key, type: :integer
attribute :server_id

DEFAULT_KEY = 1000
DEFAULT_TYPE = "VirtualLsiLogicController"

def initialize(attributes = {})
super
self.key ||= 1000
self.key ||= DEFAULT_KEY
self.type ||= DEFAULT_TYPE
end

def to_s
Expand Down
59 changes: 43 additions & 16 deletions lib/fog/vsphere/models/compute/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,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 +61,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,6 +291,10 @@ 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
Expand Down Expand Up @@ -348,15 +354,30 @@ def initialize_interfaces
end
end

def unassigned_volumes?
attributes[:volumes]&.any? { |vol| !vol.key?(:controller_key) } || false
end

def update_controller_key(vol)
case vol
when Hash
return if vol[:controller_key]
vol[:controller_key] = attributes[:scsi_controllers].first&.key || 1000
when Object
return if vol.controller_key
vol.controller_key = attributes.scsi_controllers.first&.key || 1000
end
end

def initialize_volumes
if attributes[:volumes] && attributes[:volumes].is_a?(Array)
attributes[:volumes].map! do |vol|
if vol.is_a?(Hash)
service.volumes.new({ server: self }.merge(vol))
else
vol.server = self
vol
end
return unless attributes[:volumes].is_a?(Array) && !attributes[:volumes].empty?
attributes[:volumes].map! do |vol|
update_controller_key(vol)
if vol.is_a?(Hash)
service.volumes.new({ server: self }.merge(vol))
else
vol.server = self
vol
end
end
end
Expand All @@ -368,19 +389,25 @@ def initialize_customvalues
end

def initialize_scsi_controllers
if attributes[:scsi_controllers] && attributes[:scsi_controllers].is_a?(Array)
if attributes[:scsi_controllers] && attributes[:scsi_controllers].is_a?(Array) && !attributes[:scsi_controllers].empty?
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)
elsif attributes[:scsi_controller] && attributes[:scsi_controller].is_a?(Hash) && !attributes[:scsi_controller].empty?

attributes[:scsi_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
]
elsif unassigned_volumes? && !attributes[:volume].empty?
attributes[:scsi_controllers] = [Fog::Vsphere::Compute::SCSIController.new]
end
end

def initialize_nvme_controllers
if attributes[:nvme_controllers] && attributes[:nvme_controllers].is_a?(Array) && !attributes[:nvme_controllers].empty?
attributes[:nvme_controllers].map! do |controller|
controller.is_a?(Hash) ? Fog::Vsphere::Compute::NVMEController.new(controller) : controller
end
end
end
end
Expand Down
3 changes: 1 addition & 2 deletions lib/fog/vsphere/models/compute/volume.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ def defaults
{
thin: true,
name: 'Hard disk',
mode: 'persistent',
controller_key: 1000
mode: 'persistent'
}
end

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

if (nvme_controllers = (attributes[:nvme_controllers]))
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)) }
end
Expand Down Expand Up @@ -255,14 +259,18 @@ 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)}))
**(check_type(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 check_type(type)
[RbVmomi::VIM::VirtualAHCIController, RbVmomi::VIM::VirtualNVMEController, "VirtualNVMEController"].include?(type)
end

def controller_get_shared_from_options(options)
if (options.key?(:shared) && (options[:shared] == false)) || (!options.key? :shared)
:noSharing
Expand Down
23 changes: 23 additions & 0 deletions lib/fog/vsphere/requests/compute/get_vm_first_nvme_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Fog
module Vsphere
class Compute
class Real
def get_vm_first_nvme_controller(vm_id)
# require 'pry'
# binding.pry
ctrl = get_vm_ref(vm_id).config.hardware.device.find { |device| device.is_a?(RbVmomi::VIM::VirtualNVMEController) }
raise(Fog::Vsphere::Compute::NotFound) unless ctrl
{
type: ctrl&.class.to_s,
device_info: ctrl&.deviceInfo,
bus_number: ctrl&.busNumber,
key: ctrl&.key
}
end
end
class Mock
def get_vm_first_nvme_controller(vm_id); end
end
end
end
end
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
1 change: 0 additions & 1 deletion lib/fog/vsphere/requests/compute/vm_clone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def vm_clone_check_options(options)
end
end

# rubocop:disable Metrics/ClassLength
class Real
include Shared

Expand Down
Loading

0 comments on commit e8469e2

Please sign in to comment.