From 0f06467fbaf8497ed5ea9d5f020d159f79a284c8 Mon Sep 17 00:00:00 2001 From: Girija Soni Date: Thu, 30 May 2024 19:25:09 +0530 Subject: [PATCH] Add support for NVME Controllers --- .rubocop.yml | 6 +++ lib/fog/vsphere/compute.rb | 8 +++ .../vsphere/models/compute/nvmecontroller.rb | 24 +++++++++ .../vsphere/models/compute/scsicontroller.rb | 6 ++- lib/fog/vsphere/models/compute/server.rb | 53 +++++++++++++------ lib/fog/vsphere/models/compute/volume.rb | 3 +- lib/fog/vsphere/requests/compute/create_vm.rb | 10 +++- .../compute/list_vm_nvme_controllers.rb | 29 ++++++++++ 8 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 lib/fog/vsphere/models/compute/nvmecontroller.rb create mode 100644 lib/fog/vsphere/requests/compute/list_vm_nvme_controllers.rb diff --git a/.rubocop.yml b/.rubocop.yml index 49cb5ac1..366d8558 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -42,3 +42,9 @@ Style/RescueModifier: Metrics/MethodLength: Max: 45 + +Metrics/ClassLength: + Enabled: false + +Style/MutableConstant: + Enabled: false \ No newline at end of file diff --git a/lib/fog/vsphere/compute.rb b/lib/fog/vsphere/compute.rb index 214bfc29..ab2b9644 100644 --- a/lib/fog/vsphere/compute.rb +++ b/lib/fog/vsphere/compute.rb @@ -43,6 +43,7 @@ class Compute < Fog::Service model :customfield collection :customfields model :scsicontroller + model :nvmecontroller model :process model :cdrom collection :cdroms @@ -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 @@ -380,6 +382,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', diff --git a/lib/fog/vsphere/models/compute/nvmecontroller.rb b/lib/fog/vsphere/models/compute/nvmecontroller.rb new file mode 100644 index 00000000..4ed46897 --- /dev/null +++ b/lib/fog/vsphere/models/compute/nvmecontroller.rb @@ -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 diff --git a/lib/fog/vsphere/models/compute/scsicontroller.rb b/lib/fog/vsphere/models/compute/scsicontroller.rb index 393fcbc8..4e6d5408 100644 --- a/lib/fog/vsphere/models/compute/scsicontroller.rb +++ b/lib/fog/vsphere/models/compute/scsicontroller.rb @@ -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 diff --git a/lib/fog/vsphere/models/compute/server.rb b/lib/fog/vsphere/models/compute/server.rb index c5ff030d..f393ec41 100644 --- a/lib/fog/vsphere/models/compute/server.rb +++ b/lib/fog/vsphere/models/compute/server.rb @@ -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 @@ -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 @@ -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 @@ -348,15 +354,24 @@ def initialize_interfaces end end + def unassigned_volumes? + attributes[:volumes]&.any? { |vol| !vol.key?(:controller_key) } || false + end + + def update_controller_key(vol) + return if vol[:controller_key] + 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 + 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 @@ -368,19 +383,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 diff --git a/lib/fog/vsphere/models/compute/volume.rb b/lib/fog/vsphere/models/compute/volume.rb index 98078d79..ea75252a 100644 --- a/lib/fog/vsphere/models/compute/volume.rb +++ b/lib/fog/vsphere/models/compute/volume.rb @@ -126,8 +126,7 @@ def defaults { thin: true, name: 'Hard disk', - mode: 'persistent', - controller_key: 1000 + mode: 'persistent' } end diff --git a/lib/fog/vsphere/requests/compute/create_vm.rb b/lib/fog/vsphere/requests/compute/create_vm.rb index f873d050..850df277 100644 --- a/lib/fog/vsphere/requests/compute/create_vm.rb +++ b/lib/fog/vsphere/requests/compute/create_vm.rb @@ -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 @@ -255,7 +259,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)})) + **(check_type(options[:type]) ? {} : {sharedBus: controller_get_shared_from_options(options)})) } end @@ -263,6 +267,10 @@ 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 diff --git a/lib/fog/vsphere/requests/compute/list_vm_nvme_controllers.rb b/lib/fog/vsphere/requests/compute/list_vm_nvme_controllers.rb new file mode 100644 index 00000000..0194cb22 --- /dev/null +++ b/lib/fog/vsphere/requests/compute/list_vm_nvme_controllers.rb @@ -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