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

Metrics/MethodLength:
Max: 45

Style/MutableConstant:
Enabled: false

13 changes: 11 additions & 2 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 @@ -346,11 +349,11 @@ def is_uuid?(id)
end
end

class Mock
class Mock # rubocop:disable Metrics/ClassLength
include Shared
# rubocop:disable Metrics/MethodLength
def self.data
@data ||= Hash.new do |hash, key|
@data ||= Hash.new do |hash, key| # rubocop:disable Metrics/BlockLength
hash[key] = {
servers: {
'5032c8a5-9c5e-ba7a-3804-832a03e16381' => {
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
53 changes: 35 additions & 18 deletions lib/fog/vsphere/models/compute/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Fog
module Vsphere
class Compute
class Server < Fog::Compute::Server
class Server < Fog::Compute::Server # rubocop:disable Metrics/ClassLength
extend Fog::Deprecation
deprecate(:ipaddress, :public_ip_address)
deprecate(:scsi_controller, :scsi_controllers)
Expand Down 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,16 +354,21 @@ def initialize_interfaces
end
end

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

def update_controller_key(vol)
vol.controller_key ||= attributes[:scsi_controllers].first&.key || 1000
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
end
return unless attributes[:volumes].is_a?(Array)
attributes[:volumes].map! do |vol|
vol = service.volumes.new({ server: self }.merge(vol)) if vol.is_a?(Hash)
vol.server = self
update_controller_key(vol)
vol
end
end

Expand All @@ -368,19 +379,25 @@ def initialize_customvalues
end

def initialize_scsi_controllers
if attributes[:scsi_controllers] && attributes[:scsi_controllers].is_a?(Array)
if 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].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].is_a?(Array)
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
14 changes: 11 additions & 3 deletions lib/fog/vsphere/requests/compute/create_vm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,14 @@ def device_change(attributes)
devices << nics.map { |nic| create_interface(nic, nics.index(nic), :add, attributes) }
end

if (scsi_controllers = (attributes[:scsi_controllers] || attributes['scsi_controller']))
if (scsi_controllers = attributes[:scsi_controllers] || attributes['scsi_controller'])
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 @@ -241,11 +245,15 @@ def create_interface(nic, index = 0, operation = :add, attributes = {})
end

def create_controller(controller = nil, index = 0)
device_options = {}
options = if controller
controller_default_options.merge(controller.attributes)
else
controller_default_options
end
end
unless [RbVmomi::VIM::VirtualAHCIController, RbVmomi::VIM::VirtualNVMEController, "VirtualNVMEController"].include?(options[:type])
device_options[:sharedBus] = controller_get_shared_from_options(options)
end
controller_class = if options[:type].is_a? String
Fog::Vsphere.class_from_string options[:type], 'RbVmomi::VIM'
else
Expand All @@ -255,7 +263,7 @@ 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)}))
**device_options)
}
end

Expand Down
21 changes: 21 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,21 @@
module Fog
module Vsphere
class Compute
class Real
def get_vm_first_nvme_controller(vm_id)
ctrl = get_vm_ref(vm_id).config.hardware.device.find { |device| device.is_a?(RbVmomi::VIM::VirtualNVMEController) }
raise Fog::Vsphere::Compute::NotFound, "No NVME controller found for #{vm_id}" 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
4 changes: 1 addition & 3 deletions lib/fog/vsphere/requests/compute/vm_clone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ def vm_clone_check_options(options)
end
end

# rubocop:disable Metrics/ClassLength
class Real
class Real # rubocop:disable Metrics/ClassLength
include Shared

# Clones a VM from a template or existing machine on your vSphere
Expand Down Expand Up @@ -887,7 +886,6 @@ def relocation_volume_backing(volume)
end
end

# rubocop:enable Metrics/ClassLength
class Mock
include Shared
def vm_clone(options = {})
Expand Down
Loading

0 comments on commit c8224bf

Please sign in to comment.